Unify device controls and restore the WiFi console
This commit is contained in:
1 parent
3746f9d5f4
commit
4c8aad5b16
44 files changed
+3573
-2948
No files matched your search
@@ -521,6 +521,37 @@ inline bool isUf2ResetCommand(const char* command) {
|
||||
return matchNoArgCommand(command, "uf2reset") == NoArgCommandMatch::Exact;
|
||||
}
|
||||
|
||||
// Shared by Companion and infrastructure logging controls. The optional suffix
|
||||
// requests a restart only when changing USB descriptors actually needs one.
|
||||
inline bool parseLoggingToggle(const char* value, bool& enabled, bool& reboot) {
|
||||
if (value == nullptr) return false;
|
||||
if (strcmp(value, "on") == 0 || strcmp(value, "on reboot") == 0) {
|
||||
enabled = true;
|
||||
reboot = value[2] != 0;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(value, "off") == 0 || strcmp(value, "off reboot") == 0) {
|
||||
enabled = false;
|
||||
reboot = value[3] != 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool parseLoggingOutput(const char* value, bool& usb, bool& wifi) {
|
||||
if (value == nullptr) return false;
|
||||
if (strcmp(value, "off") == 0) { usb = false; wifi = false; }
|
||||
else if (strcmp(value, "usb") == 0) { usb = true; wifi = false; }
|
||||
else if (strcmp(value, "wifi") == 0) { usb = false; wifi = true; }
|
||||
else if (strcmp(value, "both") == 0) { usb = true; wifi = true; }
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline const char* loggingOutputName(bool usb, bool wifi) {
|
||||
return usb ? (wifi ? "both" : "usb") : (wifi ? "wifi" : "off");
|
||||
}
|
||||
|
||||
inline void formatUnknownSetting(char* reply, size_t capacity,
|
||||
const char* setting) {
|
||||
if (reply == nullptr || capacity == 0) return;
|
||||
|
||||
+34
-53
@@ -2861,41 +2861,13 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re
|
||||
strcpy(reply, "Can't find GPS");
|
||||
}
|
||||
#endif
|
||||
} else if (memcmp(command, "powersaving on", 14) == 0) {
|
||||
#if defined(NRF52_PLATFORM)
|
||||
if (sender_timestamp == 0 || _board->isUsbDataConnected()) {
|
||||
strcpy(reply, "Error: USB serial connected");
|
||||
} else {
|
||||
_prefs->powersaving_enabled = 1;
|
||||
_sensors->setPowerSavingEnabled(true);
|
||||
savePrefs();
|
||||
strcpy(reply, "on - Immediate effect");
|
||||
}
|
||||
#elif defined(ESP32) && !defined(WITH_BRIDGE)
|
||||
if (sender_timestamp == 0 || _board->isUsbDataConnected()) {
|
||||
strcpy(reply, "Error: USB serial connected");
|
||||
} else {
|
||||
_prefs->powersaving_enabled = 1;
|
||||
_sensors->setPowerSavingEnabled(true);
|
||||
savePrefs();
|
||||
strcpy(reply, "on - After 2 minutes");
|
||||
}
|
||||
#elif defined(WITH_BRIDGE)
|
||||
strcpy(reply, "Bridge not supported");
|
||||
#else
|
||||
strcpy(reply, "Board not supported");
|
||||
#endif
|
||||
} else if (memcmp(command, "powersaving off", 15) == 0) {
|
||||
_prefs->powersaving_enabled = 0;
|
||||
_sensors->setPowerSavingEnabled(false);
|
||||
savePrefs();
|
||||
strcpy(reply, "off");
|
||||
} else if (memcmp(command, "powersaving", 11) == 0) {
|
||||
if (_prefs->powersaving_enabled) {
|
||||
strcpy(reply, "on");
|
||||
} else {
|
||||
strcpy(reply, "off");
|
||||
}
|
||||
} else if (strcmp(command, "powersaving on") == 0 || strcmp(command, "powersaving off") == 0) {
|
||||
char canonical[24];
|
||||
snprintf(canonical, sizeof(canonical), "set %s", command);
|
||||
handleSetCmd(sender_timestamp, canonical, reply);
|
||||
} else if (strcmp(command, "powersaving") == 0) {
|
||||
char canonical[] = "get powersaving";
|
||||
handleGetCmd(sender_timestamp, canonical, reply);
|
||||
} else if (memcmp(command, "sensor", 6) == 0) {
|
||||
// I2C
|
||||
#if ENV_HAS_SECONDARY_I2C
|
||||
@@ -3122,6 +3094,18 @@ bool CommonCLI::handleSdCardGetCmd(const char* config, char* reply) {
|
||||
|
||||
void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* reply) {
|
||||
const char* config = &command[4];
|
||||
#if ENV_INCLUDE_GPS == 1
|
||||
if (strncmp(config, "gps ", 4) == 0) {
|
||||
if (strcmp(config + 4, "on") != 0 && strcmp(config + 4, "off") != 0) {
|
||||
strcpy(reply, "Error: use set gps on|off");
|
||||
} else {
|
||||
char gps_command[8];
|
||||
snprintf(gps_command, sizeof(gps_command), "%s", config);
|
||||
handleCommand(sender_timestamp, gps_command, reply);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if defined(MESH_PRIMARY_ESPNOW) && MESH_PRIMARY_ESPNOW
|
||||
if (strncmp(config, "espnow.channel", 14) == 0
|
||||
&& (config[14] == 0 || config[14] == ' ' || config[14] == '\t')) {
|
||||
@@ -3155,8 +3139,8 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
&& (config[11] == 0 || config[11] == ' ' || config[11] == '\t')) {
|
||||
const char* value = &config[11];
|
||||
while (*value == ' ' || *value == '\t') value++;
|
||||
if (strcmp(value, "on") == 0 || strcmp(value, "off") == 0) {
|
||||
const bool enabled = strcmp(value, "on") == 0;
|
||||
bool enabled = false, reboot_if_needed = false;
|
||||
if (mesh::cli::parseLoggingToggle(value, enabled, reboot_if_needed)) {
|
||||
_prefs->usb_logging_enabled = enabled ? 1 : 0;
|
||||
mesh::setUsbLoggingEnabled(enabled);
|
||||
savePrefs();
|
||||
@@ -3174,19 +3158,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
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 {
|
||||
if (!mesh::cli::parseLoggingOutput(value, usb_enabled, wifi_enabled)) {
|
||||
strcpy(reply, "Error: usage set logging.output off|usb|wifi|both");
|
||||
return;
|
||||
}
|
||||
@@ -4329,6 +4301,17 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
|
||||
void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* reply) {
|
||||
const char* config = &command[4];
|
||||
if (strcmp(config, "powersaving") == 0) {
|
||||
snprintf(reply, 160, "> %s", _prefs->powersaving_enabled ? "on" : "off");
|
||||
return;
|
||||
}
|
||||
#if ENV_INCLUDE_GPS == 1
|
||||
if (strcmp(config, "gps") == 0) {
|
||||
char gps_command[] = "gps";
|
||||
handleCommand(sender_timestamp, gps_command, reply);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if defined(MESH_PRIMARY_ESPNOW) && MESH_PRIMARY_ESPNOW
|
||||
if (strcmp(config, "espnow.channel") == 0) {
|
||||
const uint8_t saved = mesh::wifi::loadConfiguredEspNowChannel();
|
||||
@@ -4353,9 +4336,7 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
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");
|
||||
const char* mode = mesh::cli::loggingOutputName(usb_enabled, wifi_enabled);
|
||||
snprintf(reply, 160, "> %s", mode);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -182,6 +182,17 @@ static void formatMQTTPresetListReply(char* reply, size_t reply_size, int start)
|
||||
bool CommonCLI::handleObserverSetCmd(uint32_t sender_timestamp, const char* config, char* reply) {
|
||||
#ifdef WITH_MQTT_BRIDGE
|
||||
bool handled = true;
|
||||
if (strncmp(config, "mqtt.enabled ", 13) == 0) {
|
||||
const char* value = config + 13;
|
||||
if (strcmp(value, "on") != 0 && strcmp(value, "off") != 0) {
|
||||
strcpy(reply, "Error: use set mqtt.enabled on|off");
|
||||
} else {
|
||||
char canonical[24];
|
||||
snprintf(canonical, sizeof(canonical), "set bridge.enabled %s", value);
|
||||
handleSetCmd(sender_timestamp, canonical, reply);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
const auto restart_observer_bridge = [this]() {
|
||||
return mesh::cli::restartBridgeIfEnabled(
|
||||
_prefs->bridge_enabled != 0,
|
||||
@@ -871,6 +882,14 @@ bool CommonCLI::handleObserverSetCmd(uint32_t sender_timestamp, const char* conf
|
||||
bool CommonCLI::handleObserverGetCmd(uint32_t sender_timestamp, const char* config, char* reply) {
|
||||
#ifdef WITH_MQTT_BRIDGE
|
||||
bool handled = true;
|
||||
if (strcmp(config, "mqtt.enabled") == 0) {
|
||||
snprintf(reply, 160, "> %s", _prefs->bridge_enabled ? "on" : "off");
|
||||
return true;
|
||||
}
|
||||
if (strcmp(config, "mqtt.running") == 0) {
|
||||
snprintf(reply, 160, "> %s", _callbacks->isBridgeRunning() ? "on" : "off");
|
||||
return true;
|
||||
}
|
||||
if (memcmp(config, "snmp.community", 14) == 0) {
|
||||
sprintf(reply, "> %s", _mqtt_prefs.snmp_community);
|
||||
} else if (memcmp(config, "snmp", 4) == 0 && (config[4] == '\0' || config[4] == '\n' || config[4] == '\r')) {
|
||||
|
||||
@@ -637,6 +637,22 @@ bool CompanionMqttSetupPortal::loadStoredConfig(MQTTPrefs& prefs) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompanionMqttSetupPortal::loadEnabled() {
|
||||
Preferences nvs;
|
||||
if (!nvs.begin(NVS_NAMESPACE, false)) return true;
|
||||
const bool enabled = !nvs.isKey("enabled") || nvs.getBool("enabled", true);
|
||||
nvs.end();
|
||||
return enabled;
|
||||
}
|
||||
|
||||
bool CompanionMqttSetupPortal::saveEnabled(bool enabled) {
|
||||
Preferences nvs;
|
||||
if (!nvs.begin(NVS_NAMESPACE, false)) return false;
|
||||
const bool saved = nvs.putBool("enabled", enabled) == sizeof(bool);
|
||||
nvs.end();
|
||||
return saved;
|
||||
}
|
||||
|
||||
bool CompanionMqttSetupPortal::saveStoredConfig(const MQTTPrefs& prefs) {
|
||||
Preferences nvs;
|
||||
if (!nvs.begin(NVS_NAMESPACE, false)) return false;
|
||||
|
||||
@@ -21,6 +21,8 @@ public:
|
||||
|
||||
static bool loadStoredConfig(MQTTPrefs& prefs);
|
||||
static bool saveStoredConfig(const MQTTPrefs& prefs);
|
||||
static bool loadEnabled();
|
||||
static bool saveEnabled(bool enabled);
|
||||
|
||||
private:
|
||||
volatile bool _active;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <stddef.h> // size_t / NULL for the reply classifiers below
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
// Fork-owned, dependency-free spec for the WebConfig "config batch / reboot /
|
||||
// stop" decision + timing core, plus its host tests (test/test_webconfig_batch/).
|
||||
@@ -320,6 +321,14 @@ static inline bool cliWriteSucceeded(const char* reply) {
|
||||
return reply != NULL && reply[0] == 'O' && reply[1] == 'K';
|
||||
}
|
||||
|
||||
// CommonCLI echoes a newly saved password instead of returning "OK". Mask
|
||||
// that success before sending it over HTTP, while preserving unsupported-role
|
||||
// errors from roles such as Companion which have no admin password.
|
||||
static inline bool cliPasswordChanged(const char* reply) {
|
||||
return cliWriteSucceeded(reply)
|
||||
|| (reply != NULL && strncmp(reply, "password now:", 13) == 0);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Reboot fire (.cpp:262-265) and isRebootPending (.cpp:70-74).
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
@@ -26,7 +26,7 @@ static const char* const WC_ALLOWED_SET_KEYS[] = {
|
||||
"flood.max", "flood.max.advert", "flood.max.unscoped", "loop.detect",
|
||||
// MQTTPrefs (WiFi / MQTT / misc observer)
|
||||
"wifi.ssid", "wifi.pwd", "wifi.powersave", "espnow.channel",
|
||||
"mqtt.origin", "mqtt.iata", "mqtt.status", "mqtt.packets", "mqtt.raw",
|
||||
"mqtt.enabled", "mqtt.origin", "mqtt.iata", "mqtt.status", "mqtt.packets", "mqtt.raw",
|
||||
"mqtt.tx", "mqtt.rx", "mqtt.interval", "mqtt.neighbors", "mqtt.neighbors.interval",
|
||||
"mqtt.ntp", "mqtt.owner", "mqtt.email",
|
||||
"timezone", "timezone.offset", "snmp", "snmp.community",
|
||||
|
||||
+1510
-1452
File diff suppressed because it is too large.
Load diff
@@ -1303,7 +1303,7 @@ void WebConfigServer::drainBatch(uint32_t now) {
|
||||
}
|
||||
if (e.reply[0] == 0) strcpy(e.reply, "(no reply)");
|
||||
const bool set_admin_pwd = wcCliEchoesSecret(e.cmd);
|
||||
if (set_admin_pwd) {
|
||||
if (set_admin_pwd && WebConfigBatch::cliPasswordChanged(e.reply)) {
|
||||
strcpy(e.reply, "OK");
|
||||
_admin_pwd_set = true;
|
||||
}
|
||||
@@ -1817,6 +1817,7 @@ void WebConfigServer::handleConfigGet(AsyncWebServerRequest* req) {
|
||||
MQTTPrefs* obs = static_cast<MQTTPrefs*>(_mqtt_prefs);
|
||||
if (obs) {
|
||||
JsonObject mqtt = doc.createNestedObject("mqtt");
|
||||
mqtt["enabled"] = node.mqtt_enabled;
|
||||
mqtt["origin"] = (const char*)obs->mqtt_origin;
|
||||
mqtt["iata"] = (const char*)obs->mqtt_iata;
|
||||
mqtt["status"] = (bool)obs->mqtt_status_enabled;
|
||||
|
||||
@@ -117,6 +117,7 @@ public:
|
||||
uint32_t rx_ps_rx_us;
|
||||
uint32_t rx_ps_sleep_us;
|
||||
uint8_t power_saving;
|
||||
bool mqtt_enabled;
|
||||
uint8_t repeat;
|
||||
uint16_t advert_interval;
|
||||
uint8_t flood_advert_interval;
|
||||
|
||||
Reference in new issue
Block a user