--- name: weather-data description: Retrieve current Estonian weather observations and forecasts from Environment Agency XML feeds. module: ilm.mjs execution: get --- # Estonian Weather XML ## Vetted module (use this first) `ilm.mjs` ships in https://kodanikukratt.ee/kratt-agent.tar.gz (plain ESM, Node 22+) and is re-verified against the live source: ```js import { show } from "./kratt.mjs"; import { weatherNow, weatherForecast } from "./ilm.mjs"; const now = await weatherNow("Tallinn"); show({ jaam: now.station.name, aeg: now.observedAt, ohutemperatuur: now.airTemperatureC, tuul: now.windSpeedMs, puhang: now.windGustMs, suund: now.windDirectionDeg, nahtus: now.phenomenon, puudub: now.missing, page: now.page, note: now.note, }); ``` - **Every measurement is a named field carrying its unit** — `airTemperatureC`, `windSpeedMs`, `windGustMs`, `windDirectionDeg`, and the rest under `measurements`. A question that asks for two numbers has to get both: print each one you were asked for, with the unit its name gives it. - `weatherNow(place)` resolves a place name to one station: "Tallinn" reaches `Tallinn-Harku`, "Narva" reaches the station called exactly Narva rather than Narva-Jõesuu. Over a third of the feed's 154 stations are hydrological posts with no air temperature and no wind at all, so those are never selected. Pass `{lat, lon}` (from `address-search`) instead of a name to get the nearest station. - **`missing` and `note` are the honest half.** A station that does not measure something is not a zero: `missing` names those fields, and `note` names the nearest station that does measure them. When no station matches the place at all, the call still succeeds — `alsoMatched` is then the complete list of station names, and the right move is a second call, not a guessed number. - `weatherForecast()` returns the national 4-day forecast. Its named points are Harku, Jõhvi, Tartu, Pärnu, Kuressaare and Türi — **there is no point called Tallinn; Tallinn is "Harku"** — and it cannot answer "what is it doing right now". - `weatherStations({measuring})` lists every station with the fields it reported, for finding a name `weatherNow()` will match. - The two URLs you may cite are `source` (the XML feed) and `page` (the public observations or forecast page). There is no third. The endpoints below are the fallback if a module call throws. ## Access Public XML feeds. No authentication. Send a normal user agent if Cloudflare rejects the default client. ## Endpoints - Observations: https://www.ilmateenistus.ee/ilma_andmed/xml/observations.php - English forecast: https://www.ilmateenistus.ee/ilma_andmed/xml/forecast.php?lang=eng - Estonian forecast: https://www.ilmateenistus.ee/ilma_andmed/xml/forecast.php?lang=est ## Retrieve 1. Fetch observations for station measurements or forecasts for daily/night/day outlooks. 2. Parse XML; read the observation root `timestamp` as Unix time. 3. Select stations by `name`, `wmocode`, or coordinates. 4. Preserve missing/empty measurements rather than converting them to zero. ## Return For observations keep station name/code, longitude, latitude, phenomenon, visibility, precipitation, pressure, humidity, temperature, wind direction/speed/gust, water level/temperature, UV, radiation fields, source URL, observation timestamp, and retrieval time. For forecasts keep date plus night/day place, phenomenon, temperature, wind, sea, and text fields present. ## Limits - These feeds describe current observations and near-term forecasts, not a historical archive. - Station fields vary by sensor availability. - Forecast text and place labels depend on `lang`. ## Verify Require HTTP 200 XML. Observations must have root `observations`, a numeric `timestamp`, and at least one `station` with `name`, coordinates, and a measurement field. Forecasts must have root `forecasts` and at least one dated `forecast` containing `night` and `day`. ## Module API weatherNow(place, {lat, lon}) -> {source, page, observedAt, station, airTemperatureC, windSpeedMs, windGustMs, windDirectionDeg, phenomenon, measurements, missing, alsoMatched, note} weatherForecast({lang}) -> {source, page, issuedFor, places, days, note}