AAG CloudWatcher (Solo)
The AAG CloudWatcher Solo is Starship's primary safety source. It's a self-contained weather station with a built-in web server that exposes a CGI endpoint returning the current readings (cloud, rain, wind, temperature, humidity, sky brightness, pressure) together with the Solo's own safe/unsafe verdict.
Starship reads the Solo but never commands it. The Solo has a relay output (its switch field) that Starship deliberately leaves alone — the Solo's own logic, and the hardwired interlock between the Solo and your roof, stay authoritative.
Connecting to the Solo
The Solo hosts its CGI at a .local or fixed-IP address. On most networks it's reachable by the hostname aagsolo, which maps via mDNS / local DNS to the Solo's IP.
In Settings → AAG CloudWatcher (Solo) (the [solo] section of the config), set:
- Host (
host, defaultaagsolo) — the hostname or IP that resolves to your Solo. A raw IP such as192.168.1.42works too. - Poll interval (
poll_interval_s, default30) — how often Starship fetches a fresh reading, in seconds. - Timeout (
timeout_s, default5) — how long to wait for the Solo to answer before treating the fetch as a failure. This must be shorter than the poll interval.
Starship polls http://<host>/cgi-bin/cgiLastData on the configured interval, parses the key=value text payload, and publishes solo.reading events on the internal bus (with solo.stale and solo.error events when a reading is old or the fetch fails).
What the Solo reports
The Solo returns its own per-sensor verdicts, each of which is SAFE, WARNING, or UNSAFE:
- Cloud
- Wind
- Rain
- Humidity
- Light / daylight
- Pressure
The Solo's overall verdict is SAFE only when every sub-sensor is SAFE. Starship trusts that headline verdict for the Solo's own sensors.
What it contributes to the Safety Supervisor
The Safety Supervisor is the only part of Starship allowed to declare the overall safety state; the Sequencer, Scheduler, and scripting all act on its verdict. The Supervisor treats the Solo as its primary source and adds its own meta-rules on top of the Solo's verdict:
- Fail-closed. If the Solo has never reported, or Starship loses contact with it, the state is UNKNOWN / UNSAFE — never "no data, keep going."
- No contact. If no reading arrives for the primary-loss timeout (
safety.primary_loss_timeout_s, default 60 s), the verdict goes UNSAFE. - Stale reading. If the Solo's newest reading is older than ~90 seconds by the Solo's own clock, it's treated as stale and forces UNSAFE.
- Reported unsafe. If the Solo's overall verdict is unsafe, Starship is UNSAFE, and the reason names which sensors are in WARNING or UNSAFE.
- Asymmetric recovery (dwell). SAFE → UNSAFE is instant. Coming back the other way, the Solo must report SAFE continuously for the dwell window (
safety.unsafe_to_safe_dwell_s, default 600 s) before the Supervisor releases UNSAFE. During that window the state shows WARNING with a countdown, so the roof doesn't flap on marginal skies.
Any of unsafe / stale / no-contact pushes the Supervisor verdict toward UNSAFE (or UNKNOWN, which is treated the same for gating).
Sustained-loss escalation (optional)
Normally an UNSAFE that came from a lost or stale Solo link auto-recovers once the link returns. If you'd rather a dead weather link not leave the rig flapping the roof under unknown skies all night, set safety.weather_loss_emergency_s (default 0 = off). After that many seconds of continuous loss or silence, the Supervisor escalates to a latched EMERGENCY (park + close, manual reset) instead of auto-recovering. This counts only loss/silence — a plain reported-unsafe (rain, cloud) still auto-recovers on the dwell.
Poll-thread watchdog
Because the Supervisor is event-driven, it only ticks when the Solo driver publishes an event. A separate health-monitor watchdog ([health] → solo_heartbeat_enabled, on by default) notices if the Solo poll thread has gone silent — no solo.reading or solo.error for a few poll intervals — and drives the same emergency safe-state, so a silently dead poll thread can't leave the rig unguarded. Tune the silence threshold with solo_heartbeat_poll_multiple (multiple of the poll interval, default 3×) and solo_heartbeat_min_age_s (an absolute floor).
Manual mode (monitoring off)
For a portable / no-observatory / no-weather-sensor rig where a person is present, set safety.enabled = false. In this mode the Supervisor doesn't arm, the Solo isn't polled, and the verdict reads DISABLED — which never blocks anything (roof-open included). The UI shows "MANUAL MODE / monitoring off" rather than a red UNSAFE, and it's the operator's job to keep the rig safe.
Current readings on the dashboard
The Status / Safety page shows the latest Solo reading, live-updated over the WebSocket (solo.reading) and available at GET /api/solo/last:
- Overall safe/unsafe plus the per-sensor states (cloud, wind, rain, humidity, light, pressure)
- Sky-minus-ambient temperature (the cloud indicator), ambient temperature, and dew point
- Relative humidity
- Wind speed and gust
- Rain counter (lower = wetter)
- Sky brightness (SQM, mag/arcsec²)
- Absolute and relative pressure
- Solo firmware version
- Time since the last reading, and a stale flag
- A plain-language list of the reasons the Solo is reporting unsafe
Notes
The driver is read-only and straightforward Python. If the Solo's behaviour ever needs adjusting for your firmware or units, it's a small module you can fork, fix, and send back as a PR.