Webserver
This commit is contained in:
parent
da30730029
commit
f34eb810da
@ -2,6 +2,7 @@
|
|||||||
#include "driver/i2c_master.h"
|
#include "driver/i2c_master.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_lcd_touch_gt911.h"
|
#include "esp_lcd_touch_gt911.h"
|
||||||
|
#include "WidgetManager.hpp"
|
||||||
|
|
||||||
// Common display resolutions, used for touch dimensions
|
// Common display resolutions, used for touch dimensions
|
||||||
#define LCD_H_RES 800
|
#define LCD_H_RES 800
|
||||||
@ -75,6 +76,7 @@ void Touch::lv_indev_read_cb(lv_indev_t *indev, lv_indev_data_t *data)
|
|||||||
data->point.x = x[0];
|
data->point.x = x[0];
|
||||||
data->point.y = y[0];
|
data->point.y = y[0];
|
||||||
data->state = LV_INDEV_STATE_PRESSED;
|
data->state = LV_INDEV_STATE_PRESSED;
|
||||||
|
WidgetManager::instance().onUserActivity();
|
||||||
} else {
|
} else {
|
||||||
data->state = LV_INDEV_STATE_RELEASED;
|
data->state = LV_INDEV_STATE_RELEASED;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,14 +6,28 @@
|
|||||||
|
|
||||||
// Maximum number of widgets
|
// Maximum number of widgets
|
||||||
static constexpr size_t MAX_WIDGETS = 32;
|
static constexpr size_t MAX_WIDGETS = 32;
|
||||||
|
static constexpr size_t MAX_SCREENS = 8;
|
||||||
static constexpr size_t MAX_TEXT_LEN = 32;
|
static constexpr size_t MAX_TEXT_LEN = 32;
|
||||||
|
static constexpr size_t MAX_SCREEN_NAME_LEN = 24;
|
||||||
|
|
||||||
enum class WidgetType : uint8_t {
|
enum class WidgetType : uint8_t {
|
||||||
LABEL = 0,
|
LABEL = 0,
|
||||||
BUTTON = 1,
|
BUTTON = 1,
|
||||||
|
LED = 2,
|
||||||
// Future: GAUGE, IMAGE, ARC, etc.
|
// Future: GAUGE, IMAGE, ARC, etc.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ScreenMode : uint8_t {
|
||||||
|
FULLSCREEN = 0,
|
||||||
|
MODAL = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ButtonAction : uint8_t {
|
||||||
|
KNX = 0,
|
||||||
|
JUMP = 1,
|
||||||
|
BACK = 2,
|
||||||
|
};
|
||||||
|
|
||||||
// Text source: static text or KNX group address
|
// Text source: static text or KNX group address
|
||||||
enum class TextSource : uint8_t {
|
enum class TextSource : uint8_t {
|
||||||
STATIC = 0, // Static text
|
STATIC = 0, // Static text
|
||||||
@ -77,9 +91,11 @@ struct WidgetConfig {
|
|||||||
// Button specific
|
// Button specific
|
||||||
bool isToggle; // For buttons: toggle mode
|
bool isToggle; // For buttons: toggle mode
|
||||||
uint16_t knxAddressWrite; // KNX address to write on click
|
uint16_t knxAddressWrite; // KNX address to write on click
|
||||||
|
ButtonAction action; // Button action (KNX, Jump, Back)
|
||||||
|
uint8_t targetScreen; // Target screen ID for jump
|
||||||
|
|
||||||
// Serialization size (fixed for NVS storage)
|
// Serialization size (fixed for NVS storage)
|
||||||
static constexpr size_t SERIALIZED_SIZE = 64;
|
static constexpr size_t SERIALIZED_SIZE = 68;
|
||||||
|
|
||||||
void serialize(uint8_t* buf) const;
|
void serialize(uint8_t* buf) const;
|
||||||
void deserialize(const uint8_t* buf);
|
void deserialize(const uint8_t* buf);
|
||||||
@ -98,13 +114,29 @@ struct WidgetConfig {
|
|||||||
|
|
||||||
// Screen configuration (holds all widgets)
|
// Screen configuration (holds all widgets)
|
||||||
struct ScreenConfig {
|
struct ScreenConfig {
|
||||||
|
uint8_t id;
|
||||||
|
char name[MAX_SCREEN_NAME_LEN];
|
||||||
|
ScreenMode mode;
|
||||||
Color backgroundColor;
|
Color backgroundColor;
|
||||||
uint8_t widgetCount;
|
uint8_t widgetCount;
|
||||||
WidgetConfig widgets[MAX_WIDGETS];
|
WidgetConfig widgets[MAX_WIDGETS];
|
||||||
|
|
||||||
void clear();
|
void clear(uint8_t newId = 0, const char* newName = nullptr);
|
||||||
int addWidget(const WidgetConfig& widget); // Returns widget ID or -1
|
int addWidget(const WidgetConfig& widget); // Returns widget ID or -1
|
||||||
bool removeWidget(uint8_t id);
|
bool removeWidget(uint8_t id);
|
||||||
WidgetConfig* findWidget(uint8_t id);
|
WidgetConfig* findWidget(uint8_t id);
|
||||||
const WidgetConfig* findWidget(uint8_t id) const;
|
const WidgetConfig* findWidget(uint8_t id) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GuiConfig {
|
||||||
|
uint8_t screenCount;
|
||||||
|
ScreenConfig screens[MAX_SCREENS];
|
||||||
|
uint8_t startScreenId;
|
||||||
|
bool standbyEnabled;
|
||||||
|
uint8_t standbyScreenId;
|
||||||
|
uint16_t standbyMinutes;
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
ScreenConfig* findScreen(uint8_t id);
|
||||||
|
const ScreenConfig* findScreen(uint8_t id) const;
|
||||||
|
};
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -27,14 +27,24 @@ public:
|
|||||||
// Reset to factory defaults
|
// Reset to factory defaults
|
||||||
void resetToDefaults();
|
void resetToDefaults();
|
||||||
|
|
||||||
|
// Periodic tasks (standby handling)
|
||||||
|
void loop();
|
||||||
|
|
||||||
|
// User activity (resets standby timer)
|
||||||
|
void onUserActivity();
|
||||||
|
|
||||||
// KNX value update (called from KnxWorker)
|
// KNX value update (called from KnxWorker)
|
||||||
void onKnxValue(uint16_t groupAddr, float value);
|
void onKnxValue(uint16_t groupAddr, float value);
|
||||||
void onKnxSwitch(uint16_t groupAddr, bool value);
|
void onKnxSwitch(uint16_t groupAddr, bool value);
|
||||||
void onKnxText(uint16_t groupAddr, const char* text);
|
void onKnxText(uint16_t groupAddr, const char* text);
|
||||||
|
|
||||||
|
// Button action handler
|
||||||
|
void handleButtonAction(const WidgetConfig& cfg, lv_obj_t* target);
|
||||||
|
void goBack();
|
||||||
|
|
||||||
// Direct config access
|
// Direct config access
|
||||||
ScreenConfig& getConfig() { return config_; }
|
GuiConfig& getConfig() { return config_; }
|
||||||
const ScreenConfig& getConfig() const { return config_; }
|
const GuiConfig& getConfig() const { return config_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WidgetManager();
|
WidgetManager();
|
||||||
@ -45,18 +55,38 @@ private:
|
|||||||
void loadFromSdCard();
|
void loadFromSdCard();
|
||||||
void saveToSdCard();
|
void saveToSdCard();
|
||||||
void destroyAllWidgets();
|
void destroyAllWidgets();
|
||||||
void createAllWidgets();
|
void createAllWidgets(const ScreenConfig& screen, lv_obj_t* parent);
|
||||||
lv_obj_t* createWidget(const WidgetConfig& cfg);
|
lv_obj_t* createWidget(const WidgetConfig& cfg, lv_obj_t* parent);
|
||||||
void applyStyle(lv_obj_t* obj, const WidgetConfig& cfg);
|
void applyStyle(lv_obj_t* obj, const WidgetConfig& cfg);
|
||||||
|
void applyLedStyle(lv_obj_t* obj, const WidgetConfig& cfg);
|
||||||
const lv_font_t* getFontBySize(uint8_t sizeIndex);
|
const lv_font_t* getFontBySize(uint8_t sizeIndex);
|
||||||
|
|
||||||
void createDefaultConfig();
|
void createDefaultConfig();
|
||||||
|
void applyScreen(uint8_t screenId);
|
||||||
|
void showScreen(uint8_t screenId);
|
||||||
|
void showModalScreen(const ScreenConfig& screen);
|
||||||
|
void closeModal();
|
||||||
|
void enterStandby();
|
||||||
|
ScreenConfig* activeScreen();
|
||||||
|
const ScreenConfig* activeScreen() const;
|
||||||
|
|
||||||
static constexpr const char* CONFIG_FILE = "/sdcard/lvgl.json";
|
static constexpr const char* CONFIG_FILE = "/sdcard/lvgl.json";
|
||||||
|
|
||||||
ScreenConfig config_;
|
GuiConfig config_;
|
||||||
|
uint8_t activeScreenId_ = 0;
|
||||||
|
uint8_t previousScreenId_ = 0xFF;
|
||||||
|
uint8_t standbyReturnScreenId_ = 0xFF;
|
||||||
|
uint8_t modalScreenId_ = 0xFF;
|
||||||
|
bool standbyActive_ = false;
|
||||||
|
bool standbyWakePending_ = false;
|
||||||
|
uint8_t standbyWakeTarget_ = 0xFF;
|
||||||
|
bool navPending_ = false;
|
||||||
|
ButtonAction navAction_ = ButtonAction::KNX;
|
||||||
|
uint8_t navTargetScreen_ = 0xFF;
|
||||||
|
int64_t lastActivityUs_ = 0;
|
||||||
|
|
||||||
// Runtime widget references (indexed by widget ID)
|
// Runtime widget references (indexed by widget ID)
|
||||||
std::array<lv_obj_t*, MAX_WIDGETS> widgetObjects_;
|
std::array<lv_obj_t*, MAX_WIDGETS> widgetObjects_;
|
||||||
lv_obj_t* screen_ = nullptr;
|
lv_obj_t* screen_ = nullptr;
|
||||||
|
lv_obj_t* modalContainer_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
#include "Display.hpp"
|
#include "Display.hpp"
|
||||||
#include "Touch.hpp"
|
#include "Touch.hpp"
|
||||||
#include "Gui.hpp"
|
#include "Gui.hpp"
|
||||||
|
#include "WidgetManager.hpp"
|
||||||
#include "Nvs.hpp"
|
#include "Nvs.hpp"
|
||||||
#include "KnxWorker.hpp"
|
#include "KnxWorker.hpp"
|
||||||
#include "Wifi.hpp"
|
#include "Wifi.hpp"
|
||||||
@ -72,6 +73,7 @@ public:
|
|||||||
while (true) {
|
while (true) {
|
||||||
vTaskDelay(pdMS_TO_TICKS(10));
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
knxWorker.loop();
|
knxWorker.loop();
|
||||||
|
WidgetManager::instance().loop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,13 +6,13 @@
|
|||||||
static const char* TAG = "WebServer";
|
static const char* TAG = "WebServer";
|
||||||
|
|
||||||
esp_err_t WebServer::getConfigHandler(httpd_req_t* req) {
|
esp_err_t WebServer::getConfigHandler(httpd_req_t* req) {
|
||||||
char* buf = new char[8192];
|
char* buf = new char[32768];
|
||||||
if (buf == nullptr) {
|
if (buf == nullptr) {
|
||||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Out of memory");
|
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Out of memory");
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
WidgetManager::instance().getConfigJson(buf, 8192);
|
WidgetManager::instance().getConfigJson(buf, 32768);
|
||||||
|
|
||||||
httpd_resp_set_type(req, "application/json");
|
httpd_resp_set_type(req, "application/json");
|
||||||
httpd_resp_send(req, buf, strlen(buf));
|
httpd_resp_send(req, buf, strlen(buf));
|
||||||
@ -23,7 +23,7 @@ esp_err_t WebServer::getConfigHandler(httpd_req_t* req) {
|
|||||||
|
|
||||||
esp_err_t WebServer::postConfigHandler(httpd_req_t* req) {
|
esp_err_t WebServer::postConfigHandler(httpd_req_t* req) {
|
||||||
int total_len = req->content_len;
|
int total_len = req->content_len;
|
||||||
if (total_len > 8192) {
|
if (total_len > 32768) {
|
||||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Content too large");
|
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Content too large");
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user