• Station je celá stanice/sestava skládající se z x boxů, může se skládat z několika sloupců. Každý station má z výroby vygenerované UUIDv4, dále jako stationId.

  • Box je jedna schránka. Každý box má také z výroby vygenerované UUIDv4, dále jako boxId.

stationId, boxId a basic auth password budou poskytnuta k nastavení do knihovního systému.

Komunikace

Systém komunikace stanice s knihovním systémem je stylem klient-server (klient je stanice) pomocí protokolu HTTPS. Stanice posílá serveru události a server vrací seznam příkazů, které stanice provádí. Například, po zadání pinu na stanici o tom stanice posílá request a server vrací příkaz na otevření boxu.

Adresy requestů mají definovatelnou doménu a prefix cesty, ta se může měnit. Aktuálně ale je https://verbis-boxer.kpsys.cz/verbisbox/v2.

Komunikace probíhá ve formátu JSON.

  • Jestliže server/klient dostane v odpovědi neznámé/nezdokumentované fieldy, ignoruje je.

  • Všechny hodnoty jsou case-sensitive.

  • Všechna UUIDv4 jsou lowercase.

  • Pokud není explicitně řečeno jinak, všechny hodnoty jsou not-null.

Každý request obsahuje field event, ve kterém je stanicí vygenerovaníé UUIDv4 události, dále jako eventId.

V případě, že server do 20s neodpoví, stanice zkusí stejnou (i se stejným eventId) zprávu poslat ještě 2x. Pokud ani na posledni request server neodpoví, stanice se nastaví do deaktivovaného režimu. Dále posílá pouze heartbeat (viz níže).

Autentikace

Klient (station) se autentikuje v každém requestu pomocí basic auth, tedy

Authorization: Basic a2FyZWw6aGVzbG8=

, kde username je stationId stanice, tedy např. 9a64be42-2f1f-4451-915f-dc6cc69aa789, password je náhodně vygenerovaný, 20-ti místný alfanumerický řetězec.

Testovací uživatel

  • Username: 9a64be42-2f1f-4451-915f-dc6cc69aa789

  • Password: kVyqwcqfP4uPCbhn4RER

HTTP hlavičky

Klient (station), kromě Authorization, posílá i hlavičky

Content-Type: application/json
Accept: application/json
User-Agent: VerbisBox/{version}

, kde místo {version} bude aktuální verze SW stanice, ideálně (ne nutně) v SemVer formátu, např. 4.1.35.

Accept-Language

Klient (station) MŮŽE posílat i hlavičku Accept-Language podle specifikace, viz např. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language

X-Verbis-Trace-Id

Klient (station) MŮŽE posílat i hlavičku X-Verbis-Trace-Id sloužící jako MDC (Mapped Diagnostic Context) pro identifikaci akce/requestu v logu. Stanice by měla pro každý request vygenerovat UUID a v této hlavičce ho posílat. Všechny řádky v logu portara v rámci tohoto requestu budou toto UUID obsahovat. Tím lze jednoduše vyfiltrovat jen logy relevantní pro daný request

Log je z webu dostupný pod knihovnickým účtem na stránce /actuator/logfile.

State

Stanice posílá pravidelně echo o svem stavu. Maximální interval bude daný nastavením stanice, defaultně 30s. Maximální znamená, že stanice může echo poslat dříve, např. okamžitě při nastalé chybě.

Stav obsahuje jak aktualní "health" stanice, tak stavy jednotlivých boxů. Boxy stanice posílá všechny, což se může v budoucnu změnit kvůli optimalizaci.

POST /state
{
  "station": "9a64be42-2f1f-4451-915f-dc6cc69aa789",
  "st": "UP",
  "errorMessage": null,
  "inputVoltage": 11.7,
  "internetSignalStrength": 67,
  "boxes": [
    {
      "id": "bad0cc90-54d2-4267-8e2a-9737a3e5b1f8",
      "st": "OPEN"
    },
    {
      "id": "b8ec8f91-2835-4f16-a358-6426e0bc0308",
      "st": "CLOSED"
    }
  ],
  "event": "b171a575-ba4c-48b4-a6bb-3d0670c8ec13"
}
  • Field st nabývá hodnot UP a DOWN.

  • Field errorMessage je nullable.

  • Field inputVoltage je not null JSON number. Udává vstupní napětí (z baterie nebo z adaptéru) ve voltech.

  • Field internetSignalStrength je not null JSON integer (celočíselný). Udává procentuální sílu signálu použitého pro připojení k internetu. Pokud je stanice připojnena drátem, hodnota bude 100.

  • Field boxes[].st nabývá hodnot OPEN a CLOSED.

Pokud je stanice v chybovém stavu, posílá (pokud je toho schopna) stav také:

POST /state
{
  "station": "9a64be42-2f1f-4451-915f-dc6cc69aa789",
  "st": "DOWN",
  "errorMessage": "Low voltage",
  "boxes": [
    {
      "id": "bad0cc90-54d2-4267-8e2a-9737a3e5b1f8",
      "st": "OPEN"
    },
    {
      "id": "b8ec8f91-2835-4f16-a358-6426e0bc0308",
      "st": "CLOSED"
    }
  ],
  "event": "ba0cb1ce-2b6a-4162-83d2-70e76f4fe929"
}

