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>
90 lines
3.4 KiB
Markdown
90 lines
3.4 KiB
Markdown
# PiP Weather Widget
|
|
|
|
A small, always-on **weather widget** that floats in the corner of a ScreenTinker screen.
|
|
It polls [Open-Meteo](https://open-meteo.com) (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 URL
|
|
- `api_token` — an `st_` API token with the **`full`** scope (PiP is fleet-affecting)
|
|
- `overlay_base_url` — where `weather-overlay.html` is served (see "Serve the overlay")
|
|
- `device_id` — a device **or** group id
|
|
- `lat`, `lon`, `location_name` — the place to report
|
|
- `units` — `"metric"` (°C, km/h) or `"imperial"` (°F, mph)
|
|
- `poll_interval_sec` (default 600), `position` (default `top-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.:
|
|
|
|
```bash
|
|
cp weather-overlay.html weather-overlay.js /path/to/screentinker/frontend/
|
|
# then overlay_base_url = https://<your-server>/weather-overlay.html
|
|
```
|
|
|
|
## Run
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
npm test # -> RESULT: PASS ✅
|
|
```
|
|
|
|
## Local quick-start (this machine)
|
|
|
|
A player is already running and paired here:
|
|
|
|
- `device_id`: `DEVICE_OR_GROUP_ID`
|
|
- `api_base`: `https://localhost:3443/`
|
|
- `overlay_base_url`: `https://localhost:3443/weather-overlay.html` (copy the two overlay files into the local server's `frontend/` first)
|
|
- token: an `st_…` full-scope token
|
|
|
|
The local server uses a self-signed cert, so prefix the command:
|
|
|
|
```bash
|
|
NODE_TLS_REJECT_UNAUTHORIZED=0 node weather.js ./config.json
|
|
```
|
|
|
|
> Keep `overlay_base_url` on the **same origin** as the player (e.g. both `localhost`),
|
|
> 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.
|