Skip to content

Automation bridge: harden TX watchdog re-unkey + fail-safe env parsing (fast-follow to #3727) #3743

Description

@ten9876

Fast-follow to #3727 (TX automation hardening). Two robustness items the review flagged as non-blocking; the first is a safety-backstop hardening worth doing.

1. Watchdog should re-issue the unkey each tick while still keyed-past-limit (safety)

AutomationServer::forceUnkey() resets m_txKeyedSinceMs = 0, and onTxWatchdog() re-arms from now whenever it sees keyed && m_txKeyedSinceMs == 0. So if an unkey doesn't take — the radio ignores stopTune()/setMox(false) — the watchdog grants another full m_txMaxKeyMs (~20s) window before it tries again, instead of re-issuing the unkey on the next tick.

The primary threat (a hung/abandoned script leaving TX keyed) is fully handled today — forceUnkey succeeds because the script isn't what's holding the key. This only degrades the rarer "radio ignored the unkey" case from continuous-retry to every-~20s-retry. But this is the last-resort transmitter safety rail, so for a "can never leave a live transmitter on" guarantee it should be airtight.

Fix: latch the limit-exceeded state instead of resetting the start timestamp in forceUnkey(), so onTxWatchdog() keeps issuing the unkey every tick while the radio remains keyed past the limit. Clear the latch only when the radio actually reports un-keyed.

2. Fail safe to defaults on a misconfigured env value (usability)

qEnvironmentVariableIntValue returns 0 for an empty/non-numeric value, so AETHER_AUTOMATION_TX_MAX_MS= (or a typo) sets m_txMaxKeyMs = 0 (unkey on the first watchdog tick of any transmit), and AETHER_AUTOMATION_TX_MAX_POWER=0 clamps all power to 0. Both fail safe (toward not transmitting), so this is a usability nit rather than a safety risk — but a bad value silently disabling TX is surprising.

Fix: only override the defaults when the parsed value is > 0:

bool ok = false;
const int ms = qEnvironmentVariableIntValue("AETHER_AUTOMATION_TX_MAX_MS", &ok);
if (ok && ms > 0) m_txMaxKeyMs = ms;

Both surfaced in the #3727 review (verified live on a FLEX-8400M into a dummy load). Scope: src/core/AutomationServer.cpp. ALLOW_TX-gated paths only.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementImprovement to existing featuremaintainer-reviewRequires maintainer review before any action is takenpriority: mediumMedium prioritysafetyEquipment protection concern

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions