MQTT Integration¶
SQMeter publishes its readings, the safety verdict and alerts to any MQTT broker, and can announce itself to Home Assistant automatically.
Enabling MQTT¶
In Settings → Network → MQTT, turn on Publish to a broker and set the broker, credentials, Base topic (default sqmeter) and how often readings are sent. The same settings over the API:
{
"mqtt": {
"enabled": true,
"broker": "192.168.1.10",
"port": 1883,
"username": "mqttuser",
"password": "mqttpass",
"topic": "sqmeter",
"publishIntervalMs": 60000,
"publish": { "sky": true, "environment": true, "clouds": true, "gps": true, "rain": true, "wind": true, "safety": true, "diagnostics": false },
"homeAssistant": { "enabled": true, "discoveryPrefix": "homeassistant" }
}
}
The base topic may use letters, numbers, _ and -, with / between levels.
Telemetry, not an interlock
MQTT is a plaintext LAN integration. Use it for telemetry and automation; keep physical safety interlocks independent.
Topics¶
| Topic | Retained | Payload | When |
|---|---|---|---|
<base>/availability |
Yes | online / offline (last will) |
On connect / disconnect |
<base>/state |
Yes | The readings document (below) | Every publish interval, and on reconnect |
<base>/safe |
Yes | 1 safe, 0 unsafe |
On every change, refreshed every minute |
<base>/safety |
Yes | The safety object - same as GET /api/safety |
With <base>/safe |
<base>/alerts |
No | One message per alert (with Settings → Alerts → MQTT on): {"event","events"?,"title","message","level","device","timestamp"} |
Each alert |
<base>/alerts/armed |
Yes | 1 alerts on, 0 off |
On change and reconnect |
<base>/alerts/armed/set |
- | Subscribed: 1/0, on/off, true/false switch alerts on or off |
Command |
<base>/diagnostics |
No | Light-sensor sample counts and RG-15 serial counters - same as /api/status → diagnostics |
Every publish interval, when enabled |
Booleans are 1/0; availability uses Home Assistant's online/offline.
Choosing what's published¶
Settings → Network → MQTT → Publish switches each part on or off:
| Switch | Controls |
|---|---|
| Sky quality and light | light and sky in <base>/state |
| Temperature, humidity, pressure | environment |
| IR and cloud cover | infrared and clouds |
| GPS, Rain, Wind | gps, rain, wind (only when that hardware is enabled) |
| Safe / unsafe | <base>/safe and <base>/safety |
| Diagnostics | <base>/diagnostics (off by default) |
Readings (<base>/state)¶
The same document as GET /api/sensors and /ws/sensors, minus the safety object (it has its own topics) and any groups switched off:
{
"timestamp": 1791401772,
"timeValid": true,
"dataAgeMs": 412,
"dataStale": false,
"light": { "status": "ok", "ageMs": 400, "lux": 0.0003, "visible": 307, "infrared": 47, "full": 357, "gain": "MAX", "gainFactor": 9876, "integrationMs": 600, "saturated": false, "nightMode": true },
"sky": { "status": "ok", "sqm": 21.48, "rawSqm": 21.41, "nelm": 6.2, "bortle": 2, "description": "Typical truly dark site", "calibrated": false, "averagingWindowSeconds": 90 },
"environment": { "status": "ok", "ageMs": 3100, "temperature": 12.3, "humidity": 64.7, "pressure": 1013.4, "dewpoint": 6.1 },
"infrared": { "status": "ok", "ageMs": 3100, "skyTemperature": -24.7, "ambientTemperature": 12.4 },
"clouds": { "status": "ok", "coverPercent": 3, "condition": "clear", "description": "Clear", "temperatureDelta": -37.1, "correctedDelta": -33.0, "humidity": 64.7, "humiditySource": "measured" },
"gps": { "status": "ok", "ageMs": 750, "fix": true, "satellites": 9, "latitude": 51.5074, "longitude": -0.1278, "altitude": 42.0, "hdop": 1.1 },
"rain": { "status": "ok", "ageMs": 40, "raining": false, "rainingNow": false, "intensity": 0.0, "eventAccumulation": 0.4, "sensorEventAccumulation": 0.4, "totalAccumulation": 12.6, "lensFault": false, "emitterSaturated": false },
"wind": { "status": "ok", "ageMs": 900, "speed": 3.3, "gust": 6.8, "direction": 246, "vaneFault": false }
}
timestampis Unix seconds;timeValidisfalse(andtimestamp0) until the clock is set.statusisok,missing(not detected or not responding),errororstale. A group whose status isn'tokcarries onlystatusandageMs(noageMswhenmissing- it has never answered) - never zeros that look like readings.gps,rain,windare only present when that hardware is enabled.- Units: °C, %, hPa, lux, mag/arcsec², m/s, degrees (0 = north), mm and mm/h (an RG-15 set to inches is converted).
wind.directionis left out when it's calm or there's no vane. rain.rainingis held for the rain clear delay after the last drop;rainingNowis instantaneous.eventAccumulationis cleared by the clear delay;sensorEventAccumulationis the RG-15's own event total.clouds.humiditySourceisassumedwhen there's no humidity sensor (53% is used).
Home Assistant¶
Turn on Settings → Network → MQTT → Home Assistant → MQTT discovery. SQMeter then appears as a device with:
- Sensors: sky quality, limiting magnitude, Bortle class, illuminance, temperature, humidity, pressure, dew point, sky temperature, cloud cover, rain intensity, wind speed, gust and direction - for the groups you publish
- Binary sensors: Raining (moisture) and Observatory (safety: on = unsafe)
- Switch: Alerts - turn alerts off while you're not imaging
Each entity is unavailable while the device is offline or its sensor isn't ok. Switching a group off removes its entities. The discovery prefix defaults to homeassistant.
Without discovery, read <base>/state with a value_template:
mqtt:
sensor:
- name: "Sky quality"
state_topic: "sqmeter/state"
value_template: "{{ value_json.sky.sqm }}"
unit_of_measurement: "mag/arcsec²"
See Alerts for the alert events.