Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: J. Nick Koston <nick@home-assistant.io>
134 lines
3.9 KiB
Python
134 lines
3.9 KiB
Python
import esphome.codegen as cg
|
|
from esphome.components import sensor
|
|
import esphome.config_validation as cv
|
|
from esphome.const import (
|
|
CONF_ACCURACY_DECIMALS,
|
|
CONF_DEVICE_CLASS,
|
|
CONF_ID,
|
|
CONF_STATE_CLASS,
|
|
CONF_UNIT_OF_MEASUREMENT,
|
|
DEVICE_CLASS_CURRENT,
|
|
DEVICE_CLASS_ENERGY,
|
|
DEVICE_CLASS_POWER,
|
|
DEVICE_CLASS_POWER_FACTOR,
|
|
DEVICE_CLASS_TEMPERATURE,
|
|
DEVICE_CLASS_VOLTAGE,
|
|
STATE_CLASS_MEASUREMENT,
|
|
STATE_CLASS_TOTAL_INCREASING,
|
|
UNIT_AMPERE,
|
|
UNIT_CELSIUS,
|
|
UNIT_EMPTY,
|
|
UNIT_PULSES,
|
|
UNIT_VOLT,
|
|
UNIT_WATT,
|
|
UNIT_WATT_HOURS,
|
|
)
|
|
from esphome.types import ConfigType
|
|
|
|
from .. import CONF_EMONTX_ID, CONF_TAG_NAME, EmonTx, emontx_ns
|
|
|
|
EmonTxSensor = emontx_ns.class_("EmonTxSensor", sensor.Sensor, cg.Component)
|
|
|
|
# Define sensor type configurations by prefix
|
|
SENSOR_CONFIGS = {
|
|
"P": {
|
|
CONF_UNIT_OF_MEASUREMENT: UNIT_WATT,
|
|
CONF_DEVICE_CLASS: DEVICE_CLASS_POWER,
|
|
CONF_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
|
CONF_ACCURACY_DECIMALS: 0,
|
|
},
|
|
"E": {
|
|
CONF_UNIT_OF_MEASUREMENT: UNIT_WATT_HOURS,
|
|
CONF_DEVICE_CLASS: DEVICE_CLASS_ENERGY,
|
|
CONF_STATE_CLASS: STATE_CLASS_TOTAL_INCREASING,
|
|
CONF_ACCURACY_DECIMALS: 0,
|
|
},
|
|
"V": {
|
|
CONF_UNIT_OF_MEASUREMENT: UNIT_VOLT,
|
|
CONF_DEVICE_CLASS: DEVICE_CLASS_VOLTAGE,
|
|
CONF_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
|
CONF_ACCURACY_DECIMALS: 2,
|
|
},
|
|
"I": {
|
|
CONF_UNIT_OF_MEASUREMENT: UNIT_AMPERE,
|
|
CONF_DEVICE_CLASS: DEVICE_CLASS_CURRENT,
|
|
CONF_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
|
CONF_ACCURACY_DECIMALS: 2,
|
|
},
|
|
"T": {
|
|
CONF_UNIT_OF_MEASUREMENT: UNIT_CELSIUS,
|
|
CONF_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
|
|
CONF_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
|
CONF_ACCURACY_DECIMALS: 2,
|
|
},
|
|
}
|
|
|
|
# Pattern-based configurations
|
|
PATTERN_CONFIGS = {
|
|
"PULSE": {
|
|
CONF_UNIT_OF_MEASUREMENT: UNIT_PULSES,
|
|
CONF_DEVICE_CLASS: DEVICE_CLASS_ENERGY,
|
|
CONF_ACCURACY_DECIMALS: 0,
|
|
},
|
|
"PF": {
|
|
CONF_UNIT_OF_MEASUREMENT: UNIT_EMPTY,
|
|
CONF_DEVICE_CLASS: DEVICE_CLASS_POWER_FACTOR,
|
|
CONF_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
|
CONF_ACCURACY_DECIMALS: 2,
|
|
},
|
|
}
|
|
|
|
# Create a base schema that's flexible for any tag
|
|
BASE_SCHEMA = sensor.sensor_schema(
|
|
EmonTxSensor,
|
|
state_class=STATE_CLASS_MEASUREMENT,
|
|
accuracy_decimals=0,
|
|
).extend(
|
|
{
|
|
cv.GenerateID(CONF_EMONTX_ID): cv.use_id(EmonTx),
|
|
cv.Required(CONF_TAG_NAME): cv.string,
|
|
}
|
|
)
|
|
|
|
|
|
def apply_tag_defaults(config: ConfigType) -> ConfigType:
|
|
"""Apply defaults based on tag prefix if applicable, but don't restrict any tags."""
|
|
tag = config[CONF_TAG_NAME]
|
|
|
|
# Skip if tag is too short
|
|
if len(tag) < 2:
|
|
return config
|
|
|
|
# Check if this tag starts with a known prefix
|
|
tag_upper = tag.upper()
|
|
|
|
for pattern, pattern_config in PATTERN_CONFIGS.items():
|
|
if tag_upper.startswith(pattern):
|
|
# Apply pattern defaults if not overridden by user
|
|
for key, value in pattern_config.items():
|
|
if key not in config:
|
|
config[key] = value
|
|
return config
|
|
|
|
# Only apply defaults for known prefixes with numeric indices
|
|
prefix = tag_upper[0]
|
|
if prefix in SENSOR_CONFIGS and len(tag) > 1 and tag[1:].isdigit():
|
|
# Apply defaults for known tag types, but only if not overridden by user
|
|
defaults = SENSOR_CONFIGS[prefix]
|
|
for key, value in defaults.items():
|
|
if key not in config:
|
|
config[key] = value
|
|
|
|
return config
|
|
|
|
|
|
CONFIG_SCHEMA = cv.All(BASE_SCHEMA, apply_tag_defaults)
|
|
|
|
|
|
async def to_code(config: ConfigType) -> None:
|
|
var = cg.new_Pvariable(config[CONF_ID])
|
|
await cg.register_component(var, config)
|
|
await sensor.register_sensor(var, config)
|
|
hub = await cg.get_variable(config[CONF_EMONTX_ID])
|
|
cg.add(hub.register_sensor(config[CONF_TAG_NAME], var))
|