diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index fe6096d..165b891 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -91,7 +91,7 @@ jobs: - board: esp32c3 addr_bootloader: 0x0 chip: ESP32-C3 - fqbn: esp32:esp32:esp32c3:JTAGAdapter=default,CDCOnBoot=cdc,PartitionScheme=default,CPUFreq=160,FlashMode=qio,FlashFreq=80,FlashSize=4M,UploadSpeed=921600,DebugLevel=none,EraseFlash=none + fqbn: esp32:esp32:esp32c3:JTAGAdapter=default,CDCOnBoot=default,PartitionScheme=default,CPUFreq=160,FlashMode=qio,FlashFreq=80,FlashSize=4M,UploadSpeed=921600,DebugLevel=none,EraseFlash=none # esp32:esp32:esp32c3:JTAGAdapter=default,CDCOnBoot=default,PartitionScheme=default,CPUFreq=160,FlashMode=qio,FlashFreq=80,FlashSize=4M,UploadSpeed=921600,DebugLevel=none,EraseFlash=none name: ESP32C3 obname: SomfyController.onboard.esp32c3.bin @@ -99,7 +99,7 @@ jobs: - board: esp32s2 addr_bootloader: 0x1000 chip: ESP32-S2 - fqbn: esp32:esp32:esp32s2:JTAGAdapter=default,CDCOnBoot=cdc,MSCOnBoot=default,DFUOnBoot=default,UploadMode=default,PSRAM=disabled,PartitionScheme=default,CPUFreq=240,FlashMode=qio,FlashFreq=80,FlashSize=4M,UploadSpeed=921600,DebugLevel=none,EraseFlash=none + fqbn: esp32:esp32:esp32s2:JTAGAdapter=default,CDCOnBoot=default,MSCOnBoot=default,DFUOnBoot=default,UploadMode=default,PSRAM=disabled,PartitionScheme=default,CPUFreq=240,FlashMode=qio,FlashFreq=80,FlashSize=4M,UploadSpeed=921600,DebugLevel=none,EraseFlash=none # esp32:esp32:esp32s2:JTAGAdapter=default,CDCOnBoot=default,MSCOnBoot=default,DFUOnBoot=default,UploadMode=default,PSRAM=disabled,PartitionScheme=default,CPUFreq=240,FlashMode=qio,FlashFreq=80,FlashSize=4M,UploadSpeed=921600,DebugLevel=none,EraseFlash=none name: ESP32S2 obname: SomfyController.onboard.esp32s2.bin diff --git a/.gitignore b/.gitignore index be96788..8eec9f2 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,3 @@ debug.cfg SomfyController.ino.XIAO_ESP32S3.bin SomfyController.ino.esp32c3.bin SomfyController.ino.esp32s2.bin -.vscode/settings.json diff --git a/ConfigSettings.cpp b/ConfigSettings.cpp index 5deec5e..2906efb 100644 --- a/ConfigSettings.cpp +++ b/ConfigSettings.cpp @@ -580,21 +580,18 @@ bool WifiSettings::fromJSON(JsonObject &obj) { this->parseValueString(obj, "ssid", this->ssid, sizeof(this->ssid)); this->parseValueString(obj, "passphrase", this->passphrase, sizeof(this->passphrase)); if(obj.containsKey("roaming")) this->roaming = obj["roaming"]; - if(obj.containsKey("hidden")) this->hidden = obj["hidden"]; return true; } bool WifiSettings::toJSON(JsonObject &obj) { obj["ssid"] = this->ssid; obj["passphrase"] = this->passphrase; obj["roaming"] = this->roaming; - obj["hidden"] = this->hidden; return true; } void WifiSettings::toJSON(JsonResponse &json) { json.addElem("ssid", this->ssid); json.addElem("passphrase", this->passphrase); json.addElem("roaming", this->roaming); - json.addElem("hidden", this->hidden); } bool WifiSettings::save() { @@ -603,7 +600,6 @@ bool WifiSettings::save() { pref.putString("ssid", this->ssid); pref.putString("passphrase", this->passphrase); pref.putBool("roaming", this->roaming); - pref.putBool("hidden", this->hidden); pref.end(); return true; } @@ -614,7 +610,6 @@ bool WifiSettings::load() { this->ssid[sizeof(this->ssid) - 1] = '\0'; this->passphrase[sizeof(this->passphrase) - 1] = '\0'; this->roaming = pref.getBool("roaming", true); - this->hidden = pref.getBool("hidden", false); pref.end(); return true; } diff --git a/ConfigSettings.h b/ConfigSettings.h index 350db96..f5a5d0a 100644 --- a/ConfigSettings.h +++ b/ConfigSettings.h @@ -3,7 +3,7 @@ #ifndef configsettings_h #define configsettings_h #include "WResp.h" -#define FW_VERSION "v2.4.7" +#define FW_VERSION "v2.4.5" enum class conn_types_t : byte { unset = 0x00, wifi = 0x01, @@ -72,7 +72,6 @@ class WifiSettings: BaseSettings { public: WifiSettings(); bool roaming = true; - bool hidden = false; char ssid[65] = ""; char passphrase[65] = ""; //bool ssdpBroadcast = true; diff --git a/GitOTA.cpp b/GitOTA.cpp index 49ea3c5..4560ea9 100644 --- a/GitOTA.cpp +++ b/GitOTA.cpp @@ -252,7 +252,6 @@ void GitRepo::toJSON(JsonResponse &json) { #define ERR_DOWNLOAD_CONNECTION -42 void GitUpdater::loop() { - if(!net.connected()) return; if(this->status == GIT_STATUS_READY) { if(settings.checkForUpdate && (millis() > net.connectTime + 60000) && // Wait a minute before checking after connection. diff --git a/MQTT.cpp b/MQTT.cpp index 55f693a..e24c144 100644 --- a/MQTT.cpp +++ b/MQTT.cpp @@ -35,16 +35,12 @@ void MQTTClass::reset() { this->connect(); } bool MQTTClass::loop() { - if(settings.MQTT.enabled && !rebootDelay.reboot && !this->suspended && !mqttClient.connected()) { - esp_task_wdt_reset(); - if(!this->connected() && net.connected()) this->connect(); - } - esp_task_wdt_reset(); + if(settings.MQTT.enabled && !rebootDelay.reboot && !this->suspended && !mqttClient.connected()) + this->connect(); if(settings.MQTT.enabled) mqttClient.loop(); return true; } void MQTTClass::receive(const char *topic, byte*payload, uint32_t length) { - esp_task_wdt_reset(); // Make sure we do not reboot here. Serial.print("MQTT Topic:"); Serial.print(topic); Serial.print(" payload:"); @@ -183,10 +179,8 @@ void MQTTClass::receive(const char *topic, byte*payload, uint32_t length) { } } } - esp_task_wdt_reset(); // Make sure we do not reboot here. } bool MQTTClass::connect() { - esp_task_wdt_reset(); // Make sure we do not reboot here. if(mqttClient.connected()) { if(!settings.MQTT.enabled || this->suspended) return this->disconnect(); @@ -281,7 +275,6 @@ bool MQTTClass::unsubscribe(const char *topic) { } bool MQTTClass::subscribe(const char *topic) { if(mqttClient.connected()) { - esp_task_wdt_reset(); // Make sure we do not reboot here. char top[128]; if(strlen(settings.MQTT.rootTopic) > 0) snprintf(top, sizeof(top), "%s/%s", settings.MQTT.rootTopic, topic); @@ -300,7 +293,6 @@ bool MQTTClass::publish(const char *topic, const char *payload, bool retain) { snprintf(top, sizeof(top), "%s/%s", settings.MQTT.rootTopic, topic); else strlcpy(top, topic, sizeof(top)); - esp_task_wdt_reset(); // Make sure we do not reboot here. mqttClient.publish(top, payload, retain); return true; } @@ -317,7 +309,6 @@ bool MQTTClass::unpublish(const char *topic) { snprintf(top, sizeof(top), "%s/%s", settings.MQTT.rootTopic, topic); else strlcpy(top, topic, sizeof(top)); - esp_task_wdt_reset(); // Make sure we do not reboot here. mqttClient.publish(top, (const uint8_t *)"", 0, true); return true; } @@ -332,7 +323,6 @@ bool MQTTClass::publishBuffer(const char *topic, uint8_t *data, uint16_t len, bo uint16_t offset = 0; uint16_t to_write = len; uint16_t buff_len; - esp_task_wdt_reset(); // Make sure we do not reboot here. mqttClient.beginPublish(topic, len, retain); do { buff_len = to_write; diff --git a/Network.cpp b/Network.cpp index ad8f2e1..8025e69 100644 --- a/Network.cpp +++ b/Network.cpp @@ -34,9 +34,7 @@ bool Network::setup() { WiFi.setScanMethod(WIFI_ALL_CHANNEL_SCAN); WiFi.setSortMethod(WIFI_CONNECT_AP_BY_SIGNAL); WiFi.persistent(false); - WiFi.setAutoReconnect(false); WiFi.onEvent(this->networkEvent); - this->disconnectTime = millis(); if(WiFi.status() == WL_CONNECTED) WiFi.disconnect(true, true); if(settings.connType == conn_types_t::wifi || settings.connType == conn_types_t::unset) { WiFi.persistent(false); @@ -44,125 +42,66 @@ bool Network::setup() { Serial.print("WiFi Mode: "); Serial.println(WiFi.getMode()); WiFi.mode(WIFI_STA); + //settings.WIFI.printNetworks(); } sockEmit.begin(); return true; } -conn_types_t Network::preferredConnType() { - switch(settings.connType) { - case conn_types_t::wifi: - return settings.WIFI.ssid[0] != '\0' ? conn_types_t::wifi : conn_types_t::ap; - case conn_types_t::unset: - case conn_types_t::ap: - return conn_types_t::ap; - case conn_types_t::ethernetpref: - return settings.WIFI.ssid[0] != '\0' && (!ETH.linkUp() && this->ethStarted) ? conn_types_t::wifi : conn_types_t::ethernet; - case conn_types_t::ethernet: - return ETH.linkUp() || !this->ethStarted ? conn_types_t::ethernet : conn_types_t::ap; - default: - return settings.connType; - } -} void Network::loop() { - // ORDER OF OPERATIONS: - // ---------------------------------------------- - // 1. If we are in the middle of a connection process we need to simply bail after the connect method. The - // connect method will take care of our target connection for us. - // 2. Check to see what type of target connection we need. - // a. If this is an ethernet target then the connection needs to perform a fallback if applicable. - // b. If this is a wifi target then we need to first check to see if the SSID is available. - // c. If an SSID has not been set then we need to turn on the Soft AP. - // 3. If the Soft AP is open and the target is either wifi, ethernet, or ethernetpref then - // we need to shut it down if there are no connections and the preferred connection is available. - // a. Ethernet: Check for an active ethernet connection. We cannot rely on linkup because the PHY will - // report that the link is up when no IP address is being served. - // 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. - 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. - if(_apScanning) { - if(settings.WIFI.hidden || // This user has elected to use a hidden AP. - (this->connected() && !settings.WIFI.roaming) || // We are already connected and should not be roaming. - (this->softAPOpened && WiFi.softAPgetStationNum() != 0) || // The Soft AP is open and a user is connected. - (ctype != conn_types_t::wifi)) { // The Ethernet link is up so we should ignore this scan. - Serial.println("Cancelling WiFi STA Scan..."); - _apScanning = false; - WiFi.scanDelete(); + this->connect(); + if(!this->connected() || this->connecting()) return; + if(millis() - this->lastEmit > 1500) { + this->lastEmit = millis(); + if(this->connected()) { + this->emitSockets(); + this->lastEmit = millis(); } + } + sockEmit.loop(); + if(this->connected() && millis() - this->lastMDNS > 60000) { + // Every 60 seconds we are going to look at wifi connectivity + // to get around the roaming issues with ESP32. We will try to do this in an async manner. If + // there is a channel that is better we will stop the wifi radio and reconnect + if(this->connType == conn_types_t::wifi && settings.WIFI.roaming && !this->softAPOpened) { + // If we are not already scanning then we need to start a passive scan + // and only respond if there is a better connection. + // 1. If there is currently a waiting scan don't do anything + if(!_apScanning && WiFi.scanNetworks(true, false, true, 300, 0, settings.WIFI.ssid) == -1) { + _apScanning = true; + } + } + this->lastMDNS = millis(); + } + if(_apScanning) { + if(!settings.WIFI.roaming || this->connType != conn_types_t::wifi || this->softAPOpened) _apScanning = false; else { - int16_t n = WiFi.scanComplete(); - if( n >= 0) { // If the scan is complete but the WiFi isn't ready this can return 0. + uint16_t n = WiFi.scanComplete(); + if( n > 0) { uint8_t bssid[6]; int32_t channel = 0; if(this->getStrongestAP(settings.WIFI.ssid, bssid, &channel)) { - if(!WiFi.BSSID() || memcmp(bssid, WiFi.BSSID(), sizeof(bssid)) != 0) { - if(!this->connected()) { - Serial.printf("Connecting to AP %02X:%02X:%02X:%02X:%02X:%02X CH: %d\n", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5], channel); - this->connectWiFi(bssid, channel); - } - else { - Serial.printf("Found stronger AP %02X:%02X:%02X:%02X:%02X:%02X CH: %d\n", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5], channel); - this->changeAP(bssid, channel); - } + if(memcmp(bssid, WiFi.BSSID(), sizeof(bssid)) != 0) { + Serial.printf("Found stronger AP %d %02X:%02X:%02X:%02X:%02X:%02X\n", channel, bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); + this->changeAP(bssid, channel); } } _apScanning = false; } } } - if(!this->connecting() && !settings.WIFI.hidden) { - 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 - // our target exists we will exit out of the Soft AP and start that connection. We are also - // going to continuously scan when there is no connection and our preferred connection is wifi. - if(ctype == conn_types_t::wifi) { - // Scan for an AP but only if we are not already scanning. - if(!_apScanning && WiFi.scanNetworks(true, false, true, 300, 0, settings.WIFI.ssid) == -1) { - _apScanning = true; - } - } - } - else if(this->connected() && ctype == conn_types_t::wifi && settings.WIFI.roaming) { - // Periodically look for a roaming AP. - if(millis() > SSID_SCAN_INTERVAL + this->lastWifiScan) { - //Serial.println("Started scan for access points"); - if(!_apScanning && WiFi.scanNetworks(true, false, true, 300, 0, settings.WIFI.ssid) == -1) { - _apScanning = true; - this->lastWifiScan = millis(); - } - } - } - } - if(millis() - this->lastEmit > 1500) { - // Post our connection status if needed. - this->lastEmit = millis(); - if(this->connected()) { - this->emitSockets(); - this->lastEmit = millis(); - } - esp_task_wdt_reset(); // Make sure we do not reboot here. - } - - sockEmit.loop(); - mqtt.loop(); - if(settings.ssdpBroadcast && this->connected()) { + if(settings.ssdpBroadcast) { if(!SSDP.isStarted) SSDP.begin(); if(SSDP.isStarted) SSDP.loop(); } else if(!settings.ssdpBroadcast && SSDP.isStarted) SSDP.end(); + mqtt.loop(); } bool Network::changeAP(const uint8_t *bssid, const int32_t channel) { esp_task_wdt_reset(); // Make sure we do not reboot here. if(SSDP.isStarted) SSDP.end(); mqtt.disconnect(); - //sockEmit.end(); + sockEmit.end(); WiFi.disconnect(false, true); - this->connType = conn_types_t::unset; - this->_connecting = true; - this->connectStart = millis(); WiFi.begin(settings.WIFI.ssid, settings.WIFI.passphrase, channel, bssid); this->connectStart = millis(); return false; @@ -177,6 +116,7 @@ void Network::emitSockets() { } } void Network::emitSockets(uint8_t num) { + //char buf[128]; if(this->connType == conn_types_t::ethernet) { JsonSockEvent *json = sockEmit.beginEmit("ethernet"); json->beginObject(); @@ -185,6 +125,13 @@ void Network::emitSockets(uint8_t num) { json->addElem("fullduplex", ETH.fullDuplex()); json->endObject(); sockEmit.endEmit(num); + /* + snprintf(buf, sizeof(buf), "{\"connected\":%s,\"speed\":%d,\"fullduplex\":%s}", this->connected() ? "true" : "false", ETH.linkSpeed(), ETH.fullDuplex() ? "true" : "false"); + if(num == 255) + sockEmit.sendToClients("ethernet", buf); + else + sockEmit.sendToClient(num, "ethernet", buf); + */ } else { if(WiFi.status() == WL_CONNECTED) { @@ -195,6 +142,13 @@ void Network::emitSockets(uint8_t num) { json->addElem("channel", (int32_t)this->channel); json->endObject(); sockEmit.endEmit(num); + /* + snprintf(buf, sizeof(buf), "{\"ssid\":\"%s\",\"strength\":%d,\"channel\":%d}", WiFi.SSID().c_str(), WiFi.RSSI(), this->channel); + if(num == 255) + sockEmit.sendToClients("wifiStrength", buf); + else + sockEmit.sendToClient(num, "wifiStrength", buf); + */ this->lastRSSI = WiFi.RSSI(); this->lastChannel = WiFi.channel(); } @@ -214,6 +168,17 @@ void Network::emitSockets(uint8_t num) { json->addElem("fullduplex", false); json->endObject(); sockEmit.endEmit(num); + /* + + if(num == 255) { + sockEmit.sendToClients("wifiStrength", "{\"ssid\":\"\", \"strength\":-100,\"channel\":-1}"); + sockEmit.sendToClients("ethernet", "{\"connected\":false,\"speed\":0,\"fullduplex\":false}"); + } + else { + sockEmit.sendToClient(num, "wifiStrength", "{\"ssid\":\"\", \"strength\":-100,\"channel\":-1}"); + sockEmit.sendToClient(num, "ethernet", "{\"connected\":false,\"speed\":0,\"fullduplex\":false}"); + } + */ this->lastRSSI = -100; this->lastChannel = -1; } @@ -221,11 +186,9 @@ void Network::emitSockets(uint8_t num) { this->emitHeap(num); } void Network::setConnected(conn_types_t connType) { - esp_task_wdt_reset(); this->connType = connType; this->connectTime = millis(); connectRetries = 0; - Serial.println("Setting connected..."); if(this->connType == conn_types_t::wifi) { if(this->softAPOpened && WiFi.softAPgetStationNum() == 0) { WiFi.softAPdisconnect(true); @@ -250,8 +213,6 @@ void Network::setConnected(conn_types_t connType) { } // NET: Begin this in the startup. //sockEmit.begin(); - esp_task_wdt_reset(); - if(this->connectAttempts == 1) { Serial.println(); if(this->connType == conn_types_t::wifi) { @@ -284,7 +245,6 @@ void Network::setConnected(conn_types_t connType) { settings.IP.dns1 = ETH.dnsIP(0); settings.IP.dns2 = ETH.dnsIP(1); } - esp_task_wdt_reset(); JsonSockEvent *json = sockEmit.beginEmit("ethernet"); json->beginObject(); json->addElem("connected", this->connected()); @@ -292,7 +252,6 @@ void Network::setConnected(conn_types_t connType) { json->addElem("fullduplex", ETH.fullDuplex()); json->endObject(); sockEmit.endEmit(); - esp_task_wdt_reset(); } } else { @@ -343,7 +302,6 @@ void Network::setConnected(conn_types_t connType) { SSDP.setManufacturerURL(0, "https://github.com/rstrouse"); SSDP.setURL(0, "/"); SSDP.setActive(0, true); - esp_task_wdt_reset(); if(MDNS.begin(settings.hostname)) { Serial.printf("MDNS Responder Started: serverId=%s\n", settings.serverId); MDNS.addService("http", "tcp", 80); @@ -356,11 +314,9 @@ void Network::setConnected(conn_types_t connType) { MDNS.addServiceTxt("espsomfy_rts", "tcp", "version", String(settings.fwVersion.name)); } if(settings.ssdpBroadcast) { - esp_task_wdt_reset(); SSDP.begin(); } else if(SSDP.isStarted) SSDP.end(); - esp_task_wdt_reset(); this->emitSockets(); settings.printAvailHeap(); this->needsBroadcast = true; @@ -369,15 +325,15 @@ bool Network::connectWired() { if(ETH.linkUp()) { // If the ethernet link is re-established then we need to shut down wifi. if(WiFi.status() == WL_CONNECTED) { - //sockEmit.end(); + sockEmit.end(); WiFi.disconnect(true); WiFi.mode(WIFI_OFF); } if(this->connType != conn_types_t::ethernet) this->setConnected(conn_types_t::ethernet); + this->wifiFallback = false; return true; } else if(this->ethStarted) { - // There is no wired connection so we need to fallback if appropriate. if(settings.connType == conn_types_t::ethernetpref && settings.WIFI.ssid[0] != '\0') return this->connectWiFi(); } @@ -391,34 +347,34 @@ bool Network::connectWired() { this->connTarget = conn_types_t::ethernet; this->connType = conn_types_t::unset; if(!this->ethStarted) { - // Currently the ethernet module will leak memory if you call begin more than once. - this->ethStarted = true; - WiFi.mode(WIFI_OFF); - if(settings.hostname[0] != '\0') - ETH.setHostname(settings.hostname); - else - ETH.setHostname("ESPSomfy-RTS"); - Serial.print("Set hostname to:"); - Serial.println(ETH.getHostname()); - if(!ETH.begin(settings.Ethernet.phyAddress, settings.Ethernet.PWRPin, settings.Ethernet.MDCPin, settings.Ethernet.MDIOPin, settings.Ethernet.phyType, settings.Ethernet.CLKMode)) { - Serial.println("Ethernet Begin failed"); - this->ethStarted = false; - if(settings.connType == conn_types_t::ethernetpref) { - this->wifiFallback = true; - return connectWiFi(); - } - return false; - } - else { - if(!settings.IP.dhcp) { - if(!ETH.config(settings.IP.ip, settings.IP.gateway, settings.IP.subnet, settings.IP.dns1, settings.IP.dns2)) { - Serial.println("Unable to configure static IP address...."); - ETH.config(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE); - } - } + this->ethStarted = true; + WiFi.mode(WIFI_OFF); + if(settings.hostname[0] != '\0') + ETH.setHostname(settings.hostname); else - ETH.config(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE); - } + ETH.setHostname("ESPSomfy-RTS"); + + Serial.print("Set hostname to:"); + Serial.println(ETH.getHostname()); + if(!ETH.begin(settings.Ethernet.phyAddress, settings.Ethernet.PWRPin, settings.Ethernet.MDCPin, settings.Ethernet.MDIOPin, settings.Ethernet.phyType, settings.Ethernet.CLKMode)) { + Serial.println("Ethernet Begin failed"); + this->ethStarted = false; + if(settings.connType == conn_types_t::ethernetpref) { + this->wifiFallback = true; + return connectWiFi(); + } + return false; + } + else { + if(!settings.IP.dhcp) { + if(!ETH.config(settings.IP.ip, settings.IP.gateway, settings.IP.subnet, settings.IP.dns1, settings.IP.dns2)) { + Serial.println("Unable to configure static IP address...."); + ETH.config(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE); + } + } + else + ETH.config(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE); + } } this->connectStart = millis(); return true; @@ -440,43 +396,18 @@ void Network::updateHostname() { } } } -bool Network::connectWiFi(const uint8_t *bssid, const int32_t channel) { +bool Network::connectWiFi() { if(this->softAPOpened && WiFi.softAPgetStationNum() > 0) { - // There is a client connected to the soft AP. We do not want to close out the connection. While both the - // Soft AP and a wifi connection can coexist on ESP32 the performance is abysmal. WiFi.disconnect(false); this->_connecting = false; this->connType = conn_types_t::unset; return true; } - WiFi.setSleep(false); - if(!settings.IP.dhcp) { - if(!WiFi.config(settings.IP.ip, settings.IP.gateway, settings.IP.subnet, settings.IP.dns1, settings.IP.dns2)) - WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE); - } - else - WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE); - if(settings.hostname[0] != '\0') WiFi.setHostname(settings.hostname); - delay(100); - - if(bssid && channel > 0) { - if(WiFi.status() == WL_CONNECTED && WiFi.SSID().compareTo(settings.WIFI.ssid) == 0 - && WiFi.channel() == channel) { - this->disconnected = 0; - return true; - } - this->connTarget = conn_types_t::wifi; - this->connType = conn_types_t::unset; - Serial.println("WiFi begin..."); - this->_connecting = true; - WiFi.begin(settings.WIFI.ssid, settings.WIFI.passphrase, channel, bssid); - this->connectStart = millis(); - } - else if(settings.WIFI.ssid[0] != '\0') { + + if(settings.WIFI.ssid[0] != '\0') { if(WiFi.status() == WL_CONNECTED && WiFi.SSID().compareTo(settings.WIFI.ssid) == 0) { // If we are connected to the target SSID then just return. this->disconnected = 0; - this->_connecting = true; return true; } if(this->_connecting) return true; @@ -493,49 +424,74 @@ bool Network::connectWiFi(const uint8_t *bssid, const int32_t channel) { Serial.println("dbm) "); } else Serial.println("Connecting to AP"); + // If the soft AP is currently opened then we do not want to kill it. + WiFi.setSleep(false); + WiFi.disconnect(false); + //WiFi.mode(WIFI_MODE_NULL); + if(!settings.IP.dhcp) { + if(!WiFi.config(settings.IP.ip, settings.IP.gateway, settings.IP.subnet, settings.IP.dns1, settings.IP.dns2)) + WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE); + } + else + WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE); delay(100); // There is also another method simply called hostname() but this is legacy for esp8266. if(settings.hostname[0] != '\0') WiFi.setHostname(settings.hostname); Serial.print("Set hostname to:"); Serial.println(WiFi.getHostname()); + //WiFi.mode(WIFI_STA); WiFi.setScanMethod(WIFI_ALL_CHANNEL_SCAN); WiFi.setSortMethod(WIFI_CONNECT_AP_BY_SIGNAL); - uint8_t _bssid[6]; - int32_t _channel = 0; - if(!settings.WIFI.hidden && this->getStrongestAP(settings.WIFI.ssid, _bssid, &_channel)) { - Serial.printf("Found strongest AP %02X:%02X:%02X:%02X:%02X:%02X CH:%d\n", _bssid[0], _bssid[1], _bssid[2], _bssid[3], _bssid[4], _bssid[5], _channel); - WiFi.begin(settings.WIFI.ssid, settings.WIFI.passphrase, _channel, _bssid); + uint8_t bssid[6]; + int32_t channel = 0; + if(this->getStrongestAP(settings.WIFI.ssid, bssid, &channel)) { + Serial.printf("Found strongest AP %d %02X:%02X:%02X:%02X:%02X:%02X\n", channel, bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); + WiFi.begin(settings.WIFI.ssid, settings.WIFI.passphrase, channel, bssid); } else - // If the user has the hidden flag set just connect to whatever the AP gives us. WiFi.begin(settings.WIFI.ssid, settings.WIFI.passphrase); } this->connectStart = millis(); return true; } -bool Network::connect(conn_types_t ctype) { - esp_task_wdt_reset(); - if(this->connecting()) return true; - if(this->disconnectTime == 0) this->disconnectTime = millis(); - if(ctype == conn_types_t::ethernet && this->connType != conn_types_t::ethernet) { - // Here we need to call the connect to ethernet. +bool Network::connect() { + if(this->connecting()) { + // We are currently connecting and this flag is triggered while there is an attempt + // to connect to the network. If the connection type is set then we need to + // finish the connection. If it is not then we need to fall back to AP or in + // the case where the target was originally ethernet then we need to open the softAP. + if(this->connType == conn_types_t::unset) { + // If we reached our timeout for the connection then we need to open the soft ap. + if(millis() > this->connectStart + CONNECT_TIMEOUT) { + esp_task_wdt_reset(); + if(this->connTarget == conn_types_t::ethernet && settings.connType == conn_types_t::ethernetpref && settings.WIFI.ssid[0] != '\0') + this->connectWiFi(); + else if(this->softAPOpened) { + if(settings.connType == conn_types_t::ethernet || settings.connType == conn_types_t::ethernetpref) + this->connectWired(); + else if(settings.connType == conn_types_t::wifi && strlen(settings.WIFI.ssid) > 0) + this->connectWiFi(); + } + else { + //Serial.println("Fell into timeout"); + this->openSoftAP(); + } + } + } + else + this->setConnected(this->connTarget); + } + else if(settings.connType == conn_types_t::ethernet || settings.connType == conn_types_t::ethernetpref) this->connectWired(); - } - else if(ctype == conn_types_t::ap || (!this->connected() && millis() > this->disconnectTime + CONNECT_TIMEOUT)) { - if(!this->softAPOpened && !this->openingSoftAP) { - this->disconnectTime = millis(); - this->openSoftAP(); - } - else if(this->softAPOpened && !this->openingSoftAP && - (ctype == conn_types_t::wifi && this->connType != conn_types_t::wifi && settings.WIFI.hidden)) { - // When thge softAP is open then we need to try to connect to wifi repeatedly if the user connects to a hidden SSID. - this->connectWiFi(); - } - } - else if((ctype == conn_types_t::wifi && this->connType != conn_types_t::wifi && settings.WIFI.hidden)) { + else if(settings.connType == conn_types_t::wifi && strlen(settings.WIFI.ssid) > 0) this->connectWiFi(); + else + this->openSoftAP(); + if(this->softAPOpened && this->connected() && WiFi.softAPgetStationNum() == 0) { + Serial.println("Closing uneeded SoftAP"); + WiFi.softAPdisconnect(true); + if(this->connType == conn_types_t::wifi) WiFi.mode(WIFI_STA); } - return true; } uint32_t Network::getChipId() { @@ -546,16 +502,16 @@ uint32_t Network::getChipId() { } return chipId; } + bool Network::getStrongestAP(const char *ssid, uint8_t *bssid, int32_t *channel) { // The new AP must be at least 10dbm greater. int32_t strength = this->connected() ? WiFi.RSSI() + 10 : -127; int32_t chan = -1; memset(bssid, 0x00, 6); esp_task_wdt_delete(NULL); - int16_t n = WiFi.scanComplete(); - //int16_t n = this->connected() ? WiFi.scanComplete() : WiFi.scanNetworks(false, false, false, 300, 0, ssid); + uint8_t n = this->connected() ? WiFi.scanComplete() : WiFi.scanNetworks(false, false, false, 300, 0, ssid); esp_task_wdt_add(NULL); - for(int16_t i = 0; i < n; i++) { + for(uint8_t i = 0; i < n; i++) { if(WiFi.SSID(i).compareTo(ssid) == 0) { if(WiFi.RSSI(i) > strength) { strength = WiFi.RSSI(i); @@ -569,12 +525,13 @@ bool Network::getStrongestAP(const char *ssid, uint8_t *bssid, int32_t *channel) } bool Network::openSoftAP() { if(this->softAPOpened || this->openingSoftAP) return true; - if(this->connected()) WiFi.disconnect(false); + WiFi.disconnect(false); this->openingSoftAP = true; Serial.println(); Serial.println("Turning the HotSpot On"); esp_task_wdt_reset(); // Make sure we do not reboot here. - WiFi.softAP(strlen(settings.hostname) > 0 ? settings.hostname : "ESPSomfy RTS", ""); + WiFi.softAP("ESPSomfy RTS", ""); + Serial.println("Initializing AP for credentials modification"); delay(200); return true; } @@ -587,37 +544,25 @@ bool Network::connected() { return false; } bool Network::connecting() { - if(this->_connecting && millis() > this->connectStart + CONNECT_TIMEOUT) this->_connecting = false; - return this->_connecting; + return this->_connecting; } -void Network::clearConnecting() { this->_connecting = false; } void Network::networkEvent(WiFiEvent_t event) { switch(event) { case ARDUINO_EVENT_WIFI_READY: Serial.println("(evt) WiFi interface ready"); break; - case ARDUINO_EVENT_WIFI_SCAN_DONE: - Serial.printf("(evt) Completed scan for access points (%d)\n", WiFi.scanComplete()); - //Serial.println("(evt) Completed scan for access points"); - net.lastWifiScan = millis(); - break; + case ARDUINO_EVENT_WIFI_SCAN_DONE: Serial.println("(evt) Completed scan for access points"); break; case ARDUINO_EVENT_WIFI_STA_START: Serial.println("WiFi station mode started"); if(settings.hostname[0] != '\0') WiFi.setHostname(settings.hostname); break; case ARDUINO_EVENT_WIFI_STA_STOP: Serial.println("(evt) WiFi clients stopped"); break; - case ARDUINO_EVENT_WIFI_STA_CONNECTED: Serial.println("(evt) Connected to WiFi STA access point"); break; - case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: - Serial.printf("(evt) Disconnected from WiFi STA access point. Connecting: %d\n", net.connecting()); - net.connType = conn_types_t::unset; - net.disconnectTime = millis(); - net.clearConnecting(); - break; - case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE: Serial.println("(evt) Authentication mode of STA access point has changed"); break; + case ARDUINO_EVENT_WIFI_STA_CONNECTED: Serial.println("(evt) Connected to access point"); break; + case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: Serial.println("(evt) Disconnected from WiFi access point"); break; + case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE: Serial.println("(evt) Authentication mode of access point has changed"); break; case ARDUINO_EVENT_WIFI_STA_GOT_IP: - Serial.print("(evt) Got WiFi STA IP: "); + Serial.print("Got WiFi IP: "); Serial.println(WiFi.localIP()); net.connType = conn_types_t::wifi; net.connectTime = millis(); - net.setConnected(conn_types_t::wifi); break; case ARDUINO_EVENT_WIFI_STA_LOST_IP: Serial.println("Lost IP address and IP address is reset to 0"); break; case ARDUINO_EVENT_ETH_GOT_IP: @@ -627,14 +572,6 @@ void Network::networkEvent(WiFiEvent_t event) { Serial.println(ETH.localIP()); net.connectTime = millis(); net.connType = conn_types_t::ethernet; - if(settings.IP.dhcp) { - settings.IP.ip = ETH.localIP(); - settings.IP.subnet = ETH.subnetMask(); - settings.IP.gateway = ETH.gatewayIP(); - settings.IP.dns1 = ETH.dnsIP(0); - settings.IP.dns2 = ETH.dnsIP(1); - } - net.setConnected(conn_types_t::ethernet); break; case ARDUINO_EVENT_ETH_CONNECTED: Serial.print("(evt) Ethernet Connected "); @@ -642,8 +579,6 @@ void Network::networkEvent(WiFiEvent_t event) { case ARDUINO_EVENT_ETH_DISCONNECTED: Serial.println("(evt) Ethernet Disconnected"); net.connType = conn_types_t::unset; - net.disconnectTime = millis(); - net.clearConnecting(); break; case ARDUINO_EVENT_ETH_START: Serial.println("(evt) Ethernet Started"); @@ -661,7 +596,8 @@ void Network::networkEvent(WiFiEvent_t event) { net.softAPOpened = true; break; case ARDUINO_EVENT_WIFI_AP_STOP: - if(!net.openingSoftAP) Serial.println("(evt) WiFi SoftAP Stopped"); + Serial.println("(evt) WiFi SoftAP Stopped"); + //if(net.softAPOpened) net.openingSoftAP = false; net.softAPOpened = false; break; default: diff --git a/Network.h b/Network.h index 864966c..9f4e443 100644 --- a/Network.h +++ b/Network.h @@ -6,7 +6,6 @@ //enum class conn_types_t : byte; #define CONNECT_TIMEOUT 20000 -#define SSID_SCAN_INTERVAL 60000 class Network { protected: unsigned long lastEmit = 0; @@ -16,7 +15,6 @@ class Network { int linkSpeed = 0; bool _connecting = false; public: - unsigned long lastWifiScan = 0; bool ethStarted = false; bool wifiFallback = false; bool softAPOpened = false; @@ -26,20 +24,17 @@ class Network { conn_types_t connTarget = conn_types_t::unset; bool connected(); bool connecting(); - void clearConnecting(); - conn_types_t preferredConnType(); String ssid; String mac; int channel; int strength; int disconnected = 0; int connectAttempts = 0; - uint32_t disconnectTime = 0; uint32_t connectStart = 0; uint32_t connectTime = 0; bool openSoftAP(); - bool connect(conn_types_t ctype); - bool connectWiFi(const uint8_t *bssid = nullptr, const int32_t channel = -1); + bool connect(); + bool connectWiFi(); bool connectWired(); void setConnected(conn_types_t connType); bool getStrongestAP(const char *ssid, uint8_t *bssid, int32_t *channel); diff --git a/SSDP.cpp b/SSDP.cpp index f866865..6f76a1f 100644 --- a/SSDP.cpp +++ b/SSDP.cpp @@ -161,7 +161,7 @@ void UPNPDeviceType::setChipId(uint32_t chipId) { (uint16_t)chipId & 0xff); } SSDPClass::SSDPClass():sendQueue{false, INADDR_NONE, 0, nullptr, false, 0, "", response_types_t::root} {} -SSDPClass::~SSDPClass() { end(); this->isStarted = false; } +SSDPClass::~SSDPClass() { end(); } bool SSDPClass::begin() { for(int i = 0; i < SSDP_QUEUE_SIZE; i++) { this->sendQueue[i].waiting = false; @@ -209,7 +209,6 @@ void SSDPClass::end() { if(this->_server.connected()) { this->_sendByeBye(); this->_server.close(); - Serial.println("Disconnected from SSDP..."); } this->isStarted = false; // Clear out the last notified so if the user starts us up again it will notify @@ -217,6 +216,8 @@ void SSDPClass::end() { for(uint8_t i = 0; i < this->m_cdeviceTypes; i++) { this->deviceTypes[i].lastNotified = 0; } + + Serial.println("Disconnected from SSDP..."); } UPNPDeviceType* SSDPClass::getDeviceType(uint8_t ndx) { if(ndx < this->m_cdeviceTypes) return &this->deviceTypes[ndx]; return nullptr; } UPNPDeviceType* SSDPClass::findDeviceByType(char *devType) { diff --git a/Sockets.cpp b/Sockets.cpp index 51765aa..6d098a8 100644 --- a/Sockets.cpp +++ b/Sockets.cpp @@ -43,9 +43,6 @@ bool room_t::leave(uint8_t num) { } return true; } -void room_t::clear() { - memset(this->clients, 255, sizeof(this->clients)); -} uint8_t room_t::activeClients() { uint8_t n = 0; for(uint8_t i = 0; i < sizeof(this->clients); i++) { @@ -80,7 +77,7 @@ void SocketEmitter::begin() { sockServer.enableHeartbeat(20000, 10000, 3); sockServer.onEvent(this->wsEvent); Serial.println("Socket Server Started..."); - //settings.printAvailHeap(); + settings.printAvailHeap(); } void SocketEmitter::loop() { this->initClients(); @@ -129,11 +126,7 @@ void SocketEmitter::delayInit(uint8_t num) { } } } -void SocketEmitter::end() { - sockServer.close(); - for(uint8_t i = 0; i < SOCK_MAX_ROOMS; i++) - this->rooms[i].clear(); -} +void SocketEmitter::end() { sockServer.close(); } void SocketEmitter::disconnect() { sockServer.disconnect(); } void SocketEmitter::wsEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length) { switch(type) { diff --git a/Sockets.h b/Sockets.h index d76ab93..f6acf46 100644 --- a/Sockets.h +++ b/Sockets.h @@ -12,7 +12,6 @@ struct room_t { bool isJoined(uint8_t num); bool join(uint8_t num); bool leave(uint8_t num); - void clear(); }; class SocketEmitter { protected: diff --git a/SomfyController.ino b/SomfyController.ino index 464d179..46dfc8d 100644 --- a/SomfyController.ino +++ b/SomfyController.ino @@ -49,9 +49,7 @@ void loop() { Serial.print("Rebooting after "); Serial.print(rebootDelay.rebootTime); Serial.println("ms"); - net.end(); ESP.restart(); - return; } uint32_t timing = millis(); diff --git a/SomfyController.ino.esp32.bin b/SomfyController.ino.esp32.bin index bb87d58..4e613d7 100644 Binary files a/SomfyController.ino.esp32.bin and b/SomfyController.ino.esp32.bin differ diff --git a/SomfyController.ino.esp32s3.bin b/SomfyController.ino.esp32s3.bin index 76f303c..1c00b7e 100644 Binary files a/SomfyController.ino.esp32s3.bin and b/SomfyController.ino.esp32s3.bin differ diff --git a/SomfyController.littlefs.bin b/SomfyController.littlefs.bin index 98d9f83..a05cd1a 100644 Binary files a/SomfyController.littlefs.bin and b/SomfyController.littlefs.bin differ diff --git a/WResp.cpp b/WResp.cpp index e44e3ba..3b158ca 100644 --- a/WResp.cpp +++ b/WResp.cpp @@ -21,7 +21,7 @@ void JsonSockEvent::endEvent(uint8_t num) { else this->server->sendTXT(num, this->buff); } void JsonSockEvent::_safecat(const char *val, bool escape) { - size_t len = (escape ? this->calcEscapedLength(val) : strlen(val)) + strlen(this->buff); + size_t len = strlen(val) + strlen(this->buff); if(escape) len += 2; if(len >= this->buffSize) { Serial.printf("Socket exceeded buffer size %d - %d\n", this->buffSize, len); @@ -29,8 +29,7 @@ void JsonSockEvent::_safecat(const char *val, bool escape) { return; } if(escape) strcat(this->buff, "\""); - if(escape) this->escapeString(val, &this->buff[strlen(this->buff)]); - else strcat(this->buff, val); + strcat(this->buff, val); if(escape) strcat(this->buff, "\""); } void JsonResponse::beginResponse(WebServer *server, char *buff, size_t buffSize) { @@ -53,14 +52,13 @@ void JsonResponse::send() { this->_headersSent = true; } void JsonResponse::_safecat(const char *val, bool escape) { - size_t len = (escape ? this->calcEscapedLength(val) : strlen(val)) + strlen(this->buff); + size_t len = strlen(val) + strlen(this->buff); if(escape) len += 2; if(len >= this->buffSize) { this->send(); } if(escape) strcat(this->buff, "\""); - if(escape) this->escapeString(val, &this->buff[strlen(this->buff)]); - else strcat(this->buff, val); + strcat(this->buff, val); if(escape) strcat(this->buff, "\""); } @@ -135,70 +133,13 @@ void JsonFormatter::addElem(const char *name, uint64_t lval) { sprintf(this->_nu void JsonFormatter::addElem(const char *name, bool bval) { strcpy(this->_numbuff, bval ? "true" : "false"); this->_appendNumber(name); } void JsonFormatter::_safecat(const char *val, bool escape) { - size_t len = (escape ? this->calcEscapedLength(val) : strlen(val)) + strlen(this->buff); + size_t len = strlen(val) + strlen(this->buff); if(escape) len += 2; if(len >= this->buffSize) { return; } if(escape) strcat(this->buff, "\""); - if(escape) this->escapeString(val, &this->buff[strlen(this->buff)]); - else strcat(this->buff, val); + strcat(this->buff, val); if(escape) strcat(this->buff, "\""); } void JsonFormatter::_appendNumber(const char *name) { this->appendElem(name); this->_safecat(this->_numbuff); } -uint32_t JsonFormatter::calcEscapedLength(const char *raw) { - uint32_t len = 0; - for(size_t i = strlen(raw); i > 0; i--) { - switch(raw[i]) { - case '"': - case '/': - case '\b': - case '\f': - case '\n': - case '\r': - case '\t': - case '\\': - len += 2; - break; - default: - len++; - break; - } - } - return len; -} -void JsonFormatter::escapeString(const char *raw, char *escaped) { - for(uint32_t i = 0; i < strlen(raw); i++) { - switch(raw[i]) { - case '"': - strcat(escaped, "\\\""); - break; - case '/': - strcat(escaped, "\\/"); - break; - case '\b': - strcat(escaped, "\\b"); - break; - case '\f': - strcat(escaped, "\\f"); - break; - case '\n': - strcat(escaped, "\\n"); - break; - case '\r': - strcat(escaped, "\\r"); - break; - case '\t': - strcat(escaped, "\\t"); - break; - case '\\': - strcat(escaped, "\\\\"); - break; - default: - size_t len = strlen(escaped); - escaped[len] = raw[i]; - escaped[len+1] = 0x00; - break; - } - } -} diff --git a/WResp.h b/WResp.h index 4bda5d5..f1a7f2c 100644 --- a/WResp.h +++ b/WResp.h @@ -16,8 +16,6 @@ class JsonFormatter { virtual void _safecat(const char *val, bool escape = false); void _appendNumber(const char *name); public: - void escapeString(const char *raw, char *escaped); - uint32_t calcEscapedLength(const char *raw); void beginObject(const char *name = nullptr); void endObject(); void beginArray(const char *name = nullptr); diff --git a/data/appversion b/data/appversion index 48a6b50..26f8b8b 100644 --- a/data/appversion +++ b/data/appversion @@ -1 +1 @@ -2.4.7 \ No newline at end of file +2.4.5 \ No newline at end of file diff --git a/data/index.html b/data/index.html index fda0670..41be767 100644 --- a/data/index.html +++ b/data/index.html @@ -8,9 +8,9 @@ - - - + + + @@ -114,7 +114,7 @@ rel="apple-touch-startup-image"> - +
@@ -160,7 +160,7 @@
-
+
@@ -275,24 +275,17 @@