技能创建器
skill-creator
创建、改进和评估自定义技能,把专业流程转化为可重复使用的 AI 能力。
tempest【数据与研究】Query hyper-local weather from a WeatherFlow Tempest station over its REST API and the hub's local UDP broadcast: current conditions, forecast, historical observations, and real-time decoded datagrams (obs_st, rapid_wind, evt_precip, evt_strike, hub_status). Use when the user asks about weather, temperature, rain, wind, humidity, or forecast data fro…
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
requests. UDP
listening needs a Tempest hub on the LAN and no token. --help and
--dry-run work without credentials.
metadata:
tags: weather, tempest, weatherflow, forecast, station, udp, hyper-local
sources: https://apidocs.tempestwx.com/reference/quick-start, https://weatherflow.github.io/Tempest/api/udp/v171/Drive a WeatherFlow Tempest station from the terminal. Two transports, both
first-class: the documented REST API (swd.weatherflow.com/swd/rest,
personal-use token) for conditions, forecast, and history — officially the
primary data source — and the hub's unauthenticated UDP broadcast on port
50222 for real-time, lowest-latency readings on your LAN. The bundled CLI
decodes the positional observation arrays and every UDP message family, keeps
--json output metric-native, and converts units only for human display.
export TEMPEST_TOKEN="<YOUR_TOKEN>"
The token travels to the API as a query parameter (?token=...) per the
official docs — the CLI handles this. If the env var is not set, the CLI
falls back to reading TEMPEST_TOKEN= from ~/.tempest.env (handy for agent
subprocesses that skip shell profiles). --help and --dry-run never need a
token. UDP listening never needs one either — the hub broadcast is
unauthenticated and LAN-only.
tempest stations # names, station ids, device types, serials
tempest stations --json | jq '.stations[] | {station_id, name,
devices: [.devices[] | {device_id, device_type, serial_number}]}'
Every station response nests a devices array: device_type is ST (the
Tempest all-in-one), AR/AIR, SK/SKY, or HB (the hub — it has no
observations; always filter it out before querying observations). Run this
first when you don't know your ids.
tempest current # human-readable, converted
tempest current --json # metric-native, jq-ready
tempest current --station-id 12799 --device-id 60526 # pin exact hardware
With one station it auto-selects and picks the best sensor (ST, then
SKY/SK, then AIR/AR, skipping HB). Output .observation carries the
decoded positional array as named fields with _unit companions.
tempest forecast # current + 5-day daily + next 12 hours
tempest forecast --days 7 --json
tempest forecast --station-id 12799 --days 3
The better_forecast response nests daily/hourly under a forecast wrapper
key, and it is unit-selectable (units_temp=c|f and friends, default metric)
— the CLI reads the response's units before converting anything.
tempest obs --device-id 60526 --days 1 # last UTC day (day_offset)
tempest obs --device-id 60526 --days 7
tempest obs --device-id 60526 --json
--days N maps to the API's day_offset (whole UTC days). The underlying
endpoint also accepts time_start/time_end epoch ranges (one-minute
resolution guaranteed up to 5 days) — use raw calls for those; see
references/rest-api-and-auth.md.
tempest udp listen # live stream until Ctrl-C
tempest udp listen --timeout 30 # auto-stop after 30s
tempest udp listen --timeout 60 --json # one JSON object per datagram
tempest udp listen --show-all # include hub_status/device_status
Requires being on the same LAN as the hub (routed connectivity is not enough
— broadcasts don't cross routers). No token involved. The listener decodes
every message family, dispatching on type before touching array positions:
| Family | Payload shape | Decoded fields |
|---|---|---|
obs_st / obs_air / obs_sky | list of report rows under obs | named observation fields |
rapid_wind | ONE 3-element array under ob | wind_speed_mps, wind_direction |
evt_precip | ONE array under evt | timestamp (rain started) |
evt_strike | ONE array under evt | distance_km, energy |
hub_status, device_status | named fields, no array | uptime, rssi, seq, voltage, sensor_status |
# Stage 1 -> stage 2: stations --json emits integer ids that current consumes
tempest stations --json | jq -r '.stations[].devices[]
| select(.device_type == "ST") | .device_id' | head -1
tempest current --device-id <DEVICE_ID> --json
tempest obs --device-id 60526 --days 1 --json \
| jq '{samples: (.observations | length),
day_rain_mm: .observations[-1].local_day_rain_accumulation}'
tempest udp listen --timeout 600 --json | jq 'select(.type == "evt_precip")'
obs --json ends with decoded observations carrying
local_day_rain_accumulation (mm, number); evt_precip datagrams decode to
{type, serial_number, timestamp} — both stages emit typed fields the next
stage can consume.
tempest forecast --days 7 --json \
| jq '{units_temp: .forecast.units.units_temp,
highs_f: [.forecast.forecast.daily[] | .air_temp_high * 9 / 5 + 32],
rain_hours: [.forecast.forecast.hourly[]
| select(.precip_probability > 30) | .local_hour]}'
The jq math here is safe only because it checks units_temp first — see
gotcha 2.
--json output is metric-native — the raw wire units (m/s wind, mm rain,
°C temperature, MB pressure) with _unit companion fields naming each.
Convert at the consumption edge:
tempest current --json | jq '{temp_c: .observation.air_temperature,
temp_f: (.observation.air_temperature * 9 / 5 + 32),
wind_mph: (.observation.wind_avg * 2.237),
rain_in: (.observation.rain_accumulation / 25.4)}'
Global flags work in any position: tempest --json current --device-id 60526
and tempest current --device-id 60526 --json are identical. --quiet
silences the progress logs (data on stdout, logs on stderr).
--dry-run prints a plan object and exits 0 without touching the network.
obs rows have
no field names; meaning comes from the index (obs_st: 0 epoch, 2 wind avg
m/s, 4 wind direction, 6 pressure MB, 7 temperature °C, 12 rain mm, 16
battery V, 17 report interval). Reading index 6 as temperature gives you a
plausible-looking wrong number — decode with the CLI or the layout tables
in references/observation-layouts-and-units.md./better_forecast is unit-selectable, not Celsius-locked. It defaults
to metric but honors units_temp=f, units_wind=mph, units_pressure=inhg,
units_precip=in. It reports what it used in response.units. Converting
an already-Fahrenheit response doubles it (25.4 °C → 77.7 °F → 172 "°F").
Always read units before converting; the CLI does this for you.type first.
obs families nest rows under obs; rapid_wind carries one array under
ob; evt_precip/evt_strike carry one array under evt;
hub_status/device_status carry named fields with no payload array.
Iterating rapid_wind's ob element-wise is the classic TypeError; the
bundled decode_message() shows the correct dispatch.None for missing tails.day_start_local, sunrise, sunset, hourly time are epoch seconds;
hourly objects carry local_hour (0–23) and local_day (day of month).
There is no local_time or time_string field — code expecting one
silently falls back to its default branch.forecast wrapper key. data["daily"] is
always empty; read data["forecast"]["daily"] and
data["forecast"]["hourly"] (the CLI's --json preserves the full
response, wrapper and all).HB) have no observations. They only relay. Auto-selection
skips them; if you call the API directly, filter device_type == "HB"
out before hitting /observations/device/{id} (documented 404 otherwise).obs_sky UDP day-rain is always null. Local-day rain accumulation
(index 11) is null in UDP SKY broadcasts; REST supplies the real value.
Don't build day-rain totals from UDP SKY rows.| File | Read when |
|---|---|
| references/rest-api-and-auth.md | Working with REST endpoints directly: token auth, StationSet shapes, observation parameters, forecast units, error signatures |
| references/udp-broadcast-protocol.md | Parsing raw UDP datagrams: port 50222 transport, every message family's layout, the type-dispatch rule |
| references/observation-layouts-and-units.md | Decoding positional observation arrays by index (obs_st/obs_air/obs_sky, UDP vs REST lengths) and unit conversion tables |
| references/cli-worked-recipes.md | Copy-paste multi-step CLI recipes with jq stages, dry-run plans, and expected error paths |
stations, current, obs,
forecast, udp listen; global --json, --dry-run, --quiet,
--verbose accepted in any position; offline dry-run plans for every
command.requests (the only dependency).TEMPEST_TOKEN for REST commands (free, personal use; created in the
Tempest web app). UDP listening needs no token, only line-of-sight to the
hub's LAN.