|
| 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