Files
MeshCore/examples/companion_radio/CompanionBluetooth.h
mikecarper 071ca663c2 Add guarded Bluetooth CLI on/off with force override
Add get bluetooth and set bluetooth on|off, with ble aliases. Require another
active management connection before disabling Bluetooth unless off has a
trailing force argument. Keep the toggle local to the current boot.

Drain Bluetooth replies before disconnecting and recheck the remaining
connection before applying a normal shutdown. Enabling Bluetooth cancels a
pending shutdown. Document the commands and add compiled regression coverage
to CI for native USB, HWCDC, UART, network clients, force, and timer rollover.

Validation: CLI, Bluetooth, and USB regression tests passed. XIAO ESP32-S3
and RAK4631 Full Companion builds passed RAM, flash, and capability checks.
2026-09-14 23:02:54 -07:00

48 lines
1.9 KiB
C

#pragma once
#include <stddef.h>
#include <string.h>
enum class CompanionBluetoothCommandSource { Other, Terminal, Framed };
enum class CompanionBluetoothCommand { None, Get, On, Off, ForceOff, Invalid };
inline const char* skipBluetoothCommandSpace(const char* text) {
while (*text == ' ' || *text == '\t') ++text;
return text;
}
inline bool bluetoothCommandWord(const char* text, const char* word) {
const size_t length = strlen(word);
return strncmp(text, word, length) == 0
&& *skipBluetoothCommandSpace(text + length) == 0;
}
inline CompanionBluetoothCommand parseCompanionBluetoothCommand(const char* text) {
if (!text) return CompanionBluetoothCommand::None;
text = skipBluetoothCommandSpace(text);
if (bluetoothCommandWord(text, "get bluetooth")
|| bluetoothCommandWord(text, "get ble")) return CompanionBluetoothCommand::Get;
const char* value = nullptr;
const char* const prefixes[] = {"set bluetooth", "set ble"};
for (const char* prefix : prefixes) {
const size_t length = strlen(prefix);
if (strncmp(text, prefix, length) == 0
&& (text[length] == 0 || text[length] == ' ' || text[length] == '\t')) {
value = skipBluetoothCommandSpace(text + length);
break;
}
}
if (!value) return CompanionBluetoothCommand::None;
if (bluetoothCommandWord(value, "on")) return CompanionBluetoothCommand::On;
if (bluetoothCommandWord(value, "off")) return CompanionBluetoothCommand::Off;
if (strncmp(value, "off", 3) == 0 && (value[3] == ' ' || value[3] == '\t')
&& bluetoothCommandWord(skipBluetoothCommandSpace(value + 3), "force")) {
return CompanionBluetoothCommand::ForceOff;
}
return CompanionBluetoothCommand::Invalid;
}
bool handleCompanionBluetoothCommand(
const char* command, char* reply, size_t reply_size,
CompanionBluetoothCommandSource source = CompanionBluetoothCommandSource::Other);