Ja musiałem oszukać blokadę roamingu w AiMesh, bo u mnie nie mogl złapać sieci tylko przeskakiwał. Wymyśliłem takie cosik z możliwością podania MAC danego BSSID oraz kanału (numeru kanału - dotyczy tylko tych AP co mają na stałe włączone konkretny kanał a nie AUTO na routerze).
Kod powstał poprzez przerobienie innego znanego rozwiązania (bez ograniczeń licencyjnych) aby dostosować do supli.
No i powstalo kombo Supla Schrodingera: lock na BSSID i jednoczesnie mozna odwrotnie failover i szukanie na multi sieci.
Code: Select all
#include "supla/network/esp_wifi.h" // oryginalny nagłówek
namespace Supla {
// Kandydat SSID
struct WifiCandidate {
const char* ssid;
const char* pass;
const uint8_t* bssid; // nullptr = bez locka
int channel; // 0 = auto
};
// Multi-SSID: dziedziczona od ESPWifi (żeby Matka-Supla widziała ją jako swoja)
class ESPWifiMulti_GMX : public Supla::ESPWifi {
public:
ESPWifiMulti_GMX(WifiCandidate* list, int count)
: ESPWifi(nullptr, nullptr, nullptr), list(list), count(count) {}
void setup() override {
// rejestruj eventy PRZED pierwszą próbą, bo jak podlaczysz to nie będziesz znał innych sieci
WiFi.onEvent([this](WiFiEvent_t ev, WiFiEventInfo_t info) {
switch (ev) {
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
SUPLA_LOG_INFO("WiFi disc. reason=%d", info.wifi_sta_disconnected.reason);
// nie używamy WiFi.reconnect(); sami sterujemy cyklem wyszukiwania i podłączania
// krótka pauza, potem kolejna próba
scheduleTryMillis = millis() + 200;
break;
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
SUPLA_LOG_INFO("WiFi OK, IP=%s", WiFi.localIP().toString().c_str());
lastOkMillis = millis();
break;
default: break;
}
});
WiFi.mode(WIFI_STA);
WiFi.setSleep(false);
WiFi.persistent(false);
if (hostname && *hostname) WiFi.setHostname(hostname); //lepiej działa z hostname
// pierwsza próba natychmiast - kuj zelazo poki gorace
scheduleTryMillis = 0;
tryConnect();
}
// Zwracam faktyczny status, ale nie dubluj logiki reconnecttu
bool iterate() override {
bool ok = Supla::ESPWifi::iterate(); // standardowe rzeczy Supli
ok = ok && (WiFi.status() == WL_CONNECTED); // gotowość sieci
// failover po 5 min braku "ok"
if (millis() - lastOkMillis > FAILOVER_MS) {
SUPLA_LOG_INFO("No internet for 5 min → rotate SSID");
nextSSID();
scheduleTryMillis = 0; // natychmiastowa próba
lastOkMillis = millis(); // zresetuj strażnik, żeby nie spamować
}
// miękki scheduler prób (żeby nie spamować begin() w pętli)
if (WiFi.status() != WL_CONNECTED && millis() >= scheduleTryMillis) {
tryConnect();
}
return ok;
}
private:
WifiCandidate* list;
int count;
int idx = 0;
unsigned long lastOkMillis = 0;
unsigned long scheduleTryMillis = 0;
static constexpr unsigned long FAILOVER_MS = 5UL * 60UL * 1000UL; // ustawiany czas po którym przełączymi się na nastepna znana siec
void tryConnect() {
// każda próba zaczyna się od czystego rozłączenia NVS + chwilka przerwy (chwila ciszy)
WiFi.disconnect(true);
delay(50);
for (int attempt = 0; attempt < count; attempt++) {
int i = (idx + attempt) % count;
SUPLA_LOG_INFO("WiFi try SSID=\"%s\"", list[i].ssid);
if (list[i].bssid) {
WiFi.begin(list[i].ssid, list[i].pass, list[i].channel, list[i].bssid, true);
} else {
WiFi.begin(list[i].ssid, list[i].pass);
}
unsigned long t0 = millis();
while (millis() - t0 < 8000) { // 8 s na próbę
if (WiFi.status() == WL_CONNECTED) {
idx = i;
lastOkMillis = millis();
SUPLA_LOG_INFO("WiFi connected: \"%s\" IP=%s",
list[i].ssid, WiFi.localIP().toString().c_str());
scheduleTryMillis = millis() + 10000; // następne sprawdzenie za 10 s
return;
}
delay(200);
}
SUPLA_LOG_INFO("SSID \"%s\" nie podłączono, bierz nastepna.....", list[i].ssid);
}
// wszystkie próby nieudane – spróbuj ponownie za chwilę aby nie zaspamowac sieci
scheduleTryMillis = millis() + 5000;
SUPLA_LOG_INFO("Bedzie powtorka szukania");
}
void nextSSID() {
idx = (idx + 1) % count;
}
};
// Twoja lista SSID (możesz dodać bssid, channel gdy chcesz) - przykład sarkastyczny ciutek
WifiCandidate wifiList[] = {
{ "SSID1", "haslo", nullptr, 0 },
{ "SSID2", "passwordzik", nullptr, 0 },
{ "SSID3", "admin1234", nullptr, 0 },
{ "SSID4", "12345578", bssid, 11 } //11 kanal, bssid mac i tylko ten AP
};
} // namespace Supla
// Globalny obiekt – musi istnieć PRZED setup(), żeby Supla widziała sieć
static Supla::ESPWifiMulti_GMX wifiki(Supla::wifiList, sizeof(Supla::wifiList) / sizeof(Supla::wifiList[0]));
a BSSID to deklarowane wyżej:
Code: Select all
uint8_t bssid[] = { 0xEE, 0x99, 0x25, 0x18, 0x02, 0x12 }; // ten właściwy AP