Zařízení¶
Zařízení jsou fyzické prvky (zámky, světla, zásuvky) připojené k systému Dveřník.
Typy zařízení¶
| Typ | Popis | Akce |
|---|---|---|
lock |
Zámek (dveře, brána, turniket) | open, close, short_open |
light |
Osvětlení | on, off, blink |
outlet |
Zásuvka / napájení | on, off |
locker |
Skříňka | open, close, short_open |
custom |
Vlastní typ | dle adaptéru |
Role zařízení v zóně¶
Každé zařízení je přiřazeno k zóně přes kolekci zone_devices s jednou ze dvou rolí:
Primární zařízení (primary)¶
- Řídí přístup do zóny (typicky zámek)
- Každá zóna musí mít alespoň jedno primární zařízení
- Při zahájení relace se odemkne
- Při odchodu posledního uživatele se zavře
- Určuje, zda je zóna "obsazena"
Sekundární zařízení (secondary)¶
- Doplňková zařízení (světla, zásuvky)
- Zapínají se při zahájení relace
- Vypínají se při ukončení relace
- Uživatelé je mohou během relace ovládat manuálně
Sdílení zařízení
Jedno fyzické zařízení může být přiřazeno k více zónám s různou rolí. Například zámek na chodbových dveřích může být primary v zóně A a secondary v zóně B.
Režimy zámku (lock_mode)¶
Primární zařízení typu lock mají nastavení režimu:
| Režim | Popis |
|---|---|
permanent |
Zámek zůstane otevřený po celou dobu relace |
short_open_5s |
Zámek se odemkne na 5 sekund a automaticky zavře |
short_open_10s |
Zámek se odemkne na 10 sekund a automaticky zavře |
Režim zámku se uplatňuje vždy — jak při zahájení relace, tak při manuálním ovládání během relace.
Hlavní dveře a ukončení relace
Zámek s rolí primary a režimem permanent se v panelu aktivní relace považuje za hlavní dveře. Když zákazník úspěšně zamkne všechny takové zámky zóny, aplikace sama otevře potvrzení ukončení relace (stejné jako tlačítko Ukončit), a pokud zákazník zůstane v relaci, zobrazí nad tlačítkem upozornění, že akce stále běží a účtuje se. Zámky s krátkým otevřením (short_open_*) a sekundární zámky tohle chování nespouštějí. Je to čistě chování rozhraní — na straně serveru se nic nemění.
Komunikační adaptéry¶
Každé zařízení má nastavený komunikační adaptér, který určuje jak systém komunikuje s fyzickým hardwarem.
Demo adaptér (demo)¶
Simuluje zařízení pro vývoj a testování. Stav se ukládá do kolekce app_config.
Konfigurace: adapter_config = null nebo libovolný JSON objekt (např. {}) — obsah se ignoruje.
Stav zařízení v app_config:
demo_lock_state_{device_id}— hodnoty:"open","close"demo_light_state_{device_id}— hodnoty:"on","off"demo_outlet_state_{device_id}— hodnoty:"on","off"
REST API adaptér (rest_api)¶
Komunikuje s hardwarem přes HTTP. Koncové zařízení (Raspberry Pi, ESP, …) je „hloupý“ GPIO řadič — nic neví o zámcích ani světlech. Veškerý význam akcí je v adapter_config, kde pin_mapping říká, které piny se mají při které akci nastavit.
Adaptér mluví s řadičem dvěma endpointy:
| Endpoint | Účel |
|---|---|
POST /gpio |
Nastaví stavy pinů: {"pins": [{"pin": 4, "state": "on", "duration_ms": 5000}]} (+ jméno uživatele pro audit). duration_ms = automatický návrat do původního stavu |
GET /gpio/status |
Přečte aktuální stavy pinů (stav zařízení + heartbeat) |
HTTP klient má timeout 15 sekund.
Příklad — zámek:
{
"base_url": "http://192.168.1.50:9999",
"auth_header": "Bearer váš-token",
"pin_mapping": {
"open": {"pins": [{"pin": 4, "state": "on"}]},
"close": {"pins": [{"pin": 4, "state": "off"}]},
"short_open": {"pins": [{"pin": 4, "state": "on", "duration_ms": 5000}]}
},
"status_pin": 4
}
| Pole | Povinné | Popis |
|---|---|---|
base_url |
ano | Adresa řadiče, http:// nebo https:// + host (bez koncového lomítka) |
auth_header |
ano | Hodnota hlavičky Authorization, neprázdná |
pin_mapping |
ano | Objekt akce → {"pins": [...]} (viz níže) |
status_pin |
ne | Pin čtený z GET /gpio/status pro zjištění stavu; 0/vynecháno = stav neznámý. Pokud je > 0, musí se objevit v některé akci pin_mapping |
sequence_delay_ms |
ne | Pauza (ms) mezi piny jedné akce; při > 0 se piny posílají jeden po druhém (první synchronně, zbytek na pozadí) — chrání před proudovou špičkou při současném sepnutí více relé. Výchozí 0 |
Jiné klíče na nejvyšší úrovni nejsou povoleny.
Pin v pins (pole s alespoň jedním prvkem):
| Pole | Povinné | Popis |
|---|---|---|
pin |
ano | Číslo pinu, celé číslo ≥ 0 |
state |
ano | "on" nebo "off" |
duration_ms |
ne | Celé číslo ≥ 0; po této době se pin vrátí do původního stavu |
Klíče pin_mapping mohou být pouze open, close, short_open, on, off, blink. Které jsou povinné a které povolené, závisí na typu zařízení:
| Typ zařízení | Povinné akce | Povolené akce |
|---|---|---|
lock, locker |
open, close |
open, close, short_open |
light |
on, off |
on, off, blink |
outlet |
on, off |
on, off |
custom |
žádné | všechny |
Stav zařízení se odvozuje z status_pin a mapování: pokud pin 4 je u open ve stavu on, znamená on na pinu 4 „otevřeno“. Podporuje tak jakoukoli konvenci zapojení — viz invertovaný zámek v předvolbách (on = zavřeno).
Nezačínejte od prázdného JSONu
Ve formuláři zařízení zvolte Začít z předvolby — viz Předvolby a kontrola konfigurace. Předvolby obsahují ověřené konfigurace zámku (standardní i invertovaný), skříňky, světla (jednoduché, s blikáním, sekvenční), zásuvky i demo zařízení pro každý typ.
Kontrola konfigurace při uložení¶
Při vytvoření zařízení a při změně adapter_config, communication_adapter nebo device_type systém konfiguraci zkontroluje a při chybě zařízení neuloží; chyba obsahuje cestu k problému, např. pin_mapping.open.pins[0].state. Kontrola je pouze strukturální — nezjišťuje, zda je zařízení dostupné ani zda je aktivní. Neaktivní (ještě nezapojené) zařízení tak lze předem nakonfigurovat, ale musí mít stejně platnou konfiguraci.
Stávající zařízení se tím nerozbijí. Běh systému (sestavení adaptéru, ovládání, heartbeat) se nezměnil. U zařízení, jehož uložená konfigurace dnešním pravidlům neodpovídá, funguje dál přejmenování, aktivace/deaktivace i změna jiných polí — kontrola se spustí, až když změníte některé z výše uvedených tří polí. Přehled takových zařízení ukazuje kontrola stavu konfigurace.
Znak CHANGE_ME v hodnotě (např. Bearer CHANGE_ME z předvolby) vyvolá jen upozornění — uložit lze, ale zařízení s placeholderem nebude komunikovat, dokud hodnotu nenahradíte.
MQTT adaptér (mqtt)¶
Není implementován. Volba zůstává v databázi kvůli zpětné kompatibilitě, ale ve formuláři se nenabízí (zobrazí se jen u zařízení, které ji již má) a nové zařízení ani změnu konfigurace s ním systém neuloží.
Akce zařízení¶
Všechny příkazy jsou explicitní — systém nikdy nepoužívá "toggle". Vždy se posílá konkrétní příkaz (OPEN/CLOSE, ON/OFF).
| Akce | Popis |
|---|---|
open |
Trvalé odemknutí |
close |
Zamknutí |
short_open |
Krátkodobé odemknutí (5–10 s) a automatické zamknutí |
on |
Zapnutí (světla, zásuvky) |
off |
Vypnutí |
blink |
Zablikání (pouze světla — varování) |
Stav zařízení v panelu relace¶
Panel aktivní relace ukazuje u zařízení stav (Svítí / Zhasnuto / Otevřeno / Zamčeno) jen tehdy, když ho adaptér skutečně potvrdil — to znamená, že dotaz na stav zařízení proběhl bez chyby a vrátil jiný stav než unknown. Jinak panel žádný stav nezobrazí a místo toho napíše poslední známý příkaz („Naposledy: zapnuto 18:02“).
| Situace | Co uvidí uživatel |
|---|---|
| Demo adaptér | Potvrzený stav (demo je vlastním zdrojem pravdy) |
REST API adaptér s nastaveným status_pin a dostupným zařízením |
Potvrzený stav |
REST API adaptér bez status_pin |
Nepotvrzeno — jen „Naposledy: …“ (dostupnost se přesto ověřuje, viz heartbeat níže) |
| Zařízení nedostupné, chyba nebo timeout (2 s) | Nepotvrzeno — jen „Naposledy: …“ |
Poslední příkaz se bere z action_logs napříč všemi relacemi (zařízení mohl mezitím přepnout jiný uživatel, cron nebo ukončení relace). Příkaz blink se nepočítá — stav zapnuto/vypnuto nepřepisuje. Chcete-li, aby panel ukazoval skutečný stav i u REST zařízení, nastavte status_pin.
Dotazy na stav se krátce (3 s) cachují, aby časté obnovování dashboardu nezatěžovalo řadič. Po úspěšném příkazu se cache daného zařízení hned zahodí.
Online / offline zařízení (heartbeat)¶
Cron úloha (výchozí interval DEVICE_HEARTBEAT_INTERVAL_MINUTES = 5 min) ověřuje dostupnost každého aktivního zařízení a ukládá čas posledního úspěšného ověření. Zařízení je online, jen pokud má platný heartbeat (ne starší než DEVICE_HEARTBEAT_TIMEOUT_MINUTES, výchozí 15 min); bez důkazu se nikdy neoznačí jako online.
- REST API adaptér: heartbeat je autorizovaný dotaz
GET /gpio/statusna řadič. Provádí se vždy, i když zařízení nemástatus_pin—status_pinovlivňuje jen to, zda lze z odpovědi zjistit stav (zapnuto/vypnuto), nikoli zda je zařízení dostupné. Úspěchem je odpověď HTTP 200; chyba spojení, timeout (5 s na zařízení) nebo jiný HTTP kód heartbeat neobnoví, takže zařízení po vypršení timeoutu přejde na offline. - Demo adaptér: je vždy dostupný (simuluje se v databázi).
Zařízení se kontrolují postupně, každé nejvýše 5 s, takže nedostupné zařízení zdržuje běh jen o tento limit.
Auditní log¶
Každá akce zařízení se zaznamenává do action_logs s:
- ID relace
- ID zařízení
- Typ akce
- Kdo akci vyvolal (uživatel / systém)
- Časová značka
- Metadata (jméno uživatele, doba trvání)
- Výsledek příkazu (
status,failure_reason,error_detail)
Výsledek příkazu¶
Do action_logs se zapisuje každý pokus o příkaz zařízení, i ten nepovedený. Sloupec status má hodnoty:
status |
Význam | Počítá se do ceny? |
|---|---|---|
success |
Zařízení příkaz potvrdilo. | Ano |
failed |
Příkaz se nepodařilo provést (zařízení neodpovědělo, odmítlo příkaz nebo je špatně nastavené). | Ne |
not_sent |
Zaznamenáno, ale příkaz se neposlal — při odchodu z zóny, kterou dál používají jiní hráči, se světla ani zámky nevypínají. | Ano (uživatel zónu opustil) |
| (prázdné) | Starší nebo ručně vložený záznam. Chová se vždy jako success. |
Ano |
U failed je v failure_reason důvod: timeout (zařízení neodpovědělo včas), unreachable (spojení se nepodařilo navázat), device_rejected (zařízení vrátilo chybu), config_error (chybí pin_mapping pro danou akci nebo je neplatný) a unknown. Pole error_detail (max. 1024 znaků, bez přihlašovacích údajů v URL a tokenů) obsahuje technický detail — HTTP status a tělo odpovědi zařízení — a vidí ho jen administrátor (admin tabulka akcí a časová osa relace); uživatel vidí jen přeložený důvod.
Neúspěšné pokusy nemění cenu relace: cena se počítá jen ze záznamů, které nejsou failed, takže výsledná cena je stejná, jako kdyby se pokus nikdy nestal. Stejně tak neúspěšný příkaz nepřepíše „poslední příkaz“ zařízení na dashboardu. Zapisují se tyto pokusy: otevření primárních zařízení při vstupu (včetně zavíracích pokusů při vrácení vstupu zpět), tlačítka v běžící relaci, vypnutí světel a zavření zámků při ukončení relace, vypnutí světel po zavření provozu (cron) a blikání před zavřením. Záznamy mají stejnou retenci jako ostatní action_logs (90 dní); relace zrušená kvůli nepovedenému vstupu se i s těmito záznamy smaže běžným úklidem prázdných relací.