feat(train): workouts' weather from Open-Meteo, through the instance (ADR 0036)

A workout with a track gets the weather over it as its page opens, once
while it has none: the hours from the one it started in to the one it
ended in, kept in its sealed payload (temperature, feels-like, humidity,
precipitation, the WMO code, the wind, its gusts and direction) and shown
under its totals with the link to Open-Meteo its licence asks for.

Train's server asks Open-Meteo in the person's place (the `weather`
endpoint), so Open-Meteo never sees their address: the place rounded to
two decimals (also on the phone), a span of at most 48 hours, the
forecast API for recent spans and the archive for older ones, for people
signed in, at most 30 requests a person a minute, nothing kept or
logged. On by default; `WEATHER=off` switches it off, and
`OPEN_METEO_API_KEY` moves it to the paid hosts for an instance used
commercially.

Health Connect's fingerprint leaves the weather out, so keeping it
writes nothing again. No table and no migration.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-11-02 13:59:41 +01:00
commit 3f7b409e80
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64
3 changed files with 2503 additions and 7 deletions

View file

@ -59,6 +59,11 @@ DOMAIN=http://localhost
# The Loop's firmware through the instance (Train's ADR 0030, D40): `off` to stop
# relaying it; empty: on.
#LOOP_FIRMWARE_RELAY=
# Workouts' weather from Open-Meteo (Train's ADR 0036): `off` to stop asking; empty: on,
# on Open-Meteo's free API, which is for non-commercial use alone. An instance with ads
# or subscriptions needs a paid plan: its key.
#WEATHER=
#OPEN_METEO_API_KEY=
# Train's map (ADR 0030, D22): a MapLibre style over HTTPS, with its name, credit and
# page; empty: OpenFreeMap's.
#MAP_STYLE_URL=

View file

@ -39,6 +39,10 @@ services:
BROUTER_URL: http://brouter:17777/
# The Loop's firmware through the instance (D40): on unless `off`.
LOOP_FIRMWARE_RELAY: ${LOOP_FIRMWARE_RELAY:-}
# Workouts' weather from Open-Meteo (ADR 0036): on unless `off`; a key
# for its paid hosts where the instance is used commercially.
WEATHER: ${WEATHER:-}
OPEN_METEO_API_KEY: ${OPEN_METEO_API_KEY:-}
# The map source (D22); empty: OpenFreeMap.
MAP_STYLE_URL: ${MAP_STYLE_URL:-}
MAP_SOURCE_NAME: ${MAP_SOURCE_NAME:-}

View file

@ -378,6 +378,11 @@ Steps, in order; ✱ marks a step as root.
7. **Check it**: `https://train.halkyon.eu/` answers; in Train, signed in with a Learn
account, a route plans between two points of the region.
Workouts' weather (Halkyon Train's ADR 0036) comes from Open-Meteo through Train's
server, on by default, the free API from the server's address (non-commercial use alone,
10,000 requests a day). `WEATHER=off` in `deploy/.env` stops it; an instance with ads or
subscriptions needs one of Open-Meteo's paid plans, its key in `OPEN_METEO_API_KEY`.
## Train's map