WebSocket¶
Connect to /ws/sensors for a live stream of sensor readings. The device currently pushes messages every second.
Data freshness
The default sensor poll interval is 5 seconds, so several WebSocket messages can contain the same sensor reading. Each message carries dataAgeMs and dataStale, and every sensor group its own ageMs.
Connecting¶
const ws = new WebSocket('ws://sqmeter.local/ws/sensors');
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('SQM:', data.sky.sqm);
};
ws.onclose = () => {
// reconnect with backoff
};
Message Format¶
Each message on /ws/sensors is the readings document - the same as GET /api/sensors and MQTT <base>/state - with the safety object added:
{
"timestamp": 1791401772,
"timeValid": true,
"dataAgeMs": 412,
"dataStale": false,
"light": { "status": "ok", "ageMs": 400, "lux": 0.0003, "...": "..." },
"sky": { "status": "ok", "sqm": 21.48, "nelm": 6.2, "bortle": 2, "...": "..." },
"environment": { "status": "ok", "temperature": 12.3, "humidity": 64.7, "pressure": 1013.4, "dewpoint": 6.1, "...": "..." },
"infrared": { "status": "ok", "skyTemperature": -24.7, "ambientTemperature": 12.4, "...": "..." },
"clouds": { "status": "ok", "coverPercent": 3, "condition": "clear", "...": "..." },
"rain": { "status": "ok", "raining": false, "intensity": 0.0, "...": "..." },
"safety": { "safe": true, "reasons": [], "...": "..." }
}
See MQTT → Readings for every field and the rules: units, status values (ok, missing, error, stale), and groups for disabled hardware being left out.
Python Example¶
import asyncio
import json
import websockets
async def stream():
async with websockets.connect("ws://sqmeter.local/ws/sensors") as ws:
async for message in ws:
data = json.loads(message)
sky, clouds = data["sky"], data["clouds"]
if sky["status"] == "ok":
cover = clouds.get("description", "unknown")
print(f"SQM: {sky['sqm']:.2f} Bortle: {sky['bortle']} Sky: {cover}")
asyncio.run(stream())
Notes¶
/ws/statusstreams the same object asGET /api/statusevery 2 seconds (WiFi, memory, MQTT, Bluetooth, darkness/sun position)- The server broadcasts to all connected clients simultaneously
- There is no authentication on the WebSocket endpoint
- Broadcasts happen every 1 second regardless of
sensor.readIntervalMs