Last year when looking at wireless concepts with my Year 8 Digital Technologies students, I wrote a program for wireless beacons and laser cut a Ghostbusters style PKE Meter with some servos and a RGB LED for students to go on a hunt in our library. It was a good opportunity to look at things like the range of wireless signals, interference due to obstruction of different materials, and noisy broadcast channels. The students quite enjoyed it and it was a nice excuse to get out of the classroom.
2020 has been the year of living with the global SARS-CoV2 pandemic, and there has been a lot of discussion about the various contact tracing apps which have been developed left and right (which is great fuel for my classes on ethics and data privacy!) and I figured I’d spin up a new idea for the activity on wireless networks and flip the contact tracing app on its head, using it to infect other devices instead of keep records of potentially risky contact.
The basic concept of the contact tracing apps (at least of the moderately sane variety) is this:
- Broadcast an ID (often randomised) via Bluetooth Low Energy
- Monitor incoming beacon messages, and use the signal to determine approximate proximity and whether this falls within the threshhold of $DANGER_DISTANCE
- Keep a record of IDs which have been in proximity for $DANGER_TIME
- IDs are purged after some time period (21 days is thrown around a lot) which would cover the time taken to typically develop symptoms
- In the event of someone testing positive for COVID-19 contacts could be uploaded to local health services to enable more efficient contact tracing (with the method for this varying by implementation)
The typical values for $DANGER_DISTANCE and $DANGER_TIME have been around 2 meters and 15 minutes respectively.
Using Micro:bits
Since the Micro:bit has a Bluetooth radio and can easily monitor signal strength and signal device IDs, it was fairly straightforward to implement some code (written in Microsoft’s MakeCode this time, whereas I used Python for the PKE meter).
I’d like to do up a version of this that uses a speaker as well for some audio feedback about symptom status - some bleeps and bloops for coughing perhaps, or even just for some basic tactile feedback of vibration from a piezo to alert students that their device is sick.
I’ve included links to the code and discussion of the algorithm further down the page.
Video
Here’s a video of my first test run of more than a pair of clients. There’s one mistake in my discussion as it plays where I say more than 10 infection messages in a 30 second period, which should be a 40 second period - since infection messages are broadcast every 2 seconds, it would make it hard to get infected otherwise!
The Code
Since this section will be a bit lengthy, here are links to the code. I’ve tried to comment most of the important blocks so hopefully most of it will be pretty self-explanatory.
Virus Master
The virus master device is responsible for monitoring of the client devices, and also initial infection of a client device so that I have a known infection time and get an opportunity to prime students for the activity (which I’m planning on running twice - once unaware, and once with intentional physical distancing).
The code is pretty straightforward - it just monitors radio traffic and collects device IDs and infection messages to keep track of total and infected devices.
Set the radio group and create arrays for keeping device IDs of nearby Micro:bits and infected devices.
Incoming messages will either be discovery messages or infection messages. Capture device IDs and put into relevant arrays if not already present.
Use the captured device IDs to report on number of devices seen and infected using A or B.
Pick a random device ID to send an infection message to as Patient Zero.
Virus Client
The virus client maintains arrays of infected devices around itself based on the RSSI (signal strength) values of incoming messages. Each incoming message also contains the device ID of the sender, which can be used for determining whether enough infection messages have been received to merit being infected itself.
If sufficient time (40s in this case) passes without enough infection messages from a seen device, that device’s info is purged from the lists. This has a couple of purposes:
- It keeps the idea of device lists easier to understand - if it’s there it’s infectious and close enough to be a problem
- If it isn’t there, we’re preserving that device’s privacy by not keeping its info on our device
When devices are infected, they remain asymptomatic for 60 seconds, so only show the sad face on the screen after they’ve been merrily infecting other close devices for some time.
The client needs to maintain arrays of other devices it has seen which are broadcasting infected messages, when it first saw an infected device, and how many messages it has seen. It also needs to know if it is infectious and displaying symptoms.
The clients broadcast discovery messages intended for the master device. If they are infected, they broadcast infect messages, and use the screen to displays whether or not they are symptomatic. Contacts are also pruned when they fall out of range for the infection window.
When radio packets are received, the client needs to determine if the device has been seen before, if the signal is strong enough to merit contributing to infection, and whether enough contact has occured to infect this device. This also listens for the master device to see if an infection message refers to this device ID.
I could probably get away without pruning and just maintain data for every device seen, but this keeps the list of infected devices easy to understand. If it’s in the array, it’s something to worry about. This also stays true to the idea of not keeping identifying data for devices which are not relevant.