#Hardware, peripherals and the device fleet
TL;DR
- Buying the hardware is easy; driving it is 13 eng-months and ~45% of your support tickets forever
[estimate]— of which ~60% are printing, i.e. ~27% of all tickets. Canonical Domain D effort is 5.0 eng-months at MVP, 10.0 at v1 sellable (S1 cut), 13.0 at Full, +4.0 in v2 (of which 3.0 is v2 core, the P3 build, and 1.0 is v3 handheld SKU certification — see §10) — see 07 — Roadmap, Team and Budget for how that sits against the 125 eng-month total. - Certify six SKUs, not twenty. v1 ships one till family (Sunmi D3 Mini/Pro GMS), one till printer (Epson TM-m30III all-interface, C31CK50152, EUR 314.87
[verified]), one kitchen printer (Epson TM-U220II impact), one CloudPRNT printer (Star TSP143IV), one KDS (Elo I-Series 4), one router (Teltonika RUT241). Every additional SKU costs ~0.25 eng-months to certify and 0.25 eng-months/quarter forever to keep certified. - Per-site hardware: EUR 1,374–1,764 (café) · EUR 4,900–5,800 (40-seat bistro, 2 tills + kitchen) · EUR 11,800–13,400 v1-shippable / EUR 14,300–15,900 with v3 handhelds (120-seat multi-station, and that site is out of v1 scope). The café figure carries the verified GMS till price of EUR 579 (§2.1); canon §5.5 has been corrected from EUR 1,260–1,650 to match. Sold at cost + 15%, which is a 10–13% gross margin after freight, spares and DOA, ~EUR 700–900 of working-capital float per site for 30–90 days.
- The router and a validated AP are a contractual precondition of installation, not a recommendation. Without them peer sync cannot establish on an AP-isolated network and we owe 1.5–2.0 eng-months of cloud-relayed peer path nobody costed. Anything that prints gets a cable.
- Do not build hardware. The BOM saving is EUR 0 at white-label tier and EUR 60–120/unit at custom tier, recoverable only after 3,000–8,000 units — against CE + GPSR + WEEE + Battery Regulation + CRA producer liability. Note the sting: the CRA does not spare us anyway. Our installable Android app plus the backend it requires to function are plausibly a "product with digital elements" regardless of whose logo is on the tablet
[verified — CRA reporting obligations from 11 Sep 2026, full application 11 Dec 2027]. - Hardware operations cost EUR 25–43/Site/month at 100 Sites against the canonical EUR 110–130/Site/month subscription (POS+CRM+KDS, excluding payments residual and messaging). That number, not the BOM, is why the certified matrix stays small and why the in-app Device Health screen is MVP scope.
Cross-references: card-reader commercial choice and PCI posture live in 04 — Payments, fiscalisation, privacy and security; the offline/Coordinator/Epoch semantics that print dispatch depends on live in 02 — System architecture; install-day labour and CAC live in 07 — Roadmap, Team and Budget.
#1. The five rules that generate everything else
| # | Rule | Why it exists | What it costs if broken |
|---|---|---|---|
| R1 | Anything that prints gets a cable. Wi-Fi printers are "unsupported, best effort" and are never sold in a bundle | Kitchens are a 2.4 GHz worst case: stainless multipath, microwave in ch. 6–11, walk-ins as Faraday cages [known] | ~15% of all "printer offline" tickets, permanently |
| R2 | Raster-only printing. HTML/Canvas → 1-bit bitmap → GS v 0. No text fast path, no code-page matrix | CP852/CP1250/CP866/CP1251 per model per language is where CEE bleeds. Raster deletes the entire matrix | ~1.0 eng-months plus an open-ended per-model bug class |
| R3 | GMS/EDLA SKUs only for anything running our app | Non-GMS costs an own MQTT foreground-service push transport at 1.8–2.2 eng-months [estimate, c01], an own OTA pipeline, and a WebView frozen at ROM version | 1.8–2.2 eng-months + the "tablet stopped getting online orders overnight" failure class |
| R4 | We resell OEM-branded devices in our box. Branded bundle, not branded hardware | CE, GPSR, WEEE, EU Battery Regulation and the device half of the CRA stay with Sunmi/Epson/Elo | EUR 15–40k lab testing per SKU + per-member-state WEEE registration + producer liability |
| R5 | The router and a validated AP are a hard install precondition | AP/client isolation makes LAN peer sync impossible, not merely undiscoverable — a cloud-published LAN IP is useless when L2 is blocked | 1.5–2.0 eng-months of cloud-relayed peer path, uncosted anywhere |
R2 has one consequence people miss: on the TM-U220II impact printer a 40-line raster Ticket takes ~2.5 s against ~0.8 s for text [estimate]. That is acceptable at counter-service volumes and is the price of never owning a code-page table. Reinstate the text fast path on the first Customer who measures it and complains.
#2. The certified hardware matrix for v1
Prices are single-unit EU reseller, ex VAT. "Tier" is the canonical scope tier the SKU first appears in (see 05 — The CRM Product and Scope Tiers).
| Role | SKU | EUR ex VAT | Supplier | Tier | Dominant failure mode |
|---|---|---|---|---|---|
Till (Station TILL), 1-till Site | Sunmi D3 Mini GMS, 10.1", integrated 58 mm printer | 579 [verified 2026-08-18; see §2.1] | Jarltech / Shop NFC / Sunmi EU direct | MVP | Integrated printhead is the wear part; 58 mm is narrow for an itemised Receipt |
| Till, 2+ till Site | Sunmi D3 Pro GMS, 15.6" | 639 [verified, r01] | Jarltech / Shop NFC | MVP | Grease haze on glass in 2–4 weeks over a pass; Android version rot |
| Front Receipt printer | Epson TM-m30III, C31CK50152 all-interface (USB-B + USB-C + Ethernet + BT + Wi-Fi in one SKU) | 314.87 [verified, Jarltech] | Jarltech | MVP | Autocutter at ~1–1.5 M cuts; paper roll changes |
| Kitchen printer | Epson TM-U220II impact, Ethernet, 2-colour | 280–340 [estimate] | Jarltech / Logiscenter | v1 | Ribbon every 4–10 weeks; loud; 6 lps |
| Bar / secondary printer | Star TSP143IV LAN (CloudPRNT built in) | 230–280 [estimate] | Jarltech / ITG Store | v1 | Thermal fade near ice and condensation |
KDS (Station KDS) | Elo I-Series 4, 15.6" Android, wall mount | ~1,150 [verified USD-derived, r01] | Elo EU distribution / Jarltech | v1 | Nothing for 3 years — that is why it costs 2× a Sunmi |
| Bump bar | Logic Controls KB1700, USB HID | 250–350 [estimate] | Logiscenter | v1 | Keys stick with grease; wipeable membrane is the spec that matters |
| Cash drawer, 1-till | Safescan SD-4141, 24 V | 85 [canon] | Safescan EU / Jarltech | MVP | Voltage mismatch destroys hardware. Runners jam with coins |
| Cash drawer, heavy | APG Vasario 1616, 24 V | 110–150 [estimate] | Jarltech | v1 | Runners |
| Card reader | Stripe Reader S710 (cellular smart reader) or S700 + S700/S710 Hub for Ethernet | 230–320 [canon] | Stripe Dashboard → Terminal → Shop [verified] | MVP | Pairing/network; commercial choice is 04, not this doc |
| Router | Teltonika RUT241 (4G failover built in) | 155 [canon] | Teltonika EU distribution | MVP | The most reliable box on this list. Nothing |
| UPS | APC BE850G2 (or EcoFlow River 2 for multi-hour) | 125 (110–350) [canon] | Any EU IT distributor | MVP | Battery dies at ~3 yr; it is a consumable, sell the replacement |
| PoE switch | UniFi Flex Mini 2.5G / TP-Link TL-SG1008P | 60–130 [estimate] | Jarltech / local | v1 | A EUR 25 unmanaged switch is a false economy — ~8% of printer incidents |
| AP | UniFi U6 Lite / U6 Pro | 110–200 [estimate] | Local | v1 | Multicast "enhancement" silently breaks mDNS |
Handheld (Station HANDHELD) | Sunmi V3 Mix 575 / L2s Pro 535–595 [verified, r01] | 535–595 | Jarltech | v3 | Dropped, battery at ~5 h continuous, taken home |
| Barcode scanner | Zebra DS2208 | 90–130 [estimate] | Logiscenter | Full only | Cable strain relief |
| Label printer | Zebra ZD421d (ZPL over 9100) | 380–520 [estimate] | Logiscenter | Full only | Head wear; media supply is the Customer's problem |
#2.1 The one price in the matrix I do not believe
Canon fixed the Tier A till at Sunmi D3 Mini GMS, EUR 465. The nearest thing I can verify is the D3 Mini GMS with the 80 mm printer at EUR 579 [verified 2026-08-18, shopnfc.com single-unit listing]; r01's EUR 465 anchor was the non-GMS SKU, and R3 forbids non-GMS. The gap is the EUR 30–260 GMS/EDLA delta [verified from the r01 price table]. The verified EUR 579 wins and canon §5.5 has been corrected to match: the Tier A BOM total is EUR 1,374–1,764, not EUR 1,260–1,650 — the canonical pair of verified till prices is now EUR 579 (D3 Mini GMS) / EUR 639 (D3 Pro GMS), and no other figure should be quoted for either SKU.
Reading: EUR 465 is a distributor number, not a retail number. It is reachable at 28–40% off list at 50+ units/yr [estimate], which we will not have until P2. Until a distributor account exists, quote and budget the till at EUR 579 — that is what the corrected EUR 1,374–1,764 Tier A range already assumes — and treat any distributor discount as upside, not as the plan. This is the highest-value line item in the P0 procurement work: get written quotes from Jarltech, Logiscenter, ITG Store and Sunmi EU direct for a 100-unit annual commitment on D3 Mini GMS, D3 Pro GMS, TM-m30III, TM-U220II and TSP143IV.
#2.2 What we explicitly do NOT support in v1
Publishing this list saves more engineering time than any feature. It goes in the MSA and on the website.
| Not supported | Why | Reinstates when |
|---|---|---|
| Wi-Fi-only printers | R1 | Never |
| Serial-only legacy printers without a network bridge | RS-232 needs an FTDI bridge and a host that owns it | Never in v1 |
| Bluetooth printers on iOS that are not MFi-certified | No iOS target in v1–v2 anyway | Never |
| Generic Xprinter / Rongta clones | Raw 9100 usually works; status reporting does not. "Best effort, unsupported" mode ships — refusing them loses deals in UA/PL | Already "best effort" |
| Coaster pagers (Retekess/LRS) | Integration is a serial "call number N" at best. SMS "your order is ready" at EUR 0.03–0.05 is strictly better and feeds the CRM (05) | Never |
| USB caller-ID modems | PSTN is dead in the EU. SIP webhook (3CX/Asterisk ARI, Twilio) is ~1.5 eng-weeks and works everywhere | v2, if a Customer asks |
| Scales | Legal metrology. WELMEC 7.2 is a notified-body engagement, not a sprint | First deli/bakery Customer who pays, price-computing legal-for-trade only |
| Self-order kiosk + unattended EMV | 4.5 eng-months app + 5–8 unattended EMV cert + 1.0–1.5 EAA/ADA accessibility | Never in this plan |
| Windows POS terminals as primary | Only ever a fiscal-printer bridge, and PL fiscal is a partner printer, not our bridge | Never |
| Raspberry Pi hub SKU (T3) | A Pi with NVMe-on-PoE in a 45 °C cabinet is a truck roll waiting to happen | Cancelled permanently |
| iPad / iOS | No USB host API, no background socket (an iPad cannot be a Coordinator), multicast entitlement by Apple application only | Never in v1–v2; the CMP seam costs +6–10 eng-months to activate |
#3. Per-site BOM at three Site sizes
#3.1 Size 1 — café / bakery, 1 till (the canonical ICP Site)
| Role | SKU | EUR ex VAT |
|---|---|---|
| Till | Sunmi D3 Mini GMS 10.1" (integrated 58 mm printer) | 579 |
| Card reader | Stripe Reader S710 (or WisePOS E) | 230–320 |
| Cash drawer | Safescan SD-4141, 24 V | 85 |
| Router | Teltonika RUT241 | 155 |
| UPS | APC BE850G2 | 125 |
| Cabling | Cat6, 2–3 runs | 200–500 |
| Total | EUR 1,374–1,764 [verified till price; canon §5.5 corrected from EUR 1,260–1,650 to match] |
Sold at cost + 15% → EUR 1,580–2,030 invoiced, EUR 206–265 gross before freight and the spare-pool allocation. Cost + 15% is 13.0% of revenue before freight, spares and DOA, so the achievable hardware gross margin is 10–13%, not the 15–25% canon §5.5 previously stated (corrected). This BOM does not pay anybody's salary; it exists to control the install.
#3.2 Size 2 — 40-seat bistro, counter-service, 2 tills + kitchen
| Role | SKU | Qty | EUR each | Line |
|---|---|---|---|---|
| Till | Sunmi D3 Pro GMS 15.6" | 2 | 639 | 1,278 |
| Front Receipt printer | Epson TM-m30III C31CK50152 | 1 | 314.87 | 315 |
| Kitchen printer | Epson TM-U220II impact, Ethernet | 1 | 280–340 | 280–340 |
| Bar printer | Star TSP143IV LAN (CloudPRNT) | 1 | 230–280 | 230–280 |
| KDS | Elo I-Series 4 15.6" Android, wall mount | 1 | ~1,150 | 1,150 |
| Bump bar | Logic Controls KB1700 | 1 | 250–350 | 250–350 |
| Card readers | Stripe S710 / WisePOS E | 2 | 230–320 | 460–640 |
| Cash drawer | APG Vasario 1616, 24 V | 1 | 110–150 | 110–150 |
| Network | RUT241 + 8-port PoE switch + 1–2 U6 Lite | 1 set | 400–650 | 400–650 |
| UPS | APC BE850G2 or EcoFlow River 2 | 1 | 110–350 | 110–350 |
| Cabling | 4–6 runs | 200–500 | 200–500 | |
| Total | EUR 4,900–5,800 [canon] |
A 40-seat bistro that runs table service is not a v1 Customer. Canon restricts the ICP to counter-service, single-station-first; table plans, coursing, seat splits and handhelds are v3 — they moved out of the P3 build when the v2 tier was split into v2 core (T2 LAN multi-station, UA/PL fiscal, guest ordering + QR PWA + Wallet passes, card-linked identity, Brand Vouchers, WhatsApp/Viber, segmentation, the payments-attach machinery) and v3 (P4 and later). Table service and the handheld waiter app serve a different ICP than canon §1's counter-service-only, single-station-first shape and cannot be funded before the counter-service base is at ~150 Sites. If this Site wants tableside ordering, add 2 × Sunmi V3 Mix (EUR 1,150) and 3 spare batteries, and quote the software as v3.
#3.3 Size 3 — 120-seat multi-station (out of v1 ICP; costed so sales can say no with a number)
[estimate throughout — derived from the canonical unit prices, not a canonical BOM]
| Role | SKU | Qty | EUR each | Line |
|---|---|---|---|---|
| Till | Sunmi D3 Pro GMS 15.6" | 3 | 639 | 1,917 |
| Front Receipt printer | Epson TM-m30III | 2 | 315 | 630 |
| Kitchen printers (grill / cold / fry) | Epson TM-U220II | 3 | 310 | 930 |
| Bar printer | Star TSP143IV | 1 | 255 | 255 |
| Expo printer | Star SP742 HI X (impact + CloudPRNT) | 1 | 300–360 | 330 |
| KDS | Elo I-Series 4 15.6" | 2 | 1,150 | 2,300 |
| Expo screen | Elo I-Series 4 21.5" | 1 | ~1,450 | 1,450 |
| Bump bars | Logic Controls KB1700 | 3 | 300 | 900 |
| Card readers | Stripe S710 | 3 | 275 | 825 |
| Cash drawers | APG Vasario 1616 | 2 | 130 | 260 |
| Network | RUT241 + 16-port PoE + 3 × U6 Pro | 1 set | 900–1,300 | 900–1,300 |
| UPS | 2 × APC BE850G2 or 1 × EcoFlow | 400–700 | 400–700 | |
| Cabling | 8–14 runs, likely in a fitted-out building | 700–1,600 | 700–1,600 | |
| v1-shippable subtotal | EUR 11,800–13,400 | |||
| Handhelds (v3 only) | Sunmi V3 Mix + 2 spare batteries each | 4 | 575 + 60 | 2,540 |
| Total with handhelds | EUR 14,300–15,900 |
Three honest notes on this tier. (a) It needs T2 LAN multi-station — elected Coordinator, Epochs, fencing — which is v2 core, the P3 build (+9.0 eng-months in Domain A). Selling it in v1 is selling a product that does not exist. (b) Networking is EUR 2,000–3,600 = 17–27% of the bill, and the Customer has budgeted EUR 0 of it. (c) Install is 2 people × 2 days, not 5–8 hours; the canonical EUR 550–1,400 install cost is a Tier A/B number and does not hold here.
#3.4 Rules that are part of the BOM, not commentary
- GMS/EDLA SKUs for anything running our app (R3).
- Kitchen printers are impact, never thermal — thermal paper fades to black near a pass. Two-colour is used for allergens and 86'd items.
- Cash drawer voltage is specified with the printer, always. A 12 V drawer on a 24 V DK port burns out. This is the classic destroyed-hardware incident and it is entirely preventable by never selling a drawer separately.
- Spare pool 5–8% in-region · 1 spare card reader per 25 live units · 2–4% RMA/DOA reserve.
- Device lab capex EUR 8–12k for rig 1, second CI rig EUR 8–10k by M12. Without the lab every estimate in this document is fiction.
- Re-certify the matrix every 18 months at 0.25 eng-months/quarter forever. Sunmi and Elo refresh SKUs on a 24–36 month cycle; your runbooks decay with them.
#4. How each peripheral class is actually driven
| Class | Physical transport | Protocol / SDK / API | Where the code lives | Eng-months | Tier |
|---|---|---|---|---|---|
| Till Receipt printer | Ethernet, static IP outside the DHCP pool | Raw TCP 9100, ESC/POS: ESC @ init, GS v 0 raster, GS V 1 cut, ESC p 0 25 250 drawer kick, DLE EOT 1..4 ASB status | :android-app socket layer (Kotlin Socket), serialised per printer | 1.5 (raster core) + 0.8 (transport) | MVP |
| Kitchen printer (impact) | Ethernet, static IP | Same ESC/POS raster path; ~2.5 s per 40-line Ticket at 6 lps [estimate] | Same driver, different paper width (76 mm) and layout template | in the above | v1 |
| Bar / secondary printer | Ethernet, pull | Star CloudPRNT: printer HTTP(S)-polls our endpoint, we return Star markup / ESC/POS passthrough / PNG; printer acks the job ID after printing | Backend job queue + poll endpoint; no device-side socket | 0.8 | v1 |
| Cash drawer | RJ12 6P6C off the printer's DK port, 24 V | ESC p m t1 t2 (m=0 → pin 2). Open-sense line readable in ASB → every open logged with an actor and correlated against no-sale/void | Printer driver; one DK port = one drawer | 0.2 | MVP |
| KDS | Ethernet or Wi-Fi (it is a peer, not a peripheral) | Our own app over WebSocket + local event log. Not a print target | :ui-kds (Domain C, not D) | 0 in D | v1 |
| Bump bar | USB HID | Android InputDevice key events; per-Site remapping required; app is lock-tasked so the keypad cannot navigate away | :android-app | 0.15 | v1 |
| Barcode scanner | USB or Bluetooth HID keyboard wedge; Sunmi integrated engines via broadcast intent | Buffer keystrokes, treat a burst with <30 ms inter-key gaps ending in CR as a scan. Configure CR suffix from the vendor config-barcode sheet | :android-app input interceptor. Focus stealing is the bug | 0.25 | Full |
Customer display (CFD) | Second panel on the same Device (Sunmi D3 Pro dual-screen) | DisplayManager + Presentation, same process → zero IPC, zero sync problem. A crash takes both screens | :ui-cfd (UI in C); device plumbing in D | 0.4 in D | Full / v3 |
| Label printer | Ethernet | ZPL II over raw 9100. Send text over a socket, done | Reuses the 9100 transport | 0.4 | Full |
| Scales | RS-232 via FTDI FT232R USB-serial (~EUR 12), or USB-HID PoS Usage Page 0x8D | Receive a completed Line only (weight + unit price + total). The POS never computes a trade price → we stay outside WELMEC 7.2 | :android-app UsbManager | 0.7 | v2, gated on a paying Customer |
| Handheld | Wi-Fi | Same APK, HANDHELD Station role, one-handed layout | :ui-pos variant | 1.0 (cert only) | v3 |
| Card reader | Ethernet via S700/S710 Hub, Wi-Fi, or cellular (S710) | Server-driven REST + local SDK — see 04 — Payments, fiscalisation, privacy and security. Here: it needs its own VLAN, its own power, and a cable if the Site has one | Domain E | 0 in D | MVP |
| Kiosk | — | — | — | — | Never |
#4.1 The print dispatch path, with the Epoch
Print dispatch is the one peripheral path that touches the correctness core. Every print job carries the durable monotonic Epoch the Coordinator stamped on it; a Device that loses an election stops dispatching. Ticket numbers are cosmetic in the fiscal sense — they are never allocated by the fiscal component and carry no legal meaning — but they are the only human dedupe primitive when fsync turns out to be dishonest (assumption A7), so they are printed in 24 pt and monotonic per Station.
Two properties of this diagram are non-negotiable. CloudPRNT gives genuine at-least-once with dedupe because the printer acks the job ID — that is the technical reason kitchen and bar printers are pull, not push. Raw 9100 has an irreducible ambiguity window — the printer may print and then lose power before your socket flushes — which is why the verify queue and the printed Ticket number exist, and why an engineering-led argument says sell the KDS, not the printer, wherever the Customer will take it.
The fallback chain needs a rate limit that nobody writes down until it bites: when a kitchen switch dies, 40 open Tickets fail over to the expo printer at once and print in queue-drain order rather than fire order. Per-Station ordering by fire time, plus a cap dialog — "40 backlogged Tickets — print all / print summary?" — is 0.2 of the 1.3 eng-months in the health/failover line.
#4.2 Discovery and addressing
| Mechanism | Detail | Reliability |
|---|---|---|
| mDNS / Bonjour | _pdl-datastream._tcp (9100), _printer._tcp. Android NsdManager is flaky; use jmDNS in the native layer | Best-effort only. APs "enhance" multicast and break it |
| Epson proprietary | UDP broadcast on port 3289 (EpsonNet Config) [known] | Good on Epson |
| Star discovery | Star SDK UDP broadcast; mDNS on newer models | Good on Star |
| ARP sweep | Scan the /24, TCP-connect 9100, read DLE EOT, match MAC OUI (00:26:AB Epson) | Ugly, 2–15 s, and the only thing that works behind mDNS snooping. Ship it anyway |
| Addressing policy | Static IP outside the DHCP pool (.240–.250), MAC stored as the durable key, physical label on the printer: KITCHEN — 192.168.1.241 | This is the fix for ~20% of all printer incidents |
The install wizard confirms identity by printing the Station name in 48 pt and asking the installer which physical printer produced it. There is no other reliable way to know which box is the grill.
#5. In-restaurant networking and the standard install kit
#5.1 The requirement, stated as a contract clause
| VLAN | Members | Policy |
|---|---|---|
POS | Tills, printers, KDS, CFD | No inbound from GUEST; static leases for printers |
PAY | Card readers | Isolated; materially reduces the merchant's PCI scope. Merchants land on SAQ B-IP — see 04 |
GUEST | Guest Wi-Fi | Client isolation on, rate-limited, no route to POS/PAY |
~70% of SMB Sites have an ISP all-in-one with no VLAN support [estimate, r01]. That is why we ship the router. The alternative — accepting a flat network — is survivable for a single-station Site (device-level auth, mTLS everywhere, no LAN trust) and is not survivable at T2, because AP/client isolation blocks L2 between peers.
#5.2 Standard install kit (one flight case per installer)
| Item | Qty | EUR [estimate] | Why |
|---|---|---|---|
| Cat6 patch leads, 0.5/2/5/10 m | 12 | 60 | The single most-used item |
| Cat6 box + RJ45 crimp/punch tooling + tester | 1 | 180 | Sites never have the run you need |
| Cable clips, trunking, labels, label printer (Brother P-touch) | 1 set | 120 | Every plug is labelled. ~25% of printer incidents are "staff needed the socket" |
| Spare TM-m30III | 1 | 315 | A dead printer must not become a return visit |
| Spare Sunmi D3 Mini (pre-provisioned) | 1 | 579 | Same |
| Spare RUT241 + spare 8-port switch | 1 ea | 215 | A EUR 25 switch failure is ~8% of incidents |
| Paper rolls (58/80 mm) + TM-U220II ribbons | 20 / 4 | 45 | Never leave a Site on its last roll |
| USB-C PD charger, multi-socket, extension | 1 set | 60 | Counters have one socket |
| Recovery cards (Site ID, Device IDs, support number, offline manager override code) | per Site | ~0 | The offline fallback when the WAN and the phone both fail |
| Wi-Fi survey tool (phone app + a U6 Lite as a test AP) | 1 | 110 | Say no to a bad Site before installing |
| Kit total | EUR 1,684 | One kit per installer, amortised |
The site-survey checklist is not optional and it is the cheapest churn prevention in the plan: socket count and position at the counter · run length from the router to each print point · listed/heritage building? · does the ISP CPE allow static leases? · does the existing AP have client isolation on? · is there a 4G signal in the cellar? A Site that fails the survey is quoted network remediation before the contract, not discovered on install day.
#6. Zero-touch provisioning and MDM
#6.1 The happy path: 4 Devices live in 25–35 minutes
- Devices ship pre-registered: either the reseller enrols them in Android zero-touch (GMS/EDLA only), or we ship a printed QR provisioning card in the box. The QR carries
PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME, the base64url SHA-256 signature checksum, the DPC download URL, the Site Wi-Fi SSID/PSK, and an admin extras bundle with{ "site_claim": "K7M-4T2", "role": "TILL" }[known — key names stable across API 26+]. - Installer powers on, taps the welcome screen 6×, scans the card. Device joins Wi-Fi, downloads the DPC, becomes Device Owner. ~4 min/Device, mostly download.
- DPC applies policy:
setLockTaskPackages+startLockTask, factory reset disabled, USB debugging disabled,setSystemUpdatePolicy(TYPE_INSTALL_WINDOWED, …)— window configured relative to the Site's Business Day close, never hard-coded to 03:00–05:00 (see §9, failure #4). - Our app launches, reads
site_claim, calls home, self-assigns its Station role from the pre-built Site plan in back office. - Printer wizard: mDNS + Epson UDP 3289 + ARP sweep → 48 pt test print per printer → assign static IP, record MAC, stick the physical label. 6–10 min.
- Menu Snapshot, staff, PINs, tax config, signed config bundle sync down. Site is live.
Device Owner can only be established at factory-reset time. A Device an installer "just set up normally" can never be silently updated again without a wipe. The 20-minute runbook is therefore a product requirement, not ops hygiene.
#6.2 The 20% that misses the happy path — the real budget
| Failure | Frequency [estimate] | Recovery | Cost |
|---|---|---|---|
| Device already set up normally → Device Owner unavailable | 8–12% of first-timer installs | Factory reset, redo. If the Customer has already entered data, this is a phone call | 20 min |
| Captive-portal or WPA2-Enterprise Wi-Fi at the Site | 5% | Provision on the RUT241's own SSID first, then migrate | 15 min |
| DPC download blocked by a venue firewall / school-style filter | 3% | Tether to the installer's phone | 10 min |
| Sunmi ROM whose setup wizard does not expose the 6-tap QR path | 2–4% per new ROM | NFC bump provisioning, or a known-good ROM in the lab | 30 min + a lab ticket |
| Zero-touch not enabled by the reseller on that batch | one batch in five | QR card fallback (always ship the card) | 0 if the card is in the box |
| Net | ~20% of installs | Budget 4.5–5.5 net eng-months across Domains C+D for the agent + this taxonomy [c01] |
#6.3 MDM: buy the OS bits, build the product bits
| Capability | Owner | Rationale |
|---|---|---|
| Enrolment, supervision, lock-task/kiosk, OS update window, Wi-Fi payloads, remote wipe, lost mode | MDM (Hexnode or Mosyle base tier) | Only the OS can do these |
| App version, remote config, feature flags with last-known-good cache, log ring-buffer upload, printer health, telemetry, remote app restart, Device Health screen | Our own in-app agent | It works offline against a cached signed config bundle; an MDM does not. It knows what a printer and an unsynced Check are; an MDM does not |
| Option | EUR/Site/mo | Verdict |
|---|---|---|
| Esper Bridge on everything, 6 Devices (USD 4/device/mo, 25-device min) | ~22 [verified list, r08] | 17–28% of a EUR 79–129 subscription. Only above 200 Sites or with a kiosk fleet |
| Hexnode Pro on everything, 6 Devices | ~10 [verified: annual USD 1 / 1.8 / 2.8 / 3.8 / 5.8 per device/mo by tier] | Reasonable, over-bought |
| Base tier for enrolment + kiosk + update window only, 4–6 managed endpoints | 5.5 [canon] | Chosen |
| Build everything ourselves | 0 recurring, +2.0 eng-months and permanent ownership | Only if MDM cost threatens gross margin at scale |
Remote control does not exist on iOS and costs Esper money on Android. Therefore the product must be self-diagnosing: a Device Health screen on every Device (printers green/amber/red, last sync, unsynced Check count, WAN/LAN state, app version, free storage, thermal) plus a single "Send diagnostics to support" button returning a 6-character reference the staff member reads over the phone. This one screen removes an estimated 30–40% of support call time [estimate, r08] and is MVP scope.
Telemetry volume: 6 Devices × 1,440 heartbeats/day × ~200 B ≈ 1.7 MB/Site/day → ~50 MB/Site/month [r08]. Compress and batch on-device — CEE Sites run on metered LTE during outages.
#7. Support, RMA and spares: what it costs per 100 Sites
Assume a realistic P2 mix: 70 Tier A + 30 Tier B Sites, ~EUR 270,000 of hardware deployed (70 × the corrected Tier A mid-point of ~EUR 1,570 + 30 × the Tier B mid-point of ~EUR 5,350), ~450 devices in the field (130 tills, 90 printers, 30 KDS, 100 routers, 100 UPS).
| Line | Basis | EUR/yr per 100 Sites |
|---|---|---|
| Support labour, hardware share of tickets | 1.4 tickets/Site/mo blended [canon] × ~45% hardware-caused [estimate] (of which ~60% are printing, i.e. ~27% of all tickets) × EUR 40–55/Site/mo fully-loaded CZ support cost | 21,600–29,700 |
| Same, with the AI tier-0 agent deployed | EUR 25–32/Site/mo [canon] | 13,500–17,300 |
| MDM base tier | 100 × EUR 5.5 × 12 | 6,600 |
| Spare pool carrying cost | ~EUR 12–16k of standing stock (5 tills, 7 printers, 5 readers, 2 KDS, routers/UPS), 3-yr depreciation + finance | 4,500–6,000 |
| RMA freight + admin | ~23 RMAs/yr at 5% AFR [estimate], advance replacement, EUR 60–90 round trip | 1,600–2,300 |
| Truck rolls after year 1 | ~0.15/Site/yr [estimate] × EUR 180–350 | 2,700–5,250 |
| Consumables goodwill (paper, ribbons, the drawer that arrived jammed) | 800–1,500 | |
| Total, no AI tier-0 | 37,800–51,350 → EUR 31–43/Site/month | |
| Total, with AI tier-0 | 29,700–38,950 → EUR 25–32/Site/month |
Fixed costs allocated on top, not per 100 Sites: device lab EUR 8–12k capex (rig 1) + EUR 8–10k (CI rig 2 by M12); matrix re-certification 0.25 eng-months/quarter forever ≈ EUR 6,000/yr loaded [estimate at EUR 6k/eng-month]; hardware SKU rot 1–2 eng-months/yr [c03].
Working capital. At cost + 15% with 30–90 days between order and collection, each Site carries EUR 700–900 of float [r09]. At P2's 40–60 Sites that is EUR 28–54k standing; at 300 Sites and a Tier-B-heavy mix it is EUR 200k+ — a real reason to route hardware through the distributor's own financing or a leasing partner as soon as volume allows.
The one operational rule that decides whether this scales. One support FTE covers roughly 400–700 Sites on hardware tickets alone at 0.6–1.2 hardware tickets/Site/month and 15 min AHT [estimate, r01]. That is only true if remote diagnostics ship before Site #100. Build the printer status page, the "send test print" button, the network self-test and the one-tap log upload during P1, or gross margin evaporates into a phone queue — and canon's hard stop ("two consecutive quarters in which support headcount grows faster than Site count") fires.
#8. Build our own hardware? No — and the reason is not the BOM
#8.1 What "build your own" costs at each tier
| Tier | What you get | MOQ | NRE | Lead time | Saving vs Sunmi |
|---|---|---|---|---|---|
| T1 — cosmetic white label | Logo on boot animation, silkscreen, retail box, preloaded ROM | 300–1,000 [estimate] | EUR 5–20k [estimate] | 8–12 wk | ~EUR 0/unit |
| T2 — custom ROM + minor mech | Custom Android build, MDM baked in, custom bezel/ports | 2,000–5,000 [estimate] | EUR 50–150k [estimate] | 16–24 wk | EUR 60–120/unit |
| T3 — new ID + tooling | Own industrial design, injection moulds, custom mainboard | 5,000–10,000 [estimate] | EUR 250k–1M+ (tooling alone 60–200k) [estimate] | 9–15 mo | EUR 60–120/unit |
Indicative BOM for a 15.6" Android AIO with printer: USD 217–355, ODM invoice at ×1.4–1.6 = USD 310–520 [estimate, r01]. Against a Sunmi D3 Pro GMS at EUR 639 retail / ~EUR 400 at distributor pricing, T1 saves nothing and T2/T3 recover their NRE only after 3,000–8,000 units. S1 will not ship 3,000 units inside the plan; S2 might, in year 4.
#8.2 The regulatory bill you inherit the moment your logo is on the box
| Obligation | Trigger | Cost |
|---|---|---|
| CE — EMC 2014/30/EU, LVD 2014/35/EU, RED 2014/53/EU | Placing under your own brand | EUR 15–40k lab testing per SKU + technical file [estimate] |
| GPSR (EU) 2023/988, applicable since 13 Dec 2024 | Private-labelling makes you the manufacturer [known] | EU responsible person, technical documentation, traceability, incident reporting |
| WEEE producer registration | EU, per member state | EUR 500–3,000/country/yr + take-back [estimate] |
| EU Battery Regulation 2023/1542 | Any Device with a battery (every handheld, every UPS you brand) | Producer registration, due diligence, labelling |
| CRA (EU) 2024/2847 | Products with digital elements | Reporting obligations from 11 Sep 2026; full application 11 Dec 2027 [verified] — SBOM, coordinated vulnerability disclosure, security updates for the support period, conformity assessment |
| Firmware ownership | Own hardware = own Android security patches, bootloader, OTA | 1.5–3 eng-months/yr forever [estimate] |
| Working capital | 300 Sites × EUR 1,400 | EUR 420k of inventory + in-transit [r01] |
#8.3 The sting: reselling does not exempt us from the CRA
R4 keeps CE/GPSR/WEEE/Battery with the OEM. It does not obviously keep the CRA there. Pure browser-consumed SaaS is out of scope, but downloadable/installable software with a data connection is a product with digital elements, and a remote data-processing service that the product needs to function correctly is pulled into scope with it [verified — DLA Piper and EC CRA guidance, Aug 2026]. Our Android APK is installed on Devices and our backend is necessary for it to function correctly. The conservative planning assumption is therefore:
We owe SBOM, coordinated vulnerability disclosure, a documented support period and vulnerability/incident reporting to ENISA + national CSIRT (24 h early warning / 72 h notification / 14-day final report) from 11 Sep 2026, whether or not we ever brand a device.
[verified on the dates and the reporting clock;[estimate]on our own scoping — this needs a counsel opinion, and it is the same EUR 3–5k conversation as A4]
That reframes the build-vs-buy verdict honestly: reselling saves us the device compliance stack (worth EUR 100k+ per SKU and per-country WEEE admin) but not the software one. Budget the CRA work as a platform line in 08 — Pros, cons, difficulties and risks, not as a hardware line.
#8.4 Verdict
Resell OEM-branded devices in our own bundle: our box, our quick-start card, our pre-provisioned config, our SIM, our support number. The Customer gets the perceived integration of own hardware; we get none of the producer liability. Square/SumUp/Toast build hardware because they are payments-led and subsidise the device against interchange at 100k+ unit volumes; Lightspeed, Revel, Storyous and Dotypos do not, because they are software-led and hardware is a channel cost. We are software-led with a payments residual, not an acquirer.
Reconsider only when all three are simultaneously true: (a) >3,000 terminals/yr, (b) we are merchant-of-record on payments so hardware can be subsidised, (c) a dedicated hardware/ops hire exists. Any one alone is a trap. The T3 hub SKU is cancelled permanently — canon, and correct: correctness must never depend on a box in a 45 °C cabinet.
#9. Top 10 things that break in production
| # | Failure | Share of hardware incidents [estimate] | Blast radius | Detection | What we ship |
|---|---|---|---|---|---|
| 1 | Printer power unplugged — staff needed the socket | ~25% | One Station stops receiving Tickets mid-service | Heartbeat gap >60 s on the ASB poll | Labelled plug + cable clip in the install kit; alert within 60 s; fallback chain to expo/KDS; Device Health screen shows red before the kitchen notices |
| 2 | DHCP lease changed / ISP swapped the router — often a whole new /24 | ~20% | Every printer and every peer at once; at T2 the Coordinator is stranded | "My subnet changed" as a first-class event | Static IPs outside the pool, MAC as the durable key, peers keyed on device_id + cert fingerprint with cloud rendezvous re-resolve, manager notification |
| 3 | Cover ajar / paper out / cutter jam | ~15% | One Station; cutter jam needs ESC @ or a power cycle | DLE EOT 1..4 ASB, polled every 20–30 s | Proactive "paper low" toast before it blocks; route to fallback, never block the Check; printed instructions on the Device Health screen |
| 4 | Nightly ISP CPE reboot at 03:00 inside the OS update window | ~7% | Every Device loses the Coordinator, an election fires while Android may be patching | Simultaneous link-down across all peers | (a) OS update window configured relative to Business Day close, never hard-coded; (b) suppress elections for 120 s after an all-peer link-down — if you lost everyone you lost the network, not the Coordinator; (c) never schedule Daily Close inside that window |
| 5 | Wi-Fi printer out of range / congested | ~8% (and only at Sites that ignored R1) | One Station, intermittently — the worst kind | Latency spikes then socket timeouts | We do not sell Wi-Fi printers. Where one is inherited: "unsupported, best effort", stated in writing |
| 6 | Cheap unmanaged switch or PSU dies | ~8% | Everything downstream of it | All Devices on that switch go dark together | Spare switch in the flight case; PoE switch is a bundle line item, not the Customer's Amazon purchase |
| 7 | Epoch reuse after a whole-Site power cut → double-fire | ~3%, catastrophic when it happens | Duplicate Tickets across the whole kitchen; the "double-fire Friday" | Divergence detector + duplicate Ticket numbers on paper | Coordinator identity = (persisted_epoch, boot_id, monotonic_start); claim needs majority ack from reachable peers or cloud confirmation; in a two-Device Site with no WAN the election loser freezes print dispatch for 60 s |
| 8 | fsync lies on cheap eMMC — the intent log did not survive the power cut | unknown until tested | Silent: a Ticket both did and did not print | The lab test, not production | Week 3 of build: write intent, cut power at 1,000 random offsets on the smart PDU, count survivors (assumption A7). If it lies, the printed monotonic per-Station Ticket number is the only dedupe primitive and print health rises +1.0 eng-months |
| 9 | KDS silently stops receiving — socket in CLOSE_WAIT, screen looks alive | ~5% | The kitchen quietly goes back to paper and never comes back | Nothing, unless we build it | Last-heartbeat age rendered on-screen; full-screen state change after 45 s without a Coordinator heartbeat; Coordinator alarms when a Station holding open Tickets stops acking |
| 10 | Reprint storm after a Station failover | ~4% | 40 Tickets drain to the expo printer in queue order, not fire order | Queue depth on failover | Per-Station ordering by fire time + a cap dialog: "40 backlogged Tickets — print all / print summary?" |
| 11 | Grease film and thermal throttling — haze in 2–4 weeks over a pass; passive AIOs throttle above ~40 °C | ~3% | Slow degradation nobody reports until it is a churn conversation | Thermal state in the heartbeat | Install rule: KDS on the cold side of the pass, ≥1.5 m from a fryer, tilted down. Screen protector + cleaning protocol shipped as a consumable |
| 12 | Device event-log growth makes month 9 slow at the best Customer | 100% of high-volume Sites, eventually | "It's slow on Fridays", unfalsifiable | DB size in the heartbeat | 7 days of closed Checks + all open Checks on-device, hard alarm at 500 MB; cloud is the archive |
Twelve rows for a "top 10" table, because #8 and #12 are the two that are invisible until they are expensive.
#10. Engineering effort — Domain D, reconciled
This is the canonical Domain D roll-up. It excludes the KDS/CFD/POS applications (Domain C), payment terminal integration (Domain E), and the offline/Coordinator core (Domain A).
Each column shows new work in that tier; the total row is cumulative and matches the canonical Domain D figures (5.0 / 10.0 / 13.0 / +4.0).
| Work item | MVP | + v1 (S1 cut) | + Full | v2 delta |
|---|---|---|---|---|
Raster print core: layout → 1-bit bitmap, GS v 0, logos, QR, 58/76/80 mm | 1.5 | — | — | — |
Transport: raw TCP 9100 from :android-app, ASB polling, serialisation per printer | 0.8 | — | — | — |
| Discovery + static-IP wizard + MAC-keyed rebinding + physical labelling flow | 1.0 | — | — | — |
| Basic health / failover / dedupe + verify queue, one printer SKU | 0.8 | — | — | — |
| Cash drawer kick + open-audit | 0.2 | — | — | — |
| Device lab build, one-SKU certification matrix, fsync power-cut rig | 0.7 | — | — | — |
| Star CloudPRNT pull driver | — | 0.8 | — | — |
| Routing engine: Station fan-out, per-Station language, void/modify slips, reprint job IDs | — | 1.4 | — | — |
| Full health/failover/dedupe, Epoch on every print job, reprint-storm cap | — | 1.3 | — | — |
| SKUs 2–3 certified (TM-U220II, TSP143IV) | — | 0.5 | — | — |
| Installer tooling: site survey, network self-test, one-tap provisioning, runbook, labels | — | 0.7 | — | — |
| Support tooling: printer status page, test print, diagnostics bundle | — | 0.3 | — | — |
| HID scanner handling + camera scan path | — | — | 0.4 | — |
CFD device plumbing (DisplayManager/Presentation) | — | — | 0.4 | — |
| Automated regression rig (nightly printer shelf, CI on real hardware) | — | — | 1.0 | — |
| Certification matrix 6→10 SKUs incl. clone "best effort" mode | — | — | 0.6 | — |
| Label printing, ZPL only | — | — | 0.4 | — |
| Peripheral telemetry depth (health history, predictive paper alerts) | — | — | 0.2 | — |
| Handheld SKU certification (drop, battery, cradle, one-handed validation) — v3, not v2 core | — | — | — | 1.0 |
| KDS SKU 2–3 + per-Site bump-bar remapping | — | — | — | 0.6 |
| UA/PL printer matrix expansion incl. driving a GUM-homologated kasa-online printer | — | — | — | 1.2 |
| Scales, receive-completed-Line only | — | — | — | 0.7 |
| Matrix re-certification and SKU rot | — | — | — | 0.5 |
| New work in this tier | 5.0 | 5.0 | 3.0 | 4.0 |
| Domain D cumulative | 5.0 | 10.0 | 13.0 | +4.0 |
The canonical +4.0 v2 delta is unchanged, but it now straddles the v2-core/v3 split: 3.0 is v2 core (KDS SKUs 2–3 + bump-bar remapping, the UA/PL printer matrix incl. the GUM-homologated kasa-online printer, scales, matrix re-certification) and 1.0 is v3 (handheld SKU certification), because the handheld waiter app moved out of the P3 build. Domain D's contribution to the P3 build is therefore 3.0 eng-months, not 4.0.
AI assistance is already baked in at ≈1.25× for this domain [canon]. It helps with ESC/POS and ZPL emission and the layout DSL; it helps not at all with "the Sunmi AIDL service unbinds after 4 h idle", a TM-U220II needing ESC @ after a cutter jam, an Elo panel reporting the wrong Configuration.orientation on a landscape-locked screen, or anything requiring a physical Device on a desk. Certification queues, physical install and RMA logistics compress by 0%.
#11. Open items this document cannot close
| # | Question | Owner | Due | If it goes the wrong way |
|---|---|---|---|---|
| H1 | Distributor pricing. Written quotes at a 100-unit annual commitment for D3 Mini GMS, D3 Pro GMS, TM-m30III, TM-U220II, TSP143IV | Founder | P0 exit (M4) | The plan already assumes the verified EUR 579 GMS SKU and a EUR 1,374–1,764 Tier A BOM (canon §5.5 corrected). If quotes come back at list with no volume discount, hardware GM sits at the bottom of the 10–13% band; a 28–40% distributor discount is the only path back toward 13% |
| H2 | A7 — is fsync honest on the certified SKUs? | QA, smart PDU, 1,000 random power cuts | M1 | Print health +1.0 eng-months; the printed Ticket number becomes the sole dedupe primitive |
| H3 | A8 — does under 40% of the CZ beachhead run 2+ Stations? 30 discovery calls counting actual station counts | Founder | M3 | T2 LAN multi-station moves into v1: +9.0 eng-months in Domain A, MVP slips ~3 months |
| H4 | CRA scoping for our software. Is the APK + backend a "product with digital elements"? | EU counsel, ~EUR 3–5k, same engagement as A4 | before 11 Sep 2026 reporting date | SBOM + CVD + support-period obligations become a permanent platform line regardless of the resell decision |
| H5 | Stripe Terminal per-country device roster for CZ. WisePOS E is documented for 10 Western markets; S700/S710 availability in CZ is the load-bearing fact | Payments owner | M1 | If S710 is unavailable in CZ, the Tier A BOM's reader line and the v3 Apps-on-Devices story both change — see 04 |
| H6 | Elo I-Series 4 EU list price and lead time. The EUR ~1,150 figure is USD-derived | Founder | P0 exit | KDS is ~24% of the Tier B BOM; a EUR 1,450 reality makes the "sell the KDS instead of the printer" argument commercially harder even though it stays technically right |