Skip to content
SBC-Standard The data standard for libraries

Operation

The protocol alone is not enough. A controlling program must first find the display, the connection needs securing, and what may appear on a screen standing in public is not determined by design intent but by data protection.

The identification file#

A display places an identification file <programname>.dat beside its executable: UTF-8, one KEY=value per line, lines beginning with # are comments. It is written at start-up and replaced atomically (write, rename).

APP_NAME=displayprogram
APP_VERSION=0.2.0
PROTOCOL=SBC-AP
PROTOCOL_VERSION=1
CAPS=session,idle,message,venue,monitor,config,lifecycle
HOST=127.0.0.1
PORT=7207
PID=4711
MUTEX=A manufacturer's display
EXE_PATH=c:\programs\display\display.exe
CONFIG_PATH=c:\programs\display\display.ini
STARTED_UNIX_UTC=1786819200

APP_NAME, PROTOCOL, PROTOCOL_VERSION, HOST, PORT and PID are required. CAPS saves connecting when all that needs settling is whether an area exists at all.

Is the display running?#

That is answered not by the presence of the identification file but by this check, in this order:

  1. On Windows: the named mutex from MUTEX. Your own handle is to be closed again immediately – while it is open it keeps the name alive artificially, and a display that ended long ago would still count as running.
  2. Otherwise: the process id from PID.
  3. Failing that: ping.

If the check fails, HOST and PORT still hold good – they say where the display will be reachable once it has started. PID and STARTED_UNIX_UTC, by contrast, always refer to the last run and mean nothing afterwards.

Securing the connection#

The default is binding to 127.0.0.1: then only someone already working at that computer can reach the display. For the usual case – display and controlling program on the same computer – that is all there is to say.

If the display sits on another computer on the library's local network, for instance as a small computer behind the screen, it must require authentication:

{"v":1,"cmd":"hello","auth":{"token":"…"}}

If the value is missing or wrong, the display answers every request other than hello and ping with 401 unauthorized. The secret is agreed outside the protocol and entered in both programs.

Not on the internet#

The interface does not belong on the internet – not even with a token. It transmits in the clear and is meant for short distances within the library, not for a publicly reachable service.

Anyone wanting to drive a display at a remote site connects the two networks (VPN) and then treats the display like one on the local network. Port forwarding on the router is no substitute.

Data protection#

A patron display stands in public, and whoever is standing alongside reads it. Therefore:

  • No name in the clear, no address, no full e-mail address. customer.masked carries initials or the like; e-mail addresses are shortened (b***[at]example.org).
  • The patron number is expressly permitted (customer.number). It is said out loud at the desk anyway, names nobody on its own and helps when comparing with the card.
  • Item titles say what somebody is reading and are therefore particularly worth protecting. A display that evaluates items should show titles only while the person is standing there and drop them when the session ends. A display that does without titles and merely counts is expressly conformant.
  • If the workplace is left unattended – locked screen, break – the controlling program sends idle.show so that nothing is left standing.
  • The display does not store session data permanently.

Logging#

Both sides should offer a log that can be switched off and that records every incoming line and every response with a timestamp. It is the only tool with which the interplay of two manufacturers can be traced.

Because the log contains personal data it is switched off by default, is kept on the device itself and is limited in size.

Obligations of both sides#

A display

  • ignores unknown fields,
  • answers every request exactly once and never closes without a response,
  • answers ping even while it is busy,
  • states truthfully in caps what it understands.

A controlling program

  • evaluates caps and copes with missing areas,
  • treats 404 and 501 as information, not as a fault,
  • works with a short timeout and few retries,
  • never holds up business at the desk because a display does not answer,
  • tells the staff at most in passing that the display is absent.

Checking your own implementation#

The following client is enough to run a display through its paces – it needs nothing but Python.

#!/usr/bin/env python3
"""Smallest complete SBC-AP client. Usage: sbcap.py [port]"""
import json, socket, sys

PORT = int(sys.argv[1]) if len(sys.argv) > 1 else 7207

def call(cmd, **fields):
    request = {"v": 1, "cmd": cmd, **fields}
    with socket.create_connection(("127.0.0.1", PORT), timeout=5) as s:
        s.sendall((json.dumps(request, ensure_ascii=False) + "\n").encode("utf-8"))
        s.shutdown(socket.SHUT_WR)
        response = b""
        while b"\n" not in response:
            part = s.recv(4096)
            if not part:
                break
            response += part
    return json.loads(response.decode("utf-8").strip())

print(call("hello", client={"name": "sbcap.py", "version": "1.0"}))
print(call("session.open", lang="en",
           customer={"masked": "B. L.", "number": "10245"},
           counters={"loans": 5, "holds": 1, "holds_ready": 1}))
print(call("session.update",
           items=[{"kind": "loan", "title": "Der Schwarm", "due": "2026-08-29"}],
           counters={"loans": 6, "borrowed": 1}))
print(call("session.close", delay=1, seconds=10,
           dates={"due_next": "2026-08-29", "next_open": "2026-08-18"}))

This page was translated automatically from the German original. If anything reads oddly or looks wrong, please let us know — the German edition prevails.