fix: Stream Deck Tune Toggle parses wrong TCI status field#3647
Conversation
The Stream Deck Tune Toggle only ever turned tuning on. The TCI status
parser read the tune boolean from p[0] (the trx index) instead of p[1],
so radio.tuning was always evaluated as ("0" === "true") = false,
making the cached state stale and the toggle one-directional.
Aligns the tune case with every sibling boolean handler (trx, mute,
rx_nb, split_enable, lock), which all read p[1] with a >= 2 guard.
There was a problem hiding this comment.
Verified the fix against the source — it's correct and minimal.
Confirmed:
src/core/TciProtocol.cpp:518emitstune:%1,%2;with%1= trx index,%2= the boolean. So the tune state isp[1], notp[0]. The PR's root-cause analysis is accurate.- The pre-fix line was the lone outlier: every sibling boolean handler in
parseTci—trx,mute,rx_nb,rx_anf,sql_enable,split_enable,lock,rit_enable,xit_enable— already readsp[1]with a>= 2length guard. Thetunecase usedp[0]with>= 1, soradio.tuningwas always("0" === "true")→false, leavingtune-toggle(tune:0,${!radio.tuning};) stuck sendingtrue. - The
>= 2guard is the right call: a malformedtune:0;now leavesradio.tuningunchanged rather than misparsing the trx index as a boolean. mox-togglealready reads thetrx-sourcedradio.transmittingcorrectly and is unaffected, as noted.
Single-line change, platform-independent (pure JS plugin), consistent with the surrounding code. No concerns — the unchecked test-plan item is a real-radio behavioral confirmation, which is reasonable to leave to the maintainer.
Thanks for the thorough write-up and for tracing it back to the TCI emission code rather than guessing, @mvanhorn. LGTM.
🤖 aethersdr-agent · cost: $5.1785 · model: claude-opus-4-8
ten9876
left a comment
There was a problem hiding this comment.
Approving — textbook one-line fix, diagnosis verified against the source.
TciProtocol.cpp:518 emits tune:%1,%2; (%1=trx, %2=boolean), so tune:0,true → p[0]="0", p[1]="true". The old radio.tuning = p[0] === "true" evaluated "0" === "true" → always false, so !radio.tuning was always true and the toggle stuck on. The fix reads p[1] with a >= 2 guard — matching every sibling boolean handler (trx/mute/rx_nb/split_enable/lock), which all already use p[1] — and harmlessly ignores a malformed tune:0;. Correct and consistent. CI green. Nice catch @mvanhorn.
|
Huge thanks for the merge, @ten9876. Reading the right TCI status makes the Stream Deck Tune Toggle actually toggle instead of only turning on. |
|
Thanks @ten9876 - fixing the Stream Deck Tune Toggle so it actually toggles instead of only turning tuning on is a satisfying catch. |
Summary
Fixes #3622. The Stream Deck Tune Toggle only ever turned tuning on; pressing it again never turned it off. The Tune Toggle action emits
tune:0,${!radio.tuning};, which relies on the plugin's cachedradio.tuningstaying in sync with the radio. The TCI status parser read thetuneboolean fromp[0](the trx index) instead ofp[1], soradio.tuningwas always evaluated as("0" === "true")=false. That made!radio.tuningalwaystrue, so the toggle was stuck on.AetherSDR's TCI server emits
tune:<trx>,<true|false>;— confirmed atsrc/core/TciProtocol.cpp:518(tune:%1,%2;with%1= trx,%2= the boolean). Every sibling boolean handler inplugin.js(trx,mute,rx_nb,split_enable,lock) already readsp[1]with a>= 2length guard; thetunecase was the lone outlier. This brings it in line:radio.tuningnow stays synced, so the toggle alternates on/off correctly. The bug is in the JS plugin, so it is platform-independent (not Windows-specific).mox-togglealready readsp[1]and is unaffected.Constitution principle honored
Radio-authoritative live state — the plugin's cached
radio.tuningmust faithfully reflect the state the radio reports over TCI. The fix restores that mirror by parsing the boolean from the field the radio actually emits, rather than holding a stale value.Test plan
tune:0,true;was parsed asradio.tuning = ("0" === "true")=false.node --checkpasses onplugin.js(single-line change, JS syntax valid).tune:0,true;setsradio.tuning = true; a malformedtune:0;(length < 2) leaves it unchanged rather than misparsing; subsequent presses alternatetune:0,false;/tune:0,true;.Checklist
AppSettingscalls (Principle V) — N/A, JS plugin change onlyMeterSmoother— N/A, no meter UI touched