diff --git a/ConfigFile.cpp b/ConfigFile.cpp index 8bcab04..d64bde4 100644 --- a/ConfigFile.cpp +++ b/ConfigFile.cpp @@ -125,6 +125,29 @@ bool ConfigFile::readString(char *buff, size_t len) { _rtrim(buff); return true; } +bool ConfigFile::skipValue(size_t len) { + if(!this->file) return false; + uint8_t quotes = 0; + uint8_t j = 0; + while(j < len) { + uint8_t val; + j++; + if(this->file.read(&val, 1) == 1) { + switch(val) { + case CFG_VALUE_SEP: + if(quotes >= 2 || quotes == 0) return true; + break; + case CFG_REC_END: + return true; + case CFG_TOK_QUOTE: + quotes++; + break; + } + } + else return false; + } + return true; +} bool ConfigFile::readVarString(char *buff, size_t len) { if(!this->file) return false; memset(buff, 0x00, len); @@ -564,8 +587,8 @@ bool ShadeConfigFile::restoreFile(SomfyShadeController *s, const char *filename, else { this->file.seek(this->file.position() + this->header.settingsRecordSize, SeekSet); } - if(opts.network) { - this->readNetRecord(); + if(opts.network || opts.mqtt) { + this->readNetRecord(opts); } else { this->file.seek(this->file.position() + this->header.netRecordSize, SeekSet); @@ -583,44 +606,68 @@ bool ShadeConfigFile::restoreFile(SomfyShadeController *s, const char *filename, settings.WIFI.save(); settings.Ethernet.save(); } + if(opts.mqtt) settings.MQTT.save(); return true; } -bool ShadeConfigFile::readNetRecord() { +bool ShadeConfigFile::readNetRecord(restore_options_t &opts) { if(this->header.netRecordSize > 0) { uint32_t startPos = this->file.position(); - Serial.println("Reading network settings from file..."); - settings.connType = static_cast(this->readUInt8(static_cast(conn_types::unset))); - settings.IP.dhcp = this->readBool(true); - char ip[24]; - this->readVarString(ip, sizeof(ip)); - settings.IP.ip.fromString(ip); - this->readVarString(ip, sizeof(ip)); - settings.IP.gateway.fromString(ip); - this->readVarString(ip, sizeof(ip)); - settings.IP.subnet.fromString(ip); - this->readVarString(ip, sizeof(ip)); - settings.IP.dns1.fromString(ip); - this->readVarString(ip, sizeof(ip)); - settings.IP.dns2.fromString(ip); + if(opts.network) { + Serial.println("Reading network settings from file..."); + settings.connType = static_cast(this->readUInt8(static_cast(conn_types::unset))); + settings.IP.dhcp = this->readBool(true); + char ip[24]; + this->readVarString(ip, sizeof(ip)); + settings.IP.ip.fromString(ip); + this->readVarString(ip, sizeof(ip)); + settings.IP.gateway.fromString(ip); + this->readVarString(ip, sizeof(ip)); + settings.IP.subnet.fromString(ip); + this->readVarString(ip, sizeof(ip)); + settings.IP.dns1.fromString(ip); + this->readVarString(ip, sizeof(ip)); + settings.IP.dns2.fromString(ip); + } + else { + this->skipValue(4); // connType + this->skipValue(6); // dhcp flag + this->skipValue(24); // ip + this->skipValue(24); // gateway + this->skipValue(24); // subnet + this->skipValue(24); // dns1 + this->skipValue(24); // dns2 + } if(this->header.version >= 22) { - this->readVarString(settings.MQTT.protocol, sizeof(settings.MQTT.protocol)); - this->readVarString(settings.MQTT.hostname, sizeof(settings.MQTT.hostname)); - settings.MQTT.port = this->readUInt16(1883); - settings.MQTT.pubDisco = this->readBool(false); - this->readVarString(settings.MQTT.rootTopic, sizeof(settings.MQTT.rootTopic)); - this->readVarString(settings.MQTT.discoTopic, sizeof(settings.MQTT.discoTopic)); + if(opts.mqtt) { + this->readVarString(settings.MQTT.protocol, sizeof(settings.MQTT.protocol)); + this->readVarString(settings.MQTT.hostname, sizeof(settings.MQTT.hostname)); + settings.MQTT.port = this->readUInt16(1883); + settings.MQTT.pubDisco = this->readBool(false); + this->readVarString(settings.MQTT.rootTopic, sizeof(settings.MQTT.rootTopic)); + this->readVarString(settings.MQTT.discoTopic, sizeof(settings.MQTT.discoTopic)); + } + else { + this->skipValue(sizeof(settings.MQTT.protocol)); + this->skipValue(sizeof(settings.MQTT.hostname)); + this->skipValue(6); // Port + this->skipValue(6); // pubDisco + this->skipValue(sizeof(settings.MQTT.rootTopic)); + this->skipValue(sizeof(settings.MQTT.discoTopic)); + } } // Now lets check to see if we are the same board. If we are then we will restore // the ethernet phy settings. - if(strncmp(settings.serverId, this->header.serverId, sizeof(settings.serverId)) == 0) { - Serial.println("Restoring Ethernet adapter settings"); - settings.Ethernet.boardType = this->readUInt8(1); - settings.Ethernet.phyType = static_cast(this->readUInt8(0)); - settings.Ethernet.CLKMode = static_cast(this->readUInt8(0)); - settings.Ethernet.phyAddress = this->readInt8(1); - settings.Ethernet.PWRPin = this->readInt8(1); - settings.Ethernet.MDCPin = this->readInt8(16); - settings.Ethernet.MDIOPin = this->readInt8(23); + if(opts.network) { + if(strncmp(settings.serverId, this->header.serverId, sizeof(settings.serverId)) == 0) { + Serial.println("Restoring Ethernet adapter settings"); + settings.Ethernet.boardType = this->readUInt8(1); + settings.Ethernet.phyType = static_cast(this->readUInt8(0)); + settings.Ethernet.CLKMode = static_cast(this->readUInt8(0)); + settings.Ethernet.phyAddress = this->readInt8(1); + settings.Ethernet.PWRPin = this->readInt8(1); + settings.Ethernet.MDCPin = this->readInt8(16); + settings.Ethernet.MDIOPin = this->readInt8(23); + } } if(this->file.position() != startPos + this->header.netRecordSize) { Serial.println("Reading to end of network record"); diff --git a/ConfigFile.h b/ConfigFile.h index be603b1..5ad9281 100644 --- a/ConfigFile.h +++ b/ConfigFile.h @@ -55,6 +55,7 @@ class ConfigFile { bool writeFloat(const float val, const uint8_t prec, const char tok = CFG_VALUE_SEP); bool readString(char *buff, size_t len); bool readVarString(char *buff, size_t len); + bool skipValue(size_t len); bool writeString(const char *val, size_t len, const char tok = CFG_VALUE_SEP); bool writeVarString(const char *val, const char tok = CFG_VALUE_SEP); char readChar(const char defVal = '\0'); @@ -79,7 +80,7 @@ class ShadeConfigFile : public ConfigFile { bool readShadeRecord(SomfyShade *shade); bool readGroupRecord(SomfyGroup *group); bool readSettingsRecord(); - bool readNetRecord(); + bool readNetRecord(restore_options_t &opts); bool readTransRecord(transceiver_config_t &cfg); public: static bool exists(); diff --git a/ConfigSettings.cpp b/ConfigSettings.cpp index 5b452ce..2059706 100644 --- a/ConfigSettings.cpp +++ b/ConfigSettings.cpp @@ -15,6 +15,7 @@ void restore_options_t::fromJSON(JsonObject &obj) { if(obj.containsKey("network")) this->network = obj["network"]; if(obj.containsKey("transceiver")) this->transceiver = obj["transceiver"]; if(obj.containsKey("repeaters")) this->repeaters = obj["repeaters"]; + if(obj.containsKey("mqtt")) this->mqtt = obj["mqtt"]; } int8_t appver_t::compare(appver_t &ver) { if(this->major == ver.major && this->minor == ver.minor && this->build == ver.build) return 0; @@ -571,7 +572,7 @@ void WifiSettings::print() { Serial.println("]"); } void WifiSettings::printNetworks() { - int n = WiFi.scanNetworks(false, true); + int n = WiFi.scanNetworks(false, false); Serial.print("Scanned "); Serial.print(n); Serial.println(" Networks..."); diff --git a/ConfigSettings.h b/ConfigSettings.h index 88bf3db..fb02107 100644 --- a/ConfigSettings.h +++ b/ConfigSettings.h @@ -3,7 +3,7 @@ #ifndef configsettings_h #define configsettings_h -#define FW_VERSION "v2.4.0" +#define FW_VERSION "v2.4.1" enum DeviceStatus { DS_OK = 0, DS_ERROR = 1, @@ -15,6 +15,7 @@ struct restore_options_t { bool network = false; bool transceiver = false; bool repeaters = false; + bool mqtt = false; void fromJSON(JsonObject &obj); }; struct appver_t { diff --git a/Network.cpp b/Network.cpp index 4242e57..8bdf533 100644 --- a/Network.cpp +++ b/Network.cpp @@ -25,9 +25,11 @@ void Network::end() { } bool Network::setup() { WiFi.persistent(false); + WiFi.onEvent(this->networkEvent); if(WiFi.status() == WL_CONNECTED) WiFi.disconnect(true); if(settings.connType == conn_types::wifi || settings.connType == conn_types::unset) { WiFi.persistent(false); + if(settings.hostname[0] != '\0') WiFi.setHostname(settings.hostname); Serial.print("WiFi Mode: "); Serial.println(WiFi.getMode()); WiFi.mode(WIFI_STA); @@ -71,7 +73,8 @@ void Network::loop() { mqtt.loop(); } void Network::emitSockets() { - if(this->needsBroadcast || abs(abs(WiFi.RSSI()) - abs(this->lastRSSI)) > 1 || WiFi.channel() != this->lastChannel) { + if(this->needsBroadcast || + (this->connType == conn_types::wifi && (abs(abs(WiFi.RSSI()) - abs(this->lastRSSI)) > 1 || WiFi.channel() != this->lastChannel))) { this->emitSockets(255); sockEmit.loop(); this->needsBroadcast = false; @@ -230,14 +233,23 @@ void Network::setConnected(conn_types connType) { else if(SSDP.isStarted) SSDP.end(); this->emitSockets(); settings.printAvailHeap(); + this->needsBroadcast = true; } bool Network::connectWired() { //if(this->connType == conn_types::ethernet && ETH.linkUp()) { if(ETH.linkUp()) { - this->disconnected = 0; + if(WiFi.status() == WL_CONNECTED) { + WiFi.disconnect(true); + WiFi.mode(WIFI_OFF); + } + if(this->connType != conn_types::ethernet) this->setConnected(conn_types::ethernet); this->wifiFallback = false; return true; } + else if(this->ethStarted) { + if(settings.connType == conn_types::ethernetpref && settings.WIFI.ssid[0] != '\0') + return this->connectWiFi(); + } if(this->connectAttempts > 0) { Serial.printf("Ethernet Connection Lost... %d Reconnecting ", this->connectAttempts); Serial.println(this->mac); @@ -248,12 +260,16 @@ bool Network::connectWired() { if(!this->ethStarted) { this->ethStarted = true; WiFi.mode(WIFI_OFF); - WiFi.onEvent(this->networkEvent); - if(settings.hostname[0] != '\0') ETH.setHostname(settings.hostname); + 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::ethernetpref) { this->wifiFallback = true; return connectWiFi(); @@ -272,7 +288,11 @@ bool Network::connectWired() { uint32_t wait = millis(); while(millis() - wait < 14000) { - if(this->connected()) return true; + if(ETH.linkUp()) { + net.mac = ETH.macAddress(); + net.setConnected(conn_types::ethernet); + return true; + } delay(500); } if(settings.connType == conn_types::ethernetpref) { @@ -281,12 +301,6 @@ bool Network::connectWired() { } } } - int retries = 0; - while(retries++ < 100) { - delay(100); - if(this->connected()) return true; - } - if(this->connectAttempts > 10) this->wifiFallback = true; return false; } void Network::updateHostname() { @@ -326,7 +340,7 @@ bool Network::connectWiFi() { this->connectStart = millis(); WiFi.setSleep(false); WiFi.mode(WIFI_MODE_NULL); - WiFi.onEvent(this->networkEvent); + //WiFi.onEvent(this->networkEvent); if(!settings.IP.dhcp) { if(!WiFi.config(settings.IP.ip, settings.IP.gateway, settings.IP.subnet, settings.IP.dns1, settings.IP.dns2)) @@ -397,12 +411,15 @@ bool Network::connect() { if(settings.connType == conn_types::unset) return true; else if(settings.connType == conn_types::ethernet || (settings.connType == conn_types::ethernetpref)) { bool bConnected = this->connectWired(); - if(!bConnected && settings.connType == conn_types::ethernetpref && settings.WIFI.ssid[0] != '\0') + if(!bConnected && settings.connType == conn_types::ethernetpref && settings.WIFI.ssid[0] != '\0') { bConnected = this->connectWiFi(); + this->wifiFallback = true; + } return bConnected; } return this->connectWiFi(); } +/* DEPRECATED 03-02-24 int Network::getStrengthByMac(const char *macAddr) { int n = WiFi.scanNetworks(true); for(int i = 0; i < n; i++) { @@ -411,6 +428,7 @@ int Network::getStrengthByMac(const char *macAddr) { } return -100; } +*/ uint32_t Network::getChipId() { uint32_t chipId = 0; uint64_t mac = ESP.getEfuseMac(); @@ -421,7 +439,7 @@ uint32_t Network::getChipId() { } int Network::getStrengthBySSID(const char *ssid) { int32_t strength = -100; - int n = WiFi.scanNetworks(false, true); + int n = WiFi.scanNetworks(false, false); for(int i = 0; i < n; i++) { if(WiFi.SSID(i).compareTo(ssid) == 0) strength = max(WiFi.RSSI(i), strength); } @@ -516,18 +534,12 @@ 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_LOST_IP: @@ -539,12 +551,12 @@ void Network::networkEvent(WiFiEvent_t event) { 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); + //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}"); + sockEmit.sendToClients("ethernet", "{\"connected\":false,\"speed\":0,\"fullduplex\":false}"); net.connType = conn_types::unset; break; case ARDUINO_EVENT_ETH_STOP: diff --git a/Network.h b/Network.h index 0a4b409..b673b3e 100644 --- a/Network.h +++ b/Network.h @@ -29,7 +29,7 @@ class Network { bool connectWiFi(); bool connectWired(); void setConnected(conn_types connType); - int getStrengthByMac(const char *mac); + //int getStrengthByMac(const char *mac); int getStrengthBySSID(const char *ssid); void updateHostname(); bool setup(); diff --git a/Sockets.cpp b/Sockets.cpp index 5429acd..cde9249 100644 --- a/Sockets.cpp +++ b/Sockets.cpp @@ -196,6 +196,7 @@ void SocketEmitter::wsEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t git.emitUpdateCheck(num); net.emitSockets(num); sockServer.loop(); + net.needsBroadcast = true; } break; case WStype_TEXT: diff --git a/SomfyController.ino.esp32.bin b/SomfyController.ino.esp32.bin index ca229da..8f6a9ad 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 8dd001b..b082c2d 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 3fd9d09..7964885 100644 Binary files a/SomfyController.littlefs.bin and b/SomfyController.littlefs.bin differ diff --git a/Utils.cpp b/Utils.cpp index ece3c49..0e5442d 100644 --- a/Utils.cpp +++ b/Utils.cpp @@ -9,13 +9,13 @@ unsigned long Timestamp::epoch() { struct tm tmNow; time_t now; - if(!getLocalTime(&tmNow)) return 0; + if(!getLocalTime(&tmNow,50)) return 0; time(&now); return now; } time_t Timestamp::now() { struct tm tmNow; - getLocalTime(&tmNow); + getLocalTime(&tmNow,50); return mktime(&tmNow); } time_t Timestamp::getUTC() { diff --git a/data/appversion b/data/appversion index 9183195..58073ef 100644 --- a/data/appversion +++ b/data/appversion @@ -1 +1 @@ -2.4.0 \ No newline at end of file +2.4.1 \ No newline at end of file diff --git a/data/index.html b/data/index.html index cdba8f7..85c2272 100644 --- a/data/index.html +++ b/data/index.html @@ -3,11 +3,11 @@ - - - + + + - +
diff --git a/data/index.js b/data/index.js index a8cf5bb..ac1a0f4 100644 --- a/data/index.js +++ b/data/index.js @@ -1264,7 +1264,7 @@ var security = new Security(); class General { initialized = false; - appVersion = 'v2.4.0'; + appVersion = 'v2.4.1'; reloadApp = false; init() { if (this.initialized) return; @@ -4254,12 +4254,13 @@ class Firmware { let div = this.createFileUploader('/restore'); let inst = div.querySelector('div[id=divInstText]'); let html = '
Select a backup file that you would like to restore and the options you would like to restore then press the Upload File button.

'; - html += `
Restoring network settings from a different board than the original will ignore Ethernet chip settings. Security, MQTT and WiFi will also not be restored since backup files do not contain passwords.

`; + html += `
Restoring network settings from a different board than the original will ignore Ethernet chip settings. Security, MQTT and WiFi connection information will also not be restored since backup files do not contain passwords.

`; html += '
'; html += `
`; html += `
`; html += `
`; html += `
` + html += `
` html += `
`; html += '
'; inst.innerHTML = html; @@ -4633,7 +4634,7 @@ class Firmware { ui.errorMessage(el, 'This file is not a valid backup file'); return; } - if (!data.shades && !data.settings && !data.network && !data.transceiver && !data.repeaters) { + if (!data.shades && !data.settings && !data.network && !data.transceiver && !data.repeaters && !data.mqtt) { ui.errorMessage(el, 'No restore options have been selected'); return; }