Developing a Mobile App for Vending Machines
A vending machine without a mobile app means cash acceptors and coin mechanisms. With an app: QR payment, cashless transactions, loyalty program, push notifications about new products, purchase history. For network operators: real-time telemetry, fill levels, mechanical errors, revenue by location.
Telemetry: DEX/UCS Protocol and Modern IoT
The vending machine standard is the DEX/UCS (Data Exchange / Universal Communications Standard) protocol. Most commercial machines (Crane, Sanden, Azkoyen) have a DEX port — RS-232, 9600 baud. Through DEX you can read sales counters, errors, inventory levels. The problem: DEX was designed for periodic data collection during service, not for real-time online monitoring.
Modern solution: IoT controller (Telemetry Gateway) connects to the DEX port and network (4G/Wi-Fi). Vendors: Parlance, CPI, Nayax, Coinco. They provide REST APIs for mobile apps and dashboards.
No standard IoT module? Build one with Raspberry Pi Zero + RS-232 adapter + Python DEX parser + MQTT publishing:
import serial, paho.mqtt.client as mqtt
def read_dex_data(port='/dev/ttyUSB0'):
ser = serial.Serial(port, 9600, timeout=5)
# Initialize DEX session
ser.write(b'\x04') # EOT — start session
response = ser.read_until(b'\x04') # read until EOT
return parse_dex_block(response)
def parse_dex_block(data: bytes) -> dict:
# Parse VA (Vending Machine Audit) blocks
# VA1 — identification, VA2 — sales data, VA3 — inventory
blocks = data.split(b'\x1c') # FS separator
return {block[:3].decode(): block[3:].decode() for block in blocks}
MDB: Payment Management
MDB (Multi-Drop Bus) is the protocol for payment devices inside a machine (cash acceptor, coin mechanism, card reader). Most modern payment controllers work through MDB Master — the main machine controller manages peripherals.
For cashless payment from phone: a payment module (Nayax VPOS Touch, PayLink) connects to the machine's MDB bus as an MDB Peripheral. User pays in the app → server signals the payment module → module emulates a coin/bill in MDB → machine dispenses item.
QR Payment: Session Mechanics
// iOS: generate QR with session token for machine
class VendingSessionManager {
func createPaymentSession(machineId: String, amount: Decimal) async throws -> PaymentSession {
let session = try await api.createSession(VendingSessionRequest(
machineId: machineId,
amount: amount,
expiresIn: 120 // 2 minutes
))
// QR contains session.deepLink — opens app when scanned
return session
}
func pollSessionStatus(sessionId: String) -> AsyncStream<SessionStatus> {
AsyncStream { continuation in
Task {
for await _ in Timer.publish(every: 2, on: .main, in: .common).autoconnect().values {
let status = try? await api.getSessionStatus(sessionId)
continuation.yield(status ?? .unknown)
if status == .completed || status == .expired { break }
}
continuation.finish()
}
}
}
}
Polling session status every 2 seconds is simpler than WebSocket in this case. Session has a 120-second TTL: if user doesn't pay, the QR is stale and the machine resets waiting state.
Inventory and Telemetry for Operators
Operators see in the app (or web dashboard) for each machine: inventory by slot, revenue by day/week/month, errors (jammed item, cash acceptor failure, refrigeration issue). Route optimization: an optimized list of machines to restock today, considering inventory and sales forecast.
Integration with operator accounting systems: 1C, SAP, custom ERPs — via REST or file exchange (CSV/XLS). Data normalization from different machine models is a key backend task.
Developing a client app (QR payment, purchase history, loyalty) + operator dashboard for a vending machine network: 3–5 months. Pricing is calculated individually after analyzing machine models and payment infrastructure.







