150 lines
7.1 KiB
Markdown
150 lines
7.1 KiB
Markdown
# Weather API Integration
|
|
|
|
Weatherreporter fetches normalized weather inputs from a configured Weather API
|
|
base URL. This guide defines the HTTP contract the service must satisfy; it is
|
|
not a general Weather API reference. Configuration values are defined in the
|
|
[configuration reference](../config.md). Normalization and collection behavior
|
|
are documented in [Weather data internals](../internal/weather-data.md) and
|
|
[Collection internals](../internal/collect.md).
|
|
|
|
## Base URL And Requests
|
|
|
|
`weather_api.base_url` must be an absolute HTTP(S) URL. Weatherreporter joins
|
|
each endpoint path to the configured base URL path, so a service hosted under a
|
|
path prefix must keep that prefix available. Requests use `GET` and carry the
|
|
configured timeout on every HTTP attempt.
|
|
|
|
Every request sends `format` and, except where noted below, `units`. The
|
|
configured format must be `json`.
|
|
|
|
Before retrieving sources, Weatherreporter warms up
|
|
`/conditions/current` with the same `format`, `units`, and `precision` query
|
|
parameters used for current conditions. The warmup only requires a readable
|
|
2xx response; its body is not decoded. Failure after its internal retry budget
|
|
stops the fetch before source requests begin.
|
|
|
|
## Endpoints And Query Parameters
|
|
|
|
The adapter makes one source request for each endpoint after a successful
|
|
warmup, subject to retry on transient failures.
|
|
|
|
| Source | Endpoint | Query parameters | Availability |
|
|
| --- | --- | --- | --- |
|
|
| Observations | `/observations` | `format`, `units`, `precision` | Optional |
|
|
| Current conditions | `/conditions/current` | `format`, `units`, `precision` | Optional |
|
|
| Hourly forecast | `/forecast/hourly` | `format`, `units`, `precision`, `tz` | Required |
|
|
| Narrative forecast | `/forecast/narrative` | `format`, `units`, `precision`, `tz` | Optional |
|
|
| Active alerts | `/alerts/active` | `format`, `units` | Optional; `data: null` means checked with no active alerts |
|
|
| Forecast discussion | `/discussion` | `format`, `units`, `tz` | Optional |
|
|
| Weather story | `/weatherstories/latest` | `format` | Optional |
|
|
| SPC convective outlooks | `/outlooks/convective` | `format`, `tz` | Optional; non-null empty lists are checked empty data |
|
|
|
|
`precision` comes from `weather_api.precision`; `tz` comes from
|
|
`weather_api.timezone`. Weatherreporter does not call day-slice forecast or
|
|
discussion-subsection endpoints.
|
|
|
|
## Response Envelope
|
|
|
|
Each endpoint response must be JSON with a top-level `data` member:
|
|
|
|
```json
|
|
{
|
|
"data": {}
|
|
}
|
|
```
|
|
|
|
An absent `data` member is treated as a missing source. For ordinary sources,
|
|
`data: null` is also missing. The active-alert exception is listed above: its
|
|
explicit `null` payload represents an empty alert result.
|
|
|
|
Hourly forecast data must be present and contain at least one `period`. Every
|
|
hourly period needs nonzero `startTime` and `endTime` values, with `endTime`
|
|
after `startTime`; a missing, malformed, empty, or invalidly bounded hourly
|
|
product fails collection. The remaining sources follow the configured
|
|
missing-source policy. Under `error`, collection fails; under `warn`, the
|
|
source is omitted and an inspectable warning is recorded; under `none`, the
|
|
source is omitted without a warning. A per-source policy overrides the default.
|
|
See [Configuration](../config.md) for policy settings and [Weather data
|
|
internals](../internal/weather-data.md) for recorded source metadata.
|
|
|
|
Malformed top-level JSON envelopes and HTTP failures are direct request errors.
|
|
Malformed `data` for an optional source follows its missing-source policy.
|
|
|
|
## Payload Fields Used
|
|
|
|
Weatherreporter decodes only the fields below; additional upstream fields are
|
|
ignored. Timestamps must be JSON values accepted by Go's `time.Time` decoder.
|
|
|
|
### Observations And Current Conditions
|
|
|
|
`/observations` uses `stationId`, `stationName`, `timestamp`, `conditionCode`,
|
|
`isDay`, `textDescription`, `temperatureC`, `temperatureF`, `dewpointC`,
|
|
`dewpointF`, `windSpeedKmh`, `windSpeedMph`, `windGustKmh`, `windGustMph`,
|
|
`windDirectionDegrees`, `barometricPressurePa`, `barometricPressureInHg`,
|
|
`visibilityMeters`, `visibilityMiles`, `relativeHumidityPercent`,
|
|
`apparentTemperatureC`, `apparentTemperatureF`, and `presentWeather`.
|
|
|
|
`/conditions/current` uses `conditionText`, `isDay`,
|
|
`relativeHumidityPercent`, `windDirectionDegrees`, `temperatureC`,
|
|
`temperatureF`, `apparentTemperatureC`, `apparentTemperatureF`, `dewpointC`,
|
|
`dewpointF`, `windSpeedKmh`, and `windSpeedMph`.
|
|
|
|
### Hourly And Narrative Forecasts
|
|
|
|
Both forecast endpoints use run-level `locationId`, `locationName`, `issuedAt`,
|
|
`updatedAt`, `product`, `latitude`, `longitude`, `elevationMeters`,
|
|
`elevationFeet`, and `periods`.
|
|
|
|
Each `periods` item uses `startTime`, `endTime`, `name`, `isDay`,
|
|
`conditionCode`, `textDescription`, `temperatureC`, `temperatureF`,
|
|
`temperatureCMin`, `temperatureFMin`, `temperatureCMax`, `temperatureFMax`,
|
|
`dewpointC`, `dewpointF`, `windSpeedKmh`, `windSpeedMph`, `windGustKmh`,
|
|
`windGustMph`, `windDirectionDegrees`, `barometricPressurePa`,
|
|
`barometricPressureInHg`, `visibilityMeters`, `visibilityMiles`,
|
|
`apparentTemperatureC`, `apparentTemperatureF`, `cloudCoverPercent`,
|
|
`probabilityOfPrecipitationPercent`, `precipitationAmountMm`,
|
|
`precipitationAmountIn`, `snowfallDepthMM`, `snowfallDepthIn`, `uvIndex`, and
|
|
`relativeHumidityPercent`.
|
|
|
|
### Alerts, Discussion, And Weather Story
|
|
|
|
`/alerts/active` uses the `asOf` timestamp and keeps each item in `alerts` as
|
|
an alert payload. Weatherreporter does not require a separate alert-item schema
|
|
at this integration boundary.
|
|
|
|
`/discussion` uses `officeId`, `officeName`, `product`, `issuedAt`,
|
|
`updatedAt`, `keyMessages`, and the `shortTerm` and `longTerm` sections. Each
|
|
section uses `qualifier`, `text`, and `issuedAt`.
|
|
|
|
`/weatherstories/latest` uses `officeId`, `startTime`, `endTime`, `updatedAt`,
|
|
`title`, `description`, `altText`, `priority`, `order`, and `downloadUrl`.
|
|
|
|
### SPC Convective Outlooks
|
|
|
|
`/outlooks/convective` uses run-level `locationId`, `locationName`, `asOf`,
|
|
`issuedAt`, `updatedAt`, `product`, `outlooks`, and `discussions`.
|
|
|
|
Each outlook uses `id`, `provider`, `product`, `day`, `outlookType`, `label`,
|
|
`labelText`, `forecaster`, `severityRank`, `validFrom`, `validTo`, `issuedAt`,
|
|
`expiresAt`, `sourceUrl`, `imageUrl`, `containsLocation`, and GeoJSON
|
|
`geometry`. Each discussion uses `day`, `headline`, `summary`, `discussion`,
|
|
and `updatedAt`.
|
|
|
|
## Timeouts, Retries, And Failures
|
|
|
|
The configured Weather API timeout applies to each warmup and source HTTP
|
|
attempt. Weatherreporter retries transient transport and response-read failures
|
|
and these response statuses: `408`, `429`, `500`, `502`, `503`, and `504`.
|
|
It does not retry other HTTP statuses, malformed envelopes, missing data, or
|
|
payload decoding failures. A canceled context also stops an in-progress retry
|
|
delay.
|
|
|
|
The adapter accepts response bodies up to 10 MiB and rejects larger bodies
|
|
before decoding. A non-2xx response reports its relative endpoint and status,
|
|
without including upstream response text. Request construction, response-limit,
|
|
read, and decode failures include endpoint context in their errors.
|
|
|
|
Retry counts and delays are adapter behavior rather than Weather API request
|
|
parameters. Do not depend on a particular attempt count when implementing the
|
|
service.
|