Server může odpovědí vynutit např. nastavení textu displeje

Response 200

{
  "type": "wait-for-input",
  "displayMessages": ["Zadejte PIN"]
}

Nebo v případě chyby, dočasně deaktivovat stanici

Response 200

{
  "type": "station-disable",
  "displayMessages": ["Stanice je vypnuta"]
}

Jestliže server nedostane od stanice po 2min žádný heartbeat request, stanice se považuje za vypnutou/nedostupnou. Verbis zakáže jakékoliv akce s boxem a upozorní administrátory.

Jestliže naopak stanice nedostane od serveru po 20s odpověď, server se považuje za vypnutý/nedostupný. Stanice nastaví na displeji text "Stanice je vypnuta" a zakáže jakékoliv operace.

Vložení objednávky do boxu

Knihovník příjde ke stanici, naskenuje knihu. Stanice pošle serveru request s typem identifikátoru: BAR_CODE nebo RFID a hodnotou.

POST /item-identify
{
  "station": "9a64be42-2f1f-4451-915f-dc6cc69aa789",
  "identifierValue": "1234567890",
  "identifierType": "BAR_CODE",
  "event": "b3118eb2-41cf-44c6-8f3b-e2dc85913df4"
}

Response 200

{
  "type": "box-open",
  "boxes": ["bad0cc90-54d2-4267-8e2a-9737a3e5b1f8"],
  "displayMessages": ["Otevírám schránku..."]
}

Na základě box-open se otevře box s id bad0cc90-54d2-4267-8e2a-9737a3e5b1f8 a na displeji se zobrazí informační text "Vložte knihu do schránky a zavřete". Po otevření boxu (nebo všech boxů) stanice posílá /state s aktuálním stavem otevřenosti boxů.

POST /state

Response 200

{
  "type": "wait-for-closing",
  "boxes": ["bad0cc90-54d2-4267-8e2a-9737a3e5b1f8"],
  "displayMessages": [
    "Vložte knihu",
    "do schránky",
    "a zavřete"
  ],
  "cancellable": true
}

Knihovník vloží knihu do schránky a schránku zavře. Zavřením stanice pošle serveru opět request /state s aktuálním stavem otevřenosti boxů.

POST /state

Response 200

{
  "type": "wait-for-input",
  "displayMessages": ["Zadejte PIN"]
}

Do jednoho boxu může knihovník vložit více knih, každou knihu ale vkládá samostatně. Po každé musí box zavrít a otevřít, aby se eliminovaly lidské chyby.

V této chvíli má knihovník možnost akci zrušit stisknutím tlačítka "zrušit", ještě před uzavřením boxu. Stisknutím tlačítka "zrušit" stanice pošle serveru request

POST /cancel
{
  "station": "9a64be42-2f1f-4451-915f-dc6cc69aa789",
  "event": "b35d890f-a8f4-4ce9-a2c8-3cc9e213df2f"
}

Server v takovém případě ví, který box je otevřený a tedy ví, která akce (v tomto případě objednávka) se ruší.

Response 200

{
  "type": "wait-for-closing",
  "boxes": ["bad0cc90-54d2-4267-8e2a-9737a3e5b1f8"],
  "displayMessages": ["Zavřete schránku"]
}

Vyzvednutí objednávky z boxu

Čtenář příjde ke stanici, zadá 6-místný PIN, který dostal např. SMSkou. Stanice pošle serveru request

POST /pin-enter
{
  "station": "9a64be42-2f1f-4451-915f-dc6cc69aa789",
  "pin": "123456",
  "event": "150e9676-91cf-4870-a02a-2bdb9cf03884"
}

Response 200

{
  "type": "box-open",
  "boxes": ["bad0cc90-54d2-4267-8e2a-9737a3e5b1f8"],
  "displayMessages": ["Otevírám schránku..."]
}

Na základě box-open se otevře box s id bad0cc90-54d2-4267-8e2a-9737a3e5b1f8, stanice posílá /state request a na displeji se zobrazí informační text "Odeberte knihy a zavřete".

POST /state

Response 200

{
  "type": "wait-for-closing",
  "boxes": ["bad0cc90-54d2-4267-8e2a-9737a3e5b1f8"],
  "displayMessages": [
    "Odeberte knihy",
    "a zavřete"
  ]
}

Čtenář odebere knihy a schránku zavře. Zavřením stanice pošle serveru /state request

POST /state

Response 200

{
  "type": "wait-for-input",
  "displayMessages": ["Zadejte PIN"]
}

Chybové odpovědi

Jakýkoliv request může skončit s chybou. Chybové odpovědi podporují standardní HTTP status kódy (série 4XX a 5XX) a jsou ve standardizovaném formátu. Field type je v případě chyby exception, exceptionType pak definuje konkretni chybu. Hodnoty v níže uvedených přikladech jsou jen orientační.

Např. v případě stisknutí tlačítka "zrušit" ve chvíli, kdy akci zrušit nelze:

Response 400

{
  "type": "exception",
  "exceptionType": "CannotCancelException",
  "displayMessages": [
    "Tuto akci",
    "nelze zrušit"
  ]
}

Např. v případě chyby na serveru:

Response 500

{
  "type": "exception",
  "exceptionType": "IllegalStateException",
  "displayMessages": [
    "Nastala chyba",
    "na serveru"
  ]
}