Final v2.3.1

This commit is contained in:
Robert Strouse 2024-01-21 18:19:43 -08:00
parent 3f07b481dc
commit 54f98805b4
17 changed files with 318 additions and 503 deletions

View file

@ -649,3 +649,11 @@ void EthernetSettings::print() {
Serial.println("Ethernet Settings"); 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.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);
} }
void ConfigSettings::printAvailHeap() {
Serial.print("Max Heap: ");
Serial.println(ESP.getMaxAllocHeap());
Serial.print("Free Heap: ");
Serial.println(ESP.getFreeHeap());
Serial.print("Min Heap: ");
Serial.println(ESP.getMinFreeHeap());
}

View file

@ -153,6 +153,7 @@ enum class conn_types : byte {
}; };
class ConfigSettings: BaseSettings { class ConfigSettings: BaseSettings {
public: public:
static void printAvailHeap();
char serverId[10] = ""; char serverId[10] = "";
char hostname[32] = "ESPSomfyRTS"; char hostname[32] = "ESPSomfyRTS";
char chipModel[10] = "ESP32"; char chipModel[10] = "ESP32";

View file

@ -83,136 +83,142 @@ bool GitRelease::toJSON(JsonObject &obj) {
#define ERR_CLIENT_OFFSET -50 #define ERR_CLIENT_OFFSET -50
int16_t GitRepo::getReleases(uint8_t num) { int16_t GitRepo::getReleases(uint8_t num) {
WiFiClientSecure *client = new WiFiClientSecure; WiFiClientSecure sclient;
if(client) { sclient.setInsecure();
client->setInsecure(); uint8_t ndx = 0;
HTTPClient https; uint8_t count = min((uint8_t)GIT_MAX_RELEASES, num);
uint8_t ndx = 0; char url[128];
uint8_t count = min((uint8_t)GIT_MAX_RELEASES, num); memset(this->releases, 0x00, sizeof(GitRelease) * GIT_MAX_RELEASES);
char url[128]; sprintf(url, "https://api.github.com/repos/rstrouse/espsomfy-rts/releases?per_page=%d&page=1", count);
memset(this->releases, 0x00, sizeof(GitRelease) * GIT_MAX_RELEASES); GitRelease *main = &this->releases[GIT_MAX_RELEASES];
sprintf(url, "https://api.github.com/repos/rstrouse/espsomfy-rts/releases?per_page=%d&page=1", count); main->releaseDate = Timestamp::now();
GitRelease *main = &this->releases[GIT_MAX_RELEASES]; main->id = 1;
main->releaseDate = Timestamp::now(); main->main = true;
main->id = 1; strcpy(main->version.name, "main");
main->main = true; strcpy(main->name, "Main");
strcpy(main->version.name, "main"); strcpy(main->hwVersions, "32,s3");
strcpy(main->name, "Main"); HTTPClient *https = new HTTPClient();
strcpy(main->hwVersions, "32,s3"); https->setReuse(false);
if(https.begin(*client, url)) { if(https->begin(sclient, url)) {
int httpCode = https.GET(); int httpCode = https->GET();
Serial.printf("[HTTPS] GET... code: %d\n", httpCode); Serial.printf("[HTTPS] GET... code: %d\n", httpCode);
if(httpCode > 0) { if(httpCode > 0) {
int len = https.getSize(); int len = https->getSize();
Serial.printf("[HTTPS] GET... code: %d - %d\n", httpCode, len); Serial.printf("[HTTPS] GET... code: %d - %d\n", httpCode, len);
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) { if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
WiFiClient *stream = https.getStreamPtr(); WiFiClient *stream = https->getStreamPtr();
uint8_t buff[128] = {0}; uint8_t buff[128] = {0};
char jsonElem[32] = ""; char jsonElem[32] = "";
char jsonValue[128] = ""; char jsonValue[128] = "";
int arrTok = 0; int arrTok = 0;
int objTok = 0; int objTok = 0;
bool inQuote = false; bool inQuote = false;
bool inElem = false; bool inElem = false;
bool inValue = false; bool inValue = false;
bool awaitValue = false; bool awaitValue = false;
bool inAss = false; bool inAss = false;
while(https.connected() && (len > 0 || len == -1) && ndx < count) { while(https->connected() && (len > 0 || len == -1) && ndx < count) {
size_t size = stream->available(); size_t size = stream->available();
if(size) { if(size) {
int c = stream->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size)); int c = stream->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size));
//Serial.write(buff, c); //Serial.write(buff, c);
if(len > 0) len -= c; if(len > 0) len -= c;
// Now we should have some data. // Now we should have some data.
for(uint8_t i = 0; i < c; i++) { for(uint8_t i = 0; i < c; i++) {
// Read the buffer a byte at a time until we have a key value pair. // Read the buffer a byte at a time until we have a key value pair.
char ch = static_cast<char>(buff[i]); char ch = static_cast<char>(buff[i]);
if(ch == '[') { if(ch == '[') {
arrTok++; arrTok++;
if(arrTok == 2 && strcmp(jsonElem, "assets") == 0) { if(arrTok == 2 && strcmp(jsonElem, "assets") == 0) {
inElem = inValue = awaitValue = false; inElem = inValue = awaitValue = false;
inAss = true; inAss = true;
//Serial.printf("%s: %d\n", jsonElem, arrTok); //Serial.printf("%s: %d\n", jsonElem, arrTok);
}
else if(arrTok < 2) inAss = false;
}
else if(ch == ']') {
arrTok--;
if(arrTok < 2) inAss = false;
}
else if(ch == '{') {
objTok++;
if(objTok != 1 && !inAss) inElem = inValue = awaitValue = false;
}
else if(ch == '}') {
objTok--;
if(objTok == 0) ndx++;
}
else if(objTok == 1 || inAss) {
// We only want data from the root object.
//if(inAss) Serial.print(ch);
if(ch == '\"') {
inQuote = !inQuote;
if(inElem) {
inElem = false;
awaitValue = true;
} }
else if(arrTok < 2) inAss = false; else if(inValue) {
} inValue = false;
else if(ch == ']') { inElem = false;
arrTok--; awaitValue = false;
if(arrTok < 2) inAss = false; if(inAss)
} this->releases[ndx].setAssetProperty(jsonElem, jsonValue);
else if(ch == '{') { else
objTok++; this->releases[ndx].setReleaseProperty(jsonElem, jsonValue);
if(objTok != 1 && !inAss) inElem = inValue = awaitValue = false;
}
else if(ch == '}') {
objTok--;
if(objTok == 0) ndx++;
}
else if(objTok == 1 || inAss) {
// We only want data from the root object.
//if(inAss) Serial.print(ch);
if(ch == '\"') {
inQuote = !inQuote;
if(inElem) {
inElem = false;
awaitValue = true;
}
else if(inValue) {
inValue = false;
inElem = false;
awaitValue = false;
if(inAss)
this->releases[ndx].setAssetProperty(jsonElem, jsonValue);
else
this->releases[ndx].setReleaseProperty(jsonElem, jsonValue);
memset(jsonElem, 0x00, sizeof(jsonElem));
memset(jsonValue, 0x00, sizeof(jsonValue));
}
else if(awaitValue) inValue = true;
else {
inElem = true;
awaitValue = false;
}
}
else if(awaitValue) {
if(ch != ' ' && ch != ':') {
strncat(jsonValue, &ch, 1);
awaitValue = false;
inValue = true;
}
}
else if((!inQuote && ch == ',') || ch == '\r' || ch == '\n') {
inElem = inValue = awaitValue = false;
if(strlen(jsonElem) > 0) {
if(inAss)
this->releases[ndx].setAssetProperty(jsonElem, jsonValue);
else
this->releases[ndx].setReleaseProperty(jsonElem, jsonValue);
}
memset(jsonElem, 0x00, sizeof(jsonElem)); memset(jsonElem, 0x00, sizeof(jsonElem));
memset(jsonValue, 0x00, sizeof(jsonValue)); memset(jsonValue, 0x00, sizeof(jsonValue));
} }
else if(awaitValue) inValue = true;
else { else {
if(inElem) { inElem = true;
if(strlen(jsonElem) < sizeof(jsonElem) - 1) strncat(jsonElem, &ch, 1); awaitValue = false;
} }
else if(inValue) { }
if(strlen(jsonValue) < sizeof(jsonValue) - 1) strncat(jsonValue, &ch, 1); else if(awaitValue) {
} if(ch != ' ' && ch != ':') {
strncat(jsonValue, &ch, 1);
awaitValue = false;
inValue = true;
}
}
else if((!inQuote && ch == ',') || ch == '\r' || ch == '\n') {
inElem = inValue = awaitValue = false;
if(strlen(jsonElem) > 0) {
if(inAss)
this->releases[ndx].setAssetProperty(jsonElem, jsonValue);
else
this->releases[ndx].setReleaseProperty(jsonElem, jsonValue);
}
memset(jsonElem, 0x00, sizeof(jsonElem));
memset(jsonValue, 0x00, sizeof(jsonValue));
}
else {
if(inElem) {
if(strlen(jsonElem) < sizeof(jsonElem) - 1) strncat(jsonElem, &ch, 1);
}
else if(inValue) {
if(strlen(jsonValue) < sizeof(jsonValue) - 1) strncat(jsonValue, &ch, 1);
} }
} }
} }
delay(1);
} }
//else break; delay(1);
} }
//else break;
} }
else return httpCode;
} }
https.end(); else {
https->end();
sclient.stop();
delete https;
return httpCode;
}
} }
delete client; https->end();
delete https;
} }
sclient.stop();
settings.printAvailHeap();
return 0; return 0;
} }
bool GitRepo::toJSON(JsonObject &obj) { bool GitRepo::toJSON(JsonObject &obj) {
@ -257,6 +263,7 @@ void GitUpdater::checkForUpdate() {
if(this->status != 0) return; // If we are already checking. if(this->status != 0) return; // If we are already checking.
Serial.println("Check github for updates..."); Serial.println("Check github for updates...");
this->status = GIT_STATUS_CHECK; this->status = GIT_STATUS_CHECK;
settings.printAvailHeap();
if(this->checkInternet() == 0) { if(this->checkInternet() == 0) {
GitRepo repo; GitRepo repo;
this->lastCheck = millis(); this->lastCheck = millis();
@ -310,26 +317,26 @@ void GitUpdater::emitUpdateCheck(uint8_t num) {
int GitUpdater::checkInternet() { int GitUpdater::checkInternet() {
int err = 500; int err = 500;
uint32_t t = millis(); uint32_t t = millis();
WiFiClientSecure *client = new WiFiClientSecure; WiFiClientSecure client;
if(client) { client.setInsecure();
client->setInsecure(); HTTPClient *https = new HTTPClient();
HTTPClient https; https->setReuse(false);
if(https.begin(*client, "https://github.com/rstrouse/ESPSomfy-RTS")) { if(https->begin(client, "https://github.com/rstrouse/ESPSomfy-RTS")) {
https.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS); https->setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS);
https.setTimeout(5000); https->setTimeout(5000);
int httpCode = https.sendRequest("HEAD"); int httpCode = https->sendRequest("HEAD");
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY || httpCode == HTTP_CODE_FOUND) { if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY || httpCode == HTTP_CODE_FOUND) {
err = 0; err = 0;
Serial.printf("Check Internet Success: %ldms\n", millis() - t); Serial.printf("Check Internet Success: %ldms\n", millis() - t);
}
else {
err = httpCode;
Serial.printf("Check Internet Error: %d: %ldms\n", err, millis() - t);
}
https.end();
} }
delete client; else {
err = httpCode;
Serial.printf("Check Internet Error: %d: %ldms\n", err, millis() - t);
}
https->end();
} }
client.stop();
delete https;
return err; return err;
} }
void GitUpdater::emitDownloadProgress(size_t total, size_t loaded, const char *evt) { this->emitDownloadProgress(255, total, loaded, evt); } void GitUpdater::emitDownloadProgress(size_t total, size_t loaded, const char *evt) { this->emitDownloadProgress(255, total, loaded, evt); }
@ -523,6 +530,7 @@ int8_t GitUpdater::downloadFile() {
Serial.printf("End update %s\n", this->currentFile); Serial.printf("End update %s\n", this->currentFile);
} }
client->stop();
delete client; delete client;
} }
return 0; return 0;

