added espasyncota lib

This commit is contained in:
2021-08-06 15:50:44 +02:00
parent 42bac7c293
commit 76ef403bbf
19 changed files with 311 additions and 124 deletions

3
.gitmodules vendored
View File

@@ -40,3 +40,6 @@
[submodule "components/esp-nimble-cpp"] [submodule "components/esp-nimble-cpp"]
path = components/esp-nimble-cpp path = components/esp-nimble-cpp
url = git@github.com:0xFEEDC0DE64/esp-nimble-cpp.git url = git@github.com:0xFEEDC0DE64/esp-nimble-cpp.git
[submodule "components/espasyncota"]
path = components/espasyncota
url = git@github.com:0xFEEDC0DE64/espasyncota.git

View File

@@ -12,6 +12,7 @@ set(headers
myconfig.h myconfig.h
mymdns.h mymdns.h
mymqtt.h mymqtt.h
myota.h
mywifi.h mywifi.h
nvswrappers.h nvswrappers.h
webserver.h webserver.h
@@ -29,13 +30,14 @@ set(sources
myconfig.cpp myconfig.cpp
mymdns.cpp mymdns.cpp
mymqtt.cpp mymqtt.cpp
myota.cpp
mywifi.cpp mywifi.cpp
webserver.cpp webserver.cpp
) )
set(dependencies set(dependencies
freertos nvs_flash esp_http_server esp_https_ota mdns app_update esp_system mqtt 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 Adafruit_BMP085_Unified Adafruit_TSL2561 DHT-sensor-library
) )

View File

