nx_mqtt_sink_for_telemetry.nx
buildroot/runtime/nx_mqtt_sink_for_telemetry.nx
about
nx_mqtt_sink_for_telemetry.nx -- MQTT sink for telemetry events.
Converts an NxTelemetryEvent into an MQTT PUBLISH frame, so the
substrate's anomaly verdicts (pred-maint commit d3037668 +
telemetry bus 469f822f) become operator-visible on whatever MQTT
broker the operator points to.
Architectural note (V1 vs V2):
V1 ships a STANDALONE sink module. The operator calls
nx_mqtt_sink_emit alongside the bus's stdout-JSON sink in a
fanout pattern (manual wiring):
nx_tm_emit(bus, event) -- writes stdout NDJSON
nx_mqtt_sink_emit(cfg, event, ...) -- builds PUBLISH frame
that operator transmits
over socket
V2 will extend NxTelemetrySink with a sealed sink-kind enum
(STDOUT_JSON / MQTT / SYSLOG / FILE / FANOUT) so the bus
dispatches automatically; this V1 module survives as the
MQTT-specific frame builder either way.
Status: SEED v0.1.0. 2026-05-27.
WINNER-TIER: WINNER-A CANDIDATE (preserved from telemetry bus;
this commit adds the MQTT-output capability without
changing the underlying value-add claim)
INCUMBENTS: Eclipse Paho's MQTTClient_publishMessage,
mqtt.js client.publish(), AWS IoT SDK publish(),
Mosquitto's mosquitto_pub CLI
NUMBERS: V1 ships the frame-builder; latency vs Paho
publish() pending paired bench on real broker
GAP: Paho buffers + retries + auto-reconnects internally;
V1 is purely the wire-format builder. Operator
owns socket lifecycle for V1; V2 adds nx_tcp_shim
integration when that ships.
PLAN: M-next: paired publish-latency bench vs Paho; add
socket-write integration when nx_tcp_shim ships
EXEMPTION REASON: n/a; provisional pending measurement
Topic shape (operator-customizable via topic_prefix):
<prefix>/<source>
where <source> is the NxTelemetryEvent.source_str (e.g.,
dependencies 3 imports · 0 importers
imports: nx_syscalls.nxnx_telemetry.nxnx_mqtt_shim.nx
imported by: nobody (leaf or entry point)
structs
| 62 | struct NxMqttSinkConfig |
consts
| 53 | const NX_MQTT_SINK_OK: i64 = 0 |
| 54 | const NX_MQTT_SINK_BAD_INPUT: i64 = 1 |
| 55 | const NX_MQTT_SINK_NOT_INITIALIZED: i64 = 2 |
| 56 | const NX_MQTT_SINK_BAD_TOPIC: i64 = 3 |
| 57 | const NX_MQTT_SINK_PAYLOAD_OVERFLOW: i64 = 4 |
| 58 | const NX_MQTT_SINK_FRAME_OVERFLOW: i64 = 5 |
functions
| 70 | func nx_mqtt_sink_init(cfg: *NxMqttSinkConfig, |
| 94 | func nx_mqtt_sink_emit_int(out: *u8, off: i64, value: i64) -> i64 |
| 122 | func nx_mqtt_sink_emit_str(out: *u8, off: i64, src: *u8, src_len: i64) -> i64 |
| 135 | func nx_mqtt_sink_build_topic(cfg: *NxMqttSinkConfig, |
| 149 | func nx_mqtt_sink_build_payload(event: *NxTelemetryEvent, |
| 181 | func nx_mqtt_sink_emit(cfg: *NxMqttSinkConfig, |