mirror of
https://github.com/screentinker/screentinker.git
synced 2026-06-29 09:23:16 -06:00
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>
104 lines
4.7 KiB
Markdown
104 lines
4.7 KiB
Markdown
# PiP Event Countdown
|
|
|
|
Push a **live, self-clearing countdown overlay** to a ScreenTinker screen (or group) with
|
|
the PiP API. The overlay ticks down `DD : HH : MM : SS` in real time and — the fun part —
|
|
**removes itself the instant the target time arrives**. There is no clearing poll: the
|
|
script sets the PiP `duration` to "seconds until the target", so the player drops the
|
|
overlay at exactly zero and shows a quick 🎉 first.
|
|
|
|
Great for: New Year's Eve, product launches, store opening / closing, shift changes,
|
|
webinar "starts in…", conference session timers, "back in 15 minutes".
|
|
|
|
## How it works
|
|
|
|
```
|
|
countdown.js --(POST /api/pip, type:web, duration = seconds-to-target)--> player
|
|
|
|
|
overlay_base_url/countdown-overlay.html?target=<ms>&title=<text> |
|
|
v
|
|
countdown-overlay.js ticks the clock every second; at zero shows 🎉 <title>
|
|
...and the player auto-removes the PiP at the same moment (duration elapsed)
|
|
```
|
|
|
|
`countdown.js` is a **one-shot** push — it doesn't stay running. Re-run it to change the
|
|
target or title; the player keeps last-show-wins, so the new overlay replaces the old.
|
|
|
|
## Files
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `countdown.js` | Computes seconds-to-target and pushes one PiP. `--clear` removes it early. |
|
|
| `countdown-overlay.html` / `countdown-overlay.js` | The overlay page the player loads in an iframe. Must be served by your ScreenTinker host (same-origin with the player). |
|
|
| `config.example.json` | Copy to `config.json` and fill in. |
|
|
| `test.js` | Offline unit test of the date math (`npm test`). |
|
|
|
|
## Setup
|
|
|
|
1. **Mint a token.** In the dashboard create an API token with the **`full`** scope
|
|
(PiP is fleet-affecting and can render arbitrary web content, so it requires `full`).
|
|
|
|
2. **Serve the overlay assets.** Copy `countdown-overlay.html` and `countdown-overlay.js`
|
|
into the directory your ScreenTinker server serves at the web root (the same place
|
|
`index.html` is served from — the `frontend/` dir in this repo). They must be reachable
|
|
at `overlay_base_url`, and **same-origin** with the player so the server's CSP
|
|
(`script-src 'self'`) allows `countdown-overlay.js`. (Inline scripts are blocked by the
|
|
CSP — that's why the JS is a separate file.)
|
|
|
|
3. **Configure.**
|
|
```bash
|
|
cp config.example.json config.json
|
|
# edit config.json: api_base, api_token, overlay_base_url, device_id, target, title
|
|
```
|
|
|
|
4. **Run.**
|
|
```bash
|
|
node countdown.js
|
|
# or override target/title on the CLI:
|
|
node countdown.js "2026-07-04T21:00:00-05:00" "Fireworks!"
|
|
# clear it early:
|
|
node countdown.js --clear
|
|
```
|
|
|
|
## config.json
|
|
|
|
| Key | Meaning |
|
|
|-----|---------|
|
|
| `api_base` | Base URL of your ScreenTinker server, e.g. `https://signage.example.com`. |
|
|
| `api_token` | A `full`-scope `st_…` token. |
|
|
| `overlay_base_url` | Public URL of `countdown-overlay.html` (served by your host). |
|
|
| `device_id` | A device **or** group id to show on. |
|
|
| `target` | Target datetime, any `Date.parse`-able string (ISO 8601 recommended, include a TZ offset). |
|
|
| `title` | Heading shown above the clock, and the 🎉 message at zero. |
|
|
| `position` | `center` (default), `top-right`, `top-left`, `bottom-right`, `bottom-left`. |
|
|
|
|
## Local quick-start (this repo's dev instance)
|
|
|
|
The dev server runs at `https://localhost:3443/` with a self-signed cert, so disable TLS
|
|
verification for the run. Copy the overlay assets into the served `frontend/` dir first so
|
|
`https://localhost:3443/countdown-overlay.html` resolves.
|
|
|
|
```bash
|
|
cp config.example.json config.json
|
|
# config.json:
|
|
# "api_base": "https://localhost:3443/"
|
|
# "api_token": "st_REPLACE_WITH_A_FULL_SCOPE_TOKEN"
|
|
# "overlay_base_url": "https://localhost:3443/countdown-overlay.html"
|
|
# "device_id": "DEVICE_OR_GROUP_ID"
|
|
# "target": a time ~2 minutes out, e.g. "2026-06-18T19:42:00-05:00"
|
|
# "title": "Demo"
|
|
|
|
NODE_TLS_REJECT_UNAUTHORIZED=0 node countdown.js
|
|
```
|
|
|
|
Watch the screen count down and disappear on its own at zero. (`config.json` is
|
|
git-ignored so your token never gets committed.)
|
|
|
|
## Notes & limits
|
|
|
|
- The PiP `duration` caps at **24h (86400s)**. For a target more than a day out the
|
|
overlay still shows, but it can't auto-clear at zero — re-run within 24h of the target
|
|
for the self-clear effect. The script warns you when the target is beyond the cap.
|
|
- PiP is **ephemeral**: it isn't part of the device's saved layout, so a player reboot
|
|
clears it. Re-run `countdown.js` after a reboot if needed.
|
|
- Offline devices are reported, not queued — show it while the screen is online.
|