From be185b46a7a44911e0f251acad954c1443b8533c Mon Sep 17 00:00:00 2001 From: cschwinne Date: Fri, 18 Oct 2019 23:47:11 +0200 Subject: [PATCH] Reworked WiFi logic Remaining issues: MQTT reconnects too often WiFI AP doesn't work if searching for STA --- wled00/wled00.ino | 22 ++--- wled00/wled05_init.ino | 181 +++++++++++++++++++++++++-------------- wled00/wled07_notify.ino | 2 +- wled00/wled12_alexa.ino | 5 -- wled00/wled17_mqtt.ino | 17 ++-- wled00/wled18_server.ino | 4 +- 6 files changed, 140 insertions(+), 91 deletions(-) diff --git a/wled00/wled00.ino b/wled00/wled00.ino index 12eb3136..e66e8c67 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -99,7 +99,7 @@ //version code in format yymmddb (b = daily build) -#define VERSION 1910181 +#define VERSION 1910182 char versionString[] = "0.8.5"; @@ -124,6 +124,7 @@ char apSSID[33] = ""; //AP off by default (unless setup) byte apChannel = 1; //2.4GHz WiFi AP channel (1-13) byte apHide = 0; //hidden AP SSID byte apWaitTimeSecs = 32; //time to wait for connection before opening AP +bool apAlwaysOn = true; bool recoveryAPDisabled = false; //never open AP (not recommended) IPAddress staticIP(0, 0, 0, 0); //static IP of ESP IPAddress staticGateway(0, 0, 0, 0); //gateway (router) IP @@ -259,6 +260,12 @@ uint16_t userVar0 = 0, userVar1 = 0; //internal global variable declarations +//wifi +bool apActive = false; +bool forceReconnect = false; +uint32_t lastReconnectAttempt = 0; +bool interfacesInited = false; + //color byte col[]{255, 159, 0, 0}; //target RGB(W) color byte colOld[]{0, 0, 0, 0}; //color before transition @@ -398,7 +405,6 @@ EspalexaDevice* espalexaDevice; //dns server DNSServer dnsServer; -bool dnsActive = false; //network time bool ntpConnected = false; @@ -433,6 +439,7 @@ E131* e131; WS2812FX strip = WS2812FX(); #define WLED_CONNECTED (WiFi.status() == WL_CONNECTED) +#define WLED_WIFI_CONFIGURED (strlen(clientSSID) >= 1 && strcmp(clientSSID,"Your_Network") != 0) //debug macros #ifdef WLED_DEBUG @@ -498,7 +505,6 @@ bool oappendi(int i) //boot starts here void setup() { - pinMode(4, OUTPUT); digitalWrite(4, HIGH); wledInit(); } @@ -524,7 +530,7 @@ void loop() { if (!realtimeActive) //block stuff if WARLS/Adalight is enabled { - if (dnsActive) dnsServer.processNextRequest(); + if (apActive) dnsServer.processNextRequest(); #ifndef WLED_DISABLE_OTA if (aOtaEnabled) ArduinoOTA.handle(); #endif @@ -533,16 +539,12 @@ void loop() { handleHue(); handleBlynk(); - yield(); - if (millis() - lastMqttReconnectAttempt > 30000) - { - initMqtt(); - lastMqttReconnectAttempt = millis(); - } yield(); if (!offMode) strip.service(); } + yield(); + if (millis() - lastMqttReconnectAttempt > 30000) initMqtt(); //DEBUG serial logging #ifdef WLED_DEBUG diff --git a/wled00/wled05_init.ino b/wled00/wled05_init.ino index 8ec6fae8..6b2370b9 100644 --- a/wled00/wled05_init.ino +++ b/wled00/wled05_init.ino @@ -40,23 +40,12 @@ void wledInit() DEBUG_PRINTLN("Load EEPROM"); loadSettingsFromEEPROM(true); beginStrip(); - DEBUG_PRINT("CSSID: "); - DEBUG_PRINT(clientSSID); userBeginPreConnection(); if (strcmp(clientSSID,"Your_Network") == 0) showWelcomePage = true; WiFi.persistent(false); - initCon(); - DEBUG_PRINTLN(""); - DEBUG_PRINT("Connected! IP address: "); - DEBUG_PRINTLN(WiFi.localIP()); - - if (hueIP[0] == 0) - { - hueIP[0] = WiFi.localIP()[0]; - hueIP[1] = WiFi.localIP()[1]; - hueIP[2] = WiFi.localIP()[2]; - } + if (macroBoot>0) applyMacro(macroBoot); + Serial.println("Ada"); if (udpPort > 0 && udpPort != ntpLocalPort) { @@ -66,15 +55,10 @@ void wledInit() if (ntpEnabled && WLED_CONNECTED) ntpConnected = ntpUdp.begin(ntpLocalPort); - //start captive portal if AP active - if (!WLED_CONNECTED || strlen(apSSID) > 0) - { - dnsServer.setErrorReplyCode(DNSReplyCode::NoError); - dnsServer.start(53, "*", WiFi.softAPIP()); - dnsActive = true; - } - - prepareIds(); //UUID from MAC (for Alexa and MQTT) + //generate module IDs + escapedMac = WiFi.macAddress(); + escapedMac.replace(":", ""); + escapedMac.toLowerCase(); if (strcmp(cmDNS,"x") == 0) //fill in unique mdns default { strcpy(cmDNS, "wled-"); @@ -97,14 +81,12 @@ void wledInit() initServer(); strip.service(); - //init Alexa hue emulation - if (alexaEnabled) alexaInit(); server.begin(); DEBUG_PRINTLN("HTTP server started"); //init ArduinoOTA - if (WLED_CONNECTED) { + if (true) { #ifndef WLED_DISABLE_OTA if (aOtaEnabled) { @@ -138,10 +120,8 @@ void wledInit() e131Enabled = false; } + initConnection(); userBegin(); - - if (macroBoot>0) applyMacro(macroBoot); - Serial.println("Ada"); } @@ -176,17 +156,25 @@ void beginStrip() void initAP(bool resetAP=false){ - DEBUG_PRINTLN("Opening AP..."); + if (recoveryAPDisabled) return; bool set = apSSID[0]; if (!set || resetAP) strcpy(apSSID, "WLED-AP"); - //if (resetAP) strcpy(apPass,"wled1234"); + if (resetAP) strcpy(apPass,"wled1234"); + DEBUG_PRINT("Opening access point "); + DEBUG_PRINTLN(apSSID); WiFi.softAPConfig(IPAddress(4, 3, 2, 1), IPAddress(4, 3, 2, 1), IPAddress(255,255,255,0)); WiFi.softAP(apSSID, apPass, apChannel, apHide); if (!set) apSSID[0] = 0; + + if (!apActive) //start captive portal if AP active + { + dnsServer.setErrorReplyCode(DNSReplyCode::NoError); + dnsServer.start(53, "*", WiFi.softAPIP()); + } + apActive = true; } - -void initCon() +void initConnection() { WiFi.disconnect(); //close old connections @@ -198,23 +186,28 @@ void initCon() WiFi.config(0U, 0U, 0U); } - if (strlen(apSSID)>0) + lastReconnectAttempt = millis(); + + if (apAlwaysOn) { - DEBUG_PRINT(" USING AP"); - DEBUG_PRINTLN(strlen(apSSID)); initAP(); - } else + } else if (!apActive) { - DEBUG_PRINTLN(" NO AP"); + DEBUG_PRINTLN("Access point disabled."); WiFi.softAPdisconnect(true); } - if (strlen(clientSSID) <1 || strcmp(clientSSID,"Your_Network") == 0) + if (!WLED_WIFI_CONFIGURED) { DEBUG_PRINT("No connection configured. "); initAP(); //instantly go to ap mode return; } + showWelcomePage = false; + + DEBUG_PRINT("Connecting to "); + DEBUG_PRINT(clientSSID); + DEBUG_PRINTLN("..."); #ifndef ARDUINO_ARCH_ESP32 WiFi.hostname(serverDescription); @@ -223,37 +216,97 @@ void initCon() #ifdef ARDUINO_ARCH_ESP32 WiFi.setHostname(serverDescription); #endif - //wifiInit = true; - uint32_t fail_count = 0; - unsigned long lastTry = 0; - bool con = false; - while(!con) - { - yield(); - handleTransitions(); - handleButton(); - handleOverlays(); - if (briT) strip.service(); - if (millis()-lastTry > 499) { - con = WLED_CONNECTED; - lastTry = millis(); - DEBUG_PRINTLN("C_NC"); - if (!recoveryAPDisabled && fail_count > apWaitTimeSecs*2) - { - WiFi.disconnect(); - DEBUG_PRINT("Can't connect. "); - initAP(); - return; - } - fail_count++; - } - } } +void initInterfaces() { + if (hueIP[0] == 0) + { + hueIP[0] = WiFi.localIP()[0]; + hueIP[1] = WiFi.localIP()[1]; + hueIP[2] = WiFi.localIP()[2]; + } + + //init Alexa hue emulation + if (alexaEnabled) alexaInit(); + + initMqtt(); + + #ifndef WLED_DISABLE_OTA + if (aOtaEnabled) + { + ArduinoOTA.onStart([]() { + #ifndef ARDUINO_ARCH_ESP32 + wifi_set_sleep_type(NONE_SLEEP_T); + #endif + DEBUG_PRINTLN("Start ArduinoOTA"); + }); + if (strlen(cmDNS) > 0) ArduinoOTA.setHostname(cmDNS); + ArduinoOTA.begin(); + } + #endif + + strip.service(); + // Set up mDNS responder: + if (strlen(cmDNS) > 0) + { + MDNS.begin(cmDNS); + DEBUG_PRINTLN("mDNS responder started"); + // Add service to MDNS + MDNS.addService("http", "tcp", 80); + MDNS.addService("wled", "tcp", 80); + } + strip.service(); + + initBlynk(blynkApiKey); + initE131(); + reconnectHue(); + + interfacesInited = true; +} + +byte stacO = 0; void handleConnection() { + byte stac = wifi_softap_get_station_num(); + if (stac != stacO) + { + stacO = stac; + DEBUG_PRINT("Connected AP clients: "); + DEBUG_PRINTLN(stac); + if (!WLED_CONNECTED && WLED_WIFI_CONFIGURED) { //trying to connect, but not connected + if (stac) WiFi.disconnect(); //disable search so that AP can work + else initConnection(); //restart search + } + } + if (forceReconnect) { + DEBUG_PRINTLN("Forcing reconnect."); + initConnection(); + interfacesInited = false; + forceReconnect = false; + return; + } if (!WLED_CONNECTED) { - + if (interfacesInited) { + DEBUG_PRINTLN("Disconnected!"); + interfacesInited = false; + initConnection(); + } + if (millis() - lastReconnectAttempt > 300000 && WLED_WIFI_CONFIGURED) initConnection(); + if (!apActive && millis() - lastReconnectAttempt > apWaitTimeSecs*1000) initAP(); + } else if (!interfacesInited) { //newly connected + DEBUG_PRINTLN(""); + DEBUG_PRINT("Connected! IP address: "); + DEBUG_PRINTLN(WiFi.localIP()); + initInterfaces(); + + //shut down AP + if (!apAlwaysOn && apActive) + { + dnsServer.stop(); + DEBUG_PRINTLN("Access point disabled."); + WiFi.softAPdisconnect(true); + apActive = false; + } } } diff --git a/wled00/wled07_notify.ino b/wled00/wled07_notify.ino index 2756e720..21e44155 100644 --- a/wled00/wled07_notify.ino +++ b/wled00/wled07_notify.ino @@ -89,7 +89,7 @@ void arlsLock(uint32_t timeoutMs) void initE131(){ if (WLED_CONNECTED && e131Enabled) { - e131 = new E131(); + if (e131 == nullptr) e131 = new E131(); e131->begin((e131Multicast) ? E131_MULTICAST : E131_UNICAST , e131Universe); } else { e131Enabled = false; diff --git a/wled00/wled12_alexa.ino b/wled00/wled12_alexa.ino index a9256b1c..b858d238 100644 --- a/wled00/wled12_alexa.ino +++ b/wled00/wled12_alexa.ino @@ -5,11 +5,6 @@ * https://github.com/kakopappa/arduino-esp8266-alexa-wemo-switch * https://github.com/probonopd/ESP8266HueEmulator */ -void prepareIds() { - escapedMac = WiFi.macAddress(); - escapedMac.replace(":", ""); - escapedMac.toLowerCase(); -} #ifndef WLED_DISABLE_ALEXA void onAlexaChange(EspalexaDevice* dev); diff --git a/wled00/wled17_mqtt.ino b/wled00/wled17_mqtt.ino index 159080f8..2dc361df 100644 --- a/wled00/wled17_mqtt.ino +++ b/wled00/wled17_mqtt.ino @@ -2,8 +2,6 @@ * MQTT communication protocol for home automation */ -//#define WLED_MQTT_PORT 1883 - void parseMQTTBriPayload(char* payload) { if (strstr(payload, "ON") || strstr(payload, "on") || strstr(payload, "true")) {bri = briLast; colorUpdated(1);} @@ -47,7 +45,7 @@ void onMqttConnect(bool sessionPresent) sendHADiscoveryMQTT(); publishMqtt(); - DEBUG_PRINTLN("MQ ready"); + DEBUG_PRINTLN("MQTT ready"); } @@ -74,8 +72,7 @@ void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties void publishMqtt() { - if (mqtt == NULL) return; - if (!mqtt->connected()) return; + if (mqtt == nullptr || !mqtt->connected()) return; DEBUG_PRINTLN("Publish MQTT"); char s[10]; @@ -206,8 +203,8 @@ Send out HA MQTT Discovery message on MQTT connect (~2.4kB): DEBUG_PRINTLN(buffer); char pubt[25 + 12 + 8]; - strcpy(pubt, "homeassistant/light/WLED_"); - strcat(pubt, escapedMac.c_str()); + strcpy(pubt, "homeassistant/light/"); + strcat(pubt, mqttClientID); strcat(pubt, "/config"); mqtt->publish(pubt, 0, true, buffer); #endif @@ -215,11 +212,13 @@ Send out HA MQTT Discovery message on MQTT connect (~2.4kB): bool initMqtt() { + lastMqttReconnectAttempt = millis(); if (mqttServer[0] == 0 || !WLED_CONNECTED) return false; - if (!mqtt) mqtt = new AsyncMqttClient(); + if (mqtt == nullptr) mqtt = new AsyncMqttClient(); if (mqtt->connected()) return true; + DEBUG_PRINTLN("Reconnecting MQTT"); IPAddress mqttIP; if (mqttIP.fromString(mqttServer)) //see if server is IP or domain { @@ -228,7 +227,7 @@ bool initMqtt() mqtt->setServer(mqttServer, mqttPort); } mqtt->setClientId(mqttClientID); - if (mqttUser[0] && mqttPass[0] != 0) mqtt->setCredentials(mqttUser, mqttPass); + if (mqttUser[0] && mqttPass[0]) mqtt->setCredentials(mqttUser, mqttPass); mqtt->onMessage(onMqttMessage); mqtt->onConnect(onMqttConnect); mqtt->connect(); diff --git a/wled00/wled18_server.ino b/wled00/wled18_server.ino index 07d1ea1d..6a937f32 100644 --- a/wled00/wled18_server.ino +++ b/wled00/wled18_server.ino @@ -64,8 +64,8 @@ void initServer() server.on("/settings/wifi", HTTP_POST, [](AsyncWebServerRequest *request){ if (!(wifiLock && otaLock)) handleSettingsSet(request, 1); - serveMessage(request, 200,"WiFi settings saved.","Rebooting now...",255); - doReboot = true; + serveMessage(request, 200,"WiFi settings saved.","Reconnecting now...",255); + forceReconnect = true; }); server.on("/settings/leds", HTTP_POST, [](AsyncWebServerRequest *request){