2 Commits
Author SHA1 Message Date
mattandClaude ee22a54398 Add broker checker; correct EMQX version to 6.0.1
The broker is EMQX 6.0.1, not 5.x as first assumed -- 6.x keeps serving its
management API under /api/v5 for backward compatibility, so the API path is
not a version indicator. Menu paths in the setup guide verified against the
current EMQX documentation.

tools/check_broker.py verifies broker configuration end to end: anonymous
refused, made-up credentials refused, the configured account accepted, and
publishes permitted to both topic trees the firmware uses. It reads the local
config header by path and never prints the account secret, so its output is
safe to paste anywhere.

Two bugs found and fixed while testing it against the live broker:

  - paho 2.x hands the VERSION2 on_connect callback a ReasonCode object, not
    an int. int(rc) raised, every probe fell back to the timeout path, and the
    script reported an open broker as secure -- a false pass on the one check
    that most needs to be trustworthy.
  - An inconclusive result (timeout, transport error) was rendered as a pass.
    It now reports INCONCLUSIVE and fails the run, because "could not tell"
    must never read as "locked down".

The reason-code table now covers both MQTT 3.1.1 CONNACK codes and the MQTT 5
numbering paho normalises onto, so refusals print as text rather than 134/135.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 14:35:07 -07:00
mattandClaude f6630c547c Add EMQX broker setup guide and bring-up watcher
Target broker is EMQX 5.x at 192.168.1.31.

Probed its current state and documented it in docs/MQTT_SETUP.md: all
listeners up, retained messages working, management API protected (401),
but the MQTT data plane has no authenticator -- anonymous connects are
accepted, and so are arbitrary made-up credentials. Until an authenticator
exists, the broker account values in the local config header are decorative
and a successful connection proves nothing about them.

The guide covers creating the password-based authenticator, separate
soil-node and homeassistant accounts, per-account ACLs (including setting
no-match to Deny, without which the rules are cosmetic), pointing the HA
MQTT integration at EMQX, and a CONNACK/PubSubClient troubleshooting table.

tools/mqtt_watch.py watches the broker directly during bring-up. It answers
what the HA UI cannot: whether the retained discovery configs are actually
on the broker. Those are what HA rebuilds entities from after a restart, so
a node can look healthy today and disappear on the next HA restart if they
are missing. It reads its broker account secret from a file or environment
variable rather than argv, which is visible process-wide.

The broker IP is deliberately kept out of the committed template header,
since the Gitea repo is public.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 14:17:02 -07:00