Merge fix/mqtt-review-2026-09-09 into feat/abstract-networking
#54 lands first, so the network abstraction is reworked on top of the per-slot client ownership model instead of alongside it. Two resolutions are semantic, not textual: - Link-transition teardown goes through the ownership API. It called softDisconnect() on every started client, which bypassed client_state and ignored the typed result. A slot that is still Starting now gets a real stop: softDisconnect() returns immediately on a client that is not yet connected, so its attempt would otherwise complete against the old route and deliver a CONNECTED event indistinguishable from the new one's (F04). On a medium switch the old route can still be briefly usable, so that is not hypothetical. A connected client keeps the cheap bounded path, and a quarantined one is left alone. - NetworkLink::applyPowerPrefs() adopts WifiPowerSavePolicy. Its local `2 ? MAX : NONE` mapping would have reintroduced F11 and read the new stored value 3 (explicit `min`) as none. It also applies the setting when the link starts already associated, which is the case the bridge used to cover. The NTP probe from #54 keeps its validation and its one-attempt-per-server bound, but resolves and gates on the selected link rather than on WiFi, so it works on an Ethernet-preferred node.
This commit is contained in:
commit
7f28231b25
30 files changed
+3075
-451
No files matched your search
@@ -16,6 +16,7 @@
|
||||
#include "AlertReporter.h" // for alertReporterBannedChannelMatch[Hex]()
|
||||
#include "MQTTObserverValidation.h" // pure input validators (host-testable)
|
||||
#include "NetworkLink.h"
|
||||
#include "WifiPowerSavePolicy.h" // one powersave value->mode/name mapping
|
||||
#include <Utils.h>
|
||||
#include <climits>
|
||||
#include <new>
|
||||
@@ -441,42 +442,29 @@ bool CommonCLI::handleObserverSetCmd(uint32_t sender_timestamp, const char* conf
|
||||
if (!persistObserverPrefs(reply)) return true;
|
||||
strcpy(reply, "OK");
|
||||
} else if (memcmp(config, "wifi.powersave ", 15) == 0) {
|
||||
const char* value = &config[15];
|
||||
uint8_t ps_value;
|
||||
bool valid = false;
|
||||
if (memcmp(value, "min", 3) == 0 && (value[3] == 0 || value[3] == ' ')) {
|
||||
ps_value = 0;
|
||||
valid = true;
|
||||
} else if (memcmp(value, "none", 4) == 0 && (value[4] == 0 || value[4] == ' ')) {
|
||||
ps_value = 1;
|
||||
valid = true;
|
||||
} else if (memcmp(value, "max", 3) == 0 && (value[3] == 0 || value[3] == ' ')) {
|
||||
ps_value = 2;
|
||||
valid = true;
|
||||
}
|
||||
if (!valid) {
|
||||
if (!WifiPowerSavePolicy::parseName(&config[15], &ps_value)) {
|
||||
strcpy(reply, "Error: must be none, min, or max");
|
||||
} else {
|
||||
_mqtt_prefs.wifi_power_save = ps_value;
|
||||
if (!persistObserverPrefs(reply)) return true;
|
||||
const char* ps_name = WifiPowerSavePolicy::nameFor(ps_value);
|
||||
#ifdef ESP_PLATFORM
|
||||
if (strcmp(activeNetworkLink().mediumName(), "wifi") == 0 &&
|
||||
activeNetworkLink().isConnected()) {
|
||||
wifi_ps_type_t ps_mode = (ps_value == 1) ? WIFI_PS_NONE :
|
||||
(ps_value == 2) ? WIFI_PS_MAX_MODEM : WIFI_PS_MIN_MODEM;
|
||||
esp_err_t ps_result = esp_wifi_set_ps(ps_mode);
|
||||
// Same mapping the link applies on every association, so this cannot
|
||||
// drift back apart (see WifiPowerSavePolicy).
|
||||
esp_err_t ps_result =
|
||||
esp_wifi_set_ps((wifi_ps_type_t)WifiPowerSavePolicy::modeFor(ps_value));
|
||||
if (ps_result == ESP_OK) {
|
||||
const char* ps_name = (ps_value == 1) ? "none" : (ps_value == 2) ? "max" : "min";
|
||||
sprintf(reply, "OK - power save set to %s", ps_name);
|
||||
} else {
|
||||
sprintf(reply, "OK - saved, but failed to apply: %d", ps_result);
|
||||
}
|
||||
} else {
|
||||
const char* ps_name = (ps_value == 1) ? "none" : (ps_value == 2) ? "max" : "min";
|
||||
sprintf(reply, "OK - saved as %s (will apply on next WiFi connection)", ps_name);
|
||||
}
|
||||
#else
|
||||
const char* ps_name = (ps_value == 1) ? "none" : (ps_value == 2) ? "max" : "min";
|
||||
sprintf(reply, "OK - saved as %s", ps_name);
|
||||
#endif
|
||||
}
|
||||
@@ -1121,9 +1109,7 @@ bool CommonCLI::handleObserverGetCmd(uint32_t sender_timestamp, const char* conf
|
||||
#endif
|
||||
}
|
||||
} else if (memcmp(config, "wifi.powersave", 14) == 0) {
|
||||
uint8_t ps = _mqtt_prefs.wifi_power_save;
|
||||
const char* ps_name = (ps == 1) ? "none" : (ps == 2) ? "max" : "min";
|
||||
sprintf(reply, "> %s", ps_name);
|
||||
sprintf(reply, "> %s", WifiPowerSavePolicy::nameFor(_mqtt_prefs.wifi_power_save));
|
||||
} else if (memcmp(config, "timezone.offset", 15) == 0) {
|
||||
// Must precede the "timezone" (8-byte) check below — that prefix-matches
|
||||
// "timezone.offset" too, so the more-specific key has to come first or
|
||||
|
||||
Reference in new issue
Block a user