1
0
mirror of https://github.com/esphome/esphome.git synced 2025-03-25 12:08:16 +00:00
2025-03-20 09:51:23 -10:00

106 lines
3.2 KiB
Python

import esphome.codegen as cg
from esphome.components import binary_sensor, sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_BINARY_SENSOR,
CONF_CHANNELS,
CONF_GROUP,
CONF_SUM,
CONF_TYPE,
CONF_VALUE,
ICON_CHECK_CIRCLE_OUTLINE,
)
DEPENDENCIES = ["binary_sensor"]
binary_sensor_map_ns = cg.esphome_ns.namespace("binary_sensor_map")
BinarySensorMap = binary_sensor_map_ns.class_(
"BinarySensorMap", cg.Component, sensor.Sensor
)
SensorMapType = binary_sensor_map_ns.enum("SensorMapType")
CONF_BAYESIAN = "bayesian"
CONF_PRIOR = "prior"
CONF_PROB_GIVEN_TRUE = "prob_given_true"
CONF_PROB_GIVEN_FALSE = "prob_given_false"
CONF_OBSERVATIONS = "observations"
SENSOR_MAP_TYPES = {
CONF_GROUP: SensorMapType.BINARY_SENSOR_MAP_TYPE_GROUP,
CONF_SUM: SensorMapType.BINARY_SENSOR_MAP_TYPE_SUM,
CONF_BAYESIAN: SensorMapType.BINARY_SENSOR_MAP_TYPE_BAYESIAN,
}
entry_one_parameter = {
cv.Required(CONF_BINARY_SENSOR): cv.use_id(binary_sensor.BinarySensor),
cv.Required(CONF_VALUE): cv.float_,
}
entry_bayesian_parameters = {
cv.Required(CONF_BINARY_SENSOR): cv.use_id(binary_sensor.BinarySensor),
cv.Required(CONF_PROB_GIVEN_TRUE): cv.float_range(min=0, max=1),
cv.Required(CONF_PROB_GIVEN_FALSE): cv.float_range(min=0, max=1),
}
CONFIG_SCHEMA = cv.typed_schema(
{
CONF_GROUP: sensor.sensor_schema(
BinarySensorMap,
icon=ICON_CHECK_CIRCLE_OUTLINE,
accuracy_decimals=0,
).extend(
{
cv.Required(CONF_CHANNELS): cv.All(
cv.ensure_list(entry_one_parameter), cv.Length(min=1, max=64)
),
}
),
CONF_SUM: sensor.sensor_schema(
BinarySensorMap,
icon=ICON_CHECK_CIRCLE_OUTLINE,
accuracy_decimals=0,
).extend(
{
cv.Required(CONF_CHANNELS): cv.All(
cv.ensure_list(entry_one_parameter), cv.Length(min=1, max=64)
),
}
),
CONF_BAYESIAN: sensor.sensor_schema(
BinarySensorMap,
accuracy_decimals=2,
).extend(
{
cv.Required(CONF_PRIOR): cv.float_range(min=0, max=1),
cv.Required(CONF_OBSERVATIONS): cv.All(
cv.ensure_list(entry_bayesian_parameters), cv.Length(min=1, max=64)
),
}
),
},
lower=True,
)
async def to_code(config):
var = await sensor.new_sensor(config)
await cg.register_component(var, config)
constant = SENSOR_MAP_TYPES[config[CONF_TYPE]]
cg.add(var.set_sensor_type(constant))
if config[CONF_TYPE] == CONF_BAYESIAN:
cg.add(var.set_bayesian_prior(config[CONF_PRIOR]))
for obs in config[CONF_OBSERVATIONS]:
input_var = await cg.get_variable(obs[CONF_BINARY_SENSOR])
cg.add(
var.add_channel(
input_var, obs[CONF_PROB_GIVEN_TRUE], obs[CONF_PROB_GIVEN_FALSE]
)
)
else:
for ch in config[CONF_CHANNELS]:
input_var = await cg.get_variable(ch[CONF_BINARY_SENSOR])
cg.add(var.add_channel(input_var, ch[CONF_VALUE]))