Using QR Codes to send data from offline devices
đ From a sensor
If a sensor has a display, it can show a qr code with the data encoded in a url. An example is this temperature sensor sharing recent values in a collector page.
đ Everything works offline. The microcontroller has no network code and the collector page can work offline.
đ Power efficient. E-ink displays don't require continous power so controller could go into deep sleep between updates.
đ¨ Robust. You could take a polaroid photo of the sensor and mail it to your friend for them to scan it if you want!
đž Collection. Storing historical data is possible by forwarding to server when the collector device is back online.
đ From a web page
You don't need a microcontroller to collect data. Browsers are a rich source of content. When you draw in the box below it'll encode your art in a qr code (source).
You might notice as you draw more lines the QR code becomes more dense. I implemented some rudimentary path simplification, but there's limits to the amount of content you can share this way.
The key requirement is that target page state should be derived from the url, and once you've got that you can save and share content in any number of ways, not just a qr code.
đ Between web pages
Browsers can also scan QR Codes. This allows us to create a bidirectional socket between two offline devices using their front-facing cameras.
I implemented this as a joke, but after a while it started seeming actually good.
To manage the connection I used a basic protocol; a client bootstraps the connection by displaying the url of the current page (useful for setting up the second device). When a matching url is detected the devices go into "data mode", where a string of [RX, TX, Data]
is encoded in the qr code.
RX
- last message id seen by the deviceTX
- message id being transmittedData
- payload (string)
Messages are chunked to a fairly arbitrary string length. This could definitely be improved to target the capacity of a particular code size. An interesting extension could be switching between different resolutions to pick the highest capacity for a camera+screen combination.
Side note: QR Codes support structured append for spreading messages over multiple codes. Pretty cool, but I didn't use it.
The coding interface feels a bit like a WebSocket:
const qs = new QRSocket();
qs.on("message", (message) => console.log(message));
qs.send("Hello World!");
One area for improvement is disposing of the socket; currently you have to close the page otherwise the camera will still be active. Having some method for pausing the socket might make this feel more natural.
đšī¸ There's some demos online at remotehack.space/QR-TX and source on github.
- Send - Basic example that sends text of different lengths.
- Chat - Send multiple messages between devices. Panda and I built this at remote hack, it was a lot of fun and slightly mind-bending when we were lining up our phones remotely over a discord room.
- Signalling - Negotiates a peer-to-peer webrtc video link between devices. This could be a DataChannel to create an upgraded connection between the clients.
As before, these demos have a Serice Worker so they load offline. I've enjoyed giving demos to people before showing them that my phone is in aeroplane mode đ¤¯. It feels like there's interesting use cases of being able to sync with someone when either of you are completely offline.
I showed a quick demo at Future of Coding [slides] last year. And a longer talk about QR Codes and other stuff at MKGN [video].
More things
That I've built:
- QR Code Scanner - This scanner auto-redirects to any detected urls (even if that url is
'javascript:alert("hello")'
đŦ). - QR Undistort - This looks for a QR Code from a camera feed and transforms the video element so that it's central. Like this!
- QR Text - An text-based version of qdraw.
That I like:
- "I built a QR code with my bare hands to see how it works" - great video exploring how qr codes work. This made reed solomon encoding finally click for me.
- Snake in a QR Code - there's something I love about "chmod +x" on something you captured from your webcam.
- qrs & txr - cool approach for one-way streaming using fountain codes.
- meshtastic - not QR codes, but it's pretty cool to use WebBluetooth to communicate with devices over a different network.