lots of stability improvements

This commit is contained in:
2021-09-19 02:51:16 +02:00
parent 2992cbb613
commit d6217492c7
11 changed files with 145 additions and 33 deletions

View File

@ -148,6 +148,7 @@ set(headers
utils.h utils.h
webserver.h webserver.h
webserver_displaycontrol.h webserver_displaycontrol.h
webserver_lock.h
webserver_ota.h webserver_ota.h
webserver_settings.h webserver_settings.h
webserver_stringsettings.h webserver_stringsettings.h

View File

@ -31,14 +31,14 @@ class InputDispatcher
public: public:
static void update() static void update()
{ {
if (upPressedSince && espchrono::ago(*upPressedSince) > (upPressRepeat > 3 ? 100ms : 500ms)) if (upPressedSince && espchrono::ago(*upPressedSince) > (upPressRepeat > 2 ? 50ms : 400ms))
{ {
upPressedSince = espchrono::millis_clock::now(); upPressedSince = espchrono::millis_clock::now();
upPressRepeat++; upPressRepeat++;
rotated -= 1; rotated -= 1;
} }
if (downPressedSince && espchrono::ago(*downPressedSince) > (downPressRepeat > 3 ? 100ms : 500ms)) if (downPressedSince && espchrono::ago(*downPressedSince) > (downPressRepeat > 2 ? 50ms : 400ms))
{ {
downPressedSince = espchrono::millis_clock::now(); downPressedSince = espchrono::millis_clock::now();
downPressRepeat++; downPressRepeat++;

View File

@ -6,6 +6,7 @@
// 3rdparty lib includes // 3rdparty lib includes
#include <wrappers/websocket_client.h> #include <wrappers/websocket_client.h>
#include <espwifistack.h> #include <espwifistack.h>
#include <esphttpdutils.h>
// local includes // local includes
#include "globals.h" #include "globals.h"
@ -23,7 +24,9 @@ void startCloud();
void initCloud() void initCloud()
{ {
if (settings.cloudSettings.cloudEnabled) if (settings.cloudSettings.cloudEnabled &&
!stringSettings.cloudUrl.empty() &&
esphttpdutils::urlverify(stringSettings.cloudUrl))
{ {
createCloud(); createCloud();
if (!cloudClient) if (!cloudClient)
@ -38,7 +41,9 @@ void initCloud()
void handleCloud() void handleCloud()
{ {
if (settings.cloudSettings.cloudEnabled) if (settings.cloudSettings.cloudEnabled &&
!stringSettings.cloudUrl.empty() &&
esphttpdutils::urlverify(stringSettings.cloudUrl))
{ {
if (!cloudClient) if (!cloudClient)
{ {

View File

@ -100,7 +100,7 @@ private:
Label m_labelWifiStatus{35, bottomLines[0]}; // 120, 15 Label m_labelWifiStatus{35, bottomLines[0]}; // 120, 15
Label m_labelLimit0{205, bottomLines[0]}; // 35, 15 Label m_labelLimit0{205, bottomLines[0]}; // 35, 15
Label m_labelIpAddress{25, bottomLines[1]}; // 130, 15 Label m_labelIpAddress{25, bottomLines[1]}; // 130, 15
Label m_labelSignal{120, bottomLines[1]}; // 130, 15 Label m_labelSignal{125, bottomLines[1]}; // 130, 15
Label m_labelLimit1{205, bottomLines[1]}; // 35, 15 Label m_labelLimit1{205, bottomLines[1]}; // 35, 15
Label m_labelPerformance{40, bottomLines[2]}; // 40, 15 Label m_labelPerformance{40, bottomLines[2]}; // 40, 15
Label m_labelFreeMem{70, bottomLines[2]}; // 40, 15 Label m_labelFreeMem{70, bottomLines[2]}; // 40, 15
@ -132,12 +132,12 @@ void StatusDisplay::initScreen()
tft.setTextFont(2); tft.setTextFont(2);
tft.drawString("WiFi:", 0, bottomLines[0]); tft.drawString("WiFi:", 0, bottomLines[0]);
m_labelWifiStatus.start(); m_labelWifiStatus.start();
tft.drawString("Limit0:", 160, bottomLines[0]); tft.drawString("Lim0:", 173, bottomLines[0]);
m_labelLimit0.start(); m_labelLimit0.start();
tft.drawString("IP:", 0, bottomLines[1]); tft.drawString("IP:", 0, bottomLines[1]);
m_labelIpAddress.start(); m_labelIpAddress.start();
m_labelSignal.start(); m_labelSignal.start();
tft.drawString("Limit1:", 160, bottomLines[1]); tft.drawString("Lim1:", 173, bottomLines[1]);
m_labelLimit1.start(); m_labelLimit1.start();
tft.drawString("Perf:", 0, bottomLines[2]); tft.drawString("Perf:", 0, bottomLines[2]);
m_labelPerformance.start(); m_labelPerformance.start();

View File

@ -168,7 +168,7 @@ constexpr Settings::BoardcomputerHardware defaultBoardcomputerHardware {
#ifdef FEATURE_CLOUD #ifdef FEATURE_CLOUD
constexpr Settings::CloudSettings defaultCloudSettings { constexpr Settings::CloudSettings defaultCloudSettings {
.cloudEnabled = true, .cloudEnabled = false,
.cloudTransmitTimeout = 10 .cloudTransmitTimeout = 10
}; };
#endif #endif

View File

@ -15,6 +15,7 @@
#include <esphttpdutils.h> #include <esphttpdutils.h>
// local includes // local includes
#include "webserver_lock.h"
#include "webserver_displaycontrol.h" #include "webserver_displaycontrol.h"
#ifdef FEATURE_OTA #ifdef FEATURE_OTA
#include "webserver_ota.h" #include "webserver_ota.h"
@ -26,8 +27,6 @@
namespace { namespace {
httpd_handle_t httpdHandle; httpd_handle_t httpdHandle;
std::atomic<bool> shouldReboot;
void initWebserver(); void initWebserver();
void handleWebserver(); void handleWebserver();
esp_err_t webserver_reboot_handler(httpd_req_t *req); esp_err_t webserver_reboot_handler(httpd_req_t *req);
@ -36,7 +35,8 @@ esp_err_t webserver_reboot_handler(httpd_req_t *req);
namespace { namespace {
void initWebserver() void initWebserver()
{ {
shouldReboot = false; webserver_lock.construct();
webserver_lock->take(portMAX_DELAY);
{ {
httpd_config_t httpConfig HTTPD_DEFAULT_CONFIG(); httpd_config_t httpConfig HTTPD_DEFAULT_CONFIG();
@ -74,16 +74,13 @@ void initWebserver()
void handleWebserver() void handleWebserver()
{ {
if (shouldReboot) webserver_lock->give();
{ webserver_lock->take(portMAX_DELAY);
shouldReboot = false;
esp_restart();
}
} }
esp_err_t webserver_reboot_handler(httpd_req_t *req) esp_err_t webserver_reboot_handler(httpd_req_t *req)
{ {
shouldReboot = true; esp_restart();
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::Ok, "text/plain", "REBOOT called...") CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::Ok, "text/plain", "REBOOT called...")
} }

View File

@ -15,10 +15,13 @@
#include <textinterface.h> #include <textinterface.h>
#include <menudisplay.h> #include <menudisplay.h>
#include <changevaluedisplay.h> #include <changevaluedisplay.h>
#include <lockhelper.h>
#include <tickchrono.h>
// local includes // local includes
#include "buttons.h" #include "buttons.h"
#include "globals.h" #include "globals.h"
#include "webserver_lock.h"
#ifdef FEATURE_WEBSERVER #ifdef FEATURE_WEBSERVER
namespace { namespace {
@ -33,6 +36,14 @@ using esphttpdutils::HtmlTag;
namespace { namespace {
esp_err_t webserver_root_handler(httpd_req_t *req) esp_err_t webserver_root_handler(httpd_req_t *req)
{ {
espcpputils::LockHelper helper{webserver_lock->handle, std::chrono::ceil<espcpputils::ticks>(5s).count()};
if (!helper.locked())
{
constexpr const std::string_view msg = "could not lock webserver_lock";
ESP_LOGE(TAG, "%.*s", msg.size(), msg.data());
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
}
std::string body; std::string body;
{ {
@ -125,6 +136,14 @@ esp_err_t webserver_root_handler(httpd_req_t *req)
esp_err_t webserver_triggerButton_handler(httpd_req_t *req) esp_err_t webserver_triggerButton_handler(httpd_req_t *req)
{ {
espcpputils::LockHelper helper{webserver_lock->handle, std::chrono::ceil<espcpputils::ticks>(5s).count()};
if (!helper.locked())
{
constexpr const std::string_view msg = "could not lock webserver_lock";
ESP_LOGE(TAG, "%.*s", msg.size(), msg.data());
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
}
std::string query; std::string query;
if (auto result = esphttpdutils::webserver_get_query(req)) if (auto result = esphttpdutils::webserver_get_query(req))
query = *result; query = *result;
@ -233,6 +252,14 @@ esp_err_t webserver_triggerButton_handler(httpd_req_t *req)
esp_err_t webserver_triggerItem_handler(httpd_req_t *req) esp_err_t webserver_triggerItem_handler(httpd_req_t *req)
{ {
espcpputils::LockHelper helper{webserver_lock->handle, std::chrono::ceil<espcpputils::ticks>(5s).count()};
if (!helper.locked())
{
constexpr const std::string_view msg = "could not lock webserver_lock";
ESP_LOGE(TAG, "%.*s", msg.size(), msg.data());
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
}
std::string query; std::string query;
if (auto result = esphttpdutils::webserver_get_query(req)) if (auto result = esphttpdutils::webserver_get_query(req))
query = *result; query = *result;
@ -311,6 +338,14 @@ esp_err_t webserver_triggerItem_handler(httpd_req_t *req)
esp_err_t webserver_setValue_handler(httpd_req_t *req) esp_err_t webserver_setValue_handler(httpd_req_t *req)
{ {
espcpputils::LockHelper helper{webserver_lock->handle, std::chrono::ceil<espcpputils::ticks>(5s).count()};
if (!helper.locked())
{
constexpr const std::string_view msg = "could not lock webserver_lock";
ESP_LOGE(TAG, "%.*s", msg.size(), msg.data());
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
}
std::string query; std::string query;
if (auto result = esphttpdutils::webserver_get_query(req)) if (auto result = esphttpdutils::webserver_get_query(req))
query = *result; query = *result;

11
main/webserver_lock.h Normal file
View File

@ -0,0 +1,11 @@
#pragma once
// 3rdparty lib includes
#include <delayedconstruction.h>
#include <wrappers/mutex_semaphore.h>
namespace {
cpputils::DelayedConstruction<espcpputils::mutex_semaphore> webserver_lock;
} // namespace

View File

@ -11,11 +11,14 @@
#include <fmt/core.h> #include <fmt/core.h>
#include <espcppmacros.h> #include <espcppmacros.h>
#include <esphttpdutils.h> #include <esphttpdutils.h>
#include <lockhelper.h>
#include <tickchrono.h>
// local includes // local includes
#ifdef FEATURE_OTA #ifdef FEATURE_OTA
#include "ota.h" #include "ota.h"
#endif #endif
#include "webserver_lock.h"
#if defined(FEATURE_WEBSERVER) && defined(FEATURE_OTA) #if defined(FEATURE_WEBSERVER) && defined(FEATURE_OTA)
namespace { namespace {
@ -28,6 +31,14 @@ using esphttpdutils::HtmlTag;
namespace { namespace {
esp_err_t webserver_ota_handler(httpd_req_t *req) esp_err_t webserver_ota_handler(httpd_req_t *req)
{ {
espcpputils::LockHelper helper{webserver_lock->handle, std::chrono::ceil<espcpputils::ticks>(5s).count()};
if (!helper.locked())
{
constexpr const std::string_view msg = "could not lock webserver_lock";
ESP_LOGE(TAG, "%.*s", msg.size(), msg.data());
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
}
std::string body; std::string body;
{ {
@ -208,6 +219,14 @@ esp_err_t webserver_ota_handler(httpd_req_t *req)
esp_err_t webserver_trigger_ota_handler(httpd_req_t *req) esp_err_t webserver_trigger_ota_handler(httpd_req_t *req)
{ {
espcpputils::LockHelper helper{webserver_lock->handle, std::chrono::ceil<espcpputils::ticks>(5s).count()};
if (!helper.locked())
{
constexpr const std::string_view msg = "could not lock webserver_lock";
ESP_LOGE(TAG, "%.*s", msg.size(), msg.data());
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
}
std::string query; std::string query;
if (auto result = esphttpdutils::webserver_get_query(req)) if (auto result = esphttpdutils::webserver_get_query(req))
query = *result; query = *result;

View File

@ -15,9 +15,12 @@
#include <espcppmacros.h> #include <espcppmacros.h>
#include <esphttpdutils.h> #include <esphttpdutils.h>
#include <numberparsing.h> #include <numberparsing.h>
#include <lockhelper.h>
#include <tickchrono.h>
// local includes // local includes
#include "globals.h" #include "globals.h"
#include "webserver_lock.h"
#ifdef FEATURE_WEBSERVER #ifdef FEATURE_WEBSERVER
namespace { namespace {
@ -41,11 +44,11 @@ template<typename T>
typename std::enable_if<std::is_same<T, bool>::value, bool>::type typename std::enable_if<std::is_same<T, bool>::value, bool>::type
showInputForSetting(std::string_view key, T value, std::string &body) showInputForSetting(std::string_view key, T value, std::string &body)
{ {
body += fmt::format("<input type=\"hidden\" name=\"{}\" value=\"false\" />" body += fmt::format("<input type=\"checkbox\" name=\"{}\" value=\"true\" {}/>"
"<input type=\"checkbox\" name=\"{}\" value=\"true\" {}/>", "<input type=\"hidden\" name=\"{}\" value=\"false\" />",
esphttpdutils::htmlentities(key), esphttpdutils::htmlentities(key),
esphttpdutils::htmlentities(key), value ? "checked " : "",
value ? "checked " : ""); esphttpdutils::htmlentities(key));
return true; return true;
} }
@ -63,6 +66,14 @@ showInputForSetting(std::string_view key, T value, std::string &body)
esp_err_t webserver_settings_handler(httpd_req_t *req) esp_err_t webserver_settings_handler(httpd_req_t *req)
{ {
espcpputils::LockHelper helper{webserver_lock->handle, std::chrono::ceil<espcpputils::ticks>(5s).count()};
if (!helper.locked())
{
constexpr const std::string_view msg = "could not lock webserver_lock";
ESP_LOGE(TAG, "%.*s", msg.size(), msg.data());
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
}
std::string body; std::string body;
{ {
@ -190,6 +201,14 @@ saveSetting(T &value, std::string_view newValue, std::string &body)
esp_err_t webserver_saveSettings_handler(httpd_req_t *req) esp_err_t webserver_saveSettings_handler(httpd_req_t *req)
{ {
espcpputils::LockHelper helper{webserver_lock->handle, std::chrono::ceil<espcpputils::ticks>(5s).count()};
if (!helper.locked())
{
constexpr const std::string_view msg = "could not lock webserver_lock";
ESP_LOGE(TAG, "%.*s", msg.size(), msg.data());
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
}
std::string query; std::string query;
if (auto result = esphttpdutils::webserver_get_query(req)) if (auto result = esphttpdutils::webserver_get_query(req))
query = *result; query = *result;
@ -204,13 +223,16 @@ esp_err_t webserver_saveSettings_handler(httpd_req_t *req)
settings.executeForEveryCommonSetting([&](std::string_view key, auto &value){ settings.executeForEveryCommonSetting([&](std::string_view key, auto &value){
char valueBufEncoded[256]; char valueBufEncoded[256];
if (const auto result = httpd_query_key_value(query.data(), key.data(), valueBufEncoded, 256); result != ESP_OK && result != ESP_ERR_NOT_FOUND) if (const auto result = httpd_query_key_value(query.data(), key.data(), valueBufEncoded, 256); result != ESP_OK)
{ {
const auto msg = fmt::format("{}: httpd_query_key_value() failed with {}", key, esp_err_to_name(result)); if (result != ESP_ERR_NOT_FOUND)
ESP_LOGE(TAG, "%.*s", msg.size(), msg.data()); {
body += msg; const auto msg = fmt::format("{}: httpd_query_key_value() failed with {}", key, esp_err_to_name(result));
body += '\n'; ESP_LOGE(TAG, "%.*s", msg.size(), msg.data());
success = false; body += msg;
body += '\n';
success = false;
}
return; return;
} }

View File

@ -11,9 +11,12 @@
#include <fmt/core.h> #include <fmt/core.h>
#include <espcppmacros.h> #include <espcppmacros.h>
#include <esphttpdutils.h> #include <esphttpdutils.h>
#include <lockhelper.h>
#include <tickchrono.h>
// local includes // local includes
#include "globals.h" #include "globals.h"
#include "webserver_lock.h"
#ifdef FEATURE_WEBSERVER #ifdef FEATURE_WEBSERVER
namespace { namespace {
@ -26,6 +29,14 @@ using esphttpdutils::HtmlTag;
namespace { namespace {
esp_err_t webserver_stringSettings_handler(httpd_req_t *req) esp_err_t webserver_stringSettings_handler(httpd_req_t *req)
{ {
espcpputils::LockHelper helper{webserver_lock->handle, std::chrono::ceil<espcpputils::ticks>(5s).count()};
if (!helper.locked())
{
constexpr const std::string_view msg = "could not lock webserver_lock";
ESP_LOGE(TAG, "%.*s", msg.size(), msg.data());
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
}
std::string body; std::string body;
{ {
@ -107,6 +118,14 @@ esp_err_t webserver_stringSettings_handler(httpd_req_t *req)
esp_err_t webserver_saveStringSettings_handler(httpd_req_t *req) esp_err_t webserver_saveStringSettings_handler(httpd_req_t *req)
{ {
espcpputils::LockHelper helper{webserver_lock->handle, std::chrono::ceil<espcpputils::ticks>(5s).count()};
if (!helper.locked())
{
constexpr const std::string_view msg = "could not lock webserver_lock";
ESP_LOGE(TAG, "%.*s", msg.size(), msg.data());
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
}
std::string query; std::string query;
if (auto result = esphttpdutils::webserver_get_query(req)) if (auto result = esphttpdutils::webserver_get_query(req))
query = *result; query = *result;
@ -121,13 +140,16 @@ esp_err_t webserver_saveStringSettings_handler(httpd_req_t *req)
stringSettings.executeForEveryCommonSetting([&](std::string_view key, auto &value){ stringSettings.executeForEveryCommonSetting([&](std::string_view key, auto &value){
char valueBufEncoded[256]; char valueBufEncoded[256];
if (const auto result = httpd_query_key_value(query.data(), key.data(), valueBufEncoded, 256); result != ESP_OK && result != ESP_ERR_NOT_FOUND) if (const auto result = httpd_query_key_value(query.data(), key.data(), valueBufEncoded, 256); result != ESP_OK)
{ {
const auto msg = fmt::format("{}: httpd_query_key_value() failed with {}", key, esp_err_to_name(result)); if (result != ESP_ERR_NOT_FOUND)
ESP_LOGE(TAG, "%.*s", msg.size(), msg.data()); {
body += msg; const auto msg = fmt::format("{}: httpd_query_key_value() failed with {}", key, esp_err_to_name(result));
body += '\n'; ESP_LOGE(TAG, "%.*s", msg.size(), msg.data());
success = false; body += msg;
body += '\n';
success = false;
}
return; return;
} }