Skip to content

Commit 9be220a

Browse files
committed
Add Finland publisher expansion plan
1 parent 9c46892 commit 9be220a

1 file changed

Lines changed: 363 additions & 0 deletions

File tree

Lines changed: 363 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,363 @@
1+
# Finland Publisher Expansion Plan
2+
3+
Date: 2026-05-29
4+
Status: Planning
5+
Repository: OSHConnect-Python
6+
7+
## Purpose
8+
9+
This folder tracks the planned Finland-origin data-source expansion for the OS4CSAPI publisher fleet. The goal is to add Finnish public-data publishers that match the quality and operational shape of the existing fleet while preserving the proven CSAPI pattern:
10+
11+
- idempotent bootstrap scripts,
12+
- stable source-derived UIDs,
13+
- curated sidecar station/source config,
14+
- source-native identifiers and URLs preserved in observation results,
15+
- dry-run, once, interval, and subset CLI support,
16+
- completion reports and live smoke evidence before production use.
17+
18+
## Current Publisher Baseline
19+
20+
The existing publisher fleet reviewed for this activity includes:
21+
22+
| Publisher | Source family | Pattern to reuse |
23+
| --- | --- | --- |
24+
| `iss` | CelesTrak TLE / SGP4 | Moving-platform position publisher |
25+
| `nws` | NOAA weather stations | Fixed station weather observations |
26+
| `aviation_wx` | AviationWeather METAR | Airport weather observations |
27+
| `ndbc` | NOAA buoys and BuoyCAM | Marine station observations and imagery |
28+
| `coops` | NOAA tides and currents | Coastal water-level station observations |
29+
| `opensky` | ADS-B aircraft states | Moving-object feed adapter |
30+
| `usgs_water` | USGS water monitoring | Hydrology station observations |
31+
| `usgs_nims` | USGS station imagery | Image-reference observations on existing systems |
32+
| `usgs_eq` | USGS earthquake feed | Event-feed publisher |
33+
| `environment_agency_hydrology` | UK hydrology | Curated latest readings by measure |
34+
| `uk_air` | UK air quality | Fixed air-quality station observations |
35+
| `bgs_sensorthings` | UKGEOS SensorThings telemetry | Curated geoscience telemetry |
36+
| `met_office_datahub` | UK land observations | Access-gated weather observations |
37+
| `met_office_global_spot` | UK point forecasts | Access-gated forecast observations |
38+
39+
The Finland expansion should live in the same `publishers/` package model, with each new source receiving a bootstrap module, runtime publisher module, README, sidecar config, tests where practical, and a completion report under this folder.
40+
41+
## Source Research Summary
42+
43+
### Finnish Meteorological Institute Open Data
44+
45+
Primary URL: `https://en.ilmatieteenlaitos.fi/open-data`
46+
Machine endpoint: `https://opendata.fmi.fi/wfs?request=GetCapabilities`
47+
48+
Relevant datasets:
49+
50+
- weather station observations,
51+
- point weather forecasts,
52+
- air quality observations,
53+
- road weather observations,
54+
- sea and ocean observations,
55+
- wave buoys and mareographs,
56+
- aviation weather reports with FMI's published disclaimer.
57+
58+
Verified during research:
59+
60+
- WFS capabilities endpoint returned XML successfully.
61+
- Helsinki weather observation stored-query sample returned a WFS feature collection.
62+
- Helsinki air-quality stored-query sample returned a WFS feature collection.
63+
64+
Implementation fit:
65+
66+
- Best analogs: `nws`, `uk_air`, `met_office_datahub`, `met_office_global_spot`, `ndbc`, `coops`.
67+
- Main technical issue: parse WFS XML/GML or use an existing FMI Open Data client library, then normalize to CSAPI observations.
68+
- Recommended first scope: one weather-observation publisher and one air-quality publisher, sharing a small FMI WFS helper.
69+
70+
### Fintraffic Digitraffic Road
71+
72+
Primary URL: `https://www.digitraffic.fi/en/road-traffic/`
73+
Swagger: `https://tie.digitraffic.fi/swagger/`
74+
75+
Relevant APIs:
76+
77+
- road weather stations: `/api/weather/v1/stations`, `/api/weather/v1/stations/data`, station history endpoints,
78+
- weather cameras: `/api/weathercam/v1/stations`, `/api/weathercam/v1/stations/data`, image URLs under `weathercam.digitraffic.fi`,
79+
- traffic measurement system stations: `/api/tms/v1/stations`, `/api/tms/v1/stations/data`,
80+
- traffic messages and roadworks,
81+
- variable signs,
82+
- road maintenance vehicle latest locations,
83+
- walking and cycling counters.
84+
85+
Verified during research:
86+
87+
- road weather station metadata returned live GeoJSON,
88+
- road weather latest data returned live JSON,
89+
- weather camera metadata returned live GeoJSON,
90+
- TMS station metadata returned live GeoJSON.
91+
92+
Implementation fit:
93+
94+
- Best analogs: `nws`, `ndbc_buoycam`, `opensky`, `environment_agency_hydrology`.
95+
- Best first Finland publisher because it offers high visual value, no credentials, station geometry, frequent updates, and camera imagery.
96+
- Recommended first scope: curated road weather station observations plus a separate road weather camera image-reference publisher.
97+
98+
### Fintraffic Digitraffic Marine
99+
100+
Primary URL: `https://www.digitraffic.fi/en/marine-traffic/`
101+
Swagger: `https://meri.digitraffic.fi/swagger/`
102+
103+
Relevant APIs:
104+
105+
- AIS vessel locations: `/api/ais/v1/locations`,
106+
- AIS vessel metadata: `/api/ais/v1/vessels`,
107+
- port calls,
108+
- winter navigation,
109+
- sea state estimation from smart AtoN sites,
110+
- AtoN faults,
111+
- MQTT-over-WebSocket vessel and sea-state streams.
112+
113+
Verified during research:
114+
115+
- AIS latest locations returned a live GeoJSON feature collection.
116+
117+
Implementation fit:
118+
119+
- Best analogs: `opensky`, `ndbc`, `coops`.
120+
- Good moving-object demo source that originates from Finland's traffic data infrastructure.
121+
- Recommended first scope: feed-adapter system publishing latest AIS vessel observations for a bounded Finland area or curated vessel subset.
122+
123+
### Fintraffic Digitraffic Railway
124+
125+
Primary URL: `https://www.digitraffic.fi/en/railway-traffic/`
126+
GraphQL: `https://rata.digitraffic.fi/api/v2/graphql`
127+
GTFS-RT locations: `https://rata.digitraffic.fi/api/v1/trains/gtfs-rt-locations`
128+
129+
Relevant APIs:
130+
131+
- currently running trains with latest locations,
132+
- timetables, delays, compositions,
133+
- GTFS and GTFS-RT feeds,
134+
- passenger information messages.
135+
136+
Verified during research:
137+
138+
- GTFS-RT location endpoint returned protobuf successfully.
139+
- Documentation includes GraphQL examples for latest train locations.
140+
141+
Implementation fit:
142+
143+
- Best analogs: `opensky` and `iss`, with richer operational metadata.
144+
- Recommended first scope: GraphQL JSON publisher for currently running trains before adding protobuf GTFS-RT parsing.
145+
146+
### SYKE / Vesi.fi Hydrology
147+
148+
Primary URL: `https://www.vesi.fi/en/`
149+
150+
Relevant domains:
151+
152+
- water level,
153+
- discharge and general water situation,
154+
- flood status,
155+
- snow, ice, soil frost,
156+
- groundwater,
157+
- citizen observations.
158+
159+
Verified during research:
160+
161+
- public site presents current water situation products and identifies SYKE, FMI, Flood Centre, and related Finnish agencies as producers.
162+
163+
Implementation fit:
164+
165+
- Best analogs: `environment_agency_hydrology`, `usgs_water`, `bgs_sensorthings`.
166+
- Requires an additional API reconnaissance pass before coding because the clean machine endpoint is less obvious than FMI or Digitraffic.
167+
168+
## Recommended Implementation Order
169+
170+
### Phase 0: Reconnaissance Hardening
171+
172+
Deliverables:
173+
174+
- `docs/research/finland-publisher-expansion/Finland_Source_Endpoint_Probe_2026-05-29.md`
175+
- endpoint probe scripts or notes for FMI WFS, Digitraffic Road, Digitraffic Marine, Digitraffic Rail, and SYKE/Vesi.fi,
176+
- source licensing and attribution notes,
177+
- selected demo regions and station/source subsets.
178+
179+
Exit criteria:
180+
181+
- each Phase 1 candidate has at least one live, no-secret endpoint probe,
182+
- source timestamps, geometry fields, and source IDs are documented,
183+
- any rate limits or attribution requirements are captured.
184+
185+
### Phase 1: Digitraffic Road Weather
186+
187+
Package target: `publishers/digitraffic_road_weather/`
188+
189+
Scope:
190+
191+
- curated set of 5 to 8 Finnish road weather stations,
192+
- one CSAPI system per road weather station,
193+
- one datastream per station for latest road-weather sensor values,
194+
- preserve station ID, sensor IDs, sensor names, units, source update time, and source URL.
195+
196+
Bootstrap resources:
197+
198+
- procedure UID: `urn:os4csapi:procedure:digitraffic-road-weather:v1`,
199+
- deployment UID: `urn:os4csapi:deployment:digitraffic-road-weather-demo:v1`,
200+
- system UID pattern: `urn:os4csapi:system:digitraffic-road-weather:{stationId}:v1`,
201+
- datastream output name: `roadWeatherObs`.
202+
203+
Runtime source endpoints:
204+
205+
- station metadata: `https://tie.digitraffic.fi/api/weather/v1/stations`,
206+
- latest readings: `https://tie.digitraffic.fi/api/weather/v1/stations/{id}/data` or all-stations latest data.
207+
208+
Acceptance criteria:
209+
210+
- dry-run prints current observations for every curated station,
211+
- bootstrap is idempotent against OSH,
212+
- live publisher posts one observation per station per cycle with 0 errors,
213+
- Explorer map cards show current latest readings and road-weather role classification.
214+
215+
### Phase 2: Digitraffic Road Weather Cameras
216+
217+
Package target: `publishers/digitraffic_weathercam/`
218+
219+
Scope:
220+
221+
- curated set of camera presets associated with Phase 1 stations where possible,
222+
- image-reference observations using Digitraffic image URLs,
223+
- optional thumbnail support via `thumbnail=true`.
224+
225+
Bootstrap resources:
226+
227+
- procedure UID: `urn:os4csapi:procedure:digitraffic-weathercam:v1`,
228+
- datastream output name: `digitrafficWeatherCamImage`.
229+
230+
Runtime source endpoints:
231+
232+
- camera metadata: `https://tie.digitraffic.fi/api/weathercam/v1/stations`,
233+
- camera latest data: `https://tie.digitraffic.fi/api/weathercam/v1/stations/{id}/data`,
234+
- image URL pattern: `https://weathercam.digitraffic.fi/{presetId}.jpg`.
235+
236+
Acceptance criteria:
237+
238+
- cards display live or recent camera imagery,
239+
- image timestamps and preset IDs are preserved,
240+
- no local image cache is required unless direct image hotlinking becomes unreliable.
241+
242+
### Phase 3: FMI Weather And Air Quality
243+
244+
Package targets:
245+
246+
- `publishers/fmi_weather/`,
247+
- `publishers/fmi_air_quality/`,
248+
- optional shared helper: `publishers/fmi_common.py` or package-local utility module.
249+
250+
Scope:
251+
252+
- start with Helsinki plus 3 to 5 additional Finnish cities/stations,
253+
- weather parameters such as temperature, humidity, wind speed/direction, pressure, precipitation,
254+
- air-quality parameters such as NO2, O3, PM10, PM2.5 where available.
255+
256+
Runtime source endpoint:
257+
258+
- `https://opendata.fmi.fi/wfs`
259+
260+
Likely stored queries:
261+
262+
- `fmi::observations::weather::simple`,
263+
- `fmi::observations::airquality::hourly::simple`,
264+
- forecast stored queries after observation publishers are stable.
265+
266+
Implementation choice:
267+
268+
- Prefer a small, well-tested XML/GML parser if the simple stored-query output is stable.
269+
- Consider the `fmiopendata` Python library only if it materially reduces parser risk without adding awkward packaging constraints.
270+
271+
Acceptance criteria:
272+
273+
- weather and air-quality observations publish with current phenomenon times,
274+
- station/source metadata and FMI attribution are preserved,
275+
- Explorer cards classify FMI weather and air-quality sites distinctly from UK/NOAA sources.
276+
277+
### Phase 4: Digitraffic Marine AIS
278+
279+
Package target: `publishers/digitraffic_marine_ais/`
280+
281+
Scope:
282+
283+
- feed-adapter system for live vessel observations,
284+
- optional curated bounding box around Helsinki/Gulf of Finland or Archipelago Sea,
285+
- publish latest AIS state vectors with MMSI, course, speed, heading, navigation status, and source timestamps.
286+
287+
Runtime source endpoints:
288+
289+
- latest locations: `https://meri.digitraffic.fi/api/ais/v1/locations`,
290+
- vessel metadata: `https://meri.digitraffic.fi/api/ais/v1/vessels`.
291+
292+
Acceptance criteria:
293+
294+
- live vessel icons appear on Explorer map without overwhelming feature count,
295+
- source MMSI and vessel metadata are preserved,
296+
- stale vessel positions are filtered or marked explicitly.
297+
298+
### Phase 5: Digitraffic Railway Live Trains
299+
300+
Package target: `publishers/digitraffic_rail_trains/`
301+
302+
Scope:
303+
304+
- currently running trains via GraphQL,
305+
- publish latest train positions with train number, operator, speed, timestamp, and route context,
306+
- later extension to GTFS-RT if useful.
307+
308+
Runtime source endpoints:
309+
310+
- GraphQL: `https://rata.digitraffic.fi/api/v2/graphql`,
311+
- optional GTFS-RT: `https://rata.digitraffic.fi/api/v1/trains/gtfs-rt-locations`.
312+
313+
Acceptance criteria:
314+
315+
- current train locations are published with source timestamps,
316+
- first implementation avoids protobuf unless GraphQL proves insufficient,
317+
- map styling distinguishes trains from aircraft and vessels.
318+
319+
### Phase 6: SYKE / Vesi.fi Hydrology
320+
321+
Package target: to be named after the confirmed API surface.
322+
323+
Scope:
324+
325+
- identify stable API endpoints for water level, discharge, groundwater, snow, ice, or flood observations,
326+
- curate a small national demo set,
327+
- reuse `environment_agency_hydrology` and `usgs_water` patterns.
328+
329+
Acceptance criteria before implementation:
330+
331+
- direct machine endpoint is identified,
332+
- license/attribution is clear,
333+
- latest observation timestamps and station geometry can be retrieved without scraping a user-facing map page.
334+
335+
## Shared Engineering Tasks
336+
337+
1. Add a Finland source classification layer in Explorer only after the first publisher is live.
338+
2. Keep publisher code independent of Explorer UI changes.
339+
3. Reuse current bootstrap helper patterns and stable UID conventions.
340+
4. Add representative thumbnails only when source media is absent and attribution is clean.
341+
5. Add completion reports after each publisher reaches live smoke status.
342+
6. Update `publishers/README.md` and Docker Compose/systemd deployment notes after each accepted source.
343+
344+
## Risks And Controls
345+
346+
| Risk | Control |
347+
| --- | --- |
348+
| FMI WFS XML/GML parsing complexity | Start with simple stored queries and fixture tests; isolate parser in a helper. |
349+
| Digitraffic all-stations feeds are large | Curate station IDs first; use station-specific endpoints or filter client-side with care. |
350+
| Moving-object feeds overwhelm Explorer | Start with bounding boxes, sample caps, and stale filtering. |
351+
| Source labels and units are Finnish/domain-specific | Preserve source names and units; add normalized display labels separately. |
352+
| SYKE API surface unclear | Do not implement until a stable machine endpoint is verified. |
353+
| Demo regressions in existing publishers | Keep Finland packages additive; avoid modifying shared base behavior unless covered by tests. |
354+
355+
## Immediate Next Steps
356+
357+
1. Create `Finland_Source_Endpoint_Probe_2026-05-29.md` with concrete probe results and selected station candidates.
358+
2. Implement `publishers/digitraffic_road_weather/stations.json` with 5 to 8 curated stations.
359+
3. Build `bootstrap_digitraffic_road_weather.py` using existing idempotent bootstrap helpers.
360+
4. Build `digitraffic_road_weather_publisher.py` with `--dry-run`, `--once`, `--interval`, and `--stations`.
361+
5. Run local dry-run and fixture tests.
362+
6. Bootstrap to the target CSAPI server only after dry-run source freshness is verified.
363+
7. Smoke test in Explorer and document the result in this folder.

0 commit comments

Comments
 (0)