From e7af29e5515ff63e36ae8ea194741ed597131ba1 Mon Sep 17 00:00:00 2001 From: Nick Dunklee Date: Fri, 5 Jun 2026 11:24:39 -0600 Subject: [PATCH] feat: rak ble companion led behavior change RAK nodes use default board behavior for BLE handling. This keeps the BLE LED turned on solid all the time, and blue LEDs tend to have a shorter life than most. Most MeshCore node behavior is minimalist to save power. This is a simple change for RAK boards to do basic BLE LED handling. **Feature:** - Companion BLE LED blinks during initial pairing - Companion BLE LED turns off once connected to a device - Companion BLE LED blinks when disconnected from a device Tested on RAK19003, RAK19001 --- src/helpers/nrf52/SerialBLEInterface.cpp | 30 +++++++++++++++++++++--- src/helpers/nrf52/SerialBLEInterface.h | 4 ++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/helpers/nrf52/SerialBLEInterface.cpp b/src/helpers/nrf52/SerialBLEInterface.cpp index 75a4e3b064..e9f56fd9a4 100644 --- a/src/helpers/nrf52/SerialBLEInterface.cpp +++ b/src/helpers/nrf52/SerialBLEInterface.cpp @@ -128,9 +128,13 @@ void SerialBLEInterface::begin(const char* prefix, char* name, uint32_t pin_code char charpin[20]; snprintf(charpin, sizeof(charpin), "%lu", (unsigned long)pin_code); - - // If we want to control BLE LED ourselves, uncomment this: - // Bluefruit.autoConnLed(false); + +#if defined(RAK_BOARD) + Bluefruit.autoConnLed(false); + #ifdef LED_BLUE + digitalWrite(LED_BLUE, 1 - LED_STATE_ON); + #endif +#endif Bluefruit.configPrphBandwidth(BANDWIDTH_MAX); Bluefruit.begin(); @@ -252,6 +256,8 @@ void SerialBLEInterface::enable() { _isEnabled = true; clearBuffers(); _last_health_check = millis(); + _last_led_blink = 0; + _led_state = false; Bluefruit.Advertising.restartOnDisconnect(true); Bluefruit.Advertising.start(0); @@ -265,6 +271,10 @@ void SerialBLEInterface::disconnect() { void SerialBLEInterface::disable() { _isEnabled = false; + _led_state = false; +#if defined(RAK_BOARD) && defined(LED_BLUE) && LED_BLUE >= 0 + digitalWrite(LED_BLUE, 1 - LED_STATE_ON); +#endif BLE_DEBUG_PRINTLN("SerialBLEInterface: disable"); Bluefruit.Advertising.restartOnDisconnect(false); @@ -296,6 +306,20 @@ size_t SerialBLEInterface::writeFrame(const uint8_t src[], size_t len) { } size_t SerialBLEInterface::checkRecvFrame(uint8_t dest[]) { +#if defined(RAK_BOARD) && defined(LED_BLUE) && LED_BLUE >= 0 + if (_isEnabled && _conn_handle == BLE_CONN_HANDLE_INVALID) { + unsigned long t = millis(); + if (t - _last_led_blink >= 500) { + _last_led_blink = t; + _led_state = !_led_state; + digitalWrite(LED_BLUE, _led_state ? LED_STATE_ON : (1 - LED_STATE_ON)); + } + } else if (_led_state) { + _led_state = false; + digitalWrite(LED_BLUE, 1 - LED_STATE_ON); + } +#endif + if (send_queue_len > 0) { if (!isConnected()) { BLE_DEBUG_PRINTLN("writeBytes: connection invalid, clearing send queue"); diff --git a/src/helpers/nrf52/SerialBLEInterface.h b/src/helpers/nrf52/SerialBLEInterface.h index de1030548f..a84b0d8e7b 100644 --- a/src/helpers/nrf52/SerialBLEInterface.h +++ b/src/helpers/nrf52/SerialBLEInterface.h @@ -15,6 +15,8 @@ class SerialBLEInterface : public BaseSerialInterface { uint16_t _conn_handle; unsigned long _last_health_check; unsigned long _last_retry_attempt; + unsigned long _last_led_blink; + bool _led_state; struct Frame { uint8_t len; @@ -49,6 +51,8 @@ class SerialBLEInterface : public BaseSerialInterface { _conn_handle = BLE_CONN_HANDLE_INVALID; _last_health_check = 0; _last_retry_attempt = 0; + _last_led_blink = 0; + _led_state = false; send_queue_len = 0; recv_queue_len = 0; }