mirror of
https://github.com/esphome/esphome.git
synced 2024-11-25 08:28:12 +01: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:
parent
efa6fd03e5
commit
fdda47db6e
7 changed files with 476 additions and 0 deletions
|
@ -82,6 +82,7 @@ esphome/components/hitachi_ac424/* @sourabhjaiswal
|
||||||
esphome/components/homeassistant/* @OttoWinter
|
esphome/components/homeassistant/* @OttoWinter
|
||||||
esphome/components/honeywellabp/* @RubyBailey
|
esphome/components/honeywellabp/* @RubyBailey
|
||||||
esphome/components/hrxl_maxsonar_wr/* @netmikey
|
esphome/components/hrxl_maxsonar_wr/* @netmikey
|
||||||
|
esphome/components/hydreon_rgxx/* @functionpointer
|
||||||
esphome/components/i2c/* @esphome/core
|
esphome/components/i2c/* @esphome/core
|
||||||
esphome/components/improv_serial/* @esphome/core
|
esphome/components/improv_serial/* @esphome/core
|
||||||
esphome/components/ina260/* @MrEditor97
|
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'
|
name: 'Temperature'
|
||||||
humidity:
|
humidity:
|
||||||
name: '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
|
- platform: adc
|
||||||
pin: VCC
|
pin: VCC
|
||||||
id: my_sensor
|
id: my_sensor
|
||||||
|
@ -796,6 +814,10 @@ binary_sensor:
|
||||||
then:
|
then:
|
||||||
- cover.toggle: time_based_cover
|
- cover.toggle: time_based_cover
|
||||||
- cover.toggle: endstop_cover
|
- cover.toggle: endstop_cover
|
||||||
|
- platform: hydreon_rgxx
|
||||||
|
hydreon_rgxx_id: "hydreon_rg9"
|
||||||
|
too_cold:
|
||||||
|
name: "rg9_toocold"
|
||||||
- platform: template
|
- platform: template
|
||||||
id: 'pzemac_reset_energy'
|
id: 'pzemac_reset_energy'
|
||||||
on_press:
|
on_press:
|
||||||
|
|
Loading…
Reference in a new issue