From 8fb544b4cf2e09e25ee10a8a403eb2728e77ba19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20Koek?= Date: Thu, 19 Sep 2024 15:43:47 +0000 Subject: [PATCH] something --- esphome/components/ebyte_lora/__init__.py | 74 +++++++++++++--- .../components/ebyte_lora/binary_sensor.py | 27 ++++++ .../ebyte_lora/ebyte_lora_component.cpp | 46 +++++----- .../ebyte_lora/ebyte_lora_component.h | 88 +++++++++++++------ esphome/components/ebyte_lora/sensor.py | 27 ++++++ esphome/components/ebyte_lora/switch.py | 28 ------ 6 files changed, 202 insertions(+), 88 deletions(-) create mode 100644 esphome/components/ebyte_lora/binary_sensor.py create mode 100644 esphome/components/ebyte_lora/sensor.py delete mode 100644 esphome/components/ebyte_lora/switch.py diff --git a/esphome/components/ebyte_lora/__init__.py b/esphome/components/ebyte_lora/__init__.py index fc3660a7bd..d1f3a3d3a3 100644 --- a/esphome/components/ebyte_lora/__init__.py +++ b/esphome/components/ebyte_lora/__init__.py @@ -1,25 +1,34 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins -from esphome.components import sensor, uart +from esphome.components.binary_sensor import BinarySensor +from esphome.components.sensor import Sensor +from esphome.components import uart from esphome.const import ( + CONF_BINARY_SENSORS, DEVICE_CLASS_SIGNAL_STRENGTH, STATE_CLASS_MEASUREMENT, CONF_ID, + CONF_INTERNAL, + CONF_NAME, UNIT_PERCENT, CONF_CHANNEL, + CONF_SENSORS, ) +from esphome.cpp_generator import MockObjClass CODEOWNERS = ["@danielkoek"] DEPENDENCIES = ["uart"] -AUTO_LOAD = ["uart", "sensor"] +AUTO_LOAD = ["uart"] MULTI_CONF = True ebyte_lora_ns = cg.esphome_ns.namespace("ebyte_lora") EbyteLoraComponent = ebyte_lora_ns.class_( "EbyteLoraComponent", cg.PollingComponent, uart.UARTDevice ) +CONF_REMOTE_ID = "remote_id" +CONF_PROVIDER = "provider" WorPeriod = ebyte_lora_ns.enum("WorPeriod") WOR_PERIOD_OPTIONS = { "WOR_500": WorPeriod.WOR_500, @@ -85,6 +94,7 @@ ENABLE_OPTIONS = { CONF_EBYTE_LORA_COMPONENT_ID = "ebyte_lora_component_id" +CONF_BROADCAST_ID = "broadcast_id" CONF_PIN_AUX = "pin_aux" CONF_PIN_M0 = "pin_m0" CONF_PIN_M1 = "pin_m1" @@ -104,8 +114,30 @@ CONF_SUB_PACKET = "sub_packet" CONF_SENT_SWITCH_STATE = "sent_switch_state" CONF_REPEATER = "repeater" CONF_NETWORK_ID = "network_id" -CONFIG_SCHEMA = ( - cv.Schema( + + +def sensor_validation(cls: MockObjClass): + return cv.maybe_simple_value( + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(cls), + cv.Optional(CONF_BROADCAST_ID): cv.validate_id_name, + } + ), + key=CONF_ID, + ) + + +def require_internal_with_name(config): + if CONF_NAME in config and CONF_INTERNAL not in config: + raise cv.Invalid("Must provide internal: config when using name:") + return config + + +CONFIG_SCHEMA = cv.All( + cv.polling_component_schema("15s") + .extend(uart.UART_DEVICE_SCHEMA) + .extend( { cv.GenerateID(): cv.declare_id(EbyteLoraComponent), # for communication to let us know that we can receive data @@ -116,10 +148,13 @@ CONFIG_SCHEMA = ( cv.Required(CONF_PIN_M1): pins.internal_gpio_output_pin_schema, # to be able to repeater hop cv.Required(CONF_NETWORK_ID): cv.int_range(min=0, max=255), - cv.Optional(CONF_SENT_SWITCH_STATE, default=True): cv.boolean, cv.Optional(CONF_REPEATER, default=False): cv.boolean, + cv.Optional(CONF_SENSORS): cv.ensure_list(sensor_validation(Sensor)), + cv.Optional(CONF_BINARY_SENSORS): cv.ensure_list( + sensor_validation(BinarySensor) + ), # if you want to see the rssi - cv.Optional(CONF_LORA_RSSI): sensor.sensor_schema( + cv.Optional(CONF_LORA_RSSI): Sensor.sensor_schema( device_class=DEVICE_CLASS_SIGNAL_STRENGTH, unit_of_measurement=UNIT_PERCENT, accuracy_decimals=1, @@ -163,24 +198,28 @@ CONFIG_SCHEMA = ( ), } ) - .extend(cv.polling_component_schema("60s")) - .extend(uart.UART_DEVICE_SCHEMA) +) + +SENSOR_SCHEMA = cv.Schema( + { + cv.Optional(CONF_REMOTE_ID): cv.string_strict, + cv.Required(CONF_PROVIDER): cv.valid_name, + cv.GenerateID(CONF_EBYTE_LORA_COMPONENT_ID): cv.use_id(EbyteLoraComponent), + } ) async def to_code(config): + cg.add_global(ebyte_lora_ns.using) var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) await uart.register_uart_device(var, config) - pin_aux = await cg.gpio_pin_expression(config[CONF_PIN_AUX]) cg.add(var.set_pin_aux(pin_aux)) - pin_m0 = await cg.gpio_pin_expression(config[CONF_PIN_M0]) cg.add(var.set_pin_m0(pin_m0)) pin_m1 = await cg.gpio_pin_expression(config[CONF_PIN_M1]) cg.add(var.set_pin_m1(pin_m1)) - cg.add(var.set_sent_switch_state(config[CONF_SENT_SWITCH_STATE])) cg.add(var.set_repeater(config[CONF_REPEATER])) cg.add(var.set_network_id(config[CONF_NETWORK_ID])) cg.add(var.set_addh(config[CONF_ADDH])) @@ -196,7 +235,16 @@ async def to_code(config): cg.add(var.set_enable_lbt(config[CONF_ENABLE_LBT])) cg.add(var.set_transmission_mode(config[CONF_TRANSMISSION_MODE])) cg.add(var.set_enable_rssi(config[CONF_ENABLE_RSSI])) - + for sens_conf in config.get(CONF_SENSORS, ()): + sens_id = sens_conf[CONF_ID] + sensor = await cg.get_variable(sens_id) + bcst_id = sens_conf.get(CONF_BROADCAST_ID, sens_id.id) + cg.add(var.add_sensor(bcst_id, sensor)) + for sens_conf in config.get(CONF_BINARY_SENSORS, ()): + sens_id = sens_conf[CONF_ID] + sensor = await cg.get_variable(sens_id) + bcst_id = sens_conf.get(CONF_BROADCAST_ID, sens_id.id) + cg.add(var.add_binary_sensor(bcst_id, sensor)) if CONF_LORA_RSSI in config: - sens = await sensor.new_sensor(config[CONF_LORA_RSSI]) + sens = await Sensor.new_sensor(config[CONF_LORA_RSSI]) cg.add(var.set_rssi_sensor(sens)) diff --git a/esphome/components/ebyte_lora/binary_sensor.py b/esphome/components/ebyte_lora/binary_sensor.py new file mode 100644 index 0000000000..74b5291636 --- /dev/null +++ b/esphome/components/ebyte_lora/binary_sensor.py @@ -0,0 +1,27 @@ +import esphome.codegen as cg +from esphome.components import binary_sensor +from esphome.config_validation import All, has_at_least_one_key +from esphome.const import CONF_ID + +from . import ( + CONF_PROVIDER, + CONF_REMOTE_ID, + CONF_EBYTE_LORA_COMPONENT_ID, + SENSOR_SCHEMA, + require_internal_with_name, +) + +DEPENDENCIES = ["ebyte_lora"] + +CONFIG_SCHEMA = All( + binary_sensor.binary_sensor_schema().extend(SENSOR_SCHEMA), + has_at_least_one_key(CONF_ID, CONF_REMOTE_ID), + require_internal_with_name, +) + + +async def to_code(config): + var = await binary_sensor.new_binary_sensor(config) + comp = await cg.get_variable(config[CONF_EBYTE_LORA_COMPONENT_ID]) + remote_id = str(config.get(CONF_REMOTE_ID) or config.get(CONF_ID)) + cg.add(comp.add_remote_binary_sensor(config[CONF_PROVIDER], remote_id, var)) diff --git a/esphome/components/ebyte_lora/ebyte_lora_component.cpp b/esphome/components/ebyte_lora/ebyte_lora_component.cpp index 2dc31cda4c..f5d9921d65 100644 --- a/esphome/components/ebyte_lora/ebyte_lora_component.cpp +++ b/esphome/components/ebyte_lora/ebyte_lora_component.cpp @@ -414,24 +414,24 @@ void EbyteLoraComponent::loop() { this->repeat_message_(data); } // only configs with switches should sent too -#ifdef USE_SWITCH - // Make sure it is not itself - if (network_id_ != data[1]) { - ESP_LOGD(TAG, "Got switch info to process"); - // last data bit is rssi - for (int i = 2; i < data.size() - 1; i = i + 2) { - uint8_t pin = data[i]; - bool value = data[i + 1]; - for (auto *sensor : this->sensors_) { - if (pin == sensor->get_pin()) { - sensor->publish_state(value); - } - } - } - ESP_LOGD(TAG, "Updated all"); - this->send_switch_info(); - } -#endif +// #ifdef USE_SWITCH +// // Make sure it is not itself +// if (network_id_ != data[1]) { +// ESP_LOGD(TAG, "Got switch info to process"); +// // last data bit is rssi +// for (int i = 2; i < data.size() - 1; i = i + 2) { +// uint8_t pin = data[i]; +// bool value = data[i + 1]; +// for (auto *sensor : this->sensors_) { +// if (pin == sensor->get_pin()) { +// sensor->publish_state(value); +// } +// } +// } +// ESP_LOGD(TAG, "Updated all"); +// this->send_switch_info(); +// } +// #endif break; case PROGRAM_CONF: ESP_LOGD(TAG, "GOT PROGRAM_CONF"); @@ -444,7 +444,9 @@ void EbyteLoraComponent::loop() { // RSSI is always found whenever it is not program info if (data[0] != PROGRAM_CONF) { +#ifdef USE_SENSOR this->rssi_sensor_->publish_state((data[data.size() - 1] / 255.0) * 100); +#endif ESP_LOGD(TAG, "RSSI: %f", (data[data.size() - 1] / 255.0) * 100); } } @@ -497,10 +499,10 @@ void EbyteLoraComponent::send_switch_info() { std::vector data; data.push_back(SWITCH_INFO); data.push_back(network_id_); - for (auto *sensor : this->sensors_) { - data.push_back(sensor->get_pin()); - data.push_back(sensor->state); - } + // for (auto *sensor : this->sensors_) { + // data.push_back(sensor->get_pin()); + // data.push_back(sensor->state); + // } ESP_LOGD(TAG, "Sending switch info"); this->write_array(data); this->setup_wait_response_(5000); diff --git a/esphome/components/ebyte_lora/ebyte_lora_component.h b/esphome/components/ebyte_lora/ebyte_lora_component.h index 3ac7cae7e3..b020086892 100644 --- a/esphome/components/ebyte_lora/ebyte_lora_component.h +++ b/esphome/components/ebyte_lora/ebyte_lora_component.h @@ -1,18 +1,40 @@ #pragma once + +#include "esphome/core/component.h" +#ifdef USE_SENSOR +#include "esphome/components/sensor/sensor.h" +#endif +#ifdef USE_BINARY_SENSOR +#include "esphome/components/binary_sensor/binary_sensor.h" +#endif #include #include -#include "esphome/core/component.h" -#include "esphome/components/sensor/sensor.h" +#include #include "esphome/core/helpers.h" #include "esphome/components/uart/uart.h" #include "esphome/core/log.h" #include "config.h" -#ifdef USE_SWITCH -#include "esphome/components/switch/switch.h" -#endif + namespace esphome { namespace ebyte_lora { + +#ifdef USE_SENSOR +struct Sensor { + sensor::Sensor *sensor; + const char *id; + bool updated; +}; +#endif + +#ifdef USE_BINARY_SENSOR +struct BinarySensor { + binary_sensor::BinarySensor *sensor; + const char *id; + bool updated; +}; +#endif + static const char *const TAG = "ebyte_lora"; static const int MAX_SIZE_TX_PACKET = 200; @@ -21,8 +43,6 @@ enum ModeType { NORMAL = 0, WOR_SEND = 1, WOR_RECEIVER = 2, CONFIGURATION = 3, M // 1 byte, 8 bits in total // note that the data sheets shows the order in reverse -// has to be defined first, will be implemented later -class EbyteLoraSwitch; class EbyteLoraComponent : public PollingComponent, public uart::UARTDevice { public: void setup() override; @@ -31,10 +51,35 @@ class EbyteLoraComponent : public PollingComponent, public uart::UARTDevice { void loop() override; void dump_config() override; + +#ifdef USE_SENSOR + void add_sensor(const char *id, sensor::Sensor *sensor) { + Sensor st{sensor, id, true}; + this->sensors_.push_back(st); + } + void add_remote_sensor(const char *hostname, const char *remote_id, sensor::Sensor *sensor) { + //this->add_provider(hostname); + this->remote_sensors_[hostname][remote_id] = sensor; + } +#endif +#ifdef USE_BINARY_SENSOR + void add_binary_sensor(const char *id, binary_sensor::BinarySensor *sensor) { + BinarySensor st{sensor, id, true}; + this->binary_sensors_.push_back(st); + } + + void add_remote_binary_sensor(const char *hostname, const char *remote_id, binary_sensor::BinarySensor *sensor) { + // this->add_provider(hostname); + this->remote_binary_sensors_[hostname][remote_id] = sensor; + } +#endif + void send_switch_info(); + +#ifdef USE_SENSOR void set_rssi_sensor(sensor::Sensor *rssi_sensor) { rssi_sensor_ = rssi_sensor; } +#endif void set_pin_aux(InternalGPIOPin *pin_aux) { pin_aux_ = pin_aux; } - void set_switch(EbyteLoraSwitch *obj) { this->sensors_.push_back(obj); } void set_pin_m0(InternalGPIOPin *pin_m0) { pin_m0_ = pin_m0; } void set_pin_m1(InternalGPIOPin *pin_m1) { pin_m1_ = pin_m1; } void set_addh(uint8_t addh) { expected_config_.addh = addh; } @@ -55,7 +100,6 @@ class EbyteLoraComponent : public PollingComponent, public uart::UARTDevice { void set_network_id(int id) { network_id_ = id; } private: - std::vector sensors_; ModeType mode_ = MODE_INIT; // set WOR mode void set_mode_(ModeType mode); @@ -85,26 +129,20 @@ class EbyteLoraComponent : public PollingComponent, public uart::UARTDevice { std::string raw_message_; RegisterConfig current_config_; RegisterConfig expected_config_; +#ifdef USE_SENSOR + std::vector sensors_{}; + std::map> remote_sensors_{}; +#endif +#ifdef USE_BINARY_SENSOR + std::vector binary_sensors_{}; + std::map> remote_binary_sensors_{}; +#endif +#ifdef USE_SENSOR sensor::Sensor *rssi_sensor_{nullptr}; +#endif InternalGPIOPin *pin_aux_{nullptr}; InternalGPIOPin *pin_m0_{nullptr}; InternalGPIOPin *pin_m1_{nullptr}; }; -#ifdef USE_SWITCH -class EbyteLoraSwitch : public switch_::Switch, public Parented { - public: - void set_pin(uint8_t pin) { pin_ = pin; } - uint8_t get_pin() { return pin_; } - - protected: - void write_state(bool state) override { - // set it first - this->publish_state(state); - // then tell the world about it - this->parent_->send_switch_info(); - } - uint8_t pin_; -}; -#endif } // namespace ebyte_lora } // namespace esphome diff --git a/esphome/components/ebyte_lora/sensor.py b/esphome/components/ebyte_lora/sensor.py new file mode 100644 index 0000000000..69dd23163e --- /dev/null +++ b/esphome/components/ebyte_lora/sensor.py @@ -0,0 +1,27 @@ +import esphome.codegen as cg +from esphome.components.sensor import new_sensor, sensor_schema +from esphome.config_validation import All, has_at_least_one_key +from esphome.const import CONF_ID + +from . import ( + CONF_PROVIDER, + CONF_REMOTE_ID, + CONF_EBYTE_LORA_COMPONENT_ID, + SENSOR_SCHEMA, + require_internal_with_name, +) + +DEPENDENCIES = ["udp"] + +CONFIG_SCHEMA = All( + sensor_schema().extend(SENSOR_SCHEMA), + has_at_least_one_key(CONF_ID, CONF_REMOTE_ID), + require_internal_with_name, +) + + +async def to_code(config): + var = await new_sensor(config) + comp = await cg.get_variable(config[CONF_EBYTE_LORA_COMPONENT_ID]) + remote_id = str(config.get(CONF_REMOTE_ID) or config.get(CONF_ID)) + cg.add(comp.add_remote_sensor(config[CONF_PROVIDER], remote_id, var)) diff --git a/esphome/components/ebyte_lora/switch.py b/esphome/components/ebyte_lora/switch.py deleted file mode 100644 index fceddedc38..0000000000 --- a/esphome/components/ebyte_lora/switch.py +++ /dev/null @@ -1,28 +0,0 @@ -import esphome.codegen as cg -import esphome.config_validation as cv -from esphome.components import switch -from . import EbyteLoraComponent, CONF_EBYTE_LORA_COMPONENT_ID, ebyte_lora_ns - - -DEPENDENCIES = ["ebyte_lora"] -EbyteLoraSwitch = ebyte_lora_ns.class_("EbyteLoraSwitch", switch.Switch, cg.Component) - -PIN_TO_SEND = "pin_to_send" -CONFIG_SCHEMA = ( - switch.switch_schema(EbyteLoraSwitch) - .extend( - { - cv.GenerateID(CONF_EBYTE_LORA_COMPONENT_ID): cv.use_id(EbyteLoraComponent), - cv.Required(PIN_TO_SEND): cv.int_range(min=1, max=4), - } - ) - .extend(cv.COMPONENT_SCHEMA) -) - - -async def to_code(config): - ebyte_lora_component = await cg.get_variable(config[CONF_EBYTE_LORA_COMPONENT_ID]) - var = await switch.new_switch(config) - await cg.register_parented(var, config[CONF_EBYTE_LORA_COMPONENT_ID]) - cg.add(var.set_pin(config[PIN_TO_SEND])) - cg.add(ebyte_lora_component.set_switch(var))