From 76ef403bbfb2caf740c786f869cccd7ce61d929a Mon Sep 17 00:00:00 2001 From: 0xFEEDC0DE64 Date: Fri, 6 Aug 2021 15:50:44 +0200 Subject: [PATCH] added espasyncota lib --- .gitmodules | 3 + components/cpputils | 2 +- components/espasyncota | 1 + components/espchrono | 2 +- components/espcpputils | 2 +- components/espwifistack | 2 +- components/fmt | 2 +- main/CMakeLists.txt | 4 +- main/feature_bmp.cpp | 39 ++++++++---- main/feature_dht.cpp | 26 +++++--- main/feature_switch.cpp | 9 ++- main/feature_tsl.cpp | 33 +++++++--- main/main.cpp | 6 ++ main/myconfig.cpp | 9 ++- main/mymqtt.cpp | 44 ++++++++----- main/myota.cpp | 49 +++++++++++++++ main/myota.h | 19 ++++++ main/mywifi.cpp | 49 +++++++-------- main/webserver.cpp | 134 ++++++++++++++++++++++++++++------------ 19 files changed, 311 insertions(+), 124 deletions(-) create mode 160000 components/espasyncota create mode 100644 main/myota.cpp create mode 100644 main/myota.h diff --git a/.gitmodules b/.gitmodules index f22c7d2..55daf02 100644 --- a/.gitmodules +++ b/.gitmodules @@ -40,3 +40,6 @@ [submodule "components/esp-nimble-cpp"] path = components/esp-nimble-cpp url = git@github.com:0xFEEDC0DE64/esp-nimble-cpp.git +[submodule "components/espasyncota"] + path = components/espasyncota + url = git@github.com:0xFEEDC0DE64/espasyncota.git diff --git a/components/cpputils b/components/cpputils index 89bff1a..b12426f 160000 --- a/components/cpputils +++ b/components/cpputils @@ -1 +1 @@ -Subproject commit 89bff1a8dcac2f951ac3f2c3d7415691ce16ca12 +Subproject commit b12426ffeef41bf107b0388c56031d0d1ce4bcb8 diff --git a/components/espasyncota b/components/espasyncota new file mode 160000 index 0000000..bbc1f64 --- /dev/null +++ b/components/espasyncota @@ -0,0 +1 @@ +Subproject commit bbc1f643e2f4af41edc642f73c420edda8ea16cc diff --git a/components/espchrono b/components/espchrono index 7f8a185..4d2e930 160000 --- a/components/espchrono +++ b/components/espchrono @@ -1 +1 @@ -Subproject commit 7f8a185678cccf0307910bffc6422a5564dccb0c +Subproject commit 4d2e9305dc8c434a7a5ddf5c534a3a896be04bee diff --git a/components/espcpputils b/components/espcpputils index 3a350f1..78fa43e 160000 --- a/components/espcpputils +++ b/components/espcpputils @@ -1 +1 @@ -Subproject commit 3a350f11897f8f82bfc906efb7fbebd14e7da352 +Subproject commit 78fa43edcfc24dfd2faceb16396332a9f1b3c203 diff --git a/components/espwifistack b/components/espwifistack index 01189ca..717d877 160000 --- a/components/espwifistack +++ b/components/espwifistack @@ -1 +1 @@ -Subproject commit 01189ca83367d67acb1072e3eceb308759061bd8 +Subproject commit 717d877a44056c51e4a3ab777c4279c3d7a2e220 diff --git a/components/fmt b/components/fmt index 4b11c94..d3c349f 160000 --- a/components/fmt +++ b/components/fmt @@ -1 +1 @@ -Subproject commit 4b11c94036d4c5012dc4cb3854f47052f6f49812 +Subproject commit d3c349f69de79e0014e2e4fe1c4a1cd7c74983da diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 61c51fb..fd791c7 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -12,6 +12,7 @@ set(headers myconfig.h mymdns.h mymqtt.h + myota.h mywifi.h nvswrappers.h webserver.h @@ -29,13 +30,14 @@ set(sources myconfig.cpp mymdns.cpp mymqtt.cpp + myota.cpp mywifi.cpp webserver.cpp ) set(dependencies freertos nvs_flash esp_http_server esp_https_ota mdns app_update esp_system mqtt - arduino-esp32 cpputils date esp-nimble-cpp espchrono espcpputils espwifistack expected fmt + arduino-esp32 cpputils date esp-nimble-cpp espasyncota espchrono espcpputils espwifistack expected fmt Adafruit_BMP085_Unified Adafruit_TSL2561 DHT-sensor-library ) diff --git a/main/feature_bmp.cpp b/main/feature_bmp.cpp index 547d8ff..bd474ed 100644 --- a/main/feature_bmp.cpp +++ b/main/feature_bmp.cpp @@ -39,7 +39,8 @@ void init_bmp() bmpInitialized = bmp->begin(); ESP_LOGI(TAG, "finished with %s", bmpInitialized ? "true" : "false"); - if (bmpInitialized) { + if (bmpInitialized) + { sensor_t sensor = bmp->getSensor(); ESP_LOGI(TAG, "------------------------------------"); ESP_LOGI(TAG, "Sensor: %s", sensor.name); @@ -58,14 +59,17 @@ void update_bmp() if (!config::enable_i2c.value() || !config::enable_bmp.value()) return; - if (bmpInitialized) { + if (bmpInitialized) + { if (espchrono::ago(last_bmp085_readout) < 5s) return; last_bmp085_readout = espchrono::millis_clock::now(); - if (std::optional values = bmp->getTemperatureAndPressure()) { - if (values->temperature && values->pressure) { + if (std::optional values = bmp->getTemperatureAndPressure()) + { + if (values->temperature && values->pressure) + { BmpValue bmpValue { .timestamp = espchrono::millis_clock::now(), .pressure = values->pressure, @@ -79,35 +83,46 @@ void update_bmp() bmpValue.altitude = bmp->pressureToAltitude(seaLevelPressure, bmpValue.pressure); ESP_LOGI(TAG, "read bmp Altitude: %.1f m", bmpValue.altitude); - if (mqttConnected) { + if (mqttConnected) + { if (!lastBmpValue) mqttVerbosePub(config::topic_bmp085_availability.value(), "online", 0, 1); - if (!lastBmpValue || espchrono::ago(last_bmp085_pressure_pub) >= config::valueUpdateInterval.value()) { + if (!lastBmpValue || espchrono::ago(last_bmp085_pressure_pub) >= config::valueUpdateInterval.value()) + { if (mqttVerbosePub(config::topic_bmp085_pressure.value(), fmt::format("{:.1f}", bmpValue.pressure), 0, 1) >= 0) last_bmp085_pressure_pub = espchrono::millis_clock::now(); } - if (!lastBmpValue || espchrono::ago(last_bmp085_temperature_pub) >= config::valueUpdateInterval.value()) { + if (!lastBmpValue || espchrono::ago(last_bmp085_temperature_pub) >= config::valueUpdateInterval.value()) + { if (mqttVerbosePub(config::topic_bmp085_temperature.value(), fmt::format("{:.1f}", bmpValue.temperature), 0, 1) >= 0) last_bmp085_temperature_pub = espchrono::millis_clock::now(); } - if (!lastBmpValue || espchrono::ago(last_bmp085_altitude_pub) >= config::valueUpdateInterval.value()) { + if (!lastBmpValue || espchrono::ago(last_bmp085_altitude_pub) >= config::valueUpdateInterval.value()) + { if (mqttVerbosePub(config::topic_bmp085_altitude.value(), fmt::format("{:.1f}", bmpValue.altitude), 0, 1) >= 0) last_bmp085_altitude_pub = espchrono::millis_clock::now(); } } lastBmpValue = bmpValue; - } else { + } + else + { ESP_LOGW(TAG, "bmp sensor error"); goto bmpOffline; } - } else { + } + else + { ESP_LOGW(TAG, "bmp failed"); goto bmpOffline; } - } else { + } + else + { bmpOffline: - if (lastBmpValue && espchrono::ago(lastBmpValue->timestamp) >= config::availableTimeoutTime.value()) { + if (lastBmpValue && espchrono::ago(lastBmpValue->timestamp) >= config::availableTimeoutTime.value()) + { ESP_LOGW(TAG, "bmp timeouted"); if (mqttConnected) mqttVerbosePub(config::topic_bmp085_availability.value(), "offline", 0, 1); diff --git a/main/feature_dht.cpp b/main/feature_dht.cpp index 93eb672..dd8b18f 100644 --- a/main/feature_dht.cpp +++ b/main/feature_dht.cpp @@ -44,13 +44,15 @@ void update_dht() if (!config::enable_dht.value()) return; - if (dhtInitialized) { + if (dhtInitialized) + { if (espchrono::ago(last_dht11_readout) < 5s) return; last_dht11_readout = espchrono::millis_clock::now(); - if (const auto data = dht->read()) { + if (const auto data = dht->read()) + { DhtValue dhtValue { .timestamp = espchrono::millis_clock::now(), .temperature = dht->readTemperature(*data), @@ -60,27 +62,35 @@ void update_dht() ESP_LOGI(TAG, "read dht temperature: %.1f C", dhtValue.temperature); ESP_LOGI(TAG, "read dht humidity: %.1f %%", dhtValue.humidity); - if (mqttConnected) { + if (mqttConnected) + { if (!lastDhtValue) mqttVerbosePub(config::topic_dht11_availability.value(), "online", 0, 1); - if (!lastDhtValue || espchrono::ago(last_dht11_temperature_pub) >= config::valueUpdateInterval.value()) { + if (!lastDhtValue || espchrono::ago(last_dht11_temperature_pub) >= config::valueUpdateInterval.value()) + { if (mqttVerbosePub(config::topic_dht11_temperature.value(), fmt::format("{:.1f}", dhtValue.temperature), 0, 1) >= 0) last_dht11_temperature_pub = espchrono::millis_clock::now(); } - if (!lastDhtValue || espchrono::ago(last_dht11_humidity_pub) >= config::valueUpdateInterval.value()) { + if (!lastDhtValue || espchrono::ago(last_dht11_humidity_pub) >= config::valueUpdateInterval.value()) + { if (mqttVerbosePub(config::topic_dht11_humidity.value(), fmt::format("{:.1f}", dhtValue.humidity), 0, 1) >= 0) last_dht11_humidity_pub = espchrono::millis_clock::now(); } } lastDhtValue = dhtValue; - } else { + } + else + { ESP_LOGW(TAG, "dht failed"); goto dhtOffline; } - } else { + } + else + { dhtOffline: - if (lastDhtValue && espchrono::ago(lastDhtValue->timestamp) >= config::availableTimeoutTime.value()) { + if (lastDhtValue && espchrono::ago(lastDhtValue->timestamp) >= config::availableTimeoutTime.value()) + { ESP_LOGW(TAG, "dht timeouted"); if (mqttConnected) mqttVerbosePub(config::topic_dht11_availability.value(), "offline", 0, 1); diff --git a/main/feature_switch.cpp b/main/feature_switch.cpp index 5cfec66..ac9d7af 100644 --- a/main/feature_switch.cpp +++ b/main/feature_switch.cpp @@ -41,9 +41,11 @@ void update_switch() const auto newState = readSwitch(); if (newState == switchState.load()) switchDebounce = 0; - else { + else + { switchDebounce++; - if (switchDebounce >= 10) { + if (switchDebounce >= 10) + { switchDebounce = 0; switchState = newState; @@ -51,7 +53,8 @@ void update_switch() if (mqttConnected) mqttVerbosePub(config::topic_switch_status.value(), switchState ? "ON" : "OFF", 0, 1); - if (config::enable_lamp.value()) { + if (config::enable_lamp.value()) + { lampState = !lampState; writeLamp(lampState); diff --git a/main/feature_tsl.cpp b/main/feature_tsl.cpp index 57ba9c1..c300bd2 100644 --- a/main/feature_tsl.cpp +++ b/main/feature_tsl.cpp @@ -37,7 +37,8 @@ void init_tsl() tslInitialized = tsl->begin(true); ESP_LOGI(TAG, "finished with %s", tslInitialized ? "true" : "false"); - if (tslInitialized) { + if (tslInitialized) + { sensor_t sensor = tsl->getSensor(); ESP_LOGI(TAG, "------------------------------------"); ESP_LOGI(TAG, "Sensor: %s", sensor.name); @@ -72,44 +73,56 @@ void update_tsl() if (!config::enable_i2c.value() || !config::enable_tsl.value()) return; - if (tslInitialized) { + if (tslInitialized) + { if (espchrono::ago(last_tsl2561_readout) < 5s) return; last_tsl2561_readout = espchrono::millis_clock::now(); - if (std::optional event = tsl->getEvent()) { + if (std::optional event = tsl->getEvent()) + { /* Display the results (light is measured in lux) */ - if (event->light) { + if (event->light) + { TslValue tslValue { .timestamp = espchrono::millis_clock::now(), .lux = event->light }; ESP_LOGI(TAG, "read tsl: %.1f lux", tslValue.lux); - if (mqttConnected) { + if (mqttConnected) + { if (!lastTslValue) mqttVerbosePub(config::topic_tsl2561_availability.value(), "online", 0, 1); - if (!lastTslValue || espchrono::ago(last_tsl2561_lux_pub) >= config::valueUpdateInterval.value()) { + if (!lastTslValue || espchrono::ago(last_tsl2561_lux_pub) >= config::valueUpdateInterval.value()) + { if (mqttVerbosePub(config::topic_tsl2561_lux.value(), fmt::format("{:.1f}", tslValue.lux), 0, 1) >= 0) last_tsl2561_lux_pub = espchrono::millis_clock::now(); } } lastTslValue = tslValue; - } else { + } + else + { /* If event.light = 0 lux the sensor is probably saturated * and no reliable data could be generated! */ ESP_LOGW(TAG, "tsl sensor overload %f", event->light); goto tslOffline; } - } else { + } + else + { ESP_LOGW(TAG, "tsl failed"); goto tslOffline; } - } else { + } + else + { tslOffline: - if (lastTslValue && espchrono::ago(lastTslValue->timestamp) >= config::availableTimeoutTime.value()) { + if (lastTslValue && espchrono::ago(lastTslValue->timestamp) >= config::availableTimeoutTime.value()) + { ESP_LOGW(TAG, "tsl timeouted"); if (mqttConnected) mqttVerbosePub(config::topic_tsl2561_availability.value(), "offline", 0, 1); diff --git a/main/main.cpp b/main/main.cpp index 4318953..bceb6df 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -23,6 +23,7 @@ #include "webserver.h" #include "mymdns.h" #include "mymqtt.h" +#include "myota.h" #include "feature_lamp.h" #include "feature_switch.h" #include "feature_dht.h" @@ -99,6 +100,8 @@ extern "C" void app_main() init_mqtt(); + init_ota(); + init_dht(); init_tsl(); @@ -130,6 +133,9 @@ extern "C" void app_main() update_mqtt(); vPortYield(); + update_ota(); + vPortYield(); + update_dht(); vPortYield(); diff --git a/main/myconfig.cpp b/main/myconfig.cpp index 0692208..ff9c5c4 100644 --- a/main/myconfig.cpp +++ b/main/myconfig.cpp @@ -102,15 +102,18 @@ namespace { template void loadParam(ConfigWrapper &config) { - if (const auto len = std::strlen(config.nvsKey()); len > 15) { + if (const auto len = std::strlen(config.nvsKey()); len > 15) + { ESP_LOGE(TAG, "%s too long %zd (%zd)", config.nvsKey(), len, len-15); assert(false); } - if (const auto value = config.readFromFlash()) { + if (const auto value = config.readFromFlash()) + { if (*value) config.setValue(**value); - } else + } + else ESP_LOGE(TAG, "error loading config %s: %.*s", config.name(), value.error().size(), value.error().data()); } } // namespace diff --git a/main/mymqtt.cpp b/main/mymqtt.cpp index 95cf6fe..f5340fa 100644 --- a/main/mymqtt.cpp +++ b/main/mymqtt.cpp @@ -70,7 +70,8 @@ int mqttVerbosePub(std::string_view topic, std::string_view value, int qos, int { ESP_LOGD(TAG, "topic=\"%.*s\" value=\"%.*s\"", topic.size(), topic.data(), value.size(), value.data()); - if (!mqttClient) { + if (!mqttClient) + { ESP_LOGE(TAG, "mqttClient not constructed!"); return -1; } @@ -90,7 +91,8 @@ void mqttEventHandler(void *event_handler_arg, esp_event_base_t event_base, int3 const esp_mqtt_event_t *data = reinterpret_cast(event_data); - switch (esp_mqtt_event_id_t(event_id)) { + switch (esp_mqtt_event_id_t(event_id)) + { case MQTT_EVENT_ERROR: ESP_LOGE(TAG, "%s event_id=%s", event_base, "MQTT_EVENT_ERROR"); @@ -110,20 +112,24 @@ void mqttEventHandler(void *event_handler_arg, esp_event_base_t event_base, int3 mqttConnected = true; - if (config::enable_lamp.value()) { + if (config::enable_lamp.value()) + { mqttVerbosePub(config::topic_lamp_availability.value(), "online", 0, 1); mqttVerbosePub(config::topic_lamp_status.value(), lampState.load() ? "ON" : "OFF", 0, 1); mqttClient.subscribe(config::topic_lamp_set.value(), 0); } - if (config::enable_switch.value()) { + if (config::enable_switch.value()) + { mqttVerbosePub(config::topic_switch_availability.value(), "online", 0, 1); mqttVerbosePub(config::topic_switch_status.value(), switchState.load() ? "ON" : "OFF", 0, 1); } - if (config::enable_dht.value()) { + if (config::enable_dht.value()) + { mqttVerbosePub(config::topic_dht11_availability.value(), lastDhtValue ? "online" : "offline", 0, 1); - if (lastDhtValue) { + if (lastDhtValue) + { if (mqttVerbosePub(config::topic_dht11_temperature.value(), fmt::format("{:.1f}", lastDhtValue->temperature), 0, 1) >= 0) last_dht11_temperature_pub = espchrono::millis_clock::now(); if (mqttVerbosePub(config::topic_dht11_humidity.value(), fmt::format("{:.1f}", lastDhtValue->humidity), 0, 1) >= 0) @@ -131,17 +137,21 @@ void mqttEventHandler(void *event_handler_arg, esp_event_base_t event_base, int3 } } - if (config::enable_i2c.value() && config::enable_tsl.value()) { + if (config::enable_i2c.value() && config::enable_tsl.value()) + { mqttVerbosePub(config::topic_tsl2561_availability.value(), lastTslValue ? "online" : "offline", 0, 1); - if (lastTslValue) { + if (lastTslValue) + { if (mqttVerbosePub(config::topic_tsl2561_lux.value(), fmt::format("{:.1f}", lastTslValue->lux), 0, 1) >= 0) last_tsl2561_lux_pub = espchrono::millis_clock::now(); } } - if (config::enable_i2c.value() && config::enable_bmp.value()) { + if (config::enable_i2c.value() && config::enable_bmp.value()) + { mqttVerbosePub(config::topic_bmp085_availability.value(), lastBmpValue ? "online" : "offline", 0, 1); - if (lastBmpValue) { + if (lastBmpValue) + { if (mqttVerbosePub(config::topic_bmp085_pressure.value(), fmt::format("{:.1f}", lastBmpValue->pressure), 0, 1) >= 0) last_bmp085_pressure_pub = espchrono::millis_clock::now(); if (mqttVerbosePub(config::topic_bmp085_temperature.value(), fmt::format("{:.1f}", lastBmpValue->temperature), 0, 1) >= 0) @@ -178,16 +188,22 @@ void mqttEventHandler(void *event_handler_arg, esp_event_base_t event_base, int3 ESP_LOGI(TAG, "%s event_id=%s topic=%.*s data=%.*s", event_base, "MQTT_EVENT_DATA", topic.size(), topic.data(), value.size(), value.data()); - if (topic == config::topic_lamp_set.value()) { - if (config::enable_lamp.value()) { + if (topic == config::topic_lamp_set.value()) + { + if (config::enable_lamp.value()) + { bool newState = (lampState = (value == "ON")); writeLamp(newState); if (mqttConnected) mqttVerbosePub(config::topic_lamp_status.value(), newState ? "ON" : "OFF", 0, 1); - } else { + } + else + { ESP_LOGW(TAG, "received lamp set without lamp support enabled!"); } - } else { + } + else + { ESP_LOGW(TAG, "received unknown data topic=%.*s data=%.*s", topic.size(), topic.data(), value.size(), value.data()); } diff --git a/main/myota.cpp b/main/myota.cpp new file mode 100644 index 0000000..85703cb --- /dev/null +++ b/main/myota.cpp @@ -0,0 +1,49 @@ +#include "myota.h" + +// esp-idf includes +#include + +// local includes +#include "delayedconstruction.h" +#include "espasyncota.h" +#include "espwifistack.h" + +namespace deckenlampe { +namespace { +constexpr const char * const TAG = "OTA"; + +cpputils::DelayedConstruction _asyncOta; +} // namespace + +EspAsyncOta &asyncOta{_asyncOta.getUnsafe()}; + +void init_ota() +{ + ESP_LOGI(TAG, "called"); + + _asyncOta.construct(); + + if (const auto result = _asyncOta->startTask(); !result) + { + ESP_LOGE(TAG, "starting OTA task failed: %.*s", result.error().size(), result.error().data()); + return; + } +} + +void update_ota() +{ + _asyncOta->update(); +} + +tl::expected triggerOta(std::string_view url) +{ + ESP_LOGI(TAG, "%.*s", url.size(), url.data()); + + if (const auto result = _asyncOta->trigger(url, {}, {}, {}); !result) + return tl::make_unexpected(std::move(result).error()); + + wifi_stack::delete_scan_result(); + + return {}; +} +} // namespace deckenlampe diff --git a/main/myota.h b/main/myota.h new file mode 100644 index 0000000..ffd065f --- /dev/null +++ b/main/myota.h @@ -0,0 +1,19 @@ +#pragma once + +// system includes +#include +#include + +// 3rdparty lib includes +#include +// forward declares +class EspAsyncOta; + +namespace deckenlampe { +extern EspAsyncOta &asyncOta; + +void init_ota(); +void update_ota(); + +tl::expected triggerOta(std::string_view url); +} // namespace deckenlampe diff --git a/main/mywifi.cpp b/main/mywifi.cpp index 7ebb17b..25f534a 100644 --- a/main/mywifi.cpp +++ b/main/mywifi.cpp @@ -25,40 +25,35 @@ wifi_stack::config makeWifiConfig() return wifi_stack::config { .wifiEnabled = true, .hostname = config::hostname.value(), - .wifis = std::array { - wifi_stack::wifi_entry { .ssid = config::sta_ssid.value(), .key = config::sta_key.value() }, - wifi_stack::wifi_entry { .ssid = {}, .key = {} }, - wifi_stack::wifi_entry { .ssid = {}, .key = {} }, - wifi_stack::wifi_entry { .ssid = {}, .key = {} }, - wifi_stack::wifi_entry { .ssid = {}, .key = {} }, - wifi_stack::wifi_entry { .ssid = {}, .key = {} }, - wifi_stack::wifi_entry { .ssid = {}, .key = {} }, - wifi_stack::wifi_entry { .ssid = {}, .key = {} }, - wifi_stack::wifi_entry { .ssid = {}, .key = {} }, - wifi_stack::wifi_entry { .ssid = {}, .key = {} } - }, - .sta_ip = { - .staticIpEnabled = false, -// .staticIp = {}, -// .staticGateway = {}, -// .staticSubnet = {}, -// .staticDns1 = {}, -// .staticDns2 = {} + .sta = { + .wifis = std::array { + wifi_stack::wifi_entry { .ssid = config::sta_ssid.value(), .key = config::sta_key.value() }, + wifi_stack::wifi_entry { .ssid = {}, .key = {} }, + wifi_stack::wifi_entry { .ssid = {}, .key = {} }, + wifi_stack::wifi_entry { .ssid = {}, .key = {} }, + wifi_stack::wifi_entry { .ssid = {}, .key = {} }, + wifi_stack::wifi_entry { .ssid = {}, .key = {} }, + wifi_stack::wifi_entry { .ssid = {}, .key = {} }, + wifi_stack::wifi_entry { .ssid = {}, .key = {} }, + wifi_stack::wifi_entry { .ssid = {}, .key = {} }, + wifi_stack::wifi_entry { .ssid = {}, .key = {} } + }, + .min_rssi = -90 }, .ap = { - { - .ssid = config::ap_ssid.value(), - .key = config::ap_key.value() + .ssid = config::ap_ssid.value(), + .key = config::ap_key.value(), + .static_ip = { + .ip = ap_ip, + .subnet = ap_subnet, + .gateway = ap_ip }, .channel = 1, .authmode = WIFI_AUTH_WPA2_PSK, .ssid_hidden = false, .max_connection = 4, - .beacon_interval = 100, - .ip = ap_ip, - .subnet = ap_subnet - }, - .min_rssi = -90 + .beacon_interval = 100 + } }; } } // namespace diff --git a/main/webserver.cpp b/main/webserver.cpp index 1bc1fde..f350f5c 100644 --- a/main/webserver.cpp +++ b/main/webserver.cpp @@ -25,6 +25,8 @@ #include "strutils.h" #include "espchrono.h" #include "numberparsing.h" +#include "myota.h" +#include "espasyncota.h" namespace deckenlampe { httpd_handle_t httpdHandle; @@ -98,14 +100,16 @@ esp_err_t webserver_root_handler(httpd_req_t *req) { std::string query; - if (const size_t queryLength = httpd_req_get_url_query_len(req)) { + if (const size_t queryLength = httpd_req_get_url_query_len(req)) + { query.resize(queryLength); CALL_AND_EXIT_ON_ERROR(httpd_req_get_url_query_str, req, query.data(), query.size() + 1) } std::string body; - if (config::enable_lamp.value()) { + if (config::enable_lamp.value()) + { body += "on
\n" "off
\n" "toggle
\n"; @@ -146,11 +150,14 @@ esp_err_t webserver_root_handler(httpd_req_t *req) esp_err_t webserver_dht_display(httpd_req_t *req, std::string &body) { - if (config::enable_dht.value()) { - if (lastDhtValue) { + if (config::enable_dht.value()) + { + if (lastDhtValue) + { body += fmt::format("DHT11 Temperature: {:.1f} C
\n", lastDhtValue->temperature); body += fmt::format("DHT11 Humidity: {:.1f} %
\n", lastDhtValue->humidity); - } else + } + else body += "DHT11 not available at the moment
\n"; } @@ -159,10 +166,13 @@ esp_err_t webserver_dht_display(httpd_req_t *req, std::string &body) esp_err_t webserver_tsl_display(httpd_req_t *req, std::string &body) { - if (config::enable_i2c.value() && config::enable_tsl.value()) { - if (lastTslValue) { + if (config::enable_i2c.value() && config::enable_tsl.value()) + { + if (lastTslValue) + { body += fmt::format("TSL2561 Brightness: {:.1f} lux
\n", lastTslValue->lux); - } else + } + else body += "TSL2561 not available at the moment
\n"; } @@ -171,12 +181,15 @@ esp_err_t webserver_tsl_display(httpd_req_t *req, std::string &body) esp_err_t webserver_bmp_display(httpd_req_t *req, std::string &body) { - if (config::enable_i2c.value() && config::enable_bmp.value()) { - if (lastBmpValue) { + if (config::enable_i2c.value() && config::enable_bmp.value()) + { + if (lastBmpValue) + { body += fmt::format("BMP085 Pressure: {:.1f} lux
\n", lastBmpValue->pressure); body += fmt::format("BMP085 Temperature: {:.1f} C
\n", lastBmpValue->temperature); body += fmt::format("BMP085 Altitude: {:.1f} m
\n", lastBmpValue->altitude); - } else + } + else body += "BMP085 not available at the moment
\n"; } @@ -192,21 +205,28 @@ esp_err_t webserver_wifi_display(httpd_req_t *req, std::string &body) { const auto staStatus = wifi_stack::get_sta_status(); body += fmt::format("STA status{}\n", wifi_stack::toString(staStatus)); - if (staStatus == wifi_stack::WiFiStaStatus::WL_CONNECTED) { - if (const auto result = wifi_stack::get_sta_ap_info(); result) { + if (staStatus == wifi_stack::WiFiStaStatus::WL_CONNECTED) + { + if (const auto result = wifi_stack::get_sta_ap_info(); result) + { body += fmt::format("STA rssi{}dB\n", result->rssi); body += fmt::format("STA SSID{}\n", htmlentities(result->ssid)); body += fmt::format("STA channel{}\n", result->primary); body += fmt::format("STA BSSID{}\n", wifi_stack::toString(wifi_stack::mac_t{result->bssid})); - } else { + } + else + { body += fmt::format("get_sta_ap_info() failed: {}\n", htmlentities(result.error())); } - if (const auto result = wifi_stack::get_ip_info(TCPIP_ADAPTER_IF_STA)) { + if (const auto result = wifi_stack::get_ip_info(TCPIP_ADAPTER_IF_STA)) + { body += fmt::format("STA ip{}\n", wifi_stack::toString(result->ip)); body += fmt::format("STA netmask{}\n", wifi_stack::toString(result->netmask)); body += fmt::format("STA gw{}\n", wifi_stack::toString(result->gw)); - } else { + } + else + { body += fmt::format("get_ip_info() failed: {}\n", htmlentities(result.error())); } } @@ -216,7 +236,8 @@ esp_err_t webserver_wifi_display(httpd_req_t *req, std::string &body) body += "\n" "

scan result

\n"; - if (const auto &scanResult = wifi_stack::get_scan_result()) { + if (const auto &scanResult = wifi_stack::get_scan_result()) + { body += fmt::format("scan age: {}s
\n", std::chrono::round(espchrono::ago(scanResult->finished)).count()); body += "\n" "\n" @@ -232,7 +253,8 @@ esp_err_t webserver_wifi_display(httpd_req_t *req, std::string &body) "\n" "\n"; - for (const auto &entry : scanResult->entries) { + for (const auto &entry : scanResult->entries) + { body += fmt::format( "\n" "\n" @@ -254,7 +276,9 @@ esp_err_t webserver_wifi_display(httpd_req_t *req, std::string &body) body += "\n" "
{}
\n"; - } else { + } + else + { body += "no wifi scan result at the moment!
\n"; } @@ -263,13 +287,15 @@ esp_err_t webserver_wifi_display(httpd_req_t *req, std::string &body) esp_err_t webserver_mqtt_display(httpd_req_t *req, std::string &body) { - if (config::enable_mqtt.value()) { + if (config::enable_mqtt.value()) + { body += "
\n" "

MQTT

\n" "\n"; body += fmt::format("\n", htmlentities(config::broker_url.value())); body += fmt::format("\n", mqttClient ? "true" : "false"); - if (mqttClient) { + if (mqttClient) + { body += fmt::format("\n", mqttStarted ? "true" : "false"); body += fmt::format("\n", mqttConnected ? "true" : "false"); } @@ -292,21 +318,27 @@ std::string webserver_form_for_config(httpd_req_t *req, ConfigWrapper &con { char valueBufEncoded[256]; - if (const auto result = httpd_query_key_value(query.data(), config.nvsKey(), valueBufEncoded, 256); result == ESP_OK) { + if (const auto result = httpd_query_key_value(query.data(), config.nvsKey(), valueBufEncoded, 256); result == ESP_OK) + { char valueBuf[257]; espcpputils::urldecode(valueBuf, valueBufEncoded); std::string_view value{valueBuf}; - if (value == "true" || value == "false") { + if (value == "true" || value == "false") + { if (const auto result = config.writeToFlash(value == "true")) str += "Successfully saved"; else str += fmt::format("Error while saving: {}", htmlentities(result.error())); - } else { + } + else + { str += fmt::format("Error while saving: Invalid value \"{}\"", htmlentities(value)); } - } else if (result != ESP_ERR_NOT_FOUND) { + } + else if (result != ESP_ERR_NOT_FOUND) + { ESP_LOGE(TAG, "httpd_query_key_value() %s failed with %s", config.nvsKey(), esp_err_to_name(result)); str += fmt::format("Error while saving: httpd_query_key_value() failed with {}", esp_err_to_name(result)); } @@ -331,7 +363,8 @@ std::string webserver_form_for_config(httpd_req_t *req, ConfigWrapperSuccessfully saved"; else str += fmt::format("Error while saving: {}", htmlentities(result.error())); - } else if (result != ESP_ERR_NOT_FOUND) { + } + else if (result != ESP_ERR_NOT_FOUND) + { ESP_LOGE(TAG, "httpd_query_key_value() %s failed with %s", config.nvsKey(), esp_err_to_name(result)); str += fmt::format("Error while saving: httpd_query_key_value() failed with {}", esp_err_to_name(result)); } @@ -362,21 +397,27 @@ std::string webserver_form_for_config(httpd_req_t *req, ConfigWrapper>(value)) { + if (auto parsed = cpputils::fromString>(value)) + { if (const auto result = config.writeToFlash(gpio_num_t(*parsed))) str += "Successfully saved"; else str += fmt::format("Error while saving: {}", htmlentities(result.error())); - } else { + } + else + { str += fmt::format("Error while saving: Invalid value \"{}\"", htmlentities(value)); } - } else if (result != ESP_ERR_NOT_FOUND) { + } + else if (result != ESP_ERR_NOT_FOUND) + { ESP_LOGE(TAG, "httpd_query_key_value() %s failed with %s", config.nvsKey(), esp_err_to_name(result)); } } @@ -398,21 +439,27 @@ std::string webserver_form_for_config(httpd_req_t *req, ConfigWrapper(value)) { + if (auto parsed = cpputils::fromString(value)) + { if (const auto result = config.writeToFlash(espchrono::seconds32(*parsed))) str += "Successfully saved"; else str += fmt::format("Error while saving: {}", htmlentities(result.error())); - } else { + } + else + { str += fmt::format("Error while saving: Invalid value \"{}\"", htmlentities(value)); } - } else if (result != ESP_ERR_NOT_FOUND) { + } + else if (result != ESP_ERR_NOT_FOUND) + { ESP_LOGE(TAG, "httpd_query_key_value() %s failed with %s", config.nvsKey(), esp_err_to_name(result)); } } @@ -442,7 +489,7 @@ esp_err_t webserver_config_display(httpd_req_t *req, std::string &body, std::str "\n" "\n"; - config::foreachConfig([&](auto &config){ + config::foreachConfig([&](auto &config) { using cpputils::toString; using espchrono::toString; @@ -456,12 +503,14 @@ esp_err_t webserver_config_display(httpd_req_t *req, std::string &body, std::str //htmlentities(toString(config.value())), webserver_form_for_config(req, config, query), [&]() -> std::string { - if (const auto result = config.readFromFlash()) { + if (const auto result = config.readFromFlash()) + { if (*result) return htmlentities(toString(**result)); else return "not set"; - } else + } + else return fmt::format("{}", htmlentities(result.error())); }()); }); @@ -474,7 +523,8 @@ esp_err_t webserver_config_display(httpd_req_t *req, std::string &body, std::str esp_err_t webserver_on_handler(httpd_req_t *req) { - if (!config::enable_lamp.value()) { + if (!config::enable_lamp.value()) + { ESP_LOGW(TAG, "lamp support not enabled!"); CALL_AND_EXIT(httpd_resp_send_err, req, HTTPD_400_BAD_REQUEST, "lamp support not enabled!") } @@ -492,7 +542,8 @@ esp_err_t webserver_on_handler(httpd_req_t *req) esp_err_t webserver_off_handler(httpd_req_t *req) { - if (!config::enable_lamp.value()) { + if (!config::enable_lamp.value()) + { ESP_LOGW(TAG, "lamp support not enabled!"); CALL_AND_EXIT(httpd_resp_send_err, req, HTTPD_400_BAD_REQUEST, "lamp support not enabled!") } @@ -510,7 +561,8 @@ esp_err_t webserver_off_handler(httpd_req_t *req) esp_err_t webserver_toggle_handler(httpd_req_t *req) { - if (!config::enable_lamp.value()) { + if (!config::enable_lamp.value()) + { ESP_LOGW(TAG, "lamp support not enabled!"); CALL_AND_EXIT(httpd_resp_send_err, req, HTTPD_400_BAD_REQUEST, "lamp support not enabled!") }
client url{}
client constructed{}
client started{}
client connected{}