Vaccination QR Code on WaspOS smartwatches

Last year, when I first read about the PineTime smart watch, I got really excited. Screw expensive Apple Watches or data-harvesting fitness loggers, I want to be able to create my own watch faces and peek at the firmware! Because if you can’t hack your gadget, do you really own it?

Installation Notes for the Colmi P8

Skip this section

Alas, ordering a PineTime watch from the Hong Kong-based Pine Store, was not as easy as I had hoped and after three months my package is still stuck at customs. What did arrive, however, was a Colmi P8 watch I ordered that has the same chipset and is compatible with the Watch Operating System of my choice: WaspOS.

Along with WaspOS documentation comes a comprehensive Installation Guide. It even has a video showing the whole process. The warning in the description of the video about incompatibility with devices whose serial number contains the sequence MOY-TON5 can be safely ignored, I can confirm that flashing the appropriate bootloader will (most likely) not brick your device. Nevertheless, the nervousness when jailbreaking new devices is still real, let alone because of the possibility of committing a climate atrocity by having a device assembled, shipped around half the globe, only for it to be dumped into landfill after 10 minutes of use because some bits ended up in the wrong location.

Manually compiling the firmware

Because of this issue, the prebuilt firmware version offered on the GitHub Releases page did not work for me. Thankfully, a helpful commenter has already figured out the solution. You need to manually define a macro in a micropython configuration file.

Writing apps

Once all systems are up and running, you can either stick to the preloaded applications or begin writing your own.

The Application Writer’s Guide is a must read. A few notes about things that confused me when I first read the article:

  1. The watch has two types of flash storage: internal & external. The internal flash storage is where the firmware build lives. The external flash is larger and can be used to store user apps, but they cannot be executed directly from it. Instead, they are first loaded into memory.
  2. If you want your application to show up in the drawer, you must first register it with wasp.system.register. If your app is a watch face, you can specify the option watch_face=True and the OS will automatically set it as default watch face.

As a trial run, I tried implementing a binary watch face.

Figure 1: Simple binary clock face

QR code viewer

And now for the application advertised in the title. In the EU, a simple static QR code can be used as proof of vaccination when entering certain venues. Tobias Girstmair has written an excellent article about the actual data encoded.

Writing an image viewer would be really simple with WaspOS’s API, if it weren’t for memory constraints, but because the image was a bit to large to be stored directly in the internal flash or alongside the program, I had to rewrite the rle_blit function to read the image file in chunks from the external flash.

The whole thing can be found on GitHub. Installation steps are provided below.

Step 1: Build and install alternative firmware

My fork of Wasp OS can be found here. These are the necessary steps to build an image:

 git clone --recursive https://github.com/stelzch/wasp-os
 cd wasp-os
 patch micropython/ports/nrf/boards/p8/mpconfigboard.mk colmi-p8-clk.patch
 make submodules
 make softdevice
 ./tools/docker/shell
    make -j 8 BOARD=p8 all
    exit

Afterwards, you will find the flashable firmware under build-p8/micropython.zip.

Step 2: Take a screenshot

Display your vaccination certificate on e.g. your smartphone, take a screenshot and crop it down until only the QR code is left in the image.

Step 3: Scale and run-length encode

I wrote a python script that takes care of scaling down the image. It also applies the run-length encoding used by WaspOS to compress images. Instead of storing each pixel value, information is added about how often a value is repeated. This allows blank space to be stored efficiently.

Step 4: Upload

The script will output a certificate.bin file, which you can transfer to the external flash with wasptool:

./tools/wasptool --upload certificate.bin
A word of caution: as tracked in this GitHub issue, WaspOS currently does not do any kind of access control. Anyone with a laptop nearby can connect to your watch and download the certificate. If you transfer your personal certificate to your watch, always leave Bluetooth disabled to prevent data theft!

Demo

Figure 2: QR Code App

Conclusion

Hackable smart watches are fun little gadget. While they are not as polished as their “commercial” competitors, they can easily be extended to use cases of your own imagination.

Comments

To add a comment, write an email with this link.