screentinker/Examples/PIP-Incident-Webhook/README.md
screentinker 0b138f10c6
Add PiP overlay example recipes (#132)
Self-contained examples for the PiP overlay API (POST /api/pip), each
with a CSP-safe query-param overlay (external JS), config.example.json,
zero runtime deps, an offline test, and a README:

- PIP-Announce-Broadcast    manual one-shot message to a screen/group
- PIP-Weather-Widget        Open-Meteo current conditions (keyless)
- PIP-Air-Quality           Open-Meteo US AQI widget (keyless)
- PIP-Crypto-Ticker         CoinGecko price strip (keyless)
- PIP-News-Ticker           scrolling RSS/Atom headlines
- PIP-Room-Status-Calendar  ICS-driven Available/Busy room sign
- PIP-Event-Countdown       client-side countdown, auto-clears at zero
- PIP-Welcome-Board         rotating welcome/birthday cards from CSV
- PIP-Fundraiser-Thermometer goal-progress bar from local/URL JSON
- PIP-QR-Rotator            rotating QR codes, encoded client-side
- PIP-Incident-Webhook      event-driven: red on firing, clear on resolved

Also includes the CAP-AU (NSW RFS) and US NWS/NOAA emergency-alert
monitors that push expiry-aware PiP overlays.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 20:20:37 -05:00

109 lines
3.9 KiB
Markdown

# PiP Incident Webhook
An **event-driven** PiP example: a tiny webhook receiver that turns your monitoring
stack's alerts into a floating ScreenTinker overlay — perfect for an engineering wall
TV or NOC screen.
- alert **firing** → red overlay appears (kept until cleared)
- alert **resolved** → overlay disappears
Unlike the CAP / NOAA examples (which *poll* a feed), nothing happens here until your
alerting system **pushes** to `POST /webhook`. Zero runtime dependencies — just Node 18+
(`http` + global `fetch`).
## Payload shapes
It accepts either:
**Generic** (great for `curl`, cron jobs, custom scripts):
```json
{ "status": "firing", "key": "db-down", "title": "Primary DB unreachable", "detail": "conn refused on 5432", "severity": "critical" }
```
**Prometheus Alertmanager** (point a `webhook_config` straight at it):
```json
{ "status": "firing", "alerts": [
{ "status": "firing", "fingerprint": "abc123",
"labels": { "alertname": "HighCPU", "severity": "warning", "instance": "web-1" },
"annotations": { "summary": "CPU > 90%", "description": "web-1 hot for 5m" } }
]}
```
`severity` drives the band colour: `critical`→dark red, `warning`→orange, `info`→amber,
anything else→red. The `key` (or Alertmanager `fingerprint`) is what matches a later
*resolve* back to the overlay it should clear.
## Setup
1. `cp config.example.json config.json` and fill in:
- `api_token` — an `st_` API token with the **`full`** scope.
- `api_base` / `overlay_base_url` — your signage server.
- `device_id` — a device **or** group id.
- `shared_secret` *(optional)* — if set, callers must send it as the `X-Webhook-Secret`
header or `?secret=` query param.
2. **Serve the overlay assets.** The overlay is a `web` PiP rendered in an iframe, so the
player fetches `overlay_base_url` directly. Copy `incident-overlay.html` and
`incident-overlay.js` into the directory your signage server serves at the web root
(e.g. the server's `frontend/` dir) so that `https://<server>/incident-overlay.html`
resolves. They must be **same-origin** with the player (the server CSP only allows
same-origin scripts — that's why the JS is an external `incident-overlay.js`, not inline).
3. `node server.js` (or `npm start`).
## Local quick-start (this repo's dev server)
```bash
cp config.example.json config.json
# edit config.json:
# "api_base": "https://localhost:3443/"
# "api_token": "st_REPLACE_WITH_A_FULL_SCOPE_TOKEN"
# "overlay_base_url": "https://localhost:3443/incident-overlay.html"
# "device_id": "DEVICE_OR_GROUP_ID"
# copy the overlay assets into the server's web root (served same-origin as the player):
cp incident-overlay.html incident-overlay.js ../../frontend/
# self-signed cert on localhost -> let Node accept it:
NODE_TLS_REJECT_UNAUTHORIZED=0 node server.js
```
Then drive it with `curl`:
```bash
# fire a critical incident -> red overlay appears on the player
curl -s localhost:8088/webhook -H 'Content-Type: application/json' -d \
'{"status":"firing","key":"db-down","title":"Primary DB unreachable","detail":"conn refused on 5432","severity":"critical"}'
# ...later, resolve it -> overlay clears
curl -s localhost:8088/webhook -H 'Content-Type: application/json' -d \
'{"status":"resolved","key":"db-down"}'
# health
curl -s localhost:8088/healthz
```
`Ctrl-C` clears any still-showing overlays before exiting.
> Heads-up: this dev box has a shared player. If someone else is demoing on
> `d7c88aa0-…`, point `device_id` at your own device/group instead.
## Wire up Alertmanager
```yaml
# alertmanager.yml
route:
receiver: signage
receivers:
- name: signage
webhook_configs:
- url: http://YOUR_HOST:8088/webhook
send_resolved: true # so "resolved" clears the overlay
```
If you set a `shared_secret`, append it to the URL: `...:8088/webhook?secret=YOUR_SECRET`.
## Test
```bash
npm test # offline; exercises both payload shapes + the colour map
```