Refresh nRF52 Companion BLE name without reboot
This commit is contained in:
1 parent
a569f55dc7
commit
960936183c
4 files changed
+86
-16
No files matched your search
@@ -6663,11 +6663,19 @@ bool MyMesh::applyAndSaveBluetoothName(const char* value, char* reply,
|
||||
|
||||
if (use_default) {
|
||||
snprintf(reply, reply_size,
|
||||
#if defined(NRF52_PLATFORM)
|
||||
"OK - Bluetooth name follows %s<node name>; advertising refreshes after disconnect",
|
||||
#else
|
||||
"OK - Bluetooth name follows %s<node name>; reboot required",
|
||||
#endif
|
||||
BLE_NAME_PREFIX);
|
||||
} else {
|
||||
snprintf(reply, reply_size,
|
||||
#if defined(NRF52_PLATFORM)
|
||||
"OK - Bluetooth name saved as '%s'; advertising refreshes after disconnect", value);
|
||||
#else
|
||||
"OK - Bluetooth name saved as '%s'; reboot required", value);
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2323,6 +2323,24 @@ void halt() {
|
||||
startCompanionBluetooth();
|
||||
}
|
||||
|
||||
#if defined(NRF52_PLATFORM)
|
||||
static void serviceCompanionBluetoothName() {
|
||||
if (!companion_bluetooth_initialized) return;
|
||||
static uint32_t last_check = 0;
|
||||
const uint32_t now = millis();
|
||||
if ((uint32_t)(now - last_check) < 250) return;
|
||||
last_check = now;
|
||||
|
||||
const CompanionNodePrefs* prefs = the_mesh.getNodePrefs();
|
||||
if (prefs == nullptr) return;
|
||||
const bool custom =
|
||||
mesh::companion::hasCustomBluetoothName(prefs->bluetooth_name);
|
||||
bluetooth_interface.refreshName(custom ? "" : BLE_NAME_PREFIX,
|
||||
custom ? prefs->bluetooth_name
|
||||
: prefs->node_name);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void serviceCompanionBluetoothIdentity() {
|
||||
if (!companion_bluetooth_initialized) return;
|
||||
|
||||
@@ -3472,5 +3490,8 @@ void loop() {
|
||||
#endif
|
||||
serviceCompanionBluetoothIdentity();
|
||||
serviceCompanionBluetoothControl();
|
||||
#if defined(NRF52_PLATFORM)
|
||||
serviceCompanionBluetoothName();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
@@ -30,6 +30,27 @@
|
||||
|
||||
static SerialBLEInterface* instance = nullptr;
|
||||
|
||||
static bool formatDeviceName(char* dest, size_t capacity,
|
||||
const char* prefix, const char* name) {
|
||||
if (dest == nullptr || capacity == 0 || prefix == nullptr || name == nullptr) {
|
||||
return false;
|
||||
}
|
||||
char resolved_name[32];
|
||||
const char* suffix = name;
|
||||
if (strcmp(name, "@@MAC") == 0) {
|
||||
ble_gap_addr_t addr;
|
||||
if (sd_ble_gap_addr_get(&addr) == NRF_SUCCESS) {
|
||||
snprintf(resolved_name, sizeof(resolved_name),
|
||||
"%02X%02X%02X%02X%02X%02X",
|
||||
addr.addr[5], addr.addr[4], addr.addr[3], addr.addr[2],
|
||||
addr.addr[1], addr.addr[0]);
|
||||
suffix = resolved_name;
|
||||
}
|
||||
}
|
||||
const int length = snprintf(dest, capacity, "%s%s", prefix, suffix);
|
||||
return length >= 0 && length < (int)capacity;
|
||||
}
|
||||
|
||||
#if defined(COMPANION_RADIO_FULL) && COMPANION_RADIO_FULL
|
||||
// Bluefruit's bonded CCCD flash write resets some nRF52 Full Companions.
|
||||
// Retain the small SoftDevice system-attribute image in RAM for reconnects
|
||||
@@ -616,22 +637,8 @@ bool SerialBLEInterface::begin(const char* prefix, const char* name,
|
||||
}
|
||||
}
|
||||
|
||||
char resolved_name[32];
|
||||
const char* suffix = name;
|
||||
if (strcmp(name, "@@MAC") == 0) {
|
||||
ble_gap_addr_t addr;
|
||||
if (sd_ble_gap_addr_get(&addr) == NRF_SUCCESS) {
|
||||
snprintf(resolved_name, sizeof(resolved_name),
|
||||
"%02X%02X%02X%02X%02X%02X",
|
||||
addr.addr[5], addr.addr[4], addr.addr[3], addr.addr[2],
|
||||
addr.addr[1], addr.addr[0]);
|
||||
suffix = resolved_name;
|
||||
}
|
||||
}
|
||||
char dev_name[32+16];
|
||||
const int dev_name_len = snprintf(dev_name, sizeof(dev_name), "%s%s",
|
||||
prefix, suffix);
|
||||
if (dev_name_len < 0 || dev_name_len >= (int)sizeof(dev_name)) {
|
||||
char dev_name[sizeof(_active_name)];
|
||||
if (!formatDeviceName(dev_name, sizeof(dev_name), prefix, name)) {
|
||||
strncpy(_begin_failure, "Bluetooth device name is too long",
|
||||
sizeof(_begin_failure) - 1);
|
||||
_begin_failure[sizeof(_begin_failure) - 1] = 0;
|
||||
@@ -660,6 +667,7 @@ bool SerialBLEInterface::begin(const char* prefix, const char* name,
|
||||
|
||||
Bluefruit.setTxPower(BLE_TX_POWER);
|
||||
Bluefruit.setName(dev_name);
|
||||
memcpy(_active_name, dev_name, strlen(dev_name) + 1);
|
||||
|
||||
Bluefruit.Security.setMITM(true);
|
||||
Bluefruit.Security.setPIN(charpin);
|
||||
@@ -752,6 +760,35 @@ bool SerialBLEInterface::begin(const char* prefix, const char* name,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SerialBLEInterface::refreshName(const char* prefix, const char* name) {
|
||||
if (!_begin_ready || _conn_handle != BLE_CONN_HANDLE_INVALID) return false;
|
||||
|
||||
char desired[sizeof(_active_name)];
|
||||
if (!formatDeviceName(desired, sizeof(desired), prefix, name)) return false;
|
||||
if (strcmp(desired, _active_name) == 0) return true;
|
||||
|
||||
const bool was_advertising = isAdvertising();
|
||||
if (was_advertising && !Bluefruit.Advertising.stop()) return false;
|
||||
|
||||
Bluefruit.setName(desired);
|
||||
char actual[sizeof(_active_name)];
|
||||
const size_t actual_len = Bluefruit.getName(actual, sizeof(actual));
|
||||
if (actual_len != strlen(desired)
|
||||
|| memcmp(actual, desired, actual_len) != 0) {
|
||||
if (was_advertising) startAdvertising("advertising failed after name refresh");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Directed bonded-only advertisements have no payload to refresh.
|
||||
if (!_bonded_only) {
|
||||
Bluefruit.ScanResponse.clearData();
|
||||
Bluefruit.ScanResponse.addName();
|
||||
}
|
||||
memcpy(_active_name, desired, strlen(desired) + 1);
|
||||
if (was_advertising) startAdvertising("advertising failed after name refresh");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SerialBLEInterface::takeSuccessfulConnection(
|
||||
mesh::companion::BluetoothPeerIdentity* peer) {
|
||||
if (!_successfulConnectionPending.load(std::memory_order_acquire)) {
|
||||
|
||||
@@ -65,6 +65,7 @@ class SerialBLEInterface : public BaseSerialInterface {
|
||||
bool _begin_attempted = false;
|
||||
bool _begin_ready = false;
|
||||
char _begin_failure[96] = {};
|
||||
char _active_name[48] = {};
|
||||
bool _isDeviceConnected;
|
||||
uint16_t _conn_handle;
|
||||
unsigned long _last_health_check;
|
||||
@@ -166,6 +167,9 @@ public:
|
||||
bool clear_bonds = false, bool stealth_pair_once = false,
|
||||
const mesh::companion::BluetoothPeerIdentity*
|
||||
bonded_only_peer = nullptr);
|
||||
// Refresh the GAP and scan-response name after a saved node/Bluetooth name
|
||||
// changes. A connected phone is left alone; the next idle pass applies it.
|
||||
bool refreshName(const char* prefix, const char* name);
|
||||
// Kept after a failed begin so a normal Companion terminal can report the
|
||||
// cause even when early USB logging was not available.
|
||||
const char* beginFailure() const { return _begin_failure; }
|
||||
|
||||
Reference in new issue
Block a user