Unify full firmware profiles and add dual USB logging
This commit is contained in:
1 parent
b699e552ec
commit
f2d4ffbb7e
56 files changed
+1652
-361
No files matched your search
+16
-11
@@ -222,10 +222,12 @@ uint32_t Dispatcher::getCADFailMaxDuration() const {
|
||||
|
||||
#if MESH_PACKET_LOGGING
|
||||
void Dispatcher::logPacketStart(const char* direction, const Packet* packet, int len) {
|
||||
Serial.print(getLogDateTime());
|
||||
Serial.printf(": %s, len=%d (type=%d, route=%s, payload_len=%d)",
|
||||
direction, len, packet->getPayloadType(),
|
||||
packet->isRouteDirect() ? "D" : "F", packet->payload_len);
|
||||
Stream& logging_port = usbLoggingPort();
|
||||
logging_port.print(getLogDateTime());
|
||||
logging_port.printf(": %s, len=%d (type=%d, route=%s, payload_len=%d)",
|
||||
direction, len, packet->getPayloadType(),
|
||||
packet->isRouteDirect() ? "D" : "F",
|
||||
packet->payload_len);
|
||||
}
|
||||
|
||||
void Dispatcher::logPacketEnd(const Packet* packet) {
|
||||
@@ -233,10 +235,11 @@ void Dispatcher::logPacketEnd(const Packet* packet) {
|
||||
if (packet->payload_len >= 2
|
||||
&& (type == PAYLOAD_TYPE_PATH || type == PAYLOAD_TYPE_REQ
|
||||
|| type == PAYLOAD_TYPE_RESPONSE || type == PAYLOAD_TYPE_TXT_MSG)) {
|
||||
Serial.printf(" [%02X -> %02X]\n", (uint32_t)packet->payload[1],
|
||||
(uint32_t)packet->payload[0]);
|
||||
usbLoggingPort().printf(" [%02X -> %02X]\n",
|
||||
(uint32_t)packet->payload[1],
|
||||
(uint32_t)packet->payload[0]);
|
||||
} else {
|
||||
Serial.write((uint8_t)'\n');
|
||||
usbLoggingPort().write((uint8_t)'\n');
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -593,13 +596,15 @@ void Dispatcher::checkRecv() {
|
||||
#if MESH_PACKET_LOGGING
|
||||
if (isUsbLoggingEnabled()) {
|
||||
logPacketStart("RX", pkt, pkt->getRawLength());
|
||||
Serial.printf(" SNR=%d RSSI=%d score=%d time=%d", (int)pkt->getSNR(),
|
||||
(int)rssi, (int)(score * 1000), air_time);
|
||||
Stream& logging_port = usbLoggingPort();
|
||||
logging_port.printf(" SNR=%d RSSI=%d score=%d time=%d",
|
||||
(int)pkt->getSNR(), (int)rssi,
|
||||
(int)(score * 1000), air_time);
|
||||
|
||||
static uint8_t packet_hash[MAX_HASH_SIZE];
|
||||
pkt->calculatePacketHash(packet_hash);
|
||||
Serial.print(" hash=");
|
||||
mesh::Utils::printHex(Serial, packet_hash, MAX_HASH_SIZE);
|
||||
logging_port.print(" hash=");
|
||||
mesh::Utils::printHex(logging_port, packet_hash, MAX_HASH_SIZE);
|
||||
logPacketEnd(pkt);
|
||||
}
|
||||
#endif
|
||||
|
||||
+5
-5
@@ -25,23 +25,23 @@
|
||||
|
||||
#if MESH_DEBUG && ARDUINO
|
||||
#include <Arduino.h>
|
||||
#define MESH_DEBUG_PRINT(F, ...) do { if (mesh::isUsbLoggingEnabled() && Serial.availableForWrite() > 0) { Serial.printf("DEBUG: " F, ##__VA_ARGS__); } } while(0)
|
||||
#define MESH_DEBUG_PRINTLN(F, ...) do { if (mesh::isUsbLoggingEnabled() && Serial.availableForWrite() > 0) { Serial.printf("DEBUG: " F "\n", ##__VA_ARGS__); } } while(0)
|
||||
#define MESH_DEBUG_PRINT(F, ...) do { if (mesh::isUsbLoggingEnabled() && mesh::usbLoggingPort().availableForWrite() > 0) { mesh::usbLoggingPort().printf("DEBUG: " F, ##__VA_ARGS__); } } while(0)
|
||||
#define MESH_DEBUG_PRINTLN(F, ...) do { if (mesh::isUsbLoggingEnabled() && mesh::usbLoggingPort().availableForWrite() > 0) { mesh::usbLoggingPort().printf("DEBUG: " F "\n", ##__VA_ARGS__); } } while(0)
|
||||
#else
|
||||
#define MESH_DEBUG_PRINT(...) {}
|
||||
#define MESH_DEBUG_PRINTLN(...) {}
|
||||
#endif
|
||||
|
||||
#if BRIDGE_DEBUG && ARDUINO
|
||||
#define BRIDGE_DEBUG_PRINTLN(F, ...) do { if (mesh::isUsbLoggingEnabled() && Serial.availableForWrite() > 0) { Serial.printf("%s BRIDGE: " F, getLogDateTime(), ##__VA_ARGS__); } } while(0)
|
||||
#define BRIDGE_DEBUG_PRINTLN(F, ...) do { if (mesh::isUsbLoggingEnabled() && mesh::usbLoggingPort().availableForWrite() > 0) { mesh::usbLoggingPort().printf("%s BRIDGE: " F, getLogDateTime(), ##__VA_ARGS__); } } while(0)
|
||||
#else
|
||||
#define BRIDGE_DEBUG_PRINTLN(...) {}
|
||||
#endif
|
||||
|
||||
#if POWERSAVING_DEBUG && ARDUINO
|
||||
#include <Arduino.h>
|
||||
#define POWERSAVING_DEBUG_PRINT(F, ...) do { if (mesh::isUsbLoggingEnabled()) { Serial.printf("POWERSAVING: " F, ##__VA_ARGS__); } } while(0)
|
||||
#define POWERSAVING_DEBUG_PRINTLN(F, ...) do { if (mesh::isUsbLoggingEnabled()) { Serial.printf("POWERSAVING: " F "\n", ##__VA_ARGS__); } } while(0)
|
||||
#define POWERSAVING_DEBUG_PRINT(F, ...) do { if (mesh::isUsbLoggingEnabled()) { mesh::usbLoggingPort().printf("POWERSAVING: " F, ##__VA_ARGS__); } } while(0)
|
||||
#define POWERSAVING_DEBUG_PRINTLN(F, ...) do { if (mesh::isUsbLoggingEnabled()) { mesh::usbLoggingPort().printf("POWERSAVING: " F "\n", ##__VA_ARGS__); } } while(0)
|
||||
#else
|
||||
#define POWERSAVING_DEBUG_PRINT(...) {}
|
||||
#define POWERSAVING_DEBUG_PRINTLN(...) {}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#ifdef MQTT_DEBUG
|
||||
#include <Arduino.h>
|
||||
#define ALERT_DEBUG_PRINTLN(...) do { if (mesh::isUsbLoggingEnabled()) { Serial.printf("Alert: " __VA_ARGS__); Serial.println(); } } while (0)
|
||||
#define ALERT_DEBUG_PRINTLN(...) do { if (mesh::isUsbLoggingEnabled()) { mesh::usbLoggingPort().printf("Alert: " __VA_ARGS__); mesh::usbLoggingPort().println(); } } while (0)
|
||||
#else
|
||||
#define ALERT_DEBUG_PRINTLN(...) do {} while (0)
|
||||
#endif
|
||||
|
||||
@@ -722,6 +722,7 @@ void CommonCLI::loadPrefs(FILESYSTEM* fs) {
|
||||
// contain its appended byte, so they safely inherit the enabled default.
|
||||
_prefs->system_watchdog_enabled = 1;
|
||||
memset(_prefs->extra_sf, 0, sizeof(_prefs->extra_sf));
|
||||
_prefs->usb_logging_enabled = 1;
|
||||
|
||||
#ifdef WITH_MQTT_BRIDGE
|
||||
bool node_prefs_needs_migration = false;
|
||||
@@ -825,6 +826,9 @@ void CommonCLI::loadPrefs(FILESYSTEM* fs) {
|
||||
#if defined(ENABLE_OTA)
|
||||
if (loaded) syncOtaConfigFromPrefs(); // persisted OTA policy/keys -> OtaContext (else keep safe defaults)
|
||||
#endif
|
||||
#if MESH_USB_LOGGING_AVAILABLE
|
||||
mesh::setUsbLoggingEnabled(_prefs->usb_logging_enabled != 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(ENABLE_OTA)
|
||||
@@ -1205,6 +1209,10 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
||||
if (file.available() >= (int)sizeof(_prefs->radio_fem_txgain)) {
|
||||
file.read((uint8_t *)&_prefs->radio_fem_txgain,
|
||||
sizeof(_prefs->radio_fem_txgain));
|
||||
if (file.available() >= (int)sizeof(_prefs->usb_logging_enabled)) {
|
||||
file.read((uint8_t *)&_prefs->usb_logging_enabled,
|
||||
sizeof(_prefs->usb_logging_enabled));
|
||||
}
|
||||
}
|
||||
} else if (file.available() > 0) {
|
||||
// Never accept a torn append as a partial detector list.
|
||||
@@ -1275,6 +1283,7 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
||||
_prefs->rx_boosted_gain = constrain(_prefs->rx_boosted_gain, 0, 1); // boolean
|
||||
_prefs->radio_fem_rxgain = constrain(_prefs->radio_fem_rxgain, 0, 1); // boolean
|
||||
_prefs->radio_fem_txgain = constrain(_prefs->radio_fem_txgain, 0, 1); // boolean
|
||||
_prefs->usb_logging_enabled = constrain(_prefs->usb_logging_enabled, 0, 1); // boolean
|
||||
_prefs->cad_enabled = constrain(_prefs->cad_enabled, 0, 1); // boolean
|
||||
if (!directRetryPrefsValid(_prefs)) {
|
||||
setDefaultDirectRetryPrefs(_prefs);
|
||||
@@ -1482,6 +1491,7 @@ static bool writeCommonPrefsImage(Writer& writer, NodePrefs* prefs) {
|
||||
WRITE_COMMON_PREFS(&prefs->system_watchdog_enabled); // 855
|
||||
WRITE_COMMON_PREFS(&prefs->extra_sf); // 856
|
||||
WRITE_COMMON_PREFS(&prefs->radio_fem_txgain); // 860
|
||||
WRITE_COMMON_PREFS(&prefs->usb_logging_enabled); // 861
|
||||
|
||||
#undef WRITE_COMMON_PREFS_BYTES
|
||||
#undef WRITE_COMMON_PREFS
|
||||
@@ -1633,7 +1643,8 @@ void CommonCLI::savePrefs(FILESYSTEM* fs, PrefsSaveRouting::Scope scope) {
|
||||
sizeof(_prefs->system_watchdog_enabled)); // 855
|
||||
file.write((uint8_t *)_prefs->extra_sf, sizeof(_prefs->extra_sf)); // 856
|
||||
file.write((uint8_t *)&_prefs->radio_fem_txgain, sizeof(_prefs->radio_fem_txgain)); // 860
|
||||
// next: 861
|
||||
file.write((uint8_t *)&_prefs->usb_logging_enabled, sizeof(_prefs->usb_logging_enabled)); // 861
|
||||
// next: 862
|
||||
|
||||
#if defined(NRF52_PLATFORM)
|
||||
if (!file.commit()) {
|
||||
@@ -3028,15 +3039,48 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
while (*value == ' ' || *value == '\t') value++;
|
||||
if (strcmp(value, "on") == 0 || strcmp(value, "off") == 0) {
|
||||
const bool enabled = strcmp(value, "on") == 0;
|
||||
_prefs->usb_logging_enabled = enabled ? 1 : 0;
|
||||
mesh::setUsbLoggingEnabled(enabled);
|
||||
snprintf(reply, 160, "OK - USB logging %s until reboot",
|
||||
enabled ? "on" : "off");
|
||||
savePrefs();
|
||||
snprintf(reply, 160, "OK - USB logging %s (saved)", enabled ? "on" : "off");
|
||||
} else {
|
||||
strcpy(reply, "Error: usage set usb.logging on|off");
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if MESH_USB_LOGGING_AVAILABLE && defined(WITH_MQTT_BRIDGE)
|
||||
if (strncmp(config, "logging.output", 14) == 0
|
||||
&& (config[14] == 0 || config[14] == ' ' || config[14] == '\t')) {
|
||||
const char* value = &config[14];
|
||||
while (*value == ' ' || *value == '\t') value++;
|
||||
bool usb_enabled;
|
||||
bool wifi_enabled;
|
||||
if (strcmp(value, "off") == 0) {
|
||||
usb_enabled = false;
|
||||
wifi_enabled = false;
|
||||
} else if (strcmp(value, "usb") == 0) {
|
||||
usb_enabled = true;
|
||||
wifi_enabled = false;
|
||||
} else if (strcmp(value, "wifi") == 0) {
|
||||
usb_enabled = false;
|
||||
wifi_enabled = true;
|
||||
} else if (strcmp(value, "both") == 0) {
|
||||
usb_enabled = true;
|
||||
wifi_enabled = true;
|
||||
} else {
|
||||
strcpy(reply, "Error: usage set logging.output off|usb|wifi|both");
|
||||
return;
|
||||
}
|
||||
_prefs->usb_logging_enabled = usb_enabled ? 1 : 0;
|
||||
_prefs->bridge_enabled = wifi_enabled ? 1 : 0;
|
||||
mesh::setUsbLoggingEnabled(usb_enabled);
|
||||
_callbacks->setBridgeState(wifi_enabled);
|
||||
savePrefs();
|
||||
snprintf(reply, 160, "OK - logging.output %s (saved)", value);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if defined(ESP32_PLATFORM) || defined(USER_GPIO_CONTROL)
|
||||
if (isGpioConfig(config)) {
|
||||
const UserGpio::SetResult result = _user_gpio.handleSet(
|
||||
@@ -4000,6 +4044,17 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if MESH_USB_LOGGING_AVAILABLE && defined(WITH_MQTT_BRIDGE)
|
||||
if (strcmp(config, "logging.output") == 0) {
|
||||
const bool usb_enabled = mesh::isUsbLoggingEnabled();
|
||||
const bool wifi_enabled = _prefs->bridge_enabled != 0;
|
||||
const char* mode = usb_enabled
|
||||
? (wifi_enabled ? "both" : "usb")
|
||||
: (wifi_enabled ? "wifi" : "off");
|
||||
snprintf(reply, 160, "> %s", mode);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if defined(ESP32_PLATFORM) || defined(USER_GPIO_CONTROL)
|
||||
if (isGpioConfig(config)) {
|
||||
_user_gpio.handleGet(config + 4, reply, 160);
|
||||
|
||||
@@ -166,6 +166,10 @@ public:
|
||||
// in-memory placement here does not shift the established binary layout.
|
||||
uint8_t extra_sf[4] = {};
|
||||
uint8_t radio_fem_txgain = 0; // LoRa FEM TX gain; persisted at /com_prefs offset 860
|
||||
// Runtime USB packet output gate. Appended at /com_prefs offset 861 so
|
||||
// older images remain readable and logging builds keep their historical
|
||||
// enabled-at-first-boot behavior.
|
||||
uint8_t usb_logging_enabled = 1;
|
||||
uint8_t retry_preset = 0;
|
||||
uint8_t direct_retry_attempts = 0;
|
||||
uint16_t direct_retry_base_ms = 0;
|
||||
@@ -263,6 +267,7 @@ private:
|
||||
def("baud", _parent->bridge_baud);
|
||||
def("ch", _parent->bridge_channel);
|
||||
def("secret", _parent->bridge_secret, sizeof(_parent->bridge_secret));
|
||||
def("usb_log", _parent->usb_logging_enabled);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
@@ -1,12 +1,28 @@
|
||||
#include "UsbLogging.h"
|
||||
|
||||
#if defined(ARDUINO)
|
||||
#include <Arduino.h>
|
||||
#include <atomic>
|
||||
|
||||
#if defined(MESH_DUAL_CDC_LOGGING)
|
||||
#if !defined(NRF52_PLATFORM) || !defined(COMPANION_RADIO_FULL)
|
||||
#error "MESH_DUAL_CDC_LOGGING is only supported by nRF52 Full Companion"
|
||||
#endif
|
||||
#if !defined(CFG_TUD_CDC) || CFG_TUD_CDC < 2
|
||||
#error "MESH_DUAL_CDC_LOGGING requires CFG_TUD_CDC >= 2"
|
||||
#endif
|
||||
#include <Adafruit_TinyUSB.h>
|
||||
#endif
|
||||
|
||||
namespace mesh {
|
||||
|
||||
static std::atomic<bool> usb_logging_enabled{true};
|
||||
|
||||
#if defined(MESH_DUAL_CDC_LOGGING)
|
||||
static Adafruit_USBD_CDC dedicated_usb_logging_port;
|
||||
static bool dedicated_usb_logging_port_started = false;
|
||||
#endif
|
||||
|
||||
bool isUsbLoggingEnabled() {
|
||||
return usb_logging_enabled.load(std::memory_order_relaxed);
|
||||
}
|
||||
@@ -15,5 +31,40 @@ void setUsbLoggingEnabled(bool enabled) {
|
||||
usb_logging_enabled.store(enabled, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void beginUsbLoggingPort() {
|
||||
#if defined(MESH_DUAL_CDC_LOGGING)
|
||||
if (dedicated_usb_logging_port_started) return;
|
||||
|
||||
dedicated_usb_logging_port.begin(115200);
|
||||
dedicated_usb_logging_port_started = true;
|
||||
|
||||
// The nRF52 core starts TinyUSB before setup(). If the host completed
|
||||
// enumeration in that small window, reconnect once so it reads the expanded
|
||||
// two-CDC descriptor. Usually enumeration has not completed and no reconnect
|
||||
// is needed.
|
||||
if (TinyUSBDevice.mounted()) {
|
||||
TinyUSBDevice.detach();
|
||||
delay(10);
|
||||
TinyUSBDevice.attach();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Stream& usbLoggingPort() {
|
||||
#if defined(MESH_DUAL_CDC_LOGGING)
|
||||
return dedicated_usb_logging_port;
|
||||
#else
|
||||
return Serial;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool hasDedicatedUsbLoggingPort() {
|
||||
#if defined(MESH_DUAL_CDC_LOGGING)
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace mesh
|
||||
#endif
|
||||
@@ -12,12 +12,21 @@
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO)
|
||||
class Stream;
|
||||
|
||||
namespace mesh {
|
||||
|
||||
// This is intentionally session-only. Logging artifacts start enabled after
|
||||
// every boot so a stale setting cannot make a diagnostic image look silent.
|
||||
// Logging starts enabled on first boot. Roles with saved preferences restore
|
||||
// the persisted setting after their preferences are loaded.
|
||||
bool isUsbLoggingEnabled();
|
||||
void setUsbLoggingEnabled(bool enabled);
|
||||
|
||||
// Start the optional dedicated USB logging interface. Ordinary builds keep
|
||||
// using Serial. nRF52 Full Companion builds expose a second CDC ACM interface
|
||||
// so plaintext diagnostics never share the framed Companion stream.
|
||||
void beginUsbLoggingPort();
|
||||
Stream& usbLoggingPort();
|
||||
bool hasDedicatedUsbLoggingPort();
|
||||
|
||||
} // namespace mesh
|
||||
#endif
|
||||
@@ -45,6 +45,7 @@ static const uint32_t kRebootConfirmMs = 3000; // .cpp:784 first result-read
|
||||
static const uint32_t kSetupWiFiConnectTimeoutMs = 20000;
|
||||
static const uint32_t kSetupHandoffRebootConfirmMs = 1000;
|
||||
static const uint32_t kStopWarnMs = 10000; // .h:95 STOP_WARN_MS
|
||||
static const uint32_t kFullSetupApWindowMs = 30UL * 60UL * 1000UL;
|
||||
|
||||
// The batch lifecycle. A fresh POST moves Idle->Pending; the drainer moves
|
||||
// Pending->Done; Done stays re-readable until the next POST claims the slot;
|
||||
@@ -70,6 +71,22 @@ static inline bool deadlineReached(uint32_t now, uint32_t deadline) {
|
||||
return (int32_t)(now - deadline) >= 0;
|
||||
}
|
||||
|
||||
// FULL images expose an unconfigured setup AP for one bounded, boot-local
|
||||
// window. Activity and connected stations do not extend it: until an SSID is
|
||||
// saved the WiFi radio must go dark after 30 minutes. A reboot constructs a new
|
||||
// WebConfigServer and therefore starts a new automatic window without
|
||||
// persisting a timeout state. An explicit later `start webconfig` is still an
|
||||
// operator override. timeout_ms == 0 keeps this policy disabled for profiles
|
||||
// that retain the legacy idle-only behavior.
|
||||
static inline bool unconfiguredSetupWindowExpired(bool setup_mode,
|
||||
bool has_saved_ssid,
|
||||
uint32_t now,
|
||||
uint32_t setup_started_at,
|
||||
uint32_t timeout_ms) {
|
||||
return timeout_ms != 0 && setup_mode && !has_saved_ssid
|
||||
&& elapsedMs(now, setup_started_at) >= timeout_ms;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// POST accept classification (.cpp:637-718). Precedence, verbatim from the
|
||||
// source: an in-flight/finished batch with the SAME reqid is an idempotent
|
||||
|
||||
@@ -248,7 +248,7 @@ static void agentLogHeap(const char* location, const char* message, const char*
|
||||
"\"data\":{\"free\":%u,\"max_alloc\":%u,\"internal_free\":%lu,\"spiram_free\":%lu},\"timestamp\":%lu}",
|
||||
location, message, hypothesisId, (unsigned)free_h, (unsigned)max_alloc, internal_free, spiram_free,
|
||||
(unsigned long)millis());
|
||||
Serial.println(buf);
|
||||
mesh::usbLoggingPort().println(buf);
|
||||
}
|
||||
// #endregion
|
||||
#endif
|
||||
|
||||
@@ -31,8 +31,8 @@ class MeshSNMPAgent; // Forward declaration
|
||||
// USB CDC-aware debug macros: only print if Serial is ready (non-blocking check)
|
||||
// Serial.availableForWrite() returns bytes available in write buffer (>0 means ready)
|
||||
// This prevents hangs when USB CDC isn't ready yet (e.g., ESP32-S3 native USB)
|
||||
#define MQTT_DEBUG_PRINT(F, ...) do { if (mesh::isUsbLoggingEnabled() && Serial.availableForWrite() > 0) { Serial.printf("MQTT: " F, ##__VA_ARGS__); } } while(0)
|
||||
#define MQTT_DEBUG_PRINTLN(F, ...) do { if (mesh::isUsbLoggingEnabled() && Serial.availableForWrite() > 0) { Serial.printf("MQTT: " F "\n", ##__VA_ARGS__); } } while(0)
|
||||
#define MQTT_DEBUG_PRINT(F, ...) do { if (mesh::isUsbLoggingEnabled() && mesh::usbLoggingPort().availableForWrite() > 0) { mesh::usbLoggingPort().printf("MQTT: " F, ##__VA_ARGS__); } } while(0)
|
||||
#define MQTT_DEBUG_PRINTLN(F, ...) do { if (mesh::isUsbLoggingEnabled() && mesh::usbLoggingPort().availableForWrite() > 0) { mesh::usbLoggingPort().printf("MQTT: " F "\n", ##__VA_ARGS__); } } while(0)
|
||||
#else
|
||||
#define MQTT_DEBUG_PRINT(...) {}
|
||||
#define MQTT_DEBUG_PRINTLN(...) {}
|
||||
|
||||
@@ -64,8 +64,8 @@ public:
|
||||
|
||||
#if ESPNOW_DEBUG_LOGGING && ARDUINO
|
||||
#include <Arduino.h>
|
||||
#define ESPNOW_DEBUG_PRINT(F, ...) do { if (mesh::isUsbLoggingEnabled()) { Serial.printf("ESP-Now: " F, ##__VA_ARGS__); } } while(0)
|
||||
#define ESPNOW_DEBUG_PRINTLN(F, ...) do { if (mesh::isUsbLoggingEnabled()) { Serial.printf("ESP-Now: " F "\n", ##__VA_ARGS__); } } while(0)
|
||||
#define ESPNOW_DEBUG_PRINT(F, ...) do { if (mesh::isUsbLoggingEnabled()) { mesh::usbLoggingPort().printf("ESP-Now: " F, ##__VA_ARGS__); } } while(0)
|
||||
#define ESPNOW_DEBUG_PRINTLN(F, ...) do { if (mesh::isUsbLoggingEnabled()) { mesh::usbLoggingPort().printf("ESP-Now: " F "\n", ##__VA_ARGS__); } } while(0)
|
||||
#else
|
||||
#define ESPNOW_DEBUG_PRINT(...) {}
|
||||
#define ESPNOW_DEBUG_PRINTLN(...) {}
|
||||
|
||||
@@ -115,8 +115,8 @@ public:
|
||||
|
||||
#if BLE_DEBUG_LOGGING && ARDUINO
|
||||
#include <Arduino.h>
|
||||
#define BLE_DEBUG_PRINT(F, ...) do { if (mesh::isUsbLoggingEnabled()) { Serial.printf("BLE: " F, ##__VA_ARGS__); } } while(0)
|
||||
#define BLE_DEBUG_PRINTLN(F, ...) do { if (mesh::isUsbLoggingEnabled()) { Serial.printf("BLE: " F "\n", ##__VA_ARGS__); } } while(0)
|
||||
#define BLE_DEBUG_PRINT(F, ...) do { if (mesh::isUsbLoggingEnabled()) { mesh::usbLoggingPort().printf("BLE: " F, ##__VA_ARGS__); } } while(0)
|
||||
#define BLE_DEBUG_PRINTLN(F, ...) do { if (mesh::isUsbLoggingEnabled()) { mesh::usbLoggingPort().printf("BLE: " F "\n", ##__VA_ARGS__); } } while(0)
|
||||
#else
|
||||
#define BLE_DEBUG_PRINT(...) {}
|
||||
#define BLE_DEBUG_PRINTLN(...) {}
|
||||
|
||||
@@ -67,8 +67,8 @@ public:
|
||||
|
||||
#if WIFI_DEBUG_LOGGING && ARDUINO
|
||||
#include <Arduino.h>
|
||||
#define WIFI_DEBUG_PRINT(F, ...) do { if (mesh::isUsbLoggingEnabled()) { Serial.printf("WiFi: " F, ##__VA_ARGS__); } } while(0)
|
||||
#define WIFI_DEBUG_PRINTLN(F, ...) do { if (mesh::isUsbLoggingEnabled()) { Serial.printf("WiFi: " F "\n", ##__VA_ARGS__); } } while(0)
|
||||
#define WIFI_DEBUG_PRINT(F, ...) do { if (mesh::isUsbLoggingEnabled()) { mesh::usbLoggingPort().printf("WiFi: " F, ##__VA_ARGS__); } } while(0)
|
||||
#define WIFI_DEBUG_PRINTLN(F, ...) do { if (mesh::isUsbLoggingEnabled()) { mesh::usbLoggingPort().printf("WiFi: " F "\n", ##__VA_ARGS__); } } while(0)
|
||||
#else
|
||||
#define WIFI_DEBUG_PRINT(...) {}
|
||||
#define WIFI_DEBUG_PRINTLN(...) {}
|
||||
|
||||
@@ -585,6 +585,7 @@ bool WebConfigServer::startSetupMode(char reply[]) {
|
||||
_retry_saved_wifi_in_setup = false;
|
||||
_setup_reconnect_in_progress = false;
|
||||
_setup_reconnect_deadline = 0;
|
||||
_setup_started_at = 0;
|
||||
// AP_STA (not pure AP) so the WiFi scan for the SSID picker works while
|
||||
// the AP is up. STA stays unconnected - the bridge won't touch WiFi
|
||||
// while wifi_ssid is empty, and `start webconfig ap` requires it stopped.
|
||||
@@ -630,7 +631,8 @@ bool WebConfigServer::startSetupMode(char reply[]) {
|
||||
NodeSnapshot node = {};
|
||||
_cb->getNodeSnapshot(node);
|
||||
_initial_setup = _wifi_ssid[0] == 0 && node.admin_password[0] != 0;
|
||||
_last_activity = millis();
|
||||
_setup_started_at = millis();
|
||||
_last_activity = _setup_started_at;
|
||||
WiFi.scanNetworks(true); // pre-populate the SSID picker
|
||||
|
||||
sprintf(reply, "WebConfig AP started: join '%s' then open http://%s/", _ap_ssid, ip.toString().c_str());
|
||||
@@ -647,6 +649,7 @@ bool WebConfigServer::startLanMode(char reply[]) {
|
||||
return false;
|
||||
}
|
||||
_mode = MODE_LAN;
|
||||
_setup_started_at = 0;
|
||||
_wifi_reconnect_tracker.noteConnected();
|
||||
_retry_saved_wifi_in_setup = false;
|
||||
_setup_reconnect_in_progress = false;
|
||||
@@ -678,6 +681,7 @@ bool WebConfigServer::startAutoMode(char reply[]) {
|
||||
_retry_saved_wifi_in_setup = false;
|
||||
_setup_reconnect_in_progress = false;
|
||||
_setup_reconnect_deadline = 0;
|
||||
_setup_started_at = 0;
|
||||
_wifi_reconnect_tracker.noteDisconnected(millis());
|
||||
WiFi.begin(_wifi_ssid, _wifi_password);
|
||||
_wifi_power_save = effectiveWiFiPowerSave(_wifi_power_save);
|
||||
@@ -749,6 +753,7 @@ void WebConfigServer::finalizeTeardown() {
|
||||
WiFi.mode(WIFI_OFF);
|
||||
}
|
||||
_initial_setup = false;
|
||||
_setup_started_at = 0;
|
||||
_stopping = false;
|
||||
_stop_warn_at = 0;
|
||||
_stop_warned = false;
|
||||
@@ -857,6 +862,7 @@ void WebConfigServer::tick(uint32_t now) {
|
||||
WiFi.setAutoReconnect(true);
|
||||
_was_setup_ap = false;
|
||||
_initial_setup = false;
|
||||
_setup_started_at = 0;
|
||||
_retry_saved_wifi_in_setup = false;
|
||||
_setup_reconnect_in_progress = false;
|
||||
_setup_reconnect_deadline = 0;
|
||||
@@ -907,6 +913,21 @@ void WebConfigServer::tick(uint32_t now) {
|
||||
_stats_built_at = now;
|
||||
}
|
||||
|
||||
// A FULL image with no saved SSID gets one absolute setup window per boot.
|
||||
// Browser activity and an attached station cannot extend it. requestStop()
|
||||
// tears down the AP and finalizeTeardown() powers WiFi fully off; the saved
|
||||
// bridge/output preference is deliberately left unchanged for the next boot.
|
||||
if (WebConfigBatch::unconfiguredSetupWindowExpired(
|
||||
_mode == MODE_SETUP, _wifi_ssid[0] != 0, now,
|
||||
_setup_started_at,
|
||||
(uint32_t)WEBCONFIG_UNCONFIGURED_SETUP_TIMEOUT_MS)) {
|
||||
Serial.printf(
|
||||
"WebConfig: WiFi still unconfigured after %lu minutes; powering off until reboot or explicit restart\n",
|
||||
(unsigned long)((uint32_t)WEBCONFIG_UNCONFIGURED_SETUP_TIMEOUT_MS / 60000UL));
|
||||
requestStop();
|
||||
return;
|
||||
}
|
||||
|
||||
// Idle timeout: only the setup AP auto-stops (a deployed node must not be
|
||||
// left broadcasting an open AP). LAN mode runs until `stop webconfig`.
|
||||
if (_mode == MODE_SETUP && WiFi.softAPgetStationNum() == 0 &&
|
||||
@@ -925,6 +946,7 @@ void WebConfigServer::tick(uint32_t now) {
|
||||
WiFi.setAutoReconnect(true);
|
||||
_was_setup_ap = false;
|
||||
_initial_setup = false;
|
||||
_setup_started_at = 0;
|
||||
_retry_saved_wifi_in_setup = false;
|
||||
_setup_reconnect_in_progress = false;
|
||||
_setup_reconnect_deadline = 0;
|
||||
|
||||
@@ -36,7 +36,18 @@ class AsyncWebServerRequest;
|
||||
class DNSServer;
|
||||
|
||||
#ifndef WEBCONFIG_AP_IDLE_TIMEOUT_MS
|
||||
#define WEBCONFIG_AP_IDLE_TIMEOUT_MS (10UL * 60UL * 1000UL)
|
||||
#if defined(MESHCORE_ESP32_FULL_PROFILE)
|
||||
#define WEBCONFIG_AP_IDLE_TIMEOUT_MS WebConfigBatch::kFullSetupApWindowMs
|
||||
#else
|
||||
#define WEBCONFIG_AP_IDLE_TIMEOUT_MS (10UL * 60UL * 1000UL)
|
||||
#endif
|
||||
#endif
|
||||
#ifndef WEBCONFIG_UNCONFIGURED_SETUP_TIMEOUT_MS
|
||||
#if defined(MESHCORE_ESP32_FULL_PROFILE)
|
||||
#define WEBCONFIG_UNCONFIGURED_SETUP_TIMEOUT_MS WebConfigBatch::kFullSetupApWindowMs
|
||||
#else
|
||||
#define WEBCONFIG_UNCONFIGURED_SETUP_TIMEOUT_MS 0UL
|
||||
#endif
|
||||
#endif
|
||||
#ifndef WEBCONFIG_SESSION_TTL_MS
|
||||
#define WEBCONFIG_SESSION_TTL_MS (20UL * 60UL * 1000UL)
|
||||
@@ -227,6 +238,7 @@ private:
|
||||
bool _stopping = false;
|
||||
bool _was_setup_ap = false;
|
||||
bool _initial_setup = false;
|
||||
uint32_t _setup_started_at = 0;
|
||||
uint32_t _connect_deadline = 0;
|
||||
char _wifi_ssid[32] = {0};
|
||||
char _wifi_password[64] = {0};
|
||||
|
||||
@@ -70,9 +70,9 @@ class SerialEthernetInterface : public BaseSerialInterface {
|
||||
|
||||
#if ETHERNET_DEBUG_LOGGING && ARDUINO
|
||||
#include <Arduino.h>
|
||||
#define ETHERNET_DEBUG_PRINT(F, ...) do { if (mesh::isUsbLoggingEnabled()) { Serial.printf("ETH: " F, ##__VA_ARGS__); } } while(0)
|
||||
#define ETHERNET_DEBUG_PRINTLN(F, ...) do { if (mesh::isUsbLoggingEnabled()) { Serial.printf("ETH: " F "\n", ##__VA_ARGS__); } } while(0)
|
||||
#define ETHERNET_DEBUG_PRINT_IP(name, ip) do { if (mesh::isUsbLoggingEnabled()) { Serial.printf("ETH: " name ": %u.%u.%u.%u" "\n", ip[0], ip[1], ip[2], ip[3]); } } while(0)
|
||||
#define ETHERNET_DEBUG_PRINT(F, ...) do { if (mesh::isUsbLoggingEnabled()) { mesh::usbLoggingPort().printf("ETH: " F, ##__VA_ARGS__); } } while(0)
|
||||
#define ETHERNET_DEBUG_PRINTLN(F, ...) do { if (mesh::isUsbLoggingEnabled()) { mesh::usbLoggingPort().printf("ETH: " F "\n", ##__VA_ARGS__); } } while(0)
|
||||
#define ETHERNET_DEBUG_PRINT_IP(name, ip) do { if (mesh::isUsbLoggingEnabled()) { mesh::usbLoggingPort().printf("ETH: " name ": %u.%u.%u.%u" "\n", ip[0], ip[1], ip[2], ip[3]); } } while(0)
|
||||
#else
|
||||
#define ETHERNET_DEBUG_PRINT(...) {}
|
||||
#define ETHERNET_DEBUG_PRINTLN(...) {}
|
||||
|
||||
@@ -95,8 +95,8 @@ public:
|
||||
|
||||
#if BLE_DEBUG_LOGGING && ARDUINO
|
||||
#include <Arduino.h>
|
||||
#define BLE_DEBUG_PRINT(F, ...) do { if (mesh::isUsbLoggingEnabled()) { Serial.printf("BLE: " F, ##__VA_ARGS__); } } while(0)
|
||||
#define BLE_DEBUG_PRINTLN(F, ...) do { if (mesh::isUsbLoggingEnabled()) { Serial.printf("BLE: " F "\n", ##__VA_ARGS__); } } while(0)
|
||||
#define BLE_DEBUG_PRINT(F, ...) do { if (mesh::isUsbLoggingEnabled()) { mesh::usbLoggingPort().printf("BLE: " F, ##__VA_ARGS__); } } while(0)
|
||||
#define BLE_DEBUG_PRINTLN(F, ...) do { if (mesh::isUsbLoggingEnabled()) { mesh::usbLoggingPort().printf("BLE: " F "\n", ##__VA_ARGS__); } } while(0)
|
||||
#else
|
||||
#define BLE_DEBUG_PRINT(...) {}
|
||||
#define BLE_DEBUG_PRINTLN(...) {}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#if defined(OTA_DEBUG) && defined(ARDUINO)
|
||||
#include <Arduino.h>
|
||||
#include <helpers/UsbLogging.h>
|
||||
#define OTA_DBG(...) do { if (mesh::isUsbLoggingEnabled()) { Serial.printf(__VA_ARGS__); } } while (0)
|
||||
#define OTA_DBG(...) do { if (mesh::isUsbLoggingEnabled()) { mesh::usbLoggingPort().printf(__VA_ARGS__); } } while (0)
|
||||
#else
|
||||
#define OTA_DBG(...) do {} while (0)
|
||||
#endif
|
||||
@@ -51,8 +51,8 @@ class CustomLLCC68 : public LLCC68 {
|
||||
status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo);
|
||||
}
|
||||
if (status != RADIOLIB_ERR_NONE) {
|
||||
Serial.print("ERROR: radio init failed: ");
|
||||
Serial.println(status);
|
||||
mesh::usbLoggingPort().print("ERROR: radio init failed: ");
|
||||
mesh::usbLoggingPort().println(status);
|
||||
return false; // fail
|
||||
}
|
||||
|
||||
|
||||
@@ -58,8 +58,8 @@ class CustomLR2021 : public LR2021 {
|
||||
status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_LR2021_LORA_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo);
|
||||
}
|
||||
if (status != RADIOLIB_ERR_NONE) {
|
||||
Serial.print("ERROR: radio init failed: ");
|
||||
Serial.println(status);
|
||||
mesh::usbLoggingPort().print("ERROR: radio init failed: ");
|
||||
mesh::usbLoggingPort().println(status);
|
||||
return false; // fail
|
||||
}
|
||||
|
||||
|
||||
@@ -96,8 +96,8 @@ class CustomSX1262 : public SX1262 {
|
||||
status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo, useRegulatorLDO);
|
||||
}
|
||||
if (status != RADIOLIB_ERR_NONE) {
|
||||
Serial.print("ERROR: radio init failed: ");
|
||||
Serial.println(status);
|
||||
mesh::usbLoggingPort().print("ERROR: radio init failed: ");
|
||||
mesh::usbLoggingPort().println(status);
|
||||
return false; // fail
|
||||
}
|
||||
|
||||
|
||||
@@ -51,8 +51,8 @@ class CustomSX1268 : public SX1268 {
|
||||
status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo);
|
||||
}
|
||||
if (status != RADIOLIB_ERR_NONE) {
|
||||
Serial.print("ERROR: radio init failed: ");
|
||||
Serial.println(status);
|
||||
mesh::usbLoggingPort().print("ERROR: radio init failed: ");
|
||||
mesh::usbLoggingPort().println(status);
|
||||
return false; // fail
|
||||
}
|
||||
|
||||
|
||||
@@ -43,8 +43,8 @@ class CustomSX1276 : public SX1276 {
|
||||
int status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16);
|
||||
// if radio init fails with -707/-706, try again with tcxo voltage set to 0.0f
|
||||
if (status != RADIOLIB_ERR_NONE) {
|
||||
Serial.print("ERROR: radio init failed: ");
|
||||
Serial.println(status);
|
||||
mesh::usbLoggingPort().print("ERROR: radio init failed: ");
|
||||
mesh::usbLoggingPort().println(status);
|
||||
return false; // fail
|
||||
}
|
||||
#ifdef SX127X_CURRENT_LIMIT
|
||||
|
||||
@@ -147,7 +147,7 @@ public :
|
||||
while (_gps_serial->available()) {
|
||||
char c = _gps_serial->read();
|
||||
#ifdef GPS_NMEA_DEBUG
|
||||
if (mesh::isUsbLoggingEnabled()) Serial.print(c);
|
||||
if (mesh::isUsbLoggingEnabled()) mesh::usbLoggingPort().print(c);
|
||||
#endif
|
||||
nmea.process(c);
|
||||
}
|
||||
|
||||
@@ -442,11 +442,12 @@ bool ST7735Display::begin() {
|
||||
// alloc offscreen canvas
|
||||
sprite = new TFT_eSprite(&lcd);
|
||||
if (!sprite) {
|
||||
Serial.println("ST7735Display: failed to alloc canvas");
|
||||
mesh::usbLoggingPort().println("ST7735Display: failed to alloc canvas");
|
||||
return false;
|
||||
}
|
||||
if (!sprite->createSprite(160, 80)) {
|
||||
Serial.println("ST7735Display: failed to alloc canvas pixels");
|
||||
mesh::usbLoggingPort().println(
|
||||
"ST7735Display: failed to alloc canvas pixels");
|
||||
delete sprite;
|
||||
sprite = NULL;
|
||||
return false;
|
||||
|
||||
Reference in new issue
Block a user