From f9a7e890741bff2f8098c907406e3e957f9fef90 Mon Sep 17 00:00:00 2001 From: krahabb <13969600+krahabb@users.noreply.github.com> Date: Fri, 18 Oct 2024 10:26:10 +0200 Subject: [PATCH] refactor (commonize) vedirect entities for TEXT and HEX data (m3_vedirect) --- esphome/components/m3_vedirect/__init__.py | 115 ++++++++---------- .../m3_vedirect/binary_sensor/__init__.py | 34 +++--- .../binary_sensor/binary_sensor.cpp | 20 +-- .../m3_vedirect/binary_sensor/binary_sensor.h | 13 +- esphome/components/m3_vedirect/entity.cpp | 113 +++++++++++------ esphome/components/m3_vedirect/entity.h | 98 ++++++++------- esphome/components/m3_vedirect/factory.cpp | 92 -------------- esphome/components/m3_vedirect/factory.h | 18 --- esphome/components/m3_vedirect/manager.cpp | 18 +-- esphome/components/m3_vedirect/manager.h | 15 ++- .../components/m3_vedirect/sensor/__init__.py | 47 +++---- .../components/m3_vedirect/sensor/sensor.cpp | 73 ++++------- .../components/m3_vedirect/sensor/sensor.h | 43 ++----- .../m3_vedirect/text_sensor/__init__.py | 31 +++-- .../m3_vedirect/text_sensor/text_sensor.cpp | 29 +---- .../m3_vedirect/text_sensor/text_sensor.h | 20 +-- 16 files changed, 289 insertions(+), 490 deletions(-) delete mode 100644 esphome/components/m3_vedirect/factory.cpp delete mode 100644 esphome/components/m3_vedirect/factory.h diff --git a/esphome/components/m3_vedirect/__init__.py b/esphome/components/m3_vedirect/__init__.py index 298fe967ea14..892c9d6f74d3 100644 --- a/esphome/components/m3_vedirect/__init__.py +++ b/esphome/components/m3_vedirect/__init__.py @@ -26,6 +26,7 @@ ) CONF_VEDIRECT_ID = "vedirect_id" +CONF_VEDIRECT_ENTITIES = "vedirect_entities" CONF_TEXTFRAME = "textframe" CONF_HEXFRAME = "hexframe" @@ -38,6 +39,9 @@ def validate_register_id(): return cv.hex_int_range(min=0, max=65535) +CONF_TEXT_LABEL = "text_label" +CONF_REGISTER_ID = "register_id" +CONF_DATA_TYPE = "data_type" HexDataType = HexFrame.enum("DataType") DATA_TYPES = { "uint8": HexDataType.enum("u8"), @@ -45,26 +49,17 @@ def validate_register_id(): "int16": HexDataType.enum("i16"), "uint32": HexDataType.enum("u32"), } - -CONF_REGISTER_ID = "register_id" -CONF_DATA_TYPE = "data_type" -CONF_LABEL = "label" -HEX_ENTITY_SCHEMA = cv.Schema( +VEDIRECT_ENTITY_SCHEMA = cv.Schema( { + # binds to the corresponding TEXT frame field + cv.Optional(CONF_TEXT_LABEL): cv.string, # binds to the corresponding HEX register - cv.Required(CONF_REGISTER_ID): validate_register_id(), + cv.Optional(CONF_REGISTER_ID): validate_register_id(), # configures the format of the HEX register cv.Optional(CONF_DATA_TYPE): cv.enum(DATA_TYPES), } ) -TEXT_ENTITY_SCHEMA = cv.Schema( - { - # binds to the corresponding TEXT frame field - cv.Required(CONF_LABEL): cv.string, - } -) - # root schema to group (platform) entities linked to a Manager VEDIRECT_PLATFORM_SCHEMA = cv.Schema( { @@ -81,78 +76,67 @@ def vedirect_platform_schema( ) +async def new_vedirect_entity(config, *args): + var = cg.new_Pvariable(config[CONF_ID], *args) + valid = False + if CONF_TEXT_LABEL in config: + valid = True + cg.add(var.set_text_label(config[CONF_TEXT_LABEL])) + if CONF_REGISTER_ID in config: + valid = True + cg.add(var.set_register_id(config[CONF_REGISTER_ID])) + if CONF_DATA_TYPE in config: + cg.add(var.set_hex_data_type(config[CONF_DATA_TYPE])) + assert valid, f"Either {CONF_TEXT_LABEL} or {CONF_REGISTER_ID} must be provided" + return var + + async def vedirect_platform_to_code( config: dict, platform_entities: dict[str, cv.Schema], - setup_entity_func, - setup_hfentity_func, - setup_tfentity_func, + new_vedirectentity_func, + new_entity_func, ): manager = await cg.get_variable(config[CONF_VEDIRECT_ID]) for entity_key, entity_config in config.items(): - if entity_key == CONF_HEXFRAME: + if entity_key == CONF_VEDIRECT_ENTITIES: for _entity_config in entity_config: - var = await setup_hfentity_func( - _entity_config, manager, _entity_config[CONF_REGISTER_ID] - ) - if CONF_DATA_TYPE in _entity_config: - cg.add(var.set_hex_data_type(_entity_config[CONF_DATA_TYPE])) - continue - if entity_key == CONF_TEXTFRAME: - for _entity_config in entity_config: - var = await setup_tfentity_func( - _entity_config, manager, _entity_config[CONF_LABEL] - ) + await new_vedirectentity_func(_entity_config, manager) continue if entity_key in platform_entities: - var = await setup_entity_func(entity_config) + var = await new_entity_func(entity_config) cg.add(getattr(manager, f"set_{entity_key}")(var)) # main component (Manager) schema CONF_AUTO_CREATE_ENTITIES = "auto_create_entities" +CONF_PING_TIMEOUT = "ping_timeout" CONF_DEFAULT_ENTITIES = "default_entities" DEFAULT_ENTITIES_MAP = { - CONF_TEXTFRAME: { - "mppt": (), - "bmv60": (), - "bmv70": (), - "bmv71": (), - "inverter": (), - "charger": (), - }, - CONF_HEXFRAME: { - "mppt": (), - "bmv60": (), - "bmv70": (), - "bmv71": (), - "inverter": (), - "charger": (), - }, + "mppt": (), + "bmv60": (), + "bmv70": (), + "bmv71": (), + "inverter": (), + "charger": (), } - CONF_ON_FRAME_RECEIVED = "on_frame_received" - CONFIG_SCHEMA = cv.All( cv.Schema( { cv.GenerateID(): cv.declare_id(Manager), cv.Optional(CONF_NAME): cv.string_strict, + cv.Optional(CONF_DEFAULT_ENTITIES): cv.one_of(*DEFAULT_ENTITIES_MAP), cv.Optional(CONF_TEXTFRAME): cv.Schema( { - cv.Optional(CONF_AUTO_CREATE_ENTITIES, default=True): cv.boolean, - cv.Optional(CONF_DEFAULT_ENTITIES): cv.one_of( - *DEFAULT_ENTITIES_MAP[CONF_TEXTFRAME] - ), + cv.Optional(CONF_AUTO_CREATE_ENTITIES): cv.boolean, } ), cv.Optional(CONF_HEXFRAME): cv.Schema( { - cv.Optional(CONF_AUTO_CREATE_ENTITIES, default=True): cv.boolean, - cv.Optional(CONF_DEFAULT_ENTITIES): cv.one_of( - *DEFAULT_ENTITIES_MAP[CONF_HEXFRAME] - ), + cv.Optional(CONF_AUTO_CREATE_ENTITIES): cv.boolean, + cv.Optional(CONF_PING_TIMEOUT): cv.positive_time_period_seconds, cv.Optional(CONF_ON_FRAME_RECEIVED): automation.validate_automation( { cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( @@ -174,16 +158,23 @@ async def to_code(config: dict): cg.add(var.set_vedirect_id(str(var.base))) cg.add(var.set_vedirect_name(config.get(CONF_NAME, str(var.base)))) if config_textframe := config.get(CONF_TEXTFRAME): - cg.add( - var.set_auto_create_text_entities( - config_textframe[CONF_AUTO_CREATE_ENTITIES] + if CONF_AUTO_CREATE_ENTITIES in config_textframe: + cg.add( + var.set_auto_create_text_entities( + config_textframe[CONF_AUTO_CREATE_ENTITIES] + ) ) - ) if config_hexframe := config.get(CONF_HEXFRAME): - cg.add( - var.set_auto_create_hex_entities(config_hexframe[CONF_AUTO_CREATE_ENTITIES]) - ) + if CONF_AUTO_CREATE_ENTITIES in config_hexframe: + cg.add( + var.set_auto_create_hex_entities( + config_hexframe[CONF_AUTO_CREATE_ENTITIES] + ) + ) + if CONF_PING_TIMEOUT in config_hexframe: + cg.add(var.set_ping_timeout(config_hexframe[CONF_PING_TIMEOUT])) + for conf in config_hexframe.get(CONF_ON_FRAME_RECEIVED, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation( diff --git a/esphome/components/m3_vedirect/binary_sensor/__init__.py b/esphome/components/m3_vedirect/binary_sensor/__init__.py index de37d71f0797..383023fecabf 100644 --- a/esphome/components/m3_vedirect/binary_sensor/__init__.py +++ b/esphome/components/m3_vedirect/binary_sensor/__init__.py @@ -1,11 +1,11 @@ -import esphome.config_validation as cv from esphome.components import binary_sensor +import esphome.config_validation as cv + from .. import ( - CONF_HEXFRAME, - CONF_TEXTFRAME, - HEX_ENTITY_SCHEMA, - TEXT_ENTITY_SCHEMA, + CONF_VEDIRECT_ENTITIES, + VEDIRECT_ENTITY_SCHEMA, m3_vedirect_ns, + new_vedirect_entity, vedirect_platform_schema, vedirect_platform_to_code, ) @@ -16,29 +16,29 @@ ) # m3_vedirect::BinarySensor mapped to HEX/TEXT data -HFBinarySensor = m3_vedirect_ns.class_("HFBinarySensor", binary_sensor.BinarySensor) -TFBinarySensor = m3_vedirect_ns.class_("TFBinarySensor", binary_sensor.BinarySensor) -HFBINARYSENSOR_SCHEMA = binary_sensor.binary_sensor_schema(HFBinarySensor).extend( - HEX_ENTITY_SCHEMA -) -TFBINARYSENSOR_SCHEMA = binary_sensor.binary_sensor_schema(TFBinarySensor).extend( - TEXT_ENTITY_SCHEMA -) +VEDirectBinarySensor = m3_vedirect_ns.class_("BinarySensor", binary_sensor.BinarySensor) +VEDIRECT_BINARY_SENSOR_SCHEMA = binary_sensor.binary_sensor_schema( + VEDirectBinarySensor +).extend(VEDIRECT_ENTITY_SCHEMA) PLATFORM_ENTITIES = { - CONF_HEXFRAME: cv.ensure_list(HFBINARYSENSOR_SCHEMA), - CONF_TEXTFRAME: cv.ensure_list(TFBINARYSENSOR_SCHEMA), + CONF_VEDIRECT_ENTITIES: cv.ensure_list(VEDIRECT_BINARY_SENSOR_SCHEMA), "link_connected": _diagnostic_binary_sensor_schema, } CONFIG_SCHEMA = vedirect_platform_schema(PLATFORM_ENTITIES) +async def new_vedirect_binary_sensor(config, *args): + var = await new_vedirect_entity(config, *args) + await binary_sensor.register_binary_sensor(var, config) + return var + + async def to_code(config: dict): await vedirect_platform_to_code( config, PLATFORM_ENTITIES, - binary_sensor.new_binary_sensor, - binary_sensor.new_binary_sensor, + new_vedirect_binary_sensor, binary_sensor.new_binary_sensor, ) diff --git a/esphome/components/m3_vedirect/binary_sensor/binary_sensor.cpp b/esphome/components/m3_vedirect/binary_sensor/binary_sensor.cpp index 9d22f3b0c1c7..e6977a8ea08a 100644 --- a/esphome/components/m3_vedirect/binary_sensor/binary_sensor.cpp +++ b/esphome/components/m3_vedirect/binary_sensor/binary_sensor.cpp @@ -6,25 +6,7 @@ namespace esphome { namespace m3_vedirect { -void HFBinarySensor::dynamic_register() { - char *object_id = new char[7]; - sprintf(object_id, "0x%04X", (int) this->id); - char *name = new char[16]; - sprintf(name, "Register %s", object_id); - // name and object_id should likely need to be freed - this->manager->setup_entity_name_id(this, name, object_id); - - App.register_binary_sensor(this); - if (api::global_api_server) { - add_on_state_callback([this](bool state) { api::global_api_server->on_binary_sensor_update(this, state); }); - } -} - -TFBinarySensor::TFBinarySensor(Manager *manager, const char *label, const DEF *def) : TFEntity(manager, label, def) { - manager->setup_entity_name_id(this, def ? def->description : label, label); -} - -void TFBinarySensor::dynamic_register() { +void BinarySensor::dynamic_register() { App.register_binary_sensor(this); if (api::global_api_server) { add_on_state_callback([this](bool state) { api::global_api_server->on_binary_sensor_update(this, state); }); diff --git a/esphome/components/m3_vedirect/binary_sensor/binary_sensor.h b/esphome/components/m3_vedirect/binary_sensor/binary_sensor.h index cb9cf0ce2b35..137092cb3e77 100644 --- a/esphome/components/m3_vedirect/binary_sensor/binary_sensor.h +++ b/esphome/components/m3_vedirect/binary_sensor/binary_sensor.h @@ -6,25 +6,18 @@ namespace esphome { namespace m3_vedirect { -class HFBinarySensor : public esphome::binary_sensor::BinarySensor, public HFEntity { +class BinarySensor : public esphome::binary_sensor::BinarySensor, public VEDirectEntity { public: - void dynamic_register() override; + BinarySensor(Manager *manager) : VEDirectEntity(manager) {} + void parse_text_value(const char *text_value) override { publish_state(!strcasecmp(text_value, "ON")); } void parse_hex_value(const HexFrame *hexframe) override { if (hexframe->data_size() == sizeof(uint8_t)) { publish_state(hexframe->data_u8()); } }; -}; - -class TFBinarySensor : public esphome::binary_sensor::BinarySensor, public TFEntity { - public: - TFBinarySensor(Manager *manager, const char *label, const DEF *def); - TFBinarySensor(Manager *manager, const char *label) : TFBinarySensor(manager, label, TFEntity::get_def(label)) {} void dynamic_register() override; - - void parse_text_value(const char *text_value) override { publish_state(!strcasecmp(text_value, "ON")); } }; } // namespace m3_vedirect diff --git a/esphome/components/m3_vedirect/entity.cpp b/esphome/components/m3_vedirect/entity.cpp index df5e8db0a366..ec048a2acbf3 100644 --- a/esphome/components/m3_vedirect/entity.cpp +++ b/esphome/components/m3_vedirect/entity.cpp @@ -13,10 +13,6 @@ namespace m3_vedirect { static const char *const TAG = "m3_vedirect.entity"; -HexRegister::HexRegister(Manager *manager, register_id_t id) : manager(manager), id(id) { - manager->hex_registers_.emplace(id, this); -} - const char *VEDirectEntity::UNITS[] = { "A", "V", "VA", "W", "Ah", "kWh", "%", "min", "°C", }; @@ -33,30 +29,26 @@ const sensor::StateClass VEDirectEntity::STATE_CLASSES[UNIT::_COUNT] = { const float VEDirectEntity::DIGITS_TO_SCALE[] = {1.f, .1f, .01f, .001f}; #define DEF_TFBINARYSENSOR(name, disabled) \ - { name, entity_builder, disabled } + { name, VEDirectEntity::CLASS::BOOLEAN, VEDirectEntity::SUBCLASS::ENUM, disabled } #define DEF_TFSENSOR(name, disabled, unit, digits) \ - { name, entity_builder, disabled, unit, digits } + { name, VEDirectEntity::CLASS::MEASUREMENT, VEDirectEntity::SUBCLASS::MEASURE, disabled, unit, digits } #define DEF_TFTEXTSENSOR(name, disabled) \ - { name, entity_builder, disabled } - -template TFEntity *entity_builder(Manager *manager, const char *label, const TFEntity::DEF *def) { - return new T(manager, label, def); -} + { name, VEDirectEntity::CLASS::ENUMERATION, VEDirectEntity::SUBCLASS::ENUM, disabled } -const TFEntity::def_map_t TFEntity::DEFS{ - {"AC_OUT_I", DEF_TFSENSOR("AC output current", false, TFEntity::UNIT::A, TFEntity::DIGITS::D_1)}, - {"AC_OUT_S", DEF_TFSENSOR("AC output apparent power", false, TFEntity::UNIT::VA, TFEntity::DIGITS::D_0)}, - {"AC_OUT_V", DEF_TFSENSOR("AC output voltage", false, TFEntity::UNIT::V, TFEntity::DIGITS::D_2)}, - {"H19", DEF_TFSENSOR("Yield total", false, TFEntity::UNIT::kWh, TFEntity::DIGITS::D_2)}, - {"H20", DEF_TFSENSOR("Yield today", false, TFEntity::UNIT::kWh, TFEntity::DIGITS::D_2)}, - {"H21", DEF_TFSENSOR("Maximum power today", false, TFEntity::UNIT::W, TFEntity::DIGITS::D_0)}, - {"H22", DEF_TFSENSOR("Yield yesterday", true, TFEntity::UNIT::kWh, TFEntity::DIGITS::D_2)}, - {"H23", DEF_TFSENSOR("Maximum power yesterday", true, TFEntity::UNIT::W, TFEntity::DIGITS::D_0)}, - {"I", DEF_TFSENSOR("Battery current", false, TFEntity::UNIT::A, TFEntity::DIGITS::D_3)}, - {"IL", DEF_TFSENSOR("Load current", false, TFEntity::UNIT::A, TFEntity::DIGITS::D_3)}, - {"PPV", DEF_TFSENSOR("PV power", false, TFEntity::UNIT::W, TFEntity::DIGITS::D_0)}, - {"V", DEF_TFSENSOR("Battery voltage", false, TFEntity::UNIT::V, TFEntity::DIGITS::D_3)}, - {"VPV", DEF_TFSENSOR("PV voltage", false, TFEntity::UNIT::V, TFEntity::DIGITS::D_3)}, +const VEDirectEntity::text_def_map_t VEDirectEntity::TEXT_DEFS{ + {"AC_OUT_I", DEF_TFSENSOR("AC output current", false, UNIT::A, DIGITS::D_1)}, + {"AC_OUT_S", DEF_TFSENSOR("AC output apparent power", false, UNIT::VA, DIGITS::D_0)}, + {"AC_OUT_V", DEF_TFSENSOR("AC output voltage", false, UNIT::V, DIGITS::D_2)}, + {"H19", DEF_TFSENSOR("Yield total", false, UNIT::kWh, DIGITS::D_2)}, + {"H20", DEF_TFSENSOR("Yield today", false, UNIT::kWh, DIGITS::D_2)}, + {"H21", DEF_TFSENSOR("Maximum power today", false, UNIT::W, DIGITS::D_0)}, + {"H22", DEF_TFSENSOR("Yield yesterday", true, UNIT::kWh, DIGITS::D_2)}, + {"H23", DEF_TFSENSOR("Maximum power yesterday", true, UNIT::W, DIGITS::D_0)}, + {"I", DEF_TFSENSOR("Battery current", false, UNIT::A, DIGITS::D_3)}, + {"IL", DEF_TFSENSOR("Load current", false, UNIT::A, DIGITS::D_3)}, + {"PPV", DEF_TFSENSOR("PV power", false, UNIT::W, DIGITS::D_0)}, + {"V", DEF_TFSENSOR("Battery voltage", false, UNIT::V, DIGITS::D_3)}, + {"VPV", DEF_TFSENSOR("PV voltage", false, UNIT::V, DIGITS::D_3)}, {"AR", DEF_TFTEXTSENSOR("Alarm reason", false)}, {"CS", DEF_TFTEXTSENSOR("State of operation", false)}, @@ -76,22 +68,73 @@ const TFEntity::def_map_t TFEntity::DEFS{ }; -TFEntity *TFEntity::build(Manager *manager, const char *label) { - auto entity_def = DEFS.find(label); - if (entity_def == DEFS.end()) { +VEDirectEntity *VEDirectEntity::build(Manager *manager, const char *label) { + VEDirectEntity *entity; + auto text_def_it = TEXT_DEFS.find(label); + if (text_def_it == TEXT_DEFS.end()) { // ENTITIES_DEF lacks the definition for this parameter so - // we return a disabled (TextSensor) entity. + // we return a plain TextSensor entity. // We allocate a copy since the label param is 'volatile' - auto entity = new TFTextSensor(manager, strdup(label), nullptr); - entity->set_disabled_by_default(true); - return entity; + label = strdup(label); + entity = VEDirectEntity::dynamic_build_entity_(manager, label, label); } else { - return entity_def->second.init(manager, entity_def->first, &entity_def->second); + label = text_def_it->first; + auto &text_def = text_def_it->second; + switch (text_def.cls) { + case CLASS::MEASUREMENT: + // pass our 'static' copy of the label (param is volatile) + entity = VEDirectEntity::dynamic_build_entity_(manager, text_def.description, label); + break; + case CLASS::BOOLEAN: + entity = VEDirectEntity::dynamic_build_entity_(manager, text_def.description, label); + break; + default: + entity = VEDirectEntity::dynamic_build_entity_(manager, text_def.description, label); + } + entity->init_text_def_(&text_def); } + manager->text_entities_.emplace(label, entity); + entity->dynamic_register(); + return entity; +} + +VEDirectEntity *VEDirectEntity::build(Manager *manager, register_id_t register_id) { + // check if we have a 'structured' parser or any other special behavior + /*for (const HexRegisterDef &_def : REGISTERS_DEF) { + if (_def.id == id) + return _def.init(manager, _def); + }*/ + + // else build a raw text sensor + char *object_id = new char[7]; + sprintf(object_id, "0x%04X", (int) register_id); + char *name = new char[16]; + sprintf(name, "Register %s", object_id); + + auto entity = VEDirectEntity::dynamic_build_entity_(manager, name, object_id); + entity->set_disabled_by_default(true); + entity->set_register_id(register_id); + entity->dynamic_register(); + return entity; +} + +void VEDirectEntity::set_text_label(const char *label) { + auto text_def_it = TEXT_DEFS.find(label); + if (text_def_it != TEXT_DEFS.end()) + this->init_text_def_(&text_def_it->second); + this->manager->text_entities_.emplace(label, this); +} + +void VEDirectEntity::set_register_id(register_id_t register_id) { + this->register_id_ = register_id; + this->manager->hex_registers_.emplace(register_id, this); } -TFEntity::TFEntity(Manager *manager, const char *label, const DEF *def) : label(label), def(def) { - manager->text_entities_.emplace(label, this); +template +TEntity *VEDirectEntity::dynamic_build_entity_(Manager *manager, const char *name, const char *object_id) { + auto entity = new TEntity(manager); + manager->setup_entity_name_id(entity, name, object_id); + return entity; } } // namespace m3_vedirect diff --git a/esphome/components/m3_vedirect/entity.h b/esphome/components/m3_vedirect/entity.h index 3c7395401178..e52a01901650 100644 --- a/esphome/components/m3_vedirect/entity.h +++ b/esphome/components/m3_vedirect/entity.h @@ -12,30 +12,28 @@ namespace esphome { namespace m3_vedirect { #define NO_REGISTER_ID 0 -#define NO_TEXT_NAME nullptr class Manager; -/// @brief Provides an abstraction for an HEX register id. In case of simple registers -/// @brief it also represents the associated entities while, for registers carrying -/// @brief multiple data parameters, it takes the responsibility of splitting those data -/// @brief and forwarding to the correct entity -class HexRegister { +class VEDirectEntity { public: - Manager *const manager; - - register_id_t id; - HexRegister(Manager *manager, register_id_t id); - - virtual void dynamic_register(){}; - - virtual void parse_hex_value(const HexFrame *hexframe){}; + /// @brief Together with SUBCLASS defines the data semantics of this entity + enum CLASS : u_int8_t { + BOOLEAN, + ENUMERATION, // enumeration data or bitmask + MEASUREMENT, // numeric data (either signed or unsigned) + }; - protected: -}; + /// @brief Together with CLASS defines the data semantics of this entity + enum SUBCLASS : u_int8_t { + BITMASK, // represents a set of bit flags + ENUM, // represents a value among an enumeration + SELECTOR, // same as ENUM but used to select conditional parsing + MEASURE, + TEMPERATURE, + CELLVOLTAGE, + }; -class VEDirectEntity { - public: // configuration symbols for numeric sensors enum UNIT : u_int8_t { A = 0, @@ -61,24 +59,10 @@ class VEDirectEntity { }; static const float DIGITS_TO_SCALE[4]; - /// @brief Called when an entity is dynamically initialized by the Manager loop. - /// @brief This will in turn call the proper register function against App/api - virtual void dynamic_register(){}; -}; - -class HFEntity : public HexRegister, public VEDirectEntity { - public: - protected: - HFEntity(Manager *manager, register_id_t id) : HexRegister(manager, id) {} -}; - -class TFEntity : public VEDirectEntity { - public: - struct DEF; - typedef TFEntity *(*entity_initializer_func_t)(Manager *manager, const char *label, const DEF *def); - struct DEF { + struct TEXT_DEF { const char *description; - const entity_initializer_func_t init; + const CLASS cls : 2; + const SUBCLASS subcls : 6; const bool initially_disabled; // Optional entity 'class' definitions union { @@ -90,27 +74,51 @@ class TFEntity : public VEDirectEntity { }; } __attribute__((packed)); - typedef std::unordered_map def_map_t; - static const def_map_t DEFS; - static const DEF *get_def(const char *label) { - auto entity_def = DEFS.find(label); - return entity_def == DEFS.end() ? nullptr : &entity_def->second; + typedef std::unordered_map text_def_map_t; + static const text_def_map_t TEXT_DEFS; + static const TEXT_DEF *get_text_def(const char *label) { + auto entity_def = TEXT_DEFS.find(label); + return entity_def == TEXT_DEFS.end() ? nullptr : &entity_def->second; } /// @brief Class factory method to auto generate an entity based off the TEXT frame label /// @param manager /// @param label /// @return - static TFEntity *build(Manager *manager, const char *label); + static VEDirectEntity *build(Manager *manager, const char *label); + static VEDirectEntity *build(Manager *manager, register_id_t register_id); - const char *const label; - const DEF *const def; + Manager *const manager; - /// @brief store the current text value from VE.Direct TEXT frame + /// @brief Binds the entity to a TEXT FRAME field label so that text frame parsing + /// will be automatically routed. This method is part of the public interface + /// called by yaml generaed code + /// @param label the name of the TEXT FRAME record to bind + void set_text_label(const char *label); + /// @brief Parse the current value from VE.Direct TEXT frame and update this entity /// @param value the raw data carried by VE.Direct virtual void parse_text_value(const char *text_value){}; + void set_register_id(register_id_t register_id); + register_id_t get_register_id() { return this->register_id_; } + virtual void parse_hex_value(const HexFrame *hexframe){}; + + /// @brief Called when an entity is dynamically initialized by the Manager loop. + /// @brief This will in turn call the proper register function against App/api + virtual void dynamic_register(){}; + protected: - TFEntity(Manager *manager, const char *label, const DEF *def); + VEDirectEntity(Manager *manager) : manager(manager) {} + + /// @brief Preset entity properties based off our TEXT_DEF. This is being called + /// automatically by VEDirectEntity methods when a proper definition is available. + /// @param def + virtual void init_text_def_(const TEXT_DEF *text_def) {} + + private: + register_id_t register_id_{}; + + template + static TEntity *dynamic_build_entity_(Manager *manager, const char *name, const char *object_id); }; } // namespace m3_vedirect diff --git a/esphome/components/m3_vedirect/factory.cpp b/esphome/components/m3_vedirect/factory.cpp deleted file mode 100644 index ef34ab933cba..000000000000 --- a/esphome/components/m3_vedirect/factory.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include "factory.h" -#include "./binary_sensor/binary_sensor.h" -#include "./sensor/sensor.h" -#include "./text_sensor/text_sensor.h" - -namespace esphome { -namespace m3_vedirect { - -/*REMOVE -template TFEntity *entity_builder(Manager *manager, const char *label) { return new T(manager, label); } -typedef TFEntity *(*entity_initializer_func)(Manager *manager, const char *label); -struct TFEntityInit { - const char *const label; - const entity_initializer_func init; - const bool initially_disabled; -}; - -static const TFEntityInit TFENTITIES_INIT[] = { - {"AC_OUT_I", entity_builder, false}, {"AC_OUT_S", entity_builder, false}, - {"AC_OUT_V", entity_builder, false}, {"AR", entity_builder, false}, - {"Alarm", entity_builder, false}, {"CS", entity_builder, false}, - {"ERR", entity_builder, false}, {"FW", entity_builder, true}, - {"FWE", entity_builder, true}, {"H19", entity_builder, true}, - {"H20", entity_builder, false}, {"H21", entity_builder, false}, - {"H22", entity_builder, true}, {"H23", entity_builder, true}, - {"I", entity_builder, false}, {"IL", entity_builder, false}, - {"LOAD", entity_builder, false}, {"MODE", entity_builder, false}, - {"MPPT", entity_builder, false}, {"OR", entity_builder, false}, - {"PID", entity_builder, true}, {"PPV", entity_builder, false}, - {"Relay", entity_builder, false}, {"SER#", entity_builder, true}, - {"V", entity_builder, false}, {"VPV", entity_builder, false}, - {"WARN", entity_builder, false}, -}; - -TFEntity *Factory::build_entity(Manager *manager, const char *label) { - for (const TFEntityInit &_def : TFENTITIES_INIT) { - int _strcmp = strcmp(label, _def.label); - if (_strcmp == 0) { - return _def.init(manager, _def.label); - } else if (_strcmp < 0) { - break; - } - } - // ENTITIES_DEF lacks the definition for this parameter so - // we return a disabled (TextSensor) entity. - // We allocate a copy for text_name since the param is 'volatile' - label = strdup(label); - auto entity = new TFTextSensor(manager, label); - entity->set_disabled_by_default(true); - return entity; -} -*/ - -struct HexRegisterDef; - -typedef HexRegister *(*register_initializer_func)(Manager *manager, const HexRegisterDef &); - -struct HexRegisterDef { - /// @brief the VE.Direct register id for entities managed through HEX frames - const register_id_t id; - /// @brief Friendly name - const char *const description; - - const register_initializer_func init; - - HexRegisterDef(register_id_t id, const char *description = nullptr, const register_initializer_func init = nullptr) - : id(id), description(description), init(init) {} -}; - -template HexRegister *register_builder(Manager *manager, const HexRegisterDef &def) { - return new T(manager, def); -} - -static const HexRegisterDef REGISTERS_DEF[] = { - -}; - -/*static*/ HexRegister *Factory::build_register(Manager *manager, register_id_t id) { - // check if we have a 'structured' parser or any other special behavior - for (const HexRegisterDef &_def : REGISTERS_DEF) { - if (_def.id == id) - return _def.init(manager, _def); - } - - // else build a raw text sensor - auto entity = new HFTextSensor(manager, id); - entity->set_disabled_by_default(true); - return entity; -} - -} // namespace m3_vedirect -} // namespace esphome diff --git a/esphome/components/m3_vedirect/factory.h b/esphome/components/m3_vedirect/factory.h deleted file mode 100644 index 650c7176133b..000000000000 --- a/esphome/components/m3_vedirect/factory.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "entity.h" -#include "hexframe.h" - -namespace esphome { -namespace m3_vedirect { - -class Manager; - -class Factory { - public: - // static TFEntity *build_entity(Manager *manager, const char *label); - static HexRegister *build_register(Manager *manager, register_id_t register_id); -}; - -} // namespace m3_vedirect -} // namespace esphome diff --git a/esphome/components/m3_vedirect/manager.cpp b/esphome/components/m3_vedirect/manager.cpp index c088f818121a..f31cc681b678 100644 --- a/esphome/components/m3_vedirect/manager.cpp +++ b/esphome/components/m3_vedirect/manager.cpp @@ -1,16 +1,6 @@ #include "manager.h" #include "esphome/core/log.h" -#include "esphome/components/wifi/wifi_component.h" -#include "esphome/components/uart/uart_component.h" -// #include -#ifdef USE_ESP32 -#include "esp_pm.h" -#include -#include -#endif - -#include "factory.h" #include "entity.h" #include "hexframe.h" @@ -54,7 +44,7 @@ void Manager::loop() { this->decode(frame_buf, frame_buf + available); } - if (this->ping_retry_timeout_ && ((millis_ - this->millis_last_ping_tx_) > this->ping_retry_timeout_)) { + if (this->ping_timeout_ && ((millis_ - this->millis_last_ping_tx_) > this->ping_timeout_)) { this->send_hexframe(HexFrame_Command(HexFrame::Ping)); this->millis_last_ping_tx_ = this->millis_last_hexframe_tx_; } @@ -163,8 +153,7 @@ void Manager::on_frame_hex_(const HexFrame &hexframe) { if (entity_iter == this->hex_registers_.end()) { if (this->auto_create_hex_entities_) { ESP_LOGD(this->logtag_, "Looking-up entity for VE.Direct hex register: %04X", (int) hex_id); - auto hex_register = Factory::build_register(this, hex_id); - hex_register->dynamic_register(); + auto hex_register = VEDirectEntity::build(this, hex_id); hex_register->parse_hex_value(&hexframe); } } else { @@ -206,8 +195,7 @@ void Manager::on_frame_text_(TextRecord **text_records, uint8_t text_records_cou if (entity_iter == this->text_entities_.end()) { if (this->auto_create_text_entities_) { ESP_LOGD(this->logtag_, "Looking-up entity for VE.Direct text field: %s", text_record->name); - auto entity = TFEntity::build(this, text_record->name); - entity->dynamic_register(); + auto entity = VEDirectEntity::build(this, text_record->name); entity->parse_text_value(text_record->value); } } else { diff --git a/esphome/components/m3_vedirect/manager.h b/esphome/components/m3_vedirect/manager.h index 6c567e297578..28188810e445 100644 --- a/esphome/components/m3_vedirect/manager.h +++ b/esphome/components/m3_vedirect/manager.h @@ -16,8 +16,7 @@ namespace esphome { namespace m3_vedirect { -class HexRegister; -class TFEntity; +class VEDirectEntity; #define MANAGER_ENTITY_(type, name) \ protected: \ @@ -41,6 +40,7 @@ class Manager : public uart::UARTDevice, public Component, protected FrameHandle void set_vedirect_name(const char *vedirect_name) { this->vedirect_name_ = vedirect_name; } void set_auto_create_text_entities(bool value) { this->auto_create_text_entities_ = value; } void set_auto_create_hex_entities(bool value) { this->auto_create_hex_entities_ = value; } + void set_ping_timeout(uint32_t seconds) { this->ping_timeout_ = seconds * 1000; } void setup() override; void loop() override; @@ -124,9 +124,9 @@ class Manager : public uart::UARTDevice, public Component, protected FrameHandle std::string vedirect_id_; std::string vedirect_name_; bool auto_create_text_entities_{true}; - bool auto_create_hex_entities_{true}; + bool auto_create_hex_entities_{false}; - uint32_t ping_retry_timeout_{60000}; + uint32_t ping_timeout_{0}; // component state bool connected_{false}; @@ -147,10 +147,9 @@ class Manager : public uart::UARTDevice, public Component, protected FrameHandle // These will provide 'map' access either by text record name (text_entities_) // or by HEX register id (hex_entities_). Since some HEX registers are also // published in TEXT frames we're also trying to map these to the same entity. - friend class TFEntity; - std::unordered_map text_entities_; - friend class HexRegister; - std::unordered_map hex_registers_; + friend class VEDirectEntity; + std::unordered_map text_entities_; + std::unordered_map hex_registers_; friend class HexFrameTrigger; CallbackManager hexframe_callback_; diff --git a/esphome/components/m3_vedirect/sensor/__init__.py b/esphome/components/m3_vedirect/sensor/__init__.py index c441b891a121..8a8bc78d14c8 100644 --- a/esphome/components/m3_vedirect/sensor/__init__.py +++ b/esphome/components/m3_vedirect/sensor/__init__.py @@ -1,43 +1,34 @@ +import esphome.codegen as cg from esphome.components import sensor import esphome.config_validation as cv import esphome.const as ec from .. import ( - CONF_HEXFRAME, - CONF_TEXTFRAME, - HEX_ENTITY_SCHEMA, - TEXT_ENTITY_SCHEMA, + CONF_VEDIRECT_ENTITIES, + VEDIRECT_ENTITY_SCHEMA, m3_vedirect_ns, + new_vedirect_entity, vedirect_platform_schema, vedirect_platform_to_code, ) # m3_vedirect::Sensor mapped to HEX/TEXT data -CONF_SCALE = "scale" -HFSensor = m3_vedirect_ns.class_("HFSensor", sensor.Sensor) -TFSensor = m3_vedirect_ns.class_("TFSensor", sensor.Sensor) -HFSENSOR_SCHEMA = ( - sensor.sensor_schema(HFSensor) - .extend(HEX_ENTITY_SCHEMA) +CONF_TEXT_SCALE = "text_scale" +CONF_HEX_SCALE = "hex_scale" +VEDirectSensor = m3_vedirect_ns.class_("Sensor", sensor.Sensor) +VEDIRECT_SENSOR_SCHEMA = ( + sensor.sensor_schema(VEDirectSensor) + .extend(VEDIRECT_ENTITY_SCHEMA) .extend( { - cv.Optional(CONF_SCALE): cv.float_, - } - ) -) -TFSENSOR_SCHEMA = ( - sensor.sensor_schema(TFSensor) - .extend(TEXT_ENTITY_SCHEMA) - .extend( - { - cv.Optional(CONF_SCALE): cv.float_, + cv.Optional(CONF_TEXT_SCALE): cv.float_, + cv.Optional(CONF_HEX_SCALE): cv.float_, } ) ) PLATFORM_ENTITIES = { - CONF_HEXFRAME: cv.ensure_list(HFSENSOR_SCHEMA), - CONF_TEXTFRAME: cv.ensure_list(TFSENSOR_SCHEMA), + CONF_VEDIRECT_ENTITIES: cv.ensure_list(VEDIRECT_SENSOR_SCHEMA), "run_time": sensor.sensor_schema( entity_category="diagnostic", device_class=ec.DEVICE_CLASS_DURATION, @@ -48,10 +39,11 @@ CONFIG_SCHEMA = vedirect_platform_schema(PLATFORM_ENTITIES) -async def new_tfsensor(config, *args): - var = await sensor.new_sensor(config, *args) - if CONF_SCALE in config: - var.set_scale(config[CONF_SCALE]) +async def new_vedirect_sensor(config, *args): + var = await new_vedirect_entity(config, *args) + if CONF_TEXT_SCALE in config: + cg.add(var.set_text_scale(config[CONF_TEXT_SCALE])) + await sensor.register_sensor(var, config) return var @@ -59,7 +51,6 @@ async def to_code(config: dict): await vedirect_platform_to_code( config, PLATFORM_ENTITIES, + new_vedirect_sensor, sensor.new_sensor, - sensor.new_sensor, - new_tfsensor, ) diff --git a/esphome/components/m3_vedirect/sensor/sensor.cpp b/esphome/components/m3_vedirect/sensor/sensor.cpp index 23631481478d..1ced49a095af 100644 --- a/esphome/components/m3_vedirect/sensor/sensor.cpp +++ b/esphome/components/m3_vedirect/sensor/sensor.cpp @@ -6,31 +6,15 @@ namespace esphome { namespace m3_vedirect { -void HFSensor::dynamic_register() { - char *object_id = new char[7]; - sprintf(object_id, "0x%04X", (int) this->id); - char *name = new char[16]; - sprintf(name, "Register %s", object_id); - // name and object_id should likely need to be freed - this->manager->setup_entity_name_id(this, name, object_id); - - App.register_sensor(this); - if (api::global_api_server) - add_on_state_callback([this](float state) { api::global_api_server->on_sensor_update(this, state); }); -} -/* -Sensor::Sensor(Manager *manager, const VEDirectEntityDef &def) - : esphome::sensor::Sensor(), VEDirectEntity(manager, def), scale_(def.scale) { - VEDirectEntity::init_entity_(this, def); - set_unit_of_measurement(def.unit_of_measurement); - set_accuracy_decimals(def.accuracy_decimals); -} -void Sensor::set_text_value(const char *text_value) { +void Sensor::parse_text_value(const char *text_value) { char *endptr; - state = strtof(text_value, &endptr) / this->scale_; - if (state != this->raw_state) - publish_state(state); + float value = strtof(text_value, &endptr) * this->text_scale_; + if (*endptr != 0) + value = NAN; + if (value != this->raw_state) + publish_state(value); } + void Sensor::parse_hex_value(const HexFrame *hexframe) { // TODO(maybe): manage inconsistencies (log error?) // and improve if any the parsing @@ -39,34 +23,34 @@ void Sensor::parse_hex_value(const HexFrame *hexframe) { case HexFrame::DataType::u8: if (hexframe->data_size() != 1) return; - state = hexframe->data_u8() / this->scale_; + state = hexframe->data_u8() / this->hex_scale_; break; case HexFrame::DataType::u16: if (hexframe->data_size() != 2) return; - state = hexframe->data_u16() / this->scale_; + state = hexframe->data_u16() / this->hex_scale_; break; case HexFrame::DataType::i16: if (hexframe->data_size() != 2) return; - state = hexframe->data_i16() / this->scale_; + state = hexframe->data_i16() / this->hex_scale_; break; case HexFrame::DataType::u32: if (hexframe->data_size() != 4) return; - state = hexframe->data_u32() / this->scale_; + state = hexframe->data_u32() / this->hex_scale_; break; default: // try to infer from data_size switch (hexframe->data_size()) { case 1: - state = hexframe->data_u16() / this->scale_; + state = hexframe->data_u16() / this->hex_scale_; break; case 2: - //it might be signed though - state = hexframe->data_u16() / this->scale_; + // it might be signed though + state = hexframe->data_u16() / this->hex_scale_; break; case 4: - state = hexframe->data_u16() / this->scale_; + state = hexframe->data_u16() / this->hex_scale_; break; default: return; @@ -76,32 +60,19 @@ void Sensor::parse_hex_value(const HexFrame *hexframe) { if (state != this->raw_state) publish_state(state); }; -*/ - -TFSensor::TFSensor(Manager *manager, const char *label, const DEF *def) : TFEntity(manager, label, def) { - if (def) { - this->set_unit_of_measurement(UNITS[def->unit]); - this->set_accuracy_decimals(def->digits); - this->set_device_class(DEVICE_CLASSES[def->unit]); - this->set_state_class(STATE_CLASSES[def->unit]); - this->set_scale(DIGITS_TO_SCALE[def->digits]); - } - manager->setup_entity_name_id(this, def ? def->description : label, label); -} -void TFSensor::dynamic_register() { +void Sensor::dynamic_register() { App.register_sensor(this); if (api::global_api_server) add_on_state_callback([this](float state) { api::global_api_server->on_sensor_update(this, state); }); } -void TFSensor::parse_text_value(const char *text_value) { - char *endptr; - float value = strtof(text_value, &endptr) * this->scale_; - if (*endptr != 0) - value = NAN; - if (value != this->raw_state) - publish_state(value); +void Sensor::init_text_def_(const TEXT_DEF *text_def) { + this->set_unit_of_measurement(UNITS[text_def->unit]); + this->set_accuracy_decimals(text_def->digits); + this->set_device_class(DEVICE_CLASSES[text_def->unit]); + this->set_state_class(STATE_CLASSES[text_def->unit]); + this->set_text_scale(DIGITS_TO_SCALE[text_def->digits]); } } // namespace m3_vedirect diff --git a/esphome/components/m3_vedirect/sensor/sensor.h b/esphome/components/m3_vedirect/sensor/sensor.h index 107e2f8868d9..21fa61b19891 100644 --- a/esphome/components/m3_vedirect/sensor/sensor.h +++ b/esphome/components/m3_vedirect/sensor/sensor.h @@ -6,49 +6,26 @@ namespace esphome { namespace m3_vedirect { -class HFSensor : public esphome::sensor::Sensor, public HFEntity { +class Sensor : public esphome::sensor::Sensor, public VEDirectEntity { public: - HFSensor(Manager *manager, register_id_t id) : HFEntity(manager, id) {} - - void dynamic_register() override; + Sensor(Manager *manager) : VEDirectEntity(manager) {} + void set_text_scale(float scale) { this->text_scale_ = scale; } + void set_hex_scale(float scale) { this->hex_scale_ = scale; } void set_hex_data_type(HexFrame::DataType hex_data_type) { this->hex_data_type_ = hex_data_type; } + void parse_text_value(const char *text_value) override; void parse_hex_value(const HexFrame *hexframe) override; - protected: - float scale_{1.}; - HexFrame::DataType hex_data_type_{HexFrame::DataType::unknown}; -}; - -/* -template class HexSensor : public Sensor { - public: - HexSensor(Manager *manager, const VEDirectEntityDef &def) : Sensor(manager, def) {} - - void parse_hex_value(const HexFrame *hexframe) override { - if (hexframe->data_size() == sizeof(T)) { - float state = (*(T *) hexframe->data_ptr()) / this->scale_; - if (state != this->raw_state) - publish_state(state); - } - }; -}; -*/ - -class TFSensor : public esphome::sensor::Sensor, public TFEntity { - public: - TFSensor(Manager *manager, const char *label, const DEF *def); - TFSensor(Manager *manager, const char *label) : TFSensor(manager, label, TFEntity::get_def(label)) {} - void dynamic_register() override; - void set_scale(float scale) { scale_ = scale; } + protected: + float text_scale_{1.}; - void parse_text_value(const char *text_value) override; + void init_text_def_(const TEXT_DEF *text_def) override; - protected: - float scale_{1.}; + float hex_scale_{1.}; + HexFrame::DataType hex_data_type_{HexFrame::DataType::unknown}; }; } // namespace m3_vedirect diff --git a/esphome/components/m3_vedirect/text_sensor/__init__.py b/esphome/components/m3_vedirect/text_sensor/__init__.py index ed96d89643a5..39867b00b243 100644 --- a/esphome/components/m3_vedirect/text_sensor/__init__.py +++ b/esphome/components/m3_vedirect/text_sensor/__init__.py @@ -1,12 +1,11 @@ -import esphome.config_validation as cv from esphome.components import text_sensor +import esphome.config_validation as cv from .. import ( - CONF_HEXFRAME, - CONF_TEXTFRAME, - HEX_ENTITY_SCHEMA, - TEXT_ENTITY_SCHEMA, + CONF_VEDIRECT_ENTITIES, + VEDIRECT_ENTITY_SCHEMA, m3_vedirect_ns, + new_vedirect_entity, vedirect_platform_schema, vedirect_platform_to_code, ) @@ -17,18 +16,13 @@ ) # m3_vedirect::TextSensor mapped to HEX/TEXT data -HFTextSensor = m3_vedirect_ns.class_("HFTextSensor", text_sensor.TextSensor) -TFTextSensor = m3_vedirect_ns.class_("TFTextSensor", text_sensor.TextSensor) -HEXTEXTSENSOR_SCHEMA = text_sensor.text_sensor_schema(HFTextSensor).extend( - HEX_ENTITY_SCHEMA -) -TEXTTEXTSENSOR_SCHEMA = text_sensor.text_sensor_schema(TFTextSensor).extend( - TEXT_ENTITY_SCHEMA +VEDirectTextSensor = m3_vedirect_ns.class_("TextSensor", text_sensor.TextSensor) +VEDIRECT_TEXT_SENSOR_SCHEMA = text_sensor.text_sensor_schema(VEDirectTextSensor).extend( + VEDIRECT_ENTITY_SCHEMA ) PLATFORM_ENTITIES = { - CONF_HEXFRAME: cv.ensure_list(HEXTEXTSENSOR_SCHEMA), - CONF_TEXTFRAME: cv.ensure_list(TEXTTEXTSENSOR_SCHEMA), + CONF_VEDIRECT_ENTITIES: cv.ensure_list(VEDIRECT_TEXT_SENSOR_SCHEMA), "rawhexframe": _diagnostic_text_sensor_schema, "rawtextframe": _diagnostic_text_sensor_schema, } @@ -36,11 +30,16 @@ CONFIG_SCHEMA = vedirect_platform_schema(PLATFORM_ENTITIES) +async def new_vedirect_text_sensor(config, *args): + var = await new_vedirect_entity(config, *args) + await text_sensor.register_text_sensor(var, config) + return var + + async def to_code(config: dict): await vedirect_platform_to_code( config, PLATFORM_ENTITIES, - text_sensor.new_text_sensor, - text_sensor.new_text_sensor, + new_vedirect_text_sensor, text_sensor.new_text_sensor, ) diff --git a/esphome/components/m3_vedirect/text_sensor/text_sensor.cpp b/esphome/components/m3_vedirect/text_sensor/text_sensor.cpp index 040fd2507f39..93d1458cd1f5 100644 --- a/esphome/components/m3_vedirect/text_sensor/text_sensor.cpp +++ b/esphome/components/m3_vedirect/text_sensor/text_sensor.cpp @@ -6,41 +6,22 @@ namespace esphome { namespace m3_vedirect { -// -// TextSensor -// -void HFTextSensor::dynamic_register() { - char *object_id = new char[7]; - sprintf(object_id, "0x%04X", (int) this->id); - char *name = new char[16]; - sprintf(name, "Register %s", object_id); - // name and object_id should likely need to be freed - this->manager->setup_entity_name_id(this, name, object_id); - App.register_text_sensor(this); - if (api::global_api_server) - add_on_state_callback([this](std::string state) { api::global_api_server->on_text_sensor_update(this, state); }); +void TextSensor::parse_text_value(const char *text_value) { + if (strcmp(this->raw_state.c_str(), text_value)) + publish_state(std::string(text_value)); } -void HFTextSensor::parse_hex_value(const HexFrame *hexframe) { +void TextSensor::parse_hex_value(const HexFrame *hexframe) { std::string hex_value; if (hexframe->data_to_hex(hex_value) && (this->raw_state != hex_value)) publish_state(hex_value); } -TFTextSensor::TFTextSensor(Manager *manager, const char *label, const DEF *def) : TFEntity(manager, label, def) { - manager->setup_entity_name_id(this, def ? def->description : label, label); -} - -void TFTextSensor::dynamic_register() { +void TextSensor::dynamic_register() { App.register_text_sensor(this); if (api::global_api_server) add_on_state_callback([this](std::string state) { api::global_api_server->on_text_sensor_update(this, state); }); } -void TFTextSensor::parse_text_value(const char *text_value) { - if (strcmp(this->raw_state.c_str(), text_value)) - publish_state(std::string(text_value)); -} - } // namespace m3_vedirect } // namespace esphome diff --git a/esphome/components/m3_vedirect/text_sensor/text_sensor.h b/esphome/components/m3_vedirect/text_sensor/text_sensor.h index 21a19a4b42d2..80b1b722b336 100644 --- a/esphome/components/m3_vedirect/text_sensor/text_sensor.h +++ b/esphome/components/m3_vedirect/text_sensor/text_sensor.h @@ -6,28 +6,14 @@ namespace esphome { namespace m3_vedirect { -class HFTextSensor : public esphome::text_sensor::TextSensor, public HFEntity { +class TextSensor : public esphome::text_sensor::TextSensor, public VEDirectEntity { public: - /// @brief Builds a text sensor from a static definition - /// @param def - // TextSensor(Manager *manager, const VEDirectEntityDef &def); - /// @brief Builds a text sensor for a TEXT frame or HEX register lacking definition - /// @param text_name - HFTextSensor(Manager *manager, register_id_t id) : HFEntity(manager, id) {} - - void dynamic_register() override; + TextSensor(Manager *manager) : VEDirectEntity(manager) {} + void parse_text_value(const char *text_value) override; void parse_hex_value(const HexFrame *hexframe) override; -}; - -class TFTextSensor : public esphome::text_sensor::TextSensor, public TFEntity { - public: - TFTextSensor(Manager *manager, const char *label, const DEF *def); - TFTextSensor(Manager *manager, const char *label) : TFTextSensor(manager, label, TFEntity::get_def(label)) {} void dynamic_register() override; - - void parse_text_value(const char *text_value) override; }; } // namespace m3_vedirect