Etap 5 — Kiosk hardware integration¶
Droga Modbus jest martwa — ten etap jest historyczny
Cały etap 5 opisuje bezpośredni sterownik Modbus TCP w kiosku (ModbusLockerHardware). Od etapu 9 kiosk nie steruje sprzętem bezpośrednio — gada z agentem SmartConf po lokalnym API 127.0.0.1:8800 (POST /v1/doors/{N}/open, POST /v1/jobs/open + poll). Ścieżki Modbus zostały zakomentowane w etapie 9/«G», a pole adresu Modbus skrytki usunięte z bazy w etapie 20. Pełny opis nowej drogi → Komunikacja kiosk ↔ agent.
Bugi lifecycle z v0.78–v0.83 (poniżej) nadal mają wartość historyczną — opisują realne wyścigi otwarcia/zamknięcia, które dziś rozwiązuje pre-check lockerOpenPreCheck (na SmartConf = NO-OP) oraz Job API (agent zarządza cyklem i re-ryglem).
Etap 5 took the Flutter kiosk from a MockLockerHardware proof-of-concept to a Modbus-driven production kiosk on LOCKER-SZB-SDI-001. It also closed several lifecycle bugs that only surfaced once a real lock + sensor was on the bus.
Production state (aktualne na v0.78–0.83) — NIEAKTUALNE
Dziś ta sama maszyna obsługiwana jest przez agenta SmartConf (LOCKER-SZB-SDI-001 na TEMREXLOCKERBOX runs Modbus TCP locker driver since v0.78, hardened through v0.83.127.0.0.1:8800), nie przez bezpośredni Modbus. Sterownik ModbusLockerHardware pozostaje w drzewie jako martwy/dev-only.
Hardware¶
- Locker rig: TEMREXLOCKERBOX with Modbus TCP latch controller on
172.31.0.201. - Driver:
lib/hardware/modbus_locker_hardware.dart. Implements the sameLockerHardwareinterface as the mock — pulses the lock coil for ~300 ms to release, then polls the door-contact register at ~5 Hz to emitLockerEvent.openedandLockerEvent.closed. - App wiring:
app.dartconstructsModbusLockerHardwarein production builds (config-driven; mock kept available for dev / CI).
Lifecycle bugs that landed in v0.78 … v0.83¶
Numbered by the version that fixed them:
v0.78— first Modbus build wired into the production kiosk; replacesMockLockerHardwareend-to-end.v0.79— "kliknąłem otwórz ponownie a była otwarta skrytka":LockerOpenScreenwould deadlock if the user re-tapped "Otwórz ponownie" while the cell was already open. Fix:open()is now idempotent on an already-released latch (no-op + immediateopenedevent).v0.80— broken contact sensor flicker would emit a phantomclosedevent mid-pickup. Fix: debounce on the sensor poll — close needs two consecutive sampled-closed reads.v0.81— "chcę nadać przesyłkę, skrytka 10 wolna": an orphanedASSIGNEDshipment could grab a locker that had been physically reused. Fix:/deposit/begin-existingnow refuses if the existing reservation points to a different machine, and the kiosk reconciles itscached_lockersview againstavailableFunctionsfrom/machines/me.v0.82— UX hardening drop:- Bigger touch targets on
Wyloguj/Anuluj/Cofnij(footer buttons). - PIN buffer is wiped on auth failure (was previously left intact, leading to silent re-attempts on top of stale digits).
Pickupis gated when the locker isn't reportingclosed— refuses to sendconfirm-pickupuntil the latch sensor agrees.Depositis gated when the cell hasn't returned toclosedsince the previous transaction.v0.83— "poszło w otwartą skrzynkę nie wykrył otwartej skrytki i jest w pętli": a deposit could go into an already-open cell because theisClosedcheck was racing the latch open/close cycle. Fix:LockerOpenScreenblocksNadajif the cell is reporting open, and the deposit flow pollsisClosed()before flipping to the success screen.
All of the above are persisted in Machine.currentVersion after the OTA agent installs the corresponding release.
Operational notes¶
Nieaktualne od etapu 9
Poniższe wskazówki dotyczą martwej drogi Modbus. Dziś: kiosk → agent SmartConf (127.0.0.1:8800); gdy agent nie odpowiada, maszyna wchodzi w auto-maintenance, a log /v1 widać w panelu (MachineApiLog).
The Modbus driver shares the kiosk's network with the backend — check the kiosk'sexternalIpinMachineand confirm it can reach the latch controller before reporting "kiosk hangs".- A latch that won't acknowledge will leave the locker in
RESERVEDuntilShipmentWorker.shipment.auto-expirefrees it onexpiresAt. To free it sooner, use the panel's emergency-open (POST /machines/:id/lockers/:lockerId/emergency-open) — that spawns anOPEN_LOCKERtask and the kiosk drives the cell open. - The
MockLockerHardwareis still in the tree for dev — toggle by env var or by editingapp.dart. CI uses the mock; production never does.
What's next¶
Etap 5 closes out kiosk hardware. Etap 7 (multi-machine sync…) and etap 8 (real notifications, OIDC code-flow, Gitea Actions, monitoring) remain.
Co faktycznie weszło później
Mapa etapów rozwinęła się inaczej niż zakładał ten akapit. Sprzęt został w całości przeprojektowany na agenta SmartConf (etap 9), DynaBox bęben (etapy 8/12), Job API (etapy 16/17), funkcje skrytek (etap 19) i Kiosk Helper (etapy 11/22). Aktualna mapa → roadmapa.