added espasyncota lib
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -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
|
||||
|
Submodule components/cpputils updated: 89bff1a8dc...b12426ffee
1
components/espasyncota
Submodule
1
components/espasyncota
Submodule
Submodule components/espasyncota added at bbc1f643e2
Submodule components/espchrono updated: 7f8a185678...4d2e9305dc
Submodule components/espcpputils updated: 3a350f1189...78fa43edcf
Submodule components/espwifistack updated: 01189ca833...717d877a44
Submodule components/fmt updated: 4b11c94036...d3c349f69d
@@ -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
|
||||
)
|
||||
|
||||
|
@@ -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<Adafruit_BMP085_Unified::TemperatureAndPressure> values = bmp->getTemperatureAndPressure()) {
|
||||
if (values->temperature && values->pressure) {
|
||||
if (std::optional<Adafruit_BMP085_Unified::TemperatureAndPressure> 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);
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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<sensors_event_t> event = tsl->getEvent()) {
|
||||
if (std::optional<sensors_event_t> 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);
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -102,15 +102,18 @@ namespace {
|
||||
template<typename T>
|
||||
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);
|
||||
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
|
||||
|
@@ -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<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:
|
||||
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());
|
||||
}
|
||||
|
||||
|
49
main/myota.cpp
Normal file
49
main/myota.cpp
Normal 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
19
main/myota.h
Normal 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
|
@@ -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, 10> {
|
||||
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, 10> {
|
||||
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
|
||||
|
@@ -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 += "<a href=\"/on\">on</a><br/>\n"
|
||||
"<a href=\"/off\">off</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)
|
||||
{
|
||||
if (config::enable_dht.value()) {
|
||||
if (lastDhtValue) {
|
||||
if (config::enable_dht.value())
|
||||
{
|
||||
if (lastDhtValue)
|
||||
{
|
||||
body += fmt::format("DHT11 Temperature: {:.1f} C<br/>\n", lastDhtValue->temperature);
|
||||
body += fmt::format("DHT11 Humidity: {:.1f} %<br/>\n", lastDhtValue->humidity);
|
||||
} else
|
||||
}
|
||||
else
|
||||
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)
|
||||
{
|
||||
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<br/>\n", lastTslValue->lux);
|
||||
} else
|
||||
}
|
||||
else
|
||||
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)
|
||||
{
|
||||
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<br/>\n", lastBmpValue->pressure);
|
||||
body += fmt::format("BMP085 Temperature: {:.1f} C<br/>\n", lastBmpValue->temperature);
|
||||
body += fmt::format("BMP085 Altitude: {:.1f} m<br/>\n", lastBmpValue->altitude);
|
||||
} else
|
||||
}
|
||||
else
|
||||
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();
|
||||
body += fmt::format("<tr><th>STA status</th><td>{}</td></tr>\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("<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 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}));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
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 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));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
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"
|
||||
"<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 += "<table border=\"1\">\n"
|
||||
"<thead>\n"
|
||||
@@ -232,7 +253,8 @@ esp_err_t webserver_wifi_display(httpd_req_t *req, std::string &body)
|
||||
"</thead>\n"
|
||||
"<tbody>\n";
|
||||
|
||||
for (const auto &entry : scanResult->entries) {
|
||||
for (const auto &entry : scanResult->entries)
|
||||
{
|
||||
body += fmt::format(
|
||||
"<tr>\n"
|
||||
"<td>{}</td>\n"
|
||||
@@ -254,7 +276,9 @@ esp_err_t webserver_wifi_display(httpd_req_t *req, std::string &body)
|
||||
|
||||
body += "</tbody>\n"
|
||||
"</table>\n";
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (config::enable_mqtt.value()) {
|
||||
if (config::enable_mqtt.value())
|
||||
{
|
||||
body += "<br/>\n"
|
||||
"<h2>MQTT</h2>\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 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 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];
|
||||
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 += "<span style=\"color: green;\">Successfully saved</span>";
|
||||
else
|
||||
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));
|
||||
}
|
||||
} 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("<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];
|
||||
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);
|
||||
|
||||
@@ -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>";
|
||||
else
|
||||
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));
|
||||
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];
|
||||
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 (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)))
|
||||
str += "<span style=\"color: green;\">Successfully saved</span>";
|
||||
else
|
||||
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));
|
||||
}
|
||||
} 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<espchrono:
|
||||
|
||||
{
|
||||
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 (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)))
|
||||
str += "<span style=\"color: green;\">Successfully saved</span>";
|
||||
else
|
||||
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));
|
||||
}
|
||||
} 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
|
||||
"</thead>\n"
|
||||
"<tbody>\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 "<span style=\"color: grey;\">not set</span>";
|
||||
} else
|
||||
}
|
||||
else
|
||||
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)
|
||||
{
|
||||
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!")
|
||||
}
|
||||
|
Reference in New Issue
Block a user