mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Add integration hydreon_rgxx for rain sensors by Hydreon (#2711)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
		| @@ -82,6 +82,7 @@ esphome/components/hitachi_ac424/* @sourabhjaiswal | ||||
| esphome/components/homeassistant/* @OttoWinter | ||||
| esphome/components/honeywellabp/* @RubyBailey | ||||
| esphome/components/hrxl_maxsonar_wr/* @netmikey | ||||
| esphome/components/hydreon_rgxx/* @functionpointer | ||||
| esphome/components/i2c/* @esphome/core | ||||
| esphome/components/improv_serial/* @esphome/core | ||||
| esphome/components/ina260/* @MrEditor97 | ||||
|   | ||||
							
								
								
									
										11
									
								
								esphome/components/hydreon_rgxx/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								esphome/components/hydreon_rgxx/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| import esphome.codegen as cg | ||||
| from esphome.components import uart | ||||
|  | ||||
| CODEOWNERS = ["@functionpointer"] | ||||
| DEPENDENCIES = ["uart"] | ||||
|  | ||||
| hydreon_rgxx_ns = cg.esphome_ns.namespace("hydreon_rgxx") | ||||
| RGModel = hydreon_rgxx_ns.enum("RGModel") | ||||
| HydreonRGxxComponent = hydreon_rgxx_ns.class_( | ||||
|     "HydreonRGxxComponent", cg.PollingComponent, uart.UARTDevice | ||||
| ) | ||||
							
								
								
									
										36
									
								
								esphome/components/hydreon_rgxx/binary_sensor.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								esphome/components/hydreon_rgxx/binary_sensor.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import binary_sensor | ||||
| from esphome.const import ( | ||||
|     CONF_ID, | ||||
|     DEVICE_CLASS_COLD, | ||||
| ) | ||||
|  | ||||
| from . import hydreon_rgxx_ns, HydreonRGxxComponent | ||||
|  | ||||
| CONF_HYDREON_RGXX_ID = "hydreon_rgxx_id" | ||||
| CONF_TOO_COLD = "too_cold" | ||||
|  | ||||
| HydreonRGxxBinarySensor = hydreon_rgxx_ns.class_( | ||||
|     "HydreonRGxxBinaryComponent", cg.Component | ||||
| ) | ||||
|  | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(HydreonRGxxBinarySensor), | ||||
|         cv.GenerateID(CONF_HYDREON_RGXX_ID): cv.use_id(HydreonRGxxComponent), | ||||
|         cv.Optional(CONF_TOO_COLD): binary_sensor.binary_sensor_schema( | ||||
|             device_class=DEVICE_CLASS_COLD | ||||
|         ), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| async def to_code(config): | ||||
|     main_sensor = await cg.get_variable(config[CONF_HYDREON_RGXX_ID]) | ||||
|     bin_component = cg.new_Pvariable(config[CONF_ID], main_sensor) | ||||
|     await cg.register_component(bin_component, config) | ||||
|     if CONF_TOO_COLD in config: | ||||
|         tc = await binary_sensor.new_binary_sensor(config[CONF_TOO_COLD]) | ||||
|         cg.add(main_sensor.set_too_cold_sensor(tc)) | ||||
							
								
								
									
										211
									
								
								esphome/components/hydreon_rgxx/hydreon_rgxx.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										211
									
								
								esphome/components/hydreon_rgxx/hydreon_rgxx.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,211 @@ | ||||
| #include "hydreon_rgxx.h" | ||||
| #include "esphome/core/log.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace hydreon_rgxx { | ||||
|  | ||||
| static const char *const TAG = "hydreon_rgxx.sensor"; | ||||
| static const int MAX_DATA_LENGTH_BYTES = 80; | ||||
| static const uint8_t ASCII_LF = 0x0A; | ||||
| #define HYDREON_RGXX_COMMA , | ||||
| static const char *const PROTOCOL_NAMES[] = {HYDREON_RGXX_PROTOCOL_LIST(, HYDREON_RGXX_COMMA)}; | ||||
|  | ||||
| void HydreonRGxxComponent::dump_config() { | ||||
|   this->check_uart_settings(9600, 1, esphome::uart::UART_CONFIG_PARITY_NONE, 8); | ||||
|   ESP_LOGCONFIG(TAG, "hydreon_rgxx:"); | ||||
|   if (this->is_failed()) { | ||||
|     ESP_LOGE(TAG, "Connection with hydreon_rgxx failed!"); | ||||
|   } | ||||
|   LOG_UPDATE_INTERVAL(this); | ||||
|  | ||||
|   int i = 0; | ||||
| #define HYDREON_RGXX_LOG_SENSOR(s) \ | ||||
|   if (this->sensors_[i++] != nullptr) { \ | ||||
|     LOG_SENSOR("  ", #s, this->sensors_[i - 1]); \ | ||||
|   } | ||||
|   HYDREON_RGXX_PROTOCOL_LIST(HYDREON_RGXX_LOG_SENSOR, ); | ||||
| } | ||||
|  | ||||
| void HydreonRGxxComponent::setup() { | ||||
|   ESP_LOGCONFIG(TAG, "Setting up hydreon_rgxx..."); | ||||
|   while (this->available() != 0) { | ||||
|     this->read(); | ||||
|   } | ||||
|   this->schedule_reboot_(); | ||||
| } | ||||
|  | ||||
| bool HydreonRGxxComponent::sensor_missing_() { | ||||
|   if (this->sensors_received_ == -1) { | ||||
|     // no request sent yet, don't check | ||||
|     return false; | ||||
|   } else { | ||||
|     if (this->sensors_received_ == 0) { | ||||
|       ESP_LOGW(TAG, "No data at all"); | ||||
|       return true; | ||||
|     } | ||||
|     for (int i = 0; i < NUM_SENSORS; i++) { | ||||
|       if (this->sensors_[i] == nullptr) { | ||||
|         continue; | ||||
|       } | ||||
|       if ((this->sensors_received_ >> i & 1) == 0) { | ||||
|         ESP_LOGW(TAG, "Missing %s", PROTOCOL_NAMES[i]); | ||||
|         return true; | ||||
|       } | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
| } | ||||
|  | ||||
| void HydreonRGxxComponent::update() { | ||||
|   if (this->boot_count_ > 0) { | ||||
|     if (this->sensor_missing_()) { | ||||
|       this->no_response_count_++; | ||||
|       ESP_LOGE(TAG, "data missing %d times", this->no_response_count_); | ||||
|       if (this->no_response_count_ > 15) { | ||||
|         ESP_LOGE(TAG, "asking sensor to reboot"); | ||||
|         for (auto &sensor : this->sensors_) { | ||||
|           if (sensor != nullptr) { | ||||
|             sensor->publish_state(NAN); | ||||
|           } | ||||
|         } | ||||
|         this->schedule_reboot_(); | ||||
|         return; | ||||
|       } | ||||
|     } else { | ||||
|       this->no_response_count_ = 0; | ||||
|     } | ||||
|     this->write_str("R\n"); | ||||
| #ifdef USE_BINARY_SENSOR | ||||
|     if (this->too_cold_sensor_ != nullptr) { | ||||
|       this->too_cold_sensor_->publish_state(this->too_cold_); | ||||
|     } | ||||
| #endif | ||||
|     this->too_cold_ = false; | ||||
|     this->sensors_received_ = 0; | ||||
|   } | ||||
| } | ||||
|  | ||||
| void HydreonRGxxComponent::loop() { | ||||
|   uint8_t data; | ||||
|   while (this->available() > 0) { | ||||
|     if (this->read_byte(&data)) { | ||||
|       buffer_ += (char) data; | ||||
|       if (this->buffer_.back() == static_cast<char>(ASCII_LF) || this->buffer_.length() >= MAX_DATA_LENGTH_BYTES) { | ||||
|         // complete line received | ||||
|         this->process_line_(); | ||||
|         this->buffer_.clear(); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Communication with the sensor is asynchronous. | ||||
|  * We send requests and let esphome continue doing its thing. | ||||
|  * Once we have received a complete line, we process it. | ||||
|  * | ||||
|  * Catching communication failures is done in two layers: | ||||
|  * | ||||
|  * 1. We check if all requested data has been received | ||||
|  *    before we send out the next request. If data keeps | ||||
|  *    missing, we escalate. | ||||
|  * 2. Request the sensor to reboot. We retry based on | ||||
|  *    a timeout. If the sensor does not respond after | ||||
|  *    several boot attempts, we give up. | ||||
|  */ | ||||
| void HydreonRGxxComponent::schedule_reboot_() { | ||||
|   this->boot_count_ = 0; | ||||
|   this->set_interval("reboot", 5000, [this]() { | ||||
|     if (this->boot_count_ < 0) { | ||||
|       ESP_LOGW(TAG, "hydreon_rgxx failed to boot %d times", -this->boot_count_); | ||||
|     } | ||||
|     this->boot_count_--; | ||||
|     this->write_str("K\n"); | ||||
|     if (this->boot_count_ < -5) { | ||||
|       ESP_LOGE(TAG, "hydreon_rgxx can't boot, giving up"); | ||||
|       for (auto &sensor : this->sensors_) { | ||||
|         if (sensor != nullptr) { | ||||
|           sensor->publish_state(NAN); | ||||
|         } | ||||
|       } | ||||
|       this->mark_failed(); | ||||
|     } | ||||
|   }); | ||||
| } | ||||
|  | ||||
| bool HydreonRGxxComponent::buffer_starts_with_(const std::string &prefix) { | ||||
|   return this->buffer_starts_with_(prefix.c_str()); | ||||
| } | ||||
|  | ||||
| bool HydreonRGxxComponent::buffer_starts_with_(const char *prefix) { return buffer_.rfind(prefix, 0) == 0; } | ||||
|  | ||||
| void HydreonRGxxComponent::process_line_() { | ||||
|   ESP_LOGV(TAG, "Read from serial: %s", this->buffer_.substr(0, this->buffer_.size() - 2).c_str()); | ||||
|  | ||||
|   if (buffer_[0] == ';') { | ||||
|     ESP_LOGI(TAG, "Comment: %s", this->buffer_.substr(0, this->buffer_.size() - 2).c_str()); | ||||
|     return; | ||||
|   } | ||||
|   if (this->buffer_starts_with_("PwrDays")) { | ||||
|     if (this->boot_count_ <= 0) { | ||||
|       this->boot_count_ = 1; | ||||
|     } else { | ||||
|       this->boot_count_++; | ||||
|     } | ||||
|     this->cancel_interval("reboot"); | ||||
|     this->no_response_count_ = 0; | ||||
|     ESP_LOGI(TAG, "Boot detected: %s", this->buffer_.substr(0, this->buffer_.size() - 2).c_str()); | ||||
|     this->write_str("P\nH\nM\n");  // set sensor to polling mode, high res mode, metric mode | ||||
|     return; | ||||
|   } | ||||
|   if (this->buffer_starts_with_("SW")) { | ||||
|     std::string::size_type majend = this->buffer_.find('.'); | ||||
|     std::string::size_type endversion = this->buffer_.find(' ', 3); | ||||
|     if (majend == std::string::npos || endversion == std::string::npos || majend > endversion) { | ||||
|       ESP_LOGW(TAG, "invalid version string: %s", this->buffer_.substr(0, this->buffer_.size() - 2).c_str()); | ||||
|     } | ||||
|     int major = strtol(this->buffer_.substr(3, majend - 3).c_str(), nullptr, 10); | ||||
|     int minor = strtol(this->buffer_.substr(majend + 1, endversion - (majend + 1)).c_str(), nullptr, 10); | ||||
|  | ||||
|     if (major > 10 || minor >= 1000 || minor < 0 || major < 0) { | ||||
|       ESP_LOGW(TAG, "invalid version: %s", this->buffer_.substr(0, this->buffer_.size() - 2).c_str()); | ||||
|     } | ||||
|     this->sw_version_ = major * 1000 + minor; | ||||
|     ESP_LOGI(TAG, "detected sw version %i", this->sw_version_); | ||||
|     return; | ||||
|   } | ||||
|   bool is_data_line = false; | ||||
|   for (int i = 0; i < NUM_SENSORS; i++) { | ||||
|     if (this->sensors_[i] != nullptr && this->buffer_starts_with_(PROTOCOL_NAMES[i])) { | ||||
|       is_data_line = true; | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
|   if (is_data_line) { | ||||
|     std::string::size_type tc = this->buffer_.find("TooCold"); | ||||
|     this->too_cold_ |= tc != std::string::npos; | ||||
|     if (this->too_cold_) { | ||||
|       ESP_LOGD(TAG, "Received TooCold"); | ||||
|     } | ||||
|     for (int i = 0; i < NUM_SENSORS; i++) { | ||||
|       if (this->sensors_[i] == nullptr) { | ||||
|         continue; | ||||
|       } | ||||
|       std::string::size_type n = this->buffer_.find(PROTOCOL_NAMES[i]); | ||||
|       if (n == std::string::npos) { | ||||
|         continue; | ||||
|       } | ||||
|       int data = strtol(this->buffer_.substr(n + strlen(PROTOCOL_NAMES[i])).c_str(), nullptr, 10); | ||||
|       this->sensors_[i]->publish_state(data); | ||||
|       ESP_LOGD(TAG, "Received %s: %f", PROTOCOL_NAMES[i], this->sensors_[i]->get_raw_state()); | ||||
|       this->sensors_received_ |= (1 << i); | ||||
|     } | ||||
|   } else { | ||||
|     ESP_LOGI(TAG, "Got unknown line: %s", this->buffer_.c_str()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| float HydreonRGxxComponent::get_setup_priority() const { return setup_priority::DATA; } | ||||
|  | ||||
| }  // namespace hydreon_rgxx | ||||
| }  // namespace esphome | ||||
							
								
								
									
										76
									
								
								esphome/components/hydreon_rgxx/hydreon_rgxx.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								esphome/components/hydreon_rgxx/hydreon_rgxx.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "esphome/core/component.h" | ||||
| #include "esphome/core/defines.h" | ||||
| #include "esphome/components/sensor/sensor.h" | ||||
| #ifdef USE_BINARY_SENSOR | ||||
| #include "esphome/components/binary_sensor/binary_sensor.h" | ||||
| #endif | ||||
| #include "esphome/components/uart/uart.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace hydreon_rgxx { | ||||
|  | ||||
| enum RGModel { | ||||
|   RG9 = 1, | ||||
|   RG15 = 2, | ||||
| }; | ||||
|  | ||||
| #ifdef HYDREON_RGXX_NUM_SENSORS | ||||
| static const uint8_t NUM_SENSORS = HYDREON_RGXX_NUM_SENSORS; | ||||
| #else | ||||
| static const uint8_t NUM_SENSORS = 1; | ||||
| #endif | ||||
|  | ||||
| #ifndef HYDREON_RGXX_PROTOCOL_LIST | ||||
| #define HYDREON_RGXX_PROTOCOL_LIST(F, SEP) F("") | ||||
| #endif | ||||
|  | ||||
| class HydreonRGxxComponent : public PollingComponent, public uart::UARTDevice { | ||||
|  public: | ||||
|   void set_sensor(sensor::Sensor *sensor, int index) { this->sensors_[index] = sensor; } | ||||
| #ifdef USE_BINARY_SENSOR | ||||
|   void set_too_cold_sensor(binary_sensor::BinarySensor *sensor) { this->too_cold_sensor_ = sensor; } | ||||
| #endif | ||||
|   void set_model(RGModel model) { model_ = model; } | ||||
|  | ||||
|   /// Schedule data readings. | ||||
|   void update() override; | ||||
|   /// Read data once available | ||||
|   void loop() override; | ||||
|   /// Setup the sensor and test for a connection. | ||||
|   void setup() override; | ||||
|   void dump_config() override; | ||||
|  | ||||
|   float get_setup_priority() const override; | ||||
|  | ||||
|  protected: | ||||
|   void process_line_(); | ||||
|   void schedule_reboot_(); | ||||
|   bool buffer_starts_with_(const std::string &prefix); | ||||
|   bool buffer_starts_with_(const char *prefix); | ||||
|   bool sensor_missing_(); | ||||
|  | ||||
|   sensor::Sensor *sensors_[NUM_SENSORS] = {nullptr}; | ||||
| #ifdef USE_BINARY_SENSOR | ||||
|   binary_sensor::BinarySensor *too_cold_sensor_ = nullptr; | ||||
| #endif | ||||
|  | ||||
|   int16_t boot_count_ = 0; | ||||
|   int16_t no_response_count_ = 0; | ||||
|   std::string buffer_; | ||||
|   RGModel model_ = RG9; | ||||
|   int sw_version_ = 0; | ||||
|   bool too_cold_ = false; | ||||
|  | ||||
|   // bit field showing which sensors we have received data for | ||||
|   int sensors_received_ = -1; | ||||
| }; | ||||
|  | ||||
| class HydreonRGxxBinaryComponent : public Component { | ||||
|  public: | ||||
|   HydreonRGxxBinaryComponent(HydreonRGxxComponent *parent) {} | ||||
| }; | ||||
|  | ||||
| }  // namespace hydreon_rgxx | ||||
| }  // namespace esphome | ||||
							
								
								
									
										119
									
								
								esphome/components/hydreon_rgxx/sensor.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								esphome/components/hydreon_rgxx/sensor.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,119 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import uart, sensor | ||||
| from esphome.const import ( | ||||
|     CONF_ID, | ||||
|     CONF_MODEL, | ||||
|     CONF_MOISTURE, | ||||
|     DEVICE_CLASS_HUMIDITY, | ||||
|     STATE_CLASS_MEASUREMENT, | ||||
| ) | ||||
|  | ||||
| from . import RGModel, HydreonRGxxComponent | ||||
|  | ||||
| UNIT_INTENSITY = "intensity" | ||||
| UNIT_MILLIMETERS = "mm" | ||||
| UNIT_MILLIMETERS_PER_HOUR = "mm/h" | ||||
|  | ||||
| CONF_ACC = "acc" | ||||
| CONF_EVENT_ACC = "event_acc" | ||||
| CONF_TOTAL_ACC = "total_acc" | ||||
| CONF_R_INT = "r_int" | ||||
|  | ||||
| RG_MODELS = { | ||||
|     "RG_9": RGModel.RG9, | ||||
|     "RG_15": RGModel.RG15, | ||||
|     # https://rainsensors.com/wp-content/uploads/sites/3/2020/07/rg-15_instructions_sw_1.000.pdf | ||||
|     # https://rainsensors.com/wp-content/uploads/sites/3/2021/03/2020.08.25-rg-9_instructions.pdf | ||||
|     # https://rainsensors.com/wp-content/uploads/sites/3/2021/03/2021.03.11-rg-9_instructions.pdf | ||||
| } | ||||
| SUPPORTED_SENSORS = { | ||||
|     CONF_ACC: ["RG_15"], | ||||
|     CONF_EVENT_ACC: ["RG_15"], | ||||
|     CONF_TOTAL_ACC: ["RG_15"], | ||||
|     CONF_R_INT: ["RG_15"], | ||||
|     CONF_MOISTURE: ["RG_9"], | ||||
| } | ||||
| PROTOCOL_NAMES = { | ||||
|     CONF_MOISTURE: "R", | ||||
|     CONF_ACC: "Acc", | ||||
|     CONF_R_INT: "Rint", | ||||
|     CONF_EVENT_ACC: "EventAcc", | ||||
|     CONF_TOTAL_ACC: "TotalAcc", | ||||
| } | ||||
|  | ||||
|  | ||||
| def _validate(config): | ||||
|     for conf, models in SUPPORTED_SENSORS.items(): | ||||
|         if conf in config: | ||||
|             if config[CONF_MODEL] not in models: | ||||
|                 raise cv.Invalid( | ||||
|                     f"{conf} is only available on {' and '.join(models)}, not {config[CONF_MODEL]}" | ||||
|                 ) | ||||
|     return config | ||||
|  | ||||
|  | ||||
| CONFIG_SCHEMA = cv.All( | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(HydreonRGxxComponent), | ||||
|             cv.Required(CONF_MODEL): cv.enum( | ||||
|                 RG_MODELS, | ||||
|                 upper=True, | ||||
|                 space="_", | ||||
|             ), | ||||
|             cv.Optional(CONF_ACC): sensor.sensor_schema( | ||||
|                 unit_of_measurement=UNIT_MILLIMETERS, | ||||
|                 accuracy_decimals=2, | ||||
|                 device_class=DEVICE_CLASS_HUMIDITY, | ||||
|                 state_class=STATE_CLASS_MEASUREMENT, | ||||
|             ), | ||||
|             cv.Optional(CONF_EVENT_ACC): sensor.sensor_schema( | ||||
|                 unit_of_measurement=UNIT_MILLIMETERS, | ||||
|                 accuracy_decimals=2, | ||||
|                 device_class=DEVICE_CLASS_HUMIDITY, | ||||
|                 state_class=STATE_CLASS_MEASUREMENT, | ||||
|             ), | ||||
|             cv.Optional(CONF_TOTAL_ACC): sensor.sensor_schema( | ||||
|                 unit_of_measurement=UNIT_MILLIMETERS, | ||||
|                 accuracy_decimals=2, | ||||
|                 device_class=DEVICE_CLASS_HUMIDITY, | ||||
|                 state_class=STATE_CLASS_MEASUREMENT, | ||||
|             ), | ||||
|             cv.Optional(CONF_R_INT): sensor.sensor_schema( | ||||
|                 unit_of_measurement=UNIT_MILLIMETERS_PER_HOUR, | ||||
|                 accuracy_decimals=2, | ||||
|                 device_class=DEVICE_CLASS_HUMIDITY, | ||||
|                 state_class=STATE_CLASS_MEASUREMENT, | ||||
|             ), | ||||
|             cv.Optional(CONF_MOISTURE): sensor.sensor_schema( | ||||
|                 unit_of_measurement=UNIT_INTENSITY, | ||||
|                 accuracy_decimals=0, | ||||
|                 device_class=DEVICE_CLASS_HUMIDITY, | ||||
|                 state_class=STATE_CLASS_MEASUREMENT, | ||||
|             ), | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.polling_component_schema("60s")) | ||||
|     .extend(uart.UART_DEVICE_SCHEMA), | ||||
|     _validate, | ||||
| ) | ||||
|  | ||||
|  | ||||
| async def to_code(config): | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     await cg.register_component(var, config) | ||||
|     await uart.register_uart_device(var, config) | ||||
|  | ||||
|     cg.add_define( | ||||
|         "HYDREON_RGXX_PROTOCOL_LIST(F, sep)", | ||||
|         cg.RawExpression( | ||||
|             " sep ".join([f'F("{name}")' for name in PROTOCOL_NAMES.values()]) | ||||
|         ), | ||||
|     ) | ||||
|     cg.add_define("HYDREON_RGXX_NUM_SENSORS", len(PROTOCOL_NAMES)) | ||||
|  | ||||
|     for i, conf in enumerate(PROTOCOL_NAMES): | ||||
|         if conf in config: | ||||
|             sens = await sensor.new_sensor(config[conf]) | ||||
|             cg.add(var.set_sensor(sens, i)) | ||||
| @@ -349,6 +349,24 @@ sensor: | ||||
|       name: 'Temperature' | ||||
|     humidity: | ||||
|       name: 'Humidity' | ||||
|   - platform: hydreon_rgxx | ||||
|     model: "RG 9" | ||||
|     uart_id: uart6 | ||||
|     id: "hydreon_rg9" | ||||
|     moisture: | ||||
|       name: "hydreon_rain" | ||||
|       id: hydreon_rain | ||||
|   - platform: hydreon_rgxx | ||||
|     model: "RG_15" | ||||
|     uart_id: uart6 | ||||
|     acc: | ||||
|       name: "hydreon_acc" | ||||
|     event_acc: | ||||
|       name: "hydreon_event_acc" | ||||
|     total_acc: | ||||
|       name: "hydreon_total_acc" | ||||
|     r_int: | ||||
|       name: "hydreon_r_int" | ||||
|   - platform: adc | ||||
|     pin: VCC | ||||
|     id: my_sensor | ||||
| @@ -796,6 +814,10 @@ binary_sensor: | ||||
|       then: | ||||
|         - cover.toggle: time_based_cover | ||||
|         - cover.toggle: endstop_cover | ||||
|   - platform: hydreon_rgxx | ||||
|     hydreon_rgxx_id: "hydreon_rg9" | ||||
|     too_cold: | ||||
|       name: "rg9_toocold" | ||||
|   - platform: template | ||||
|     id: 'pzemac_reset_energy' | ||||
|     on_press: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user