Expand and harden full companion profiles
This commit is contained in:
1 parent
f2d4ffbb7e
commit
dc92ee61ef
44 files changed
+1522
-226
No files matched your search
@@ -1376,6 +1376,9 @@ MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMe
|
||||
command_radio_cr = 0;
|
||||
command_radio_repeat = 0;
|
||||
command_radio_apply_deadline = 0;
|
||||
#if MESH_USB_LOGGING_AVAILABLE
|
||||
_usb_logging_reboot_at = 0;
|
||||
#endif
|
||||
#if defined(COMPANION_RADIO_FULL)
|
||||
_temp_radio_set_at = 0;
|
||||
_temp_radio_revert_at = 0;
|
||||
@@ -1437,7 +1440,13 @@ MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMe
|
||||
_prefs.powersaving_enabled = 1;
|
||||
_prefs.powersaving_policy_version = 0;
|
||||
_prefs.wifi_enabled = 1;
|
||||
#if defined(COMPANION_RADIO_FULL) && defined(MESH_DUAL_CDC_LOGGING)
|
||||
// Keep the primary CDC stream exclusively framed unless the owner opts in
|
||||
// to the separate plaintext logging interface and reboots.
|
||||
_prefs.usb_logging_enabled = 0;
|
||||
#else
|
||||
_prefs.usb_logging_enabled = 1;
|
||||
#endif
|
||||
recalcRxPowerSavingFromLevel(_prefs.rx_ps_level, _prefs.sf, _prefs.bw,
|
||||
_prefs.rx_ps_preamble, &_prefs.rx_ps_rx_us,
|
||||
&_prefs.rx_ps_sleep_us);
|
||||
@@ -1457,6 +1466,7 @@ MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMe
|
||||
void MyMesh::begin(bool has_display, bool radio_available) {
|
||||
_radio_available = radio_available;
|
||||
setRadioAvailable(radio_available);
|
||||
initializeContactStorage();
|
||||
initializeOfflineQueue();
|
||||
BaseChatMesh::begin();
|
||||
|
||||
@@ -1545,7 +1555,11 @@ void MyMesh::begin(bool has_display, bool radio_available) {
|
||||
_store->savePrefs(_prefs, sensors.node_lat, sensors.node_lon);
|
||||
}
|
||||
#if MESH_USB_LOGGING_AVAILABLE
|
||||
mesh::setUsbLoggingEnabled(_prefs.usb_logging_enabled != 0);
|
||||
const bool usb_logging_enabled = _prefs.usb_logging_enabled != 0;
|
||||
mesh::setUsbLoggingEnabled(usb_logging_enabled);
|
||||
if (!mesh::saveUsbLoggingBootPreference(usb_logging_enabled)) {
|
||||
MESH_DEBUG_PRINTLN("Unable to save next-boot USB logging interface state");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BLE_PIN_CODE // 123456 by default
|
||||
@@ -4925,8 +4939,11 @@ void MyMesh::handleTerminalCommand(char* command) {
|
||||
_prefs.powersaving_enabled ? "on" : "off");
|
||||
#if MESH_USB_LOGGING_AVAILABLE
|
||||
} else if (strcmp(command, "get usb.logging") == 0) {
|
||||
terminalOutput().printf(" usb.logging %s\r\n",
|
||||
mesh::isUsbLoggingEnabled() ? "on" : "off");
|
||||
terminalOutput().printf(
|
||||
" usb.logging %s%s\r\n",
|
||||
mesh::isUsbLoggingEnabled() ? "on" : "off",
|
||||
mesh::usbLoggingInterfaceRestartRequired()
|
||||
? " (reboot required to change USB interfaces)" : "");
|
||||
#endif
|
||||
} else if (strncmp(command, "powersaving ", 12) == 0) {
|
||||
char reply[160];
|
||||
@@ -4978,18 +4995,49 @@ void MyMesh::handleTerminalCommand(char* command) {
|
||||
|| config[11] == '\t')) {
|
||||
const char* value = config + 11;
|
||||
while (*value == ' ' || *value == '\t') value++;
|
||||
if (strcmp(value, "on") != 0 && strcmp(value, "off") != 0) {
|
||||
terminalOutput().print(" ERROR: use set usb.logging <on|off>\r\n");
|
||||
bool enabled = false;
|
||||
bool reboot_if_needed = false;
|
||||
bool valid = true;
|
||||
if (strcmp(value, "on") == 0) {
|
||||
enabled = true;
|
||||
} else if (strcmp(value, "off") == 0) {
|
||||
enabled = false;
|
||||
} else if (strcmp(value, "on reboot") == 0) {
|
||||
enabled = true;
|
||||
reboot_if_needed = true;
|
||||
} else if (strcmp(value, "off reboot") == 0) {
|
||||
enabled = false;
|
||||
reboot_if_needed = true;
|
||||
} else {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
terminalOutput().print(
|
||||
" ERROR: use set usb.logging <on|off> [reboot]\r\n");
|
||||
} else {
|
||||
const bool enabled = strcmp(value, "on") == 0;
|
||||
_prefs.usb_logging_enabled = enabled ? 1 : 0;
|
||||
mesh::setUsbLoggingEnabled(enabled);
|
||||
if (savePrefs()) {
|
||||
terminalOutput().printf(" OK - USB logging %s (saved)\r\n",
|
||||
enabled ? "on" : "off");
|
||||
} else {
|
||||
if (!savePrefs()) {
|
||||
terminalOutput().print(
|
||||
" ERROR: USB logging changed for this boot but save failed\r\n");
|
||||
} else if (!mesh::saveUsbLoggingBootPreference(enabled)) {
|
||||
terminalOutput().print(
|
||||
" ERROR: setting saved, but next-boot USB interface state could not be saved\r\n");
|
||||
} else if (mesh::usbLoggingInterfaceRestartRequired()) {
|
||||
if (reboot_if_needed) {
|
||||
terminalOutput().printf(
|
||||
" OK - USB logging %s (saved); rebooting to change USB interfaces\r\n",
|
||||
enabled ? "on" : "off");
|
||||
_usb_logging_reboot_at = futureMillis(1000);
|
||||
} else {
|
||||
terminalOutput().printf(
|
||||
" OK - USB logging %s (saved); reboot required to change USB interfaces\r\n",
|
||||
enabled ? "on" : "off");
|
||||
}
|
||||
} else {
|
||||
terminalOutput().printf(" OK - USB logging %s (saved)\r\n",
|
||||
enabled ? "on" : "off");
|
||||
}
|
||||
}
|
||||
} else
|
||||
@@ -5090,7 +5138,7 @@ void MyMesh::handleTerminalCommand(char* command) {
|
||||
terminalOutput().print(" powersaving [on|off]\r\n");
|
||||
#if MESH_USB_LOGGING_AVAILABLE
|
||||
terminalOutput().print(" get usb.logging\r\n");
|
||||
terminalOutput().print(" set usb.logging <on|off>\r\n");
|
||||
terminalOutput().print(" set usb.logging <on|off> [reboot]\r\n");
|
||||
#endif
|
||||
#if defined(ESP32) && defined(WIFI_SSID)
|
||||
terminalOutput().print(" get wifi.powersave\r\n");
|
||||
@@ -5361,6 +5409,14 @@ void MyMesh::checkSerialInterface() {
|
||||
}
|
||||
|
||||
void MyMesh::loop() {
|
||||
#if MESH_USB_LOGGING_AVAILABLE
|
||||
if (_usb_logging_reboot_at != 0
|
||||
&& millisHasNowPassed(_usb_logging_reboot_at)) {
|
||||
_usb_logging_reboot_at = 0;
|
||||
board.reboot();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if defined(COMPANION_RADIO_FULL)
|
||||
serviceTempRadio();
|
||||
#endif
|
||||
|
||||
@@ -415,6 +415,9 @@ private:
|
||||
uint8_t command_radio_cr;
|
||||
uint8_t command_radio_repeat;
|
||||
unsigned long command_radio_apply_deadline;
|
||||
#if MESH_USB_LOGGING_AVAILABLE
|
||||
unsigned long _usb_logging_reboot_at;
|
||||
#endif
|
||||
#if defined(COMPANION_RADIO_FULL)
|
||||
unsigned long _temp_radio_set_at;
|
||||
unsigned long _temp_radio_revert_at;
|
||||
|
||||
@@ -12,6 +12,13 @@
|
||||
#else
|
||||
#define COMPANION_IDF_PM_AVAILABLE 0
|
||||
#endif
|
||||
#if defined(BLE_PIN_CODE) && !CONFIG_IDF_TARGET_ESP32C6 \
|
||||
&& (defined(CONFIG_BT_CTRL_MODEM_SLEEP) \
|
||||
|| defined(CONFIG_BTDM_CTRL_MODEM_SLEEP))
|
||||
#define COMPANION_BT_MODEM_SLEEP_AVAILABLE 1
|
||||
#else
|
||||
#define COMPANION_BT_MODEM_SLEEP_AVAILABLE 0
|
||||
#endif
|
||||
#if defined(COMPANION_RADIO_FULL)
|
||||
#include <esp_heap_caps.h>
|
||||
#endif
|
||||
@@ -180,6 +187,22 @@ static uint32_t companionNominalCpuMhz() {
|
||||
#endif
|
||||
}
|
||||
|
||||
#if COMPANION_BT_MODEM_SLEEP_AVAILABLE
|
||||
static void applyCompanionBluetoothSleep(bool enabled,
|
||||
bool allow_uninitialized) {
|
||||
esp_err_t result = enabled ? esp_bt_sleep_enable()
|
||||
: esp_bt_sleep_disable();
|
||||
if (result == ESP_OK
|
||||
|| (allow_uninitialized && result == ESP_ERR_INVALID_STATE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mesh::usbLoggingPort().printf("Bluetooth sleep %s failed: %s\r\n",
|
||||
enabled ? "enable" : "disable",
|
||||
esp_err_to_name(result));
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool applyCompanionPowerSaving(bool enabled) {
|
||||
const uint32_t nominal_mhz = companionNominalCpuMhz();
|
||||
const uint32_t max_mhz = enabled && nominal_mhz > 80 ? 80 : nominal_mhz;
|
||||
@@ -224,14 +247,13 @@ static bool applyCompanionPowerSaving(bool enabled) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BLE_PIN_CODE) && !CONFIG_IDF_TARGET_ESP32C6
|
||||
esp_err_t bt_result = enabled ? esp_bt_sleep_enable()
|
||||
: esp_bt_sleep_disable();
|
||||
if (bt_result != ESP_OK) {
|
||||
mesh::usbLoggingPort().printf("Bluetooth sleep %s failed: %s\r\n",
|
||||
enabled ? "enable" : "disable",
|
||||
esp_err_to_name(bt_result));
|
||||
}
|
||||
#if COMPANION_BT_MODEM_SLEEP_AVAILABLE
|
||||
// Power saving is applied before the wireless interfaces are constructed.
|
||||
// An uninitialized controller is expected here; apply the saved setting
|
||||
// again immediately after BLEDevice::init() below. Some prebuilt ESP-IDF
|
||||
// targets omit Bluetooth modem sleep entirely; the compile-time guard avoids
|
||||
// calling an API which can only return ESP_ERR_NOT_SUPPORTED in those builds.
|
||||
applyCompanionBluetoothSleep(enabled, true);
|
||||
#endif
|
||||
|
||||
#if COMPANION_IDF_PM_AVAILABLE
|
||||
@@ -945,32 +967,47 @@ void halt() {
|
||||
|
||||
#if defined(BLE_PIN_CODE)
|
||||
static bool companion_bluetooth_initialized = false;
|
||||
#if defined(ESP32) && defined(COMPANION_RADIO_FULL) && defined(WIFI_SSID)
|
||||
static uint32_t companion_bluetooth_start_at = 0;
|
||||
#endif
|
||||
static constexpr uint32_t COMPANION_BLUETOOTH_RETRY_MS = 5000UL;
|
||||
|
||||
static void scheduleCompanionBluetoothRetry() {
|
||||
companion_bluetooth_start_at = millis() + COMPANION_BLUETOOTH_RETRY_MS;
|
||||
if (companion_bluetooth_start_at == 0) companion_bluetooth_start_at = 1;
|
||||
}
|
||||
|
||||
static void startCompanionBluetooth() {
|
||||
if (companion_bluetooth_initialized) return;
|
||||
companion_bluetooth_start_at = 0;
|
||||
|
||||
mesh::usbLoggingPort().println("Companion: starting Bluetooth");
|
||||
bluetooth_interface.begin(BLE_NAME_PREFIX, the_mesh.getNodePrefs()->node_name,
|
||||
the_mesh.getBLEPin());
|
||||
if (!interface_manager.addInterface(InterfaceType::Bluetooth,
|
||||
&bluetooth_interface)) {
|
||||
mesh::usbLoggingPort().println(
|
||||
"Companion: no interface slot available for Bluetooth");
|
||||
"Companion: no interface slot available for Bluetooth; retrying");
|
||||
scheduleCompanionBluetoothRetry();
|
||||
return;
|
||||
}
|
||||
if (!bluetooth_interface.begin(BLE_NAME_PREFIX,
|
||||
the_mesh.getNodePrefs()->node_name,
|
||||
the_mesh.getBLEPin())) {
|
||||
interface_manager.removeInterface(&bluetooth_interface);
|
||||
mesh::usbLoggingPort().println(
|
||||
"Companion: Bluetooth initialization failed; retrying in 5 seconds");
|
||||
scheduleCompanionBluetoothRetry();
|
||||
return;
|
||||
}
|
||||
#if defined(ESP32_PLATFORM) && COMPANION_BT_MODEM_SLEEP_AVAILABLE
|
||||
applyCompanionBluetoothSleep(
|
||||
the_mesh.getNodePrefs()->powersaving_enabled != 0, false);
|
||||
#endif
|
||||
companion_bluetooth_initialized = true;
|
||||
if (interface_manager.isEnabled()) bluetooth_interface.enable();
|
||||
}
|
||||
|
||||
static void serviceDeferredCompanionBluetooth() {
|
||||
if (companion_bluetooth_initialized) return;
|
||||
#if defined(ESP32) && defined(COMPANION_RADIO_FULL) && defined(WIFI_SSID)
|
||||
if (companion_bluetooth_start_at == 0
|
||||
|| (int32_t)(millis() - companion_bluetooth_start_at) < 0) return;
|
||||
#endif
|
||||
startCompanionBluetooth();
|
||||
}
|
||||
#endif
|
||||
@@ -1109,6 +1146,11 @@ void setup() {
|
||||
#error "need to define filesystem"
|
||||
#endif
|
||||
|
||||
// nRF52 cannot decide whether to add its optional logging CDC interface
|
||||
// until the saved Companion preferences above are available. ESP32 already
|
||||
// fixed its descriptor from the early NVS mirror, so this is harmless there.
|
||||
mesh::beginUsbLoggingPort();
|
||||
|
||||
// Load WiFi state before bringing up either wireless stack.
|
||||
#ifdef WIFI_SSID
|
||||
loadCompanionWiFiCredentials();
|
||||
@@ -1118,6 +1160,14 @@ void setup() {
|
||||
logFullCompanionMemory("before interfaces");
|
||||
#endif
|
||||
|
||||
// NimBLE must reserve its internal controller/host memory before WiFi starts
|
||||
// its AP and WebConfig services. Starting WiFi first can leave plenty of total
|
||||
// heap but no internal block large enough for nimble_port_init().
|
||||
#if defined(BLE_PIN_CODE) && defined(ESP32) \
|
||||
&& defined(COMPANION_RADIO_FULL) && defined(WIFI_SSID)
|
||||
startCompanionBluetooth();
|
||||
#endif
|
||||
|
||||
// add wifi interface
|
||||
#ifdef WIFI_SSID
|
||||
WiFi.onEvent([](WiFiEvent_t event, WiFiEventInfo_t info){
|
||||
@@ -1147,16 +1197,11 @@ void setup() {
|
||||
logFullCompanionMemory("after WiFi start");
|
||||
#endif
|
||||
|
||||
// The Full ESP32 profile starts WiFi/WebConfig first, gives its AP/server two
|
||||
// seconds to settle and reserve heap, then starts BLE from loop(). Other BLE
|
||||
// companions keep their existing immediate startup.
|
||||
// Full ESP32 WiFi+BLE companions started BLE above so its controller memory
|
||||
// could not be fragmented by WiFi. Other BLE companions start here.
|
||||
#if defined(BLE_PIN_CODE)
|
||||
#if defined(ESP32) && defined(COMPANION_RADIO_FULL) && defined(WIFI_SSID)
|
||||
companion_bluetooth_start_at = millis() + 2000UL;
|
||||
if (companion_bluetooth_start_at == 0) companion_bluetooth_start_at = 1;
|
||||
mesh::usbLoggingPort().println(
|
||||
"Companion: Bluetooth starts in 2 seconds");
|
||||
#else
|
||||
#if !(defined(ESP32) && defined(COMPANION_RADIO_FULL) \
|
||||
&& defined(WIFI_SSID))
|
||||
startCompanionBluetooth();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Reference in new issue
Block a user