Webhook
Jak si poslat webhook při krádeži telefonu
Webhook je jediná funkce v celém Pubbym, která posílá data ven. Jakmile někdo vytáhne kabel, pošle POST požadavek přesně tam, kam mu řekneš. Až poplach ukončíš, pošle druhý. Co se s tím stane dál, je celé na tobě.
Zapíná se v Nastavení, v kartě Webhook, a je to VIP funkce. Vedle pole na adresu najdeš tlačítko „Poslat test“, které pošle nanečisto to samé tělo požadavku jako ostrý poplach.
Co přesně přijde
- Metoda.
POST, s hlavičkoucontent-type: application/json; charset=utf-8. - Adresa. Pouze
https://. Android nezašifrovaný HTTP provoz aplikacím blokuje už od verze 9. Požadavek na HTTP by selhal hluboko v systému na socketu a na obrazovce bys neviděl žádnou kloudnou chybu. Adresa se vejde do dvou tisíc znaků, aby se do ní bez problémů vešel podepsaný odkaz s tokenem. - Autorizace. Žádná. Oba konce téhle roury jsou tvoje, takže si ověřovací token dej přímo do adresy (jako parametr nebo do cesty).
- Přesměrování. Nenásledujeme je. Odpověď
3xxby požadavek poslala na server, který jsi nikam nezadal, a POST se navíc při přesměrování často mění na GET, takže by tělo tiše zmizelo. Přesměrování bereme jako chybnou adresu a rovnou ti to řekneme. - Opakování (Retries). Tři pokusy v rozmezí zhruba čtyř sekund. Ale jen tehdy, když tvůj server vůbec neodpoví. Vytažení kabelu a ztráta místní Wi-Fi jdou často ruku v ruce, takže jeden pokus by nestačil. Čtvrtý pokus za dvě minuty by už ale telefonu, který za chvíli vůbec nemusí být na síti, nijak nepomohl.
- Timeout. Čtyři sekundy na spojení, osm sekund na celé volání.
Tělo požadavku
unplugged
{
"app": "pubby",
"v": 1,
"event": "unplugged",
"id": "9f2c4a1b0d3e",
"at": "2026-09-03T19:33:20Z",
"grace": 10,
"shared": true
}
Došlo k vytažení kabelu. Tento webhook odchází okamžitě, ještě před vypršením nastavené prodlevy sirény.
stopped
{
"app": "pubby",
"v": 1,
"event": "stopped",
"id": "9f2c4a1b0d3e",
"at": "2026-09-03T19:34:02Z"
}
Poplach jsi manuálně ukončil. Chodí jedině tehdy, pokud se předtím úspěšně odeslal unplugged.
test
{
"app": "pubby",
"v": 1,
"event": "test",
"id": "41d0c8b7a562",
"at": "2026-09-03T19:20:05Z"
}
Pošle ho výhradně tlačítko „Poslat test“ v nastavení aplikace.
Význam polí
app– řetězec, vždyckypubby. Užitečné pro společný endpoint, do kterého posíláš víc různých věcí.v– číslo, verze formátu těla. Přidání dalšího pole do JSONu ji nezvedne; číslo se zvedne jedině tehdy, pokud nějaké existující pole změní svůj význam.event– řetězec, jedna ze tří hodnot:unplugged,stopped,test.id– řetězec, dvanáct hexadecimálních znaků. Událostiunpluggedistoppedz jednoho konkrétního poplachu nesou stejné ID, takže si je v logu snadno spáruješ. Pokud ti stejnéidpřijde dvakrát u stejnéhoeventu, jde o opakovaný pokus (telefon si myslel, že tvůj server požadavek nezpracoval).at– řetězec, čas události v UTC (podle ISO 8601) oříznutý na celé sekundy. Jde o přesný okamžik vytažení kabelu, nikoliv o okamžik odeslání do sítě.grace– číslo, dostupné jen uunplugged. Říká, kolik sekund zbývá, než se z telefonu ozve skutečná siréna. Nula znamená, že už řve.shared– boolean, jen uunplugged. Říká, jestli v danou chvíli běžela Sdílená hlídka (tedy jestli poplach vidí ještě někdo další). Hodnotafalseznamená, že tento POST je jediné upozornění, které z telefonu ven odešlo.
Zkus to bez telefonu
Než kolem toho začneš stavět logiku, pošli si to samé tělo z příkazové řádky. Tvůj server nepozná rozdíl:
# Send a test payload exactly like the app does
curl -i -X POST \
-H 'content-type: application/json' \
-d '{"app":"pubby","v":1,"event":"unplugged","id":"9f2c4a1b0d3e","at":"2026-09-03T19:33:20Z","grace":10,"shared":true}' \
https://tvoje-instance/api/webhook/pubby-9f2c4a1b0d3e
Parametr -i je tam proto, abys rovnou viděl, co tvůj server odpovídá. Cokoli jiného než kód 2xx bere Pubby jako odmítnutí a dané číslo ti pak vypíše na obrazovku v nastavení. Druhou polovinu poplachu vyzkoušíš tak, že v JSONu přepíšeš pole event na stopped a pole grace se shared úplně vynecháš.
Co se neposílá
Z principu se nedozvíš, že se hlídání vůbec zapnulo nebo vypnulo. Nedozvíš se stav baterie ani polohu telefonu – tu Pubby nezná. O GPS oprávnění si neřekne a nikam ji tak nemůže odeslat.
Myslet si, že systém ti drží stabilní spojení jen na základě jedné počáteční zprávy (bez heartbeat/tepu), je hloupost. Kdyby proces Pubbyho potichu spadl, tvůj dashboard by svítil „hlídá se“ i dlouho potom. Skutečný „tep“ v Pubbym existuje, ale jmenuje se Sdílená hlídka – ta aktivně drží spojení s prohlížečem tvého kamaráda a naopak nečekané ticho vyhodnotí jako poplach.
Home Assistant
Níže je ukázka automatizace se spouštěčem typu webhook. Vlož ji přímo do automations.yaml a uprav pouze webhook_id a entitu, kterou chceš ovládat:
automation:
- alias: Pubby – vytažený kabel
triggers:
- trigger: webhook
# IMPORTANT: Keep this ID secret
webhook_id: pubby-9f2c4a1b0d3e
allowed_methods: [POST]
# Must be false so it works outside your home network
local_only: false
conditions:
- "{{ trigger.json.event == 'unplugged' }}"
actions:
- action: light.turn_on
target:
entity_id: light.obyvak
data:
color_name: red
Adresa, kterou následně napíšeš do aplikace, bude: https://tvoje-instance/api/webhook/pubby-9f2c4a1b0d3e. K tomu si pamatuj tři věci:
webhook_idje tvoje tajné heslo. Kdo ho zná, dokáže ti na dálku spustit automatizaci. Zvol si ho proto dostatečně dlouhé a náhodné.- Parametr
local_only: falsetam být musí. Ve výchozím stavu přijímá Home Assistant webhooky jen z domácí sítě, takže požadavek z telefonu přes mobilní data by neprošel. A protože Pubby odesílá výhradně přeshttps://, potřebuješ instanci dostupnou zvenčí (např. přes Nabu Casa nebo vlastní reverzní proxy). - Událost
stoppedvyřešíš zkopírováním stejné automatizace. Stačí změnit podmínku nastoppeda akci nalight.turn_off. Hodnotawebhook_idzůstává pochopitelně stejná, obě události totiž padají na tu samou adresu.
Další recepty
- ntfy, Pushover, Gotify. Push notifikace přímo do druhého telefonu nebo hodinek. U ntfy stačí zadat adresu tvého tématu a bude to fungovat okamžitě – tělo JSONu se ti jen ukáže v surové formě jako text zprávy.
- Node-RED nebo n8n. Přidej uzel pro příjem POST požadavků a hned za něj dej výhybku (Switch) podle hodnoty v poli
event. Je to nejrychlejší cesta, jak naučit každou událost spouštět jinou komplexní akci. - Discord, Slack, Telegram. Sem napřímo posílat nejde. Tyto služby očekávají vlastní specifická pole (např.
contentnebotext), ale Pubby posílá tvrdě svůj pevný formát. Budeš k tomu potřebovat mezikus (třeba Cloudflare Worker nebo n8n), který ten první JSON prostě přepíše na ten druhý. - Vlastní skript. Dva řádky kódu, které si jen zaznamenají časovou stopu do logu, pokud tě zajímá, jak často ti na mobil někdo sahá.
Na co si dát u webhooků pozor
- Zprávu odesílá přímo hlídaný telefon. Webhook není náhrada za Sdílenou hlídku. Pokud zloděj telefon vypne, nebo se mu rychle vybije baterka, žádný další POST (
stopped) nepřijde a automatizace zůstane viset. - Vynucené zastavení aplikace
stoppednepošle. Pokud systém aplikaci zabije (Force Stop), proces okamžitě zmizí a nemá jak událost odeslat. Kdo si podle událostistoppedněco automaticky vypíná, ať k tomu má pro jistotu postavený i časovač. unpluggedodchází ještě před odkladem. Odklad (grace period) se týká jen reálné sirény v místnosti. Zpráva odchází ihned. Proto je v těle hodnotagrace– ať tvůj server ví, jestli je v danou chvíli v kavárně ještě ticho, nebo už tam je řev.- Nespárované
stoppednechodí. Pokud si na telefonu webhook zapneš až chvíli po vytažení kabelu, ukončovací zpráva už nepřijde, protože neproběhl ten prvotní POST. - Klidná hlídka mlčí. Pokud jsi celou dobu poctivě hlídal, ale nikdo s kabelem ani nehnul, z aplikace ti nepřijde do logu vůbec nic.
Když z telefonu nic nechodí
Zmáčkni v nastavení tlačítko „Poslat test“ a hned si přečti, co ti aplikace vypíše. Tyto tři hlášky mají tři různá řešení:
- „Dorazilo!“ Cílový server v pořádku odpověděl kódem ze série
2xx. - „Někdo tam je, ale odpověděl chybou 404.“ Vrátila se nám odpověď, ale nebyla to
2xxa tohle číslo je její reálný kód. Například:404znamená špatnou cestu,401/403znamená špatný token,3xxje přesměrování (které ignorujeme) a5xxje chyba přímo na tvém serveru. - „Zaklepal jsem, ale server neodpovídá.“ Neozval se vůbec nikdo. Příčinou může být neexistující jméno hostitele, zavřený port, spadlá domácí síť, případně zpracování trvalo déle než tvrdý limit osmi sekund.
A ještě jedna věc, na kterou se dívej jako první: Tvoje adresa musí začínat na https://. Dokud na to nezměníš, Pubby se ani nepokusí komunikovat a textové pole zůstane podsvícené červeně.