MQTT UX: forgiving broker input + per-GPU Home Assistant sensors#7
Merged
Conversation
Publishes controller status to MQTT and accepts commands, so the R730's fan state appears in Home Assistant as a self-registered device. Off by default; zero behavior change when disabled. - New internal/mqtt bridge (paho) consuming the same controller methods the HTTP API uses (GetStatus/SetOverride/ClearOverride/AddHint/ RemoveHint), so MQTT commands inherit all safety rules: min/max clamping, 24h override cap, critical-temp ramp override, hint validation. The controller package stays MQTT-unaware. - MQTT Discovery: one HA device with 11 entities (6 sensors, 3 binary sensors, an override-speed number bounded to min/max, a clear-override button), retained config republished on every (re)connect. - Per-tick retained state JSON on monitoring.interval; availability topic with Last Will so HA marks the device unavailable the instant the process dies. - Command topics (override/clear/hint, QoS 1) validated by a shared internal/validate package extracted from the HTTP layer so both enforce identical rules. Retained command messages are dropped (logged once per topic) to avoid stale commands replaying on reconnect. - A hung or unreachable broker can never block the control loop or delay the shutdown restore(): connect is fire-and-forget, publish/subscribe/ stop are bounded, and bridge teardown is sequenced after the BMC hand-back with a 3s bound. - Config: mqtt section (default off, broker required when enabled, password json:"-", env overrides); README HA section; Unraid template MQTT fields; config.example.yaml documents the block and validates verbatim. Design + plan: docs/superpowers/specs and docs/superpowers/plans. Task: dex e6fla2yl - MQTT / Home Assistant support Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…earer logging Two MQTT/Home Assistant UX improvements from real-world setup friction. Broker input normalization (internal/mqtt/broker.go): - Accept a bare host (10.0.1.160), host:port, or a pasted http(s):// URL and normalize to tcp://host:port, defaulting to port 1883; map mqtt://->tcp://, mqtts/tls->ssl:// (8883); handle IPv6 literals; trim whitespace/trailing slash. Unparseable input passes through unchanged rather than crashing. - Log how the broker string was interpreted; warn when the resolved port is 8123 (Home Assistant's web UI, a common wrong-port mistake); on a stuck publish, log a one-time hint pointing at host/port instead of silent timeouts. Per-GPU sensors (internal/mqtt/discovery.go, state.go): - Publish one Temperature/Utilization/Power sensor set per detected GPU (dynamic count), named 'GPU N (model) ...', under the same HA device, plus the existing aggregate renamed 'GPU Temperature (Max)' (unique_id unchanged, preserving HA history). State gains a per-card gpus[] array. - Per-GPU discovery is published lazily on the first tick a card is seen (not only at connect, which races ahead of the first GPU read at cold start) and re-emitted on reconnect; announced once per index per connection, self- healing on transient publish failure. Controller stays MQTT-unaware; bounded publish/connect/stop, retained-command drop, and zero-activity-when-disabled all preserved. Verified on a live R730 with two Tesla P40s: bare-host broker connects and both cards register as individual HA entities. Tasks: dex i5zslbn2, df9afuxm Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Stacked on #6 (the MQTT feature) — merge #6 first. Two UX improvements that came directly out of setting this up against a real Home Assistant install on an R730 with two Tesla P40s.
1. Forgiving broker input + clearer logging. You no longer need
tcp://host:port:10.0.1.160),host:port, or even a pastedhttp://…:8123— it normalizes totcp://host:port, defaulting to port 1883. (mqtt://→tcp://,mqtts:///tls://→ssl://:8883, IPv6 handled, whitespace/trailing-slash trimmed; unparseable input passes through unchanged rather than crashing.)2. Per-GPU sensors (dynamic). Instead of one aggregate GPU temperature, each detected card gets Temperature / Utilization / Power, named
GPU N (model) …, under the same HA device. The aggregate stays, renamed "GPU Temperature (Max)" (unique_id unchanged, so HA history survives). State gains a per-cardgpus[]array.Review & verification
go vet+go test -raceclean across all 8 packages; new cold-start unit + integration tests (real in-process broker).1.2.0-rc): bare-host broker10.0.1.160→ connected; all 17 entities on the broker includingGPU 0 (Tesla P40)andGPU 1 (Tesla P40)temp/util/power.Follow-ups filed (non-blocking): more robust broker parser via
net/url, GPU index-vs-position hardening, HAstate_classfor statistics.Tasks: dex i5zslbn2, df9afuxm
🤖 Generated with Claude Code