Skip to content

Commit 3aaa637

Browse files
committed
Add Met Office Global Spot forecast publisher
1 parent 7115da5 commit 3aaa637

10 files changed

Lines changed: 1366 additions & 1 deletion

publishers/.env.example

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,19 @@ OSH_ROOT=sensorhub
3030
# Optional override if Met Office changes/publishes a different gateway URL.
3131
# MET_OFFICE_LAND_OBSERVATIONS_BASE_URL=https://data.hub.api.metoffice.gov.uk/observation-land/1
3232

33+
# Met Office Weather DataHub Global Spot / Site-Specific Forecast API key.
34+
# Required for publishers.met_office_global_spot.
35+
# MET_OFFICE_GLOBAL_SPOT_API_KEY=
36+
37+
# Optional alternative for systemd/Oracle deployments: point to a root-owned
38+
# file containing either the raw key or MET_OFFICE_GLOBAL_SPOT_API_KEY=...
39+
# MET_OFFICE_GLOBAL_SPOT_API_KEY_FILE=/etc/os4csapi/secrets/met-office-global-spot.key
40+
41+
# Optional overrides for the access-gated Site-Specific Forecast endpoint.
42+
# MET_OFFICE_GLOBAL_SPOT_BASE_URL=https://data.hub.api.metoffice.gov.uk/sitespecific/v0
43+
# MET_OFFICE_GLOBAL_SPOT_HOURLY_PATH=/point/hourly
44+
# MET_OFFICE_GLOBAL_SPOT_FORECAST_HOURS=24
45+
3346
# Optional API-key header name. Default is apikey.
3447
# MET_OFFICE_DATAHUB_API_KEY_HEADER=apikey
3548

