esphome/esphome/components/hydreon_rgxx/sensor.py

158 lines
5.1 KiB
Python

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,
CONF_RESOLUTION,
CONF_TEMPERATURE,
DEVICE_CLASS_PRECIPITATION_INTENSITY,
DEVICE_CLASS_PRECIPITATION,
STATE_CLASS_MEASUREMENT,
STATE_CLASS_TOTAL_INCREASING,
UNIT_CELSIUS,
ICON_THERMOMETER,
)
from . import RGModel, RG15Resolution, 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"
CONF_DISABLE_LED = "disable_led"
RG_MODELS = {
"RG_9": RGModel.RG9,
"RG_15": RGModel.RG15,
# RG-15
# 1.000 - https://rainsensors.com/wp-content/uploads/sites/3/2020/07/rg-15_instructions_sw_1.000.pdf
# RG-9
# 1.000 - https://rainsensors.com/wp-content/uploads/sites/3/2021/03/2020.08.25-rg-9_instructions.pdf
# 1.100 - https://rainsensors.com/wp-content/uploads/sites/3/2021/03/2021.03.11-rg-9_instructions.pdf
# 1.200 - https://rainsensors.com/wp-content/uploads/sites/3/2022/03/2022.02.17-rev-1.200-rg-9_instructions.pdf
}
RG15_RESOLUTION = {
"low": RG15Resolution.FORCE_LOW,
"high": RG15Resolution.FORCE_HIGH,
}
SUPPORTED_OPTIONS = {
CONF_ACC: ["RG_15"],
CONF_EVENT_ACC: ["RG_15"],
CONF_TOTAL_ACC: ["RG_15"],
CONF_R_INT: ["RG_15"],
CONF_RESOLUTION: ["RG_15"],
CONF_MOISTURE: ["RG_9"],
CONF_TEMPERATURE: ["RG_9"],
CONF_DISABLE_LED: ["RG_9"],
}
PROTOCOL_NAMES = {
CONF_MOISTURE: "R",
CONF_ACC: "Acc",
CONF_R_INT: "RInt",
CONF_EVENT_ACC: "EventAcc",
CONF_TOTAL_ACC: "TotalAcc",
CONF_TEMPERATURE: "t",
}
def _validate(config):
for conf, models in SUPPORTED_OPTIONS.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_RESOLUTION): cv.enum(RG15_RESOLUTION, upper=False),
cv.Optional(CONF_ACC): sensor.sensor_schema(
unit_of_measurement=UNIT_MILLIMETERS,
accuracy_decimals=2,
device_class=DEVICE_CLASS_PRECIPITATION,
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_PRECIPITATION,
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_PRECIPITATION,
state_class=STATE_CLASS_TOTAL_INCREASING,
),
cv.Optional(CONF_R_INT): sensor.sensor_schema(
unit_of_measurement=UNIT_MILLIMETERS_PER_HOUR,
accuracy_decimals=2,
device_class=DEVICE_CLASS_PRECIPITATION_INTENSITY,
state_class=STATE_CLASS_MEASUREMENT,
),
cv.Optional(CONF_MOISTURE): sensor.sensor_schema(
unit_of_measurement=UNIT_INTENSITY,
accuracy_decimals=0,
device_class=DEVICE_CLASS_PRECIPITATION_INTENSITY,
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,
),
cv.Optional(CONF_DISABLE_LED): cv.boolean,
}
)
.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))
cg.add(var.set_model(config[CONF_MODEL]))
if CONF_RESOLUTION in config:
cg.add(var.set_resolution(config[CONF_RESOLUTION]))
cg.add(var.set_request_temperature(CONF_TEMPERATURE in config))
if CONF_DISABLE_LED in config:
cg.add(var.set_disable_led(config[CONF_DISABLE_LED]))