Skip to content

MQTT Topics

gas2mqtt publishes device state, health information, and errors to a set of MQTT topics under the gas2mqtt/ prefix. One topic accepts inbound commands.


Topic Overview

Topic Dir Payload Retain QoS
gas2mqtt/gas_counter/state outbound Gas counter JSON yes 1
gas2mqtt/gas_counter/set inbound Set consumption JSON
gas2mqtt/gas_counter/availability outbound "online" / "offline" yes 1
gas2mqtt/temperature/state outbound Temperature JSON yes 1
gas2mqtt/temperature/availability outbound "online" / "offline" yes 1
gas2mqtt/magnetometer/state ¹ outbound Raw magnetometer JSON yes 1
gas2mqtt/magnetometer/availability ¹ outbound "online" / "offline" yes 1
gas2mqtt/status outbound Heartbeat JSON + LWT "offline" yes 1
gas2mqtt/error outbound Error JSON no 1

¹ Only active when GAS2MQTT_ENABLE_DEBUG_DEVICE=true.


Payload Schemas

Gas Counter

Topic: gas2mqtt/gas_counter/state

Published on every trigger event (not every poll). Includes the optional consumption_m3 field when consumption tracking is enabled.

Basic
{
  "counter": 42,
  "trigger": "CLOSED"
}
With consumption tracking
{
  "counter": 42,
  "trigger": "CLOSED",
  "consumption_m3": 0.42
}
Field Type Description
counter integer Cumulative tick count (wraps at 65536)
trigger string "OPEN" or "CLOSED" — current trigger state
consumption_m3 float Cumulative gas in m³ (optional)

Temperature

Topic: gas2mqtt/temperature/state

Polled at the configured temperature_interval (default: every 5 minutes) but only published when the PT1-filtered value changes by more than 0.05 °C (cosalette OnChange publish strategy). This suppresses duplicate readings when the temperature is stable.

{
  "temperature": 21.5
}
Field Type Description
temperature float PT1-filtered temperature in °C

Magnetometer (Debug)

Topic: gas2mqtt/magnetometer/state

Only published when GAS2MQTT_ENABLE_DEBUG_DEVICE=true. Published at poll_interval.

{
  "bx": 123,
  "by": -456,
  "bz": -5000
}
Field Type Description
bx integer Magnetic field strength, X axis
by integer Magnetic field strength, Y axis
bz integer Magnetic field strength, Z axis

Availability

Topics: gas2mqtt/{device}/availability

Each device publishes its availability status. The cosalette framework manages these automatically.

"online"     # device is running
"offline"    # device has stopped (or app shutting down)

Status (Heartbeat)

Topic: gas2mqtt/status

Periodic heartbeat published by the cosalette health reporter. Also used as the Last Will and Testament (LWT) — the broker publishes "offline" if gas2mqtt disconnects unexpectedly.

Heartbeat
{
  "status": "online",
  "uptime": 3600.0,
  "version": "1.0.0",
  "devices": {
    "gas_counter": { "status": "online" },
    "temperature": { "status": "online" },
    "magnetometer": { "status": "online" }
  }
}

Error

Topic: gas2mqtt/error

Published (not retained) when a device encounters an error. The cosalette framework deduplicates consecutive identical errors.

{
  "type": "OSError",
  "message": "I2C bus read failed",
  "device": "gas_counter",
  "timestamp": 1700000000.0
}

!!! info "Per-device error topics" In addition to the global error topic, cosalette publishes device-specific errors to gas2mqtt/{device}/error (e.g., gas2mqtt/gas_counter/error). These have the same payload format.


Inbound Commands

Set Consumption

Topic: gas2mqtt/gas_counter/set

Set the cumulative consumption counter to an absolute value. Requires GAS2MQTT_ENABLE_CONSUMPTION_TRACKING=true.

{
  "consumption_m3": 12345.678
}

After receiving a valid command, gas2mqtt publishes an updated state to gas2mqtt/gas_counter/state.

!!! warning "Consumption tracking must be enabled" Commands sent when enable_consumption_tracking is false are logged as warnings and ignored.


Framework Topics

Alongside the gas2mqtt-specific topics above, cosalette itself publishes two framework-owned topics. Both are always on — no setting disables them — retained, QoS 1, and republished byte-identically on every broker connect.

Topic Payload Retain QoS
gas2mqtt/_meta/registry Canonical AsyncAPI 3.0.0 document yes 1
gas2mqtt/_meta/state_model_drift state_model drift snapshot JSON yes 1

Registry (gas2mqtt/_meta/registry)

The canonical AsyncAPI document describing every channel gas2mqtt publishes and subscribes to. Inbound command channels are stripped from the published copy so the command surface is not exposed to anyone who can subscribe on a shared broker.

State Model Drift (gas2mqtt/_meta/state_model_drift)

A machine-readable snapshot of state_model declaration drift (ADR-069): a handler whose state_model= argument disagrees with its return type annotation. The topic is published even when there is no drift — a clean app publishes drift_count: 0 rather than omitting the topic, so "no drift" is distinguishable from "never ran a version that publishes this topic".

{
  "schema_version": 1,
  "drift_count": 0,
  "entries": []
}
Field Type Description
schema_version integer Envelope version; bumped only on an incompatible payload change
drift_count integer Number of handlers with a declaration/annotation conflict
entries[].handler string Registered handler name
entries[].archetype string "telemetry" or "command"
entries[].kind string Drift kind — currently only "annotation_conflict"
entries[].declared_model string The state_model= class name declared on the handler
entries[].effective_annotation string The handler's actual return type annotation

Fleet-wide scraping

One subscription across a whole broker distinguishes a healthy app from one that predates this topic:

mosquitto_sub -t '+/_meta/state_model_drift'

An app publishing drift_count: 0 is healthy. An app with no retained message on this topic at all has not been upgraded past cosalette 0.9.0.

ACL guidance

Both topics disclose handler names, channel addresses, and payload schemas. If you run a production broker ACL file, protect _meta/# the same way you protect _meta/registry. Every mosquitto.conf shipped in this repo is dev-only (allow_anonymous true, no ACL file), so there is nothing to change in-repo — this note only applies if you deploy your own broker ACLs.


Topic Naming Convention

gas2mqtt follows the cosalette topic convention:

{prefix}/{device}/{channel}
Segment Value
prefix App name — gas2mqtt by default
device Device name: gas_counter, temperature, magnetometer
channel state, set, availability, or error

Global topics (status, error) omit the device segment:

gas2mqtt/status
gas2mqtt/error