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>
3.4 KiB
PiP Weather Widget
A small, always-on weather widget that floats in the corner of a ScreenTinker screen.
It polls Open-Meteo (free, no API key) for current conditions
plus today's high/low and pushes a compact web overlay via the PiP API. On each poll it
re-pushes; the player keeps a single overlay slot (last-show-wins), so the widget updates in
place. It's shown with duration: 0 (stays until cleared) and clears itself on exit.
Open-Meteo ──poll──▶ weather.js ──POST /api/pip──▶ ScreenTinker ──▶ screen overlay
What it shows
Big current temperature, a condition emoji + text, the location, today's H/L, and a footer with humidity, wind, and the last-updated time. The card tints blue in daytime, dark at night.
Files
| File | Purpose |
|---|---|
weather.js |
poller + PiP pusher; also exports the pure normaliser for tests |
weather-overlay.html / weather-overlay.js |
the overlay page rendered in the player's iframe |
config.example.json |
copy to config.json and fill in |
fixture-weather.json |
saved Open-Meteo response used by the offline test |
test.js |
offline test of the WMO code map + normaliser (npm test) |
Configure
Copy config.example.json to config.json and set:
api_base— your ScreenTinker base URLapi_token— anst_API token with thefullscope (PiP is fleet-affecting)overlay_base_url— whereweather-overlay.htmlis served (see "Serve the overlay")device_id— a device or group idlat,lon,location_name— the place to reportunits—"metric"(°C, km/h) or"imperial"(°F, mph)poll_interval_sec(default 600),position(defaulttop-right),width/height,border_radius,opacity
Serve the overlay
A web PiP renders overlay_base_url in an iframe in the player. Because the server CSP is
scriptSrc 'self', the overlay loads its JS from a same-origin file (weather-overlay.js),
so host the overlay on the same origin as the player. Copy both files into the signage
server's static frontend directory (the one served at /), e.g.:
cp weather-overlay.html weather-overlay.js /path/to/screentinker/frontend/
# then overlay_base_url = https://<your-server>/weather-overlay.html
Run
node weather.js # uses ./config.json
node weather.js /path/to/config.json
Stop with Ctrl-C — it clears the overlay before exiting.
Offline test
npm test # -> RESULT: PASS ✅
Local quick-start (this machine)
A player is already running and paired here:
device_id:DEVICE_OR_GROUP_IDapi_base:https://localhost:3443/overlay_base_url:https://localhost:3443/weather-overlay.html(copy the two overlay files into the local server'sfrontend/first)- token: an
st_…full-scope token
The local server uses a self-signed cert, so prefix the command:
NODE_TLS_REJECT_UNAUTHORIZED=0 node weather.js ./config.json
Keep
overlay_base_urlon the same origin as the player (e.g. bothlocalhost), or the self-signed cert / CSP will block the iframe.
Notes
- PiP is ephemeral — it isn't persisted, so a screen reboot clears it; the next poll re-shows it.
- Offline devices are reported, not queued.
- Open-Meteo asks for reasonable polling; 600s (10 min) is plenty for a weather widget.