|
| 1 | +# UK-AIR Publisher Completion Report - 2026-05-26 |
| 2 | + |
| 3 | +## Summary |
| 4 | + |
| 5 | +Implemented the first-pass UK-AIR publisher package for OSHConnect-Python and bootstrapped it into the live OSH SensorHub backend used by the CSAPI Explorer `OSH (OS4CSAPI)` preset. |
| 6 | + |
| 7 | +The new publisher models three curated UK-AIR monitoring sites and four pollutant timeseries: |
| 8 | + |
| 9 | +| Site | Pollutant | UK-AIR timeseries | Datastream | |
| 10 | +| --- | --- | ---: | --- | |
| 11 | +| Camden Kerbside | NO2 | 3 | `ukAirNO2` | |
| 12 | +| Auchencorth Moss | O3 | 24 | `ukAirO3` | |
| 13 | +| Toft Newton | PM10 | 5125 | `ukAirPM10` | |
| 14 | +| Toft Newton | PM2.5 | 5130 | `ukAirPM25` | |
| 15 | + |
| 16 | +## Files Added |
| 17 | + |
| 18 | +- `publishers/uk_air/__init__.py` |
| 19 | +- `publishers/uk_air/stations.json` |
| 20 | +- `publishers/uk_air/README.md` |
| 21 | +- `publishers/uk_air/bootstrap_uk_air.py` |
| 22 | +- `publishers/uk_air/uk_air_publisher.py` |
| 23 | + |
| 24 | +## Files Updated |
| 25 | + |
| 26 | +- `publishers/README.md` |
| 27 | + - Added UK-AIR to the publisher fleet table. |
| 28 | + - Added the UK-AIR bootstrap command. |
| 29 | + - Added source/API notes for the UK-AIR SOS / 52 North Timeseries REST API. |
| 30 | + |
| 31 | +## Implementation Notes |
| 32 | + |
| 33 | +- Source API: `https://uk-air.defra.gov.uk/sos-ukair/api/v1/` |
| 34 | +- Timeseries list endpoint: `https://uk-air.defra.gov.uk/sos-ukair/api/v1/timeseries` |
| 35 | +- Recent data endpoint pattern: `timeseries/{id}/getData?timespan=PT72H/{utcEnd}` |
| 36 | +- UK-AIR exposes point coordinates as `[lat, lon, alt]`; `stations.json` preserves normalized `lat` and `lon`, and the bootstrap writes standard GeoJSON ordering as `[lon, lat]`. |
| 37 | +- UK-AIR timestamps are millisecond Unix epoch values; the runtime normalizes them to CSAPI UTC phenomenon times. |
| 38 | +- UK-AIR source units are exposed as `ug.m-3`; the CSAPI observation payload uses display text `ug/m3` while preserving pollutant-specific result fields such as `no2_ugm3` and `pm25_ugm3`. |
| 39 | +- Runtime filtering ignores missing, `NaN`, and sentinel `<= -99` values. |
| 40 | + |
| 41 | +## Live Bootstrap Result |
| 42 | + |
| 43 | +Command: |
| 44 | + |
| 45 | +```powershell |
| 46 | +py -m publishers.uk_air.bootstrap_uk_air |
| 47 | +``` |
| 48 | + |
| 49 | +Result: |
| 50 | + |
| 51 | +- Created procedure `urn:os4csapi:procedure:uk-air:v1` with server id `04dg`. |
| 52 | +- Created systems: |
| 53 | + - `urn:os4csapi:system:uk-air:camden-kerbside:v1` -> `05lg` |
| 54 | + - `urn:os4csapi:system:uk-air:auchencorth-moss:v1` -> `05m0` |
| 55 | + - `urn:os4csapi:system:uk-air:toft-newton:v1` -> `05mg` |
| 56 | +- Created datastreams: |
| 57 | + - `ukAirNO2` -> `05kg` |
| 58 | + - `ukAirO3` -> `05l0` |
| 59 | + - `ukAirPM10` -> `05lg` |
| 60 | + - `ukAirPM25` -> `05m0` |
| 61 | +- Created deployments: |
| 62 | + - `urn:os4csapi:deployment:uk-air-demo:v1` -> `05g0` |
| 63 | + - `urn:os4csapi:deployment:uk-air-stations:v1` -> `05gg` |
| 64 | + - `urn:os4csapi:deployment:uk-air-camden-kerbside:v1` -> `05h0` |
| 65 | + - `urn:os4csapi:deployment:uk-air-auchencorth-moss:v1` -> `05hg` |
| 66 | + - `urn:os4csapi:deployment:uk-air-toft-newton:v1` -> `05i0` |
| 67 | + |
| 68 | +The bootstrap helper stripped unsupported datastream `documentation` and `uid` fields before POST. This matches current server behavior and kept the operational datastream creation path clean. |
| 69 | + |
| 70 | +## Live Publish Result |
| 71 | + |
| 72 | +Initial live publish found that the server-accepted datastream schema did not include the runtime `timestamp` field in the observation result. The runtime payload was adjusted so `stationId` is the first result field, matching the schema accepted by OSH. |
| 73 | + |
| 74 | +Command after the adjustment: |
| 75 | + |
| 76 | +```powershell |
| 77 | +py -m publishers.uk_air.uk_air_publisher --once |
| 78 | +``` |
| 79 | + |
| 80 | +Result: |
| 81 | + |
| 82 | +- Published: 4 |
| 83 | +- Skipped: 0 |
| 84 | +- Errors: 0 |
| 85 | + |
| 86 | +Published readings: |
| 87 | + |
| 88 | +| Site / stream | Phenomenon time | Value | |
| 89 | +| --- | --- | --- | |
| 90 | +| Camden Kerbside `ukAirNO2` | `2026-05-26T09:00:00Z` | `NO2=27.731 ug/m3` | |
| 91 | +| Auchencorth Moss `ukAirO3` | `2026-05-26T09:00:00Z` | `O3=67.854 ug/m3` | |
| 92 | +| Toft Newton `ukAirPM10` | `2026-05-26T09:00:00Z` | `PM10=45.1 ug/m3` | |
| 93 | +| Toft Newton `ukAirPM25` | `2026-05-26T09:00:00Z` | `PM2.5=18.396 ug/m3` | |
| 94 | + |
| 95 | +## Server Read-Back Verification |
| 96 | + |
| 97 | +Latest-observation read-back from live OSH confirmed the stored results: |
| 98 | + |
| 99 | +| Datastream id | Result field | Value | Phenomenon time | |
| 100 | +| --- | --- | ---: | --- | |
| 101 | +| `05kg` | `no2_ugm3` | `27.731` | `2026-05-26T09:00:00Z` | |
| 102 | +| `05l0` | `o3_ugm3` | `67.854` | `2026-05-26T09:00:00Z` | |
| 103 | +| `05lg` | `pm10_ugm3` | `45.1` | `2026-05-26T09:00:00Z` | |
| 104 | +| `05m0` | `pm25_ugm3` | `18.396` | `2026-05-26T09:00:00Z` | |
| 105 | + |
| 106 | +## Explorer-Facing Visibility Check |
| 107 | + |
| 108 | +The Explorer-facing OSH endpoint at `https://129-80-248-53.sslip.io/sensorhub/api` returned the new UK-AIR resources by UID. |
| 109 | + |
| 110 | +Verified examples: |
| 111 | + |
| 112 | +- `systems?uid=urn:os4csapi:system:uk-air:camden-kerbside:v1&limit=1000` returned system id `05lg`. |
| 113 | +- `deployments?uid=urn:os4csapi:deployment:uk-air-demo:v1&limit=1000` returned one item. |
| 114 | +- `deployments?uid=urn:os4csapi:deployment:uk-air-stations:v1&limit=1000` returned one item. |
| 115 | + |
| 116 | +## Validation Commands |
| 117 | + |
| 118 | +```powershell |
| 119 | +py -m py_compile publishers\uk_air\bootstrap_uk_air.py publishers\uk_air\uk_air_publisher.py |
| 120 | +py -m publishers.uk_air.uk_air_publisher --dry-run --once |
| 121 | +py -m publishers.uk_air.bootstrap_uk_air --dry-run |
| 122 | +py -m publishers.uk_air.bootstrap_uk_air |
| 123 | +py -m publishers.uk_air.uk_air_publisher --once |
| 124 | +``` |
| 125 | + |
| 126 | +All final validation commands completed successfully. |
| 127 | + |
| 128 | +## Follow-Up Items |
| 129 | + |
| 130 | +1. Open the production Explorer map with the `OSH (OS4CSAPI)` preset and visually confirm marker styling, side-card labels, and popup latest-reading display for UK-AIR deployments. |
| 131 | +2. If the marker falls back to a blank/generic NATO symbol, add a targeted UK-AIR / air-quality keyword mapping in the Explorer symbol mapper. |
| 132 | +3. Consider adding a representative monitoring-station image/fallback after the visual pass, following the Environment Agency Hydrology pattern. |
| 133 | +4. Consider expanding the curated sidecar after demo validation, especially for additional urban NO2/PM sites and rural background stations. |
0 commit comments