Nachrichtenaufbau
Jede Nachricht ist eine einzelne Textzeile und enthält genau ein JSON-Objekt. Das Steuerprogramm sendet einen Auftrag, die Anzeige sendet genau eine Antwort.
→ {"v":1,"id":17,"cmd":"session.open","customer":{"masked":"B. L."}}
│ │ │ │
│ │ │ └─ Angaben des Kommandos
│ │ └────────────────────── Kommando
│ └────────────────────────────── frei wählbare Kennung des Auftrags
└───────────────────────────────────── Fassung des Protokolls
← {"v":1,"id":17,"ok":true,"result":{"state":"active"}}
Verbindung#
Die Verbindung ist eine gewöhnliche TCP-Verbindung. Die Anzeige nimmt sie an, das Steuerprogramm baut sie auf.
Die Anzeige lauscht vorgabegemäß auf 127.0.0.1, also nur auf demselben
Rechner. Steht sie an einem anderen Rechner im örtlichen Netz der Bücherei, muss
sie die Anmeldung verlangen; ins Internet gehört die Schnittstelle überhaupt
nicht (siehe Betrieb).
Der Standardport ist 7207. Weicht eine Anzeige davon ab, gibt sie den Port über ihre Kenndatei bekannt; auch dort steht, unter welcher Adresse sie zu erreichen ist.
Zwei Verbindungsmodelle#
Beide muss eine Anzeige beherrschen:
- Eine Verbindung je Auftrag – verbinden, senden, Antwort lesen, schließen. Zustandslos und ausfallfest; ein Steuerprogramm braucht dafür kaum mehr als einen Socket. Die Anzeige schließt die Verbindung, sobald sie die Antwort abgeschickt hat.
- Stehende Verbindung – mehrere Aufträge nacheinander über dieselbe
Verbindung. Die Anzeige beantwortet sie in der Reihenfolge des Eingangs; wer
mehrere Aufträge gleichzeitig unterwegs haben will, ordnet sie über das Feld
idzu.
Die Anzeige darf eine stehende Verbindung nach längerer Ruhe schließen (empfohlen: zehn Minuten). Das Steuerprogramm muss damit rechnen und neu verbinden. Ein Verbindungsabbruch beendet keine laufende Sitzung: Was auf dem Bildschirm steht, bleibt stehen.
Zeile und Zeichensatz#
- Jede Nachricht endet mit einem Zeilenvorschub (
LF, 0x0A). Ein davor stehender Wagenrücklauf muss die Gegenseite hinnehmen, aber nicht erzeugen. - Der Zeichensatz ist UTF-8 ohne Byte-Order-Mark. Ein trotzdem vorangestelltes BOM verwirft die Anzeige.
- Eine Zeile soll 8 KiB nicht überschreiten; verarbeiten muss die Anzeige mindestens 8 KiB.
Ohne Prüfsumme und Sequenznummer#
Wer die Verbuchungsschnittstelle kennt, wird beides vermissen. Hier gibt es weder das eine noch das andere, und zwar mit Absicht:
- Die Prüfsumme stammt in SIP2 aus der Zeit der seriellen Leitung, auf der
ein einzelnes gekipptes Zeichen unbemerkt durchging. TCP sichert die Strecke
bereits selbst ab und stellt die Reihenfolge her. Bleibt eine Zeile
unvollständig, ist sie kein gültiges JSON – die Anzeige antwortet mit
400 bad_request, statt Halbes zu verarbeiten. - Die Sequenznummer dient in SIP2 dazu, eine verlorene Antwort erneut anzufordern. Hier kann nichts verlorengehen, ohne dass es auffällt: Jeder Auftrag erhält genau eine Antwort, und bricht die Verbindung ab, weiß das Steuerprogramm es sofort.
Das Feld id ist deshalb ausdrücklich keine Sequenznummer: Es ordnet nur
Antworten zu, wenn mehrere Aufträge gleichzeitig unterwegs sind. Es muss weder
lückenlos noch aufsteigend sein, und die Anzeige merkt es sich nicht.
Wiederholt ein Steuerprogramm einen Auftrag, weil keine Antwort kam, führt die
Anzeige ihn gegebenenfalls ein zweites Mal aus. Das ist hier folgenlos: Jedes
Kommando beschreibt einen Zustand und keine Bewegung – session.update
setzt den Stand der Sitzung, es zählt nichts hoch.
Der Auftrag#
| Feld | Pflicht | Inhalt |
|---|---|---|
v |
ja | Fassung des Protokolls, derzeit 1 |
cmd |
ja | Kommando, kleingeschrieben, Punkt als Trenner |
id |
nein | Zahl oder Zeichenkette; die Antwort trägt sie unverändert zurück |
Alle weiteren Felder gehören zum jeweiligen Kommando.
Die Antwort#
{"v":1,"id":17,"ok":true,"result":{"state":"active"}}
{"v":1,"id":18,"ok":false,"error":{"code":404,"name":"unknown_command","text":"…"}}
ok sagt, ob der Auftrag ausgeführt wurde. result fehlt, wenn es nichts zu
berichten gibt.
error.text ist eine Diagnosemeldung für den Mitschnitt – nicht zur Anzeige
bestimmt und in keiner festgelegten Sprache. Wer dem Personal etwas melden will,
wertet code und name aus.
Fehlerkennungen#
| Code | name |
Anlass |
|---|---|---|
| 400 | bad_request |
Zeile unlesbar, Pflichtfeld fehlt, Wert unbrauchbar |
| 401 | unauthorized |
Anmeldung nötig oder fehlgeschlagen |
| 404 | unknown_command |
Kommando unbekannt |
| 404 | unknown_key |
Schlüssel bei config.get/config.set unbekannt |
| 409 | wrong_state |
Kommando im derzeitigen Zustand nicht sinnvoll |
| 500 | internal |
innerer Fehler der Anzeige |
| 501 | not_supported |
Kommando bekannt, auf diesem Gerät aber nicht vorhanden |
Ein Steuerprogramm muss einen unbekannten Code wie den nächstniedrigeren Hunderterwert behandeln.
Schreibweise der Daten#
| Art | Schreibweise | Beispiel |
|---|---|---|
| Datum | ISO 8601, JJJJ-MM-TT |
"2026-08-29" |
| Zeitpunkt | ISO 8601 mit Zeitzone | "2026-08-29T17:30:00+02:00" |
| Uhrzeit | HH:MM in Ortszeit, 24 Stunden |
"15:00" |
| Wochentag | ISO 8601: 1 Montag bis 7 Sonntag |
2 |
| Dauer | ganze Sekunden als Zahl | 10 |
| Betrag | Dezimalstring, Punkt als Trenner | "-3.50" |
| Währung | ISO 4217 | "EUR" |
| Sprache | BCP 47 | "de", "de-AT", "uk" |
| Wahrheitswert | echtes JSON-true/false |
|
| Kennungen | Zeichenkette, auch wenn sie wie eine Zahl aussieht | "10245" |
Kennungen werden immer als Zeichenkette übertragen, auch wenn sie nur aus
Ziffern bestehen. Lesernummern und Barcodezahlen beginnen in manchen Büchereien
mit Nullen oder enthalten Buchstaben. Als JSON-Zahl geschrieben ginge beides
verloren: Aus "00123" würde 123, und "A4711" ließe sich überhaupt nicht
darstellen.
Fertiger Text als Ausnahme#
Zu jedem darstellbaren Feld x darf ein Feld x_text mit fertig formuliertem
Text treten. Ist es vorhanden, zeigt die Anzeige diesen Text unverändert und
formuliert nicht selbst.
Das ist die Brücke für bestehende Programme und für Büchereien mit eigenen
Formulierungen – nicht der Regelweg. Wer x_text verwendet, gibt Sprachwahl und
Gestaltungshoheit der Anzeige aus der Hand.
Erweiterbarkeit#
Damit das Protokoll wachsen kann, ohne bestehende Einbindungen zu brechen, gelten fünf Regeln:
- Unbekannte Felder werden stillschweigend übergangen. Nie ein Fehler. Wer neue Angaben mitschickt, stört ältere Anzeigen nicht.
- Unbekannte Kommandos ergeben
404 unknown_command, bekannte, aber nicht vorhandene501 not_supported. Beides erlaubt dem Steuerprogramm, auf einen einfacheren Weg auszuweichen. - Herstellereigenes trägt ein Präfix:
x-<hersteller>.für Kommandos und Felder, etwax-ibtc.gate_alarm. Solche Namen kollidieren weder heute noch später mit dem Standard. - Fähigkeiten statt Fassungsnummer: Was ein Gerät kann, erfragt man mit
hello– nicht aus einer Versionsnummer. - Wirkungslose Angaben sind erlaubt. Eine Anzeige, die Titelbilder nicht
darstellt, meldet auf einen Auftrag mit Titelbild trotzdem
ok. Sie hat nichts falsch gemacht, und das Steuerprogramm muss nichts anders machen.