Bisher richtete die App den Pi per SSH ein: Adresse, Benutzer und Passwort ins
Webformular, Knopf druecken. Das verlangte ein SSH-Passwort in einem Browser,
ein weiteres Paket (ssh2) und eine Verbindung vom Server zum Pi.
Jetzt andersherum. Die App legt einen Link bereit und wartet. Auf dem Pi wird
das Skript geholt und gestartet, dort wird der Drucker ausgewaehlt, und am
Ende meldet sich der Pi von selbst an. Wer einen Drucker ansteckt, steht
ohnehin am Pi - dort gehoert auch die Frage hin, welcher es sein soll.
Die Auswahl zeigt Klartextnamen aus dem sysfs: "EPSON TM-T88IV" statt "lp0".
Bei mehreren Druckern ist das der Unterschied zwischen Wissen und Raten.
Das ausgelieferte Skript ist zusammengesetzt, nicht statisch: einrichten.sh ist
eine Vorlage, in die setup.js Adresse, Code, print-server.py und die
systemd-Unit einsetzt. Heraus kommt EINE Datei - auf dem Pi ist nichts
nachzuladen, und eine halb geglueckte Uebertragung kann es nicht geben.
Zwei Endpunkte muessen ohne Anmeldung auskommen, weil der Pi sich bei Authentik
nicht anmelden kann. Der Einrichtungscode ist dort der einzige Schluessel: 32
Zeichen, gilt einmal und 30 Minuten, nur im Arbeitsspeicher, zeitkonstant
verglichen, hinter einem eigenen Zaehler.
Die Adresse des Pi wird der Verbindung entnommen und nicht dem Rumpf der
Anmeldung - was der Pi ueber sich behauptet, koennte auch jemand anders
behaupten. Die eigene Adresse leitet die App aus dem Host-Kopf ab und prueft
sie streng, statt sie zu maskieren: der Wert landet in einem Shell-Skript.
Geprueft am echten Pi (Debian 13, TM-T88IV): Link erzeugen, am Pi abholen,
Drucker aus der Liste waehlen, Anmeldung, Uebernahme, Probedruck. Dazu die
Abweise: verbrauchter Code, falscher Code, Abholung ohne Code, und dass die
uebrige API weiterhin 401 liefert.
Entfaellt: provision.js, install.sh, die Abhaengigkeit ssh2, das SSH-Formular.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Einrichtung war Handarbeit: Dateien per scp auf den Pi, dort install.sh
mit sudo starten, Token abschreiben, in die .env eintragen, Dienst neu
starten. Das ist genau die Sorte Arbeit, die beim naechsten Geraetetausch
niemand mehr weiss. Jetzt macht das ein Knopf unter "Einstellungen":
Adresse, Benutzer und Passwort eintragen, und die App meldet sich per SSH an,
prueft Python/systemd/Druckergeraet, uebertraegt deploy/bondrucker/, startet
install.sh mit einem selbst erzeugten Token, raeumt auf und prueft von aussen
nach. Jeder Schritt steht mit Ergebnis im Protokoll.
Damit das ueberhaupt Sinn ergibt, liegt der Druckerzugang jetzt in der
Datenbank statt in der .env - sonst muesste hinterher doch wieder jemand auf
den Server. Die PRINTER_*-Werte in der .env sind nur noch Startwerte beim
allerersten Start, wie RATE_PER_10MIN auch.
Zwei Fehler, die beim Testen der Einrichtung auffielen:
install.sh startete den Dienst nicht neu, sondern nur "enable --now". Bei
einer erneuten Einrichtung lief die Bruecke deshalb mit dem ALTEN Token
weiter und lehnte jeden Bon mit HTTP 403 ab. Jetzt: restart.
Die Gegenprobe fragte nur /status ab - und /status prueft kein Token. Ein
Dienst mit altem Token galt damit faelschlich als bereit. Die Bruecke meldet
in /status jetzt zusaetzlich, ob das mitgeschickte Token passt (Version 1.1),
und die Einrichtung prueft das mit.
Zugangsdaten werden einmal benutzt und danach vergessen; das erzeugte Token
wird aus dem Protokoll entfernt, bevor es in den Browser oder ins Journal
geht. Neu dabei: ssh2, reines JavaScript.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Der Kunde soll mit einem Zettel zur Kasse gehen koennen, auf dem steht, was
er zahlen muss. Drei Wege fuehren jetzt zu einem Bon: der Knopf "Bon" auf der
Timer-Karte druckt den Zwischenstand und laesst den Timer weiterlaufen,
"Beenden" druckt den Endbeleg, und in der Historie laesst sich jeder Beleg
nachdrucken.
Der Drucker haengt per USB an einem Raspberry Pi und ist damit vom
Timer-Server aus nicht direkt erreichbar. Auf dem Pi laeuft deshalb eine
kleine Bruecke (deploy/bondrucker/, nur Python-Standardbibliothek), die
fertige ESC/POS-Daten per HTTP annimmt. Das Bon-Layout bleibt bewusst hier
im Repo, damit Aenderungen daran nicht auf dem Pi angefasst werden muessen.
Beim Beenden wird erst gespeichert und dann gedruckt. Eine leere Papierrolle
ist damit ein Papierproblem und kein Datenproblem - der Vorgang steht in der
Historie, die Oberflaeche sagt ausdruecklich, dass der Bon nicht gedruckt
wurde, und nennt den Grund.
Ohne PRINTER_HOST in der .env ist die Druckfunktion aus und die App verhaelt
sich unveraendert.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>