Fixes
This commit is contained in:
parent
631d1eb250
commit
87e8deab0e
1
.gitignore
vendored
1
.gitignore
vendored
@ -30,7 +30,6 @@ build/
|
||||
*.map
|
||||
flasher_args.json # Generated in build directory
|
||||
sdkconfig.old
|
||||
sdkconfig
|
||||
|
||||
# ESP-IDF dependencies
|
||||
# For older versions or manual component management
|
||||
|
||||
@ -1,190 +1,77 @@
|
||||
dependencies:
|
||||
espressif/button:
|
||||
component_hash:
|
||||
fccb18c37f1cfe0797b74a53a44d3f400f5fd01f4993b40052dfb7f401915089
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: '*'
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.0'
|
||||
dependencies: []
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
path:
|
||||
/home/thomas/projekte/test1/knxdisplay/managed_components/espressif__button
|
||||
type: local
|
||||
version: 4.1.5
|
||||
espressif/cmake_utilities:
|
||||
component_hash:
|
||||
351350613ceafba240b761b4ea991e0f231ac7a9f59a9ee901f751bddc0bb18f
|
||||
05165f30922b422b4b90c08845e6d449329b97370fbd06309803d8cb539d79e3
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.1'
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 0.5.3
|
||||
version: 1.1.1
|
||||
espressif/eppp_link:
|
||||
component_hash:
|
||||
9472e6825f4bb71eca2b39cf1bc92659c1ac60bfd7416560ad033a7dd8641b17
|
||||
dependencies:
|
||||
- name: espressif/esp_serial_slave_link
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: ^1.1.0
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.2'
|
||||
dependencies: []
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
path:
|
||||
/home/thomas/projekte/test1/knxdisplay/managed_components/espressif__eppp_link
|
||||
type: local
|
||||
version: 1.1.4
|
||||
espressif/esp_hosted:
|
||||
component_hash:
|
||||
49424510d8cf3659aa4bcf787e7b4abbf11848a25e7e5f133cf7f3324860d066
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.3'
|
||||
dependencies: []
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
version: 2.11.3
|
||||
path:
|
||||
/home/thomas/projekte/test1/knxdisplay/managed_components/espressif__esp_hosted
|
||||
type: local
|
||||
version: 2.11.5
|
||||
espressif/esp_lcd_touch:
|
||||
component_hash:
|
||||
3f85a7d95af876f1a6ecca8eb90a81614890d0f03a038390804e5a77e2caf862
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4.2'
|
||||
dependencies: []
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
path:
|
||||
/home/thomas/projekte/test1/knxdisplay/managed_components/espressif__esp_lcd_touch
|
||||
type: local
|
||||
version: 1.2.1
|
||||
espressif/esp_lcd_touch_gt911:
|
||||
component_hash:
|
||||
be02e243d18b9a661bc13b0d22c0a5cfa3f708cf04d6eb059772276c8c8a4d76
|
||||
dependencies:
|
||||
- name: espressif/esp_lcd_touch
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: ^1.2.0
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4.2'
|
||||
dependencies: []
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
path:
|
||||
/home/thomas/projekte/test1/knxdisplay/managed_components/espressif__esp_lcd_touch_gt911
|
||||
type: local
|
||||
version: 1.2.0~1
|
||||
espressif/esp_lv_decoder:
|
||||
component_hash:
|
||||
0eb7b2bceaf73484ef80f5004337ee31617b2450a3d40621812998a47e7dd349
|
||||
dependencies:
|
||||
- name: espressif/esp_new_jpeg
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: espressif/libpng
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 1.*
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.3'
|
||||
- name: lvgl/lvgl
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: '>=8,<10'
|
||||
dependencies: []
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
targets:
|
||||
- esp32
|
||||
- esp32s2
|
||||
- esp32s3
|
||||
- esp32p4
|
||||
- esp32c2
|
||||
- esp32c3
|
||||
- esp32c5
|
||||
- esp32c6
|
||||
path:
|
||||
/home/thomas/projekte/test1/knxdisplay/managed_components/espressif__esp_lv_decoder
|
||||
type: local
|
||||
version: 0.3.2
|
||||
espressif/esp_lv_fs:
|
||||
component_hash:
|
||||
66896007884b817df34c964f9a114fff538ee2674e99fee7159162498b93f94b
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: espressif/esp_mmap_assets
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: '>=1.2'
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4'
|
||||
- name: lvgl/lvgl
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: '>=8,<10'
|
||||
dependencies: []
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
path:
|
||||
/home/thomas/projekte/test1/knxdisplay/managed_components/espressif__esp_lv_fs
|
||||
type: local
|
||||
version: 1.0.1
|
||||
espressif/esp_lvgl_adapter:
|
||||
component_hash:
|
||||
4ba6ad754b2533cb582bff81ba672ea7a682f4724a02327e57f96e9c73d330c2
|
||||
dependencies:
|
||||
- name: espressif/button
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: 4.*
|
||||
- name: espressif/esp_lcd_touch
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: 1.*
|
||||
- name: espressif/esp_lv_decoder
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: 0.*
|
||||
- name: espressif/esp_lv_fs
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: 1.*
|
||||
- name: espressif/freetype
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: 2.*
|
||||
- name: espressif/knob
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: 1.*
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.5'
|
||||
- name: lvgl/lvgl
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: '>=8,<10'
|
||||
dependencies: []
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
path:
|
||||
/home/thomas/projekte/test1/knxdisplay/managed_components/espressif__esp_lvgl_adapter
|
||||
type: local
|
||||
version: 0.3.0
|
||||
espressif/esp_lvgl_port:
|
||||
component_hash:
|
||||
f872401524cb645ee6ff1c9242d44fb4ddcfd4d37d7be8b9ed3f4e85a404efcd
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.1'
|
||||
- name: lvgl/lvgl
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: '>=8,<10'
|
||||
dependencies: []
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
path:
|
||||
/home/thomas/projekte/test1/knxdisplay/managed_components/espressif__esp_lvgl_port
|
||||
type: local
|
||||
version: 2.7.0
|
||||
espressif/esp_mmap_assets:
|
||||
component_hash:
|
||||
@ -198,7 +85,7 @@ dependencies:
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.4.0
|
||||
espressif/esp_new_jpeg:
|
||||
@ -206,7 +93,7 @@ dependencies:
|
||||
e6af208a875abd0ecfc0213d3751a11b504b463ebde6930f24096047925fa5c1
|
||||
dependencies: []
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
targets:
|
||||
- esp32
|
||||
@ -226,49 +113,15 @@ dependencies:
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.1.2
|
||||
espressif/esp_tinyusb:
|
||||
component_hash:
|
||||
6f1f0c140990bf27a86611e3c1f47f9fa8468bffc3bf1eb6d551cb09f31f8908
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
- name: espressif/tinyusb
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: '>=0.17.0~2'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
targets:
|
||||
- esp32s2
|
||||
- esp32s3
|
||||
- esp32p4
|
||||
- esp32h4
|
||||
version: 2.0.1~1
|
||||
espressif/esp_wifi_remote:
|
||||
component_hash:
|
||||
e5cb66acbf9b3e115dab6b8e1262a5473e7de6e4106d32a2a8ca7384bd21fc00
|
||||
dependencies:
|
||||
- name: espressif/esp_hosted
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
rules:
|
||||
- if: target in [esp32h2, esp32p4]
|
||||
version: '>=2.11'
|
||||
- name: espressif/wifi_remote_over_eppp
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: '>=0.1'
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.3'
|
||||
dependencies: []
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
path:
|
||||
/home/thomas/projekte/test1/knxdisplay/managed_components/espressif__esp_wifi_remote
|
||||
type: local
|
||||
version: 1.3.1
|
||||
espressif/freetype:
|
||||
component_hash:
|
||||
@ -278,23 +131,15 @@ dependencies:
|
||||
require: private
|
||||
version: '>=4.4'
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 2.13.3~1
|
||||
espressif/i2c_bus:
|
||||
component_hash:
|
||||
4e990dc11734316186b489b362c61d41f23f79d58bc169795cec215e528cba14
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: '*'
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.0'
|
||||
dependencies: []
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
path:
|
||||
/home/thomas/projekte/test1/knxdisplay/managed_components/espressif__i2c_bus
|
||||
type: local
|
||||
version: 1.5.0
|
||||
espressif/knob:
|
||||
component_hash:
|
||||
@ -308,7 +153,7 @@ dependencies:
|
||||
require: private
|
||||
version: '>=4.4.1'
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.2
|
||||
espressif/libpng:
|
||||
@ -323,25 +168,9 @@ dependencies:
|
||||
require: private
|
||||
version: ^1.2.13
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.6.54
|
||||
espressif/tinyusb:
|
||||
component_hash:
|
||||
5ea9d3b6d6b0734a0a0b3491967aa0e1bece2974132294dbda5dd2839b247bfa
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
targets:
|
||||
- esp32s2
|
||||
- esp32s3
|
||||
- esp32p4
|
||||
- esp32h4
|
||||
version: 0.19.0~2
|
||||
espressif/wifi_remote_over_eppp:
|
||||
component_hash:
|
||||
e1b4c485ed5afe36615b9b555dfdcbe4be33898dc3732b5bedf235bba45bd286
|
||||
@ -354,7 +183,7 @@ dependencies:
|
||||
require: private
|
||||
version: '>=5.3'
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 0.3.0
|
||||
espressif/zlib:
|
||||
@ -365,7 +194,7 @@ dependencies:
|
||||
require: private
|
||||
version: '>=4.4'
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.3.1
|
||||
idf:
|
||||
@ -377,38 +206,40 @@ dependencies:
|
||||
17e68bfd21f0edf4c3ee838e2273da840bf3930e5dbc3bfa6c1190c3aed41f9f
|
||||
dependencies: []
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 9.4.0
|
||||
waveshare/esp_lcd_jd9365_10_1:
|
||||
component_hash:
|
||||
6c1336b93a37df2b5be42c49c4c364d0bacdbf96f053a934f881349457fac679
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: espressif/i2c_bus
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: ^1.3.0
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.3'
|
||||
dependencies: []
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
targets:
|
||||
- esp32p4
|
||||
path:
|
||||
/home/thomas/projekte/test1/knxdisplay/managed_components/waveshare__esp_lcd_jd9365_10_1
|
||||
type: local
|
||||
version: 1.0.4
|
||||
direct_dependencies:
|
||||
- espressif/button
|
||||
- espressif/cmake_utilities
|
||||
- espressif/eppp_link
|
||||
- espressif/esp_hosted
|
||||
- espressif/esp_lcd_touch
|
||||
- espressif/esp_lcd_touch_gt911
|
||||
- espressif/esp_lv_decoder
|
||||
- espressif/esp_lv_fs
|
||||
- espressif/esp_lvgl_adapter
|
||||
- espressif/esp_lvgl_port
|
||||
- espressif/esp_tinyusb
|
||||
- espressif/esp_mmap_assets
|
||||
- espressif/esp_new_jpeg
|
||||
- espressif/esp_serial_slave_link
|
||||
- espressif/esp_wifi_remote
|
||||
- espressif/freetype
|
||||
- espressif/i2c_bus
|
||||
- espressif/knob
|
||||
- espressif/libpng
|
||||
- espressif/wifi_remote_over_eppp
|
||||
- espressif/zlib
|
||||
- idf
|
||||
- lvgl/lvgl
|
||||
- waveshare/esp_lcd_jd9365_10_1
|
||||
manifest_hash: 4224a9627ef40f4e86cf66ea3d5037d4b4dbfca46c368078b42e6988300c7f2f
|
||||
manifest_hash: ee0446e4a514a791315863af0d77bdcf353d357a7b8081e3e2b252138a66497b
|
||||
target: esp32p4
|
||||
version: 2.0.0
|
||||
|
||||
@ -17,7 +17,7 @@ idf_component_register(SRCS "HistoryStore.cpp" "KnxWorker.cpp" "Nvs.cpp" "main.c
|
||||
"webserver/KnxHandlers.cpp"
|
||||
"webserver/StatusHandlers.cpp"
|
||||
"webserver/FileManagerHandlers.cpp"
|
||||
PRIV_REQUIRES spi_flash esp_driver_ppa esp_lcd usb
|
||||
REQUIRES esp_mm esp_eth esp_driver_ppa esp_timer lvgl knx ethernet_init esp_wifi_remote esp_netif esp_event nvs_flash esp_http_server fatfs sdmmc json tinyusb
|
||||
PRIV_REQUIRES spi_flash esp_driver_ppa esp_lcd
|
||||
REQUIRES esp_mm esp_eth esp_driver_ppa esp_timer lvgl knx ethernet_init esp_wifi_remote esp_netif esp_event nvs_flash esp_http_server fatfs sdmmc json
|
||||
INCLUDE_DIRS "webserver" "widgets"
|
||||
EMBED_TXTFILES "embedded/filemanager.html")
|
||||
|
||||
@ -1,9 +1,14 @@
|
||||
#include "Gui.hpp"
|
||||
#include "esp_lv_adapter.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_system.h"
|
||||
#include "Gui/WifiSetting.hpp"
|
||||
#include "Gui/EthSetting.hpp"
|
||||
#include "WidgetManager.hpp"
|
||||
#include "lvgl.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
KnxWorker Gui::knxWorker; // Define the static member
|
||||
|
||||
|
||||
@ -482,7 +482,6 @@ void HistoryStore::saveToSdCard() {
|
||||
}
|
||||
|
||||
void HistoryStore::loadFromSdCard() {
|
||||
return;
|
||||
if (!SdCard::instance().isMounted()) return;
|
||||
|
||||
FILE* f = fopen(HISTORY_FILE, "rb");
|
||||
|
||||
@ -4,8 +4,6 @@
|
||||
#include "sdmmc_cmd.h"
|
||||
#include "driver/sdmmc_host.h"
|
||||
#include "sd_pwr_ctrl_by_on_chip_ldo.h"
|
||||
#include "tinyusb_default_config.h"
|
||||
#include "tinyusb_msc.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
static const char* TAG = "SdCard";
|
||||
@ -111,67 +109,3 @@ bool SdCard::init() {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SdCard::enableUsbMsc() {
|
||||
if (usbMscActive_) {
|
||||
ESP_LOGW(TAG, "USB MSC already active");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!s_card) {
|
||||
ESP_LOGE(TAG, "SD card not initialized");
|
||||
return false;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Enabling USB Mass Storage mode...");
|
||||
|
||||
// Unmount filesystem first (so PC has exclusive access)
|
||||
if (mounted_) {
|
||||
ESP_LOGI(TAG, "Unmounting SD card from filesystem...");
|
||||
esp_err_t ret = esp_vfs_fat_sdcard_unmount(MOUNT_POINT, s_card);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to unmount SD card: %s", esp_err_to_name(ret));
|
||||
return false;
|
||||
}
|
||||
mounted_ = false;
|
||||
}
|
||||
|
||||
// Initialize TinyUSB
|
||||
ESP_LOGI(TAG, "Initializing TinyUSB...");
|
||||
const tinyusb_config_t cfg = TINYUSB_DEFAULT_CONFIG();
|
||||
esp_err_t ret = tinyusb_driver_install(&cfg);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to install TinyUSB driver: %s", esp_err_to_name(ret));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize MSC storage with SD card
|
||||
ESP_LOGI(TAG, "Initializing USB MSC with SD card...");
|
||||
tinyusb_msc_storage_config_t storage_cfg = {};
|
||||
storage_cfg.medium.card = s_card;
|
||||
storage_cfg.mount_point = TINYUSB_MSC_STORAGE_MOUNT_USB;
|
||||
storage_cfg.fat_fs.base_path = nullptr;
|
||||
storage_cfg.fat_fs.config = VFS_FAT_MOUNT_DEFAULT_CONFIG();
|
||||
storage_cfg.fat_fs.config.max_files = 5;
|
||||
storage_cfg.fat_fs.config.allocation_unit_size = 16 * 1024;
|
||||
storage_cfg.fat_fs.do_not_format = true;
|
||||
storage_cfg.fat_fs.format_flags = 0;
|
||||
|
||||
tinyusb_msc_storage_handle_t storage_hdl = nullptr;
|
||||
ret = tinyusb_msc_new_storage_sdmmc(&storage_cfg, &storage_hdl);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to initialize MSC storage: %s", esp_err_to_name(ret));
|
||||
return false;
|
||||
}
|
||||
if (storage_hdl == nullptr) {
|
||||
ESP_LOGE(TAG, "MSC storage handle not initialized");
|
||||
return false;
|
||||
}
|
||||
|
||||
usbMscActive_ = true;
|
||||
ESP_LOGI(TAG, "USB Mass Storage mode enabled!");
|
||||
ESP_LOGI(TAG, "Connect USB cable to access SD card from PC.");
|
||||
ESP_LOGI(TAG, "Reboot device to return to normal mode.");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -5,11 +5,6 @@ public:
|
||||
static SdCard& instance();
|
||||
bool init();
|
||||
bool isMounted() const { return mounted_; }
|
||||
bool isUsbMscActive() const { return usbMscActive_; }
|
||||
|
||||
// Enable USB Mass Storage mode (unmounts SD from ESP, exposes via USB)
|
||||
// Returns true if successful. Requires reboot to return to normal mode.
|
||||
bool enableUsbMsc();
|
||||
|
||||
static constexpr const char* MOUNT_POINT = "/sdcard";
|
||||
|
||||
@ -20,5 +15,4 @@ private:
|
||||
SdCard& operator=(const SdCard&) = delete;
|
||||
|
||||
bool mounted_ = false;
|
||||
bool usbMscActive_ = false;
|
||||
};
|
||||
|
||||
@ -16,6 +16,21 @@
|
||||
static const char* TAG = "WidgetMgr";
|
||||
static constexpr uint8_t SCREEN_ID_NONE = 0xFF;
|
||||
|
||||
#if LV_USE_OBJ_NAME
|
||||
static void dump_flex_objects(lv_obj_t* obj, uint8_t depth) {
|
||||
if (!obj) return;
|
||||
if (lv_obj_get_style_layout(obj, LV_PART_MAIN) == LV_LAYOUT_FLEX) {
|
||||
char name[64];
|
||||
lv_obj_get_name_resolved(obj, name, sizeof(name));
|
||||
ESP_LOGI("FlexMap", "flex obj=%p name=%s depth=%u", obj, name, depth);
|
||||
}
|
||||
uint32_t count = lv_obj_get_child_count(obj);
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
dump_flex_objects(lv_obj_get_child(obj, static_cast<int32_t>(i)), depth + 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool is_valid_utf8(const char* text, size_t len) {
|
||||
size_t i = 0;
|
||||
while (i < len) {
|
||||
@ -358,6 +373,10 @@ void WidgetManager::applyScreen(uint8_t screenId) {
|
||||
createAllWidgets(*screen, root);
|
||||
ESP_LOGI(TAG, "Widgets created");
|
||||
applyCachedValuesToWidgets();
|
||||
#if LV_USE_OBJ_NAME
|
||||
ESP_LOGI(TAG, "Flex containers for screen '%s':", screen->name);
|
||||
dump_flex_objects(root, 0);
|
||||
#endif
|
||||
|
||||
if (disp) {
|
||||
lv_display_enable_invalidation(disp, invEnabled);
|
||||
|
||||
@ -61,7 +61,6 @@ h1{color:#00d4ff;margin-bottom:1rem;font-size:1.5rem}
|
||||
<h1>SD Card File Manager</h1>
|
||||
<div class="status">
|
||||
<div class="status-item"><span class="status-dot" id="sdStatus"></span><span id="sdText">SD Card</span></div>
|
||||
<div class="status-item"><span class="status-dot" id="usbStatus"></span><span id="usbText">USB MSC</span></div>
|
||||
</div>
|
||||
<div class="drop-zone" id="dropZone">
|
||||
<p>Dateien hier ablegen oder <label style="color:#00d4ff;cursor:pointer">auswählen<input type="file" id="fileInput" multiple></label></p>
|
||||
@ -173,8 +172,6 @@ async function updateStatus(){
|
||||
try{const s=await API.status();
|
||||
$('sdStatus').className='status-dot '+(s.sdMounted?'ok':'err');
|
||||
$('sdText').textContent='SD: '+(s.sdMounted?'OK':'Nicht eingebunden');
|
||||
$('usbStatus').className='status-dot '+(s.usbMscActive?'ok':'err');
|
||||
$('usbText').textContent='USB: '+(s.usbMscActive?'Aktiv':'Inaktiv');
|
||||
}catch(e){}}
|
||||
async function uploadFiles(files){
|
||||
const bar=$('uploadBar'),prog=$('uploadProgress');
|
||||
|
||||
@ -19,4 +19,3 @@ dependencies:
|
||||
espressif/esp_lcd_touch_gt911: '*'
|
||||
espressif/esp_lvgl_adapter: '*'
|
||||
espressif/esp_wifi_remote: '*'
|
||||
espressif/esp_tinyusb: ^2.0.1
|
||||
@ -40,6 +40,8 @@ public:
|
||||
|
||||
// Initialize LVGL adapter
|
||||
esp_lv_adapter_config_t cfg = ESP_LV_ADAPTER_DEFAULT_CONFIG();
|
||||
cfg.stack_in_psram = true;
|
||||
cfg.task_stack_size = 16 * 1024;
|
||||
ESP_ERROR_CHECK(esp_lv_adapter_init(&cfg));
|
||||
|
||||
// Register display
|
||||
@ -50,6 +52,7 @@ public:
|
||||
1280, // Vertical resolution
|
||||
ESP_LV_ADAPTER_ROTATE_90 // Rotation
|
||||
);
|
||||
disp_cfg.profile.buffer_height = 4; // Keep internal draw buffer small.
|
||||
lv_disp_t* lv_display = esp_lv_adapter_register_display(&disp_cfg);
|
||||
assert(lv_display != NULL);
|
||||
|
||||
|
||||
@ -1,29 +1,7 @@
|
||||
#include "WebServer.hpp"
|
||||
#include "../SdCard.hpp"
|
||||
#include "esp_log.h"
|
||||
#include <cstring>
|
||||
|
||||
static const char* TAG = "WebServer";
|
||||
|
||||
esp_err_t WebServer::postUsbModeHandler(httpd_req_t* req) {
|
||||
ESP_LOGI(TAG, "Enabling USB Mass Storage mode");
|
||||
|
||||
bool success = SdCard::instance().enableUsbMsc();
|
||||
|
||||
cJSON* json = cJSON_CreateObject();
|
||||
if (success) {
|
||||
cJSON_AddStringToObject(json, "status", "ok");
|
||||
cJSON_AddStringToObject(json, "message", "USB MSC enabled. Connect USB cable to access SD card. Reboot to return to normal mode.");
|
||||
} else {
|
||||
cJSON_AddStringToObject(json, "status", "error");
|
||||
cJSON_AddStringToObject(json, "message", "Failed to enable USB MSC");
|
||||
}
|
||||
return sendJsonObject(req, json);
|
||||
}
|
||||
|
||||
esp_err_t WebServer::getStatusHandler(httpd_req_t* req) {
|
||||
cJSON* json = cJSON_CreateObject();
|
||||
cJSON_AddBoolToObject(json, "sdMounted", SdCard::instance().isMounted());
|
||||
cJSON_AddBoolToObject(json, "usbMscActive", SdCard::instance().isUsbMscActive());
|
||||
return sendJsonObject(req, json);
|
||||
}
|
||||
|
||||
@ -71,9 +71,6 @@ void WebServer::start() {
|
||||
httpd_register_uri_handler(server_, &postKnxReset);
|
||||
|
||||
// Status routes
|
||||
httpd_uri_t postUsbMode = { .uri = "/api/usb-mode", .method = HTTP_POST, .handler = postUsbModeHandler, .user_ctx = nullptr };
|
||||
httpd_register_uri_handler(server_, &postUsbMode);
|
||||
|
||||
httpd_uri_t getStatus = { .uri = "/api/status", .method = HTTP_GET, .handler = getStatusHandler, .user_ctx = nullptr };
|
||||
httpd_register_uri_handler(server_, &getStatus);
|
||||
|
||||
|
||||
@ -37,7 +37,6 @@ private:
|
||||
static esp_err_t postKnxResetHandler(httpd_req_t* req);
|
||||
|
||||
// Status handlers (StatusHandlers.cpp)
|
||||
static esp_err_t postUsbModeHandler(httpd_req_t* req);
|
||||
static esp_err_t getStatusHandler(httpd_req_t* req);
|
||||
|
||||
// File manager handlers (FileManagerHandlers.cpp)
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#include "../WidgetManager.hpp"
|
||||
#include "../Fonts.hpp"
|
||||
#include "esp_log.h"
|
||||
#include <cstdio>
|
||||
|
||||
static const char* TAG = "ButtonWidget";
|
||||
|
||||
@ -17,6 +18,24 @@ static lv_flex_align_t toFlexAlign(uint8_t align) {
|
||||
return LV_FLEX_ALIGN_CENTER;
|
||||
}
|
||||
|
||||
static void set_obj_name(lv_obj_t* obj, const char* base, uint8_t id, const char* suffix) {
|
||||
#if LV_USE_OBJ_NAME
|
||||
if (!obj || !base) return;
|
||||
char name[48];
|
||||
if (suffix && suffix[0] != '\0') {
|
||||
snprintf(name, sizeof(name), "%s#%u_%s", base, id, suffix);
|
||||
} else {
|
||||
snprintf(name, sizeof(name), "%s#%u", base, id);
|
||||
}
|
||||
lv_obj_set_name(obj, name);
|
||||
#else
|
||||
(void)obj;
|
||||
(void)base;
|
||||
(void)id;
|
||||
(void)suffix;
|
||||
#endif
|
||||
}
|
||||
|
||||
ButtonWidget::ButtonWidget(const WidgetConfig& config)
|
||||
: Widget(config)
|
||||
, contentContainer_(nullptr)
|
||||
@ -114,6 +133,7 @@ lv_obj_t* ButtonWidget::create(lv_obj_t* parent) {
|
||||
lv_obj_set_pos(obj_, config_.x, config_.y);
|
||||
lv_obj_set_size(obj_, config_.width > 0 ? config_.width : 100,
|
||||
config_.height > 0 ? config_.height : 50);
|
||||
set_obj_name(obj_, "Button", config_.id, nullptr);
|
||||
|
||||
lv_obj_add_event_cb(obj_, clickCallback, LV_EVENT_CLICKED, this);
|
||||
|
||||
@ -127,6 +147,7 @@ lv_obj_t* ButtonWidget::create(lv_obj_t* parent) {
|
||||
if (contentContainer_ == nullptr) {
|
||||
return obj_; // Continue without icon container
|
||||
}
|
||||
set_obj_name(contentContainer_, "Button", config_.id, "content");
|
||||
lv_obj_remove_style_all(contentContainer_);
|
||||
lv_obj_set_size(contentContainer_, LV_PCT(100), LV_PCT(100));
|
||||
lv_obj_center(contentContainer_);
|
||||
@ -138,6 +159,7 @@ lv_obj_t* ButtonWidget::create(lv_obj_t* parent) {
|
||||
|
||||
if (iconFirst) {
|
||||
iconLabel_ = lv_label_create(contentContainer_);
|
||||
set_obj_name(iconLabel_, "Button", config_.id, "icon");
|
||||
char iconText[5];
|
||||
encodeUtf8(config_.iconCodepoint, iconText);
|
||||
lv_label_set_text(iconLabel_, iconText);
|
||||
@ -146,11 +168,13 @@ lv_obj_t* ButtonWidget::create(lv_obj_t* parent) {
|
||||
|
||||
// Create text label
|
||||
label_ = lv_label_create(contentContainer_);
|
||||
set_obj_name(label_, "Button", config_.id, "text");
|
||||
lv_label_set_text(label_, config_.text);
|
||||
lv_obj_clear_flag(label_, LV_OBJ_FLAG_CLICKABLE);
|
||||
|
||||
if (!iconFirst) {
|
||||
iconLabel_ = lv_label_create(contentContainer_);
|
||||
set_obj_name(iconLabel_, "Button", config_.id, "icon");
|
||||
char iconText[5];
|
||||
encodeUtf8(config_.iconCodepoint, iconText);
|
||||
lv_label_set_text(iconLabel_, iconText);
|
||||
@ -161,6 +185,7 @@ lv_obj_t* ButtonWidget::create(lv_obj_t* parent) {
|
||||
} else {
|
||||
// Simple button without icon
|
||||
label_ = lv_label_create(obj_);
|
||||
set_obj_name(label_, "Button", config_.id, "text");
|
||||
lv_label_set_text(label_, config_.text);
|
||||
applyTextAlignment();
|
||||
lv_obj_clear_flag(label_, LV_OBJ_FLAG_CLICKABLE);
|
||||
|
||||
@ -8,7 +8,6 @@ ChartWidget::ChartWidget(const WidgetConfig& config)
|
||||
}
|
||||
|
||||
lv_obj_t* ChartWidget::create(lv_obj_t* parent) {
|
||||
return nullptr;
|
||||
obj_ = lv_obj_create(parent);
|
||||
if (!obj_) return nullptr;
|
||||
lv_obj_remove_style_all(obj_);
|
||||
|
||||
@ -30,6 +30,24 @@ static void set_label_text_if_changed(lv_obj_t* label, const char* text) {
|
||||
lv_label_set_text(label, text);
|
||||
}
|
||||
|
||||
static void set_obj_name(lv_obj_t* obj, const char* base, uint8_t id, const char* suffix) {
|
||||
#if LV_USE_OBJ_NAME
|
||||
if (!obj || !base) return;
|
||||
char name[48];
|
||||
if (suffix && suffix[0] != '\0') {
|
||||
snprintf(name, sizeof(name), "%s#%u_%s", base, id, suffix);
|
||||
} else {
|
||||
snprintf(name, sizeof(name), "%s#%u", base, id);
|
||||
}
|
||||
lv_obj_set_name(obj, name);
|
||||
#else
|
||||
(void)obj;
|
||||
(void)base;
|
||||
(void)id;
|
||||
(void)suffix;
|
||||
#endif
|
||||
}
|
||||
|
||||
int LabelWidget::encodeUtf8(uint32_t codepoint, char* buf) {
|
||||
if (codepoint < 0x80) {
|
||||
buf[0] = static_cast<char>(codepoint);
|
||||
@ -103,6 +121,7 @@ lv_obj_t* LabelWidget::create(lv_obj_t* parent) {
|
||||
}
|
||||
|
||||
container_ = obj_;
|
||||
set_obj_name(container_, "Label", config_.id, "container");
|
||||
|
||||
if (hasIcon) {
|
||||
// Create elements in correct order based on icon position
|
||||
@ -111,6 +130,7 @@ lv_obj_t* LabelWidget::create(lv_obj_t* parent) {
|
||||
|
||||
if (iconFirst) {
|
||||
iconLabel_ = lv_label_create(container_);
|
||||
set_obj_name(iconLabel_, "Label", config_.id, "icon");
|
||||
char iconText[5];
|
||||
encodeUtf8(config_.iconCodepoint, iconText);
|
||||
lv_label_set_text(iconLabel_, iconText);
|
||||
@ -118,11 +138,13 @@ lv_obj_t* LabelWidget::create(lv_obj_t* parent) {
|
||||
}
|
||||
|
||||
textLabel_ = lv_label_create(container_);
|
||||
set_obj_name(textLabel_, "Label", config_.id, "text");
|
||||
lv_label_set_text(textLabel_, config_.text);
|
||||
lv_obj_clear_flag(textLabel_, LV_OBJ_FLAG_CLICKABLE);
|
||||
|
||||
if (!iconFirst) {
|
||||
iconLabel_ = lv_label_create(container_);
|
||||
set_obj_name(iconLabel_, "Label", config_.id, "icon");
|
||||
char iconText[5];
|
||||
encodeUtf8(config_.iconCodepoint, iconText);
|
||||
lv_label_set_text(iconLabel_, iconText);
|
||||
@ -133,6 +155,7 @@ lv_obj_t* LabelWidget::create(lv_obj_t* parent) {
|
||||
} else {
|
||||
// Container with just text label (for bg/radius)
|
||||
textLabel_ = lv_label_create(container_);
|
||||
set_obj_name(textLabel_, "Label", config_.id, "text");
|
||||
lv_label_set_text(textLabel_, config_.text);
|
||||
lv_obj_center(textLabel_);
|
||||
lv_obj_clear_flag(textLabel_, LV_OBJ_FLAG_CLICKABLE);
|
||||
@ -141,6 +164,7 @@ lv_obj_t* LabelWidget::create(lv_obj_t* parent) {
|
||||
// Simple label without container
|
||||
obj_ = lv_label_create(parent);
|
||||
textLabel_ = obj_;
|
||||
set_obj_name(obj_, "Label", config_.id, nullptr);
|
||||
lv_label_set_text(obj_, config_.text);
|
||||
lv_obj_set_pos(obj_, config_.x, config_.y);
|
||||
if (config_.width > 0 && config_.height > 0) {
|
||||
|
||||
@ -10,11 +10,30 @@ PowerNodeWidget::PowerNodeWidget(const WidgetConfig& config)
|
||||
valueFormat_[0] = '\0';
|
||||
}
|
||||
|
||||
static void set_label_text_if_changed(lv_obj_t* label, const char* text) {
|
||||
if (!label || !text) return;
|
||||
static bool set_label_text_if_changed(lv_obj_t* label, const char* text) {
|
||||
if (!label || !text) return false;
|
||||
const char* current = lv_label_get_text(label);
|
||||
if (current && strcmp(current, text) == 0) return;
|
||||
if (current && strcmp(current, text) == 0) return false;
|
||||
lv_label_set_text(label, text);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void set_obj_name(lv_obj_t* obj, const char* base, uint8_t id, const char* suffix) {
|
||||
#if LV_USE_OBJ_NAME
|
||||
if (!obj || !base) return;
|
||||
char name[48];
|
||||
if (suffix && suffix[0] != '\0') {
|
||||
snprintf(name, sizeof(name), "%s#%u_%s", base, id, suffix);
|
||||
} else {
|
||||
snprintf(name, sizeof(name), "%s#%u", base, id);
|
||||
}
|
||||
lv_obj_set_name(obj, name);
|
||||
#else
|
||||
(void)obj;
|
||||
(void)base;
|
||||
(void)id;
|
||||
(void)suffix;
|
||||
#endif
|
||||
}
|
||||
|
||||
int PowerNodeWidget::encodeUtf8(uint32_t codepoint, char* buf) {
|
||||
@ -73,6 +92,7 @@ lv_obj_t* PowerNodeWidget::create(lv_obj_t* parent) {
|
||||
if (obj_ == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
set_obj_name(obj_, "PowerNode", config_.id, nullptr);
|
||||
|
||||
lv_obj_remove_style_all(obj_);
|
||||
lv_obj_set_pos(obj_, config_.x, config_.y);
|
||||
@ -80,19 +100,18 @@ lv_obj_t* PowerNodeWidget::create(lv_obj_t* parent) {
|
||||
config_.width > 0 ? config_.width : 120,
|
||||
config_.height > 0 ? config_.height : 120);
|
||||
lv_obj_clear_flag(obj_, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
lv_obj_set_flex_flow(obj_, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_flex_align(obj_, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||
lv_obj_set_layout(obj_, LV_LAYOUT_NONE);
|
||||
lv_obj_set_style_pad_all(obj_, 6, 0);
|
||||
lv_obj_set_style_pad_gap(obj_, 2, 0);
|
||||
if (labelText_[0] != '\0') {
|
||||
labelLabel_ = lv_label_create(obj_);
|
||||
set_obj_name(labelLabel_, "PowerNode", config_.id, "label");
|
||||
lv_label_set_text(labelLabel_, labelText_);
|
||||
lv_obj_clear_flag(labelLabel_, LV_OBJ_FLAG_CLICKABLE);
|
||||
}
|
||||
|
||||
if (config_.iconCodepoint > 0 && Fonts::hasIconFont()) {
|
||||
iconLabel_ = lv_label_create(obj_);
|
||||
set_obj_name(iconLabel_, "PowerNode", config_.id, "icon");
|
||||
char iconText[5];
|
||||
encodeUtf8(config_.iconCodepoint, iconText);
|
||||
lv_label_set_text(iconLabel_, iconText);
|
||||
@ -100,6 +119,7 @@ lv_obj_t* PowerNodeWidget::create(lv_obj_t* parent) {
|
||||
}
|
||||
|
||||
valueLabel_ = lv_label_create(obj_);
|
||||
set_obj_name(valueLabel_, "PowerNode", config_.id, "value");
|
||||
if (valueFormat_[0] != '\0') {
|
||||
lv_label_set_text(valueLabel_, valueFormat_);
|
||||
} else {
|
||||
@ -154,11 +174,64 @@ void PowerNodeWidget::applyStyle() {
|
||||
lv_obj_set_style_text_font(valueLabel_, Fonts::bySizeIndex(valueSizeIdx), 0);
|
||||
lv_obj_set_style_text_align(valueLabel_, LV_TEXT_ALIGN_CENTER, 0);
|
||||
}
|
||||
|
||||
layoutChildren();
|
||||
}
|
||||
|
||||
void PowerNodeWidget::updateValueText(const char* text) {
|
||||
if (valueLabel_ == nullptr || text == nullptr) return;
|
||||
set_label_text_if_changed(valueLabel_, text);
|
||||
if (set_label_text_if_changed(valueLabel_, text)) {
|
||||
layoutChildren();
|
||||
}
|
||||
}
|
||||
|
||||
void PowerNodeWidget::layoutChildren() {
|
||||
if (obj_ == nullptr) return;
|
||||
|
||||
lv_obj_update_layout(obj_);
|
||||
|
||||
lv_coord_t width = lv_obj_get_width(obj_);
|
||||
lv_coord_t height = lv_obj_get_height(obj_);
|
||||
if (width <= 0 || height <= 0) return;
|
||||
|
||||
lv_coord_t pad_left = lv_obj_get_style_pad_left(obj_, LV_PART_MAIN);
|
||||
lv_coord_t pad_right = lv_obj_get_style_pad_right(obj_, LV_PART_MAIN);
|
||||
lv_coord_t pad_top = lv_obj_get_style_pad_top(obj_, LV_PART_MAIN);
|
||||
lv_coord_t pad_bottom = lv_obj_get_style_pad_bottom(obj_, LV_PART_MAIN);
|
||||
|
||||
lv_coord_t avail_w = width - pad_left - pad_right;
|
||||
lv_coord_t avail_h = height - pad_top - pad_bottom;
|
||||
if (avail_w <= 0 || avail_h <= 0) return;
|
||||
|
||||
lv_obj_t* items[3];
|
||||
uint8_t count = 0;
|
||||
if (labelLabel_) items[count++] = labelLabel_;
|
||||
if (iconLabel_) items[count++] = iconLabel_;
|
||||
if (valueLabel_) items[count++] = valueLabel_;
|
||||
if (count == 0) return;
|
||||
|
||||
const lv_coord_t gap = 2;
|
||||
lv_coord_t total = 0;
|
||||
for (uint8_t i = 0; i < count; ++i) {
|
||||
total += lv_obj_get_height(items[i]);
|
||||
}
|
||||
total += gap * (count - 1);
|
||||
|
||||
lv_coord_t start_y = pad_top;
|
||||
if (avail_h > total) {
|
||||
start_y += (avail_h - total) / 2;
|
||||
}
|
||||
|
||||
lv_coord_t y = start_y;
|
||||
for (uint8_t i = 0; i < count; ++i) {
|
||||
lv_coord_t item_w = lv_obj_get_width(items[i]);
|
||||
lv_coord_t x = pad_left;
|
||||
if (avail_w > item_w) {
|
||||
x += (avail_w - item_w) / 2;
|
||||
}
|
||||
lv_obj_set_pos(items[i], x, y);
|
||||
y += lv_obj_get_height(items[i]) + gap;
|
||||
}
|
||||
}
|
||||
|
||||
void PowerNodeWidget::onKnxValue(float value) {
|
||||
|
||||
@ -21,5 +21,6 @@ private:
|
||||
|
||||
void parseText();
|
||||
void updateValueText(const char* text);
|
||||
void layoutChildren();
|
||||
static int encodeUtf8(uint32_t codepoint, char* buf);
|
||||
};
|
||||
|
||||
@ -655,7 +655,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="top-actions">
|
||||
<button class="btn ghost" onclick="enableUsbMode()">USB-Modus</button>
|
||||
<button class="btn ghost prog" id="knxProgBtn" onclick="toggleKnxProg()" aria-pressed="false" title="KNX Programmiermodus">KNX Prog AUS</button>
|
||||
<button class="btn ghost danger" onclick="resetKnxSettings()">KNX Reset</button>
|
||||
<button class="btn ghost danger" onclick="resetConfig()">Zuruecksetzen</button>
|
||||
@ -2200,22 +2199,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function enableUsbMode() {
|
||||
if (!confirm('USB-Modus aktivieren?\n\nDie SD-Karte wird als USB-Laufwerk verfuegbar.\nZum Beenden: Geraet neu starten.')) return;
|
||||
try {
|
||||
const resp = await fetch('/api/usb-mode', { method: 'POST' });
|
||||
const data = await resp.json();
|
||||
if (data.status === 'ok') {
|
||||
showStatus('USB-Modus aktiv!');
|
||||
alert('USB Mass Storage aktiviert!\n\nVerbinde das USB-Kabel mit dem PC.\nDie SD-Karte erscheint als Wechseldatentraeger.\n\nZum Beenden: Geraet neu starten.');
|
||||
} else {
|
||||
showStatus('USB-Modus fehlgeschlagen', true);
|
||||
}
|
||||
} catch (e) {
|
||||
showStatus('Fehler beim Aktivieren', true);
|
||||
}
|
||||
}
|
||||
|
||||
function showStatus(msg, isError = false) {
|
||||
const el = document.getElementById('status');
|
||||
el.textContent = msg;
|
||||
|
||||
@ -13,6 +13,9 @@ CONFIG_LV_DRAW_THREAD_STACK_SIZE=32768
|
||||
# Increase LVGL heap to avoid draw task OOM with dynamic UI
|
||||
CONFIG_LV_MEM_SIZE_KILOBYTES=128
|
||||
|
||||
# Enable object names for LVGL debug mapping
|
||||
CONFIG_LV_USE_OBJ_NAME=y
|
||||
|
||||
# Enable FreeType fonts for extended glyph coverage (e.g. umlauts)
|
||||
CONFIG_LV_USE_FREETYPE=y
|
||||
CONFIG_ESP_LVGL_ADAPTER_ENABLE_FREETYPE=y
|
||||
|
||||
@ -9,7 +9,6 @@
|
||||
</div>
|
||||
<div class="flex items-center gap-2.5 flex-wrap justify-end">
|
||||
<button class="border border-border bg-panel-2 text-text px-3.5 py-2 rounded-[10px] text-[13px] font-semibold transition hover:-translate-y-0.5 hover:bg-[#e4ebf2] active:translate-y-0.5" @click="emit('open-settings')">Einstellungen</button>
|
||||
<button class="border border-border bg-panel-2 text-text px-3.5 py-2 rounded-[10px] text-[13px] font-semibold transition hover:-translate-y-0.5 hover:bg-[#e4ebf2] active:translate-y-0.5" @click="enableUsbMode">USB-Modus</button>
|
||||
<button
|
||||
:class="[
|
||||
'border px-3.5 py-2 rounded-[10px] text-[13px] font-semibold transition hover:-translate-y-0.5 active:translate-y-0.5',
|
||||
@ -73,21 +72,6 @@ async function handleReset() {
|
||||
}
|
||||
}
|
||||
|
||||
async function enableUsbMode() {
|
||||
if (!confirm('USB-Modus aktivieren?\n\nDie SD-Karte wird als USB-Laufwerk verfuegbar.\nZum Beenden: Geraet neu starten.')) return;
|
||||
try {
|
||||
const resp = await fetch('/api/usb-mode', { method: 'POST' });
|
||||
const data = await resp.json();
|
||||
if (data.status === 'ok') {
|
||||
alert('USB Mass Storage aktiviert!\n\nVerbinde das USB-Kabel mit dem PC.\nDie SD-Karte erscheint als Wechseldatentraeger.\n\nZum Beenden: Geraet neu starten.');
|
||||
} else {
|
||||
alert('USB-Modus fehlgeschlagen');
|
||||
}
|
||||
} catch (e) {
|
||||
alert('Fehler beim Aktivieren');
|
||||
}
|
||||
}
|
||||
|
||||
async function loadKnxProgMode() {
|
||||
try {
|
||||
const resp = await fetch('/api/knx/prog');
|
||||
|
||||
Loading…
Reference in New Issue
Block a user