Improve wifi fallback

This commit is contained in:
Robert Strouse 2024-03-03 08:33:19 -08:00
parent ea5614c700
commit 60af2bf399
14 changed files with 133 additions and 69 deletions

View file

@ -125,6 +125,29 @@ bool ConfigFile::readString(char *buff, size_t len) {
_rtrim(buff); _rtrim(buff);
return true; 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) { bool ConfigFile::readVarString(char *buff, size_t len) {
if(!this->file) return false; if(!this->file) return false;
memset(buff, 0x00, len); memset(buff, 0x00, len);
@ -564,8 +587,8 @@ bool ShadeConfigFile::restoreFile(SomfyShadeController *s, const char *filename,
else { else {
this->file.seek(this->file.position() + this->header.settingsRecordSize, SeekSet); this->file.seek(this->file.position() + this->header.settingsRecordSize, SeekSet);
} }
if(opts.network) { if(opts.network || opts.mqtt) {
this->readNetRecord(); this->readNetRecord(opts);
} }
else { else {
this->file.seek(this->file.position() + this->header.netRecordSize, SeekSet); 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.WIFI.save();
settings.Ethernet.save(); settings.Ethernet.save();
} }
if(opts.mqtt) settings.MQTT.save();
return true; return true;
} }
bool ShadeConfigFile::readNetRecord() { bool ShadeConfigFile::readNetRecord(restore_options_t &opts) {
if(this->header.netRecordSize > 0) { if(this->header.netRecordSize > 0) {
uint32_t startPos = this->file.position(); uint32_t startPos = this->file.position();
Serial.println("Reading network settings from file..."); if(opts.network) {
settings.connType = static_cast<conn_types>(this->readUInt8(static_cast<uint8_t>(conn_types::unset))); Serial.println("Reading network settings from file...");
settings.IP.dhcp = this->readBool(true); settings.connType = static_cast<conn_types>(this->readUInt8(static_cast<uint8_t>(conn_types::unset)));
char ip[24]; settings.IP.dhcp = this->readBool(true);
this->readVarString(ip, sizeof(ip)); char ip[24];
settings.IP.ip.fromString(ip); this->readVarString(ip, sizeof(ip));
this->readVarString(ip, sizeof(ip)); settings.IP.ip.fromString(ip);
settings.IP.gateway.fromString(ip); this->readVarString(ip, sizeof(ip));
this->readVarString(ip, sizeof(ip)); settings.IP.gateway.fromString(ip);
settings.IP.subnet.fromString(ip); this->readVarString(ip, sizeof(ip));
this->readVarString(ip, sizeof(ip)); settings.IP.subnet.fromString(ip);
settings.IP.dns1.fromString(ip); this->readVarString(ip, sizeof(ip));
this->readVarString(ip, sizeof(ip)); settings.IP.dns1.fromString(ip);
settings.IP.dns2.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) { if(this->header.version >= 22) {
this->readVarString(settings.MQTT.protocol, sizeof(settings.MQTT.protocol)); if(opts.mqtt) {
this->readVarString(settings.MQTT.hostname, sizeof(settings.MQTT.hostname)); this->readVarString(settings.MQTT.protocol, sizeof(settings.MQTT.protocol));
settings.MQTT.port = this->readUInt16(1883); this->readVarString(settings.MQTT.hostname, sizeof(settings.MQTT.hostname));
settings.MQTT.pubDisco = this->readBool(false); settings.MQTT.port = this->readUInt16(1883);
this->readVarString(settings.MQTT.rootTopic, sizeof(settings.MQTT.rootTopic)); settings.MQTT.pubDisco = this->readBool(false);
this->readVarString(settings.MQTT.discoTopic, sizeof(settings.MQTT.discoTopic)); 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 // Now lets check to see if we are the same board. If we are then we will restore
// the ethernet phy settings. // the ethernet phy settings.
if(strncmp(settings.serverId, this->header.serverId, sizeof(settings.serverId)) == 0) { if(opts.network) {
Serial.println("Restoring Ethernet adapter settings"); if(strncmp(settings.serverId, this->header.serverId, sizeof(settings.serverId)) == 0) {
settings.Ethernet.boardType = this->readUInt8(1); Serial.println("Restoring Ethernet adapter settings");
settings.Ethernet.phyType = static_cast<eth_phy_type_t>(this->readUInt8(0)); settings.Ethernet.boardType = this->readUInt8(1);
settings.Ethernet.CLKMode = static_cast<eth_clock_mode_t>(this->readUInt8(0)); settings.Ethernet.phyType = static_cast<eth_phy_type_t>(this->readUInt8(0));
settings.Ethernet.phyAddress = this->readInt8(1); settings.Ethernet.CLKMode = static_cast<eth_clock_mode_t>(this->readUInt8(0));
settings.Ethernet.PWRPin = this->readInt8(1); settings.Ethernet.phyAddress = this->readInt8(1);
settings.Ethernet.MDCPin = this->readInt8(16); settings.Ethernet.PWRPin = this->readInt8(1);
settings.Ethernet.MDIOPin = this->readInt8(23); settings.Ethernet.MDCPin = this->readInt8(16);
settings.Ethernet.MDIOPin = this->readInt8(23);
}
} }
if(this->file.position() != startPos + this->header.netRecordSize) { if(this->file.position() != startPos + this->header.netRecordSize) {
Serial.println("Reading to end of network record"); Serial.println("Reading to end of network record");

View file

@ -55,6 +55,7 @@ class ConfigFile {
bool writeFloat(const float val, const uint8_t prec, const char tok = CFG_VALUE_SEP); bool writeFloat(const float val, const uint8_t prec, const char tok = CFG_VALUE_SEP);
bool readString(char *buff, size_t len); bool readString(char *buff, size_t len);
bool readVarString(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 writeString(const char *val, size_t len, const char tok = CFG_VALUE_SEP);
bool writeVarString(const char *val, const char tok = CFG_VALUE_SEP); bool writeVarString(const char *val, const char tok = CFG_VALUE_SEP);
char readChar(const char defVal = '\0'); char readChar(const char defVal = '\0');
@ -79,7 +80,7 @@ class ShadeConfigFile : public ConfigFile {
bool readShadeRecord(SomfyShade *shade); bool readShadeRecord(SomfyShade *shade);
bool readGroupRecord(SomfyGroup *group); bool readGroupRecord(SomfyGroup *group);
bool readSettingsRecord(); bool readSettingsRecord();
bool readNetRecord(); bool readNetRecord(restore_options_t &opts);
bool readTransRecord(transceiver_config_t &cfg); bool readTransRecord(transceiver_config_t &cfg);
public: public:
static bool exists(); static bool exists();

View file

@ -15,6 +15,7 @@ void restore_options_t::fromJSON(JsonObject &obj) {
if(obj.containsKey("network")) this->network = obj["network"]; if(obj.containsKey("network")) this->network = obj["network"];
if(obj.containsKey("transceiver")) this->transceiver = obj["transceiver"]; if(obj.containsKey("transceiver")) this->transceiver = obj["transceiver"];
if(obj.containsKey("repeaters")) this->repeaters = obj["repeaters"]; if(obj.containsKey("repeaters")) this->repeaters = obj["repeaters"];
if(obj.containsKey("mqtt")) this->mqtt = obj["mqtt"];
} }
int8_t appver_t::compare(appver_t &ver) { int8_t appver_t::compare(appver_t &ver) {
if(this->major == ver.major && this->minor == ver.minor && this->build == ver.build) return 0; if(this->major == ver.major && this->minor == ver.minor && this->build == ver.build) return 0;
@ -571,7 +572,7 @@ void WifiSettings::print() {
Serial.println("]"); Serial.println("]");
} }
void WifiSettings::printNetworks() { void WifiSettings::printNetworks() {
int n = WiFi.scanNetworks(false, true); int n = WiFi.scanNetworks(false, false);
Serial.print("Scanned "); Serial.print("Scanned ");
Serial.print(n); Serial.print(n);
Serial.println(" Networks..."); Serial.println(" Networks...");

View file

@ -3,7 +3,7 @@
#ifndef configsettings_h #ifndef configsettings_h
#define configsettings_h #define configsettings_h
#define FW_VERSION "v2.4.0" #define FW_VERSION "v2.4.1"
enum DeviceStatus { enum DeviceStatus {
DS_OK = 0, DS_OK = 0,
DS_ERROR = 1, DS_ERROR = 1,
@ -15,6 +15,7 @@ struct restore_options_t {
bool network = false; bool network = false;
bool transceiver = false; bool transceiver = false;
bool repeaters = false; bool repeaters = false;
bool mqtt = false;
void fromJSON(JsonObject &obj); void fromJSON(JsonObject &obj);
}; };
struct appver_t { struct appver_t {

View file

@ -25,9 +25,11 @@ void Network::end() {
} }
bool Network::setup() { bool Network::setup() {
WiFi.persistent(false); WiFi.persistent(false);
WiFi.onEvent(this->networkEvent);
if(WiFi.status() == WL_CONNECTED) WiFi.disconnect(true); if(WiFi.status() == WL_CONNECTED) WiFi.disconnect(true);
if(settings.connType == conn_types::wifi || settings.connType == conn_types::unset) { if(settings.connType == conn_types::wifi || settings.connType == conn_types::unset) {
WiFi.persistent(false); WiFi.persistent(false);
if(settings.hostname[0] != '\0') WiFi.setHostname(settings.hostname);
Serial.print("WiFi Mode: "); Serial.print("WiFi Mode: ");
Serial.println(WiFi.getMode()); Serial.println(WiFi.getMode());
WiFi.mode(WIFI_STA); WiFi.mode(WIFI_STA);
@ -71,7 +73,8 @@ void Network::loop() {
mqtt.loop(); mqtt.loop();
} }
void Network::emitSockets() { 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); this->emitSockets(255);
sockEmit.loop(); sockEmit.loop();
this->needsBroadcast = false; this->needsBroadcast = false;
@ -230,14 +233,23 @@ void Network::setConnected(conn_types connType) {
else if(SSDP.isStarted) SSDP.end(); else if(SSDP.isStarted) SSDP.end();
this->emitSockets(); this->emitSockets();
settings.printAvailHeap(); settings.printAvailHeap();
this->needsBroadcast = true;
} }
bool Network::connectWired() { bool Network::connectWired() {
//if(this->connType == conn_types::ethernet && ETH.linkUp()) { //if(this->connType == conn_types::ethernet && ETH.linkUp()) {
if(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; this->wifiFallback = false;
return true; return true;
} }
else if(this->ethStarted) {
if(settings.connType == conn_types::ethernetpref && settings.WIFI.ssid[0] != '\0')
return this->connectWiFi();
}
if(this->connectAttempts > 0) { if(this->connectAttempts > 0) {
Serial.printf("Ethernet Connection Lost... %d Reconnecting ", this->connectAttempts); Serial.printf("Ethernet Connection Lost... %d Reconnecting ", this->connectAttempts);
Serial.println(this->mac); Serial.println(this->mac);
@ -248,12 +260,16 @@ bool Network::connectWired() {
if(!this->ethStarted) { if(!this->ethStarted) {
this->ethStarted = true; this->ethStarted = true;
WiFi.mode(WIFI_OFF); WiFi.mode(WIFI_OFF);
WiFi.onEvent(this->networkEvent); if(settings.hostname[0] != '\0')
if(settings.hostname[0] != '\0') ETH.setHostname(settings.hostname); ETH.setHostname(settings.hostname);
else
ETH.setHostname("ESPSomfy-RTS");
Serial.print("Set hostname to:"); Serial.print("Set hostname to:");
Serial.println(ETH.getHostname()); 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)) { 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"); Serial.println("Ethernet Begin failed");
this->ethStarted = false;
if(settings.connType == conn_types::ethernetpref) { if(settings.connType == conn_types::ethernetpref) {
this->wifiFallback = true; this->wifiFallback = true;
return connectWiFi(); return connectWiFi();
@ -272,7 +288,11 @@ bool Network::connectWired() {
uint32_t wait = millis(); uint32_t wait = millis();
while(millis() - wait < 14000) { 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); delay(500);
} }
if(settings.connType == conn_types::ethernetpref) { 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; return false;
} }
void Network::updateHostname() { void Network::updateHostname() {
@ -326,7 +340,7 @@ bool Network::connectWiFi() {
this->connectStart = millis(); this->connectStart = millis();
WiFi.setSleep(false); WiFi.setSleep(false);
WiFi.mode(WIFI_MODE_NULL); WiFi.mode(WIFI_MODE_NULL);
WiFi.onEvent(this->networkEvent); //WiFi.onEvent(this->networkEvent);
if(!settings.IP.dhcp) { if(!settings.IP.dhcp) {
if(!WiFi.config(settings.IP.ip, settings.IP.gateway, settings.IP.subnet, settings.IP.dns1, settings.IP.dns2)) 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; if(settings.connType == conn_types::unset) return true;
else if(settings.connType == conn_types::ethernet || (settings.connType == conn_types::ethernetpref)) { else if(settings.connType == conn_types::ethernet || (settings.connType == conn_types::ethernetpref)) {
bool bConnected = this->connectWired(); 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(); bConnected = this->connectWiFi();
this->wifiFallback = true;
}
return bConnected; return bConnected;
} }
return this->connectWiFi(); return this->connectWiFi();
} }
/* DEPRECATED 03-02-24
int Network::getStrengthByMac(const char *macAddr) { int Network::getStrengthByMac(const char *macAddr) {
int n = WiFi.scanNetworks(true); int n = WiFi.scanNetworks(true);
for(int i = 0; i < n; i++) { for(int i = 0; i < n; i++) {
@ -411,6 +428,7 @@ int Network::getStrengthByMac(const char *macAddr) {
} }
return -100; return -100;
} }
*/
uint32_t Network::getChipId() { uint32_t Network::getChipId() {
uint32_t chipId = 0; uint32_t chipId = 0;
uint64_t mac = ESP.getEfuseMac(); uint64_t mac = ESP.getEfuseMac();
@ -421,7 +439,7 @@ uint32_t Network::getChipId() {
} }
int Network::getStrengthBySSID(const char *ssid) { int Network::getStrengthBySSID(const char *ssid) {
int32_t strength = -100; int32_t strength = -100;
int n = WiFi.scanNetworks(false, true); int n = WiFi.scanNetworks(false, false);
for(int i = 0; i < n; i++) { for(int i = 0; i < n; i++) {
if(WiFi.SSID(i).compareTo(ssid) == 0) strength = max(WiFi.RSSI(i), strength); 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) { switch(event) {
case ARDUINO_EVENT_ETH_START: case ARDUINO_EVENT_ETH_START:
Serial.println("Ethernet Started"); Serial.println("Ethernet Started");
if(settings.hostname[0] != '\0')
ETH.setHostname(settings.hostname);
else
ETH.setHostname("ESPSomfy-RTS");
break; break;
case ARDUINO_EVENT_ETH_GOT_IP: case ARDUINO_EVENT_ETH_GOT_IP:
// If the Wifi is connected then drop that connection // If the Wifi is connected then drop that connection
if(WiFi.status() == WL_CONNECTED) WiFi.disconnect(true); if(WiFi.status() == WL_CONNECTED) WiFi.disconnect(true);
Serial.print("Got Ethernet IP "); Serial.print("Got Ethernet IP ");
Serial.println(ETH.localIP()); Serial.println(ETH.localIP());
net.mac = ETH.macAddress();
net.setConnected(conn_types::ethernet);
break; break;
/* /*
case ARDUINO_EVENT_ETH_LOST_IP: case ARDUINO_EVENT_ETH_LOST_IP:
@ -539,12 +551,12 @@ void Network::networkEvent(WiFiEvent_t event) {
case ARDUINO_EVENT_ETH_CONNECTED: case ARDUINO_EVENT_ETH_CONNECTED:
Serial.print("Ethernet Connected "); Serial.print("Ethernet Connected ");
// We don't want to call setConnected if we do not have an IP address yet // We don't want to call setConnected if we do not have an IP address yet
if(ETH.localIP() != INADDR_NONE) //if(ETH.localIP() != INADDR_NONE)
net.setConnected(conn_types::ethernet); // net.setConnected(conn_types::ethernet);
break; break;
case ARDUINO_EVENT_ETH_DISCONNECTED: case ARDUINO_EVENT_ETH_DISCONNECTED:
Serial.println("Ethernet 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; net.connType = conn_types::unset;
break; break;
case ARDUINO_EVENT_ETH_STOP: case ARDUINO_EVENT_ETH_STOP:

View file

@ -29,7 +29,7 @@ class Network {
bool connectWiFi(); bool connectWiFi();
bool connectWired(); bool connectWired();
void setConnected(conn_types connType); void setConnected(conn_types connType);
int getStrengthByMac(const char *mac); //int getStrengthByMac(const char *mac);
int getStrengthBySSID(const char *ssid); int getStrengthBySSID(const char *ssid);
void updateHostname(); void updateHostname();
bool setup(); bool setup();

View file

@ -196,6 +196,7 @@ void SocketEmitter::wsEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t
git.emitUpdateCheck(num); git.emitUpdateCheck(num);
net.emitSockets(num); net.emitSockets(num);
sockServer.loop(); sockServer.loop();
net.needsBroadcast = true;
} }
break; break;
case WStype_TEXT: case WStype_TEXT:

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -9,13 +9,13 @@
unsigned long Timestamp::epoch() { unsigned long Timestamp::epoch() {
struct tm tmNow; struct tm tmNow;
time_t now; time_t now;
if(!getLocalTime(&tmNow)) return 0; if(!getLocalTime(&tmNow,50)) return 0;
time(&now); time(&now);
return now; return now;
} }
time_t Timestamp::now() { time_t Timestamp::now() {
struct tm tmNow; struct tm tmNow;
getLocalTime(&tmNow); getLocalTime(&tmNow,50);
return mktime(&tmNow); return mktime(&tmNow);
} }
time_t Timestamp::getUTC() { time_t Timestamp::getUTC() {

View file

@ -1 +1 @@
2.4.0 2.4.1

View file

@ -3,11 +3,11 @@
<head> <head>
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="stylesheet" href="main.css?v=2.4.0c" type="text/css" /> <link rel="stylesheet" href="main.css?v=2.4.1a" type="text/css" />
<link rel="stylesheet" href="widgets.css?v=2.4.0c" type="text/css" /> <link rel="stylesheet" href="widgets.css?v=2.4.1a" type="text/css" />
<link rel="stylesheet" href="icons.css?v=2.4.0c" type="text/css" /> <link rel="stylesheet" href="icons.css?v=2.4.1a" type="text/css" />
<link rel="icon" type="image/png" href="favicon.png" /> <link rel="icon" type="image/png" href="favicon.png" />
<script type="text/javascript" src="index.js?v=2.4.0c"></script> <script type="text/javascript" src="index.js?v=2.4.1a"></script>
</head> </head>
<body> <body>
<div id="divContainer" class="container main" data-auth="false"> <div id="divContainer" class="container main" data-auth="false">

View file

@ -1264,7 +1264,7 @@ var security = new Security();
class General { class General {
initialized = false; initialized = false;
appVersion = 'v2.4.0'; appVersion = 'v2.4.1';
reloadApp = false; reloadApp = false;
init() { init() {
if (this.initialized) return; if (this.initialized) return;
@ -4254,12 +4254,13 @@ class Firmware {
let div = this.createFileUploader('/restore'); let div = this.createFileUploader('/restore');
let inst = div.querySelector('div[id=divInstText]'); let inst = div.querySelector('div[id=divInstText]');
let html = '<div style="font-size:14px;">Select a backup file that you would like to restore and the options you would like to restore then press the Upload File button.</div><hr />'; let html = '<div style="font-size:14px;">Select a backup file that you would like to restore and the options you would like to restore then press the Upload File button.</div><hr />';
html += `<div style="font-size:14px;">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.</div><hr/>`; html += `<div style="font-size:14px;">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.</div><hr/>`;
html += '<div style="font-size:14px;margin-bottom:27px;text-align:left;margin-left:70px;">'; html += '<div style="font-size:14px;margin-bottom:27px;text-align:left;margin-left:70px;">';
html += `<div class="field-group" style="vertical-align:middle;width:auto;"><input id="cbRestoreShades" type="checkbox" data-bind="shades" style="display:inline-block;" checked="true" /><label for="cbRestoreShades" style="display:inline-block;cursor:pointer;color:white;">Restore Shades and Groups</label></div>`; html += `<div class="field-group" style="vertical-align:middle;width:auto;"><input id="cbRestoreShades" type="checkbox" data-bind="shades" style="display:inline-block;" checked="true" /><label for="cbRestoreShades" style="display:inline-block;cursor:pointer;color:white;">Restore Shades and Groups</label></div>`;
html += `<div class="field-group" style="vertical-align:middle;width:auto;"><input id="cbRestoreRepeaters" type="checkbox" data-bind="repeaters" style="display:inline-block;" /><label for="cbRestoreRepeaters" style="display:inline-block;cursor:pointer;color:white;">Restore Repeaters</label></div>`; html += `<div class="field-group" style="vertical-align:middle;width:auto;"><input id="cbRestoreRepeaters" type="checkbox" data-bind="repeaters" style="display:inline-block;" /><label for="cbRestoreRepeaters" style="display:inline-block;cursor:pointer;color:white;">Restore Repeaters</label></div>`;
html += `<div class="field-group" style="vertical-align:middle;width:auto;"><input id="cbRestoreSystem" type="checkbox" data-bind="settings" style="display:inline-block;" /><label for="cbRestoreSystem" style="display:inline-block;cursor:pointer;color:white;">Restore System Settings</label></div>`; html += `<div class="field-group" style="vertical-align:middle;width:auto;"><input id="cbRestoreSystem" type="checkbox" data-bind="settings" style="display:inline-block;" /><label for="cbRestoreSystem" style="display:inline-block;cursor:pointer;color:white;">Restore System Settings</label></div>`;
html += `<div class="field-group" style="vertical-align:middle;width:auto;"><input id="cbRestoreNetwork" type="checkbox" data-bind="network" style="display:inline-block;" /><label for="cbRestoreNetwork" style="display:inline-block;cursor:pointer;color:white;">Restore Network Settings</label></div>` html += `<div class="field-group" style="vertical-align:middle;width:auto;"><input id="cbRestoreNetwork" type="checkbox" data-bind="network" style="display:inline-block;" /><label for="cbRestoreNetwork" style="display:inline-block;cursor:pointer;color:white;">Restore Network Settings</label></div>`
html += `<div class="field-group" style="vertical-align:middle;width:auto;"><input id="cbRestoreMQTT" type="checkbox" data-bind="mqtt" style="display:inline-block;" /><label for="cbRestoreMQTT" style="display:inline-block;cursor:pointer;color:white;">Restore MQTT Settings</label></div>`
html += `<div class="field-group" style="vertical-align:middle;width:auto;"><input id="cbRestoreTransceiver" type="checkbox" data-bind="transceiver" style="display:inline-block;" /><label for="cbRestoreTransceiver" style="display:inline-block;cursor:pointer;color:white;">Restore Radio Settings</label></div>`; html += `<div class="field-group" style="vertical-align:middle;width:auto;"><input id="cbRestoreTransceiver" type="checkbox" data-bind="transceiver" style="display:inline-block;" /><label for="cbRestoreTransceiver" style="display:inline-block;cursor:pointer;color:white;">Restore Radio Settings</label></div>`;
html += '</div>'; html += '</div>';
inst.innerHTML = html; inst.innerHTML = html;
@ -4633,7 +4634,7 @@ class Firmware {
ui.errorMessage(el, 'This file is not a valid backup file'); ui.errorMessage(el, 'This file is not a valid backup file');
return; 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'); ui.errorMessage(el, 'No restore options have been selected');
return; return;
} }