Skip to content

Citizen weather stations

weather.cwop reads Personal Weather Station reports from the Citizen Weather Observer Program. Use these rows as separately sourced weather inputs, never as an official settlement value.

Terminal window
pip install "mostlyrightmd-weather[cwop]"

CWOP is currently a Python-only surface. Live reports arrive through the APRS-IS TCP network; there is no official REST archive to query later.

from mostlyright.weather import cwop
stations = cwop.nearby(
"KNYC",
radius_km=25,
listen_seconds=60,
)
for station in stations:
print(
station.id,
station.distance_km,
station.last_temp_f,
station.qc_status,
)

Use scan(latitude, longitude) when you already have coordinates.

from mostlyright.weather import cwop
frame = cwop.snapshot(
"CW0875",
duration_seconds=120,
quality_control=True,
persist=True,
)
print(frame[[
"station_id",
"observed_at",
"knowledge_time",
"temp_f",
"qc_score",
"qc_status",
"source",
]])

snapshot() waits for a fixed collection window and returns a schema.cwop.v1 frame. With persist=True, it also writes the collected rows to the local monthly cache.

Use latest() for one blocking observation or stream() for an asynchronous sequence:

async for observation in cwop.stream("CW0875"):
print(
observation.observed_at,
observation.temp_f,
observation.qc_status,
)
from datetime import date
from mostlyright.weather import cwop
history = cwop.history(
"CW0875",
date(2026, 1, 1),
date(2026, 6, 30),
qc_status="clean",
)

The APRS-IS stream cannot backfill dates before your collector started. history() reads only rows previously written by snapshot(persist=True) or persist_observations().

Live rows use source="cwop.live". Replayed rows use source="cwop.cache".

Keep CWOP separate from official observations

Section titled “Keep CWOP separate from official observations”

Personal stations can be indoors, mounted over hot roofs, or poorly calibrated. Mostly Right keeps CWOP out of the official observation merge and out of weather-market settlement labels.

The QC pipeline scores range, temporal consistency, indoor behavior, nearby official stations, solar bias, and reporting reliability. Keep qc_status visible when you join these rows into your own analysis.

  • NoCWOPDataError is raised when no station or report arrives in the requested window.
  • Live calls may wait for the configured listen or timeout period.
  • No browser client is provided because APRS-IS requires a TCP connection.
  • Move CWOP state with MOSTLYRIGHT_CWOP_DIR; move the shared cache root with MOSTLYRIGHT_CACHE_DIR.