mirror of
https://github.com/esphome/esphome.git
synced 2025-02-14 01:22:08 +01:00
hydreon_rgxx: Support lens_bad, em_sat and temperature (#3642)
This commit is contained in:
parent
0f6dab394a
commit
5561d4eaeb
@ -4,12 +4,15 @@ from esphome.components import binary_sensor
|
|||||||
from esphome.const import (
|
from esphome.const import (
|
||||||
CONF_ID,
|
CONF_ID,
|
||||||
DEVICE_CLASS_COLD,
|
DEVICE_CLASS_COLD,
|
||||||
|
DEVICE_CLASS_PROBLEM,
|
||||||
)
|
)
|
||||||
|
|
||||||
from . import hydreon_rgxx_ns, HydreonRGxxComponent
|
from . import hydreon_rgxx_ns, HydreonRGxxComponent
|
||||||
|
|
||||||
CONF_HYDREON_RGXX_ID = "hydreon_rgxx_id"
|
CONF_HYDREON_RGXX_ID = "hydreon_rgxx_id"
|
||||||
CONF_TOO_COLD = "too_cold"
|
CONF_TOO_COLD = "too_cold"
|
||||||
|
CONF_LENS_BAD = "lens_bad"
|
||||||
|
CONF_EM_SAT = "em_sat"
|
||||||
|
|
||||||
HydreonRGxxBinarySensor = hydreon_rgxx_ns.class_(
|
HydreonRGxxBinarySensor = hydreon_rgxx_ns.class_(
|
||||||
"HydreonRGxxBinaryComponent", cg.Component
|
"HydreonRGxxBinaryComponent", cg.Component
|
||||||
@ -23,6 +26,12 @@ CONFIG_SCHEMA = cv.Schema(
|
|||||||
cv.Optional(CONF_TOO_COLD): binary_sensor.binary_sensor_schema(
|
cv.Optional(CONF_TOO_COLD): binary_sensor.binary_sensor_schema(
|
||||||
device_class=DEVICE_CLASS_COLD
|
device_class=DEVICE_CLASS_COLD
|
||||||
),
|
),
|
||||||
|
cv.Optional(CONF_LENS_BAD): binary_sensor.binary_sensor_schema(
|
||||||
|
device_class=DEVICE_CLASS_PROBLEM,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_EM_SAT): binary_sensor.binary_sensor_schema(
|
||||||
|
device_class=DEVICE_CLASS_PROBLEM,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -31,6 +40,14 @@ async def to_code(config):
|
|||||||
main_sensor = await cg.get_variable(config[CONF_HYDREON_RGXX_ID])
|
main_sensor = await cg.get_variable(config[CONF_HYDREON_RGXX_ID])
|
||||||
bin_component = cg.new_Pvariable(config[CONF_ID], main_sensor)
|
bin_component = cg.new_Pvariable(config[CONF_ID], main_sensor)
|
||||||
await cg.register_component(bin_component, config)
|
await cg.register_component(bin_component, config)
|
||||||
if CONF_TOO_COLD in config:
|
|
||||||
tc = await binary_sensor.new_binary_sensor(config[CONF_TOO_COLD])
|
mapping = {
|
||||||
cg.add(main_sensor.set_too_cold_sensor(tc))
|
CONF_TOO_COLD: main_sensor.set_too_cold_sensor,
|
||||||
|
CONF_LENS_BAD: main_sensor.set_lens_bad_sensor,
|
||||||
|
CONF_EM_SAT: main_sensor.set_em_sat_sensor,
|
||||||
|
}
|
||||||
|
|
||||||
|
for key, value in mapping.items():
|
||||||
|
if key in config:
|
||||||
|
sensor = await binary_sensor.new_binary_sensor(config[key])
|
||||||
|
cg.add(value(sensor))
|
||||||
|
@ -9,6 +9,7 @@ static const int MAX_DATA_LENGTH_BYTES = 80;
|
|||||||
static const uint8_t ASCII_LF = 0x0A;
|
static const uint8_t ASCII_LF = 0x0A;
|
||||||
#define HYDREON_RGXX_COMMA ,
|
#define HYDREON_RGXX_COMMA ,
|
||||||
static const char *const PROTOCOL_NAMES[] = {HYDREON_RGXX_PROTOCOL_LIST(, HYDREON_RGXX_COMMA)};
|
static const char *const PROTOCOL_NAMES[] = {HYDREON_RGXX_PROTOCOL_LIST(, HYDREON_RGXX_COMMA)};
|
||||||
|
static const char *const IGNORE_STRINGS[] = {HYDREON_RGXX_IGNORE_LIST(, HYDREON_RGXX_COMMA)};
|
||||||
|
|
||||||
void HydreonRGxxComponent::dump_config() {
|
void HydreonRGxxComponent::dump_config() {
|
||||||
this->check_uart_settings(9600, 1, esphome::uart::UART_CONFIG_PARITY_NONE, 8);
|
this->check_uart_settings(9600, 1, esphome::uart::UART_CONFIG_PARITY_NONE, 8);
|
||||||
@ -34,33 +35,37 @@ void HydreonRGxxComponent::setup() {
|
|||||||
this->schedule_reboot_();
|
this->schedule_reboot_();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HydreonRGxxComponent::sensor_missing_() {
|
int HydreonRGxxComponent::num_sensors_missing_() {
|
||||||
if (this->sensors_received_ == -1) {
|
if (this->sensors_received_ == -1) {
|
||||||
// no request sent yet, don't check
|
return -1;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
int ret = NUM_SENSORS;
|
||||||
|
for (int i = 0; i < NUM_SENSORS; i++) {
|
||||||
|
if (this->sensors_[i] == nullptr) {
|
||||||
|
ret -= 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((this->sensors_received_ >> i & 1) != 0) {
|
||||||
|
ret -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HydreonRGxxComponent::update() {
|
void HydreonRGxxComponent::update() {
|
||||||
if (this->boot_count_ > 0) {
|
if (this->boot_count_ > 0) {
|
||||||
if (this->sensor_missing_()) {
|
if (this->num_sensors_missing_() > 0) {
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this->no_response_count_++;
|
this->no_response_count_++;
|
||||||
ESP_LOGE(TAG, "data missing %d times", this->no_response_count_);
|
ESP_LOGE(TAG, "missing %d sensors; %d times in a row", this->num_sensors_missing_(), this->no_response_count_);
|
||||||
if (this->no_response_count_ > 15) {
|
if (this->no_response_count_ > 15) {
|
||||||
ESP_LOGE(TAG, "asking sensor to reboot");
|
ESP_LOGE(TAG, "asking sensor to reboot");
|
||||||
for (auto &sensor : this->sensors_) {
|
for (auto &sensor : this->sensors_) {
|
||||||
@ -79,8 +84,16 @@ void HydreonRGxxComponent::update() {
|
|||||||
if (this->too_cold_sensor_ != nullptr) {
|
if (this->too_cold_sensor_ != nullptr) {
|
||||||
this->too_cold_sensor_->publish_state(this->too_cold_);
|
this->too_cold_sensor_->publish_state(this->too_cold_);
|
||||||
}
|
}
|
||||||
|
if (this->lens_bad_sensor_ != nullptr) {
|
||||||
|
this->lens_bad_sensor_->publish_state(this->lens_bad_);
|
||||||
|
}
|
||||||
|
if (this->em_sat_sensor_ != nullptr) {
|
||||||
|
this->em_sat_sensor_->publish_state(this->em_sat_);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
this->too_cold_ = false;
|
this->too_cold_ = false;
|
||||||
|
this->lens_bad_ = false;
|
||||||
|
this->em_sat_ = false;
|
||||||
this->sensors_received_ = 0;
|
this->sensors_received_ = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,6 +159,25 @@ void HydreonRGxxComponent::process_line_() {
|
|||||||
ESP_LOGI(TAG, "Comment: %s", this->buffer_.substr(0, this->buffer_.size() - 2).c_str());
|
ESP_LOGI(TAG, "Comment: %s", this->buffer_.substr(0, this->buffer_.size() - 2).c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
std::string::size_type newlineposn = this->buffer_.find('\n');
|
||||||
|
if (newlineposn <= 1) {
|
||||||
|
// allow both \r\n and \n
|
||||||
|
ESP_LOGD(TAG, "Received empty line");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (newlineposn <= 2) {
|
||||||
|
// single character lines, such as acknowledgements
|
||||||
|
ESP_LOGD(TAG, "Received ack: %s", this->buffer_.substr(0, this->buffer_.size() - 2).c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this->buffer_.find("LensBad") != std::string::npos) {
|
||||||
|
ESP_LOGW(TAG, "Received LensBad!");
|
||||||
|
this->lens_bad_ = true;
|
||||||
|
}
|
||||||
|
if (this->buffer_.find("EmSat") != std::string::npos) {
|
||||||
|
ESP_LOGW(TAG, "Received EmSat!");
|
||||||
|
this->em_sat_ = true;
|
||||||
|
}
|
||||||
if (this->buffer_starts_with_("PwrDays")) {
|
if (this->buffer_starts_with_("PwrDays")) {
|
||||||
if (this->boot_count_ <= 0) {
|
if (this->boot_count_ <= 0) {
|
||||||
this->boot_count_ = 1;
|
this->boot_count_ = 1;
|
||||||
@ -200,7 +232,16 @@ void HydreonRGxxComponent::process_line_() {
|
|||||||
ESP_LOGD(TAG, "Received %s: %f", PROTOCOL_NAMES[i], this->sensors_[i]->get_raw_state());
|
ESP_LOGD(TAG, "Received %s: %f", PROTOCOL_NAMES[i], this->sensors_[i]->get_raw_state());
|
||||||
this->sensors_received_ |= (1 << i);
|
this->sensors_received_ |= (1 << i);
|
||||||
}
|
}
|
||||||
|
if (this->request_temperature_ && this->num_sensors_missing_() == 1) {
|
||||||
|
this->write_str("T\n");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
for (const auto *ignore : IGNORE_STRINGS) {
|
||||||
|
if (this->buffer_starts_with_(ignore)) {
|
||||||
|
ESP_LOGI(TAG, "Ignoring %s", this->buffer_.substr(0, this->buffer_.size() - 2).c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
ESP_LOGI(TAG, "Got unknown line: %s", this->buffer_.c_str());
|
ESP_LOGI(TAG, "Got unknown line: %s", this->buffer_.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,13 +26,18 @@ static const uint8_t NUM_SENSORS = 1;
|
|||||||
#define HYDREON_RGXX_PROTOCOL_LIST(F, SEP) F("")
|
#define HYDREON_RGXX_PROTOCOL_LIST(F, SEP) F("")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define HYDREON_RGXX_IGNORE_LIST(F, SEP) F("Emitters") SEP F("Event") SEP F("Reset")
|
||||||
|
|
||||||
class HydreonRGxxComponent : public PollingComponent, public uart::UARTDevice {
|
class HydreonRGxxComponent : public PollingComponent, public uart::UARTDevice {
|
||||||
public:
|
public:
|
||||||
void set_sensor(sensor::Sensor *sensor, int index) { this->sensors_[index] = sensor; }
|
void set_sensor(sensor::Sensor *sensor, int index) { this->sensors_[index] = sensor; }
|
||||||
#ifdef USE_BINARY_SENSOR
|
#ifdef USE_BINARY_SENSOR
|
||||||
void set_too_cold_sensor(binary_sensor::BinarySensor *sensor) { this->too_cold_sensor_ = sensor; }
|
void set_too_cold_sensor(binary_sensor::BinarySensor *sensor) { this->too_cold_sensor_ = sensor; }
|
||||||
|
void set_lens_bad_sensor(binary_sensor::BinarySensor *sensor) { this->lens_bad_sensor_ = sensor; }
|
||||||
|
void set_em_sat_sensor(binary_sensor::BinarySensor *sensor) { this->em_sat_sensor_ = sensor; }
|
||||||
#endif
|
#endif
|
||||||
void set_model(RGModel model) { model_ = model; }
|
void set_model(RGModel model) { model_ = model; }
|
||||||
|
void set_request_temperature(bool b) { request_temperature_ = b; }
|
||||||
|
|
||||||
/// Schedule data readings.
|
/// Schedule data readings.
|
||||||
void update() override;
|
void update() override;
|
||||||
@ -49,11 +54,13 @@ class HydreonRGxxComponent : public PollingComponent, public uart::UARTDevice {
|
|||||||
void schedule_reboot_();
|
void schedule_reboot_();
|
||||||
bool buffer_starts_with_(const std::string &prefix);
|
bool buffer_starts_with_(const std::string &prefix);
|
||||||
bool buffer_starts_with_(const char *prefix);
|
bool buffer_starts_with_(const char *prefix);
|
||||||
bool sensor_missing_();
|
int num_sensors_missing_();
|
||||||
|
|
||||||
sensor::Sensor *sensors_[NUM_SENSORS] = {nullptr};
|
sensor::Sensor *sensors_[NUM_SENSORS] = {nullptr};
|
||||||
#ifdef USE_BINARY_SENSOR
|
#ifdef USE_BINARY_SENSOR
|
||||||
binary_sensor::BinarySensor *too_cold_sensor_ = nullptr;
|
binary_sensor::BinarySensor *too_cold_sensor_ = nullptr;
|
||||||
|
binary_sensor::BinarySensor *lens_bad_sensor_ = nullptr;
|
||||||
|
binary_sensor::BinarySensor *em_sat_sensor_ = nullptr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int16_t boot_count_ = 0;
|
int16_t boot_count_ = 0;
|
||||||
@ -62,6 +69,9 @@ class HydreonRGxxComponent : public PollingComponent, public uart::UARTDevice {
|
|||||||
RGModel model_ = RG9;
|
RGModel model_ = RG9;
|
||||||
int sw_version_ = 0;
|
int sw_version_ = 0;
|
||||||
bool too_cold_ = false;
|
bool too_cold_ = false;
|
||||||
|
bool lens_bad_ = false;
|
||||||
|
bool em_sat_ = false;
|
||||||
|
bool request_temperature_ = false;
|
||||||
|
|
||||||
// bit field showing which sensors we have received data for
|
// bit field showing which sensors we have received data for
|
||||||
int sensors_received_ = -1;
|
int sensors_received_ = -1;
|
||||||
|
@ -5,8 +5,11 @@ from esphome.const import (
|
|||||||
CONF_ID,
|
CONF_ID,
|
||||||
CONF_MODEL,
|
CONF_MODEL,
|
||||||
CONF_MOISTURE,
|
CONF_MOISTURE,
|
||||||
|
CONF_TEMPERATURE,
|
||||||
DEVICE_CLASS_HUMIDITY,
|
DEVICE_CLASS_HUMIDITY,
|
||||||
STATE_CLASS_MEASUREMENT,
|
STATE_CLASS_MEASUREMENT,
|
||||||
|
UNIT_CELSIUS,
|
||||||
|
ICON_THERMOMETER,
|
||||||
)
|
)
|
||||||
|
|
||||||
from . import RGModel, HydreonRGxxComponent
|
from . import RGModel, HydreonRGxxComponent
|
||||||
@ -33,6 +36,7 @@ SUPPORTED_SENSORS = {
|
|||||||
CONF_TOTAL_ACC: ["RG_15"],
|
CONF_TOTAL_ACC: ["RG_15"],
|
||||||
CONF_R_INT: ["RG_15"],
|
CONF_R_INT: ["RG_15"],
|
||||||
CONF_MOISTURE: ["RG_9"],
|
CONF_MOISTURE: ["RG_9"],
|
||||||
|
CONF_TEMPERATURE: ["RG_9"],
|
||||||
}
|
}
|
||||||
PROTOCOL_NAMES = {
|
PROTOCOL_NAMES = {
|
||||||
CONF_MOISTURE: "R",
|
CONF_MOISTURE: "R",
|
||||||
@ -40,6 +44,7 @@ PROTOCOL_NAMES = {
|
|||||||
CONF_R_INT: "RInt",
|
CONF_R_INT: "RInt",
|
||||||
CONF_EVENT_ACC: "EventAcc",
|
CONF_EVENT_ACC: "EventAcc",
|
||||||
CONF_TOTAL_ACC: "TotalAcc",
|
CONF_TOTAL_ACC: "TotalAcc",
|
||||||
|
CONF_TEMPERATURE: "t",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -92,6 +97,12 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
device_class=DEVICE_CLASS_HUMIDITY,
|
device_class=DEVICE_CLASS_HUMIDITY,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
),
|
),
|
||||||
|
cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_CELSIUS,
|
||||||
|
accuracy_decimals=0,
|
||||||
|
icon=ICON_THERMOMETER,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.extend(cv.polling_component_schema("60s"))
|
.extend(cv.polling_component_schema("60s"))
|
||||||
@ -108,7 +119,7 @@ async def to_code(config):
|
|||||||
cg.add_define(
|
cg.add_define(
|
||||||
"HYDREON_RGXX_PROTOCOL_LIST(F, sep)",
|
"HYDREON_RGXX_PROTOCOL_LIST(F, sep)",
|
||||||
cg.RawExpression(
|
cg.RawExpression(
|
||||||
" sep ".join([f'F("{name}")' for name in PROTOCOL_NAMES.values()])
|
" sep ".join([f'F("{name} ")' for name in PROTOCOL_NAMES.values()])
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
cg.add_define("HYDREON_RGXX_NUM_SENSORS", len(PROTOCOL_NAMES))
|
cg.add_define("HYDREON_RGXX_NUM_SENSORS", len(PROTOCOL_NAMES))
|
||||||
@ -117,3 +128,5 @@ async def to_code(config):
|
|||||||
if conf in config:
|
if conf in config:
|
||||||
sens = await sensor.new_sensor(config[conf])
|
sens = await sensor.new_sensor(config[conf])
|
||||||
cg.add(var.set_sensor(sens, i))
|
cg.add(var.set_sensor(sens, i))
|
||||||
|
|
||||||
|
cg.add(var.set_request_temperature(CONF_TEMPERATURE in config))
|
||||||
|
@ -866,6 +866,10 @@ binary_sensor:
|
|||||||
hydreon_rgxx_id: "hydreon_rg9"
|
hydreon_rgxx_id: "hydreon_rg9"
|
||||||
too_cold:
|
too_cold:
|
||||||
name: "rg9_toocold"
|
name: "rg9_toocold"
|
||||||
|
em_sat:
|
||||||
|
name: "rg9_emsat"
|
||||||
|
lens_bad:
|
||||||
|
name: "rg9_lens_bad"
|
||||||
- platform: template
|
- platform: template
|
||||||
id: 'pzemac_reset_energy'
|
id: 'pzemac_reset_energy'
|
||||||
on_press:
|
on_press:
|
||||||
|
Loading…
Reference in New Issue
Block a user