# RCWeb Weather

**Weather** turns any RCWeb-capable display into a cinematic, signage-ready dashboard of the current weather for a configurable (or random) location, powered by the free [Open-Meteo](https://open-meteo.com) API. It cycles between several full-screen pages so the same display can show *now*, the *hourly* trend, the *7-day* forecast, *atmospheric details* and *sun & sky* — all without anyone having to touch it.

![icon](pwa-512x512.png "Weather App Icon")

## What it shows

The dashboard loops through five pages, each filling the screen:

1. **Now** — large weather icon, current temperature, condition, *feels like*, today's high & low, and current wind.
2. **Next 24 hours** — a strip of 12 forecast cards (every two hours) with icon, temperature and precipitation probability.
3. **7-day forecast** — daily high / low temperature bars, weather icon, condition label and precipitation probability.
4. **Conditions** — humidity, UV index, pressure, visibility, cloud cover, precipitation, wind speed + direction, dew point.
5. **Sun & sky** — sunrise, sunset, day length, daylight remaining, UV at noon, and a live arc that tracks the sun's position across the sky.

The atmospheric backdrop adapts to the actual conditions: clear day with a sunny sky, clear night with a starfield, drifting clouds, animated rain or snow, fog haze, or stormy darkness for thunderstorms. A small QR code in the corner links to the **weather-c** companion app.

## How it talks to the controller

This is a classic RCWeb asymmetric viewer. The viewer owns all state — the active location, options (units, page list, page duration), the loaded data, and the current page index. It exposes a small public API on `window.weather`:

```text
weather.setLocation({ name, country, latitude, longitude, timezone })
weather.setOptions({ tempUnit, windUnit, precipUnit, pageMs, pages })
weather.next()
weather.prev()
weather.goto(pageId | index)
weather.refresh()
weather.randomize()
weather.requestState(clientId)
```

Whenever the active page changes, the location changes, or fresh data arrives, the viewer pushes a snapshot to every `weather-c` client in the room with `rc.sendFunctionCall("weather-c", "weatherControl.receiveState", snapshot)`. Newly joining controllers also call `weather.requestState(rc.client)` to ask for a fresh snapshot addressed back to them.

## Random location

If no location has been configured, the viewer picks one of about twenty geographically diverse cities at random on first load (Tokyo, Reykjavik, Sydney, Cape Town, Cairo, Honolulu, Marrakesh, Helsinki, ...). The controller's *Surprise me* button can request a fresh random pick at any time.

## Browser support

Written in ES5 with `XMLHttpRequest`, vendor-prefixed CSS animations, plain Flexbox layout, no CSS Grid and no CSS custom properties, so it runs comfortably on older signage browsers as well as modern desktop and mobile browsers.

## URL

`/weather/?r=<room>`
