Back

Blog

Building for Hardware I Cannot Touch

A tablet running the counter POS, asking for a card to be presented to the reader beside it
Published
Read
5 minutes
Topic

Hardware

Remote work

Role
Lead Full Stack Engineer

The Setup

Every piece of hardware in this project is something I have never held.

The card reader is an Android phone at a church counter in Australia. The sticker printer is a Zebra on a USB cable in Australia. I am in the Philippines, where Stripe does not operate and tap to pay only started showing up this year. I built the software for both, and I still have not touched either.

What The Hardware Does

Two chains, and I could not test either one end to end.

St John's runs two food counters, Shepherd's Table and Chapter 6 Cafe. When someone orders, two things have to happen in the physical world.

First, they pay. The POS app uses Stripe Tap to Pay, so a regular Android phone is the card terminal. Nobody bought a Stripe reader. You tap your card on the phone.

Second, a sticker prints. The order goes from the API to PrintNode, PrintNode hands it to a Raspberry Pi at the counter, the Pi hands it to a Zebra label printer over USB, and the sticker goes on the cup. Same idea as Starbucks writing your name on it.

The cafe POS open on a laptop, its coffee menu laid out as a grid of tiles
A Zebra ZD421 printer with a freshly printed sticker reading Flat White, small, full cream milk, extra hot

The counter is one surface of a larger platform. The rest of it, the member app and the staff dashboard, is on the project page.

What Goes Wrong When You Cannot Touch It

You cannot prove it works.

Stripe gives you a simulated reader, and the simulated reader always pays. I tried tapping my own card on my own phone. It did not go through, because the feature is not enabled in this country. So the real test is somebody else's hands. I test simulated, send a production build to the client, and they run the happy path at the counter. If it works, we beta it. If it does not, I am debugging from a text message.

Every bug is yours until proven otherwise.

When stickers stop printing, the cable might be loose, the Pi might be down, the Wi-Fi might be weak. I cannot unplug anything and plug it back in. So the working assumption has to be that my software broke, and I go looking there first.

This bit me. The food Pi rebooted on a Tuesday and the printer never came back onto the USB bus. Nothing noticed. PrintNode said online. Our API said online, because it asked PrintNode. The external monitor said online, and it was right, the API was up. The Saturday service came and forty orders queued silently inside a printer queue with no printer behind it. Every layer was telling the truth about the layer below it, and the bottom layer was a USB cable, which reports nothing. Recovery was about fifty stickers, reprinted one at a time.

You recommend hardware you have never used.

The Pi was my suggestion. I had never set one up. It was the only thing I could find that did what the client needed at a price that made sense, and I was asking them to buy it on my word. If it turned out not to work with PrintNode, or with the printer, or with their network, that was on me.

Your eyes are your logs, and only while it is online.

The Pi's Linux logs tell me a lot: whether the printer is on the bus, whether the queue is enabled, when the network dropped. But I can only read them while the Pi is connected. If the counter's access point is far enough away that the Pi sits at two bars, it can fall off at any minute, and when it does I know nothing until it comes back. The moment I most need the logs is the moment I cannot reach them.

What I Did About It

Log everything, and treat silence as failure.

After the forty orders, a small agent now runs on each Pi. Every sixty seconds it checks whether the printer is physically on the USB bus and pushes a heartbeat to the API. If the heartbeats stop, that is the alarm. A Pi that has gone quiet and a Pi that has died look identical from Australia, and both get a human sent to the counter. Three of the checks would have caught the outage five days early.

Research before promising.

Forums, docs, and a lot of time in support chat with Stripe and PrintNode, asking the questions I could not answer by trying: does this work on this device, in this country, over this connection. Every restriction I found out in a chat window was one I did not find out at a counter on a Saturday.

Be honest about what you cannot do.

I told the client I had never built this before. I told them the platform works in their country and not in mine, so I could not test it myself, and if they would rather have a developer who could, I understood. I told them I would need someone on site to plug things in and tap cards for me. They stayed, and the arrangement has held because nobody was surprised by it later.

Test with what you have.

I bought a Pi here. A Zebra label printer costs too much to buy for one test, so I plugged the Pi into my inkjet instead and sent it a job through PrintNode. It printed. That was enough to rule out the question I was actually worried about: can a document sent over an API from the other side of the world come out of a printer plugged into a Pi. Yes. Then I recommended the setup with a little more confidence than I had the week before.

Where This Leaves Me

I still cannot touch any of it. It runs anyway.

The hardware is still in Australia. But the system now tells me when it is lying, the client knows exactly what I can and cannot see, and the counter runs.

Every one of these lessons came from something breaking at a counter I have never stood at. I would rather have learned them cheaper. I am glad I learned them anyway.