diff --git a/ConfigSettings.h b/ConfigSettings.h index 4707984..d77358a 100644 --- a/ConfigSettings.h +++ b/ConfigSettings.h @@ -2,7 +2,7 @@ #ifndef configsettings_h #define configsettings_h -#define FW_VERSION "v1.0.8" +#define FW_VERSION "v1.0.9" enum DeviceStatus { DS_OK = 0, DS_ERROR = 1, @@ -38,7 +38,7 @@ class WifiSettings: BaseSettings { WifiSettings(); char serverId[10] = ""; char hostname[32] = "ESPSomfyRTS"; - char ssid[32] = ""; + char ssid[64] = ""; char passphrase[32] = ""; bool ssdpBroadcast = true; bool begin(); diff --git a/Network.cpp b/Network.cpp index 6208165..e54c2af 100644 --- a/Network.cpp +++ b/Network.cpp @@ -13,6 +13,8 @@ extern ConfigSettings settings; extern Web webServer; extern SocketEmitter sockEmit; extern MQTTClass mqtt; +extern rebootDelay_t rebootDelay; + void Network::end() { sockEmit.end(); SSDP.end(); @@ -21,10 +23,10 @@ void Network::end() { } bool Network::setup() { WiFi.persistent(false); - Serial.print("WiFi Mode: "); - Serial.println(WiFi.getMode()); + //Serial.print("WiFi Mode: "); + //Serial.println(WiFi.getMode()); if(WiFi.status() == WL_CONNECTED) WiFi.disconnect(true); - WiFi.mode(WIFI_AP_STA); + WiFi.mode(WIFI_STA); settings.WIFI.printNetworks(); sockEmit.begin(); if(!this->connect()) this->openSoftAP(); @@ -36,6 +38,7 @@ void Network::loop() { this->lastEmit = millis(); this->emitSockets(); } + else sockEmit.loop(); if(settings.WIFI.ssdpBroadcast) { if(!SSDP.isStarted) SSDP.begin(); SSDP.loop(); @@ -47,8 +50,8 @@ void Network::emitSockets() { if(WiFi.status() == WL_CONNECTED) { if(abs(abs(WiFi.RSSI()) - abs(this->lastRSSI)) > 2 || WiFi.channel() != this->lastChannel) { - char buf[50]; - sprintf(buf, "{\"ssid\":\"%s\", \"strength\":%d, \"channel\":%d}", WiFi.SSID(), WiFi.RSSI(), WiFi.channel()); + char buf[128]; + sprintf(buf, "{\"ssid\":\"%s\",\"strength\":%d,\"channel\":%d}", WiFi.SSID(), WiFi.RSSI(), WiFi.channel()); sockEmit.sendToClients("wifiStrength", buf); this->lastRSSI = WiFi.RSSI(); this->lastChannel = WiFi.channel(); @@ -263,18 +266,31 @@ bool Network::openSoftAP() { while ((WiFi.status() != WL_CONNECTED)) { for(int i = 0; i < 3; i++) { - delay(100); + //delay(100); //digitalWrite(LED_BUILTIN, HIGH); - delay(100); + //delay(100); //digitalWrite(LED_BUILTIN, LOW); } int clients = WiFi.softAPgetStationNum(); - if(clients > 0) - Serial.print(clients); - else - Serial.print("."); - delay(100); + webServer.loop(); + if(millis() - this->lastEmit > 1500) { + if(this->connect()) {} + this->lastEmit = millis(); + this->emitSockets(); + if(clients > 0) + Serial.print(clients); + else + Serial.print("."); + c++; + } + sockEmit.loop(); + if(rebootDelay.reboot && millis() > rebootDelay.rebootTime) { + this->end(); + ESP.restart(); + break; + } + // If no clients have connected in 3 minutes from starting this server reboot this pig. This will // force a reboot cycle until we have some response. That is unless the SSID has been cleared. if(clients == 0 && strlen(settings.WIFI.ssid) > 0 && millis() - startTime > 3 * 60000) { @@ -289,8 +305,10 @@ bool Network::openSoftAP() { WiFi.softAPdisconnect(true); return false; } - if(++c % 100 == 0) { + if(c == 100) { Serial.println(); + c = 0; } + yield(); } } diff --git a/Somfy.cpp b/Somfy.cpp index 72c9d8d..f005282 100644 --- a/Somfy.cpp +++ b/Somfy.cpp @@ -13,6 +13,7 @@ extern SomfyShadeController somfy; extern SocketEmitter sockEmit; extern MQTTClass mqtt; +uint8_t rxmode = 0; // Indicates whether the radio is in receive mode. Just to ensure there isn't more than one interrupt hooked. #define SYMBOL 640 #if defined(ESP8266) #define RECEIVE_ATTR ICACHE_RAM_ATTR @@ -254,12 +255,7 @@ bool SomfyShadeController::begin() { pref.begin("Shades"); pref.getBytes("shadeIds", this->m_shadeIds, sizeof(this->m_shadeIds)); pref.end(); - this->transceiver.begin(); - for(uint8_t i = 0; i < sizeof(this->m_shadeIds); i++) { - if(i != 0) Serial.print(","); - Serial.print(this->m_shadeIds[i]); - } - Serial.println(); + //this->transceiver.begin(); sortArray(this->m_shadeIds, sizeof(this->m_shadeIds)); for(uint8_t i = 0; i < sizeof(this->m_shadeIds); i++) { if(i != 0) Serial.print(","); @@ -461,8 +457,8 @@ void SomfyShade::load() { memset(linkedAddresses, 0x00, sizeof(uint32_t) * SOMFY_MAX_LINKED_REMOTES); snprintf(shadeKey, sizeof(shadeKey), "SomfyShade%u", this->shadeId); // Now load up each of the shades into memory. - Serial.print("key:"); - Serial.println(shadeKey); + //Serial.print("key:"); + //Serial.println(shadeKey); pref.begin(shadeKey); pref.getString("name", this->name, sizeof(this->name)); this->paired = pref.getBool("paired", false); @@ -513,9 +509,7 @@ void SomfyShade::publish() { void SomfyShade::emitState(const char *evt) { this->emitState(255, evt); } void SomfyShade::emitState(uint8_t num, const char *evt) { char buf[220]; - char shadeKey[15]; - snprintf(shadeKey, sizeof(shadeKey), "Shade_%u", this->shadeId); - sprintf(buf, "{\"shadeId\":%d, \"remoteAddress\":%d, \"name\":\"%s\", \"direction\":%d, \"position\":%d, \"target\":%d}", this->shadeId, this->getRemoteAddress(), this->name, this->direction, this->position, this->target); + snprintf(buf, sizeof(buf), "{\"shadeId\":%d,\"remoteAddress\":%d,\"name\":\"%s\",\"direction\":%d,\"position\":%d,\"target\":%d}", this->shadeId, this->getRemoteAddress(), this->name, this->direction, this->position, this->target); if(num >= 255) sockEmit.sendToClients(evt, buf); else sockEmit.sendToClient(num, evt, buf); if(mqtt.connected()) { @@ -1086,9 +1080,11 @@ void Transceiver::clearReceived(void) { attachInterrupt(interruptPin, handleReceive, CHANGE); } void Transceiver::enableReceive(void) { + if(rxmode > 0) return; if(this->config.enabled) { Serial.print("Enabling receive on Pin #"); Serial.println(this->config.RXPin); + rxmode = 1; pinMode(this->config.RXPin, INPUT); interruptPin = digitalPinToInterrupt(this->config.RXPin); ELECHOUSE_cc1101.SetRx(); @@ -1096,8 +1092,10 @@ void Transceiver::enableReceive(void) { } } void Transceiver::disableReceive(void) { + rxmode = 0; if(interruptPin > 0) detachInterrupt(interruptPin); interruptPin = 0; + } bool Transceiver::toJSON(JsonObject& obj) { Serial.println("Setting Transceiver Json"); @@ -1281,15 +1279,14 @@ void transceiver_config_t::apply() { if(this->enabled) { Serial.print("Applying radio settings "); Serial.printf("SCK:%u MISO:%u MOSI:%u CSN:%u RX:%u TX:%u\n", this->SCKPin, this->MISOPin, this->MOSIPin, this->CSNPin, this->RXPin, this->TXPin); - + ELECHOUSE_cc1101.Init(); ELECHOUSE_cc1101.setGDO(this->RXPin, this->TXPin); ELECHOUSE_cc1101.setSpiPin(this->SCKPin, this->MISOPin, this->MOSIPin, this->CSNPin); - ELECHOUSE_cc1101.Init(); ELECHOUSE_cc1101.setMHZ(this->frequency); // Here you can set your basic frequency. The lib calculates the frequency automatically (default = 433.92).The cc1101 can: 300-348 MHZ, 387-464MHZ and 779-928MHZ. Read More info from datasheet. ELECHOUSE_cc1101.setRxBW(this->rxBandwidth); // Set the Receive Bandwidth in kHz. Value from 58.03 to 812.50. Default is 812.50 kHz. ELECHOUSE_cc1101.setPA(this->txPower); // Set TxPower. The following settings are possible depending on the frequency band. (-30 -20 -15 -10 -6 0 5 7 10 11 12) Default is max! - ELECHOUSE_cc1101.setCCMode(this->internalCCMode); // set config for internal transmission mode. - ELECHOUSE_cc1101.setModulation(this->modulationMode); // set modulation mode. 0 = 2-FSK, 1 = GFSK, 2 = ASK/OOK, 3 = 4-FSK, 4 = MSK. + //ELECHOUSE_cc1101.setCCMode(this->internalCCMode); // set config for internal transmission mode. + //ELECHOUSE_cc1101.setModulation(this->modulationMode); // set modulation mode. 0 = 2-FSK, 1 = GFSK, 2 = ASK/OOK, 3 = 4-FSK, 4 = MSK. if (!ELECHOUSE_cc1101.getCC1101()) { Serial.println("Error setting up the radio"); } @@ -1336,7 +1333,7 @@ void Transceiver::loop() { this->clearReceived(); somfy.processFrame(this->frame, false); char buf[177]; - sprintf(buf, "{\"encKey\":%d, \"address\":%d, \"rcode\":%d, \"command\":\"%s\", \"rssi\":%d}", this->frame.encKey, this->frame.remoteAddress, this->frame.rollingCode, translateSomfyCommand(this->frame.cmd), this->frame.rssi); + snprintf(buf, sizeof(buf), "{\"encKey\":%d,\"address\":%d,\"rcode\":%d,\"command\":\"%s\",\"rssi\":%d}", this->frame.encKey, this->frame.remoteAddress, this->frame.rollingCode, translateSomfyCommand(this->frame.cmd), this->frame.rssi); sockEmit.sendToClients("remoteFrame", buf); } } diff --git a/SomfyController.ino.esp32.bin b/SomfyController.ino.esp32.bin index 3d5a2b8..b025b17 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 eb72f5f..1bed716 100644 Binary files a/SomfyController.littlefs.bin and b/SomfyController.littlefs.bin differ diff --git a/Web.cpp b/Web.cpp index 8047062..f4dae67 100644 --- a/Web.cpp +++ b/Web.cpp @@ -961,7 +961,7 @@ void Web::begin() { bool reboot; if (ssid.compareTo(settings.WIFI.ssid) != 0) reboot = true; if (passphrase.compareTo(settings.WIFI.passphrase) != 0) reboot = true; - if (!settings.WIFI.ssidExists(ssid.c_str())) { + if (!settings.WIFI.ssidExists(ssid.c_str()) && ssid.length() > 0) { server.send(400, _encoding_json, "{\"status\":\"ERROR\",\"desc\":\"WiFi Network Does not exist\"}"); } else { diff --git a/data/index.html b/data/index.html index db9d09f..54db206 100644 --- a/data/index.html +++ b/data/index.html @@ -1,5 +1,4 @@  - @@ -167,7 +166,7 @@ }); }; - setAppVersion() { document.getElementById('spanAppVersion').innerText = 'v1.0.8'; }; + setAppVersion() { document.getElementById('spanAppVersion').innerText = 'v1.0.9'; }; setTimeZones() { let dd = document.getElementById('selTimeZone'); dd.length = 0; @@ -535,6 +534,7 @@ procRemoteFrame(frame) { console.log(frame); document.getElementById('spanRssi').innerHTML = frame.rssi; + document.getElementById('spanFrameCount').innerHTML = parseInt(document.getElementById('spanFrameCount').innerHTML, 10) + 1 let lnk = document.getElementById('divLinking'); if (lnk) { let obj = { @@ -1016,8 +1016,24 @@ document.getElementById('fsUpdates').appendChild(div); }; async uploadFile(service, el) { - let formData = new FormData(); let field = el.querySelector('input[type="file"]'); + let filename = field.value; + console.log(filename); + switch (service) { + case '/updateApplication': + if (filename.indexOf('.littlefs') === -1 || !filename.endsWith('.bin')) { + errorMessage(el, 'This file is not a valid littleFS file system.'); + return; + } + break; + case '/updateFirmware': + if (filename.indexOf('.ino.esp') === -1 || !filename.endsWith('.bin')) { + errorMessage(el, 'This file is not a valid firmware binary file.'); + return; + } + break; + } + let formData = new FormData(); let btnUpload = el.querySelector('button[id="btnUploadFile"]'); let btnCancel = el.querySelector('button[id="btnClose"]'); btnUpload.style.display = 'none'; @@ -1026,7 +1042,6 @@ let prog = el.querySelector('div[id="progFileUpload"]'); prog.style.display = ''; btnSelectFile.style.visibility = 'hidden'; - formData.append('file', field.files[0]); let xhr = new XMLHttpRequest(); xhr.open('POST', service, true); @@ -1234,72 +1249,80 @@ wms[i].remove(); } waitMessage(document.getElementById('divContainer')).classList.add('socket-wait'); - socket = new WebSocket(`ws://${location.host}:8080`); - socket.onmessage = (evt) => { - if (evt.data.startsWith('42')) { - let ndx = evt.data.indexOf(','); - let eventName = evt.data.substring(3, ndx); - let data = evt.data.substring(ndx + 1, evt.data.length - 1); - try { - var reISO = /^(\d{4}|\+010000)-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*))(?:Z|(\+|-)([\d|:]*))?$/; - var reMsAjax = /^\/Date\((d|-|.*)\)[\/|\\]$/; - var msg = JSON.parse(data, (key, value) => { - if (typeof value === 'string') { - var a = reISO.exec(value); - if (a) return new Date(value); - a = reMsAjax.exec(value); - if (a) { - var b = a[1].split(/[-+,.]/); - return new Date(b[0] ? +b[0] : 0 - +b[1]); + try { + console.log(location); + socket = new WebSocket(`ws://${window.location.hostname}:8080/`); + socket.onmessage = (evt) => { + if (evt.data.startsWith('42')) { + let ndx = evt.data.indexOf(','); + let eventName = evt.data.substring(3, ndx); + let data = evt.data.substring(ndx + 1, evt.data.length - 1); + try { + var reISO = /^(\d{4}|\+010000)-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*))(?:Z|(\+|-)([\d|:]*))?$/; + var reMsAjax = /^\/Date\((d|-|.*)\)[\/|\\]$/; + var msg = JSON.parse(data, (key, value) => { + if (typeof value === 'string') { + var a = reISO.exec(value); + if (a) return new Date(value); + a = reMsAjax.exec(value); + if (a) { + var b = a[1].split(/[-+,.]/); + return new Date(b[0] ? +b[0] : 0 - +b[1]); + } } + return value; + }); + switch (eventName) { + case 'wifiStrength': + wifi.procWifiStrength(msg); + break; + case 'remoteFrame': + somfy.procRemoteFrame(msg); + break; + case 'shadeState': + somfy.procShadeState(msg); + break; + case 'shadeRemoved': + break; + case 'shadeAdded': + break; } - return value; - }); - switch (eventName) { - case 'wifiStrength': - wifi.procWifiStrength(msg); - break; - case 'remoteFrame': - somfy.procRemoteFrame(msg); - break; - case 'shadeState': - somfy.procShadeState(msg); - break; - case 'shadeRemoved': - break; - case 'shadeAdded': - break; + } catch (err) { + console.log({ eventName: eventName, data: data, err: err }); } - } catch (err) { - console.log({ eventName: eventName, data: data, err: err }); } + }; + socket.onopen = (evt) => { + if (tConnect) clearTimeout(tConnect); + tConnect = null; + console.log({ msg: 'open', evt: evt }); + sockIsOpen = true; + connecting = false; + let wms = document.getElementsByClassName('socket-wait'); + for (let i = 0; i < wms.length; i++) { + wms[i].remove(); + } + }; + socket.onclose = (evt) => { + waitMessage(document.getElementById('divContainer')).classList.add('socket-wait'); + if (evt.wasClean) { + console.log({ msg: 'close-clean', evt: evt }); + tConnect = setTimeout(() => { reopenSocket(); }, 10000); + console.log('Reconnecting socket in 10 seconds'); + } + else { + console.log({ msg: 'close-died', reason: evt.reason, evt: evt, sock: socket }); + tConnect = setTimeout(() => { reopenSocket(); }, 3000); + } + }; + socket.onerror = (evt) => { + console.log({ msg: 'socket error', evt: evt, sock: socket }); } - }; - socket.onopen = (evt) => { - if (tConnect) clearTimeout(tConnect); - tConnect = null; - console.log({ msg: 'open', evt: evt }); - sockIsOpen = true; - connecting = false; - let wms = document.getElementsByClassName('socket-wait'); - for (let i = 0; i < wms.length; i++) { - wms[i].remove(); - } - }; - socket.onclose = (evt) => { - waitMessage(document.getElementById('divContainer')).classList.add('socket-wait'); - if (evt.wasClean) { - console.log({ msg: 'close-clean', evt: evt }); - tConnect = setTimeout(() => { reopenSocket(); }, 10000); - console.log('Reconnecting socket in 10 seconds'); - } - else { - console.log({ msg: 'close-died', reason: evt.reason, evt: evt }); - tConnect = setTimeout(() => { reopenSocket(); }, 3000); - } - }; - socket.onerror = (evt) => { - console.log({ msg: 'socket error', evt: evt }); + } catch (err) { + console.log({ + msg: 'Websocket connection error', err: err + }); + tConnect = setTimeout(() => { reopenSocket(); }, 5000); } } function reopenSocket() { @@ -1550,7 +1573,7 @@
- + --- dBm
@@ -1600,7 +1623,7 @@