Case study
Hardware integration
The equipment on a bus comes from several suppliers. Ticket validators, passenger counters, destination signs and audio all speak their own serial protocol and have their own idea of how things should work. I wrote the software that gets them working with our onboard computer.
Context
Our onboard computer knows the journey, the stops, the service and the state of the vehicle. The equipment around it usually comes from other companies. Each device has its own interface, its own startup behaviour and its own expectations about what we'll send it.
I connected ticket validators, two separate passenger-counting systems, destination signs, an emergency button and an audio-monitoring relay, over RS232 and RS485 serial links. Getting one device working on its own is the easy part. They also have to agree on the current journey, what comes next, and what to do when one of them is late, missing or unplugged.
The problem
Devices show up at different times. A display can boot before the computer has a journey loaded. A ticket terminal can be plugged in but not ready yet. A cable can work loose. The rest of the bus still has to work while the software figures out what's actually there.
Then there's meaning. Two systems can swap data without a single error and still read it differently. So my code translates the data for each device. Moving the bytes is the easy half.
Two devices can talk all day and still disagree about which stop is next.
Approach
I wrote one module per device, sitting between the onboard computer and that piece of equipment. Each module knows how to talk to its device, how to turn our journey data into something the device understands, and how to report whether the device is healthy.
I kept them deliberately narrow. The display module knows nothing about ticketing, and the ticketing module doesn't care about the display layout. When something breaks, you know where to look, and you can swap one device without touching the rest.
What I built
- Modules for third-party passenger displays, ticketing equipment and the other devices above.
- Mapping from our journey data to whatever each device expects.
- Handling for startup, reconnects and devices that are only half there.
- Health and status reporting, so a failure shows up instead of going unnoticed.
- Bench testing with the real equipment before anything went on a vehicle.
Choices I made
One module per device
Small modules are easier to understand, test and replace. The core software doesn't pick up device-specific quirks, and when a device changes, the change stays in its module.
Translate what the data means
The same journey means different things to a display and to a ticket terminal. The module handles that translation, including the moments when our side doesn't know the answer yet.
Keep running when a device drops out
If a device goes missing, everything else keeps running and the gap shows up in the status report. One dead counter shouldn't take down the whole bus.
Test on the real bench
Cables, power, startup order and real displays are all part of the job. The bench is where my assumptions about the hardware got corrected.
Where it ended up
Equipment from different suppliers now works together on the same journey, and each device's quirks stay inside its own module. Each integration also became a new configuration option the company could bill for.
None of this shows up in a screenshot. What you'd notice is that the screen in front of the passenger keeps working when one of those devices has a bad day.