From d084160b33d402241877436053267007afd05d52 Mon Sep 17 00:00:00 2001 From: j0ta29 Date: Sun, 12 Nov 2023 17:58:22 +0000 Subject: [PATCH] added manual configurable device_info text_sensor --- esphome/components/optolink/__init__.py | 4 - .../optolink/binary_sensor/__init__.py | 13 ++- .../components/optolink/number/__init__.py | 2 + .../components/optolink/select/__init__.py | 1 + .../components/optolink/sensor/__init__.py | 6 +- .../components/optolink/switch/__init__.py | 29 ++++--- .../optolink/text_sensor/__init__.py | 9 +- .../text_sensor/optolink_text_sensor.cpp | 82 +++++++++++++------ .../text_sensor/optolink_text_sensor.h | 4 +- 9 files changed, 99 insertions(+), 51 deletions(-) diff --git a/esphome/components/optolink/__init__.py b/esphome/components/optolink/__init__.py index deb268f981..60362a41de 100644 --- a/esphome/components/optolink/__init__.py +++ b/esphome/components/optolink/__init__.py @@ -4,7 +4,6 @@ import esphome.codegen as cg from esphome.components import text_sensor as ts import esphome.config_validation as cv from esphome.const import ( - CONF_ADDRESS, CONF_DIV_RATIO, CONF_ID, CONF_LOGGER, @@ -42,8 +41,6 @@ SENSOR_BASE_SCHEMA = cv.Schema( cv.positive_time_period_milliseconds, cv.Range(min=core.TimePeriod(seconds=1), max=core.TimePeriod(seconds=1800)), ), - cv.Required(CONF_ADDRESS): cv.hex_uint32_t, - # cv.Required(CONF_BYTES): cv.one_of(1, 2, 4, int=True), cv.Optional(CONF_DIV_RATIO, default=1): cv.one_of( 1, 10, 100, 1000, 3600, int=True ), @@ -79,7 +76,6 @@ CONFIG_SCHEMA = cv.All( ), cv.Optional(CONF_LOGGER, default=False): cv.boolean, cv.Optional(CONF_STATE): cv.string, - cv.Optional(CONF_DEVICE_INFO): cv.string, } ).extend(cv.COMPONENT_SCHEMA), cv.only_with_arduino, diff --git a/esphome/components/optolink/binary_sensor/__init__.py b/esphome/components/optolink/binary_sensor/__init__.py index 7eb50287e4..52fb20c842 100644 --- a/esphome/components/optolink/binary_sensor/__init__.py +++ b/esphome/components/optolink/binary_sensor/__init__.py @@ -1,4 +1,5 @@ import esphome.codegen as cg +import esphome.config_validation as cv from esphome.components import binary_sensor from esphome.const import CONF_ADDRESS, CONF_ID from .. import SENSOR_BASE_SCHEMA, optolink_ns, CONF_OPTOLINK_ID @@ -10,8 +11,16 @@ CODEOWNERS = ["@j0ta29"] OptolinkBinarySensor = optolink_ns.class_( "OptolinkBinarySensor", binary_sensor.BinarySensor, cg.PollingComponent ) -CONFIG_SCHEMA = binary_sensor.binary_sensor_schema(OptolinkBinarySensor).extend( - SENSOR_BASE_SCHEMA + +CONFIG_SCHEMA = ( + binary_sensor.BINARY_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(OptolinkBinarySensor), + cv.Required(CONF_ADDRESS): cv.hex_uint32_t, + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(SENSOR_BASE_SCHEMA) ) diff --git a/esphome/components/optolink/number/__init__.py b/esphome/components/optolink/number/__init__.py index c1c21a1724..8c173e96d8 100644 --- a/esphome/components/optolink/number/__init__.py +++ b/esphome/components/optolink/number/__init__.py @@ -20,6 +20,7 @@ OptolinkNumber = optolink_ns.class_( "OptolinkNumber", number.Number, cg.PollingComponent ) + CONFIG_SCHEMA = ( number.NUMBER_SCHEMA.extend( { @@ -27,6 +28,7 @@ CONFIG_SCHEMA = ( cv.Required(CONF_MAX_VALUE): cv.float_, cv.Required(CONF_MIN_VALUE): cv.float_range(min=0.0), cv.Required(CONF_STEP): cv.float_, + cv.Required(CONF_ADDRESS): cv.hex_uint32_t, cv.Required(CONF_BYTES): cv.one_of(1, 2, 4, int=True), } ) diff --git a/esphome/components/optolink/select/__init__.py b/esphome/components/optolink/select/__init__.py index 18333865f4..b1f846c4fd 100644 --- a/esphome/components/optolink/select/__init__.py +++ b/esphome/components/optolink/select/__init__.py @@ -43,6 +43,7 @@ CONFIG_SCHEMA = ( cg.std_ns.class_("map").template(cg.std_string, cg.std_string) ), cv.Required(CONF_MAP): cv.ensure_list(validate_mapping), + cv.Required(CONF_ADDRESS): cv.hex_uint32_t, cv.Required(CONF_BYTES): cv.one_of(1, 2, 4, int=True), } ) diff --git a/esphome/components/optolink/sensor/__init__.py b/esphome/components/optolink/sensor/__init__.py index c159d5e432..a7ada97826 100644 --- a/esphome/components/optolink/sensor/__init__.py +++ b/esphome/components/optolink/sensor/__init__.py @@ -17,12 +17,14 @@ OptolinkSensor = optolink_ns.class_( "OptolinkSensor", sensor.Sensor, cg.PollingComponent ) CONFIG_SCHEMA = ( - sensor.sensor_schema(OptolinkSensor) - .extend( + sensor.SENSOR_SCHEMA.extend( { + cv.GenerateID(): cv.declare_id(OptolinkSensor), + cv.Required(CONF_ADDRESS): cv.hex_uint32_t, cv.Required(CONF_BYTES): cv.one_of(1, 2, 4, int=True), } ) + .extend(cv.COMPONENT_SCHEMA) .extend(SENSOR_BASE_SCHEMA) ) diff --git a/esphome/components/optolink/switch/__init__.py b/esphome/components/optolink/switch/__init__.py index 7fabb71470..0d47229ca5 100644 --- a/esphome/components/optolink/switch/__init__.py +++ b/esphome/components/optolink/switch/__init__.py @@ -3,7 +3,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import switch from esphome.const import CONF_ADDRESS, CONF_ID, CONF_UPDATE_INTERVAL -from .. import OptolinkComponent, optolink_ns +from .. import SENSOR_BASE_SCHEMA, optolink_ns DEPENDENCIES = ["optolink"] CODEOWNERS = ["@j0ta29"] @@ -14,17 +14,22 @@ OptolinkSwitch = optolink_ns.class_( ) CONF_OPTOLINK_ID = "optolink_id" -CONFIG_SCHEMA = switch.SWITCH_SCHEMA.extend( - { - cv.GenerateID(CONF_OPTOLINK_ID): cv.use_id(OptolinkComponent), - cv.GenerateID(): cv.declare_id(OptolinkSwitch), - cv.Required(CONF_ADDRESS): cv.hex_uint32_t, - cv.Optional(CONF_UPDATE_INTERVAL, default="10s"): cv.All( - cv.positive_time_period_milliseconds, - cv.Range(min=core.TimePeriod(seconds=1), max=core.TimePeriod(seconds=1800)), - ), - } -).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = ( + switch.SWITCH_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(OptolinkSwitch), + cv.Required(CONF_ADDRESS): cv.hex_uint32_t, + cv.Optional(CONF_UPDATE_INTERVAL, default="10s"): cv.All( + cv.positive_time_period_milliseconds, + cv.Range( + min=core.TimePeriod(seconds=1), max=core.TimePeriod(seconds=1800) + ), + ), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(SENSOR_BASE_SCHEMA) +) async def to_code(config): diff --git a/esphome/components/optolink/text_sensor/__init__.py b/esphome/components/optolink/text_sensor/__init__.py index fe1db8e852..c6300438a5 100644 --- a/esphome/components/optolink/text_sensor/__init__.py +++ b/esphome/components/optolink/text_sensor/__init__.py @@ -20,6 +20,7 @@ MODE = { "RAW": TextSensorMode.RAW, "DAY_SCHEDULE": TextSensorMode.DAY_SCHEDULE, "DAY_SCHEDULE_SYNCHRONIZED": TextSensorMode.DAY_SCHEDULE_SYNCHRONIZED, + "DEVICE_INFO": TextSensorMode.DEVICE_INFO, } DAY_OF_WEEK = { "MONDAY": 0, @@ -93,15 +94,16 @@ def check_entity_id(): CONFIG_SCHEMA = cv.All( - text_sensor.text_sensor_schema(OptolinkTextSensor) - .extend( + text_sensor.TEXT_SENSOR_SCHEMA.extend( { + cv.GenerateID(): cv.declare_id(OptolinkTextSensor), cv.Optional(CONF_MODE, default="MAP"): cv.enum(MODE, upper=True), cv.Optional(CONF_BYTES): cv.int_range(min=1, max=9), cv.Optional(CONF_DAY_OF_WEEK): cv.enum(DAY_OF_WEEK, upper=True), cv.Optional(CONF_ENTITY_ID): cv.entity_id, } ) + .extend(cv.COMPONENT_SCHEMA) .extend(SENSOR_BASE_SCHEMA), check_bytes(), check_dow(), @@ -117,7 +119,8 @@ async def to_code(config): await text_sensor.register_text_sensor(var, config) cg.add(var.set_mode(config[CONF_MODE])) - cg.add(var.set_address(config[CONF_ADDRESS])) + if CONF_ADDRESS in config: + cg.add(var.set_address(config[CONF_ADDRESS])) cg.add(var.set_div_ratio(config[CONF_DIV_RATIO])) if CONF_BYTES in config: cg.add(var.set_bytes(config[CONF_BYTES])) diff --git a/esphome/components/optolink/text_sensor/optolink_text_sensor.cpp b/esphome/components/optolink/text_sensor/optolink_text_sensor.cpp index 9d362e09b9..58a432eb93 100644 --- a/esphome/components/optolink/text_sensor/optolink_text_sensor.cpp +++ b/esphome/components/optolink/text_sensor/optolink_text_sensor.cpp @@ -1,5 +1,6 @@ #ifdef USE_ARDUINO +#include "esphome/core/log.h" #include "optolink_text_sensor.h" #include "../optolink.h" #include "esphome/components/api/api_server.h" @@ -75,44 +76,55 @@ uint8_t *encode_time_string(std::string input) { } void OptolinkTextSensor::setup() { - if (mode_ == RAW) { - div_ratio_ = 0; - } else if (mode_ == DAY_SCHEDULE) { - div_ratio_ = 0; - bytes_ = 8; - address_ += (8 * dow_); - } else if (mode_ == DAY_SCHEDULE_SYNCHRONIZED) { - writeable_ = true; - div_ratio_ = 0; - bytes_ = 8; - address_ += (8 * dow_); - api::global_api_server->subscribe_home_assistant_state( - this->entity_id_, optional(), [this](const std::string &state) { - ESP_LOGD(TAG, "got time values from entity '%s': %s", this->entity_id_.c_str(), state.c_str()); - uint8_t *data = encode_time_string(state); - if (data) { - update_datapoint(data, 8); - } else { - ESP_LOGW(TAG, "not changing any value of datapoint %s", datapoint_->getName()); - } - }); + switch (mode_) { + case MAP: + break; + case RAW: + div_ratio_ = 0; + break; + case DAY_SCHEDULE: + div_ratio_ = 0; + bytes_ = 8; + address_ += (8 * dow_); + break; + case DAY_SCHEDULE_SYNCHRONIZED: + writeable_ = true; + div_ratio_ = 0; + bytes_ = 8; + address_ += (8 * dow_); + api::global_api_server->subscribe_home_assistant_state( + this->entity_id_, optional(), [this](const std::string &state) { + ESP_LOGD(TAG, "got time values from entity '%s': %s", this->entity_id_.c_str(), state.c_str()); + uint8_t *data = encode_time_string(state); + if (data) { + update_datapoint(data, 8); + } else { + ESP_LOGW(TAG, "not changing any value of datapoint %s", datapoint_->getName()); + } + }); + break; + case DEVICE_INFO: + set_entity_category(esphome::ENTITY_CATEGORY_DIAGNOSTIC); + bytes_ = 4; + address_ = 0x00f8; + break; } setup_datapoint(); }; -void OptolinkTextSensor::value_changed(uint8_t *state, size_t length) { +void OptolinkTextSensor::value_changed(uint8_t *value, size_t length) { switch (mode_) { case RAW: - publish_state(std::string((const char *) state)); + publish_state(std::string((const char *) value)); break; case DAY_SCHEDULE: case DAY_SCHEDULE_SYNCHRONIZED: if (length == 8) { char buffer[6 * length + 1]; for (int i = 0; i < 8; i++) { - int hour = state[i] >> 3; - int minute = (state[i] & 0b111) * 10; - if (state[i] != 0xFF) { + int hour = value[i] >> 3; + int minute = (value[i] & 0b111) * 10; + if (value[i] != 0xFF) { sprintf(buffer + i * 6, "%02d:%02d ", hour, minute); } else { sprintf(buffer + i * 6, " "); @@ -123,12 +135,30 @@ void OptolinkTextSensor::value_changed(uint8_t *state, size_t length) { unfitting_value_type(); } break; + case DEVICE_INFO: case MAP: unfitting_value_type(); break; } }; +void OptolinkTextSensor::value_changed(uint32_t value) { + switch (mode_) { + case DEVICE_INFO: { + ESP_LOGI(TAG, "recieved data for datapoint %s: %d", datapoint_->getName(), value); + uint8_t *bytes = (uint8_t *) &value; + uint16_t tmp = esphome::byteswap(*((uint16_t *) bytes)); + std::string geraetekennung = esphome::format_hex_pretty(&tmp, 1); + std::string hardware_revision = esphome::format_hex_pretty((uint8_t *) bytes + 2, 1); + std::string software_index = esphome::format_hex_pretty((uint8_t *) bytes + 3, 1); + publish_state("Device ID: " + geraetekennung + "|Hardware Revision: " + hardware_revision + + "|Software Index: " + software_index); + } break; + default: + publish_state(std::to_string(value)); + } +}; + } // namespace optolink } // namespace esphome diff --git a/esphome/components/optolink/text_sensor/optolink_text_sensor.h b/esphome/components/optolink/text_sensor/optolink_text_sensor.h index 1f7fbb2861..0e8617547b 100644 --- a/esphome/components/optolink/text_sensor/optolink_text_sensor.h +++ b/esphome/components/optolink/text_sensor/optolink_text_sensor.h @@ -10,7 +10,7 @@ namespace esphome { namespace optolink { -enum TextSensorMode { MAP, RAW, DAY_SCHEDULE, DAY_SCHEDULE_SYNCHRONIZED }; +enum TextSensorMode { MAP, RAW, DAY_SCHEDULE, DAY_SCHEDULE_SYNCHRONIZED, DEVICE_INFO }; class OptolinkTextSensor : public OptolinkSensorBase, public esphome::text_sensor::TextSensor, @@ -30,7 +30,7 @@ class OptolinkTextSensor : public OptolinkSensorBase, void value_changed(float state) override { publish_state(std::to_string(state)); }; void value_changed(uint8_t state) override { publish_state(std::to_string(state)); }; void value_changed(uint16_t state) override { publish_state(std::to_string(state)); }; - void value_changed(uint32_t state) override { publish_state(std::to_string(state)); }; + void value_changed(uint32_t state) override; void value_changed(uint8_t *state, size_t length) override; private: