Fix Cascade power saving, USB Companion, and mOTA flows
This commit is contained in:
1 parent
0d4274ceea
commit
818f610ba3
59 files changed
+3946
-2437
No files matched your search
@@ -290,6 +290,12 @@ void MyMesh::writeContactRespFrame(uint8_t code, const ContactInfo &contact) {
|
||||
_serial->writeFrame(out_frame, i);
|
||||
}
|
||||
|
||||
void MyMesh::stopContactsIterator() {
|
||||
if (!_iter_started) return;
|
||||
_iter_started = false;
|
||||
if (_serial != NULL) _serial->unlockReplyRoute();
|
||||
}
|
||||
|
||||
void MyMesh::updateContactFromFrame(ContactInfo &contact, uint32_t& last_mod, const uint8_t *frame, int len) {
|
||||
int i = 0;
|
||||
uint8_t code = frame[i++]; // eg. CMD_ADD_UPDATE_CONTACT
|
||||
@@ -2368,6 +2374,10 @@ void MyMesh::startInterface(BaseSerialInterface &serial) {
|
||||
serial.enable();
|
||||
}
|
||||
|
||||
void MyMesh::cancelSerialResponseStream() {
|
||||
stopContactsIterator();
|
||||
}
|
||||
|
||||
void MyMesh::handleCmdFrame(size_t len) {
|
||||
if (len == 0) {
|
||||
writeErrFrame(ERR_CODE_ILLEGAL_ARG);
|
||||
@@ -2401,7 +2411,7 @@ void MyMesh::handleCmdFrame(size_t len) {
|
||||
cmd_frame[len] = 0; // make app_name null terminated
|
||||
MESH_DEBUG_PRINTLN("App %s connected", app_name);
|
||||
|
||||
_iter_started = false; // stop any left-over ContactsIterator
|
||||
stopContactsIterator(); // stop any left-over ContactsIterator
|
||||
cancelPendingRadioParamApply();
|
||||
int i = 0;
|
||||
out_frame[i++] = RESP_CODE_SELF_INFO;
|
||||
@@ -2613,16 +2623,18 @@ void MyMesh::handleCmdFrame(size_t len) {
|
||||
_iter_filter_since = 0;
|
||||
}
|
||||
|
||||
// CONTACTS_START, every CONTACT, and END_OF_CONTACTS are one response
|
||||
// transaction. Keep them on the transport which requested the list.
|
||||
_serial->lockReplyRoute();
|
||||
_iter = startContactsIterator();
|
||||
_iter_started = true;
|
||||
_most_recent_lastmod = 0;
|
||||
|
||||
uint8_t reply[5];
|
||||
reply[0] = RESP_CODE_CONTACTS_START;
|
||||
uint32_t count = getNumContacts(); // total, NOT filtered count
|
||||
memcpy(&reply[1], &count, 4);
|
||||
_serial->writeFrame(reply, 5);
|
||||
|
||||
// start iterator
|
||||
_iter = startContactsIterator();
|
||||
_iter_started = true;
|
||||
_most_recent_lastmod = 0;
|
||||
}
|
||||
} else if (cmd_frame[0] == CMD_SET_ADVERT_NAME && len >= 2) {
|
||||
int nlen = len - 1;
|
||||
@@ -2970,7 +2982,7 @@ void MyMesh::handleCmdFrame(size_t len) {
|
||||
self_id = identity;
|
||||
writeOKFrame();
|
||||
// re-load contacts, to invalidate ecdh shared_secrets
|
||||
_iter_started = false;
|
||||
stopContactsIterator();
|
||||
resetContacts();
|
||||
_store->loadContacts(this);
|
||||
updateGpsTelemetryPolicy();
|
||||
@@ -4482,6 +4494,17 @@ void MyMesh::handleTerminalCommand(char* command) {
|
||||
char reply[160];
|
||||
applyAndSavePowerSaving(command + 12, reply);
|
||||
Serial.printf(" %s\r\n", reply);
|
||||
} else if (strcmp(command, "get radio.rxps") == 0) {
|
||||
if (!radio_driver.supportsRxPowerSaving()) {
|
||||
Serial.print(" ERROR: RX power saving is unsupported on this radio\r\n");
|
||||
} else {
|
||||
Serial.printf(" radio.rxps %s,level=%u,preamble=%u,rx=%lu,sleep=%lu\r\n",
|
||||
_prefs.rx_powersaving_enabled ? "on" : "off",
|
||||
(unsigned)_prefs.rx_ps_level,
|
||||
(unsigned)_prefs.rx_ps_preamble,
|
||||
(unsigned long)_prefs.rx_ps_rx_us,
|
||||
(unsigned long)_prefs.rx_ps_sleep_us);
|
||||
}
|
||||
} else if (strcmp(command, "get radio.fem.rxgain") == 0) {
|
||||
if (!board.canControlLoRaFemLna()) {
|
||||
Serial.print(" ERROR: FEM RX gain control is unsupported on this board\r\n");
|
||||
@@ -4502,6 +4525,10 @@ void MyMesh::handleTerminalCommand(char* command) {
|
||||
char reply[160];
|
||||
applyAndSavePowerSaving(config + 12, reply);
|
||||
Serial.printf(" %s\r\n", reply);
|
||||
} else if (strncmp(config, "radio.rxps ", 11) == 0) {
|
||||
char reply[160];
|
||||
applyAndSaveRxPowerSaving(config + 11, reply);
|
||||
Serial.printf(" %s\r\n", reply);
|
||||
} else if (strncmp(config, "af ", 3) == 0) {
|
||||
_prefs.airtime_factor = constrain((float)atof(config + 3), 0.0f, 9.0f);
|
||||
savePrefs();
|
||||
@@ -4564,6 +4591,8 @@ void MyMesh::handleTerminalCommand(char* command) {
|
||||
Serial.print("Commands:\r\n");
|
||||
Serial.print(" set {name|lat|lon|freq|tx|af} {value}\r\n");
|
||||
Serial.print(" powersaving [on|off]\r\n");
|
||||
Serial.print(" get radio.rxps\r\n");
|
||||
Serial.print(" set radio.rxps <off|on|level 1-10 [preamble 16|32]|rx_us sleep_us>\r\n");
|
||||
Serial.print(" get radio.fem.rxgain\r\n");
|
||||
Serial.print(" set radio.fem.rxgain <on|off>\r\n");
|
||||
Serial.print(" get radio.fem.txgain\r\n");
|
||||
@@ -4780,7 +4809,7 @@ void MyMesh::checkCLIRescueCmd() {
|
||||
void MyMesh::checkSerialInterface() {
|
||||
size_t len = _serial->checkRecvFrame(cmd_frame);
|
||||
if (!_serial->isConnected()) {
|
||||
_iter_started = false;
|
||||
stopContactsIterator();
|
||||
cancelPendingRadioParamApply();
|
||||
return;
|
||||
}
|
||||
@@ -4803,7 +4832,7 @@ void MyMesh::checkSerialInterface() {
|
||||
memcpy(&out_frame[1], &_most_recent_lastmod,
|
||||
4); // include the most recent lastmod, so app can update their 'since'
|
||||
_serial->writeFrame(out_frame, 5);
|
||||
_iter_started = false;
|
||||
stopContactsIterator();
|
||||
}
|
||||
//} else if (!_serial->isWriteBusy()) {
|
||||
// checkConnections(); // TODO - deprecate the 'Connections' stuff
|
||||
|
||||
@@ -116,6 +116,7 @@ public:
|
||||
void activateRadio();
|
||||
bool isRadioReady() const { return _radio_available; }
|
||||
void startInterface(BaseSerialInterface &serial);
|
||||
void cancelSerialResponseStream();
|
||||
|
||||
const char *getNodeName();
|
||||
CompanionNodePrefs *getNodePrefs();
|
||||
@@ -268,6 +269,7 @@ private:
|
||||
void writeErrFrame(uint8_t err_code);
|
||||
void writeDisabledFrame();
|
||||
void writeContactRespFrame(uint8_t code, const ContactInfo &contact);
|
||||
void stopContactsIterator();
|
||||
void updateContactFromFrame(ContactInfo &contact, uint32_t& last_mod, const uint8_t *frame, int len);
|
||||
void addToOfflineQueue(const uint8_t frame[], int len);
|
||||
int getFromOfflineQueue(uint8_t frame[]);
|
||||
|
||||
@@ -279,6 +279,7 @@ static bool isUsbTerminalDataConnected() {
|
||||
}
|
||||
|
||||
static void enterUsbTerminalMode() {
|
||||
the_mesh.cancelSerialResponseStream();
|
||||
usb_serial_interface.setPassthroughMode(true);
|
||||
clearUsbTerminalLine();
|
||||
usb_terminal_discard_line = false;
|
||||
@@ -318,6 +319,7 @@ static void leaveUsbMotaMode(bool acknowledge) {
|
||||
}
|
||||
|
||||
static void enterUsbMotaMode() {
|
||||
the_mesh.cancelSerialResponseStream();
|
||||
usb_serial_interface.setPassthroughMode(true);
|
||||
usb_mota_mode = true;
|
||||
usb_mota_line_len = 0;
|
||||
@@ -962,7 +964,8 @@ void setup() {
|
||||
// activity: a real client has to send us frames.
|
||||
usb_serial_interface.setConnectedCheck([]() {
|
||||
uint32_t last = usb_serial_interface.getLastFrameMillis();
|
||||
return (bool)Serial && last != 0 && (millis() - last) < USB_CLIENT_IDLE_TIMEOUT;
|
||||
return (bool)Serial && usb_serial_interface.hasReceivedFrame()
|
||||
&& (millis() - last) < USB_CLIENT_IDLE_TIMEOUT;
|
||||
});
|
||||
#elif (defined(ESP32) && defined(ARDUINO_USB_CDC_ON_BOOT) && ARDUINO_USB_CDC_ON_BOOT) \
|
||||
|| defined(NRF52_PLATFORM) || defined(RP2040_PLATFORM)
|
||||
@@ -1058,10 +1061,11 @@ void loop() {
|
||||
#endif
|
||||
|
||||
// USB power alone (for example, a wall charger) must not disable power
|
||||
// saving. Stay awake only while a computer has an active USB data session.
|
||||
// saving. Stay awake only while an enumerated USB host is attached.
|
||||
bool can_sleep = the_mesh.getNodePrefs()->powersaving_enabled
|
||||
&& !the_mesh.hasPendingWork();
|
||||
#if defined(NRF52_PLATFORM)
|
||||
#if defined(NRF52_PLATFORM) \
|
||||
|| (defined(ESP32_PLATFORM) && defined(ENABLE_USB_INTERFACE))
|
||||
can_sleep = can_sleep && !board.isUsbHostConnected();
|
||||
#endif
|
||||
if (can_sleep) {
|
||||
|
||||
@@ -3079,13 +3079,20 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
|
||||
_prefs.battery_alert_enabled = 0;
|
||||
_prefs.battery_alert_low_percent = BATTERY_ALERT_LOW_PERCENT_DEFAULT;
|
||||
_prefs.battery_alert_critical_percent = BATTERY_ALERT_CRITICAL_PERCENT_DEFAULT;
|
||||
_prefs.powersaving_enabled = DEFAULT_POWERSAVING_ENABLED ? 1 : 0;
|
||||
#ifdef WITH_MQTT_BRIDGE
|
||||
_prefs.agc_reset_interval = 7; // 28 seconds (secs/4) - prevents AGC drift on long-running observers
|
||||
#endif
|
||||
// Observer defaults (radio_watchdog, alert.*, snmp.*) moved to applyMQTTDefaults()
|
||||
// in MQTTDefaults.h - they live in /mqtt_prefs now, not NodePrefs.
|
||||
_prefs.rx_powersaving_enabled = DEFAULT_RXPS_ENABLED ? 1 : 0;
|
||||
_prefs.rx_ps_level = DEFAULT_RXPS_LEVEL;
|
||||
_prefs.rx_ps_preamble = DEFAULT_RXPS_PREAMBLE;
|
||||
_prefs.rx_ps_rx_us = RX_POWERSAVING_DEFAULT_RX_US;
|
||||
_prefs.rx_ps_sleep_us = RX_POWERSAVING_DEFAULT_SLEEP_US;
|
||||
recalcRxPowerSavingFromLevel(_prefs.rx_ps_level, _prefs.sf, _prefs.bw,
|
||||
_prefs.rx_ps_preamble, &_prefs.rx_ps_rx_us,
|
||||
&_prefs.rx_ps_sleep_us);
|
||||
|
||||
// bridge defaults
|
||||
_prefs.bridge_enabled = 1; // enabled
|
||||
@@ -9574,6 +9581,7 @@ void MyMesh::getNodeSnapshot(WebConfigServer::NodeSnapshot& s) {
|
||||
s.rx_ps_preamble = _prefs.rx_ps_preamble;
|
||||
s.rx_ps_rx_us = _prefs.rx_ps_rx_us;
|
||||
s.rx_ps_sleep_us = _prefs.rx_ps_sleep_us;
|
||||
s.power_saving = _prefs.powersaving_enabled;
|
||||
s.repeat = !_prefs.disable_fwd;
|
||||
s.advert_interval = _prefs.advert_interval * 2;
|
||||
s.flood_advert_interval = _prefs.flood_advert_interval;
|
||||
@@ -9585,7 +9593,8 @@ void MyMesh::getNodeSnapshot(WebConfigServer::NodeSnapshot& s) {
|
||||
| WebConfigServer::CAP_DELAYS | WebConfigServer::CAP_CAD
|
||||
| WebConfigServer::CAP_RX_GAIN | WebConfigServer::CAP_REPEAT
|
||||
| WebConfigServer::CAP_ADVERT | WebConfigServer::CAP_FLOOD
|
||||
| WebConfigServer::CAP_LOOP | WebConfigServer::CAP_WIFI_POWER_SAVE;
|
||||
| WebConfigServer::CAP_LOOP | WebConfigServer::CAP_WIFI_POWER_SAVE
|
||||
| WebConfigServer::CAP_POWER_SAVING;
|
||||
if (board.canControlLoRaFemLna()) {
|
||||
s.capabilities |= WebConfigServer::CAP_FEM_RX_GAIN;
|
||||
}
|
||||
|
||||
@@ -1182,8 +1182,15 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
|
||||
_prefs.interference_threshold = 0; // disabled
|
||||
_prefs.radio_fem_rxgain = 1; // LoRa FEM RX gain on by default (FEM boards)
|
||||
_prefs.cad_enabled = DEFAULT_CAD_ENABLED; // Cascade defaults CAD on; target default remains off
|
||||
_prefs.powersaving_enabled = DEFAULT_POWERSAVING_ENABLED ? 1 : 0;
|
||||
_prefs.rx_powersaving_enabled = DEFAULT_RXPS_ENABLED ? 1 : 0;
|
||||
_prefs.rx_ps_level = DEFAULT_RXPS_LEVEL;
|
||||
_prefs.rx_ps_preamble = DEFAULT_RXPS_PREAMBLE;
|
||||
_prefs.rx_ps_rx_us = RX_POWERSAVING_DEFAULT_RX_US;
|
||||
_prefs.rx_ps_sleep_us = RX_POWERSAVING_DEFAULT_SLEEP_US;
|
||||
recalcRxPowerSavingFromLevel(_prefs.rx_ps_level, _prefs.sf, _prefs.bw,
|
||||
_prefs.rx_ps_preamble, &_prefs.rx_ps_rx_us,
|
||||
&_prefs.rx_ps_sleep_us);
|
||||
#ifdef ROOM_PASSWORD
|
||||
StrHelper::strncpy(_prefs.guest_password, ROOM_PASSWORD, sizeof(_prefs.guest_password));
|
||||
#endif
|
||||
@@ -1568,6 +1575,7 @@ void MyMesh::getNodeSnapshot(WebConfigServer::NodeSnapshot& s) {
|
||||
s.rx_ps_preamble = _prefs.rx_ps_preamble;
|
||||
s.rx_ps_rx_us = _prefs.rx_ps_rx_us;
|
||||
s.rx_ps_sleep_us = _prefs.rx_ps_sleep_us;
|
||||
s.power_saving = _prefs.powersaving_enabled;
|
||||
s.repeat = !_prefs.disable_fwd;
|
||||
s.advert_interval = _prefs.advert_interval * 2;
|
||||
s.flood_advert_interval = _prefs.flood_advert_interval;
|
||||
@@ -1579,7 +1587,8 @@ void MyMesh::getNodeSnapshot(WebConfigServer::NodeSnapshot& s) {
|
||||
| WebConfigServer::CAP_DELAYS | WebConfigServer::CAP_CAD
|
||||
| WebConfigServer::CAP_RX_GAIN | WebConfigServer::CAP_REPEAT
|
||||
| WebConfigServer::CAP_ADVERT | WebConfigServer::CAP_FLOOD
|
||||
| WebConfigServer::CAP_LOOP | WebConfigServer::CAP_WIFI_POWER_SAVE;
|
||||
| WebConfigServer::CAP_LOOP | WebConfigServer::CAP_WIFI_POWER_SAVE
|
||||
| WebConfigServer::CAP_POWER_SAVING;
|
||||
if (board.canControlLoRaFemLna()) {
|
||||
s.capabilities |= WebConfigServer::CAP_FEM_RX_GAIN;
|
||||
}
|
||||
|
||||
@@ -937,8 +937,15 @@ SensorMesh::SensorMesh(mesh::MainBoard& board, mesh::Radio& radio, mesh::Millise
|
||||
_prefs.interference_threshold = 0; // disabled
|
||||
_prefs.radio_fem_rxgain = 1; // LoRa FEM RX gain on by default (FEM boards)
|
||||
_prefs.cad_enabled = DEFAULT_CAD_ENABLED; // Cascade defaults CAD on; target default remains off
|
||||
_prefs.powersaving_enabled = DEFAULT_POWERSAVING_ENABLED ? 1 : 0;
|
||||
_prefs.rx_powersaving_enabled = DEFAULT_RXPS_ENABLED ? 1 : 0;
|
||||
_prefs.rx_ps_level = DEFAULT_RXPS_LEVEL;
|
||||
_prefs.rx_ps_preamble = DEFAULT_RXPS_PREAMBLE;
|
||||
_prefs.rx_ps_rx_us = RX_POWERSAVING_DEFAULT_RX_US;
|
||||
_prefs.rx_ps_sleep_us = RX_POWERSAVING_DEFAULT_SLEEP_US;
|
||||
recalcRxPowerSavingFromLevel(_prefs.rx_ps_level, _prefs.sf, _prefs.bw,
|
||||
_prefs.rx_ps_preamble, &_prefs.rx_ps_rx_us,
|
||||
&_prefs.rx_ps_sleep_us);
|
||||
|
||||
// GPS defaults
|
||||
_prefs.gps_enabled = 0;
|
||||
|
||||
Reference in new issue
Block a user