@@ -39,7 +39,8 @@ void init_bmp()
bmpInitialized = bmp->begin(); bmpInitialized = bmp->begin();
ESP_LOGI(TAG, "finished with %s", bmpInitialized ? "true" : "false"); ESP_LOGI(TAG, "finished with %s", bmpInitialized ? "true" : "false");
if (bmpInitialized) { if (bmpInitialized)
{
sensor_t sensor = bmp->getSensor(); sensor_t sensor = bmp->getSensor();
ESP_LOGI(TAG, "------------------------------------"); ESP_LOGI(TAG, "------------------------------------");
ESP_LOGI(TAG, "Sensor: %s", sensor.name); ESP_LOGI(TAG, "Sensor: %s", sensor.name);
@@ -58,14 +59,17 @@ void update_bmp()
if (!config::enable_i2c.value() || !config::enable_bmp.value()) if (!config::enable_i2c.value() || !config::enable_bmp.value())
return; return;
if (bmpInitialized) { if (bmpInitialized)
{
if (espchrono::ago(last_bmp085_readout) < 5s) if (espchrono::ago(last_bmp085_readout) < 5s)
return; return;
last_bmp085_readout = espchrono::millis_clock::now(); last_bmp085_readout = espchrono::millis_clock::now();
if (std::optional<Adafruit_BMP085_Unified::TemperatureAndPressure> values = bmp->getTemperatureAndPressure()) { if (std::optional<Adafruit_BMP085_Unified::TemperatureAndPressure> values = bmp->getTemperatureAndPressure())
if (values->temperature && values->pressure) { {
if (values->temperature && values->pressure)
{
BmpValue bmpValue { BmpValue bmpValue {
.timestamp = espchrono::millis_clock::now(), .timestamp = espchrono::millis_clock::now(),
.pressure = values->pressure, .pressure = values->pressure,
@@ -79,35 +83,46 @@ void update_bmp()
bmpValue.altitude = bmp->pressureToAltitude(seaLevelPressure, bmpValue.pressure); bmpValue.altitude = bmp->pressureToAltitude(seaLevelPressure, bmpValue.pressure);
ESP_LOGI(TAG, "read bmp Altitude: %.1f m", bmpValue.altitude); ESP_LOGI(TAG, "read bmp Altitude: %.1f m", bmpValue.altitude);
if (mqttConnected) { if (mqttConnected)
{
if (!lastBmpValue) if (!lastBmpValue)
mqttVerbosePub(config::topic_bmp085_availability.value(), "online", 0, 1); 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) if (mqttVerbosePub(config::topic_bmp085_pressure.value(), fmt::format("{:.1f}", bmpValue.pressure), 0, 1) >= 0)
last_bmp085_pressure_pub = espchrono::millis_clock::now(); 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) if (mqttVerbosePub(config::topic_bmp085_temperature.value(), fmt::format("{:.1f}", bmpValue.temperature), 0, 1) >= 0)
last_bmp085_temperature_pub = espchrono::millis_clock::now(); 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) if (mqttVerbosePub(config::topic_bmp085_altitude.value(), fmt::format("{:.1f}", bmpValue.altitude), 0, 1) >= 0)
last_bmp085_altitude_pub = espchrono::millis_clock::now(); last_bmp085_altitude_pub = espchrono::millis_clock::now();
} }
} }
lastBmpValue = bmpValue; lastBmpValue = bmpValue;
} else { }
else
{
ESP_LOGW(TAG, "bmp sensor error"); ESP_LOGW(TAG, "bmp sensor error");
goto bmpOffline; goto bmpOffline;
} }
} else { }
else
{
ESP_LOGW(TAG, "bmp failed"); ESP_LOGW(TAG, "bmp failed");
goto bmpOffline; goto bmpOffline;
} }
} else { }
else
{
bmpOffline: bmpOffline:
if (lastBmpValue && espchrono::ago(lastBmpValue->timestamp) >= config::availableTimeoutTime.value()) { if (lastBmpValue && espchrono::ago(lastBmpValue->timestamp) >= config::availableTimeoutTime.value())
{
ESP_LOGW(TAG, "bmp timeouted"); ESP_LOGW(TAG, "bmp timeouted");
if (mqttConnected) if (mqttConnected)
mqttVerbosePub(config::topic_bmp085_availability.value(), "offline", 0, 1); mqttVerbosePub(config::topic_bmp085_availability.value(), "offline", 0, 1);

View File

@@ -44,13 +44,15 @@ void update_dht()
if (!config::enable_dht.value()) if (!config::enable_dht.value())
return; return;
if (dhtInitialized) { if (dhtInitialized)
{
if (espchrono::ago(last_dht11_readout) < 5s) if (espchrono::ago(last_dht11_readout) < 5s)
return; return;
last_dht11_readout = espchrono::millis_clock::now(); last_dht11_readout = espchrono::millis_clock::now();
if (const auto data = dht->read()) { if (const auto data = dht->read())
{
DhtValue dhtValue { DhtValue dhtValue {
.timestamp = espchrono::millis_clock::now(), .timestamp = espchrono::millis_clock::now(),
.temperature = dht->readTemperature(*data), .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 temperature: %.1f C", dhtValue.temperature);
ESP_LOGI(TAG, "read dht humidity: %.1f %%", dhtValue.humidity); ESP_LOGI(TAG, "read dht humidity: %.1f %%", dhtValue.humidity);
if (mqttConnected) { if (mqttConnected)
{
if (!lastDhtValue) if (!lastDhtValue)
mqttVerbosePub(config::topic_dht11_availability.value(), "online", 0, 1); 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) if (mqttVerbosePub(config::topic_dht11_temperature.value(), fmt::format("{:.1f}", dhtValue.temperature), 0, 1) >= 0)
last_dht11_temperature_pub = espchrono::millis_clock::now(); 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) if (mqttVerbosePub(config::topic_dht11_humidity.value(), fmt::format("{:.1f}", dhtValue.humidity), 0, 1) >= 0)
last_dht11_humidity_pub = espchrono::millis_clock::now(); last_dht11_humidity_pub = espchrono::millis_clock::now();
} }
} }
lastDhtValue = dhtValue; lastDhtValue = dhtValue;
} else { }
else
{
ESP_LOGW(TAG, "dht failed"); ESP_LOGW(TAG, "dht failed");
goto dhtOffline; goto dhtOffline;
} }
} else { }
else
{
dhtOffline: dhtOffline:
if (lastDhtValue && espchrono::ago(lastDhtValue->timestamp) >= config::availableTimeoutTime.value()) { if (lastDhtValue && espchrono::ago(lastDhtValue->timestamp) >= config::availableTimeoutTime.value())
{
ESP_LOGW(TAG, "dht timeouted"); ESP_LOGW(TAG, "dht timeouted");
if (mqttConnected) if (mqttConnected)
mqttVerbosePub(config::topic_dht11_availability.value(), "offline", 0, 1); mqttVerbosePub(config::topic_dht11_availability.value(), "offline", 0, 1);

View File

@@ -41,9 +41,11 @@ void update_switch()
const auto newState = readSwitch(); const auto newState = readSwitch();
if (newState == switchState.load()) if (newState == switchState.load())
switchDebounce = 0; switchDebounce = 0;
else { else
{
switchDebounce++; switchDebounce++;
if (switchDebounce >= 10) { if (switchDebounce >= 10)
{
switchDebounce = 0; switchDebounce = 0;
switchState = newState; switchState = newState;
@@ -51,7 +53,8 @@ void update_switch()
if (mqttConnected) if (mqttConnected)
mqttVerbosePub(config::topic_switch_status.value(), switchState ? "ON" : "OFF", 0, 1); mqttVerbosePub(config::topic_switch_status.value(), switchState ? "ON" : "OFF", 0, 1);
if (config::enable_lamp.value()) { if (config::enable_lamp.value())
{
lampState = !lampState; lampState = !lampState;
writeLamp(lampState); writeLamp(lampState);

View File

@@ -37,7 +37,8 @@ void init_tsl()
tslInitialized = tsl->begin(true); tslInitialized = tsl->begin(true);
ESP_LOGI(TAG, "finished with %s", tslInitialized ? "true" : "false"); ESP_LOGI(TAG, "finished with %s", tslInitialized ? "true" : "false");
if (tslInitialized) { if (tslInitialized)
{
sensor_t sensor = tsl->getSensor(); sensor_t sensor = tsl->getSensor();
ESP_LOGI(TAG, "------------------------------------"); ESP_LOGI(TAG, "------------------------------------");
ESP_LOGI(TAG, "Sensor: %s", sensor.name); ESP_LOGI(TAG, "Sensor: %s", sensor.name);
@@ -72,44 +73,56 @@ void update_tsl()
if (!config::enable_i2c.value() || !config::enable_tsl.value()) if (!config::enable_i2c.value() || !config::enable_tsl.value())
return; return;
if (tslInitialized) { if (tslInitialized)
{
if (espchrono::ago(last_tsl2561_readout) < 5s) if (espchrono::ago(last_tsl2561_readout) < 5s)
return; return;
last_tsl2561_readout = espchrono::millis_clock::now(); last_tsl2561_readout = espchrono::millis_clock::now();
if (std::optional<sensors_event_t> event = tsl->getEvent()) { if (std::optional<sensors_event_t> event = tsl->getEvent())
{
/* Display the results (light is measured in lux) */ /* Display the results (light is measured in lux) */
if (event->light) { if (event->light)
{
TslValue tslValue { TslValue tslValue {
.timestamp = espchrono::millis_clock::now(), .timestamp = espchrono::millis_clock::now(),
.lux = event->light .lux = event->light
}; };
ESP_LOGI(TAG, "read tsl: %.1f lux", tslValue.lux); ESP_LOGI(TAG, "read tsl: %.1f lux", tslValue.lux);
if (mqttConnected) { if (mqttConnected)
{
if (!lastTslValue) if (!lastTslValue)
mqttVerbosePub(config::topic_tsl2561_availability.value(), "online", 0, 1); 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) if (mqttVerbosePub(config::topic_tsl2561_lux.value(), fmt::format("{:.1f}", tslValue.lux), 0, 1) >= 0)
last_tsl2561_lux_pub = espchrono::millis_clock::now(); last_tsl2561_lux_pub = espchrono::millis_clock::now();
} }
} }
lastTslValue = tslValue; lastTslValue = tslValue;
} else { }
else
{
/* If event.light = 0 lux the sensor is probably saturated /* If event.light = 0 lux the sensor is probably saturated
* and no reliable data could be generated! */ * and no reliable data could be generated! */
ESP_LOGW(TAG, "tsl sensor overload %f", event->light); ESP_LOGW(TAG, "tsl sensor overload %f", event->light);
goto tslOffline; goto tslOffline;
} }
} else { }
else
{
ESP_LOGW(TAG, "tsl failed"); ESP_LOGW(TAG, "tsl failed");
goto tslOffline; goto tslOffline;
} }
} else { }
else
{
tslOffline: tslOffline:
if (lastTslValue && espchrono::ago(lastTslValue->timestamp) >= config::availableTimeoutTime.value()) { if (lastTslValue && espchrono::ago(lastTslValue->timestamp) >= config::availableTimeoutTime.value())
{
ESP_LOGW(TAG, "tsl timeouted"); ESP_LOGW(TAG, "tsl timeouted");
if (mqttConnected) if (mqttConnected)
mqttVerbosePub(config::topic_tsl2561_availability.value(), "offline", 0, 1); mqttVerbosePub(config::topic_tsl2561_availability.value(), "offline", 0, 1);

View File

@@ -23,6 +23,7 @@
#include "webserver.h" #include "webserver.h"
#include "mymdns.h" #include "mymdns.h"
#include "mymqtt.h" #include "mymqtt.h"
#include "myota.h"
#include "feature_lamp.h" #include "feature_lamp.h"
#include "feature_switch.h" #include "feature_switch.h"
#include "feature_dht.h" #include "feature_dht.h"
@@ -99,6 +100,8 @@ extern "C" void app_main()
init_mqtt(); init_mqtt();
init_ota();
init_dht(); init_dht();
init_tsl(); init_tsl();
@@ -130,6 +133,9 @@ extern "C" void app_main()
update_mqtt(); update_mqtt();
vPortYield(); vPortYield();
update_ota();
vPortYield();
update_dht(); update_dht();
vPortYield(); vPortYield();

View File

@@ -102,15 +102,18 @@ namespace {
template<typename T> template<typename T>
void loadParam(ConfigWrapper<T> &config) void loadParam(ConfigWrapper<T> &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); ESP_LOGE(TAG, "%s too long %zd (%zd)", config.nvsKey(), len, len-15);
assert(false); assert(false);
} }
if (const auto value = config.readFromFlash()) { if (const auto value = config.readFromFlash())
{
if (*value) if (*value)
config.setValue(**value); config.setValue(**value);
} else }
else
ESP_LOGE(TAG, "error loading config %s: %.*s", config.name(), value.error().size(), value.error().data()); ESP_LOGE(TAG, "error loading config %s: %.*s", config.name(), value.error().size(), value.error().data());
} }
} // namespace } // namespace

View File

@@ -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()); 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!"); ESP_LOGE(TAG, "mqttClient not constructed!");
return -1; 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<const esp_mqtt_event_t *>(event_data); const esp_mqtt_event_t *data = reinterpret_cast<const esp_mqtt_event_t *>(event_data);
switch (esp_mqtt_event_id_t(event_id)) { switch (esp_mqtt_event_id_t(event_id))
{
case MQTT_EVENT_ERROR: case MQTT_EVENT_ERROR:
ESP_LOGE(TAG, "%s event_id=%s", event_base, "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; 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_availability.value(), "online", 0, 1);
mqttVerbosePub(config::topic_lamp_status.value(), lampState.load() ? "ON" : "OFF", 0, 1); mqttVerbosePub(config::topic_lamp_status.value(), lampState.load() ? "ON" : "OFF", 0, 1);
mqttClient.subscribe(config::topic_lamp_set.value(), 0); 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_availability.value(), "online", 0, 1);
mqttVerbosePub(config::topic_switch_status.value(), switchState.load() ? "ON" : "OFF", 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); 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) if (mqttVerbosePub(config::topic_dht11_temperature.value(), fmt::format("{:.1f}", lastDhtValue->temperature), 0, 1) >= 0)
last_dht11_temperature_pub = espchrono::millis_clock::now(); last_dht11_temperature_pub = espchrono::millis_clock::now();
if (mqttVerbosePub(config::topic_dht11_humidity.value(), fmt::format("{:.1f}", lastDhtValue->humidity), 0, 1) >= 0) 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); 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) if (mqttVerbosePub(config::topic_tsl2561_lux.value(), fmt::format("{:.1f}", lastTslValue->lux), 0, 1) >= 0)
last_tsl2561_lux_pub = espchrono::millis_clock::now(); 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); 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) if (mqttVerbosePub(config::topic_bmp085_pressure.value(), fmt::format("{:.1f}", lastBmpValue->pressure), 0, 1) >= 0)
last_bmp085_pressure_pub = espchrono::millis_clock::now(); last_bmp085_pressure_pub = espchrono::millis_clock::now();
if (mqttVerbosePub(config::topic_bmp085_temperature.value(), fmt::format("{:.1f}", lastBmpValue->temperature), 0, 1) >= 0) 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()); 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 (topic == config::topic_lamp_set.value())
if (config::enable_lamp.value()) { {
if (config::enable_lamp.value())
{
bool newState = (lampState = (value == "ON")); bool newState = (lampState = (value == "ON"));
writeLamp(newState); writeLamp(newState);
if (mqttConnected) if (mqttConnected)
mqttVerbosePub(config::topic_lamp_status.value(), newState ? "ON" : "OFF", 0, 1); mqttVerbosePub(config::topic_lamp_status.value(), newState ? "ON" : "OFF", 0, 1);
} else { }
else
{
ESP_LOGW(TAG, "received lamp set without lamp support enabled!"); 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()); ESP_LOGW(TAG, "received unknown data topic=%.*s data=%.*s", topic.size(), topic.data(), value.size(), value.data());
} }

49
main/myota.cpp Normal file
View File

@@ -0,0 +1,49 @@
#include "myota.h"
// esp-idf includes
#include <esp_log.h>
// local includes
#include "delayedconstruction.h"
#include "espasyncota.h"
#include "espwifistack.h"
namespace deckenlampe {
namespace {
constexpr const char * const TAG = "OTA";
cpputils::DelayedConstruction<EspAsyncOta> _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<void, std::string> 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

19
main/myota.h Normal file
View File

@@ -0,0 +1,19 @@
#pragma once
// system includes
#include <string>
#include <string_view>
// 3rdparty lib includes
#include <tl/expected.hpp>
// forward declares
class EspAsyncOta;
namespace deckenlampe {
extern EspAsyncOta &asyncOta;
void init_ota();
void update_ota();
tl::expected<void, std::string> triggerOta(std::string_view url);
} // namespace deckenlampe

View File

@@ -25,40 +25,35 @@ wifi_stack::config makeWifiConfig()
return wifi_stack::config { return wifi_stack::config {
.wifiEnabled = true, .wifiEnabled = true,
.hostname = config::hostname.value(), .hostname = config::hostname.value(),
.wifis = std::array<wifi_stack::wifi_entry, 10> { .sta = {
wifi_stack::wifi_entry { .ssid = config::sta_ssid.value(), .key = config::sta_key.value() }, .wifis = std::array<wifi_stack::wifi_entry, 10> {
wifi_stack::wifi_entry { .ssid = {}, .key = {} }, 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 = {} }, 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, .min_rssi = -90
// .staticIp = {},
// .staticGateway = {},
// .staticSubnet = {},
// .staticDns1 = {},
// .staticDns2 = {}
}, },
.ap = { .ap = {
{ .ssid = config::ap_ssid.value(),
.ssid = config::ap_ssid.value(), .key = config::ap_key.value(),
.key = config::ap_key.value() .static_ip = {
.ip = ap_ip,
.subnet = ap_subnet,
.gateway = ap_ip
}, },
.channel = 1, .channel = 1,
.authmode = WIFI_AUTH_WPA2_PSK, .authmode = WIFI_AUTH_WPA2_PSK,
.ssid_hidden = false, .ssid_hidden = false,
.max_connection = 4, .max_connection = 4,
.beacon_interval = 100, .beacon_interval = 100
.ip = ap_ip, }
.subnet = ap_subnet
},
.min_rssi = -90
}; };
} }
} // namespace } // namespace

View File

@@ -25,6 +25,8 @@
#include "strutils.h" #include "strutils.h"
#include "espchrono.h" #include "espchrono.h"
#include "numberparsing.h" #include "numberparsing.h"
#include "myota.h"
#include "espasyncota.h"
namespace deckenlampe { namespace deckenlampe {
httpd_handle_t httpdHandle; httpd_handle_t httpdHandle;
@@ -98,14 +100,16 @@ esp_err_t webserver_root_handler(httpd_req_t *req)
{ {
std::string query; 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); query.resize(queryLength);
CALL_AND_EXIT_ON_ERROR(httpd_req_get_url_query_str, req, query.data(), query.size() + 1) CALL_AND_EXIT_ON_ERROR(httpd_req_get_url_query_str, req, query.data(), query.size() + 1)
} }
std::string body; std::string body;
if (config::enable_lamp.value()) { if (config::enable_lamp.value())
{
body += "<a href=\"/on\">on</a><br/>\n" body += "<a href=\"/on\">on</a><br/>\n"
"<a href=\"/off\">off</a><br/>\n" "<a href=\"/off\">off</a><br/>\n"
"<a href=\"/toggle\">toggle</a><br/>\n"; "<a href=\"/toggle\">toggle</a><br/>\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) esp_err_t webserver_dht_display(httpd_req_t *req, std::string &body)
{ {
if (config::enable_dht.value()) { if (config::enable_dht.value())
if (lastDhtValue) { {
if (lastDhtValue)
{
body += fmt::format("DHT11 Temperature: {:.1f} C<br/>\n", lastDhtValue->temperature); body += fmt::format("DHT11 Temperature: {:.1f} C<br/>\n", lastDhtValue->temperature);
body += fmt::format("DHT11 Humidity: {:.1f} %<br/>\n", lastDhtValue->humidity); body += fmt::format("DHT11 Humidity: {:.1f} %<br/>\n", lastDhtValue->humidity);
} else }
else
body += "DHT11 not available at the moment<br/>\n"; body += "DHT11 not available at the moment<br/>\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) esp_err_t webserver_tsl_display(httpd_req_t *req, std::string &body)
{ {
if (config::enable_i2c.value() && config::enable_tsl.value()) { if (config::enable_i2c.value() && config::enable_tsl.value())
if (lastTslValue) { {
if (lastTslValue)
{
body += fmt::format("TSL2561 Brightness: {:.1f} lux<br/>\n", lastTslValue->lux); body += fmt::format("TSL2561 Brightness: {:.1f} lux<br/>\n", lastTslValue->lux);
} else }
else
body += "TSL2561 not available at the moment<br/>\n"; body += "TSL2561 not available at the moment<br/>\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) esp_err_t webserver_bmp_display(httpd_req_t *req, std::string &body)
{ {
if (config::enable_i2c.value() && config::enable_bmp.value()) { if (config::enable_i2c.value() && config::enable_bmp.value())
if (lastBmpValue) { {
if (lastBmpValue)
{
body += fmt::format("BMP085 Pressure: {:.1f} lux<br/>\n", lastBmpValue->pressure); body += fmt::format("BMP085 Pressure: {:.1f} lux<br/>\n", lastBmpValue->pressure);
body += fmt::format("BMP085 Temperature: {:.1f} C<br/>\n", lastBmpValue->temperature); body += fmt::format("BMP085 Temperature: {:.1f} C<br/>\n", lastBmpValue->temperature);
body += fmt::format("BMP085 Altitude: {:.1f} m<br/>\n", lastBmpValue->altitude); body += fmt::format("BMP085 Altitude: {:.1f} m<br/>\n", lastBmpValue->altitude);
} else }
else
body += "BMP085 not available at the moment<br/>\n"; body += "BMP085 not available at the moment<br/>\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(); const auto staStatus = wifi_stack::get_sta_status();
body += fmt::format("<tr><th>STA status</th><td>{}</td></tr>\n", wifi_stack::toString(staStatus)); body += fmt::format("<tr><th>STA status</th><td>{}</td></tr>\n", wifi_stack::toString(staStatus));
if (staStatus == wifi_stack::WiFiStaStatus::WL_CONNECTED) { if (staStatus == wifi_stack::WiFiStaStatus::WL_CONNECTED)
if (const auto result = wifi_stack::get_sta_ap_info(); result) { {
if (const auto result = wifi_stack::get_sta_ap_info(); result)
{
body += fmt::format("<tr><th>STA rssi</th><td>{}dB</td></tr>\n", result->rssi); body += fmt::format("<tr><th>STA rssi</th><td>{}dB</td></tr>\n", result->rssi);
body += fmt::format("<tr><th>STA SSID</th><td>{}</td></tr>\n", htmlentities(result->ssid)); body += fmt::format("<tr><th>STA SSID</th><td>{}</td></tr>\n", htmlentities(result->ssid));
body += fmt::format("<tr><th>STA channel</th><td>{}</td></tr>\n", result->primary); body += fmt::format("<tr><th>STA channel</th><td>{}</td></tr>\n", result->primary);
body += fmt::format("<tr><th>STA BSSID</th><td>{}</td></tr>\n", wifi_stack::toString(wifi_stack::mac_t{result->bssid})); body += fmt::format("<tr><th>STA BSSID</th><td>{}</td></tr>\n", wifi_stack::toString(wifi_stack::mac_t{result->bssid}));
} else { }
else
{
body += fmt::format("<tr><td colspan=\"2\">get_sta_ap_info() failed: {}</td></tr>\n", htmlentities(result.error())); body += fmt::format("<tr><td colspan=\"2\">get_sta_ap_info() failed: {}</td></tr>\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("<tr><th>STA ip</th><td>{}</td></tr>\n", wifi_stack::toString(result->ip)); body += fmt::format("<tr><th>STA ip</th><td>{}</td></tr>\n", wifi_stack::toString(result->ip));
body += fmt::format("<tr><th>STA netmask</th><td>{}</td></tr>\n", wifi_stack::toString(result->netmask)); body += fmt::format("<tr><th>STA netmask</th><td>{}</td></tr>\n", wifi_stack::toString(result->netmask));
body += fmt::format("<tr><th>STA gw</th><td>{}</td></tr>\n", wifi_stack::toString(result->gw)); body += fmt::format("<tr><th>STA gw</th><td>{}</td></tr>\n", wifi_stack::toString(result->gw));
} else { }
else
{
body += fmt::format("<tr><td colspan=\"2\">get_ip_info() failed: {}</td></tr>\n", htmlentities(result.error())); body += fmt::format("<tr><td colspan=\"2\">get_ip_info() failed: {}</td></tr>\n", htmlentities(result.error()));
} }
} }
@@ -216,7 +236,8 @@ esp_err_t webserver_wifi_display(httpd_req_t *req, std::string &body)
body += "</table>\n" body += "</table>\n"
"<h3>scan result</h3>\n"; "<h3>scan result</h3>\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<br />\n", std::chrono::round<std::chrono::seconds>(espchrono::ago(scanResult->finished)).count()); body += fmt::format("scan age: {}s<br />\n", std::chrono::round<std::chrono::seconds>(espchrono::ago(scanResult->finished)).count());
body += "<table border=\"1\">\n" body += "<table border=\"1\">\n"
"<thead>\n" "<thead>\n"
@@ -232,7 +253,8 @@ esp_err_t webserver_wifi_display(httpd_req_t *req, std::string &body)
"</thead>\n" "</thead>\n"
"<tbody>\n"; "<tbody>\n";
for (const auto &entry : scanResult->entries) { for (const auto &entry : scanResult->entries)
{
body += fmt::format( body += fmt::format(
"<tr>\n" "<tr>\n"
"<td>{}</td>\n" "<td>{}</td>\n"
@@ -254,7 +276,9 @@ esp_err_t webserver_wifi_display(httpd_req_t *req, std::string &body)
body += "</tbody>\n" body += "</tbody>\n"
"</table>\n"; "</table>\n";
} else { }
else
{
body += "<span style=\"color: red;\">no wifi scan result at the moment!</span><br/>\n"; body += "<span style=\"color: red;\">no wifi scan result at the moment!</span><br/>\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) esp_err_t webserver_mqtt_display(httpd_req_t *req, std::string &body)
{ {
if (config::enable_mqtt.value()) { if (config::enable_mqtt.value())
{
body += "<br/>\n" body += "<br/>\n"
"<h2>MQTT</h2>\n" "<h2>MQTT</h2>\n"
"<table border=\"1\">\n"; "<table border=\"1\">\n";
body += fmt::format("<tr><th>client url</th><td>{}</td></tr>\n", htmlentities(config::broker_url.value())); body += fmt::format("<tr><th>client url</th><td>{}</td></tr>\n", htmlentities(config::broker_url.value()));
body += fmt::format("<tr><th>client constructed</th><td>{}</td></tr>\n", mqttClient ? "true" : "false"); body += fmt::format("<tr><th>client constructed</th><td>{}</td></tr>\n", mqttClient ? "true" : "false");
if (mqttClient) { if (mqttClient)
{
body += fmt::format("<tr><th>client started</th><td>{}</td></tr>\n", mqttStarted ? "true" : "false"); body += fmt::format("<tr><th>client started</th><td>{}</td></tr>\n", mqttStarted ? "true" : "false");
body += fmt::format("<tr><th>client connected</th><td>{}</td></tr>\n", mqttConnected ? "true" : "false"); body += fmt::format("<tr><th>client connected</th><td>{}</td></tr>\n", mqttConnected ? "true" : "false");
} }
@@ -292,21 +318,27 @@ std::string webserver_form_for_config(httpd_req_t *req, ConfigWrapper<bool> &con
{ {
char valueBufEncoded[256]; 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]; char valueBuf[257];
espcpputils::urldecode(valueBuf, valueBufEncoded); espcpputils::urldecode(valueBuf, valueBufEncoded);
std::string_view value{valueBuf}; std::string_view value{valueBuf};
if (value == "true" || value == "false") { if (value == "true" || value == "false")
{
if (const auto result = config.writeToFlash(value == "true")) if (const auto result = config.writeToFlash(value == "true"))
str += "<span style=\"color: green;\">Successfully saved</span>"; str += "<span style=\"color: green;\">Successfully saved</span>";
else else
str += fmt::format("<span style=\"color: red;\">Error while saving: {}</span>", htmlentities(result.error())); str += fmt::format("<span style=\"color: red;\">Error while saving: {}</span>", htmlentities(result.error()));
} else { }
else
{
str += fmt::format("<span style=\"color: red;\">Error while saving: Invalid value \"{}\"</span>", htmlentities(value)); str += fmt::format("<span style=\"color: red;\">Error while saving: Invalid value \"{}\"</span>", 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)); ESP_LOGE(TAG, "httpd_query_key_value() %s failed with %s", config.nvsKey(), esp_err_to_name(result));
str += fmt::format("<span style=\"color: red;\">Error while saving: httpd_query_key_value() failed with {}</span>", esp_err_to_name(result)); str += fmt::format("<span style=\"color: red;\">Error while saving: httpd_query_key_value() failed with {}</span>", esp_err_to_name(result));
} }
@@ -331,7 +363,8 @@ std::string webserver_form_for_config(httpd_req_t *req, ConfigWrapper<std::strin
{ {
char valueBufEncoded[256]; 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]; char valueBuf[257];
espcpputils::urldecode(valueBuf, valueBufEncoded); espcpputils::urldecode(valueBuf, valueBufEncoded);
@@ -339,7 +372,9 @@ std::string webserver_form_for_config(httpd_req_t *req, ConfigWrapper<std::strin
str += "<span style=\"color: green;\">Successfully saved</span>"; str += "<span style=\"color: green;\">Successfully saved</span>";
else else
str += fmt::format("<span style=\"color: red;\">Error while saving: {}</span>", htmlentities(result.error())); str += fmt::format("<span style=\"color: red;\">Error while saving: {}</span>", 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)); ESP_LOGE(TAG, "httpd_query_key_value() %s failed with %s", config.nvsKey(), esp_err_to_name(result));
str += fmt::format("<span style=\"color: red;\">Error while saving: httpd_query_key_value() failed with {}</span>", esp_err_to_name(result)); str += fmt::format("<span style=\"color: red;\">Error while saving: httpd_query_key_value() failed with {}</span>", esp_err_to_name(result));
} }
@@ -362,21 +397,27 @@ std::string webserver_form_for_config(httpd_req_t *req, ConfigWrapper<gpio_num_t
{ {
char valueBufEncoded[256]; 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]; char valueBuf[257];
espcpputils::urldecode(valueBuf, valueBufEncoded); espcpputils::urldecode(valueBuf, valueBufEncoded);
std::string_view value{valueBuf}; std::string_view value{valueBuf};
if (auto parsed = cpputils::fromString<std::underlying_type_t<gpio_num_t>>(value)) { if (auto parsed = cpputils::fromString<std::underlying_type_t<gpio_num_t>>(value))
{
if (const auto result = config.writeToFlash(gpio_num_t(*parsed))) if (const auto result = config.writeToFlash(gpio_num_t(*parsed)))
str += "<span style=\"color: green;\">Successfully saved</span>"; str += "<span style=\"color: green;\">Successfully saved</span>";
else else
str += fmt::format("<span style=\"color: red;\">Error while saving: {}</span>", htmlentities(result.error())); str += fmt::format("<span style=\"color: red;\">Error while saving: {}</span>", htmlentities(result.error()));
} else { }
else
{
str += fmt::format("<span style=\"color: red;\">Error while saving: Invalid value \"{}\"</span>", htmlentities(value)); str += fmt::format("<span style=\"color: red;\">Error while saving: Invalid value \"{}\"</span>", 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)); 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<espchrono:
{ {
char valueBufEncoded[256]; 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]; char valueBuf[257];
espcpputils::urldecode(valueBuf, valueBufEncoded); espcpputils::urldecode(valueBuf, valueBufEncoded);
std::string_view value{valueBuf}; std::string_view value{valueBuf};
if (auto parsed = cpputils::fromString<espchrono::seconds32::rep>(value)) { if (auto parsed = cpputils::fromString<espchrono::seconds32::rep>(value))
{
if (const auto result = config.writeToFlash(espchrono::seconds32(*parsed))) if (const auto result = config.writeToFlash(espchrono::seconds32(*parsed)))
str += "<span style=\"color: green;\">Successfully saved</span>"; str += "<span style=\"color: green;\">Successfully saved</span>";
else else
str += fmt::format("<span style=\"color: red;\">Error while saving: {}</span>", htmlentities(result.error())); str += fmt::format("<span style=\"color: red;\">Error while saving: {}</span>", htmlentities(result.error()));
} else { }
else
{
str += fmt::format("<span style=\"color: red;\">Error while saving: Invalid value \"{}\"</span>", htmlentities(value)); str += fmt::format("<span style=\"color: red;\">Error while saving: Invalid value \"{}\"</span>", 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)); 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
"</thead>\n" "</thead>\n"
"<tbody>\n"; "<tbody>\n";
config::foreachConfig([&](auto &config){ config::foreachConfig([&](auto &config) {
using cpputils::toString; using cpputils::toString;
using espchrono::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())), //htmlentities(toString(config.value())),
webserver_form_for_config(req, config, query), webserver_form_for_config(req, config, query),
[&]() -> std::string { [&]() -> std::string {
if (const auto result = config.readFromFlash()) { if (const auto result = config.readFromFlash())
{
if (*result) if (*result)
return htmlentities(toString(**result)); return htmlentities(toString(**result));
else else
return "<span style=\"color: grey;\">not set</span>"; return "<span style=\"color: grey;\">not set</span>";
} else }
else
return fmt::format("<span style=\"color: red\">{}</span>", htmlentities(result.error())); return fmt::format("<span style=\"color: red\">{}</span>", 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) 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!"); ESP_LOGW(TAG, "lamp support not enabled!");
CALL_AND_EXIT(httpd_resp_send_err, req, HTTPD_400_BAD_REQUEST, "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) 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!"); ESP_LOGW(TAG, "lamp support not enabled!");
CALL_AND_EXIT(httpd_resp_send_err, req, HTTPD_400_BAD_REQUEST, "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) 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!"); ESP_LOGW(TAG, "lamp support not enabled!");
CALL_AND_EXIT(httpd_resp_send_err, req, HTTPD_400_BAD_REQUEST, "lamp support not enabled!") CALL_AND_EXIT(httpd_resp_send_err, req, HTTPD_400_BAD_REQUEST, "lamp support not enabled!")
} }