feat: Tuner Genius XL — A/B channels, plus FlexRadio panel + Station Control cards

Push the tuner control further so it mirrors the native 4O3A app and the way the
PowerGenius XL is surfaced.

Backend (internal/tunergenius):
- Status now carries both RF channels A and B (source/mode, band, frequency,
  bound Flex nickname, per-channel bypass, antenna, PTT), the active channel,
  the C1/L/C2 relay-network positions, and the 3-way-vs-SO2R hardware variant
  (learned once from the `info` reply). Flat freq/antenna still mirror the active
  channel for the compact widget.
- New TunerGeniusActivate(ch) binding → `activate ch=N` (or `ant=N` on 3-way).

Frontend:
- New shared TunerCard, styled exactly like AmpCard (PWR/SWR meter bars,
  A/B channel selector with source+freq+antenna, Tune/Bypass/Operate). Used in
  BOTH the FlexRadio panel (its own card, like the PGXL) and Station Control.
- Docked TunerGeniusPanel widget now shows the two channels A/B with their
  source/frequency/antenna and lets you click to make one active — the missing
  A/B state the user flagged.
- i18n EN/FR for the new labels (channels, antenna, in-line/bypassed, title).

Still UNTESTED on hardware — verify the per-channel field names/units and the
activate behaviour on the real box.
This commit is contained in:
2026-07-25 10:47:11 +02:00
parent 933d601c03
commit 9b677c6b35
12 changed files with 439 additions and 28 deletions
+9
View File
@@ -13013,6 +13013,15 @@ func (a *App) TunerGeniusSetOperate(on bool) error {
return a.tunergenius.SetOperate(on)
}
// TunerGeniusActivate selects the active channel (1 = A, 2 = B; or antenna
// 1/2/3 on the 3-way variant).
func (a *App) TunerGeniusActivate(ch int) error {
if a.tunergenius == nil {
return fmt.Errorf("Tuner Genius not connected")
}
return a.tunergenius.Activate(ch)
}
// ── PowerGenius XL (4O3A) amplifier fan control (TCP, default port 9008) ─────
// PGXLSettings is the JSON shape for the Hardware → Amplifier panel. It covers