publishers/README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ server (e.g. [OpenSensorHub](https://opensensorhub.org/)).
2121
| **Environment Agency Hydrology** | EA river level, flow, rainfall, groundwater | 15 min |
2222
| **UK-AIR** | Defra UK-AIR NO2, O3, PM10, PM2.5 | 1 h |
2323
| **BGS SensorThings** | BGS UKGEOS Glasgow groundwater/geothermal telemetry | 15 min |
24-
| **Met Office DataHub** | Land Observations hourly weather data | Access-gated / planned |
24+
| **Met Office DataHub** | Land Observations hourly weather data | Access-gated / 1 h |
25+
| **Met Office Global Spot** | Site-specific deterministic hourly forecasts | Access-gated / 1 h |
2526

2627
## Quick Start
2728

@@ -62,6 +63,8 @@ python -m publishers.uk_air.bootstrap_uk_air
6263
python -m publishers.bgs_sensorthings.bootstrap_bgs_sensorthings
6364
# Met Office DataHub is access-gated; see publishers/met_office_datahub/README.md
6465
python -m publishers.met_office_datahub.bootstrap_met_office_datahub
66+
# Met Office Global Spot is access-gated; see publishers/met_office_global_spot/README.md
67+
python -m publishers.met_office_global_spot.bootstrap_met_office_global_spot
6568
python -m publishers.iss.bootstrap_iss
6669
```
6770

@@ -72,6 +75,7 @@ cd publishers
7275
docker compose up -d # start all
7376
docker compose up -d nws # start one
7477
docker compose --profile access-gated up -d met-office-datahub
78+
docker compose --profile access-gated up -d met-office-global-spot
7579
docker compose logs -f nws # follow logs
7680
docker compose ps # status
7781
docker compose down # stop all
@@ -121,6 +125,8 @@ python -m publishers.nws.nws_publisher --interval 3600
121125
| `USGS_API_KEY` | No | USGS API key for higher rate limits |
122126
| `MET_OFFICE_LAND_OBSERVATIONS_API_KEY` | For Met Office | Met Office Weather DataHub Land Observations subscription key |
123127
| `MET_OFFICE_LAND_OBSERVATIONS_API_KEY_FILE` | For Met Office | Host-local file containing the Land Observations key; useful for Oracle/systemd secrets |
128+
| `MET_OFFICE_GLOBAL_SPOT_API_KEY` | For Met Office Global Spot | Met Office Weather DataHub Site-Specific Forecast / Global Spot subscription key |
129+
| `MET_OFFICE_GLOBAL_SPOT_API_KEY_FILE` | For Met Office Global Spot | Host-local file containing the Global Spot key; useful for Oracle/systemd secrets |
124130
| `BUOYCAM_CACHE_ROOT` | No | Local directory for BuoyCAM image cache |
125131
| `BUOYCAM_CACHE_BASE_URL` | No | Public URL serving the cached images |
126132

@@ -143,4 +149,10 @@ python -m publishers.nws.nws_publisher --interval 3600
143149
caches nearest geohash lookups in ignored runtime state to stay within the
144150
free-plan call budget. In Docker Compose it is behind the `access-gated`
145151
profile, so public publishers can still start without a Met Office key.
152+
- **Met Office Global Spot** uses the access-gated Site-Specific Forecast API
153+
and reads `MET_OFFICE_GLOBAL_SPOT_API_KEY` from the environment, or
154+
`MET_OFFICE_GLOBAL_SPOT_API_KEY_FILE` from a host-local secret file. It
155+
publishes deterministic hourly forecast values for virtual forecast points,
156+
not physical sensor observations, and is also behind the `access-gated`
157+
Docker Compose profile.
146158
- All publishers use `--interval <seconds>` and `--dry-run` CLI flags.

publishers/docker-compose.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,24 @@ services:
131131
MET_OFFICE_DATAHUB_429_BACKOFF: ${MET_OFFICE_DATAHUB_429_BACKOFF:-3600}
132132
command: ["--interval", "3600"]
133133

134+
# ── Met Office Weather DataHub Global Spot Forecast (1h cadence) ──
135+
met-office-global-spot:
136+
profiles: ["access-gated"]
137+
build:
138+
context: ..
139+
dockerfile: publishers/met_office_global_spot/Dockerfile
140+
restart: always
141+
environment:
142+
<<: *osh-env
143+
MET_OFFICE_GLOBAL_SPOT_API_KEY: ${MET_OFFICE_GLOBAL_SPOT_API_KEY:-}
144+
MET_OFFICE_GLOBAL_SPOT_BASE_URL: ${MET_OFFICE_GLOBAL_SPOT_BASE_URL:-https://data.hub.api.metoffice.gov.uk/sitespecific/v0}
145+
MET_OFFICE_GLOBAL_SPOT_HOURLY_PATH: ${MET_OFFICE_GLOBAL_SPOT_HOURLY_PATH:-/point/hourly}
146+
MET_OFFICE_GLOBAL_SPOT_FORECAST_HOURS: ${MET_OFFICE_GLOBAL_SPOT_FORECAST_HOURS:-24}
147+
MET_OFFICE_DATAHUB_API_KEY_HEADER: ${MET_OFFICE_DATAHUB_API_KEY_HEADER:-apikey}
148+
MET_OFFICE_GLOBAL_SPOT_REQUEST_DELAY: ${MET_OFFICE_GLOBAL_SPOT_REQUEST_DELAY:-1.0}
149+
MET_OFFICE_GLOBAL_SPOT_429_BACKOFF: ${MET_OFFICE_GLOBAL_SPOT_429_BACKOFF:-3600}
150+
command: ["--interval", "3600"]
151+
134152
# ── USGS Earthquake Feed (60s cadence) ──
135153
usgs-eq:
136154
build:
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
FROM python:3.12-slim
2+
3+
WORKDIR /app
4+
5+
COPY publishers /app/publishers
6+
7+
ENV PYTHONUNBUFFERED=1
8+
ENV MET_OFFICE_GLOBAL_SPOT_API_KEY=
9+
ENV MET_OFFICE_GLOBAL_SPOT_API_KEY_FILE=
10+
ENV MET_OFFICE_GLOBAL_SPOT_BASE_URL=https://data.hub.api.metoffice.gov.uk/sitespecific/v0
11+
ENV MET_OFFICE_GLOBAL_SPOT_HOURLY_PATH=/point/hourly
12+
ENV MET_OFFICE_DATAHUB_API_KEY_HEADER=apikey
13+
14+
ENTRYPOINT ["python", "-m", "publishers.met_office_global_spot.met_office_global_spot_publisher"]
15+
CMD ["--interval", "3600"]
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# Met Office Global Spot Forecast Publisher
2+
3+
Status: initial implementation for the access-gated Met Office Weather DataHub Site-Specific Forecast / Global Spot product. Live validation requires a `MET_OFFICE_GLOBAL_SPOT_API_KEY` subscription key.
4+
5+
This publisher is separate from `publishers/met_office_datahub`, which publishes observed Land Observations station telemetry. Global Spot values are deterministic forecasts for configured points, not readings from physical sensors.
6+
7+
## Source
8+
9+
- Weather DataHub landing page: https://datahub.metoffice.gov.uk/
10+
- Site-specific forecast overview: https://datahub.metoffice.gov.uk/docs/g/category/site-specific/overview
11+
- Site-specific pricing: https://datahub.metoffice.gov.uk/pricing/site-specific
12+
- Weather DataHub docs: https://datahub.metoffice.gov.uk/docs
13+
14+
The subscribed product context from planning notes is `/sitespecific/v0`, API name `SiteSpecificForecast`, with a free-plan allowance of 360 calls/day.
15+
16+
## CSAPI Model
17+
18+
- One procedure for Met Office Global Spot hourly forecast retrieval.
19+
- One virtual forecast-point system per curated location.
20+
- One datastream per selected forecast parameter.
21+
- One deployment group for curated Global Spot forecast points.
22+
- Each published observation uses forecast valid time as `phenomenonTime` and preserves issued time, valid time, lead time, parameter, unit, source URL, and forecast type in the result payload.
23+
24+
These resources intentionally avoid claiming the forecast points are physical stations.
25+
26+
## Configuration
27+
28+
Store the API key outside git. In this workspace the preferred local file is `publishers/.env`, which is ignored by git.
29+
30+
```text
31+
MET_OFFICE_GLOBAL_SPOT_API_KEY=...
32+
```
33+
34+
On live hosts, prefer a service environment variable or a root-owned secret file:
35+
36+
```text
37+
MET_OFFICE_GLOBAL_SPOT_API_KEY_FILE=/etc/os4csapi/secrets/met-office-global-spot.key
38+
```
39+
40+
The key file may contain the raw key on the first non-comment line, or one of these assignments:
41+
42+
```text
43+
MET_OFFICE_GLOBAL_SPOT_API_KEY=...
44+
MET_OFFICE_SITE_SPECIFIC_FORECAST_API_KEY=...
45+
MET_OFFICE_DATAHUB_API_KEY=...
46+
```
47+
48+
Optional overrides:
49+
50+
```text
51+
MET_OFFICE_GLOBAL_SPOT_BASE_URL=https://data.hub.api.metoffice.gov.uk/sitespecific/v0
52+
MET_OFFICE_GLOBAL_SPOT_HOURLY_PATH=/point/hourly
53+
MET_OFFICE_GLOBAL_SPOT_FORECAST_HOURS=24
54+
MET_OFFICE_DATAHUB_API_KEY_HEADER=apikey
55+
MET_OFFICE_GLOBAL_SPOT_REQUEST_DELAY=1.0
56+
MET_OFFICE_GLOBAL_SPOT_429_BACKOFF=3600
57+
```
58+
59+
`MET_OFFICE_GLOBAL_SPOT_HOURLY_PATH` may be an absolute URL, a path under the base URL, or a format string containing `{lat}`, `{lon}`, `{latitude}`, and `{longitude}`.
60+
61+
## Commands
62+
63+
Probe the authenticated API and inspect response shape:
64+
65+
```bash
66+
python -m publishers.met_office_global_spot.met_office_global_spot_publisher --probe --locations london-heathrow-area
67+
```
68+
69+
Run a dry publisher cycle without POSTing to OSH:
70+
71+
```bash
72+
python -m publishers.met_office_global_spot.met_office_global_spot_publisher --dry-run --once
73+
```
74+
75+
Bootstrap CSAPI resources:
76+
77+
```bash
78+
python -m publishers.met_office_global_spot.bootstrap_met_office_global_spot
79+
```
80+
81+
Run one live publish cycle:
82+
83+
```bash
84+
python -m publishers.met_office_global_spot.met_office_global_spot_publisher --once
85+
```
86+
87+
## Implementation Notes
88+
89+
The initial curated points mirror the Met Office Land Observations demo geography: London Heathrow, Stornoway, and Cairngorm. At one hourly API request per point per cycle, a one-hour cadence uses 72 calls/day, comfortably below the 360 calls/day free-plan allowance.
90+
91+
The runtime client has a configurable endpoint path because public DataHub pages confirm the Site-Specific Forecast / Global Spot product and `/sitespecific/v0` context, but the exact hourly endpoint path should be validated with the live subscribed API before production service installation.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Met Office Weather DataHub Global Spot forecast publisher package."""

0 commit comments

Comments
 (0)