Bus Frames
Bus (Vehicle) Frames
I have done some on-the-road radio testing to see how I might detect nearby buses as they drive past a sign. In my observations there were not any standards-based 2.4GHz emitters on our buses. For a while we had passenger WiFi on certain RapidRide lines but it was never expanded to other lines was eventually phased out

RapidRide lines A-F (and also regular routes 40 and 120 for some reason) have a 4.9 GHz radio system that is tied to roadside infrastructure. This radio uses 802.11-style broadcast much like regular WiFi, but in a special, government-only (public safety) radio band. While it would be legal for me to listen for broadcasts on this band equipment is hard to come by, even for authorized users, and is being phased out by Metro in favor of cellular links with self-reported positions from buses
So I don’t think there’s anything I can do with a 2.4GHz radio to accurately detect passing buses1. I have other ideas about identifying buses; a camera could definitely pick them out, or maybe I could find a cheap 24GHz/60GHz2 radar module that is FCC pre-certified. Version 2 of this project might include something like that but for now I’m putting bus (vehicle) frame detection on the back burner
Bus (Relay Net) Frames
I have been working on a packet framing for bus sign network. Last month I talked about how frames would be relayed across the network, this month I’m talking about what is in each of those frames
My work on these packets draws from well-established protocols like IPv4, and thus our frames have a similar format, but ours is optimized for our specialized use and limited network capacity
Every packet sent between radios in this network will use a framing like this:
| CTRL | TX | SRC | DST | SEQ | PAYLOAD (var) | GROUP MAC | |
|---|---|---|---|---|---|---|---|
| Size | 1B | 1B | 1B | 1B | 2B | variable | 4B |
| Offset | 0 | 1 | 2 | 3 | 4–5 | 6 | -4 |
CTRL includes several very small pieces of information about the rest of the packet and how it should be handled
Specifically:
- A protocol number (0-3) so we can invent new versions later
- A flag marking the packet for routing upstream or downstream
- A flag allowing packets to be relayed or direct-only
- A type number (0-7) that specifies the type of payload
- A tiny bit of extra space for something we haven’t thought of yet
| Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|
| Field | VER | DIR | RELAY | PTYPE | RSV | |||
These are the network addresses of: the currently transmitting radio (TX), original packet source (SRC), and packet destination (DST). The TX address changes each time the packet is relayed so that listeners can know which radio is sending. This also requires recalculating the MAC in each hop, even though the rest of the packet is identical
Two addresses have special meaning: DST address 255 routes messages out to all radios in the network; no real node is assigned this address and it is never a valid SRC or TX address. Address 0 is always the base station, which is a terminal node on one end of every network graph and which sets and network parameters for all other radios
SEQ is a number (0-65,535) used to tell similar frames apart (or to recognize them as duplicates). It is chosen by the sender when a new frame is constructed and is expected to be unique among frames from that sender (at least over short periods). Usually it is just a number that counts up with each new packet. It is also used to group together DATA and SECRET packet sets so they can be reassembled in the right order
Payload is the actual data being sent across the network. Things like bus schedules and delay information or the date and time
Some frames also include a public key signature at the end of the payload, so that receivers can determine that the payload came from a particular original sender. But that pubkey sig uses 64 bytes — about 25% of the total space available in a frame — so most frames are protected only with the much smaller (4 bytes) truncated group MAC
A truncated HMAC calculated over the entire packet (all headers + payload) providing cryptographic integrity against an ephemeral group key held by all radios in the network. This provides verification that the frame was received completely and accurately. It also proves that the frame was was sent by a trusted member of the network and not just someone else on the same radio channel
Bus Net Software
I did initial radio testing in ESPhome, which has fairly good LoRa radio support. ESPhome is a platform I use for many tiny computer projects in homes and offices. But while that project is great it is oriented toward single-site deployments and single-purpose devices, and our bus signs will be neither. So I am designing the final software using Zephyr. I don’t have a lot of experience in Zephyr specifically, but it is a C/C++ system and it inherits hardware config concepts from the linux kernel, so many parts are familiar
I have written quite a bit of software to develop this radio plan. A preview version is available here: https://git.zi3.xyz/zib/zBusNet

There are still many parts to be done, but I have a working test network with a base station and 2 signs. They can transfer messages up and down the chain, choose the fastest path automatically, and listen and wait to avoid trampling over each other on the radio. I have encryption working for both the group MAC and identity signing so that they can trust each other and reject unknown senders
Bus Net Test Harness
Next steps for radio development include installing some nodes away from my house, so I can test them at range and under real-world conditions. But since the network isn’t working yet I also need to be able to reach the nodes via another channel so I can load new software on them and see their logs. This is easy at my test bench but difficult from 1km away
So I did a side project where I built a test harness — a second computer used as a tool to connect the DUT to testers/developers and to existing networks. In this project that means I built a tiny harness computer with WiFi and connected that computer to the control ports on the bus radio computer. The harness computer can connect back to my test bench via a WireGuard VPN and it lets me reset, program, and monitor the bus computer. It also has an SD card so it can store copies of the bus computer software and logs from the bus computer outputs



If you are a person who would like to host a test radio please let me know. I will need at least one node within about 1km of 4114 38th Ave S (ideally west of 38th, as I have poor east visibility), but I would also like to test with some nodes I cannot reach directly
- I can detect passing cops. Their vehicle frames emit all sorts of WiFi and other radio traffic. That is not the main goal of this bus network but it is a feature I hope to add once the signs are working ↩︎
- These are actually bad frequencies for traditional radar, as H20 absorbs at 24 GHz and O2 absorbs at 60 GHz, and our atmosphere has lots of both. But that means these specific bands have been mostly reserved for ISM use, and I only need to look through a few meters of air to find a nearby bus ↩︎