1
0
mirror of https://github.com/esphome/esphome.git synced 2025-03-24 11:38:23 +00:00
Chris Feenstra 64a47f840e
Added Kamstrup Multical 40x component (#4200)
Co-authored-by: Chris Feenstra <chris@cfeenstra.nl>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
Co-authored-by: cfeenstra1024 <git@cfeenstra.nl>
2024-03-13 16:01:22 +13:00

133 lines
4.3 KiB
Python

import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import sensor, uart
from esphome.const import (
CONF_COMMAND,
CONF_CUSTOM,
CONF_FLOW,
CONF_ID,
CONF_POWER,
CONF_VOLUME,
DEVICE_CLASS_EMPTY,
DEVICE_CLASS_ENERGY,
DEVICE_CLASS_POWER,
DEVICE_CLASS_TEMPERATURE,
DEVICE_CLASS_VOLUME,
STATE_CLASS_MEASUREMENT,
STATE_CLASS_TOTAL_INCREASING,
UNIT_CELSIUS,
UNIT_CUBIC_METER,
UNIT_EMPTY,
UNIT_KELVIN,
UNIT_KILOWATT,
)
CODEOWNERS = ["@cfeenstra1024"]
DEPENDENCIES = ["uart"]
kamstrup_kmp_ns = cg.esphome_ns.namespace("kamstrup_kmp")
KamstrupKMPComponent = kamstrup_kmp_ns.class_(
"KamstrupKMPComponent", cg.PollingComponent, uart.UARTDevice
)
CONF_HEAT_ENERGY = "heat_energy"
CONF_TEMP1 = "temp1"
CONF_TEMP2 = "temp2"
CONF_TEMP_DIFF = "temp_diff"
UNIT_GIGA_JOULE = "GJ"
UNIT_LITRE_PER_HOUR = "l/h"
# Note: The sensor units are set automatically based un the received data from the meter
CONFIG_SCHEMA = (
cv.Schema(
{
cv.GenerateID(): cv.declare_id(KamstrupKMPComponent),
cv.Optional(CONF_HEAT_ENERGY): sensor.sensor_schema(
accuracy_decimals=3,
device_class=DEVICE_CLASS_ENERGY,
state_class=STATE_CLASS_TOTAL_INCREASING,
unit_of_measurement=UNIT_GIGA_JOULE,
),
cv.Optional(CONF_POWER): sensor.sensor_schema(
accuracy_decimals=3,
device_class=DEVICE_CLASS_POWER,
state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=UNIT_KILOWATT,
),
cv.Optional(CONF_TEMP1): sensor.sensor_schema(
accuracy_decimals=1,
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=UNIT_CELSIUS,
),
cv.Optional(CONF_TEMP2): sensor.sensor_schema(
accuracy_decimals=1,
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=UNIT_CELSIUS,
),
cv.Optional(CONF_TEMP_DIFF): sensor.sensor_schema(
accuracy_decimals=1,
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=UNIT_KELVIN,
),
cv.Optional(CONF_FLOW): sensor.sensor_schema(
accuracy_decimals=1,
device_class=DEVICE_CLASS_VOLUME,
state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=UNIT_LITRE_PER_HOUR,
),
cv.Optional(CONF_VOLUME): sensor.sensor_schema(
accuracy_decimals=1,
device_class=DEVICE_CLASS_VOLUME,
state_class=STATE_CLASS_TOTAL_INCREASING,
unit_of_measurement=UNIT_CUBIC_METER,
),
cv.Optional(CONF_CUSTOM): cv.ensure_list(
sensor.sensor_schema(
accuracy_decimals=1,
device_class=DEVICE_CLASS_EMPTY,
state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=UNIT_EMPTY,
).extend({cv.Required(CONF_COMMAND): cv.hex_uint16_t})
),
}
)
.extend(cv.polling_component_schema("60s"))
.extend(uart.UART_DEVICE_SCHEMA)
)
FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema(
"kamstrup_kmp", baud_rate=1200, require_rx=True, require_tx=True
)
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)
# Standard sensors
for key in [
CONF_HEAT_ENERGY,
CONF_POWER,
CONF_TEMP1,
CONF_TEMP2,
CONF_TEMP_DIFF,
CONF_FLOW,
CONF_VOLUME,
]:
if key not in config:
continue
conf = config[key]
sens = await sensor.new_sensor(conf)
cg.add(getattr(var, f"set_{key}_sensor")(sens))
# Custom sensors
if CONF_CUSTOM in config:
for conf in config[CONF_CUSTOM]:
sens = await sensor.new_sensor(conf)
cg.add(var.add_custom_sensor(sens, conf[CONF_COMMAND]))