Running a fleet of smart vending machines: screens, payments and peripherals

The vending machine in a station or an office lobby is no longer just coils and a coin slot. Inside the newer ones there is a small Linux computer, often a Raspberry Pi or an industrial board, driving a touch screen, talking to a card reader and a coin unit, turning the motors that drop the product, and reading the temperature of the cabinet. All of that is software, and software needs updating: new screens for a promotion, a fix for the card reader, a new product layout. Driving to every machine with a laptop does not scale past a handful.
What runs inside a machine
Split the work into small services that each do one job. A typical machine has four:
- The shop screen, a local web app that shows products and prices and takes the customer's choice.
- Payments, which talks to the cashless reader and the coin and note units, usually over a serial link or an MDB adapter on USB.
- Vend control, which drives the motors or spirals and checks the drop sensor so a customer is never charged for a product that did not fall.
- Telemetry, which reports sales, stock and cabinet temperature.
Described together in tuna.json, they start in the right order and are updated and rolled back as one set:
{"services": {
"payments": {"command": "./payments/run.sh", "cwd": "volume", "healthPath": "/health", "port": 7001},
"vend": {"command": "./vend/run.sh", "healthPath": "/health", "port": 7002},
"shop": {"command": "./shop/run.sh", "dependsOn": ["payments", "vend"],
"port": 8080, "healthPath": "/health", "expose": true},
"telemetry": {"command": "./telemetry/run.sh", "dependsOn": ["vend"]}}}
The payments service keeps its transaction journal on the volume, so a sale that happened while the network was down is still there after an update and can be settled later.
The screen is a kiosk
Turn on the kiosk for the fleet and every machine opens the shop service full screen at boot, with no desktop, no cursor and no right-click menu. While the app is still starting, the machine shows its own status page with the device name and the state of each service instead of a blank screen, and it switches to the shop as soon as the shop answers. Resolution and zoom are fleet settings that a single machine can override, which helps when one model has a different panel. From the hub you can ask any machine for a screenshot of what its customers are looking at right now.
Peripherals and permissions
Services run as an unprivileged tuna user, never as root. The installer gives that user the screen, touch input and audio. Card readers, coin units and motor boards usually sit on serial ports or GPIO pins, so add the user to those groups once when you prepare the image:
sudo usermod -aG dialout,gpio tuna
Keep the hardware code behind a small local API (the payments and vend services above). The shop screen then never touches a serial port, and you can test it on a laptop against a fake.
Updates that never strand a customer
A new release is installed next to the running one and only becomes current after every service with a health path answers. If payments fails to open the card reader, the machine goes back to the previous release by itself and reports which service failed and its last lines of output. A power cut in the middle of an update leaves the machine on the old or the new release, never half of each.
Roll out in steps. Mark the machine in your own office as a canary, then widen to a few sites, then everyone:
tuna push vending --notes "new card reader driver" --percent 10
Stock, sales and temperature on a dashboard
Every service gets its device's own key in TUNA_DEVICE_API_KEY, so the telemetry service can send readings without any credentials of yours on the machine:
curl -X POST "$TUNA_API_URL/api/devices/self/data" \
-H "authorization: Bearer $TUNA_DEVICE_API_KEY" -H "content-type: application/json" \
-d '{"temp": {"value": 4.2, "unit": "°C", "title": "Cabinet"}, "sales_today": 37, "door_open": false}'
Each machine gets a dashboard of what it sends, and the fleet dashboard puts the same values side by side, so a machine whose cooling is failing or whose door was left open stands out before the products spoil.
One fleet, many locations
Prices, the payment provider's endpoint and the location name differ from site to site. Set defaults for the fleet and let a machine override its own values, and the overrides are marked so you can see which machines are special. A machine that stops checking in shows up as silent and can send you a notification, and when you really need a shell, the remote terminal is off by default, asks for consent each time and records the session.
More to read
Info kiosks that stay on: managing touch screens in lobbies, museums and stations
Managing PV parks: site controllers, inverters and remote updates
Keeping electric car chargers online and up to date
How to manage a fleet of weather stations
Build an IoT sensor dashboard with an ESP32 and a managed gateway
One command to release to every kind of device