From 60078bd680cafeff0caa64c073b02c9bfeefdcdd Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 12 Apr 2024 09:32:01 +0200 Subject: [PATCH] Prepares for MdiIcons library --- components/nspanel_ha_blueprint/__init__.py | 25 +++--- components/nspanel_ha_blueprint/mdiicons.cpp | 67 +++++++++++++++ components/nspanel_ha_blueprint/mdiicons.h | 86 ++++++++++++++++++++ 3 files changed, 168 insertions(+), 10 deletions(-) create mode 100644 components/nspanel_ha_blueprint/mdiicons.cpp create mode 100644 components/nspanel_ha_blueprint/mdiicons.h diff --git a/components/nspanel_ha_blueprint/__init__.py b/components/nspanel_ha_blueprint/__init__.py index 89670f1..15935df 100644 --- a/components/nspanel_ha_blueprint/__init__.py +++ b/components/nspanel_ha_blueprint/__init__.py @@ -1,18 +1,20 @@ # __init__.py + import esphome.codegen as cg import esphome.config_validation as cv from esphome.components.esp32 import add_idf_sdkconfig_option from esphome.core import CORE, coroutine_with_priority +from esphome.cpp_tools import CppFile CODEOWNERS = ["@edwardtfn"] nspanel_ha_blueprint_ns = cg.esphome_ns.namespace('nspanel_ha_blueprint') +MdiIcons = nspanel_ha_blueprint_ns.class_('MdiIcons', cg.Component) CONFIG_SCHEMA = cv.All( cv.Schema({}), ) - @coroutine_with_priority(1.0) async def to_code(config): if CORE.using_arduino: @@ -25,15 +27,18 @@ async def to_code(config): add_idf_sdkconfig_option("CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST", True) add_idf_sdkconfig_option("CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY", True) add_idf_sdkconfig_option("CONFIG_ESP32_REV_MIN_3", True) - add_idf_sdkconfig_option("CONFIG_LWIP_MAX_SOCKETS", 5) # Is this adding any advantage here? - add_idf_sdkconfig_option("CONFIG_MBEDTLS_DYNAMIC_BUFFER", True) - add_idf_sdkconfig_option("CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT", True) - add_idf_sdkconfig_option("CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA", True) - add_idf_sdkconfig_option("CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC", True) - add_idf_sdkconfig_option("CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY", True) # This makes a significant improvement on RAM - add_idf_sdkconfig_option("CONFIG_SPIRAM_IGNORE_NOTFOUND", True) - add_idf_sdkconfig_option("CONFIG_SPIRAM_RODATA", True) - add_idf_sdkconfig_option("CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP", True) + # add_idf_sdkconfig_option("CONFIG_LWIP_MAX_SOCKETS", 5) + # add_idf_sdkconfig_option("CONFIG_MBEDTLS_DYNAMIC_BUFFER", True) + # add_idf_sdkconfig_option("CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT", True) + # add_idf_sdkconfig_option("CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA", True) + # add_idf_sdkconfig_option("CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC", True) + # add_idf_sdkconfig_option("CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY", True) + # add_idf_sdkconfig_option("CONFIG_SPIRAM_RODATA", True) + # add_idf_sdkconfig_option("CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP", True) cg.add_define("USE_NSPANEL_HA_BLUEPRINT") cg.add_global(nspanel_ha_blueprint_ns.using) + + # Setup the MdiIcons class instance + mdi_icons = cg.new_Pvariable('mdi_icons') + yield cg.register_component(mdi_icons, config) diff --git a/components/nspanel_ha_blueprint/mdiicons.cpp b/components/nspanel_ha_blueprint/mdiicons.cpp new file mode 100644 index 0000000..0a9007c --- /dev/null +++ b/components/nspanel_ha_blueprint/mdiicons.cpp @@ -0,0 +1,67 @@ +// mdiicons.cpp + +#include "MdiIcons.h" +#include "esphome/core/log.h" + +using namespace esphome; + +// Setup method to allocate and initialize the icon pool +void MdiIcons::setup() { + iconPool = new MdiIcon[iconPoolCapacity]; // Allocate memory for the icon pool + if (!iconPool) { + ESP_LOGE("MdiIcons", "Failed to allocate memory for icons in PSRAM"); + return; + } + memset(iconPool, 0, iconPoolCapacity * sizeof(MdiIcon)); // Initialize memory to zero + ESP_LOGI("MdiIcons", "Icon pool initialized with capacity %u", iconPoolCapacity); +} + +// Method to log the configuration of the icon pool +void MdiIcons::dump_config() { + ESP_LOGCONFIG("MdiIcons", "MDI Icons component initialized with a pool capacity of %u", iconPoolCapacity); +} + +// Method to find an icon by name. Returns a pointer to the icon if found, otherwise nullptr +const MdiIcon* MdiIcons::find_icon(const char* name) const { + for (size_t i = 0; i < iconPoolSize; ++i) { + if (strcmp(iconPool[i].name, name) == 0) { + return &iconPool[i]; + } + } + return nullptr; +} + +// Method to add a new icon to the pool. Checks for duplicates, resizes the pool if necessary, and adds the icon +bool MdiIcons::add_icon(const char* name, const char* code) { + if (find_icon(name) != nullptr) { + ESP_LOGW("MdiIcons", "Icon '%s' is already in the pool. Not adding again.", name); + return false; + } + + if (iconPoolSize >= iconPoolCapacity) { + resize_pool(); + } + + strncpy(iconPool[iconPoolSize].name, name, sizeof(MdiIcon::name) - 1); + strncpy(iconPool[iconPoolSize].code, code, sizeof(MdiIcon::code) - 1); + iconPool[iconPoolSize].name[sizeof(MdiIcon::name) - 1] = '\0'; + iconPool[iconPoolSize].code[sizeof(MdiIcon::code) - 1] = '\0'; + iconPoolSize++; + ESP_LOGI("MdiIcons", "New icon '%s' added to the pool.", name); + return true; +} + +// Method to double the capacity of the icon pool when it is full +void MdiIcons::resize_pool() { + size_t newCapacity = iconPoolCapacity * 2; + MdiIcon* newPool = new MdiIcon[newCapacity]; + if (!newPool) { + ESP_LOGE("MdiIcons", "Failed to resize the icon pool"); + return; + } + memcpy(newPool, iconPool, iconPoolSize * sizeof(MdiIcon)); + delete[] iconPool; + iconPool = newPool; + iconPoolCapacity = newCapacity; + ESP_LOGI("MdiIcons", "Icon pool resized to %u.", iconPoolCapacity); +} diff --git a/components/nspanel_ha_blueprint/mdiicons.h b/components/nspanel_ha_blueprint/mdiicons.h new file mode 100644 index 0000000..1df07ed --- /dev/null +++ b/components/nspanel_ha_blueprint/mdiicons.h @@ -0,0 +1,86 @@ +// mdiicons.h + +#ifndef MDI_ICONS_H +#define MDI_ICONS_H + +#include "esphome/core/component.h" +#include + +// Struct to hold individual icon data +struct MdiIcon { + char name[32]; // Icon name, max length of 31 characters + null terminator + char code[5]; // Icon code, max length of 4 bytes + null terminator (UTF-8 supported) +}; + +// Class to manage a dynamic pool of MDI icons stored in PSRAM +class MdiIcons : public esphome::Component { + public: + MdiIcons() : iconPool(nullptr), iconPoolSize(0), iconPoolCapacity(100) {} + + // Component setup override, initializes the icon pool + void setup() override { + iconPool = new MdiIcon[iconPoolCapacity]; // Allocate initial pool in PSRAM + if (!iconPool) { + ESP_LOGE("MdiIcons", "Failed to allocate memory for icons in PSRAM"); + return; + } + memset(iconPool, 0, iconPoolCapacity * sizeof(MdiIcon)); // Zero out the memory + ESP_LOGI("MdiIcons", "Initialized icon pool with capacity %u", iconPoolCapacity); + } + + // Logs the component configuration + void dump_config() override { + ESP_LOGCONFIG("MdiIcons", "MDI Icons: Initialized with pool capacity %u", iconPoolCapacity); + } + + // Finds an icon by name, returns a pointer to the icon or nullptr if not found + const MdiIcon* find_icon(const char* name) const { + for (size_t i = 0; i < iconPoolSize; ++i) { + if (strcmp(iconPool[i].name, name) == 0) { + return &iconPool[i]; + } + } + return nullptr; + } + + // Adds a new icon to the pool, returns true if successful, false if icon already exists + bool add_icon(const char* name, const char* code) { + if (find_icon(name) != nullptr) { + ESP_LOGW("MdiIcons", "Icon %s is already in the pool", name); + return false; + } + + if (iconPoolSize >= iconPoolCapacity) { + resize_pool(); + } + + strncpy(iconPool[iconPoolSize].name, name, sizeof(MdiIcon::name) - 1); + strncpy(iconPool[iconPoolSize].code, code, sizeof(MdiIcon::code) - 1); + iconPool[iconPoolSize].name[sizeof(MdiIcon::name) - 1] = '\0'; + iconPool[iconPoolSize].code[sizeof(MdiIcon::code) - 1] = '\0'; + iconPoolSize++; + return true; + } + + private: + MdiIcon* iconPool; // Pointer to the icon pool array + size_t iconPoolSize; // Current number of icons in the pool + size_t iconPoolCapacity; // Current maximum capacity of the pool + + // Resizes the icon pool to accommodate more icons, called when the current pool is full + void resize_pool() { + size_t newCapacity = iconPoolCapacity * 2; + MdiIcon* newPool = new MdiIcon[newCapacity]; + if (!newPool) { + ESP_LOGE("MdiIcons", "Failed to resize icon pool"); + return; + } + memcpy(newPool, iconPool, iconPoolSize * sizeof(MdiIcon)); + delete[] iconPool; + iconPool = newPool; + iconPoolCapacity = newCapacity; + ESP_LOGI("MdiIcons", "Resized icon pool to capacity %u", iconPoolCapacity); + } +}; + +#endif // MDI_ICONS_H