Skip to content

Route MQTT updates to local antenna display names (#2880). Principle I.#2882

Closed
aethersdr-agent[bot] wants to merge 1 commit into
mainfrom
aetherclaude/issue-2880
Closed

Route MQTT updates to local antenna display names (#2880). Principle I.#2882
aethersdr-agent[bot] wants to merge 1 commit into
mainfrom
aetherclaude/issue-2880

Conversation

@aethersdr-agent
Copy link
Copy Markdown
Contributor

Summary

Fixes #2880

What was changed

Route MQTT updates to local antenna display names (#2880). Principle I.

Files modified

  • CMakeLists.txt
  • src/core/MqttAntennaAliasParser.cpp
  • src/core/MqttAntennaAliasParser.h
  • src/gui/MainWindow.cpp
  • src/gui/MqttApplet.cpp
  • src/gui/MqttApplet.h
  • tests/mqtt_antenna_alias_test.cpp
 src/gui/MainWindow.cpp              |  22 ++++
 src/gui/MqttApplet.cpp              |  10 ++
 src/gui/MqttApplet.h                |   2 +
 tests/mqtt_antenna_alias_test.cpp   | 252 ++++++++++++++++++++++++++++++++++++
 7 files changed, 381 insertions(+)

Generated by AetherClaude (automated agent for AetherSDR)

Adds a fixed MQTT topic contract that lets external station-automation
(e.g. 4O3A Antenna Genius) update AetherSDR's per-radio antenna display
aliases while preserving canonical SmartSDR tokens on the wire:

  aethersdr/antenna/name/<TOKEN>   payload = display name (empty = clear)
  aethersdr/antenna/names          payload = JSON object, null/"" = clear

The parsing logic lives in a new `MqttAntennaAliasParser` TU so the
contract is testable without a live broker and without linking Qt UI.
`MqttApplet::onMessageReceived` calls the parser and emits a new
`antennaAliasRequested` signal; `MainWindow` validates the token against
`RadioModel::knownAntennaTokens()` and drops the message entirely when
no radio is connected, so queued aliases cannot leak to a later radio.
The two fixed topics are auto-subscribed on every connect, kept out of
the user's `MqttTopics` so they can't accidentally unsubscribe them.

Honors Principle I (FlexLib Is The Protocol Authority): the existing
local-alias system keeps display labels separate from canonical tokens,
so this routes MQTT updates through `setAntennaAlias` only — antenna
commands continue to emit `ANT1`/`ANT2`/`RX_A`/`XVTA` as FlexLib
expects, never the operator's local label.

Blast radius: risk_score=0.183 on MqttApplet, all 3 high-risk callers
(MainWindow ctor, MainWindow::buildUI, AppletPanel ctor) see additive
surface only (new signal, new MqttApplet→MainWindow connection, no
changes to existing signatures).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor Author

@aethersdr-agent aethersdr-agent Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the diff against the surrounding code. Looks good — focused, well-bounded, and the test coverage is genuinely strong for this kind of integration.

What I like

  • Pure parser in its own TU. MqttAntennaAliasParser takes only QString/QByteArray, links no Qt UI types, and the test drives it directly. That's the right factoring for something whose "correctness" is really a topic-contract spec.
  • Defense in depth at the MainWindow seam. Gate on isConnected() and knownAntennaTokens().contains(token). Even during the brief window where connectionStateChanged(true) has fired but m_chassisSerial/antenna list haven't populated, known will be empty so the alias gets dropped rather than persisted under the "unconnected" fallback key from antennaAliasRadioKey() (RadioModel.cpp:541). Nice.
  • Fixed contract topics held outside MqttTopics. Keeping aethersdr/antenna/names and aethersdr/antenna/name/+ subscribed independently of the user-editable topic list (MainWindow.cpp:1710-1714) means an operator can't accidentally unsubscribe the automation contract by editing the applet's topic settings.
  • Bulk-JSON semantics for clear are explicit. Both JSON null and "" collapse to "empty alias → clear", and the comment in MqttAntennaAliasParser.h documents it. The tests pin both forms.

One small thing worth confirming (not a blocker)

MqttApplet::onMessageReceived still writes every incoming message — including the contract topics — to the visible m_messageLog (lines 266-275). For an operator who's set up bulk JSON re-publishes from Antenna Genius this could be a steady trickle into the message log. Probably fine, but if you wanted to suppress the contract topics from the human-readable log specifically, the early-return point would be right before the m_messageLog->append(line) for any topic that matches kNamesTopic or kNamePrefix. Easy follow-up if anyone complains.

Thanks for the careful work on this one — the parser/transport split and the test that exercises the disconnect-gate via a StubRadio are both above the typical bar.

@ten9876
Copy link
Copy Markdown
Collaborator

ten9876 commented May 23, 2026

Closing in favor of #2881 by @s53zo, which was opened ~1.5 hours
before this PR and addresses the same issue (#2880).

Both PRs implement the MQTT → antenna-display-name routing, but
@s53zo's:

  • Adds operator-facing documentation (resources/help/aethersdr-help.md)
    explaining the topic contract
  • Was tested against a real MQTT broker (10.0.10.9:4883) with a
    live retained-message round-trip on the author's station
  • Already passed full review (conflict-resolved against current main,
    25/25 parser tests green, build clean)

This PR is a process miss on the orchestrator's part — the
`aetherclaude-eligible` gate should have included a "check for
existing open PR addressing this issue" pre-flight, and didn't.
Filing a follow-up to add that check.

Thanks to the bot for the parallel implementation — the architectural
shape was similar, which is a good signal that #2880's design space
converges naturally. But community-contributor PRs take precedence
when both exist.

73,
Jeremy KK7GWY & Claude (AI dev partner)

@ten9876 ten9876 closed this May 23, 2026
auto-merge was automatically disabled May 23, 2026 01:53

Pull request was closed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow MQTT to update local antenna display names

1 participant