Restore ordinary WiFi protocols for browser OTA hotspots
This commit is contained in:
1 parent
64a09cbada
commit
8fbf948d68
4 files changed
+48
-1
No files matched your search
@@ -59,6 +59,7 @@ bool ESP32Board::isUserGpioAvailable(uint8_t pin) const {
|
||||
#if defined(LIGHTWEIGHT_WIFI_OTA) && \
|
||||
(defined(ADMIN_PASSWORD) || defined(COMPANION_RADIO_FULL))
|
||||
#include <WiFi.h>
|
||||
#include <helpers/esp32/WiFiRadioPolicy.h>
|
||||
#include <helpers/esp32/StaticHtml.h>
|
||||
#include <Update.h>
|
||||
#include <esp_ota_ops.h>
|
||||
@@ -304,6 +305,12 @@ bool ESP32Board::startOTAUpdate(const char* id, char reply[], bool force_ap) {
|
||||
ota_started_ap = WiFi.softAPConfig(ap_ip, ap_ip, ap_mask)
|
||||
&& WiFi.softAP("MeshCore-OTA", nullptr);
|
||||
}
|
||||
// A valid IP does not imply a discoverable hotspot. An LR protocol bit
|
||||
// left by ESP-NOW makes AP beacons incompatible with ordinary clients.
|
||||
if (ota_started_ap && mesh::wifi::applyAccessPointProtocolMask() != ESP_OK) {
|
||||
WiFi.softAPdisconnect(true);
|
||||
ota_started_ap = false;
|
||||
}
|
||||
if (!ota_started_ap) {
|
||||
inhibit_sleep = ota_server != nullptr;
|
||||
strcpy(reply, "ERR: OTA WiFi failed");
|
||||
@@ -355,6 +362,7 @@ bool ESP32Board::stopOTAUpdate(char reply[]) {
|
||||
|
||||
#elif defined(ADMIN_PASSWORD) && !defined(DISABLE_WIFI_OTA) // Repeater or Room Server only
|
||||
#include <WiFi.h>
|
||||
#include <helpers/esp32/WiFiRadioPolicy.h>
|
||||
#include <AsyncTCP.h>
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <AsyncElegantOTA.h>
|
||||
@@ -387,6 +395,10 @@ bool ESP32Board::startOTAUpdate(const char* id, char reply[], bool force_ap) {
|
||||
ota_started_ap = WiFi.softAPConfig(ap_ip, ap_ip, ap_mask)
|
||||
&& WiFi.softAP("MeshCore-OTA", NULL);
|
||||
}
|
||||
if (ota_started_ap && mesh::wifi::applyAccessPointProtocolMask() != ESP_OK) {
|
||||
WiFi.softAPdisconnect(true);
|
||||
ota_started_ap = false;
|
||||
}
|
||||
if (!ota_started_ap) {
|
||||
inhibit_sleep = ota_server != nullptr;
|
||||
strcpy(reply, "ERR: OTA WiFi failed");
|
||||
|
||||
Vendored
+22
@@ -11,6 +11,11 @@
|
||||
constexpr int WL_CONNECTED = 3;
|
||||
constexpr int HTTP_GET = 0;
|
||||
constexpr int WIFI_AP = 2;
|
||||
constexpr int ESP_OK = 0, WIFI_IF_AP = 1;
|
||||
constexpr uint8_t WIFI_PROTOCOL_11B = 1, WIFI_PROTOCOL_11G = 2;
|
||||
constexpr uint8_t WIFI_PROTOCOL_11N = 4, WIFI_PROTOCOL_LR = 8;
|
||||
using esp_err_t = int;
|
||||
bool allow_protocol_reset = true;
|
||||
struct IPAddress {
|
||||
std::string value;
|
||||
IPAddress() = default;
|
||||
@@ -24,6 +29,7 @@ struct IPAddress {
|
||||
struct WiFiFake {
|
||||
bool connected = true, ap = false, allow_ap = true;
|
||||
unsigned starts = 0;
|
||||
uint8_t ap_protocol = 15; // Valid driver state, but LR beacons hide the AP from ordinary clients.
|
||||
int status() const { return connected ? WL_CONNECTED : 0; }
|
||||
int getMode() const { return ap ? WIFI_AP : 0; }
|
||||
IPAddress localIP() const { return IPAddress(10, 20, 30, 40); }
|
||||
@@ -39,6 +45,15 @@ struct WiFiFake {
|
||||
}
|
||||
void softAPdisconnect(bool) { ap = false; }
|
||||
} WiFi;
|
||||
esp_err_t esp_wifi_set_protocol(int interface_id, uint8_t protocols) {
|
||||
assert(interface_id == WIFI_IF_AP);
|
||||
if (!allow_protocol_reset) return -1;
|
||||
WiFi.ap_protocol = protocols;
|
||||
return ESP_OK;
|
||||
}
|
||||
namespace mesh { namespace wifi {
|
||||
@AP_PROTOCOL_POLICY@
|
||||
} }
|
||||
static unsigned server_starts = 0;
|
||||
struct AsyncWebServerRequest {
|
||||
void send(int, const char*, const char*) {}
|
||||
@@ -101,6 +116,7 @@ int main() {
|
||||
+ "/update";
|
||||
assert(strncmp(reply.text, url.c_str(), url.size()) == 0);
|
||||
assert(strstr(reply.text, instruction));
|
||||
if (ap || !WiFi.connected) assert(WiFi.ap_protocol == 7);
|
||||
assert(strlen(reply.text) < 160 && reply.guard == 0x12345678);
|
||||
};
|
||||
// Normal start reports the actual LAN address and does not disconnect it.
|
||||
@@ -119,6 +135,7 @@ int main() {
|
||||
start(true, "192.168.4.1", "Join WiFi MeshCore-OTA");
|
||||
assert(WiFi.ap && WiFi.connected && server_starts == 1);
|
||||
const auto ap_starts = WiFi.starts;
|
||||
WiFi.ap_protocol = 15; // Repair an existing AP without dropping its clients.
|
||||
start(true, "192.168.4.1", "Join WiFi MeshCore-OTA");
|
||||
assert(WiFi.starts == ap_starts); // Healthy repeats retain associated clients.
|
||||
WiFi.ap = false; // An external driver stop invalidates cached AP ownership.
|
||||
@@ -136,6 +153,11 @@ int main() {
|
||||
assert(!board.inhibit_sleep && !board.ota_server && !WiFi.ap && WiFi.connected);
|
||||
|
||||
WiFi.connected = false;
|
||||
allow_protocol_reset = false;
|
||||
assert(!board.startOTAUpdate("test node", reply.text, false));
|
||||
assert(strcmp(reply.text, "ERR: OTA WiFi failed") == 0);
|
||||
assert(!board.inhibit_sleep && !board.ota_server && !WiFi.ap);
|
||||
allow_protocol_reset = true;
|
||||
start(false, "192.168.4.1", "Join WiFi MeshCore-OTA");
|
||||
assert(WiFi.ap && !WiFi.connected);
|
||||
assert(board.stopOTAUpdate(reply.text));
|
||||
|
||||
@@ -38,6 +38,7 @@ STUBS = r'''
|
||||
#define MESH_DEBUG_PRINTLN(...) ((void)0)
|
||||
constexpr int WL_CONNECTED = 3, WL_DISCONNECTED = 6, HTTP_GET = 0;
|
||||
constexpr int WIFI_AP = 2;
|
||||
constexpr int ESP_OK = 0;
|
||||
|
||||
struct IPAddress {
|
||||
uint32_t value = 0;
|
||||
@@ -61,6 +62,7 @@ struct MockWiFi {
|
||||
bool ap_config_ok = true, ap_start_ok = true;
|
||||
bool initialized_cache = false, started_cache = false;
|
||||
IPAddress station_ip, ap_ip, configured_ap_ip;
|
||||
int ap_protocol = 15;
|
||||
int status() const { return station_status; }
|
||||
int getMode() const { return sdk_ap_active ? WIFI_AP : 0; }
|
||||
IPAddress localIP() const { return station_ip; }
|
||||
@@ -78,7 +80,11 @@ struct MockWiFi {
|
||||
}
|
||||
return ap_start_ok;
|
||||
}
|
||||
void softAPdisconnect(bool) { sdk_ap_active = false; ap_ip = IPAddress(); }
|
||||
} WiFi;
|
||||
namespace mesh { namespace wifi {
|
||||
int applyAccessPointProtocolMask() { WiFi.ap_protocol = 7; return ESP_OK; }
|
||||
} }
|
||||
|
||||
int wifi_stop_calls = 0, wifi_deinit_calls = 0;
|
||||
int esp_wifi_stop() {
|
||||
@@ -148,7 +154,7 @@ void seedStation() {
|
||||
bool endpointUsable() {
|
||||
return sdk_initialized && sdk_started
|
||||
&& ((WiFi.station_status == WL_CONNECTED && WiFi.station_ip.value != 0)
|
||||
|| (sdk_ap_active && WiFi.ap_ip.value != 0));
|
||||
|| (sdk_ap_active && WiFi.ap_ip.value != 0 && WiFi.ap_protocol == 7));
|
||||
}
|
||||
int main(int argc, char** argv) {
|
||||
assert(argc == 2);
|
||||
@@ -162,6 +168,7 @@ int main(int argc, char** argv) {
|
||||
the_mesh.web = true;
|
||||
const IPAddress ip(192, 168, 4, 1), mask(255, 255, 255, 0);
|
||||
assert(WiFi.softAPConfig(ip, ip, mask) && WiFi.softAP("setup", nullptr));
|
||||
mesh::wifi::applyAccessPointProtocolMask();
|
||||
assert(endpointUsable());
|
||||
} else if (scenario == "owners_mqtt" || scenario == "cleanup_mqtt") {
|
||||
the_mesh.mqtt = true;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"""Exercise the actual browser OTA start/stop methods with fake WiFi and servers."""
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
@@ -34,6 +35,11 @@ class WiFiOtaStartTest(unittest.TestCase):
|
||||
source = (ROOT / "src/helpers/ESP32Board.cpp").read_text()
|
||||
lightweight, other = source.split("#elif defined(ADMIN_PASSWORD) && !defined(DISABLE_WIFI_OTA)", 1)
|
||||
fixture = (ROOT / "test/fixtures/wifi_ota_start.cpp").read_text()
|
||||
policy = (ROOT / "src/helpers/esp32/WiFiRadioPolicy.h").read_text()
|
||||
mask = re.search(r"static constexpr uint8_t kAccessPointProtocolMask =.*?;",
|
||||
policy, re.DOTALL).group(0)
|
||||
fixture = fixture.replace("@AP_PROTOCOL_POLICY@", mask + "\n" + extract_braced(
|
||||
policy, "inline esp_err_t applyAccessPointProtocolMask()"))
|
||||
for name, implementation, flags in (
|
||||
("lightweight infrastructure", lightweight, ["-DLIGHTWEIGHT_WIFI_OTA=1"]),
|
||||
("lightweight companion", lightweight, ["-DLIGHTWEIGHT_WIFI_OTA=1", "-DCOMPANION_RADIO_FULL=1"]),
|
||||
|
||||
Reference in new issue
Block a user