mirror of
https://github.com/esphome/esphome.git
synced 2026-10-17 19:52:50 +00:00
Convert climate.control and water_heater.template.publish temperatures into the entity unit
This commit is contained in:
@@ -170,7 +170,15 @@ def temperature_unit_of_id(climate_id: ID) -> str:
|
||||
for conf in CORE.config.get(DOMAIN, []):
|
||||
if conf[CONF_ID] == climate_id:
|
||||
return temperature_unit_of(conf)
|
||||
return UNIT_CELSIUS
|
||||
raise KeyError(f"No climate with id {climate_id}")
|
||||
|
||||
|
||||
def temperature_in_entity_unit(
|
||||
config: ConfigType, value: tuple[float, str | None]
|
||||
) -> str:
|
||||
"""Render a static action temperature in the unit of the climate the action targets."""
|
||||
unit = temperature_unit_of_id(config[CONF_ID])
|
||||
return str(cg.safe_exp(cv.convert_temperature(*value, unit)))
|
||||
|
||||
|
||||
def _visual_temperatures_in_entity_unit(config: ConfigType) -> ConfigType:
|
||||
@@ -493,9 +501,13 @@ CLIMATE_CONTROL_ACTION_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.Required(CONF_ID): cv.use_id(Climate),
|
||||
cv.Optional(CONF_MODE): cv.templatable(validate_climate_mode),
|
||||
cv.Optional(CONF_TARGET_TEMPERATURE): cv.templatable(cv.temperature),
|
||||
cv.Optional(CONF_TARGET_TEMPERATURE_LOW): cv.templatable(cv.temperature),
|
||||
cv.Optional(CONF_TARGET_TEMPERATURE_HIGH): cv.templatable(cv.temperature),
|
||||
cv.Optional(CONF_TARGET_TEMPERATURE): cv.templatable(cv.temperature_with_unit),
|
||||
cv.Optional(CONF_TARGET_TEMPERATURE_LOW): cv.templatable(
|
||||
cv.temperature_with_unit
|
||||
),
|
||||
cv.Optional(CONF_TARGET_TEMPERATURE_HIGH): cv.templatable(
|
||||
cv.temperature_with_unit
|
||||
),
|
||||
cv.Optional(CONF_TARGET_HUMIDITY): cv.templatable(cv.percentage_int),
|
||||
cv.Optional(CONF_AWAY): cv.invalid("Use preset instead"),
|
||||
cv.Exclusive(CONF_FAN_MODE, "fan_mode"): cv.templatable(
|
||||
@@ -515,12 +527,23 @@ automation.register_apply_action(
|
||||
"climate.control",
|
||||
CLIMATE_CONTROL_ACTION_SCHEMA,
|
||||
automation.ApplyField(CONF_MODE, "set_mode", ClimateMode),
|
||||
automation.ApplyField(CONF_TARGET_TEMPERATURE, "set_target_temperature", cg.float_),
|
||||
automation.ApplyField(
|
||||
CONF_TARGET_TEMPERATURE_LOW, "set_target_temperature_low", cg.float_
|
||||
CONF_TARGET_TEMPERATURE,
|
||||
"set_target_temperature",
|
||||
cg.float_,
|
||||
temperature_in_entity_unit,
|
||||
),
|
||||
automation.ApplyField(
|
||||
CONF_TARGET_TEMPERATURE_HIGH, "set_target_temperature_high", cg.float_
|
||||
CONF_TARGET_TEMPERATURE_LOW,
|
||||
"set_target_temperature_low",
|
||||
cg.float_,
|
||||
temperature_in_entity_unit,
|
||||
),
|
||||
automation.ApplyField(
|
||||
CONF_TARGET_TEMPERATURE_HIGH,
|
||||
"set_target_temperature_high",
|
||||
cg.float_,
|
||||
temperature_in_entity_unit,
|
||||
),
|
||||
automation.ApplyField(CONF_TARGET_HUMIDITY, "set_target_humidity", cg.float_),
|
||||
automation.ApplyField(CONF_FAN_MODE, "set_fan_mode", ClimateFanMode),
|
||||
|
||||
@@ -433,14 +433,6 @@ CLIMATE_TEMPLATE_PUBLISH_ACTION_SCHEMA = cv.All(
|
||||
)
|
||||
|
||||
|
||||
def _temperature_in_entity_unit(
|
||||
config: ConfigType, value: tuple[float, str | None]
|
||||
) -> str:
|
||||
# The entity's unit is only known once every climate has been validated
|
||||
unit = climate.temperature_unit_of_id(config[CONF_ID])
|
||||
return str(cg.safe_exp(cv.convert_temperature(*value, unit)))
|
||||
|
||||
|
||||
automation.register_apply_action(
|
||||
"climate.template.publish",
|
||||
CLIMATE_TEMPLATE_PUBLISH_ACTION_SCHEMA,
|
||||
@@ -448,26 +440,26 @@ automation.register_apply_action(
|
||||
CONF_CURRENT_TEMPERATURE,
|
||||
"current_temperature = {}",
|
||||
cg.float_,
|
||||
_temperature_in_entity_unit,
|
||||
climate.temperature_in_entity_unit,
|
||||
),
|
||||
automation.ApplyField(CONF_CURRENT_HUMIDITY, "current_humidity = {}", cg.float_),
|
||||
automation.ApplyField(
|
||||
CONF_TARGET_TEMPERATURE,
|
||||
"set_target_temperature",
|
||||
cg.float_,
|
||||
_temperature_in_entity_unit,
|
||||
climate.temperature_in_entity_unit,
|
||||
),
|
||||
automation.ApplyField(
|
||||
CONF_TARGET_TEMPERATURE_LOW,
|
||||
"set_target_temperature_low",
|
||||
cg.float_,
|
||||
_temperature_in_entity_unit,
|
||||
climate.temperature_in_entity_unit,
|
||||
),
|
||||
automation.ApplyField(
|
||||
CONF_TARGET_TEMPERATURE_HIGH,
|
||||
"set_target_temperature_high",
|
||||
cg.float_,
|
||||
_temperature_in_entity_unit,
|
||||
climate.temperature_in_entity_unit,
|
||||
),
|
||||
automation.ApplyField(CONF_TARGET_HUMIDITY, "set_target_humidity", cg.float_),
|
||||
automation.ApplyField(CONF_MODE, "set_mode", climate.ClimateMode),
|
||||
|
||||
@@ -129,8 +129,12 @@ async def to_code(config: ConfigType) -> None:
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.use_id(TemplateWaterHeater),
|
||||
cv.Optional(CONF_CURRENT_TEMPERATURE): cv.templatable(cv.temperature),
|
||||
cv.Optional(CONF_TARGET_TEMPERATURE): cv.templatable(cv.temperature),
|
||||
cv.Optional(CONF_CURRENT_TEMPERATURE): cv.templatable(
|
||||
cv.temperature_with_unit
|
||||
),
|
||||
cv.Optional(CONF_TARGET_TEMPERATURE): cv.templatable(
|
||||
cv.temperature_with_unit
|
||||
),
|
||||
cv.Optional(CONF_MODE): cv.templatable(
|
||||
water_heater.validate_water_heater_mode
|
||||
),
|
||||
@@ -149,13 +153,17 @@ async def water_heater_template_publish_to_code(
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
|
||||
if current_temp := config.get(CONF_CURRENT_TEMPERATURE):
|
||||
template_ = await cg.templatable(current_temp, args, cg.float_)
|
||||
cg.add(var.set_current_temperature(template_))
|
||||
|
||||
if target_temp := config.get(CONF_TARGET_TEMPERATURE):
|
||||
template_ = await cg.templatable(target_temp, args, cg.float_)
|
||||
cg.add(var.set_target_temperature(template_))
|
||||
# A static temperature is in the unit of the water heater it is published to
|
||||
unit = water_heater.temperature_unit_of_id(config[CONF_ID])
|
||||
for key, setter in (
|
||||
(CONF_CURRENT_TEMPERATURE, var.set_current_temperature),
|
||||
(CONF_TARGET_TEMPERATURE, var.set_target_temperature),
|
||||
):
|
||||
if (value := config.get(key)) is None:
|
||||
continue
|
||||
if isinstance(value, tuple):
|
||||
value = cv.convert_temperature(*value, unit)
|
||||
cg.add(setter(await cg.templatable(value, args, cg.float_)))
|
||||
|
||||
if mode := config.get(CONF_MODE):
|
||||
template_ = await cg.templatable(mode, args, water_heater.WaterHeaterMode)
|
||||
|
||||
@@ -10,7 +10,7 @@ from esphome.const import (
|
||||
CONF_VISUAL,
|
||||
UNIT_CELSIUS,
|
||||
)
|
||||
from esphome.core import CORE, CoroPriority, coroutine_with_priority
|
||||
from esphome.core import CORE, ID, CoroPriority, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import (
|
||||
entity_duplicate_validator,
|
||||
queue_entity_register,
|
||||
@@ -52,6 +52,14 @@ def temperature_unit_of(config: ConfigType) -> str:
|
||||
return unit if unit in TEMPERATURE_UNITS else UNIT_CELSIUS
|
||||
|
||||
|
||||
def temperature_unit_of_id(water_heater_id: ID) -> str:
|
||||
"""The unit of the water heater with this id, for actions that take static temperatures."""
|
||||
for conf in CORE.config.get(DOMAIN, []):
|
||||
if conf[CONF_ID] == water_heater_id:
|
||||
return temperature_unit_of(conf)
|
||||
raise KeyError(f"No water heater with id {water_heater_id}")
|
||||
|
||||
|
||||
def _visual_temperatures_in_entity_unit(config: ConfigType) -> ConfigType:
|
||||
"""Convert the visual temperatures into the entity's unit."""
|
||||
unit = temperature_unit_of(config)
|
||||
|
||||
@@ -45,6 +45,13 @@ esphome:
|
||||
id: template_climate_fahrenheit
|
||||
current_temperature: 20°C
|
||||
target_temperature: 70
|
||||
- climate.control:
|
||||
id: template_climate_fahrenheit
|
||||
target_temperature: 22°C
|
||||
- water_heater.template.publish:
|
||||
id: template_water_heater_fahrenheit
|
||||
current_temperature: 45°C
|
||||
target_temperature: 120
|
||||
- climate.template.publish:
|
||||
id: template_climate_custom_modes
|
||||
custom_fan_mode: "turbo"
|
||||
|
||||
Reference in New Issue
Block a user