From cacc4e62064ccfe5a7f2810c79437e9183779b15 Mon Sep 17 00:00:00 2001 From: Jakub <106778416+MarekZegare4@users.noreply.github.com> Date: Fri, 5 Jun 2026 12:42:14 +0200 Subject: [PATCH] fix(ui): keep hasConnection() BLE-specific; use isClientConnected() only for mute/wake MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Self-review caught a regression I'd just introduced: feeding hasConnection() from isClientConnected() (BLE *or* USB) broke the GPX-export collision warning in TrailScreen, which relies on hasConnection() meaning "BLE app connected" (BLE → USB dump is safe; otherwise the app may be on USB → warn). Correct split: - hasConnection() ← isBLEConnected() — BLE-specific consumers: BT status indicator, pairing PIN, GPX-export warning. - isClientConnected() (BLE bonded OR open USB-CDC port) used directly only by the Auto buzzer mute and message-wake, which should react to either transport. Builds clean on dual (OLED + e-ink) and pure-BLE. Co-Authored-By: Claude Opus 4.8 --- examples/companion_radio/AbstractUITask.h | 3 +++ examples/companion_radio/MyMesh.cpp | 11 ++++++----- examples/companion_radio/ui-new/UITask.cpp | 12 ++++++------ 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/examples/companion_radio/AbstractUITask.h b/examples/companion_radio/AbstractUITask.h index 0941a106..6905ecdd 100644 --- a/examples/companion_radio/AbstractUITask.h +++ b/examples/companion_radio/AbstractUITask.h @@ -39,6 +39,9 @@ public: // (BLE+USB) interface hasConnection() is always true (USB counts), so use // this for BLE-specific UI like the pairing-PIN prompt. bool isBLEConnected() const { return _serial->isBLEConnected(); } + // True when a companion app is connected over any transport (BLE bonded or an + // open USB-CDC port). For app-connected behaviour like Auto buzzer mute. + bool isClientConnected() const { return _serial->isClientConnected(); } uint16_t getBattMilliVolts() const { return _board->getBattMilliVolts(); } bool isSerialEnabled() const { return _serial->isEnabled(); } void enableSerial() { _serial->enable(); } diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index ca889598..63f8d6de 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -2497,11 +2497,12 @@ void MyMesh::loop() { } #ifdef DISPLAY_CLASS - // "a companion app is connected over any transport" — BLE bonded or a host - // holding the USB-CDC port open. Drives Auto buzzer mute + message-wake. - // (Not isConnected(): a dual interface hardcodes that true as a send - // fallback. The BT status indicator and pairing PIN use isBLEConnected().) - if (_ui) _ui->setHasConnection(_serial->isClientConnected()); + // hasConnection() means "a BLE companion app is connected". Not isConnected() + // (a dual interface hardcodes that true as a USB send-fallback). Drives the BT + // status indicator, pairing PIN, and the GPX-export collision warning — all + // BLE-specific. The Auto buzzer mute / message-wake use isClientConnected() + // (BLE *or* an open USB port) directly instead. + if (_ui) _ui->setHasConnection(_serial->isBLEConnected()); #endif } diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index 1bc1b3fa..46d1282a 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -740,9 +740,9 @@ public: display.drawXbm((display.width() - 32) / 2, content_y, _task->isSerialEnabled() ? bluetooth_on : bluetooth_off, 32, 32); const int text_y = content_y + 32 + 3; - // Gate on BLE-bonded state, not hasConnection(): on a dual BLE+USB - // interface hasConnection() is always true (USB), which would hide the - // PIN forever — the exact e-ink dual-build pairing bug. + // The pairing PIN is BLE-specific: show it while BLE is on but not yet + // bonded. (Gating on a plain isConnected() broke this on dual builds, + // where it's hardcoded true.) const bool waiting_for_pair = _task->isSerialEnabled() && !_task->isBLEConnected() && the_mesh.getBLEPin() != 0; if (waiting_for_pair && !display.isLandscape()) { char pin_buf[16]; @@ -1521,7 +1521,7 @@ void UITask::newMsg(uint8_t path_len, const char* from_name, const char* text, i showAlert(alert_buf, 3000); if (_display != NULL && !_locked) { - if (!_display->isOn() && !hasConnection()) { + if (!_display->isOn() && !isClientConnected()) { // wake for the msg unless an app (BLE/USB) is already showing it _display->turnOn(); } if (_display->isOn()) { @@ -1791,7 +1791,7 @@ void UITask::loop() { #ifdef PIN_BUZZER if (_node_prefs && _node_prefs->buzzer_auto) { - bool should_quiet = hasConnection(); + bool should_quiet = isClientConnected(); // BLE bonded or an open USB port if (buzzer.isQuiet() != should_quiet) { buzzer.quiet(should_quiet); _next_refresh = 0; @@ -2197,7 +2197,7 @@ void UITask::cycleBuzzerMode() { _node_prefs->buzzer_auto = (mode == 2) ? 1 : 0; if (mode == 0) { buzzer.quiet(false); _node_prefs->buzzer_quiet = 0; notify(UIEventType::ack); } if (mode == 1) { buzzer.quiet(true); _node_prefs->buzzer_quiet = 1; } - if (mode == 2) { buzzer.quiet(hasConnection()); } + if (mode == 2) { buzzer.quiet(isClientConnected()); } static const char* labels[] = { "Buzzer: ON", "Buzzer: OFF", "Buzzer: Auto" }; showAlert(labels[mode], 800); _next_refresh = 0;