Skip to content

Weather Station

POCS integrates with the AAG CloudWatcher weather station out of the box, but it can work with any weather source — a different sensor, a scraper for a local weather API, or a home-built station — as long as you write records in the expected JSON format to the weather database collection.

How It Works

Weather source ──────────────────► DB "weather" collection
(AAG CloudWatcher, adapter script,         │
 or any custom integration)                ▼
                               POCS.is_weather_safe()  ──► allow / deny observations

The only thing POCS.is_weather_safe() cares about is the most recent document in the weather collection. It reads two fields and makes a go/no-go decision:

Field Required Description
is_safe yes true = conditions are safe to observe
timestamp yes ISO 8601 string; records older than 180 s are treated as unsafe

Building a Custom Integration

If you are using a non-AAG sensor or want to pull data from an existing weather service, the only thing you need to do is expose an HTTP endpoint that returns a JSON object with the required fields. POCS already has the polling and database-writing machinery built in via RemoteMonitor and pocs sensor monitor.

What your endpoint must return

The JSON object returned by your endpoint must include at minimum:

{
    "is_safe": true,
    "timestamp": "2024-01-15T10:30:00.123456"
}
Field Type Description
is_safe bool true = conditions are safe to observe
timestamp str ISO 8601 datetime of the reading; records older than 180 s are treated as unsafe

Your endpoint can return any additional fields — they will be stored alongside the required ones. Including the full AAG schema fields makes your readings visible in pocs weather status output.

Polling the endpoint

Once your endpoint is running, point pocs sensor monitor at it:

# One-liner: poll http://myweather.local/status every 90 seconds
pocs sensor monitor weather --endpoint http://myweather.local/status --read-frequency 90

Or configure the URL in your config file so no --endpoint flag is needed:

environment:
  weather:
    url: http://myweather.local/status
pocs sensor monitor weather --read-frequency 90

pocs sensor monitor fetches the endpoint on every interval, merges in a date timestamp, and writes the result to the weather database collection — the same collection that POCS.is_weather_safe() reads.

Running as a background service

The supervisord configuration already includes a ready-to-use entry for this pattern. Enable the pocs-weather-reader-remote program in conf_files/pocs-supervisord.conf (and disable pocs-weather-reader if the AAG is not physically connected):

; Use this when your weather station is NOT connected to the POCS computer.
[program:pocs-weather-reader-remote]
command=pocs sensor monitor weather --read-frequency 90
autostart=true   ; change from false → true

If the monitor process stops for any reason, readings in the database will go stale and POCS will automatically suspend observations after 180 s.


Full JSON Schema

The built-in AAG CloudWatcher integration writes all of the following fields. Custom integrations may include any subset (only is_safe and timestamp are required), or additional fields of their own.

Measurement Fields

Field Type Unit Description
timestamp str ISO 8601 datetime of the reading, e.g. "2024-01-15T10:30:00.123456"
ambient_temp float °C Ambient (air) temperature
sky_temp float °C Sky infrared temperature; the difference sky_temp − ambient_temp indicates cloud cover
wind_speed float m/s Wind speed
rain_frequency float Raw rain-sensor frequency; higher values mean drier conditions
pwm float % Heater element duty cycle

Condition Fields

Derived by comparing the measurements against configurable thresholds (see environment.weather in conf_files/pocs.yaml).

Field Type Possible Values
cloud_condition str "clear", "cloudy", "very cloudy", "unknown"
wind_condition str "calm", "windy", "very windy", "gusty", "very gusty", "unknown"
rain_condition str "dry", "wet", "rainy", "unknown"

Safety Fields

Field Type Description
cloud_safe bool True when cloud_condition == "clear"
wind_safe bool True when wind_condition == "calm"
rain_safe bool True when rain_condition == "dry"
is_safe bool True only when all three of cloud_safe, wind_safe, and rain_safe are True

Full Example Record

{
    "timestamp": "2024-01-15T10:30:00.123456",
    "ambient_temp": 15.5,
    "sky_temp": -25.0,
    "wind_speed": 2.3,
    "rain_frequency": 2700.0,
    "pwm": 75.0,
    "cloud_condition": "clear",
    "wind_condition": "calm",
    "rain_condition": "dry",
    "cloud_safe": true,
    "wind_safe": true,
    "rain_safe": true,
    "is_safe": true
}

Safety Evaluation

POCS.is_weather_safe() reads the latest weather record from the database and applies two checks:

  1. Safety flag — looks for is_safe (then falls back to safe) and casts it to bool.
  2. Staleness — compares timestamp to the current time. If the record is older than stale seconds (default 180 s) the record is treated as unsafe regardless of the flag value.

This means any integration that stops writing records will automatically halt observations after the staleness window expires.


HTTP API

The weather FastAPI service (default port 6566) exposes two endpoints:

Endpoint Method Description
/status GET Returns the most recent reading as a JSON object (schema above)
/config GET Returns the active weather station configuration

Querying via the CLI

# Show a formatted status table
pocs weather status

# Show raw JSON
pocs weather status --show-raw-values

# Show configuration
pocs weather config

# Connect to a remote unit
pocs weather --host 192.168.1.100 --port 6566 status

AAG CloudWatcher Configuration

For the built-in AAG integration, settings live under environment.weather in your config file:

environment:
  weather:
    serial_port: /dev/weather   # or /dev/ttyUSB0
    auto_detect: false          # set true to probe all ttyUSB* ports
    record_interval: 60         # seconds between DB writes
    store_permanently: false    # keep every reading, not just the latest

To set up the stable /dev/weather symlink automatically, run:

pocs weather setup

This scans USB serial ports, identifies the AAG CloudWatcher by its handshake response, and writes a udev rule to /etc/udev/rules.d/92-panoptes-weather.rules.