View file

@ -214,6 +214,7 @@ void Network::setConnected(conn_types connType) {
} }
else if(SSDP.isStarted) SSDP.end(); else if(SSDP.isStarted) SSDP.end();
this->emitSockets(); this->emitSockets();
settings.printAvailHeap();
} }
bool Network::connectWired() { bool Network::connectWired() {
if(this->connType == conn_types::ethernet) { if(this->connType == conn_types::ethernet) {

View file

@ -69,6 +69,8 @@ void SocketEmitter::begin() {
sockServer.begin(); sockServer.begin();
sockServer.enableHeartbeat(20000, 10000, 3); sockServer.enableHeartbeat(20000, 10000, 3);
sockServer.onEvent(this->wsEvent); sockServer.onEvent(this->wsEvent);
Serial.println("Socket Server Started...");
settings.printAvailHeap();
} }
void SocketEmitter::loop() { void SocketEmitter::loop() {
sockServer.loop(); sockServer.loop();

View file

@ -1,7 +1,6 @@
#include <WebSocketsServer.h> #include <WebSocketsServer.h>
#ifndef sockets_h #ifndef sockets_h
#define sockets_h #define sockets_h
#include <ArduinoJson.h>
#define SOCK_MAX_ROOMS 1 #define SOCK_MAX_ROOMS 1
#define ROOM_EMIT_FRAME 0 #define ROOM_EMIT_FRAME 0

View file

@ -446,6 +446,7 @@ void SomfyShadeController::updateGroupFlags() {
} }
} }
} }
#ifdef USE_NVS
bool SomfyShadeController::loadLegacy() { bool SomfyShadeController::loadLegacy() {
Serial.println("Loading Legacy shades using NVS"); Serial.println("Loading Legacy shades using NVS");
pref.begin("Shades", true); pref.begin("Shades", true);
@ -485,18 +486,22 @@ bool SomfyShadeController::loadLegacy() {
} }
Serial.println(); Serial.println();
#endif #endif
#ifdef USE_NVS
if(!this->useNVS()) { if(!this->useNVS()) {
pref.begin("Shades"); pref.begin("Shades");
pref.putBytes("shadeIds", this->m_shadeIds, sizeof(this->m_shadeIds)); pref.putBytes("shadeIds", this->m_shadeIds, sizeof(this->m_shadeIds));
pref.end(); pref.end();
} }
#endif
this->commit(); this->commit();
return true; return true;
} }
#endif
bool SomfyShadeController::begin() { bool SomfyShadeController::begin() {
// Load up all the configuration data. // Load up all the configuration data.
//ShadeConfigFile::getAppVersion(this->appVersion); //ShadeConfigFile::getAppVersion(this->appVersion);
Serial.printf("App Version:%u.%u.%u\n", settings.appVersion.major, settings.appVersion.minor, settings.appVersion.build); Serial.printf("App Version:%u.%u.%u\n", settings.appVersion.major, settings.appVersion.minor, settings.appVersion.build);
#ifdef USE_NVS
if(!this->useNVS()) { // At 1.4 we started using the configuration file. If the file doesn't exist then booh. if(!this->useNVS()) { // At 1.4 we started using the configuration file. If the file doesn't exist then booh.
// We need to remove all the extraeneous data from NVS for the shades. From here on out we // We need to remove all the extraeneous data from NVS for the shades. From here on out we
// will rely on the shade configuration. // will rely on the shade configuration.
@ -523,13 +528,16 @@ bool SomfyShadeController::begin() {
pref.end(); pref.end();
} }
} }
else if(ShadeConfigFile::exists()) { #endif
if(ShadeConfigFile::exists()) {
Serial.println("shades.cfg exists so we are using that"); Serial.println("shades.cfg exists so we are using that");
ShadeConfigFile::load(this); ShadeConfigFile::load(this);
} }
else { else {
Serial.println("Starting clean"); Serial.println("Starting clean");
#ifdef USE_NVS
this->loadLegacy(); this->loadLegacy();
#endif
} }
this->transceiver.begin(); this->transceiver.begin();
@ -538,7 +546,7 @@ bool SomfyShadeController::begin() {
for(uint8_t i = 0; i < SOMFY_MAX_SHADES; i++) { for(uint8_t i = 0; i < SOMFY_MAX_SHADES; i++) {
SomfyShade *shade = &this->shades[i]; SomfyShade *shade = &this->shades[i];
if(shade->getShadeId() != 255 && shade->bitLength == 0) { if(shade->getShadeId() != 255 && shade->bitLength == 0) {
Serial.printf("Setting bit length to %d\n", this->transceiver.config.type); //Serial.printf("Setting bit length to %d\n", this->transceiver.config.type);
shade->bitLength = this->transceiver.config.type; shade->bitLength = this->transceiver.config.type;
saveFlag = true; saveFlag = true;
} }
@ -650,6 +658,7 @@ bool SomfyShade::linkRemote(uint32_t address, uint16_t rollingCode) {
if(this->linkedRemotes[i].getRemoteAddress() == 0) { if(this->linkedRemotes[i].getRemoteAddress() == 0) {
this->linkedRemotes[i].setRemoteAddress(address); this->linkedRemotes[i].setRemoteAddress(address);
this->linkedRemotes[i].setRollingCode(rollingCode); this->linkedRemotes[i].setRollingCode(rollingCode);
#ifdef USE_NVS
if(somfy.useNVS()) { if(somfy.useNVS()) {
uint32_t linkedAddresses[SOMFY_MAX_LINKED_REMOTES]; uint32_t linkedAddresses[SOMFY_MAX_LINKED_REMOTES];
memset(linkedAddresses, 0x00, sizeof(linkedAddresses)); memset(linkedAddresses, 0x00, sizeof(linkedAddresses));
@ -664,6 +673,7 @@ bool SomfyShade::linkRemote(uint32_t address, uint16_t rollingCode) {
pref.putBytes("linkedAddr", linkedAddresses, sizeof(uint32_t) * SOMFY_MAX_LINKED_REMOTES); pref.putBytes("linkedAddr", linkedAddresses, sizeof(uint32_t) * SOMFY_MAX_LINKED_REMOTES);
pref.end(); pref.end();
} }
#endif
this->commit(); this->commit();
return true; return true;
} }
@ -689,6 +699,7 @@ bool SomfyGroup::linkShade(uint8_t shadeId) {
void SomfyShade::commit() { somfy.commit(); } void SomfyShade::commit() { somfy.commit(); }
void SomfyShade::commitShadePosition() { void SomfyShade::commitShadePosition() {
somfy.isDirty = true; somfy.isDirty = true;
#ifdef USE_NVS
char shadeKey[15]; char shadeKey[15];
if(somfy.useNVS()) { if(somfy.useNVS()) {
snprintf(shadeKey, sizeof(shadeKey), "SomfyShade%u", this->shadeId); snprintf(shadeKey, sizeof(shadeKey), "SomfyShade%u", this->shadeId);
@ -698,9 +709,11 @@ void SomfyShade::commitShadePosition() {
pref.putFloat("currentPos", this->currentPos); pref.putFloat("currentPos", this->currentPos);
pref.end(); pref.end();
} }
#endif
} }
void SomfyShade::commitMyPosition() { void SomfyShade::commitMyPosition() {
somfy.isDirty = true; somfy.isDirty = true;
#ifdef USE_NVS
if(somfy.useNVS()) { if(somfy.useNVS()) {
char shadeKey[15]; char shadeKey[15];
snprintf(shadeKey, sizeof(shadeKey), "SomfyShade%u", this->shadeId); snprintf(shadeKey, sizeof(shadeKey), "SomfyShade%u", this->shadeId);
@ -711,9 +724,11 @@ void SomfyShade::commitMyPosition() {
pref.putUShort("myPos", this->myPos); pref.putUShort("myPos", this->myPos);
pref.end(); pref.end();
} }
#endif
} }
void SomfyShade::commitTiltPosition() { void SomfyShade::commitTiltPosition() {
somfy.isDirty = true; somfy.isDirty = true;
#ifdef USE_NVS
if(somfy.useNVS()) { if(somfy.useNVS()) {
char shadeKey[15]; char shadeKey[15];
snprintf(shadeKey, sizeof(shadeKey), "SomfyShade%u", this->shadeId); snprintf(shadeKey, sizeof(shadeKey), "SomfyShade%u", this->shadeId);
@ -723,11 +738,13 @@ void SomfyShade::commitTiltPosition() {
pref.putFloat("currentTiltPos", this->currentTiltPos); pref.putFloat("currentTiltPos", this->currentTiltPos);
pref.end(); pref.end();
} }
#endif
} }
bool SomfyShade::unlinkRemote(uint32_t address) { bool SomfyShade::unlinkRemote(uint32_t address) {
for(uint8_t i = 0; i < SOMFY_MAX_LINKED_REMOTES; i++) { for(uint8_t i = 0; i < SOMFY_MAX_LINKED_REMOTES; i++) {
if(this->linkedRemotes[i].getRemoteAddress() == address) { if(this->linkedRemotes[i].getRemoteAddress() == address) {
this->linkedRemotes[i].setRemoteAddress(0); this->linkedRemotes[i].setRemoteAddress(0);
#ifdef USE_NVS
if(somfy.useNVS()) { if(somfy.useNVS()) {
char shadeKey[15]; char shadeKey[15];
snprintf(shadeKey, sizeof(shadeKey), "SomfyShade%u", this->getShadeId()); snprintf(shadeKey, sizeof(shadeKey), "SomfyShade%u", this->getShadeId());
@ -742,6 +759,7 @@ bool SomfyShade::unlinkRemote(uint32_t address) {
pref.putBytes("linkedAddr", linkedAddresses, sizeof(uint32_t) * SOMFY_MAX_LINKED_REMOTES); pref.putBytes("linkedAddr", linkedAddresses, sizeof(uint32_t) * SOMFY_MAX_LINKED_REMOTES);
pref.end(); pref.end();
} }
#endif
this->commit(); this->commit();
return true; return true;
} }
@ -1257,6 +1275,7 @@ void SomfyShade::checkMovement() {
this->emitState(); this->emitState();
} }
} }
#ifdef USE_NVS
void SomfyShade::load() { void SomfyShade::load() {
char shadeKey[15]; char shadeKey[15];
uint32_t linkedAddresses[SOMFY_MAX_LINKED_REMOTES]; uint32_t linkedAddresses[SOMFY_MAX_LINKED_REMOTES];
@ -1317,6 +1336,7 @@ void SomfyShade::load() {
} }
pref.end(); pref.end();
} }
#endif
void SomfyRoom::publish() { void SomfyRoom::publish() {
if(mqtt.connected()) { if(mqtt.connected()) {
char topic[64]; char topic[64];
@ -2787,6 +2807,7 @@ void SomfyShade::moveToTarget(float pos, float tilt) {
} }
} }
bool SomfyShade::save() { bool SomfyShade::save() {
#ifdef USE_NVS
if(somfy.useNVS()) { if(somfy.useNVS()) {
char shadeKey[15]; char shadeKey[15];
snprintf(shadeKey, sizeof(shadeKey), "SomfyShade%u", this->getShadeId()); snprintf(shadeKey, sizeof(shadeKey), "SomfyShade%u", this->getShadeId());
@ -2814,6 +2835,7 @@ bool SomfyShade::save() {
pref.putBytes("linkedAddr", linkedAddresses, sizeof(uint32_t) * SOMFY_MAX_LINKED_REMOTES); pref.putBytes("linkedAddr", linkedAddresses, sizeof(uint32_t) * SOMFY_MAX_LINKED_REMOTES);
pref.end(); pref.end();
} }
#endif
this->commit(); this->commit();
this->publish(); this->publish();
return true; return true;
@ -3338,6 +3360,7 @@ SomfyShade *SomfyShadeController::addShade() {
shade->sortOrder = this->getMaxShadeOrder() + 1; shade->sortOrder = this->getMaxShadeOrder() + 1;
Serial.printf("Sort order set to %d\n", shade->sortOrder); Serial.printf("Sort order set to %d\n", shade->sortOrder);
this->isDirty = true; this->isDirty = true;
#ifdef USE_NVS
if(this->useNVS()) { if(this->useNVS()) {
for(uint8_t i = 0; i < sizeof(this->m_shadeIds); i++) { for(uint8_t i = 0; i < sizeof(this->m_shadeIds); i++) {
this->m_shadeIds[i] = this->shades[i].getShadeId(); this->m_shadeIds[i] = this->shades[i].getShadeId();
@ -3384,6 +3407,7 @@ SomfyShade *SomfyShadeController::addShade() {
} }
Serial.println(); Serial.println();
} }
#endif
} }
return shade; return shade;
} }
@ -3587,6 +3611,7 @@ bool SomfyShadeController::deleteShade(uint8_t shadeId) {
this->shades[i].clear(); this->shades[i].clear();
} }
} }
#ifdef USE_NVS
if(this->useNVS()) { if(this->useNVS()) {
for(uint8_t i = 0; i < sizeof(this->m_shadeIds) - 1; i++) { for(uint8_t i = 0; i < sizeof(this->m_shadeIds) - 1; i++) {
if(this->m_shadeIds[i] == shadeId) { if(this->m_shadeIds[i] == shadeId) {
@ -3601,6 +3626,7 @@ bool SomfyShadeController::deleteShade(uint8_t shadeId) {
pref.putBytes("shadeIds", this->m_shadeIds, sizeof(this->m_shadeIds)); pref.putBytes("shadeIds", this->m_shadeIds, sizeof(this->m_shadeIds));
pref.end(); pref.end();
} }
#endif
this->commit(); this->commit();
return true; return true;
} }

View file

@ -267,7 +267,9 @@ class SomfyShade : public SomfyRemote {
bool flipPosition = false; bool flipPosition = false;
shade_types shadeType = shade_types::roller; shade_types shadeType = shade_types::roller;
tilt_types tiltType = tilt_types::none; tilt_types tiltType = tilt_types::none;
#ifdef USE_NVS
void load(); void load();
#endif
somfy_tx_queue_t txQueue; somfy_tx_queue_t txQueue;
float currentPos = 0.0f; float currentPos = 0.0f;
float currentTiltPos = 0.0f; float currentTiltPos = 0.0f;
@ -546,7 +548,9 @@ class SomfyShadeController {
void commit(); void commit();
void writeBackup(); void writeBackup();
bool loadShadesFile(const char *filename); bool loadShadesFile(const char *filename);
#ifdef USE_NVS
bool loadLegacy(); bool loadLegacy();
#endif
}; };
#endif #endif

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,9 +1,13 @@
#ifndef utils_h #ifndef utils_h
#define utils_h #define utils_h
#include <Arduino.h>
#define DEBUG_SOMFY Serial #define DEBUG_SOMFY Serial
[[maybe_unused]] static void SETCHARPROP(char *prop, const char *value, size_t size) {strncpy(prop, value, size); prop[size - 1] = '\0';} [[maybe_unused]] static void SETCHARPROP(char *prop, const char *value, size_t size) {strncpy(prop, value, size); prop[size - 1] = '\0';}
namespace util { namespace util {
// Createa a custom to_string function. C++ can be annoying // Createa a custom to_string function. C++ can be annoying

463
Web.cpp
View file

@ -60,6 +60,19 @@ void Web::sendCacheHeaders(uint32_t seconds) {
void Web::end() { void Web::end() {
//server.end(); //server.end();
} }
void Web::handleDeserializationError(WebServer &server, DeserializationError &err) {
switch (err.code()) {
case DeserializationError::InvalidInput:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
}
bool Web::isAuthenticated(WebServer &server, bool cfg) { bool Web::isAuthenticated(WebServer &server, bool cfg) {
Serial.println("Checking authentication"); Serial.println("Checking authentication");
if(settings.Security.type == security_types::None) return true; if(settings.Security.type == security_types::None) return true;
@ -148,17 +161,7 @@ void Web::handleLogin(WebServer &server) {
DynamicJsonDocument docin(512); DynamicJsonDocument docin(512);
DeserializationError err = deserializeJson(docin, server.arg("plain")); DeserializationError err = deserializeJson(docin, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { this->handleDeserializationError(server, err);
case DeserializationError::InvalidInput:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
return; return;
} }
else { else {
@ -223,16 +226,17 @@ void Web::handleStreamFile(WebServer &server, const char *filename, const char *
file.close(); file.close();
} }
void Web::handleController(WebServer &server) { void Web::handleController(WebServer &server) {
webServer.sendCORSHeaders(server); webServer.sendCORSHeaders(server);
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; } if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
HTTPMethod method = server.method(); HTTPMethod method = server.method();
if (method == HTTP_POST || method == HTTP_GET) { settings.printAvailHeap();
DynamicJsonDocument doc(16384); if (method == HTTP_POST || method == HTTP_GET) {
somfy.toJSON(doc); DynamicJsonDocument doc(16384);
serializeJson(doc, g_content); somfy.toJSON(doc);
server.send(200, _encoding_json, g_content); serializeJson(doc, g_content);
} server.send(200, _encoding_json, g_content);
else server.send(404, _encoding_text, _response_404); }
else server.send(404, _encoding_text, _response_404);
} }
void Web::handleLoginContext(WebServer &server) { void Web::handleLoginContext(WebServer &server) {
webServer.sendCORSHeaders(server); webServer.sendCORSHeaders(server);
@ -307,17 +311,7 @@ void Web::handleShadeCommand(WebServer& server) {
DynamicJsonDocument doc(256); DynamicJsonDocument doc(256);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { this->handleDeserializationError(server, err);
case DeserializationError::InvalidInput:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
return; return;
} }
else { else {
@ -376,17 +370,7 @@ void Web::handleRepeatCommand(WebServer& server) {
DynamicJsonDocument doc(256); DynamicJsonDocument doc(256);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { this->handleDeserializationError(server, err);
case DeserializationError::InvalidInput:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
return; return;
} }
else { else {
@ -459,17 +443,7 @@ void Web::handleGroupCommand(WebServer &server) {
DynamicJsonDocument doc(256); DynamicJsonDocument doc(256);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { this->handleDeserializationError(server, err);
case DeserializationError::InvalidInput:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
return; return;
} }
else { else {
@ -522,17 +496,7 @@ void Web::handleTiltCommand(WebServer &server) {
DynamicJsonDocument doc(256); DynamicJsonDocument doc(256);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { this->handleDeserializationError(server, err);
case DeserializationError::InvalidInput:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
return; return;
} }
else { else {
@ -599,17 +563,8 @@ void Web::handleRoom(WebServer &server) {
DynamicJsonDocument doc(512); DynamicJsonDocument doc(512);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { this->handleDeserializationError(server, err);
case DeserializationError::InvalidInput: return;
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
} }
else { else {
JsonObject obj = doc.as<JsonObject>(); JsonObject obj = doc.as<JsonObject>();
@ -668,17 +623,8 @@ void Web::handleShade(WebServer &server) {
DynamicJsonDocument doc(512); DynamicJsonDocument doc(512);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { this->handleDeserializationError(server, err);
case DeserializationError::InvalidInput: return;
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
} }
else { else {
JsonObject obj = doc.as<JsonObject>(); JsonObject obj = doc.as<JsonObject>();
@ -737,17 +683,8 @@ void Web::handleGroup(WebServer &server) {
DynamicJsonDocument doc(512); DynamicJsonDocument doc(512);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { this->handleDeserializationError(server, err);
case DeserializationError::InvalidInput: return;
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
} }
else { else {
JsonObject obj = doc.as<JsonObject>(); JsonObject obj = doc.as<JsonObject>();
@ -845,17 +782,8 @@ void Web::handleSetPositions(WebServer &server) {
DynamicJsonDocument doc(512); DynamicJsonDocument doc(512);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { this->handleDeserializationError(server, err);
case DeserializationError::InvalidInput: return;
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
} }
else { else {
JsonObject obj = doc.as<JsonObject>(); JsonObject obj = doc.as<JsonObject>();
@ -895,17 +823,8 @@ void Web::handleSetSensor(WebServer &server) {
DynamicJsonDocument doc(512); DynamicJsonDocument doc(512);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { this->handleDeserializationError(server, err);
case DeserializationError::InvalidInput: return;
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
} }
else { else {
JsonObject obj = doc.as<JsonObject>(); JsonObject obj = doc.as<JsonObject>();
@ -1026,6 +945,20 @@ void Web::handleNotFound(WebServer &server) {
snprintf(g_content, sizeof(g_content), "404 Service Not Found: %s", server.uri().c_str()); snprintf(g_content, sizeof(g_content), "404 Service Not Found: %s", server.uri().c_str());
server.send(404, _encoding_text, g_content); server.send(404, _encoding_text, g_content);
} }
void Web::handleReboot(WebServer &server) {
webServer.sendCORSHeaders(server);
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
HTTPMethod method = server.method();
if (method == HTTP_POST || method == HTTP_PUT) {
Serial.println("Rebooting ESP...");
rebootDelay.reboot = true;
rebootDelay.rebootTime = millis() + 500;
server.send(200, "application/json", "{\"status\":\"OK\",\"desc\":\"Successfully started reboot\"}");
}
else {
server.send(201, _encoding_json, "{\"status\":\"ERROR\",\"desc\":\"Invalid HTTP Method: \"}");
}
}
void Web::begin() { void Web::begin() {
Serial.println("Creating Web MicroServices..."); Serial.println("Creating Web MicroServices...");
server.enableCORS(true); server.enableCORS(true);
@ -1052,6 +985,7 @@ void Web::begin() {
apiServer.on("/setSensor", []() { webServer.handleSetSensor(apiServer); }); apiServer.on("/setSensor", []() { webServer.handleSetSensor(apiServer); });
apiServer.on("/downloadFirmware", []() { webServer.handleDownloadFirmware(apiServer); }); apiServer.on("/downloadFirmware", []() { webServer.handleDownloadFirmware(apiServer); });
apiServer.on("/backup", []() { webServer.handleBackup(apiServer); }); apiServer.on("/backup", []() { webServer.handleBackup(apiServer); });
apiServer.on("/reboot", []() { webServer.handleReboot(apiServer); });
// Web Interface // Web Interface
server.on("/tiltCommand", []() { webServer.handleTiltCommand(server); }); server.on("/tiltCommand", []() { webServer.handleTiltCommand(server); });
@ -1102,18 +1036,7 @@ void Web::begin() {
StaticJsonDocument<256> doc; StaticJsonDocument<256> doc;
DeserializationError err = deserializeJson(doc, server.arg("data")); DeserializationError err = deserializeJson(doc, server.arg("data"));
if (err) { if (err) {
switch (err.code()) { webServer.handleDeserializationError(server, err);
case DeserializationError::InvalidInput:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
Serial.println("An error occurred when deserializing the restore data");
return; return;
} }
else { else {
@ -1208,17 +1131,8 @@ void Web::begin() {
DynamicJsonDocument doc(512); DynamicJsonDocument doc(512);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { webServer.handleDeserializationError(server, err);
case DeserializationError::InvalidInput: return;
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
} }
else { else {
JsonObject obj = doc.as<JsonObject>(); JsonObject obj = doc.as<JsonObject>();
@ -1263,17 +1177,8 @@ void Web::begin() {
DynamicJsonDocument doc(1024); DynamicJsonDocument doc(1024);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { webServer.handleDeserializationError(server, err);
case DeserializationError::InvalidInput: return;
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
} }
else { else {
JsonObject obj = doc.as<JsonObject>(); JsonObject obj = doc.as<JsonObject>();
@ -1319,17 +1224,8 @@ void Web::begin() {
DynamicJsonDocument doc(512); DynamicJsonDocument doc(512);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { webServer.handleDeserializationError(server, err);
case DeserializationError::InvalidInput: return;
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
} }
else { else {
JsonObject obj = doc.as<JsonObject>(); JsonObject obj = doc.as<JsonObject>();
@ -1416,17 +1312,8 @@ void Web::begin() {
DynamicJsonDocument doc(512); DynamicJsonDocument doc(512);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { webServer.handleDeserializationError(server, err);
case DeserializationError::InvalidInput: return;
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
} }
else { else {
JsonObject obj = doc.as<JsonObject>(); JsonObject obj = doc.as<JsonObject>();
@ -1461,17 +1348,8 @@ void Web::begin() {
DynamicJsonDocument doc(1024); DynamicJsonDocument doc(1024);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { webServer.handleDeserializationError(server, err);
case DeserializationError::InvalidInput: return;
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
} }
else { else {
JsonObject obj = doc.as<JsonObject>(); JsonObject obj = doc.as<JsonObject>();
@ -1511,17 +1389,8 @@ void Web::begin() {
DynamicJsonDocument doc(512); DynamicJsonDocument doc(512);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { webServer.handleDeserializationError(server, err);
case DeserializationError::InvalidInput: return;
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
} }
else { else {
JsonObject obj = doc.as<JsonObject>(); JsonObject obj = doc.as<JsonObject>();
@ -1561,17 +1430,7 @@ void Web::begin() {
DynamicJsonDocument doc(256); DynamicJsonDocument doc(256);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { webServer.handleDeserializationError(server, err);
case DeserializationError::InvalidInput:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
return; return;
} }
else { else {
@ -1615,17 +1474,8 @@ void Web::begin() {
StaticJsonDocument<129> doc; StaticJsonDocument<129> doc;
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { webServer.handleDeserializationError(server, err);
case DeserializationError::InvalidInput: return;
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
} }
else { else {
JsonObject obj = doc.as<JsonObject>(); JsonObject obj = doc.as<JsonObject>();
@ -1661,17 +1511,8 @@ void Web::begin() {
DynamicJsonDocument doc(512); DynamicJsonDocument doc(512);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if(err) { if(err) {
switch(err.code()) { webServer.handleDeserializationError(server, err);
case DeserializationError::InvalidInput: return;
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
} }
else { else {
JsonObject obj = doc.as<JsonObject>(); JsonObject obj = doc.as<JsonObject>();
@ -1709,17 +1550,8 @@ void Web::begin() {
DynamicJsonDocument doc(512); DynamicJsonDocument doc(512);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { webServer.handleDeserializationError(server, err);
case DeserializationError::InvalidInput: return;
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
} }
else { else {
JsonObject obj = doc.as<JsonObject>(); JsonObject obj = doc.as<JsonObject>();
@ -1758,17 +1590,8 @@ void Web::begin() {
DynamicJsonDocument doc(512); DynamicJsonDocument doc(512);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { webServer.handleDeserializationError(server, err);
case DeserializationError::InvalidInput: return;
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
} }
else { else {
JsonObject obj = doc.as<JsonObject>(); JsonObject obj = doc.as<JsonObject>();
@ -1806,17 +1629,8 @@ void Web::begin() {
DynamicJsonDocument doc(512); DynamicJsonDocument doc(512);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { webServer.handleDeserializationError(server, err);
case DeserializationError::InvalidInput: return;
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
} }
else { else {
JsonObject obj = doc.as<JsonObject>(); JsonObject obj = doc.as<JsonObject>();
@ -1854,17 +1668,8 @@ void Web::begin() {
DynamicJsonDocument doc(512); DynamicJsonDocument doc(512);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { webServer.handleDeserializationError(server, err);
case DeserializationError::InvalidInput: return;
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
} }
else { else {
JsonObject obj = doc.as<JsonObject>(); JsonObject obj = doc.as<JsonObject>();
@ -1968,17 +1773,8 @@ void Web::begin() {
DynamicJsonDocument doc(256); DynamicJsonDocument doc(256);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { webServer.handleDeserializationError(server, err);
case DeserializationError::InvalidInput: return;
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
} }
else { else {
JsonObject obj = doc.as<JsonObject>(); JsonObject obj = doc.as<JsonObject>();
@ -2009,17 +1805,8 @@ void Web::begin() {
DynamicJsonDocument doc(256); DynamicJsonDocument doc(256);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { webServer.handleDeserializationError(server, err);
case DeserializationError::InvalidInput: return;
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
} }
else { else {
JsonObject obj = doc.as<JsonObject>(); JsonObject obj = doc.as<JsonObject>();
@ -2053,17 +1840,8 @@ void Web::begin() {
DynamicJsonDocument doc(256); DynamicJsonDocument doc(256);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { webServer.handleDeserializationError(server, err);
case DeserializationError::InvalidInput: return;
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
} }
else { else {
JsonObject obj = doc.as<JsonObject>(); JsonObject obj = doc.as<JsonObject>();
@ -2239,20 +2017,7 @@ void Web::begin() {
*/ */
server.send(statusCode, "application/json", g_content); server.send(statusCode, "application/json", g_content);
}); });
server.on("/reboot", []() { server.on("/reboot", []() { webServer.handleReboot(server);});
webServer.sendCORSHeaders(server);
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
HTTPMethod method = server.method();
if (method == HTTP_POST || method == HTTP_PUT) {
Serial.println("Rebooting ESP...");
rebootDelay.reboot = true;
rebootDelay.rebootTime = millis() + 500;
server.send(200, "application/json", "{\"status\":\"OK\",\"desc\":\"Successfully started reboot\"}");
}
else {
server.send(201, _encoding_json, "{\"status\":\"ERROR\",\"desc\":\"Invalid HTTP Method: \"}");
}
});
server.on("/saveSecurity", []() { server.on("/saveSecurity", []() {
webServer.sendCORSHeaders(server); webServer.sendCORSHeaders(server);
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; } if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
@ -2347,17 +2112,7 @@ void Web::begin() {
StaticJsonDocument<128> doc; StaticJsonDocument<128> doc;
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
switch (err.code()) { webServer.handleDeserializationError(server, err);
case DeserializationError::InvalidInput:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
return; return;
} }
else { else {
@ -2389,10 +2144,8 @@ void Web::begin() {
Serial.println(server.arg("plain")); Serial.println(server.arg("plain"));
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
Serial.print("Error parsing JSON "); webServer.handleDeserializationError(server, err);
Serial.println(err.c_str()); return;
String msg = err.c_str();
server.send(400, _encoding_html, "Error parsing JSON body<br>" + msg);
} }
else { else {
JsonObject obj = doc.as<JsonObject>(); JsonObject obj = doc.as<JsonObject>();
@ -2471,10 +2224,8 @@ void Web::begin() {
DynamicJsonDocument doc(1024); DynamicJsonDocument doc(1024);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
Serial.print("Error parsing JSON "); webServer.handleDeserializationError(server, err);
Serial.println(err.c_str()); return;
String msg = err.c_str();
server.send(400, "text/html", "Error parsing JSON body<br>" + msg);
} }
else { else {
JsonObject obj = doc.as<JsonObject>(); JsonObject obj = doc.as<JsonObject>();
@ -2496,10 +2247,8 @@ void Web::begin() {
DynamicJsonDocument doc(512); DynamicJsonDocument doc(512);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
Serial.print("Error parsing JSON "); webServer.handleDeserializationError(server, err);
Serial.println(err.c_str()); return;
String msg = err.c_str();
server.send(400, "text/html", "Error parsing JSON body<br>" + msg);
} }
else { else {
JsonObject obj = doc.as<JsonObject>(); JsonObject obj = doc.as<JsonObject>();
@ -2567,10 +2316,8 @@ void Web::begin() {
DynamicJsonDocument doc(1024); DynamicJsonDocument doc(1024);
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
Serial.print("Error parsing JSON "); webServer.handleDeserializationError(server, err);
Serial.println(err.c_str()); return;
String msg = err.c_str();
server.send(400, F("text/html"), "Error parsing JSON body<br>" + msg);
} }
else { else {
JsonObject obj = doc.as<JsonObject>(); JsonObject obj = doc.as<JsonObject>();
@ -2610,10 +2357,8 @@ void Web::begin() {
Serial.println(server.arg("plain")); Serial.println(server.arg("plain"));
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
Serial.print("Error parsing JSON "); webServer.handleDeserializationError(server, err);
Serial.println(err.c_str()); return;
String msg = err.c_str();
server.send(400, _encoding_html, "Error parsing JSON body<br>" + msg);
} }
else { else {
JsonArray arr = doc.as<JsonArray>(); JsonArray arr = doc.as<JsonArray>();
@ -2644,10 +2389,8 @@ void Web::begin() {
Serial.println(server.arg("plain")); Serial.println(server.arg("plain"));
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
Serial.print("Error parsing JSON "); webServer.handleDeserializationError(server, err);
Serial.println(err.c_str()); return;
String msg = err.c_str();
server.send(400, _encoding_html, "Error parsing JSON body<br>" + msg);
} }
else { else {
JsonArray arr = doc.as<JsonArray>(); JsonArray arr = doc.as<JsonArray>();
@ -2677,10 +2420,8 @@ void Web::begin() {
Serial.println(server.arg("plain")); Serial.println(server.arg("plain"));
DeserializationError err = deserializeJson(doc, server.arg("plain")); DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) { if (err) {
Serial.print("Error parsing JSON "); webServer.handleDeserializationError(server, err);
Serial.println(err.c_str()); return;
String msg = err.c_str();
server.send(400, _encoding_html, "Error parsing JSON body<br>" + msg);
} }
else { else {
JsonArray arr = doc.as<JsonArray>(); JsonArray arr = doc.as<JsonArray>();

2
Web.h
View file

@ -28,6 +28,8 @@ class Web {
void handleSetSensor(WebServer &server); void handleSetSensor(WebServer &server);
void handleDownloadFirmware(WebServer &server); void handleDownloadFirmware(WebServer &server);
void handleBackup(WebServer &server, bool attach = false); void handleBackup(WebServer &server, bool attach = false);
void handleReboot(WebServer &server);
void handleDeserializationError(WebServer &server, DeserializationError &err);
void begin(); void begin();
void loop(); void loop();
void end(); void end();

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.3.1" type="text/css" /> <link rel="stylesheet" href="main.css?v=2.3.1r" type="text/css" />
<link rel="stylesheet" href="widgets.css?v=2.3.1" type="text/css" /> <link rel="stylesheet" href="widgets.css?v=2.3.1r" type="text/css" />
<link rel="stylesheet" href="icons.css?v=2.3.1" type="text/css" /> <link rel="stylesheet" href="icons.css?v=2.3.1r" 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.3.1"></script> <script type="text/javascript" src="index.js?v=2.3.1r"></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

@ -10,8 +10,8 @@ body {
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
font-size: 14px; font-size: 14px;
background-color: #eeeeee; background-color: #eeeeee;
margin-top: 77px;
box-sizing: border-box; box-sizing: border-box;
margin-top: 77px;
} }
@ -844,3 +844,12 @@ div.frame-pulses {
text-overflow:ellipsis; text-overflow:ellipsis;
display:none; display:none;
} }
@media only screen and (max-device-width: 480px) {
body {
margin-top: 0px;
}
.subtab-content {
padding-left:14px;
padding-right:14px;
}
}

View file

@ -303,3 +303,13 @@
.room-selector-list .room-row:hover { .room-selector-list .room-row:hover {
color: var(--shade-color, gray); color: var(--shade-color, gray);
} }
@media only screen and (max-device-width: 480px) {
body {
margin-top: 0px;
}
.container {
padding-left: 10px;
padding-right: 10px;
}
}