text_sensor DAY_SCHEDULE_SYNCHRONIZED replaced with text DAY_SCHEDULE

This commit is contained in:
j0ta29 2024-03-26 20:02:11 +00:00
parent bc00df307e
commit 164991e4f5
11 changed files with 358 additions and 196 deletions

View File

@ -21,6 +21,17 @@ MULTI_CONF = False
optolink_ns = cg.esphome_ns.namespace("optolink")
CONF_OPTOLINK_ID = "optolink_id"
DAY_OF_WEEK = {
"MONDAY": 0,
"TUESDAY": 1,
"WEDNESDAY": 2,
"THURSDAY": 3,
"FRIDAY": 4,
"SATURDAY": 5,
"SUNDAY": 6,
}
CONF_DAY_OF_WEEK = "day_of_week"
OptolinkComponent = optolink_ns.class_("Optolink", cg.Component)
CONF_OPTOLINK_ID = "optolink_id"
SENSOR_BASE_SCHEMA = cv.Schema(

View File

@ -11,9 +11,6 @@ namespace optolink {
static const char *const TAG = "optolink.datapoint_component";
// NOLINTNEXTLINE
static std::vector<HassSubscription> hass_subscriptions_;
void DatapointComponent::setup_datapoint_() {
switch (div_ratio_) {
case 0:
@ -261,38 +258,6 @@ void DatapointComponent::set_optolink_state_(const char *format, ...) {
std::string DatapointComponent::get_optolink_state_() { return optolink_->get_state(); }
void DatapointComponent::subscribe_hass_(const std::string &entity_id, const std::function<void(std::string)> &f) {
for (auto &subscription : hass_subscriptions_) {
if (subscription.entity_id == entity_id) {
subscription.callbacks.push_back(f);
return;
}
}
// NOLINTNEXTLINE
HassSubscription subscription{entity_id, ""};
subscription.callbacks.push_back(f);
hass_subscriptions_.push_back(subscription);
#ifdef USE_API
if (api::global_api_server != nullptr) {
api::global_api_server->subscribe_home_assistant_state(
entity_id, optional<std::string>(), [entity_id](const std::string &state) {
ESP_LOGD(TAG, "received schedule plan from HASS entity '%s': %s", entity_id.c_str(), state.c_str());
for (auto &subscription : hass_subscriptions_) {
if (subscription.last_state != state) {
if (subscription.entity_id == entity_id) {
subscription.last_state = state;
for (const auto &callback : subscription.callbacks) {
callback(state);
}
}
}
}
});
}
#endif
}
void conv2_100_F::encode(uint8_t *out, DPValue in) {
int16_t tmp = floor((in.getFloat() * 100) + 0.5);
out[1] = tmp >> 8;

View File

@ -11,12 +11,6 @@ namespace optolink {
class Optolink;
struct HassSubscription {
std::string entity_id;
std::string last_state;
std::vector<std::function<void(std::string)>> callbacks;
};
class DatapointComponent {
public:
DatapointComponent(Optolink *optolink, bool writeable = false) : dp_value_outstanding_((uint8_t) 0) {
@ -55,8 +49,6 @@ class DatapointComponent {
void set_optolink_state_(const char *format, ...);
std::string get_optolink_state_();
void subscribe_hass_(const std::string &entity_id, const std::function<void(std::string)> &f);
private:
const size_t max_retries_until_reset_ = 10;
Optolink *optolink_;

View File

@ -0,0 +1,89 @@
#ifdef USE_ARDUINO
#include "helpers.h"
#include "esphome/core/log.h"
#include <string.h>
namespace esphome {
namespace optolink {
static const char *const TAG = "optolink.helpers";
void rtrim(std::string &s) {
if (s.empty())
return;
std::string::iterator p;
for (p = s.end(); p != s.begin() && *--p == ' ';)
;
if (*p != ' ')
p++;
s.erase(p, s.end());
}
std::string decode_day_schedule(uint8_t *input) {
char buffer[49];
for (int i = 0; i < 8; i++) {
int hour = input[i] >> 3;
int minute = (input[i] & 0b111) * 10;
if (input[i] != 0xFF) {
sprintf(buffer + i * 6, "%02d:%02d ", hour, minute);
} else {
sprintf(buffer + i * 6, " ");
}
}
return std::string(buffer);
}
uint8_t *encode_day_schedule(const std::string &input, uint8_t *output) {
char buffer[49];
strncpy(buffer, input.c_str(), sizeof(buffer));
buffer[sizeof(buffer) - 1] = 0x00;
Time time_values[8];
Time prev_time = {0, 0};
int time_count = 0;
char *token = strtok(buffer, " ");
while (token && time_count < 8) {
Time current_time;
// NOLINTNEXTLINE
if (sscanf(token, "%d:%d", &current_time.hours, &current_time.minutes) == 2) {
if (check_time_values(current_time) && check_time_sequence(prev_time, current_time)) {
time_values[time_count++] = current_time;
prev_time = current_time;
} else {
ESP_LOGE(
TAG,
"Time values should be in the format hh:mm and in increasing order within the range of 00:00 to 23:59");
return nullptr;
}
} else {
ESP_LOGE(TAG, "Invalid time format");
return nullptr;
}
token = strtok(nullptr, " ");
}
if (time_count % 2) {
ESP_LOGE(TAG, "Number of time values must be even");
return nullptr;
}
while (time_count < 8) {
time_values[time_count++] = {31, 70};
}
for (int i = 0; i < 8; i++) {
Time time = time_values[i];
output[i] = (time.hours << 3) + (time.minutes / 10);
}
return output;
}
} // namespace optolink
} // namespace esphome
#endif

View File

@ -0,0 +1,31 @@
#ifdef USE_ARDUINO
#include <cstdint>
#include <string>
namespace esphome {
namespace optolink {
struct Time {
int hours;
int minutes;
};
inline bool check_time_sequence(const Time &t1, const Time &t2) {
return t2.hours > t1.hours || (t2.hours == t1.hours && t2.minutes >= t1.minutes);
}
inline bool check_time_values(const Time &time) {
return (time.hours >= 0 && time.hours <= 23) && (time.minutes >= 0 && time.minutes <= 59);
}
void rtrim(std::string &s);
std::string decode_day_schedule(uint8_t *input);
uint8_t *encode_day_schedule(const std::string &input, uint8_t *output);
} // namespace optolink
} // namespace esphome
#endif

View File

@ -0,0 +1,62 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import text
from esphome.const import (
CONF_ADDRESS,
CONF_BYTES,
CONF_DIV_RATIO,
CONF_ENTITY_ID,
CONF_ID,
CONF_TYPE,
CONF_MODE,
)
from .. import (
CONF_DAY_OF_WEEK,
DAY_OF_WEEK,
optolink_ns,
CONF_OPTOLINK_ID,
SENSOR_BASE_SCHEMA,
)
DEPENDENCIES = ["optolink", "api"]
CODEOWNERS = ["@j0ta29"]
TextType = optolink_ns.enum("TextType")
TYPE = {"DAY_SCHEDULE": TextType.TEXT_TYPE_DAY_SCHEDULE}
OptolinkText = optolink_ns.class_("OptolinkText", text.Text, cg.PollingComponent)
CONFIG_SCHEMA = cv.All(
text.TEXT_SCHEMA.extend(
{
cv.GenerateID(): cv.declare_id(OptolinkText),
cv.Optional(CONF_MODE, default="TEXT"): cv.enum(text.TEXT_MODES),
cv.Required(CONF_TYPE): cv.enum(TYPE, upper=True),
cv.Required(CONF_ADDRESS): cv.hex_uint32_t,
cv.Required(CONF_BYTES): cv.one_of(56, int=True),
cv.Required(CONF_DAY_OF_WEEK): cv.enum(DAY_OF_WEEK, upper=True),
}
)
.extend(cv.COMPONENT_SCHEMA)
.extend(SENSOR_BASE_SCHEMA),
)
async def to_code(config):
component = await cg.get_variable(config[CONF_OPTOLINK_ID])
var = cg.new_Pvariable(config[CONF_ID], component)
await cg.register_component(var, config)
await text.register_text(var, config)
cg.add(var.set_type(config[CONF_TYPE]))
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]))
if CONF_DAY_OF_WEEK in config:
cg.add(var.set_day_of_week(config[CONF_DAY_OF_WEEK]))
if CONF_ENTITY_ID in config:
cg.add(var.set_entity_id(config[CONF_ENTITY_ID]))

View File

@ -0,0 +1,58 @@
#ifdef USE_ARDUINO
#include "esphome/core/log.h"
#include "optolink_text.h"
#include "../optolink.h"
#include "../datapoint_component.h"
#include "../helpers.h"
namespace esphome {
namespace optolink {
static const char *const TAG = "optolink.text";
void OptolinkText::setup() {
switch (type_) {
case TEXT_TYPE_DAY_SCHEDULE:
set_writeable(true);
set_div_ratio(0);
set_bytes(8);
set_address(get_address_() + 8 * dow_);
traits.set_max_length(48);
traits.set_pattern("(((([0-1]?[0-9]|2[0-3]):[0-5]0)( |$)){2})*");
break;
}
setup_datapoint_();
};
void OptolinkText::control(const std::string &value) {
ESP_LOGE(TAG, "control %s", value.c_str());
ESP_LOGD(TAG, "update for schedule plan for component %s: %s", get_component_name().c_str(), value.c_str());
uint8_t buffer[8];
uint8_t *data = encode_day_schedule(value, buffer);
if (data) {
write_datapoint_value_(data, 8);
} else {
ESP_LOGW(TAG, "not changing any value of datapoint %s", get_component_name().c_str());
}
}
void OptolinkText::datapoint_value_changed(uint8_t *value, size_t length) {
switch (type_) {
case TEXT_TYPE_DAY_SCHEDULE:
if (length == 8) {
auto schedule = decode_day_schedule(value);
rtrim(schedule);
publish_state(schedule);
} else {
unfitting_value_type_();
}
break;
}
};
} // namespace optolink
} // namespace esphome
#endif

View File

@ -0,0 +1,37 @@
#pragma once
#ifdef USE_ARDUINO
#include "esphome/components/text/text.h"
#include "../optolink.h"
#include "../datapoint_component.h"
namespace esphome {
namespace optolink {
enum TextType { TEXT_TYPE_DAY_SCHEDULE };
class OptolinkText : public DatapointComponent, public esphome::text::Text, public esphome::PollingComponent {
public:
OptolinkText(Optolink *optolink) : DatapointComponent(optolink) {}
void set_type(TextType type) { type_ = type; }
void set_day_of_week(int dow) { dow_ = dow; }
protected:
void setup() override;
void update() override { datapoint_read_request_(); }
void control(const std::string &value);
const StringRef &get_component_name() override { return get_name(); }
void datapoint_value_changed(uint8_t *value, size_t length) override;
private:
TextType type_;
int dow_ = 0;
};
} // namespace optolink
} // namespace esphome
#endif

View File

@ -7,32 +7,28 @@ from esphome.const import (
CONF_DIV_RATIO,
CONF_ENTITY_ID,
CONF_ID,
CONF_MODE,
CONF_TYPE,
)
from .. import (
CONF_DAY_OF_WEEK,
DAY_OF_WEEK,
optolink_ns,
CONF_OPTOLINK_ID,
SENSOR_BASE_SCHEMA,
)
from .. import optolink_ns, CONF_OPTOLINK_ID, SENSOR_BASE_SCHEMA
DEPENDENCIES = ["optolink", "api"]
CODEOWNERS = ["@j0ta29"]
TextSensorMode = optolink_ns.enum("TextSensorMode")
MODE = {
"MAP": TextSensorMode.MAP,
"RAW": TextSensorMode.RAW,
"DAY_SCHEDULE": TextSensorMode.DAY_SCHEDULE,
"DAY_SCHEDULE_SYNCHRONIZED": TextSensorMode.DAY_SCHEDULE_SYNCHRONIZED,
"DEVICE_INFO": TextSensorMode.DEVICE_INFO,
"STATE_INFO": TextSensorMode.STATE_INFO,
TextSensorType = optolink_ns.enum("TextSensorType")
TYPE = {
"MAP": TextSensorType.TEXT_SENSOR_TYPE_MAP,
"RAW": TextSensorType.TEXT_SENSOR_TYPE_RAW,
"DAY_SCHEDULE": TextSensorType.TEXT_SENSOR_TYPE_DAY_SCHEDULE,
"DAY_SCHEDULE_SYNCHRONIZED": TextSensorType.TEXT_SENSOR_TYPE_DAY_SCHEDULE_SYNCHRONIZED,
"DEVICE_INFO": TextSensorType.TEXT_SENSOR_TYPE_DEVICE_INFO,
"STATE_INFO": TextSensorType.TEXT_SENSOR_TYPE_STATE_INFO,
}
DAY_OF_WEEK = {
"MONDAY": 0,
"TUESDAY": 1,
"WEDNESDAY": 2,
"THURSDAY": 3,
"FRIDAY": 4,
"SATURDAY": 5,
"SUNDAY": 6,
}
CONF_DAY_OF_WEEK = "day_of_week"
OptolinkTextSensor = optolink_ns.class_(
"OptolinkTextSensor", text_sensor.TextSensor, cg.PollingComponent
@ -41,21 +37,21 @@ OptolinkTextSensor = optolink_ns.class_(
def check_address():
def validator_(config):
modes_address_needed = [
types_address_needed = [
"MAP",
"RAW",
"DAY_SCHEDULE",
"DAY_SCHEDULE_SYNCHRONIZED",
]
address_needed = config[CONF_MODE] in modes_address_needed
address_needed = config[CONF_TYPE] in types_address_needed
address_defined = CONF_ADDRESS in config
if address_needed and not address_defined:
raise cv.Invalid(
f"{CONF_ADDRESS} is required in this modes: {modes_address_needed}"
f"{CONF_ADDRESS} is required for this types: {types_address_needed}"
)
if not address_needed and address_defined:
raise cv.Invalid(
f"{CONF_ADDRESS} is only allowed in this modes mode: {modes_address_needed}"
f"{CONF_ADDRESS} is only allowed for this types: {types_address_needed}"
)
return config
@ -64,32 +60,32 @@ def check_address():
def check_bytes():
def validator_(config):
modes_bytes_needed = ["MAP", "RAW", "DAY_SCHEDULE", "DAY_SCHEDULE_SYNCHRONIZED"]
bytes_needed = config[CONF_MODE] in modes_bytes_needed
types_bytes_needed = ["MAP", "RAW", "DAY_SCHEDULE", "DAY_SCHEDULE_SYNCHRONIZED"]
bytes_needed = config[CONF_TYPE] in types_bytes_needed
bytes_defined = CONF_BYTES in config
if bytes_needed and not bytes_defined:
raise cv.Invalid(
f"{CONF_BYTES} is required in this modes: {modes_bytes_needed}"
f"{CONF_BYTES} is required for this types: {types_bytes_needed}"
)
if not bytes_needed and bytes_defined:
raise cv.Invalid(
f"{CONF_BYTES} is only allowed in this modes: {modes_bytes_needed}"
f"{CONF_BYTES} is only allowed for this types: {types_bytes_needed}"
)
modes_bytes_range_1_to_9 = ["MAP", "RAW"]
if config[CONF_MODE] in modes_bytes_range_1_to_9 and config[
types_bytes_range_1_to_9 = ["MAP", "RAW"]
if config[CONF_TYPE] in types_bytes_range_1_to_9 and config[
CONF_BYTES
] not in range(0, 10):
raise cv.Invalid(
f"{CONF_BYTES} must be between 1 and 9 for this modes: {modes_bytes_range_1_to_9}"
f"{CONF_BYTES} must be between 1 and 9 for this types: {types_bytes_range_1_to_9}"
)
modes_bytes_day_schedule = ["DAY_SCHEDULE", "DAY_SCHEDULE_SYNCHRONIZED"]
if config[CONF_MODE] in modes_bytes_day_schedule and config[CONF_BYTES] not in [
types_bytes_day_schedule = ["DAY_SCHEDULE", "DAY_SCHEDULE_SYNCHRONIZED"]
if config[CONF_TYPE] in types_bytes_day_schedule and config[CONF_BYTES] not in [
56
]:
raise cv.Invalid(
f"{CONF_BYTES} must be 56 for this modes: {modes_bytes_day_schedule}"
f"{CONF_BYTES} must be 56 for this types: {types_bytes_day_schedule}"
)
return config
@ -99,14 +95,14 @@ def check_bytes():
def check_dow():
def validator_(config):
modes_dow_needed = ["DAY_SCHEDULE", "DAY_SCHEDULE_SYNCHRONIZED"]
if config[CONF_MODE] in modes_dow_needed and CONF_DAY_OF_WEEK not in config:
types_dow_needed = ["DAY_SCHEDULE", "DAY_SCHEDULE_SYNCHRONIZED"]
if config[CONF_TYPE] in types_dow_needed and CONF_DAY_OF_WEEK not in config:
raise cv.Invalid(
f"{CONF_DAY_OF_WEEK} is required in this modes: {modes_dow_needed}"
f"{CONF_DAY_OF_WEEK} is required for this types: {types_dow_needed}"
)
if config[CONF_MODE] not in modes_dow_needed and CONF_DAY_OF_WEEK in config:
if config[CONF_TYPE] not in types_dow_needed and CONF_DAY_OF_WEEK in config:
raise cv.Invalid(
f"{CONF_DAY_OF_WEEK} is only allowed in this modes: {modes_dow_needed}"
f"{CONF_DAY_OF_WEEK} is only allowed for this types: {types_dow_needed}"
)
return config
@ -115,20 +111,20 @@ def check_dow():
def check_entity_id():
def validator_(config):
modes_entitiy_id_needed = ["DAY_SCHEDULE_SYNCHRONIZED"]
types_entitiy_id_needed = ["DAY_SCHEDULE_SYNCHRONIZED"]
if (
config[CONF_MODE] in modes_entitiy_id_needed
config[CONF_TYPE] in types_entitiy_id_needed
and CONF_ENTITY_ID not in config
):
raise cv.Invalid(
f"{CONF_ENTITY_ID} is required in this modes: {modes_entitiy_id_needed}"
f"{CONF_ENTITY_ID} is required for this types: {types_entitiy_id_needed}"
)
if (
config[CONF_MODE] not in modes_entitiy_id_needed
config[CONF_TYPE] not in types_entitiy_id_needed
and CONF_ENTITY_ID in config
):
raise cv.Invalid(
f"{CONF_ENTITY_ID} is only allowed in this modes: {modes_entitiy_id_needed}"
f"{CONF_ENTITY_ID} is only allowed for this types: {types_entitiy_id_needed}"
)
return config
@ -139,7 +135,7 @@ CONFIG_SCHEMA = cv.All(
text_sensor.TEXT_SENSOR_SCHEMA.extend(
{
cv.GenerateID(): cv.declare_id(OptolinkTextSensor),
cv.Required(CONF_MODE): cv.enum(MODE, upper=True),
cv.Required(CONF_TYPE): cv.enum(TYPE, upper=True),
cv.Optional(CONF_ADDRESS): cv.hex_uint32_t,
cv.Optional(CONF_BYTES): cv.uint8_t,
cv.Optional(CONF_DAY_OF_WEEK): cv.enum(DAY_OF_WEEK, upper=True),
@ -162,7 +158,7 @@ async def to_code(config):
await cg.register_component(var, config)
await text_sensor.register_text_sensor(var, config)
cg.add(var.set_mode(config[CONF_MODE]))
cg.add(var.set_type(config[CONF_TYPE]))
if CONF_ADDRESS in config:
cg.add(var.set_address(config[CONF_ADDRESS]))
cg.add(var.set_div_ratio(config[CONF_DIV_RATIO]))

View File

@ -4,107 +4,31 @@
#include "optolink_text_sensor.h"
#include "../optolink.h"
#include "../datapoint_component.h"
#include "../helpers.h"
namespace esphome {
namespace optolink {
static const char *const TAG = "optolink.text_sensor";
struct Time {
int hours;
int minutes;
};
bool check_time_sequence(const Time &t1, const Time &t2) {
return t2.hours > t1.hours || (t2.hours == t1.hours && t2.minutes >= t1.minutes);
}
bool check_time_values(const Time &time) {
return (time.hours >= 0 && time.hours <= 23) && (time.minutes >= 0 && time.minutes <= 59);
}
uint8_t *encode_time_string(const std::string &input) {
char buffer[49];
strncpy(buffer, input.c_str(), sizeof(buffer));
buffer[sizeof(buffer) - 1] = 0x00;
Time time_values[8];
Time prev_time = {0, 0};
int time_count = 0;
char *token = strtok(buffer, " ");
while (token && time_count < 8) {
Time current_time;
// NOLINTNEXTLINE
if (sscanf(token, "%d:%d", &current_time.hours, &current_time.minutes) == 2) {
if (check_time_values(current_time) && check_time_sequence(prev_time, current_time)) {
time_values[time_count++] = current_time;
prev_time = current_time;
} else {
ESP_LOGE(
TAG,
"Time values should be in the format hh:mm and in increasing order within the range of 00:00 to 23:59");
return nullptr;
}
} else {
ESP_LOGE(TAG, "Invalid time format");
return nullptr;
}
token = strtok(nullptr, " ");
}
if (time_count % 2) {
ESP_LOGE(TAG, "Number of time values must be even");
return nullptr;
}
while (time_count < 8) {
time_values[time_count++] = {31, 70};
}
static uint8_t data[8];
for (int i = 0; i < 8; i++) {
Time time = time_values[i];
data[i] = (time.hours << 3) + (time.minutes / 10);
}
return data;
}
void OptolinkTextSensor::setup() {
switch (mode_) {
case MAP:
switch (type_) {
case TEXT_SENSOR_TYPE_MAP:
break;
case RAW:
case TEXT_SENSOR_TYPE_RAW:
set_div_ratio(0);
break;
case DAY_SCHEDULE:
case TEXT_SENSOR_TYPE_DAY_SCHEDULE:
set_div_ratio(0);
set_bytes(8);
set_address(get_address_() + 8 * dow_);
break;
case DAY_SCHEDULE_SYNCHRONIZED:
set_writeable(true);
set_div_ratio(0);
set_bytes(8);
set_address(get_address_() + 8 * dow_);
ESP_LOGI(TAG, "subscribing to schedule plan from HASS entity '%s' for component %s", this->entity_id_.c_str(),
get_component_name().c_str());
subscribe_hass_(entity_id_, [this](const std::string &state) {
ESP_LOGD(TAG, "update for schedule plan for component %s: %s", get_component_name().c_str(), state.c_str());
uint8_t *data = encode_time_string(state);
if (data) {
write_datapoint_value_(data, 8);
} else {
ESP_LOGW(TAG, "not changing any value of datapoint %s", get_component_name().c_str());
}
});
break;
case DEVICE_INFO:
case TEXT_SENSOR_TYPE_DEVICE_INFO:
set_entity_category(esphome::ENTITY_CATEGORY_DIAGNOSTIC);
set_bytes(4);
set_address(0x00f8);
break;
case STATE_INFO:
case TEXT_SENSOR_TYPE_STATE_INFO:
set_entity_category(esphome::ENTITY_CATEGORY_DIAGNOSTIC);
return; // no datapoint setup!
}
@ -112,7 +36,7 @@ void OptolinkTextSensor::setup() {
};
void OptolinkTextSensor::update() {
if (mode_ == STATE_INFO) {
if (type_ == TEXT_SENSOR_TYPE_STATE_INFO) {
publish_state(get_optolink_state_());
} else {
datapoint_read_request_();
@ -120,39 +44,30 @@ void OptolinkTextSensor::update() {
}
void OptolinkTextSensor::datapoint_value_changed(uint8_t *value, size_t length) {
switch (mode_) {
case RAW:
switch (type_) {
case TEXT_SENSOR_TYPE_RAW:
publish_state(std::string((const char *) value));
break;
case DAY_SCHEDULE:
case DAY_SCHEDULE_SYNCHRONIZED:
case TEXT_SENSOR_TYPE_DAY_SCHEDULE:
if (length == 8) {
char buffer[6 * length + 1];
for (int i = 0; i < 8; i++) {
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, " ");
}
}
publish_state(buffer);
auto schedule = decode_day_schedule(value);
rtrim(schedule);
publish_state(schedule);
} else {
unfitting_value_type_();
}
break;
case DEVICE_INFO:
case STATE_INFO:
case MAP:
case TEXT_SENSOR_TYPE_DEVICE_INFO:
case TEXT_SENSOR_TYPE_STATE_INFO:
case TEXT_SENSOR_TYPE_MAP:
unfitting_value_type_();
break;
}
};
void OptolinkTextSensor::datapoint_value_changed(uint32_t value) {
switch (mode_) {
case DEVICE_INFO: {
switch (type_) {
case TEXT_SENSOR_TYPE_DEVICE_INFO: {
uint8_t *bytes = (uint8_t *) &value;
uint16_t tmp = esphome::byteswap(*((uint16_t *) bytes));
std::string geraetekennung = esphome::format_hex_pretty(&tmp, 1);

View File

@ -9,7 +9,13 @@
namespace esphome {
namespace optolink {
enum TextSensorMode { MAP, RAW, DAY_SCHEDULE, DAY_SCHEDULE_SYNCHRONIZED, DEVICE_INFO, STATE_INFO };
enum TextSensorType {
TEXT_SENSOR_TYPE_MAP,
TEXT_SENSOR_TYPE_RAW,
TEXT_SENSOR_TYPE_DAY_SCHEDULE,
TEXT_SENSOR_TYPE_DEVICE_INFO,
TEXT_SENSOR_TYPE_STATE_INFO
};
class OptolinkTextSensor : public DatapointComponent,
public esphome::text_sensor::TextSensor,
@ -17,7 +23,7 @@ class OptolinkTextSensor : public DatapointComponent,
public:
OptolinkTextSensor(Optolink *optolink) : DatapointComponent(optolink) {}
void set_mode(TextSensorMode mode) { mode_ = mode; }
void set_type(TextSensorType type) { type_ = type; }
void set_day_of_week(int dow) { dow_ = dow; }
void set_entity_id(const std::string &entity_id) { entity_id_ = entity_id; }
@ -33,7 +39,7 @@ class OptolinkTextSensor : public DatapointComponent,
void datapoint_value_changed(uint8_t *value, size_t length) override;
private:
TextSensorMode mode_ = MAP;
TextSensorType type_ = TEXT_SENSOR_TYPE_MAP;
int dow_ = 0;
std::string entity_id_;
};