diff --git a/GitOTA.cpp b/GitOTA.cpp index 96ac3cf..d812e00 100644 --- a/GitOTA.cpp +++ b/GitOTA.cpp @@ -198,16 +198,19 @@ void GitUpdater::loop() { } void GitUpdater::checkForUpdate() { if(this->status != 0) return; // If we are already checking. + Serial.println("Check github for updates..."); this->status = GIT_STATUS_CHECK; - GitRepo repo; - this->lastCheck = millis(); - this->updateAvailable = false; - this->error = repo.getReleases(2); - if(this->error == 0) { // Get 2 releases so we can filter our pre-releases - this->setCurrentRelease(repo); - } - else { - this->emitUpdateCheck(); + if(this->checkInternet() == 0) { + GitRepo repo; + this->lastCheck = millis(); + this->updateAvailable = false; + this->error = repo.getReleases(2); + if(this->error == 0) { // Get 2 releases so we can filter our pre-releases + this->setCurrentRelease(repo); + } + else { + this->emitUpdateCheck(); + } } this->status = GIT_STATUS_READY; } @@ -238,14 +241,39 @@ void GitUpdater::toJSON(JsonObject &obj) { this->latest.toJSON(latest); } void GitUpdater::emitUpdateCheck(uint8_t num) { - ClientSocketEvent evt("fwStatus"); - DynamicJsonDocument doc(512); - JsonObject obj = doc.to(); - this->toJSON(obj); - if(num == 255) - sockEmit.sendToClients("fwStatus", doc); - else - sockEmit.sendToClient(num, "fwStatus", doc); + ClientSocketEvent evt("fwStatus"); + DynamicJsonDocument doc(512); + JsonObject obj = doc.to(); + this->toJSON(obj); + if(num == 255) + sockEmit.sendToClients("fwStatus", doc); + else + sockEmit.sendToClient(num, "fwStatus", doc); +} +int GitUpdater::checkInternet() { + int err = 500; + uint32_t t = millis(); + WiFiClientSecure *client = new WiFiClientSecure; + if(client) { + client->setInsecure(); + HTTPClient https; + if(https.begin(*client, "https://github.com/rstrouse/ESPSomfy-RTS")) { + https.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS); + https.setTimeout(5000); + int httpCode = https.sendRequest("HEAD"); + if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY || httpCode == HTTP_CODE_FOUND) { + err = 0; + Serial.printf("Check Internet Success: %dms\n", millis() - t); + } + else { + err = httpCode; + Serial.printf("Check Internet Error: %d: %dms\n", err, millis() - t); + } + https.end(); + } + delete client; + } + return err; } void GitUpdater::emitDownloadProgress(size_t total, size_t loaded, const char *evt) { this->emitDownloadProgress(255, total, loaded, evt); } void GitUpdater::emitDownloadProgress(uint8_t num, size_t total, size_t loaded, const char *evt) { diff --git a/GitOTA.h b/GitOTA.h index 973397f..e5e20b8 100644 --- a/GitOTA.h +++ b/GitOTA.h @@ -35,7 +35,7 @@ class GitRepo { class GitUpdater { public: uint8_t status = 0; - unsigned long lastCheck = 0; + uint32_t lastCheck = 0; bool updateAvailable = false; appver_t latest; bool cancelled = false; @@ -51,6 +51,7 @@ class GitUpdater { void setCurrentRelease(GitRepo &repo); void loop(); void toJSON(JsonObject &obj); + int checkInternet(); void emitUpdateCheck(uint8_t num=255); void emitDownloadProgress(size_t total, size_t loaded, const char *evt = "updateProgress"); void emitDownloadProgress(uint8_t num, size_t total, size_t loaded, const char *evt = "updateProgress"); diff --git a/Somfy.cpp b/Somfy.cpp index 21d9136..e8bb6ab 100644 --- a/Somfy.cpp +++ b/Somfy.cpp @@ -809,6 +809,8 @@ void SomfyShade::setGPIOs() { int8_t dir = this->direction; if(dir == 0 && this->tiltType == tilt_types::integrated) dir = this->tiltDirection; + else if(this->tiltType == tilt_types::tiltonly) + dir = this->tiltDirection; if(this->shadeType == shade_types::drycontact) { digitalWrite(this->gpioDown, this->currentPos == 100 ? HIGH : LOW); this->gpioDir = this->currentPos == 100 ? 1 : -1; @@ -1268,40 +1270,25 @@ void SomfyShade::load() { } void SomfyShade::publishState() { if(mqtt.connected()) { - char topic[32]; - snprintf(topic, sizeof(topic), "shades/%u/position", this->shadeId); - mqtt.publish(topic, this->transformPosition(this->currentPos)); - snprintf(topic, sizeof(topic), "shades/%u/direction", this->shadeId); - mqtt.publish(topic, this->direction); - snprintf(topic, sizeof(topic), "shades/%u/target", this->shadeId); - mqtt.publish(topic, this->transformPosition(this->target)); - snprintf(topic, sizeof(topic), "shades/%u/lastRollingCode", this->shadeId); - mqtt.publish(topic, this->lastRollingCode); - snprintf(topic, sizeof(topic), "shades/%u/mypos", this->shadeId); - mqtt.publish(topic, this->transformPosition(this->myPos)); - snprintf(topic, sizeof(topic), "shades/%u/myTiltPos", this->shadeId); - mqtt.publish(topic, this->transformPosition(this->myTiltPos)); + this->publish("position", this->transformPosition(this->currentPos)); + this->publish("direction", this->direction); + this->publish("target", this->transformPosition(this->target)); + this->publish("lastRollingCode", this->lastRollingCode); + this->publish("mypos", this->transformPosition(this->myPos)); + this->publish("myTiltPos", this->transformPosition(this->myTiltPos)); if(this->tiltType != tilt_types::none) { - snprintf(topic, sizeof(topic), "shades/%u/tiltDirection", this->shadeId); - mqtt.publish(topic, this->tiltDirection); - snprintf(topic, sizeof(topic), "shades/%u/tiltPosition", this->shadeId); - mqtt.publish(topic, this->transformPosition(this->currentTiltPos)); - snprintf(topic, sizeof(topic), "shades/%u/tiltTarget", this->shadeId); - mqtt.publish(topic, this->transformPosition(this->tiltTarget)); + this->publish("tiltDirection", this->tiltDirection); + this->publish("tiltPosition", this->transformPosition(this->currentTiltPos)); + this->publish("tiltTarget", this->transformPosition(this->tiltTarget)); } const uint8_t sunFlag = !!(this->flags & static_cast(somfy_flags_t::SunFlag)); const uint8_t isSunny = !!(this->flags & static_cast(somfy_flags_t::Sunny)); const uint8_t isWindy = !!(this->flags & static_cast(somfy_flags_t::Windy)); - snprintf(topic, sizeof(topic), "shades/%u/sunSensor", this->shadeId); - mqtt.publish(topic, this->hasSunSensor()); if(this->hasSunSensor()) { - snprintf(topic, sizeof(topic), "shades/%u/sunFlag", this->shadeId); - mqtt.publish(topic, sunFlag); - snprintf(topic, sizeof(topic), "shades/%u/sunny", this->shadeId); - mqtt.publish(topic, isSunny); - snprintf(topic, sizeof(topic), "shades/%u/windy", this->shadeId); + this->publish("sunFlag", sunFlag); + this->publish("sunny", isSunny); } - mqtt.publish(topic, isWindy); + this->publish("windy", isWindy); } } void SomfyShade::publishDisco() { @@ -1426,65 +1413,43 @@ void SomfyShade::publishDisco() { } void SomfyShade::publish() { if(mqtt.connected()) { - char topic[32]; - snprintf(topic, sizeof(topic), "shades/%u/shadeId", this->shadeId); - mqtt.publish(topic, this->shadeId); - snprintf(topic, sizeof(topic), "shades/%u/name", this->shadeId); - mqtt.publish(topic, this->name); - snprintf(topic, sizeof(topic), "shades/%u/remoteAddress", this->shadeId); - mqtt.publish(topic, this->getRemoteAddress()); - snprintf(topic, sizeof(topic), "shades/%u/shadeType", this->shadeId); - mqtt.publish(topic, static_cast(this->shadeType)); - snprintf(topic, sizeof(topic), "shades/%u/tiltType", this->shadeId); - mqtt.publish(topic, static_cast(this->tiltType)); - //snprintf(topic, sizeof(topic), "shades/%u/flags", this->shadeId); - mqtt.publish(topic, this->flags); - snprintf(topic, sizeof(topic), "shades/%u/flipCommands", this->shadeId); - mqtt.publish(topic, this->flipCommands); - snprintf(topic, sizeof(topic), "shades/%u/flipPosition", this->shadeId); - mqtt.publish(topic, this->flipPosition); + this->publish("shadeId", this->shadeId); + this->publish("name", this->name); + this->publish("remoteAddress", this->getRemoteAddress()); + this->publish("shadeType", static_cast(this->shadeType)); + this->publish("tiltType", static_cast(this->tiltType)); + this->publish("flags", this->flags); + this->publish("flipCommands", this->flipCommands); + this->publish("flipPosition", this->flipPosition); this->publishState(); - mqtt.loop(); this->publishDisco(); + sockEmit.loop(); // Keep our socket alive. } } void SomfyGroup::publishState() { if(mqtt.connected()) { - char topic[32]; - snprintf(topic, sizeof(topic), "groups/%u/direction", this->groupId); - mqtt.publish(topic, this->direction); - snprintf(topic, sizeof(topic), "groups/%u/lastRollingCode", this->groupId); - mqtt.publish(topic, this->lastRollingCode); + this->publish("direction", this->direction); + this->publish("lastRollingCode", this->lastRollingCode); const uint8_t sunFlag = !!(this->flags & static_cast(somfy_flags_t::SunFlag)); const uint8_t isSunny = !!(this->flags & static_cast(somfy_flags_t::Sunny)); const uint8_t isWindy = !!(this->flags & static_cast(somfy_flags_t::Windy)); - snprintf(topic, sizeof(topic), "groups/%u/sunFlag", this->groupId); - mqtt.publish(topic, sunFlag); - snprintf(topic, sizeof(topic), "groups/%u/sunny", this->groupId); - mqtt.publish(topic, isSunny); - snprintf(topic, sizeof(topic), "groups/%u/windy", this->groupId); - mqtt.publish(topic, isWindy); + this->publish("sunFlag", sunFlag); + this->publish("sunny", isSunny); + this->publish("windy", isWindy); } } void SomfyGroup::publish() { if(mqtt.connected()) { - char topic[32]; - snprintf(topic, sizeof(topic), "groups/%u/groupId", this->groupId); - mqtt.publish(topic, this->groupId); - snprintf(topic, sizeof(topic), "groups/%u/name", this->groupId); - mqtt.publish(topic, this->name); - snprintf(topic, sizeof(topic), "groups/%u/remoteAddress", this->groupId); - mqtt.publish(topic, this->getRemoteAddress()); - snprintf(topic, sizeof(topic), "groups/%u/groupType", this->groupId); - mqtt.publish(topic, static_cast(this->groupType)); - snprintf(topic, sizeof(topic), "groups/%u/flags", this->groupId); - mqtt.publish(topic, this->flags); - snprintf(topic, sizeof(topic), "groups/%u/sunSensor", this->groupId); - mqtt.publish(topic, this->hasSunSensor()); + this->publish("groupId", this->groupId); + this->publish("name", this->name); + this->publish("remoteAddress", this->getRemoteAddress()); + this->publish("groupType", static_cast(this->groupType)); + this->publish("flags", this->flags); + this->publish("sunSensor", this->hasSunSensor()); this->publishState(); } } -char mqttTopicBuffer[32]; +char mqttTopicBuffer[55]; bool SomfyShade::publish(const char *topic, int8_t val, bool retain) { if(mqtt.connected()) { snprintf(mqttTopicBuffer, sizeof(mqttTopicBuffer), "shades/%u/%s", this->shadeId, topic); @@ -1566,9 +1531,6 @@ bool SomfyGroup::publish(const char *topic, bool val, bool retain) { } return false; } - - - // State Setters float SomfyShade::p_currentPos(float pos) { float old = this->currentPos; @@ -1582,7 +1544,6 @@ float SomfyShade::p_currentTiltPos(float pos) { if(floor(old) != floor(pos)) this->publish("tiltPosition", this->transformPosition(static_cast(floor(this->currentTiltPos)))); return old; } - uint16_t SomfyShade::p_lastRollingCode(uint16_t code) { uint16_t old = SomfyRemote::p_lastRollingCode(code); if(old != code) this->publish("lastRollingCode", code); diff --git a/SomfyController.ino.esp32.bin b/SomfyController.ino.esp32.bin index 1aa00e3..655766b 100644 Binary files a/SomfyController.ino.esp32.bin and b/SomfyController.ino.esp32.bin differ diff --git a/Web.cpp b/Web.cpp index 795b8a8..70a32f6 100644 --- a/Web.cpp +++ b/Web.cpp @@ -202,6 +202,8 @@ void Web::handleLogin(WebServer &server) { } void Web::handleStreamFile(WebServer &server, const char *filename, const char *encoding) { webServer.sendCORSHeaders(server); + if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; } + // Load the index html page from the data directory. Serial.print("Loading file "); Serial.println(filename); @@ -209,7 +211,7 @@ void Web::handleStreamFile(WebServer &server, const char *filename, const char * if (!file) { Serial.print("Error opening"); Serial.println(filename); - server.send(500, _encoding_text, "shades.cfg"); + server.send(500, _encoding_text, "Error opening file"); } server.streamFile(file, encoding); file.close(); @@ -1477,7 +1479,7 @@ void Web::begin() { else { shade->paired = paired; shade->save(); - DynamicJsonDocument doc(512); + DynamicJsonDocument doc(1024); JsonObject obj = doc.to(); shade->toJSON(obj); serializeJson(doc, g_content); @@ -1526,7 +1528,7 @@ void Web::begin() { shade->sendCommand(somfy_commands::Prog, 1); shade->paired = false; shade->save(); - DynamicJsonDocument doc(512); + DynamicJsonDocument doc(1024); JsonObject obj = doc.to(); shade->toJSON(obj); serializeJson(doc, g_content);