Kiosk Helper¶
Co to jest
Kiosk Helper to jeden proces-nadzorca (C#/.NET 8) na maszynie, który zastępuje całą zbieraninę 4 tasków PowerShell wokół kiosku (OTA, czytnik RFID, tray, relaunch). Helper jest rodzicem procesu kiosku — uruchamia go, nadzoruje, aktualizuje, a operatorowi/serwisowi daje tray + zdalne sterowanie z panelu. Status: wdrożony i sprawdzony na LockerBoxie i DynaBoxie.
Po co (problem, który rozwiązuje)¶
Wcześniej na maszynie działały 4 zadania harmonogramu:
| Task | Rola |
|---|---|
SmartBoxKioskAgent |
OTA + heartbeat (SYSTEM, AtStartup) |
SmartBoxKioskUI |
uruchamiacz kiosku (interaktywny, AtLogon) |
SmartBoxKioskTray |
ikonka tray |
SmartBoxHidReader |
hook klawiatury RFID → rfid.txt |
IPC szło przez pliki (rfid.txt, update-state.json). Główny ból: kiosk sam się odpalał po zamknięciu — bo DWA relaunchery (task UI + watchdog agenta co 30 s) nie wiedziały o serwisie → nie dało się serwisować maszyny.
Rozwiązanie: jeden właściciel cyklu życia. Helper jest rodzicem kiosku (kiosk = proces-dziecko, NIE odpalany przez task), więc Tryb Serwisowy faktycznie zatrzymuje odpalanie. Jedno zadanie autostartu (SmartBoxKioskHelper, AtLogon, Highest) odpala Helpera.
Architektura¶
flowchart TB
Task["Task: SmartBoxKioskHelper (AtLogon, sesja konsoli usera)"] --> Helper
subgraph Helper["KioskHelper.exe (.NET 8)"]
Sup[KioskSupervisor<br/>rodzic kiosku]
Loop[HelperHost<br/>pętla 30 s: heartbeat / metryki / OTA / serwis]
Api[LocalApiServer<br/>REST + WS 127.0.0.1:8810]
Rfid[WindowsRfidReader<br/>hook WH_KEYBOARD_LL]
Tray[Tray + config-gate]
end
Helper -->|Process.Start / Kill| Kiosk[smartbox_kiosk.exe]
Helper -->|HTTP X-Machine-Api-Key| Backend[(Backend SmartBox)]
Helper -. most plikowy .-> Files["rfid.txt · rfid-bridge.log · update-state.json"]
Files -. czyta .-> Kiosk
Kiosk -.->|RFID/OTA dziś przez pliki, docelowo WS| Api
Podział cross-platform (mirror SmartConfa):
KioskHelper.Core+KioskHelper.Api—net8.0, cross-platform (config-gate, BackendClient, UpdateService/OTA, KioskSupervisor, lokalne API REST+WS).KioskHelper.App—net8.0-windows(WinForms tray, hook RFID, autostart task, junction, single-instance mutex).
To rozwiązuje pozorną sprzeczność „WPF/WinForms, ale ma działać na Ubuntu": rdzeń jest przenośny, shell jest per-OS (Windows teraz; Linux później reużyje Core+Api — evdev RFID, systemd autostart, symlink).
Co Helper robi¶
- Nadzór kiosku —
KioskSupervisor: startujeC:\smartbox-kiosk\current\smartbox_kiosk.exe, adoptuje już działający (nie plodzi duplikatu ginącego na mutexie), a w trybie „zamknij kiosk" aktywnie ubija kiosk, który wrócił (Reconcile()co tick). - OTA —
UpdateService: pobranie release'u (GET /releases/{id}/file), weryfikacja SHA-256 inline, stop kiosku, rozpakowanie, podmiana junctioncurrent, restart, raportINSTALLED/FAILED. - RFID —
WindowsRfidReader: globalny hookWH_KEYBOARD_LLna wątku STA z pompą komunikatów; flush UID po Enter / po bezczynności. - Lokalne API — REST + WebSocket na
127.0.0.1:8810(jak SmartConf:8800):/v1/status,/v1/config,/v1/service-mode,/v1/restart,/v1/update/check, WS/v1/events. - Heartbeat + metryki do backendu (X-Machine-Api-Key) — w panelu maszyna raportuje się przez Helpera (
agent="helper"). - Tray (jak SmartConf): niebieska ikona „SK" (runtime-rysowana), menu: Pokaż/uruchom kiosk · Serwis: komunikat · Serwis: zamknij kiosk · Restart kiosku · Sprawdź aktualizacje · Konfiguracja… · Zamknij.
- Config-gate — bez ważnego klucza API + połączenia z backendem kiosk NIE wstaje, a tray co ~2 min rzuca powiadomienie „Brak klucza API" (klik → okno konfiguracji).
Most plikowy (kompatybilność)¶
Żeby Helper był drop-inem pod istniejący build kiosku (pilot bez zmiany Fluttera), LegacyBridge pisze pliki, które czyta obecny kiosk:
rfid.txt— append UID na skan (jak staryhid-reader.ps1).rfid-bridge.log— tick liveness co 20 s (kiosk śledzi jego mtime; stale >60 s → „czytnik wymaga restartu"). To Helper musi tickać, bo przejął hook.update-state.json— faza OTA dla splash kiosku.
Most vs WebSocket (do zrobienia)
Docelowo kiosk ma czytać RFID + stan OTA przez WebSocket ws://127.0.0.1:8810/v1/events i most plikowy zniknie. Most jest sprawdzony i działa pod każdą wersją kiosku — czysty WS to porządkowy krok, nie blokuje pilota.
Tryby serwisowe (etap-21)¶
Rozdzielone na dwa niezależne, sterowane z panelu i z traya (zsync. przez backend):
| Tryb | Flaga | Efekt |
|---|---|---|
| Komunikat | Machine.maintenanceMode |
kiosk widoczny + baner „przerwa serwisowa"; kiosk renderuje go z /machines/me |
| Zamknij kiosk | Machine.kioskClosed |
kiosk zamknięty, zostaje tylko Helper → dostęp do Windows na maszynie |
- Helper: czyta obie flagi z
/machines/meco tick.kioskClosed(lokalny tray lub panel) →KioskSupervisorzatrzymuje/utrzymuje kiosk zamknięty.maintenanceModenie dotyka procesu kiosku (to tylko baner). - Endpointy:
PATCH /machines/:id/kiosk-closed(admin),POST /machines/me/service-mode {maintenanceMode?, kioskClosed?}(klucz maszyny — tray sync z webem). - Otwieranie natychmiastowe (bez 30 s oczekiwania):
SetServiceMode(false)czyści też zdalną flagę optymistycznie.
Instalacja¶
Zawsze instaluj DWUKLIKIEM na konsoli maszyny — nie przez SSH
OpenSSH sshd to usługa w sesji 0, więc proces odpalony przez SSH (i installer, i jego auto-start Helpera) ląduje w sesji 0 = niewidocznej dla konsoli usera → kiosk GUI niewidoczny. Dwuklik na konsoli = od razu właściwa sesja interaktywna.
Wariant A — per-maszyna (zaszyty klucz) — zalecany¶
- W panelu: maszyna → przycisk „Instalator Helpera (ta maszyna)" (niebieski).
- Pobiera się mały
.cmdz świeżo zrotowanym, zaszytym kluczem API. - Rotacja klucza rozłącza działający kiosk → backend zwróci 409 dla maszyny ONLINE; przy świadomej reinstalacji użyj wymuś (
?force=true). - Dwuklik
.cmdna maszynie → sam się podnosi (UAC) → bierze genericsetup.exe(obok albo pobiera z backendu z nagłówkiemX-Machine-Api-Key) → odpala/VERYSILENT /APIBASE /APIKEY→ Helper startuje skonfigurowany.
Wariant B — uniwersalny (bez klucza)¶
- Pobierz/skopiuj
SmartBoxKioskHelperSetup.exena maszynę → dwuklik (SmartScreen → „Uruchom mimo to" — niepodpisany). - Instalator sam: kasuje 4 stare taski, ubija stary kiosk, usuwa stare
.ps1(hid-reader/agent/tray), dodaje wyjątek Defendera naC:\smartbox-kiosk, startuje Helpera. Pojawia się w Programy i funkcje. - Klucz: jeśli istnieje
C:\smartbox-kiosk\config.json(stary runtime) — Helper bootstrapuje klucz automatycznie. Jeśli pomijasz klucz — kiosk nie wstaje, a tray nag co ~2 min prosi o uzupełnienie (Konfiguracja… → wpisz klucz). - Zalecany restart maszyny — czysty stan: 1 task
SmartBoxKioskHelper→ Helper → kiosk.
Layout na dysku (bez zmian względem starego)¶
C:\smartbox-kiosk\
config.json # config KIOSKU (apiBase, machineApiKey, smartconf, template…)
helper.json # OSOBNY config Helpera (nie nadpisuje config.json kiosku)
helper.log
rfid.txt · rfid-bridge.log · update-state.json # most plikowy
versions\<ver>\ # buildy kiosku
current -> versions\<ver>\ # junction
helper\KioskHelper.exe
Build instalatora (dla wdrażającego)¶
```powershell
cd kiosk-helper\installer
.\build-installer.ps1 [-SignCertThumbprint
-> publish self-contained single-file -> ISCC -> Output\SmartBoxKioskHelperSetup.exe (~74 MB)¶
Generic exe trzeba **raz** wgrać na VM do hostowania per-maszyna `.cmd`:bash
scp Output\SmartBoxKioskHelperSetup.exe smartbox:/tmp/helper-setup.exe
ssh smartbox 'docker exec smartbox-backend-1 mkdir -p /data/releases/helper && \
docker cp /tmp/helper-setup.exe smartbox-backend-1:/data/releases/helper/SmartBoxKioskHelperSetup.exe'
```
Audyt / recenzja (stan na dziś)¶
Co działa i jest zweryfikowane na żywo¶
- Cutover — instalator kasuje 4 stare taski + stare
.ps1, instaluje Helpera, wpisuje do Programów i funkcji. Sprawdzone na LockerBox + DynaBox. - Nadzór + adopt-running — Helper adoptuje działający kiosk zamiast plodzić duplikat (mutex). Sprawdzone: redeploy nie restartuje kiosku.
- Tryb serwisowy „zamknij kiosk" —
Reconcile()aktywnie utrzymuje kiosk zamknięty (re-kill); zweryfikowane: zamknięty zostaje ≥40 s, otwarcie natychmiast. (Wcześniejszy bug: stary Helper zamykał tylko lokalnie → po restarcie Helpera kiosk wracał — naprawione przez persistkioskClosed+ Reconcile.) - RFID przez most — logowanie kartą działa (Helper hook →
rfid.txt→ kiosk). -
rfid-bridge.logheartbeat — koniec fałszywego „czytnik wymaga restartu" po reboocie. - Ikona „SK" w trayu; config-gate + nag „Brak klucza API"; status w
/v1/status(kioskClosed,maintenanceMode,needsConfig). - Zdalny tryb serwisowy z panelu (oba tryby) + „Sprawdź aktualizacje" z komunikatem.
- Generator per-maszyna (.cmd zaszyty klucz) + uniwersalny + hosting generic exe; trasa
/machines/installer/helper-setup.exebramkowana kluczem maszyny.
Gotchy do zapamiętania¶
Sesje (SSH/silent install)
Instalacja przez SSH/po cichu ląduje w sesji 0 (niewidoczna). Fix po instalacji: taskkill /F /IM KioskHelper.exe + /IM smartbox_kiosk.exe, potem schtasks /Run /TN SmartBoxKioskHelper → task interaktywny w sesji konsoli (LockerBox=sesja 2, DynaBox=sesja 1). Po reboocie task ONLOGON i tak wstaje w konsoli. Dlatego dla usera: dwuklik na konsoli.
Tray po starcie z logowania
Apki startowane przy logowaniu lądują domyślnie w schowku traya („^"), nie na widocznym pasku — to NIE crash. Można przypiąć na stałe.
Do zrobienia¶
- Czysty WebSocket w kiosku — usunąć most plikowy (RFID + update-state + service-mode) →
ws://127.0.0.1:8810/v1/events; wypchnąć przez OTA. - Rollout IKEA + ewentualne pozostałe maszyny (LockerBox + DynaBox zrobione).
- Podpis instalatora (cert → koniec SmartScreen) — hook
-SignCertThumbprintgotowy. - Faza 5 — Ubuntu (Avalonia/headless shell + evdev RFID + systemd autostart + symlink); rdzeń już cross-platform.
- Self-update Helpera (stage
.new+ restart shim) — odłożone z v1.
Dostęp serwisowy (SSH) do maszyn pilotażowych¶
- LockerBox — alias
winsrv(172.31.0.201, userssh, kluczsmartbox_win); hostnameTEMREXLOCKERBOX. Zdalny shell = PowerShell. - DynaBox —
temrex@172.31.0.197(hasło) przez PuTTY plink/pscp; hostnameDynabox-SDI. Współistnieje z agentem SmartConf.
Powiązane¶
- Komunikacja kiosk ↔ agent — Helper nie rusza zamków (to SmartConf); nadzoruje proces, RFID i OTA
- Roadmapa etapów — etap 21 (tryby serwisowe), etap 22 (Helper + generator)