mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2026-10-31 13:52:15 +01:00
feat: settings ops, the WiFi and frequency scans, and reboot for socket protocol 2
Step 1d of the protocol 2 core (docs/SECURITY_PLAN.md). - getSettings/saveSettings by section: general, network, mqtt, security, radio. A save is the settings route's request, so loop() applies it with the settings' own fromJSON(). ProtoSettings checks every field first: kind, range, string length, IP addresses. - Secrets are only reported as has*. A security save replies with the client's new token and closes the other sockets; other saves send settingsChanged to the other clients. - scanWifi runs an async scan from ESPNetwork, kept apart from the roaming scan, and wifiNetworks goes to the clients that asked. - beginFrequencyScan, endFrequencyScan and reboot run at once on async_tcp, as their routes do: a scan's end mustn't wait in the loop queue behind an unpair that waits for the scan to end (new op kind 'a'). - e2e: test_settings.py and a --reboot flag. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
97a4e98183
commit
2517f40709
22 changed files with 1221 additions and 49 deletions
|
|
@ -24,7 +24,34 @@ extern SomfyShadeController somfy;
|
|||
extern LoopStats loopStats;
|
||||
|
||||
static bool _apScanning = false;
|
||||
// The scan for clients: asked for, then running. WiFi holds the results of
|
||||
// one scan at a time, so it and the roaming scan never overlap.
|
||||
static bool _clientScanWanted = false;
|
||||
static bool _clientScanning = false;
|
||||
int connectRetries = 0;
|
||||
// A client that asks during a scan gets that scan's networks.
|
||||
void ESPNetwork::scanForClients() { if(!_clientScanning) _clientScanWanted = true; }
|
||||
static void clientScanLoop(ESPNetwork &net) {
|
||||
if(_clientScanning) {
|
||||
const int16_t n = WiFi.scanComplete();
|
||||
if(n == WIFI_SCAN_RUNNING) return;
|
||||
_clientScanning = false;
|
||||
if(n < 0) ESP_LOGW(TAG, "WiFi scan failed");
|
||||
else ESP_LOGI(TAG, "Scanned %d networks", n);
|
||||
protoSocket.wifiNetworks(n);
|
||||
WiFi.scanDelete();
|
||||
return;
|
||||
}
|
||||
if(!_clientScanWanted || _apScanning) return;
|
||||
_clientScanWanted = false;
|
||||
// As /scanaps does: the soft AP's connection attempts would get in its way.
|
||||
if(net.softAPOpened) WiFi.disconnect(false);
|
||||
if(WiFi.scanNetworks(true, true) == WIFI_SCAN_RUNNING) _clientScanning = true;
|
||||
else {
|
||||
ESP_LOGW(TAG, "WiFi scan didn't start");
|
||||
protoSocket.wifiNetworks(WIFI_SCAN_FAILED);
|
||||
}
|
||||
}
|
||||
void ESPNetwork::end() {
|
||||
SSDP.end();
|
||||
mqtt.end();
|
||||
|
|
@ -86,6 +113,8 @@ void ESPNetwork::loop() {
|
|||
// b. WiFi: Perform synchronous scan for APs related to the SSID. If the SSID can be found then perform
|
||||
// the connection process for the WiFi connection.
|
||||
// c. SoftAP: This condition retains the Soft AP because no other connection method is available.
|
||||
// Before the connection steps, which return early while connecting.
|
||||
clientScanLoop(*this);
|
||||
conn_types_t ctype = this->preferredConnType();
|
||||
this->connect(ctype); // Connection timeout handled in connect function as well as the opening of the Soft AP if needed.
|
||||
if(this->connecting()) return; // If we are currently attempting to connect to something then we need to bail here.
|
||||
|
|
@ -119,7 +148,7 @@ void ESPNetwork::loop() {
|
|||
}
|
||||
}
|
||||
}
|
||||
if(!this->connecting() && !settings.WIFI.hidden) {
|
||||
if(!this->connecting() && !settings.WIFI.hidden && !_clientScanWanted && !_clientScanning) {
|
||||
if((this->softAPOpened && WiFi.softAPgetStationNum() == 0) ||
|
||||
(!this->connected() && ctype == conn_types_t::wifi)) {
|
||||
// If the Soft AP is opened and there are no clients connected then we need to scan for an AP. If
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue