added manual configurable device_info text_sensor

This commit is contained in:
j0ta29 2023-11-12 17:58:22 +00:00
parent a8ed21ae74
commit d084160b33
9 changed files with 99 additions and 51 deletions

View file

@ -4,7 +4,6 @@ import esphome.codegen as cg
from esphome.components import text_sensor as ts from esphome.components import text_sensor as ts
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.const import ( from esphome.const import (
CONF_ADDRESS,
CONF_DIV_RATIO, CONF_DIV_RATIO,
CONF_ID, CONF_ID,
CONF_LOGGER, CONF_LOGGER,
@ -42,8 +41,6 @@ SENSOR_BASE_SCHEMA = cv.Schema(
cv.positive_time_period_milliseconds, cv.positive_time_period_milliseconds,
cv.Range(min=core.TimePeriod(seconds=1), max=core.TimePeriod(seconds=1800)), 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( cv.Optional(CONF_DIV_RATIO, default=1): cv.one_of(
1, 10, 100, 1000, 3600, int=True 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_LOGGER, default=False): cv.boolean,
cv.Optional(CONF_STATE): cv.string, cv.Optional(CONF_STATE): cv.string,
cv.Optional(CONF_DEVICE_INFO): cv.string,
} }
).extend(cv.COMPONENT_SCHEMA), ).extend(cv.COMPONENT_SCHEMA),
cv.only_with_arduino, cv.only_with_arduino,

View file

@ -1,4 +1,5 @@
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import binary_sensor from esphome.components import binary_sensor
from esphome.const import CONF_ADDRESS, CONF_ID from esphome.const import CONF_ADDRESS, CONF_ID
from .. import SENSOR_BASE_SCHEMA, optolink_ns, CONF_OPTOLINK_ID from .. import SENSOR_BASE_SCHEMA, optolink_ns, CONF_OPTOLINK_ID
@ -10,8 +11,16 @@ CODEOWNERS = ["@j0ta29"]
OptolinkBinarySensor = optolink_ns.class_( OptolinkBinarySensor = optolink_ns.class_(
"OptolinkBinarySensor", binary_sensor.BinarySensor, cg.PollingComponent "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)
) )

View file

@ -20,6 +20,7 @@ OptolinkNumber = optolink_ns.class_(
"OptolinkNumber", number.Number, cg.PollingComponent "OptolinkNumber", number.Number, cg.PollingComponent
) )
CONFIG_SCHEMA = ( CONFIG_SCHEMA = (
number.NUMBER_SCHEMA.extend( number.NUMBER_SCHEMA.extend(
{ {
@ -27,6 +28,7 @@ CONFIG_SCHEMA = (
cv.Required(CONF_MAX_VALUE): cv.float_, cv.Required(CONF_MAX_VALUE): cv.float_,
cv.Required(CONF_MIN_VALUE): cv.float_range(min=0.0), cv.Required(CONF_MIN_VALUE): cv.float_range(min=0.0),
cv.Required(CONF_STEP): cv.float_, 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), cv.Required(CONF_BYTES): cv.one_of(1, 2, 4, int=True),
} }
) )

View file

@ -43,6 +43,7 @@ CONFIG_SCHEMA = (
cg.std_ns.class_("map").template(cg.std_string, cg.std_string) cg.std_ns.class_("map").template(cg.std_string, cg.std_string)
), ),
cv.Required(CONF_MAP): cv.ensure_list(validate_mapping), 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), cv.Required(CONF_BYTES): cv.one_of(1, 2, 4, int=True),
} }
) )

View file

@ -17,12 +17,14 @@ OptolinkSensor = optolink_ns.class_(
"OptolinkSensor", sensor.Sensor, cg.PollingComponent "OptolinkSensor", sensor.Sensor, cg.PollingComponent
) )
CONFIG_SCHEMA = ( CONFIG_SCHEMA = (
sensor.sensor_schema(OptolinkSensor) sensor.SENSOR_SCHEMA.extend(
.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), cv.Required(CONF_BYTES): cv.one_of(1, 2, 4, int=True),
} }
) )
.extend(cv.COMPONENT_SCHEMA)
.extend(SENSOR_BASE_SCHEMA) .extend(SENSOR_BASE_SCHEMA)
) )

View file

@ -3,7 +3,7 @@ import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.components import switch from esphome.components import switch
from esphome.const import CONF_ADDRESS, CONF_ID, CONF_UPDATE_INTERVAL 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"] DEPENDENCIES = ["optolink"]
CODEOWNERS = ["@j0ta29"] CODEOWNERS = ["@j0ta29"]
@ -14,17 +14,22 @@ OptolinkSwitch = optolink_ns.class_(
) )
CONF_OPTOLINK_ID = "optolink_id" CONF_OPTOLINK_ID = "optolink_id"
CONFIG_SCHEMA = switch.SWITCH_SCHEMA.extend( CONFIG_SCHEMA = (
switch.SWITCH_SCHEMA.extend(
{ {
cv.GenerateID(CONF_OPTOLINK_ID): cv.use_id(OptolinkComponent),
cv.GenerateID(): cv.declare_id(OptolinkSwitch), cv.GenerateID(): cv.declare_id(OptolinkSwitch),
cv.Required(CONF_ADDRESS): cv.hex_uint32_t, cv.Required(CONF_ADDRESS): cv.hex_uint32_t,
cv.Optional(CONF_UPDATE_INTERVAL, default="10s"): cv.All( cv.Optional(CONF_UPDATE_INTERVAL, default="10s"): cv.All(
cv.positive_time_period_milliseconds, cv.positive_time_period_milliseconds,
cv.Range(min=core.TimePeriod(seconds=1), max=core.TimePeriod(seconds=1800)), cv.Range(
min=core.TimePeriod(seconds=1), max=core.TimePeriod(seconds=1800)
),
), ),
} }
).extend(cv.COMPONENT_SCHEMA) )
.extend(cv.COMPONENT_SCHEMA)
.extend(SENSOR_BASE_SCHEMA)
)
async def to_code(config): async def to_code(config):

View file

@ -20,6 +20,7 @@ MODE = {
"RAW": TextSensorMode.RAW, "RAW": TextSensorMode.RAW,
"DAY_SCHEDULE": TextSensorMode.DAY_SCHEDULE, "DAY_SCHEDULE": TextSensorMode.DAY_SCHEDULE,
"DAY_SCHEDULE_SYNCHRONIZED": TextSensorMode.DAY_SCHEDULE_SYNCHRONIZED, "DAY_SCHEDULE_SYNCHRONIZED": TextSensorMode.DAY_SCHEDULE_SYNCHRONIZED,
"DEVICE_INFO": TextSensorMode.DEVICE_INFO,
} }
DAY_OF_WEEK = { DAY_OF_WEEK = {
"MONDAY": 0, "MONDAY": 0,
@ -93,15 +94,16 @@ def check_entity_id():
CONFIG_SCHEMA = cv.All( CONFIG_SCHEMA = cv.All(
text_sensor.text_sensor_schema(OptolinkTextSensor) text_sensor.TEXT_SENSOR_SCHEMA.extend(
.extend(
{ {
cv.GenerateID(): cv.declare_id(OptolinkTextSensor),
cv.Optional(CONF_MODE, default="MAP"): cv.enum(MODE, upper=True), 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_BYTES): cv.int_range(min=1, max=9),
cv.Optional(CONF_DAY_OF_WEEK): cv.enum(DAY_OF_WEEK, upper=True), cv.Optional(CONF_DAY_OF_WEEK): cv.enum(DAY_OF_WEEK, upper=True),
cv.Optional(CONF_ENTITY_ID): cv.entity_id, cv.Optional(CONF_ENTITY_ID): cv.entity_id,
} }
) )
.extend(cv.COMPONENT_SCHEMA)
.extend(SENSOR_BASE_SCHEMA), .extend(SENSOR_BASE_SCHEMA),
check_bytes(), check_bytes(),
check_dow(), check_dow(),
@ -117,6 +119,7 @@ async def to_code(config):
await text_sensor.register_text_sensor(var, config) await text_sensor.register_text_sensor(var, config)
cg.add(var.set_mode(config[CONF_MODE])) cg.add(var.set_mode(config[CONF_MODE]))
if CONF_ADDRESS in config:
cg.add(var.set_address(config[CONF_ADDRESS])) cg.add(var.set_address(config[CONF_ADDRESS]))
cg.add(var.set_div_ratio(config[CONF_DIV_RATIO])) cg.add(var.set_div_ratio(config[CONF_DIV_RATIO]))
if CONF_BYTES in config: if CONF_BYTES in config:

View file

@ -1,5 +1,6 @@
#ifdef USE_ARDUINO #ifdef USE_ARDUINO
#include "esphome/core/log.h"
#include "optolink_text_sensor.h" #include "optolink_text_sensor.h"
#include "../optolink.h" #include "../optolink.h"
#include "esphome/components/api/api_server.h" #include "esphome/components/api/api_server.h"
@ -75,13 +76,18 @@ uint8_t *encode_time_string(std::string input) {
} }
void OptolinkTextSensor::setup() { void OptolinkTextSensor::setup() {
if (mode_ == RAW) { switch (mode_) {
case MAP:
break;
case RAW:
div_ratio_ = 0; div_ratio_ = 0;
} else if (mode_ == DAY_SCHEDULE) { break;
case DAY_SCHEDULE:
div_ratio_ = 0; div_ratio_ = 0;
bytes_ = 8; bytes_ = 8;
address_ += (8 * dow_); address_ += (8 * dow_);
} else if (mode_ == DAY_SCHEDULE_SYNCHRONIZED) { break;
case DAY_SCHEDULE_SYNCHRONIZED:
writeable_ = true; writeable_ = true;
div_ratio_ = 0; div_ratio_ = 0;
bytes_ = 8; bytes_ = 8;
@ -96,23 +102,29 @@ void OptolinkTextSensor::setup() {
ESP_LOGW(TAG, "not changing any value of datapoint %s", datapoint_->getName()); 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(); setup_datapoint();
}; };
void OptolinkTextSensor::value_changed(uint8_t *state, size_t length) { void OptolinkTextSensor::value_changed(uint8_t *value, size_t length) {
switch (mode_) { switch (mode_) {
case RAW: case RAW:
publish_state(std::string((const char *) state)); publish_state(std::string((const char *) value));
break; break;
case DAY_SCHEDULE: case DAY_SCHEDULE:
case DAY_SCHEDULE_SYNCHRONIZED: case DAY_SCHEDULE_SYNCHRONIZED:
if (length == 8) { if (length == 8) {
char buffer[6 * length + 1]; char buffer[6 * length + 1];
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
int hour = state[i] >> 3; int hour = value[i] >> 3;
int minute = (state[i] & 0b111) * 10; int minute = (value[i] & 0b111) * 10;
if (state[i] != 0xFF) { if (value[i] != 0xFF) {
sprintf(buffer + i * 6, "%02d:%02d ", hour, minute); sprintf(buffer + i * 6, "%02d:%02d ", hour, minute);
} else { } else {
sprintf(buffer + i * 6, " "); sprintf(buffer + i * 6, " ");
@ -123,12 +135,30 @@ void OptolinkTextSensor::value_changed(uint8_t *state, size_t length) {
unfitting_value_type(); unfitting_value_type();
} }
break; break;
case DEVICE_INFO:
case MAP: case MAP:
unfitting_value_type(); unfitting_value_type();
break; 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 optolink
} // namespace esphome } // namespace esphome

View file

@ -10,7 +10,7 @@
namespace esphome { namespace esphome {
namespace optolink { 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, class OptolinkTextSensor : public OptolinkSensorBase,
public esphome::text_sensor::TextSensor, 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(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(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(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; void value_changed(uint8_t *state, size_t length) override;
private: private: