diff --git a/ConfigSettings.cpp b/ConfigSettings.cpp index 00bb781..d1f4289 100644 --- a/ConfigSettings.cpp +++ b/ConfigSettings.cpp @@ -67,6 +67,7 @@ bool ConfigSettings::begin() { (uint16_t)((chipId >> 16) & 0xff), (uint16_t)((chipId >> 8) & 0xff), (uint16_t)chipId & 0xff); + this->load(); this->WIFI.begin(); this->Ethernet.begin(); this->NTP.begin(); @@ -110,11 +111,14 @@ bool ConfigSettings::toJSON(JsonObject &obj) { bool ConfigSettings::fromJSON(JsonObject &obj) { if(obj.containsKey("ssdpBroadcast")) this->ssdpBroadcast = obj["ssdpBroadcast"]; if(obj.containsKey("hostname")) this->parseValueString(obj, "hostname", this->hostname, sizeof(this->hostname)); + if(obj.containsKey("connType")) this->connType = static_cast(obj["connType"].as()); return true; } void ConfigSettings::print() { + Serial.printf("Connection Type: %d\n", this->connType); this->NTP.print(); - this->WIFI.print(); + if(this->connType == conn_types::wifi || this->connType == conn_types::unset) this->WIFI.print(); + if(this->connType == conn_types::ethernet || this->connType == conn_types::ethernetpref) this->Ethernet.print(); } void ConfigSettings::emitSockets() {} void ConfigSettings::emitSockets(uint8_t num) {} @@ -321,6 +325,15 @@ bool EthernetSettings::begin() { return true; } bool EthernetSettings::fromJSON(JsonObject &obj) { + if(obj.containsKey("dhcp")) this->dhcp = obj["dhcp"]; + if(obj.containsKey("boardType")) this->boardType = obj["boardType"]; + if(obj.containsKey("phyAddress")) this->phyAddress = obj["phyAddress"]; + if(obj.containsKey("CLKMode")) this->CLKMode = static_cast(obj["CLKMode"]); + if(obj.containsKey("phyType")) this->phyType = static_cast(obj["phyType"]); + if(obj.containsKey("PWRPin")) this->PWRPin = obj["PWRPin"]; + if(obj.containsKey("MDCPin")) this->MDCPin = obj["MDCPin"]; + if(obj.containsKey("MDIOPin")) this->MDIOPin = obj["MDIOPin"]; + this->parseIPAddress(obj, "ip", &this->ip); this->parseIPAddress(obj, "gateway", &this->gateway); this->parseIPAddress(obj, "subnet", &this->subnet); this->parseIPAddress(obj, "dns1", &this->dns1); @@ -328,6 +341,15 @@ bool EthernetSettings::fromJSON(JsonObject &obj) { return true; } bool EthernetSettings::toJSON(JsonObject &obj) { + obj["boardType"] = this->boardType; + obj["phyAddress"] = this->phyAddress; + obj["dhcp"] = this->dhcp; + obj["CLKMode"] = static_cast(this->CLKMode); + obj["phyType"] = static_cast(this->phyType); + obj["PWRPin"] = this->PWRPin; + obj["MDCPin"] = this->MDCPin; + obj["MDIOPin"] = this->MDIOPin; + obj["ip"] = this->ip.toString(); obj["gateway"] = this->gateway.toString(); obj["subnet"] = this->subnet.toString(); obj["dns1"] = this->dns1.toString(); @@ -337,6 +359,15 @@ bool EthernetSettings::toJSON(JsonObject &obj) { bool EthernetSettings::save() { pref.begin("ETH"); pref.clear(); + pref.putBool("dhcp", this->dhcp); + pref.putChar("boardType", this->boardType); + pref.putChar("phyAddress", this->phyAddress); + pref.putChar("phyType", static_cast(this->phyType)); + pref.putChar("CLKMode", static_cast(this->CLKMode)); + pref.putChar("PWRPin", this->PWRPin); + pref.putChar("MDCPin", this->MDCPin); + pref.putChar("MDIOPin", this->MDIOPin); + pref.putString("ip", this->ip.toString()); pref.putString("gateway", this->gateway.toString()); pref.putString("subnet", this->subnet.toString()); pref.putString("dns1", this->dns1.toString()); @@ -346,7 +377,18 @@ bool EthernetSettings::save() { } bool EthernetSettings::load() { pref.begin("ETH"); + this->dhcp = pref.getBool("dhcp", true); + this->boardType = pref.getChar("boardType", this->boardType); + this->phyType = static_cast(pref.getChar("phyType", ETH_PHY_LAN8720)); + this->CLKMode = static_cast(pref.getChar("CLKMode", ETH_CLOCK_GPIO0_IN)); + this->phyAddress = pref.getChar("phyAddress", this->phyAddress); + this->PWRPin = pref.getChar("PWRPin", this->PWRPin); + this->MDCPin = pref.getChar("MDCPin", this->MDCPin); + this->MDIOPin = pref.getChar("MDIOPin", this->MDIOPin); + char buff[16]; + pref.getString("ip", buff, sizeof(buff)); + this->ip.fromString(buff); pref.getString("gateway", buff, sizeof(buff)); this->gateway.fromString(buff); pref.getString("subnet", buff, sizeof(buff)); @@ -360,12 +402,13 @@ bool EthernetSettings::load() { } void EthernetSettings::print() { Serial.println("Ethernet Settings"); + Serial.printf("Board:%d PHYType:%d CLK:%d ADDR:%d PWR:%d MDC:%d MDIO:%d\n", this->boardType, this->phyType, this->CLKMode, this->phyAddress, this->PWRPin, this->MDCPin, this->MDIOPin); Serial.print(" GATEWAY: "); Serial.println(this->gateway); Serial.print(" SUBNET: "); Serial.println(this->subnet); - Serial.print(" DNS1: "); + Serial.print(" DNS1: "); Serial.println(this->dns1); - Serial.print(" DNS2: "); + Serial.print(" DNS2: "); Serial.println(this->dns2); } diff --git a/ConfigSettings.h b/ConfigSettings.h index 726c2eb..99165ff 100644 --- a/ConfigSettings.h +++ b/ConfigSettings.h @@ -1,8 +1,9 @@ #include +#include #ifndef configsettings_h #define configsettings_h -#define FW_VERSION "v1.2.3" +#define FW_VERSION "v1.3.0" enum DeviceStatus { DS_OK = 0, DS_ERROR = 1, @@ -54,10 +55,20 @@ class WifiSettings: BaseSettings { class EthernetSettings: BaseSettings { public: EthernetSettings(); + uint8_t boardType = 0; // These board types are enumerated in the ui and used to set the chip settings. + bool dhcp = true; + IPAddress ip; IPAddress subnet = IPAddress(255,255,255,0); IPAddress gateway; IPAddress dns1; IPAddress dns2; + eth_phy_type_t phyType = ETH_PHY_LAN8720; + eth_clock_mode_t CLKMode = ETH_CLOCK_GPIO0_IN; + int8_t phyAddress = ETH_PHY_ADDR; + int8_t PWRPin = ETH_PHY_POWER; + int8_t MDCPin = ETH_PHY_MDC; + int8_t MDIOPin = ETH_PHY_MDIO; + bool begin(); bool fromJSON(JsonObject &obj); bool toJSON(JsonObject &obj); @@ -83,15 +94,16 @@ class MQTTSettings: BaseSettings { }; enum class conn_types : byte { unset = 0x00, - wifi = 0x1, - ethernet = 0x2 + wifi = 0x01, + ethernet = 0x02, + ethernetpref = 0x03 }; class ConfigSettings: BaseSettings { public: char serverId[10] = ""; char hostname[32] = "ESPSomfyRTS"; - conn_types connType = conn_types::wifi; + conn_types connType = conn_types::unset; const char* fwVersion = FW_VERSION; bool ssdpBroadcast = true; uint8_t status; diff --git a/Network.cpp b/Network.cpp index 15c320f..d4de417 100644 --- a/Network.cpp +++ b/Network.cpp @@ -15,6 +15,7 @@ extern Web webServer; extern SocketEmitter sockEmit; extern MQTTClass mqtt; extern rebootDelay_t rebootDelay; +extern Network net; int connectRetries = 0; void Network::end() { @@ -25,11 +26,14 @@ void Network::end() { } bool Network::setup() { WiFi.persistent(false); - //Serial.print("WiFi Mode: "); - //Serial.println(WiFi.getMode()); if(WiFi.status() == WL_CONNECTED) WiFi.disconnect(true); - WiFi.mode(WIFI_STA); - settings.WIFI.printNetworks(); + if(settings.connType == conn_types::wifi || settings.connType == conn_types::unset) { + WiFi.persistent(false); + Serial.print("WiFi Mode: "); + Serial.println(WiFi.getMode()); + WiFi.mode(WIFI_STA); + settings.WIFI.printNetworks(); + } sockEmit.begin(); if(!this->connect()) this->openSoftAP(); return true; @@ -48,7 +52,7 @@ void Network::loop() { connectRetries = 0; this->lastEmit = millis(); this->emitSockets(); - if(WiFi.status() != WL_CONNECTED) return; + if(!this->connected()) return; } sockEmit.loop(); if(settings.ssdpBroadcast) { @@ -68,48 +72,86 @@ void Network::emitSockets() { this->lastChannel = WiFi.channel(); } } - else - sockEmit.sendToClients("wifiStrength", "{\"ssid\":\"\", \"strength\":-100,\"channel\":-1}"); + else { + if(this->connType == conn_types::ethernet && this->lastRSSI != -100 && this->lastChannel != -1) { + sockEmit.sendToClients("wifiStrength", "{\"ssid\":\"\", \"strength\":-100,\"channel\":-1}"); + this->lastRSSI = -100; + this->lastChannel = -1; + } + } } void Network::emitSockets(uint8_t num) { + char buf[128]; if(WiFi.status() == WL_CONNECTED) { - char buf[128]; snprintf(buf, sizeof(buf), "{\"ssid\":\"%s\",\"strength\":%d,\"channel\":%d}", WiFi.SSID().c_str(), WiFi.RSSI(), WiFi.channel()); sockEmit.sendToClient(num, "wifiStrength", buf); this->lastRSSI = WiFi.RSSI(); this->lastChannel = WiFi.channel(); } + else { + if(this->connType == conn_types::ethernet && this->lastRSSI != -100 && this->lastChannel != -1) + sockEmit.sendToClient(num, "wifiStrength", "{\"ssid\":\"\", \"strength\":-100,\"channel\":-1}"); + this->lastRSSI = -100; + this->lastChannel = -1; + } + if(this->connType == conn_types::ethernet) { + snprintf(buf, sizeof(buf), "{\"connected\":true,\"speed\":%d,\"fullduplex\":%s}", ETH.linkSpeed(), ETH.fullDuplex() ? "true" : "false"); + sockEmit.sendToClient(num, "ethernet", buf); + } else - sockEmit.sendToClient(num, "wifiStrength", "{\"ssid\":\"\", \"strength\":-100,\"channel\":-1}"); + sockEmit.sendToClient(num, "ethernet", "{\"connected\":false, \"speed\":0,\"fullduplex\":false}"); + } -void Network::setConnected() { - WiFi.hostname(settings.hostname); - this->ssid = WiFi.SSID(); - this->mac = WiFi.BSSIDstr(); - this->strength = WiFi.RSSI(); - this->channel = WiFi.channel(); +void Network::setConnected(conn_types connType) { + this->connType = connType; this->connectTime = millis(); if(this->connectAttempts == 1) { Serial.println(); - Serial.print("Successfully Connected to WiFi!!!!"); - Serial.print(WiFi.localIP()); - Serial.print(" ("); - Serial.print(this->strength); - Serial.println("dbm)"); + if(this->connType == conn_types::wifi) { + Serial.print("Successfully Connected to WiFi!!!!"); + Serial.print(WiFi.localIP()); + Serial.print(" ("); + Serial.print(this->strength); + Serial.println("dbm)"); + } + else { + Serial.print("Successfully Connected to Ethernet!!! "); + Serial.print(ETH.localIP()); + if(ETH.fullDuplex()) { + Serial.print(" FULL DUPLEX"); + } + Serial.print(" "); + Serial.print(ETH.linkSpeed()); + Serial.println("Mbps"); + } + char buf[128]; + snprintf(buf, sizeof(buf), "{\"connected\":true,\"speed\":%d,\"fullduplex\":%s}", ETH.linkSpeed(), ETH.fullDuplex() ? "true" : "false"); + sockEmit.sendToClients("ethernet", buf); } else { Serial.println(); Serial.print("Reconnected after "); Serial.print(1.0 * (millis() - this->connectStart)/1000); - Serial.print("sec IP: "); - Serial.print(WiFi.localIP()); - Serial.print(" "); - Serial.print(this->mac); - Serial.print(" CH:"); - Serial.print(this->channel); - Serial.print(" ("); - Serial.print(this->strength); - Serial.print(" dBm)"); + Serial.print("sec IP: "); + if(this->connType == conn_types::wifi) { + Serial.print(WiFi.localIP()); + Serial.print(" "); + Serial.print(this->mac); + Serial.print(" CH:"); + Serial.print(this->channel); + Serial.print(" ("); + Serial.print(this->strength); + Serial.print(" dBm)"); + } + else { + Serial.print(ETH.localIP()); + if(ETH.fullDuplex()) { + Serial.print(" FULL DUPLEX"); + } + Serial.print(" "); + Serial.print(ETH.linkSpeed()); + Serial.print("Mbps"); + } Serial.print(" Disconnected "); Serial.print(this->connectAttempts - 1); Serial.println(" times"); @@ -145,7 +187,52 @@ void Network::setConnected() { else if(SSDP.isStarted) SSDP.end(); this->emitSockets(); } -bool Network::connect() { +bool Network::connectWired() { + if(this->connType == conn_types::ethernet) { + this->disconnected = 0; + return true; + } + if(this->connectAttempts > 0) { + Serial.printf("Ethernet Connection Lost... %d Reconnecting ", this->connectAttempts); + Serial.println(this->mac); + } + else + Serial.println("Connecting to Wired Ethernet"); + this->connectAttempts++; + if(!this->ethStarted) { + this->ethStarted = true; + WiFi.mode(WIFI_OFF); + + WiFi.onEvent(this->networkEvent); + 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"); + if(settings.connType == conn_types::ethernetpref) { + this->wifiFallback = true; + return connectWiFi(); + } + return false; + } + else { + uint32_t wait = millis(); + while(millis() - wait < 7000) { + if(this->connected()) return true; + delay(500); + } + if(settings.connType == conn_types::ethernetpref) { + this->wifiFallback = true; + return connectWiFi(); + } + } + } + int retries = 0; + while(retries++ < 100) { + delay(100); + if(this->connected()) return true; + } + if(this->connectAttempts > 10) this->wifiFallback = true; + return false; +} +bool Network::connectWiFi() { if(settings.hostname[0] != '\0') WiFi.hostname(settings.hostname); if(settings.WIFI.ssid[0] != '\0') { if(WiFi.status() == WL_CONNECTED && WiFi.SSID().compareTo(settings.WIFI.ssid) == 0) { @@ -173,7 +260,6 @@ bool Network::connect() { delay(100); int retries = 0; while(retries < 100) { - //digitalWrite(LED_BUILTIN, retries % 2 ? HIGH : LOW); // Flash the LED while connecting switch(WiFi.status()) { case WL_SCAN_COMPLETED: Serial.println("Status: Scan Completed"); @@ -188,7 +274,12 @@ bool Network::connect() { Serial.print("*"); break; case WL_CONNECTED: - this->setConnected(); + WiFi.hostname(settings.hostname); + this->ssid = WiFi.SSID(); + this->mac = WiFi.BSSIDstr(); + this->strength = WiFi.RSSI(); + this->channel = WiFi.channel(); + this->setConnected(conn_types::wifi); WiFi.setSleep(false); return true; case WL_NO_SHIELD: @@ -213,11 +304,14 @@ bool Network::connect() { //if(disconnected > 0 && st == -100) settings.WIFI.PrintNetworks(); disconnected++; } - } - //digitalWrite(LED_BUILTIN, HIGH); // Turn off the LED. return false; } +bool Network::connect() { + if(settings.connType != conn_types::wifi && !this->wifiFallback) + return this->connectWired(); + return this->connectWiFi(); +} int Network::getStrengthByMac(const char *macAddr) { int strength = -100; int n = WiFi.scanNetworks(true); @@ -314,12 +408,6 @@ bool Network::openSoftAP() { WiFi.softAPdisconnect(true); return false; } - if(digitalRead(D0) == LOW) { - Serial.println(); - Serial.println("Button Pressed...Stopping AP Mode"); - WiFi.softAPdisconnect(true); - return false; - } if(c == 100) { Serial.println(); c = 0; @@ -327,3 +415,58 @@ bool Network::openSoftAP() { yield(); } } +bool Network::connected() { + if(this->connType == conn_types::unset) return false; + else if(this->connType == conn_types::wifi) return WiFi.status() == WL_CONNECTED; + else return this->connType != conn_types::unset; + return false; +} +void Network::networkEvent(WiFiEvent_t event) { + switch(event) { + case ARDUINO_EVENT_ETH_START: + Serial.println("Ethernet Started"); + if(settings.hostname[0] != '\0') + ETH.setHostname(settings.hostname); + else + ETH.setHostname("ESPSomfy-RTS"); + break; + case ARDUINO_EVENT_ETH_GOT_IP: + // If the Wifi is connected then drop that connection + if(WiFi.status() == WL_CONNECTED) WiFi.disconnect(true); + Serial.print("Got Ethernet IP "); + Serial.println(ETH.localIP()); + net.mac = ETH.macAddress(); + net.setConnected(conn_types::ethernet); + break; + case ARDUINO_EVENT_ETH_CONNECTED: + Serial.print("Ethernet Connected "); + // We don't want to call setConnected if we do not have an IP address yet + if(ETH.localIP() != INADDR_NONE) + net.setConnected(conn_types::ethernet); + break; + case ARDUINO_EVENT_ETH_DISCONNECTED: + Serial.println("Ethernet Disconnected"); + sockEmit.sendToClients("ethernet", "{\"connected\":false, \"speed\":0,\"fullduplex\":false}"); + net.connType = conn_types::unset; + break; + case ARDUINO_EVENT_ETH_STOP: + Serial.println("Ethernet Stopped"); + net.connType = conn_types::unset; + break; + case ARDUINO_EVENT_WIFI_AP_STOP: + Serial.println("WiFi AP Stopped"); + break; + case ARDUINO_EVENT_WIFI_AP_START: + Serial.println("WiFi AP Started"); + break; + case ARDUINO_EVENT_WIFI_STA_START: + Serial.println("WiFi STA Started"); + break; + case ARDUINO_EVENT_WIFI_STA_CONNECTED: + break; + default: + if(event > ARDUINO_EVENT_ETH_START) + Serial.printf("Unknown Ethernet Event %d\n", event); + break; + } +} diff --git a/Network.h b/Network.h index 37bb1de..3b8bb46 100644 --- a/Network.h +++ b/Network.h @@ -7,7 +7,12 @@ class Network { unsigned long lastEmit = 0; int lastRSSI = 0; int lastChannel = 0; + int linkSpeed = 0; + bool ethStarted = false; public: + bool wifiFallback = false; + conn_types connType = conn_types::unset; + bool connected(); String ssid; String mac; int channel; @@ -18,7 +23,9 @@ class Network { long connectTime = 0; bool openSoftAP(); bool connect(); - void setConnected(); + bool connectWiFi(); + bool connectWired(); + void setConnected(conn_types connType); int getStrengthByMac(const char *mac); int getStrengthBySSID(const char *ssid); bool setup(); @@ -27,5 +34,6 @@ class Network { void emitSockets(); void emitSockets(uint8_t num); uint32_t getChipId(); + static void networkEvent(WiFiEvent_t event); }; #endif diff --git a/SSDP.cpp b/SSDP.cpp index bf11fff..277ec30 100644 --- a/SSDP.cpp +++ b/SSDP.cpp @@ -761,7 +761,7 @@ void SSDPClass::loop() { this->_sendQueuedResponses(); } void SSDPClass::schema(Print &client) { - IPAddress ip = WiFi.localIP(); + IPAddress ip = this->localIP(); uint8_t devCount = 0; for(uint8_t i = 0; i < this->m_cdeviceTypes; i++) { if(this->deviceTypes[i].deviceType && strlen(this->deviceTypes[i].deviceType) > 0) devCount++; diff --git a/SomfyController.ino b/SomfyController.ino index b58d716..baac1c8 100644 --- a/SomfyController.ino +++ b/SomfyController.ino @@ -21,14 +21,10 @@ void setup() { Serial.println(); Serial.println("Startup/Boot...."); settings.begin(); - WiFi.persistent(false); - Serial.print("WiFi Mode: "); - Serial.println(WiFi.getMode()); Serial.println("Mounting File System..."); if(LittleFS.begin()) Serial.println("File system mounted successfully"); else Serial.println("Error mounting file system"); if(WiFi.status() == WL_CONNECTED) WiFi.disconnect(true); - WiFi.mode(WIFI_AP_STA); delay(10); Serial.println(); webServer.startup(); @@ -43,7 +39,7 @@ void loop() { if(rebootDelay.reboot && millis() > rebootDelay.rebootTime) ESP.restart(); net.loop(); somfy.loop(); - if(WiFi.status() == WL_CONNECTED) { + if(net.connected()) { webServer.loop(); sockEmit.loop(); } diff --git a/SomfyController.ino.esp32.bin b/SomfyController.ino.esp32.bin index 1e5f7a4..59ef102 100644 Binary files a/SomfyController.ino.esp32.bin and b/SomfyController.ino.esp32.bin differ diff --git a/SomfyController.littlefs.bin b/SomfyController.littlefs.bin index 0082362..a5f20fc 100644 Binary files a/SomfyController.littlefs.bin and b/SomfyController.littlefs.bin differ diff --git a/Web.cpp b/Web.cpp index bbd4dbf..5bb9891 100644 --- a/Web.cpp +++ b/Web.cpp @@ -1091,6 +1091,54 @@ void Web::begin() { } } }); + server.on("/setNetwork", []() { + webServer.sendCORSHeaders(); + DynamicJsonDocument doc(1024); + DeserializationError err = deserializeJson(doc, server.arg("plain")); + if (err) { + Serial.print("Error parsing JSON "); + Serial.println(err.c_str()); + String msg = err.c_str(); + server.send(400, _encoding_html, "Error parsing JSON body
" + msg); + } + else { + JsonObject obj = doc.as(); + HTTPMethod method = server.method(); + if (method == HTTP_POST || method == HTTP_PUT) { + // Parse out all the inputs. + bool reboot = false; + if(obj.containsKey("connType") && obj["connType"].as() != static_cast(settings.connType)) { + settings.connType = static_cast(obj["connType"].as()); + settings.save(); + reboot = true; + } + if(settings.connType == conn_types::wifi) { + if(obj.containsKey("ssid") && obj["ssid"].as().compareTo(settings.WIFI.ssid) != 0) reboot = true; + if(obj.containsKey("passphrase") && obj["passphrase"].as().compareTo(settings.WIFI.passphrase) != 0) reboot = true; + } + else { + // This is an ethernet connection so if anything changes we need to reboot. + reboot = true; + } + JsonObject objWifi = obj["wifi"]; + JsonObject objEth = obj["ethernet"]; + settings.WIFI.fromJSON(objWifi); + settings.Ethernet.fromJSON(objEth); + + settings.WIFI.save(); + settings.Ethernet.save(); + if (reboot) { + Serial.println("Rebooting ESP for new Network settings..."); + rebootDelay.reboot = true; + rebootDelay.rebootTime = millis() + 1000; + } + server.send(200, "application/json", "{\"status\":\"OK\",\"desc\":\"Successfully set Network Settings\"}"); + } + else { + server.send(201, "application/json", "{\"status\":\"ERROR\",\"desc\":\"Invalid HTTP Method: \"}"); + } + } + }); server.on("/connectwifi", []() { webServer.sendCORSHeaders(); int statusCode = 200; diff --git a/data/index.html b/data/index.html index 664d161..fd866ea 100644 --- a/data/index.html +++ b/data/index.html @@ -3,17 +3,17 @@ - - + + - +
Radio Not Initialized

ESPSomfy RTS

- +
@@ -57,26 +63,101 @@

ESPSomfy RTS