Files
magnus919_agent-skills/tempest-cli/references/tempest-api-field-layouts.md
T
Magnus Hedemark f2756491b7 feat: add tempest-cli skill — hyper-local weather from Tempest station
CLI wrapper for the WeatherFlow Tempest API: current conditions,
forecast, historical observations, and real-time UDP broadcasts.
Demonstrates all cli-builder patterns in a working, testable project:

- Non-interactive with --json, --dry-run, --quiet, --verbose
- Lazy auth (--help and --dry-run work without a token)
- Multi-device filtering (auto-skips HB hub, prefers ST > SKY > AIR)
- Dual-output via emit() helper
- Structured logging with log/warn/die
- Stderr hygiene and import-time warning suppression
- Idempotent operations
- Global flags in any position (pre-parsed from argv)

Includes the Python CLI script (scripts/tempest-cli) and full API
field layout reference (references/tempest-api-field-layouts.md).

Signed-off-by: Jasper <magnus@groktop.us>
2026-05-21 22:33:20 -04:00

129 lines
4.8 KiB
Markdown

# Tempest API Field Layouts
Quick reference for the obs_st (Tempest all-in-one) observation array layout.
The API returns observations as positional arrays — these index maps are
required for any CLI or script that reads raw observation data.
## obs_st (Tempest Device)
| Index | Field | Units | Notes |
|-------|-------|-------|-------|
| 0 | epoch | seconds UTC | |
| 1 | wind_lull | m/s | Minimum 3-second sample |
| 2 | wind_avg | m/s | Average over report interval |
| 3 | wind_gust | m/s | Maximum 3-second sample |
| 4 | wind_direction | degrees | 0-360 |
| 5 | wind_sample_interval | seconds | |
| 6 | station_pressure | MB | |
| 7 | air_temperature | C | |
| 8 | relative_humidity | % | |
| 9 | illuminance | lux | |
| 10 | uv | index | |
| 11 | solar_radiation | W/m² | |
| 12 | rain_accumulation | mm | Over last report interval |
| 13 | precipitation_type | 0=none 1=rain 2=hail | |
| 14 | avg_strike_distance | km | |
| 15 | strike_count | count | |
| 16 | battery | volts | |
| 17 | report_interval | minutes | |
| 18 | local_day_rain_accumulation | mm | |
| 19 | nc_rain_accumulation | mm | |
| 20 | local_day_nc_rain_accumulation | mm | |
| 21 | precip_analysis_type | enum | 0=none, 1=RainCheck display on, 2=off |
## obs_air (Air Sensor)
| Index | Field | Units |
|-------|-------|-------|
| 0 | epoch | seconds UTC |
| 1 | station_pressure | MB |
| 2 | air_temperature | C |
| 3 | relative_humidity | % |
| 4 | lightning_strike_count | count |
| 5 | lightning_avg_distance | km |
| 6 | battery | volts |
| 7 | report_interval | minutes |
## obs_sky (Sky Sensor)
| Index | Field | Units | Notes |
|-------|-------|-------|-------|
| 0 | epoch | seconds UTC | |
| 1 | illuminance | lux | |
| 2 | uv | index | |
| 3 | rain_accumulation | mm | |
| 4 | wind_lull | m/s | |
| 5 | wind_avg | m/s | |
| 6 | wind_gust | m/s | |
| 7 | wind_direction | degrees | |
| 8 | battery | volts | |
| 9 | report_interval | minutes | |
| 10 | solar_radiation | W/m² | |
| 11 | local_day_rain_accumulation | mm | |
| 12 | precipitation_type | 0=none 1=rain 2=hail | |
| 13 | wind_sample_interval | seconds | |
| 14 | nc_rain | mm | |
| 15 | local_day_nc_rain | mm | |
| 16 | precip_analysis_type | 0=none 1=RainCheck on 2=off | |
## API Response Quirks
### better_forecast nesting
The `daily` and `hourly` arrays live under a `forecast` wrapper key, NOT at the
top level of the response. If reading from the raw API:
```python
# Wrong (assumes top-level):
days = data.get("daily", []) # returns []
# Right (respects nesting):
fc = data.get("forecast", {})
days = fc.get("daily", [])
hours = fc.get("hourly", [])
```
The top-level keys of `/better_forecast` are:
- `current_conditions` — dict with air_temperature, conditions, icon, etc.
- `forecast` — dict containing `daily` (list) and `hourly` (list)
- `station` — metadata (elevation, agl, station_id)
- `units` — unit system for the response
- `status` — status_code, status_message
- `timezone`, `timezone_offset_minutes`, `latitude`, `longitude`, `location_name`
### Device types in /stations
Devices within a station have a `device_type` field. Known values:
- `HB` — Hub (cannot query observations — no `/observations/device/{id}` endpoint)
- `ST` — Tempest all-in-one (preferred sensor)
- `SKY` — Sky sensor
- `AIR` — Air sensor
Always filter out HB devices before auto-selecting a device for observation queries.
### Auth
Token is passed as query parameter: `?token=XXX`
No header-based auth for the swd.weatherflow.com REST API.
Personal access tokens generated at https://weatherflow.com (account → API Tokens).
### Units
Raw observations use metric (C, m/s, MB, mm).
The `better_forecast` endpoint returns unit-converted values based on station
preferences. The `units` key in the response documents which units are in use.
All temperature values are in **Celsius** regardless of station preference — CLI
must convert to °F if displaying imperial. Unit labels from the API are authority.
### Field type traps in better_forecast
The forecast endpoint uses epoch integers where you'd expect date strings, and
field names that differ from what common sense suggests:
| Field | Actual type | Common mistake | Fix |
|-------|-----------|---------------|-----|
| `daily[].day_start_local` | epoch int (e.g. 1778385600) | Assumed ISO string "2026-05-10T..." | `datetime.fromtimestamp(ts).strftime(...)` |
| `hourly[].local_hour` | int (e.g. 10) | Assumed ISO timestamp string | Use directly as `{h:02d}:00` |
| `hourly[].local_day` | int (e.g. 10 for the 10th) | N/A | Use alongside `local_hour` for time-of-day |
| `hourly[].local_time` | **does not exist** | Commonly assumed field | Use `local_hour` instead |
The hourly objects do NOT have a `local_time` or `time_string` field — just
`time` (epoch int), `local_day` (int), and `local_hour` (int, 0-23). Any code
looking for `local_time` will silently fall back to its default/"?" branch.