mirror of
https://github.com/home-assistant/core.git
synced 2025-07-13 16:27:08 +00:00
Add support for swing horizontal mode for mqtt climate (#139303)
* Add support for swing horizontal mode for mqtt climate * Fix import
This commit is contained in:
parent
7e97ef588b
commit
5324f3e542
@ -218,10 +218,16 @@ ABBREVIATIONS = {
|
|||||||
"sup_vol": "support_volume_set",
|
"sup_vol": "support_volume_set",
|
||||||
"sup_feat": "supported_features",
|
"sup_feat": "supported_features",
|
||||||
"sup_clrm": "supported_color_modes",
|
"sup_clrm": "supported_color_modes",
|
||||||
|
"swing_h_mode_cmd_tpl": "swing_horizontal_mode_command_template",
|
||||||
|
"swing_h_mode_cmd_t": "swing_horizontal_mode_command_topic",
|
||||||
|
"swing_h_mode_stat_tpl": "swing_horizontal_mode_state_template",
|
||||||
|
"swing_h_mode_stat_t": "swing_horizontal_mode_state_topic",
|
||||||
|
"swing_h_modes": "swing_horizontal_modes",
|
||||||
"swing_mode_cmd_tpl": "swing_mode_command_template",
|
"swing_mode_cmd_tpl": "swing_mode_command_template",
|
||||||
"swing_mode_cmd_t": "swing_mode_command_topic",
|
"swing_mode_cmd_t": "swing_mode_command_topic",
|
||||||
"swing_mode_stat_tpl": "swing_mode_state_template",
|
"swing_mode_stat_tpl": "swing_mode_state_template",
|
||||||
"swing_mode_stat_t": "swing_mode_state_topic",
|
"swing_mode_stat_t": "swing_mode_state_topic",
|
||||||
|
"swing_modes": "swing_modes",
|
||||||
"temp_cmd_tpl": "temperature_command_template",
|
"temp_cmd_tpl": "temperature_command_template",
|
||||||
"temp_cmd_t": "temperature_command_topic",
|
"temp_cmd_t": "temperature_command_topic",
|
||||||
"temp_hi_cmd_tpl": "temperature_high_command_template",
|
"temp_hi_cmd_tpl": "temperature_high_command_template",
|
||||||
|
@ -113,11 +113,19 @@ CONF_PRESET_MODE_COMMAND_TOPIC = "preset_mode_command_topic"
|
|||||||
CONF_PRESET_MODE_VALUE_TEMPLATE = "preset_mode_value_template"
|
CONF_PRESET_MODE_VALUE_TEMPLATE = "preset_mode_value_template"
|
||||||
CONF_PRESET_MODE_COMMAND_TEMPLATE = "preset_mode_command_template"
|
CONF_PRESET_MODE_COMMAND_TEMPLATE = "preset_mode_command_template"
|
||||||
CONF_PRESET_MODES_LIST = "preset_modes"
|
CONF_PRESET_MODES_LIST = "preset_modes"
|
||||||
|
|
||||||
|
CONF_SWING_HORIZONTAL_MODE_COMMAND_TEMPLATE = "swing_horizontal_mode_command_template"
|
||||||
|
CONF_SWING_HORIZONTAL_MODE_COMMAND_TOPIC = "swing_horizontal_mode_command_topic"
|
||||||
|
CONF_SWING_HORIZONTAL_MODE_LIST = "swing_horizontal_modes"
|
||||||
|
CONF_SWING_HORIZONTAL_MODE_STATE_TEMPLATE = "swing_horizontal_mode_state_template"
|
||||||
|
CONF_SWING_HORIZONTAL_MODE_STATE_TOPIC = "swing_horizontal_mode_state_topic"
|
||||||
|
|
||||||
CONF_SWING_MODE_COMMAND_TEMPLATE = "swing_mode_command_template"
|
CONF_SWING_MODE_COMMAND_TEMPLATE = "swing_mode_command_template"
|
||||||
CONF_SWING_MODE_COMMAND_TOPIC = "swing_mode_command_topic"
|
CONF_SWING_MODE_COMMAND_TOPIC = "swing_mode_command_topic"
|
||||||
CONF_SWING_MODE_LIST = "swing_modes"
|
CONF_SWING_MODE_LIST = "swing_modes"
|
||||||
CONF_SWING_MODE_STATE_TEMPLATE = "swing_mode_state_template"
|
CONF_SWING_MODE_STATE_TEMPLATE = "swing_mode_state_template"
|
||||||
CONF_SWING_MODE_STATE_TOPIC = "swing_mode_state_topic"
|
CONF_SWING_MODE_STATE_TOPIC = "swing_mode_state_topic"
|
||||||
|
|
||||||
CONF_TEMP_HIGH_COMMAND_TEMPLATE = "temperature_high_command_template"
|
CONF_TEMP_HIGH_COMMAND_TEMPLATE = "temperature_high_command_template"
|
||||||
CONF_TEMP_HIGH_COMMAND_TOPIC = "temperature_high_command_topic"
|
CONF_TEMP_HIGH_COMMAND_TOPIC = "temperature_high_command_topic"
|
||||||
CONF_TEMP_HIGH_STATE_TEMPLATE = "temperature_high_state_template"
|
CONF_TEMP_HIGH_STATE_TEMPLATE = "temperature_high_state_template"
|
||||||
@ -145,6 +153,8 @@ MQTT_CLIMATE_ATTRIBUTES_BLOCKED = frozenset(
|
|||||||
climate.ATTR_MIN_TEMP,
|
climate.ATTR_MIN_TEMP,
|
||||||
climate.ATTR_PRESET_MODE,
|
climate.ATTR_PRESET_MODE,
|
||||||
climate.ATTR_PRESET_MODES,
|
climate.ATTR_PRESET_MODES,
|
||||||
|
climate.ATTR_SWING_HORIZONTAL_MODE,
|
||||||
|
climate.ATTR_SWING_HORIZONTAL_MODES,
|
||||||
climate.ATTR_SWING_MODE,
|
climate.ATTR_SWING_MODE,
|
||||||
climate.ATTR_SWING_MODES,
|
climate.ATTR_SWING_MODES,
|
||||||
climate.ATTR_TARGET_TEMP_HIGH,
|
climate.ATTR_TARGET_TEMP_HIGH,
|
||||||
@ -162,6 +172,7 @@ VALUE_TEMPLATE_KEYS = (
|
|||||||
CONF_MODE_STATE_TEMPLATE,
|
CONF_MODE_STATE_TEMPLATE,
|
||||||
CONF_ACTION_TEMPLATE,
|
CONF_ACTION_TEMPLATE,
|
||||||
CONF_PRESET_MODE_VALUE_TEMPLATE,
|
CONF_PRESET_MODE_VALUE_TEMPLATE,
|
||||||
|
CONF_SWING_HORIZONTAL_MODE_STATE_TEMPLATE,
|
||||||
CONF_SWING_MODE_STATE_TEMPLATE,
|
CONF_SWING_MODE_STATE_TEMPLATE,
|
||||||
CONF_TEMP_HIGH_STATE_TEMPLATE,
|
CONF_TEMP_HIGH_STATE_TEMPLATE,
|
||||||
CONF_TEMP_LOW_STATE_TEMPLATE,
|
CONF_TEMP_LOW_STATE_TEMPLATE,
|
||||||
@ -174,6 +185,7 @@ COMMAND_TEMPLATE_KEYS = {
|
|||||||
CONF_MODE_COMMAND_TEMPLATE,
|
CONF_MODE_COMMAND_TEMPLATE,
|
||||||
CONF_POWER_COMMAND_TEMPLATE,
|
CONF_POWER_COMMAND_TEMPLATE,
|
||||||
CONF_PRESET_MODE_COMMAND_TEMPLATE,
|
CONF_PRESET_MODE_COMMAND_TEMPLATE,
|
||||||
|
CONF_SWING_HORIZONTAL_MODE_COMMAND_TEMPLATE,
|
||||||
CONF_SWING_MODE_COMMAND_TEMPLATE,
|
CONF_SWING_MODE_COMMAND_TEMPLATE,
|
||||||
CONF_TEMP_COMMAND_TEMPLATE,
|
CONF_TEMP_COMMAND_TEMPLATE,
|
||||||
CONF_TEMP_HIGH_COMMAND_TEMPLATE,
|
CONF_TEMP_HIGH_COMMAND_TEMPLATE,
|
||||||
@ -194,6 +206,8 @@ TOPIC_KEYS = (
|
|||||||
CONF_POWER_COMMAND_TOPIC,
|
CONF_POWER_COMMAND_TOPIC,
|
||||||
CONF_PRESET_MODE_COMMAND_TOPIC,
|
CONF_PRESET_MODE_COMMAND_TOPIC,
|
||||||
CONF_PRESET_MODE_STATE_TOPIC,
|
CONF_PRESET_MODE_STATE_TOPIC,
|
||||||
|
CONF_SWING_HORIZONTAL_MODE_COMMAND_TOPIC,
|
||||||
|
CONF_SWING_HORIZONTAL_MODE_STATE_TOPIC,
|
||||||
CONF_SWING_MODE_COMMAND_TOPIC,
|
CONF_SWING_MODE_COMMAND_TOPIC,
|
||||||
CONF_SWING_MODE_STATE_TOPIC,
|
CONF_SWING_MODE_STATE_TOPIC,
|
||||||
CONF_TEMP_COMMAND_TOPIC,
|
CONF_TEMP_COMMAND_TOPIC,
|
||||||
@ -302,6 +316,13 @@ _PLATFORM_SCHEMA_BASE = MQTT_BASE_SCHEMA.extend(
|
|||||||
vol.Optional(CONF_PRESET_MODE_COMMAND_TEMPLATE): cv.template,
|
vol.Optional(CONF_PRESET_MODE_COMMAND_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_PRESET_MODE_STATE_TOPIC): valid_subscribe_topic,
|
vol.Optional(CONF_PRESET_MODE_STATE_TOPIC): valid_subscribe_topic,
|
||||||
vol.Optional(CONF_PRESET_MODE_VALUE_TEMPLATE): cv.template,
|
vol.Optional(CONF_PRESET_MODE_VALUE_TEMPLATE): cv.template,
|
||||||
|
vol.Optional(CONF_SWING_HORIZONTAL_MODE_COMMAND_TEMPLATE): cv.template,
|
||||||
|
vol.Optional(CONF_SWING_HORIZONTAL_MODE_COMMAND_TOPIC): valid_publish_topic,
|
||||||
|
vol.Optional(
|
||||||
|
CONF_SWING_HORIZONTAL_MODE_LIST, default=[SWING_ON, SWING_OFF]
|
||||||
|
): cv.ensure_list,
|
||||||
|
vol.Optional(CONF_SWING_HORIZONTAL_MODE_STATE_TEMPLATE): cv.template,
|
||||||
|
vol.Optional(CONF_SWING_HORIZONTAL_MODE_STATE_TOPIC): valid_subscribe_topic,
|
||||||
vol.Optional(CONF_SWING_MODE_COMMAND_TEMPLATE): cv.template,
|
vol.Optional(CONF_SWING_MODE_COMMAND_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_SWING_MODE_COMMAND_TOPIC): valid_publish_topic,
|
vol.Optional(CONF_SWING_MODE_COMMAND_TOPIC): valid_publish_topic,
|
||||||
vol.Optional(
|
vol.Optional(
|
||||||
@ -515,6 +536,7 @@ class MqttClimate(MqttTemperatureControlEntity, ClimateEntity):
|
|||||||
|
|
||||||
_attr_fan_mode: str | None = None
|
_attr_fan_mode: str | None = None
|
||||||
_attr_hvac_mode: HVACMode | None = None
|
_attr_hvac_mode: HVACMode | None = None
|
||||||
|
_attr_swing_horizontal_mode: str | None = None
|
||||||
_attr_swing_mode: str | None = None
|
_attr_swing_mode: str | None = None
|
||||||
_default_name = DEFAULT_NAME
|
_default_name = DEFAULT_NAME
|
||||||
_entity_id_format = climate.ENTITY_ID_FORMAT
|
_entity_id_format = climate.ENTITY_ID_FORMAT
|
||||||
@ -543,6 +565,7 @@ class MqttClimate(MqttTemperatureControlEntity, ClimateEntity):
|
|||||||
if (precision := config.get(CONF_PRECISION)) is not None:
|
if (precision := config.get(CONF_PRECISION)) is not None:
|
||||||
self._attr_precision = precision
|
self._attr_precision = precision
|
||||||
self._attr_fan_modes = config[CONF_FAN_MODE_LIST]
|
self._attr_fan_modes = config[CONF_FAN_MODE_LIST]
|
||||||
|
self._attr_swing_horizontal_modes = config[CONF_SWING_HORIZONTAL_MODE_LIST]
|
||||||
self._attr_swing_modes = config[CONF_SWING_MODE_LIST]
|
self._attr_swing_modes = config[CONF_SWING_MODE_LIST]
|
||||||
self._attr_target_temperature_step = config[CONF_TEMP_STEP]
|
self._attr_target_temperature_step = config[CONF_TEMP_STEP]
|
||||||
|
|
||||||
@ -568,6 +591,11 @@ class MqttClimate(MqttTemperatureControlEntity, ClimateEntity):
|
|||||||
|
|
||||||
if self._topic[CONF_FAN_MODE_STATE_TOPIC] is None or self._optimistic:
|
if self._topic[CONF_FAN_MODE_STATE_TOPIC] is None or self._optimistic:
|
||||||
self._attr_fan_mode = FAN_LOW
|
self._attr_fan_mode = FAN_LOW
|
||||||
|
if (
|
||||||
|
self._topic[CONF_SWING_HORIZONTAL_MODE_STATE_TOPIC] is None
|
||||||
|
or self._optimistic
|
||||||
|
):
|
||||||
|
self._attr_swing_horizontal_mode = SWING_OFF
|
||||||
if self._topic[CONF_SWING_MODE_STATE_TOPIC] is None or self._optimistic:
|
if self._topic[CONF_SWING_MODE_STATE_TOPIC] is None or self._optimistic:
|
||||||
self._attr_swing_mode = SWING_OFF
|
self._attr_swing_mode = SWING_OFF
|
||||||
if self._topic[CONF_MODE_STATE_TOPIC] is None or self._optimistic:
|
if self._topic[CONF_MODE_STATE_TOPIC] is None or self._optimistic:
|
||||||
@ -629,6 +657,11 @@ class MqttClimate(MqttTemperatureControlEntity, ClimateEntity):
|
|||||||
):
|
):
|
||||||
support |= ClimateEntityFeature.FAN_MODE
|
support |= ClimateEntityFeature.FAN_MODE
|
||||||
|
|
||||||
|
if (self._topic[CONF_SWING_HORIZONTAL_MODE_STATE_TOPIC] is not None) or (
|
||||||
|
self._topic[CONF_SWING_HORIZONTAL_MODE_COMMAND_TOPIC] is not None
|
||||||
|
):
|
||||||
|
support |= ClimateEntityFeature.SWING_HORIZONTAL_MODE
|
||||||
|
|
||||||
if (self._topic[CONF_SWING_MODE_STATE_TOPIC] is not None) or (
|
if (self._topic[CONF_SWING_MODE_STATE_TOPIC] is not None) or (
|
||||||
self._topic[CONF_SWING_MODE_COMMAND_TOPIC] is not None
|
self._topic[CONF_SWING_MODE_COMMAND_TOPIC] is not None
|
||||||
):
|
):
|
||||||
@ -744,6 +777,16 @@ class MqttClimate(MqttTemperatureControlEntity, ClimateEntity):
|
|||||||
),
|
),
|
||||||
{"_attr_fan_mode"},
|
{"_attr_fan_mode"},
|
||||||
)
|
)
|
||||||
|
self.add_subscription(
|
||||||
|
CONF_SWING_HORIZONTAL_MODE_STATE_TOPIC,
|
||||||
|
partial(
|
||||||
|
self._handle_mode_received,
|
||||||
|
CONF_SWING_HORIZONTAL_MODE_STATE_TEMPLATE,
|
||||||
|
"_attr_swing_horizontal_mode",
|
||||||
|
CONF_SWING_HORIZONTAL_MODE_LIST,
|
||||||
|
),
|
||||||
|
{"_attr_swing_horizontal_mode"},
|
||||||
|
)
|
||||||
self.add_subscription(
|
self.add_subscription(
|
||||||
CONF_SWING_MODE_STATE_TOPIC,
|
CONF_SWING_MODE_STATE_TOPIC,
|
||||||
partial(
|
partial(
|
||||||
@ -782,6 +825,20 @@ class MqttClimate(MqttTemperatureControlEntity, ClimateEntity):
|
|||||||
|
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
|
async def async_set_swing_horizontal_mode(self, swing_horizontal_mode: str) -> None:
|
||||||
|
"""Set new swing horizontal mode."""
|
||||||
|
payload = self._command_templates[CONF_SWING_HORIZONTAL_MODE_COMMAND_TEMPLATE](
|
||||||
|
swing_horizontal_mode
|
||||||
|
)
|
||||||
|
await self._publish(CONF_SWING_HORIZONTAL_MODE_COMMAND_TOPIC, payload)
|
||||||
|
|
||||||
|
if (
|
||||||
|
self._optimistic
|
||||||
|
or self._topic[CONF_SWING_HORIZONTAL_MODE_STATE_TOPIC] is None
|
||||||
|
):
|
||||||
|
self._attr_swing_horizontal_mode = swing_horizontal_mode
|
||||||
|
self.async_write_ha_state()
|
||||||
|
|
||||||
async def async_set_swing_mode(self, swing_mode: str) -> None:
|
async def async_set_swing_mode(self, swing_mode: str) -> None:
|
||||||
"""Set new swing mode."""
|
"""Set new swing mode."""
|
||||||
payload = self._command_templates[CONF_SWING_MODE_COMMAND_TEMPLATE](swing_mode)
|
payload = self._command_templates[CONF_SWING_MODE_COMMAND_TEMPLATE](swing_mode)
|
||||||
|
@ -11,6 +11,7 @@ from homeassistant.components.climate import (
|
|||||||
ATTR_HUMIDITY,
|
ATTR_HUMIDITY,
|
||||||
ATTR_HVAC_MODE,
|
ATTR_HVAC_MODE,
|
||||||
ATTR_PRESET_MODE,
|
ATTR_PRESET_MODE,
|
||||||
|
ATTR_SWING_HORIZONTAL_MODE,
|
||||||
ATTR_SWING_MODE,
|
ATTR_SWING_MODE,
|
||||||
ATTR_TARGET_TEMP_HIGH,
|
ATTR_TARGET_TEMP_HIGH,
|
||||||
ATTR_TARGET_TEMP_LOW,
|
ATTR_TARGET_TEMP_LOW,
|
||||||
@ -20,10 +21,11 @@ from homeassistant.components.climate import (
|
|||||||
SERVICE_SET_HUMIDITY,
|
SERVICE_SET_HUMIDITY,
|
||||||
SERVICE_SET_HVAC_MODE,
|
SERVICE_SET_HVAC_MODE,
|
||||||
SERVICE_SET_PRESET_MODE,
|
SERVICE_SET_PRESET_MODE,
|
||||||
|
SERVICE_SET_SWING_HORIZONTAL_MODE,
|
||||||
SERVICE_SET_SWING_MODE,
|
SERVICE_SET_SWING_MODE,
|
||||||
SERVICE_SET_TEMPERATURE,
|
SERVICE_SET_TEMPERATURE,
|
||||||
|
HVACMode,
|
||||||
)
|
)
|
||||||
from homeassistant.components.climate.const import HVACMode
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ENTITY_ID,
|
ATTR_ENTITY_ID,
|
||||||
ATTR_TEMPERATURE,
|
ATTR_TEMPERATURE,
|
||||||
@ -211,6 +213,20 @@ def set_operation_mode(
|
|||||||
hass.services.call(DOMAIN, SERVICE_SET_HVAC_MODE, data)
|
hass.services.call(DOMAIN, SERVICE_SET_HVAC_MODE, data)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_set_swing_horizontal_mode(
|
||||||
|
hass: HomeAssistant, swing_horizontal_mode: str, entity_id: str = ENTITY_MATCH_ALL
|
||||||
|
) -> None:
|
||||||
|
"""Set new target swing horizontal mode."""
|
||||||
|
data = {ATTR_SWING_HORIZONTAL_MODE: swing_horizontal_mode}
|
||||||
|
|
||||||
|
if entity_id is not None:
|
||||||
|
data[ATTR_ENTITY_ID] = entity_id
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN, SERVICE_SET_SWING_HORIZONTAL_MODE, data, blocking=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_set_swing_mode(
|
async def async_set_swing_mode(
|
||||||
hass: HomeAssistant, swing_mode: str, entity_id: str = ENTITY_MATCH_ALL
|
hass: HomeAssistant, swing_mode: str, entity_id: str = ENTITY_MATCH_ALL
|
||||||
) -> None:
|
) -> None:
|
||||||
|
@ -15,6 +15,7 @@ from homeassistant.components.climate import (
|
|||||||
ATTR_FAN_MODE,
|
ATTR_FAN_MODE,
|
||||||
ATTR_HUMIDITY,
|
ATTR_HUMIDITY,
|
||||||
ATTR_HVAC_ACTION,
|
ATTR_HVAC_ACTION,
|
||||||
|
ATTR_SWING_HORIZONTAL_MODE,
|
||||||
ATTR_SWING_MODE,
|
ATTR_SWING_MODE,
|
||||||
ATTR_TARGET_TEMP_HIGH,
|
ATTR_TARGET_TEMP_HIGH,
|
||||||
ATTR_TARGET_TEMP_LOW,
|
ATTR_TARGET_TEMP_LOW,
|
||||||
@ -85,6 +86,7 @@ DEFAULT_CONFIG = {
|
|||||||
"temperature_high_command_topic": "temperature-high-topic",
|
"temperature_high_command_topic": "temperature-high-topic",
|
||||||
"fan_mode_command_topic": "fan-mode-topic",
|
"fan_mode_command_topic": "fan-mode-topic",
|
||||||
"swing_mode_command_topic": "swing-mode-topic",
|
"swing_mode_command_topic": "swing-mode-topic",
|
||||||
|
"swing_horizontal_mode_command_topic": "swing-horizontal-mode-topic",
|
||||||
"preset_mode_command_topic": "preset-mode-topic",
|
"preset_mode_command_topic": "preset-mode-topic",
|
||||||
"preset_modes": [
|
"preset_modes": [
|
||||||
"eco",
|
"eco",
|
||||||
@ -111,6 +113,7 @@ async def test_setup_params(
|
|||||||
assert state.attributes.get("temperature") == 21
|
assert state.attributes.get("temperature") == 21
|
||||||
assert state.attributes.get("fan_mode") == "low"
|
assert state.attributes.get("fan_mode") == "low"
|
||||||
assert state.attributes.get("swing_mode") == "off"
|
assert state.attributes.get("swing_mode") == "off"
|
||||||
|
assert state.attributes.get("swing_horizontal_mode") == "off"
|
||||||
assert state.state == "off"
|
assert state.state == "off"
|
||||||
assert state.attributes.get("min_temp") == DEFAULT_MIN_TEMP
|
assert state.attributes.get("min_temp") == DEFAULT_MIN_TEMP
|
||||||
assert state.attributes.get("max_temp") == DEFAULT_MAX_TEMP
|
assert state.attributes.get("max_temp") == DEFAULT_MAX_TEMP
|
||||||
@ -123,6 +126,7 @@ async def test_setup_params(
|
|||||||
| ClimateEntityFeature.TARGET_HUMIDITY
|
| ClimateEntityFeature.TARGET_HUMIDITY
|
||||||
| ClimateEntityFeature.FAN_MODE
|
| ClimateEntityFeature.FAN_MODE
|
||||||
| ClimateEntityFeature.PRESET_MODE
|
| ClimateEntityFeature.PRESET_MODE
|
||||||
|
| ClimateEntityFeature.SWING_HORIZONTAL_MODE
|
||||||
| ClimateEntityFeature.SWING_MODE
|
| ClimateEntityFeature.SWING_MODE
|
||||||
| ClimateEntityFeature.TURN_OFF
|
| ClimateEntityFeature.TURN_OFF
|
||||||
| ClimateEntityFeature.TURN_ON
|
| ClimateEntityFeature.TURN_ON
|
||||||
@ -159,6 +163,7 @@ async def test_supported_features(
|
|||||||
state = hass.states.get(ENTITY_CLIMATE)
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
support = (
|
support = (
|
||||||
ClimateEntityFeature.TARGET_TEMPERATURE
|
ClimateEntityFeature.TARGET_TEMPERATURE
|
||||||
|
| ClimateEntityFeature.SWING_HORIZONTAL_MODE
|
||||||
| ClimateEntityFeature.SWING_MODE
|
| ClimateEntityFeature.SWING_MODE
|
||||||
| ClimateEntityFeature.FAN_MODE
|
| ClimateEntityFeature.FAN_MODE
|
||||||
| ClimateEntityFeature.PRESET_MODE
|
| ClimateEntityFeature.PRESET_MODE
|
||||||
@ -562,12 +567,29 @@ async def test_set_swing_mode_bad_attr(
|
|||||||
state = hass.states.get(ENTITY_CLIMATE)
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
assert state.attributes.get("swing_mode") == "off"
|
assert state.attributes.get("swing_mode") == "off"
|
||||||
|
|
||||||
|
assert state.attributes.get("swing_horizontal_mode") == "off"
|
||||||
|
with pytest.raises(vol.Invalid) as excinfo:
|
||||||
|
await common.async_set_swing_horizontal_mode(hass, None, ENTITY_CLIMATE) # type:ignore[arg-type]
|
||||||
|
assert (
|
||||||
|
"string value is None for dictionary value @ data['swing_horizontal_mode']"
|
||||||
|
in str(excinfo.value)
|
||||||
|
)
|
||||||
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
|
assert state.attributes.get("swing_horizontal_mode") == "off"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"hass_config",
|
"hass_config",
|
||||||
[
|
[
|
||||||
help_custom_config(
|
help_custom_config(
|
||||||
climate.DOMAIN, DEFAULT_CONFIG, ({"swing_mode_state_topic": "swing-state"},)
|
climate.DOMAIN,
|
||||||
|
DEFAULT_CONFIG,
|
||||||
|
(
|
||||||
|
{
|
||||||
|
"swing_mode_state_topic": "swing-state",
|
||||||
|
"swing_horizontal_mode_state_topic": "swing-horizontal-state",
|
||||||
|
},
|
||||||
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -579,19 +601,32 @@ async def test_set_swing_pessimistic(
|
|||||||
|
|
||||||
state = hass.states.get(ENTITY_CLIMATE)
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
assert state.attributes.get("swing_mode") is None
|
assert state.attributes.get("swing_mode") is None
|
||||||
|
assert state.attributes.get("swing_horizontal_mode") is None
|
||||||
|
|
||||||
await common.async_set_swing_mode(hass, "on", ENTITY_CLIMATE)
|
await common.async_set_swing_mode(hass, "on", ENTITY_CLIMATE)
|
||||||
state = hass.states.get(ENTITY_CLIMATE)
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
assert state.attributes.get("swing_mode") is None
|
assert state.attributes.get("swing_mode") is None
|
||||||
|
|
||||||
|
await common.async_set_swing_horizontal_mode(hass, "on", ENTITY_CLIMATE)
|
||||||
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
|
assert state.attributes.get("swing_horizontal_mode") is None
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "swing-state", "on")
|
async_fire_mqtt_message(hass, "swing-state", "on")
|
||||||
state = hass.states.get(ENTITY_CLIMATE)
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
assert state.attributes.get("swing_mode") == "on"
|
assert state.attributes.get("swing_mode") == "on"
|
||||||
|
|
||||||
|
async_fire_mqtt_message(hass, "swing-horizontal-state", "on")
|
||||||
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
|
assert state.attributes.get("swing_horizontal_mode") == "on"
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "swing-state", "bogus state")
|
async_fire_mqtt_message(hass, "swing-state", "bogus state")
|
||||||
state = hass.states.get(ENTITY_CLIMATE)
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
assert state.attributes.get("swing_mode") == "on"
|
assert state.attributes.get("swing_mode") == "on"
|
||||||
|
|
||||||
|
async_fire_mqtt_message(hass, "swing-horizontal-state", "bogus state")
|
||||||
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
|
assert state.attributes.get("swing_horizontal_mode") == "on"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"hass_config",
|
"hass_config",
|
||||||
@ -599,7 +634,13 @@ async def test_set_swing_pessimistic(
|
|||||||
help_custom_config(
|
help_custom_config(
|
||||||
climate.DOMAIN,
|
climate.DOMAIN,
|
||||||
DEFAULT_CONFIG,
|
DEFAULT_CONFIG,
|
||||||
({"swing_mode_state_topic": "swing-state", "optimistic": True},),
|
(
|
||||||
|
{
|
||||||
|
"swing_mode_state_topic": "swing-state",
|
||||||
|
"swing_horizontal_mode_state_topic": "swing-horizontal-state",
|
||||||
|
"optimistic": True,
|
||||||
|
},
|
||||||
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -611,19 +652,32 @@ async def test_set_swing_optimistic(
|
|||||||
|
|
||||||
state = hass.states.get(ENTITY_CLIMATE)
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
assert state.attributes.get("swing_mode") == "off"
|
assert state.attributes.get("swing_mode") == "off"
|
||||||
|
assert state.attributes.get("swing_horizontal_mode") == "off"
|
||||||
|
|
||||||
await common.async_set_swing_mode(hass, "on", ENTITY_CLIMATE)
|
await common.async_set_swing_mode(hass, "on", ENTITY_CLIMATE)
|
||||||
state = hass.states.get(ENTITY_CLIMATE)
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
assert state.attributes.get("swing_mode") == "on"
|
assert state.attributes.get("swing_mode") == "on"
|
||||||
|
|
||||||
|
await common.async_set_swing_horizontal_mode(hass, "on", ENTITY_CLIMATE)
|
||||||
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
|
assert state.attributes.get("swing_horizontal_mode") == "on"
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "swing-state", "off")
|
async_fire_mqtt_message(hass, "swing-state", "off")
|
||||||
state = hass.states.get(ENTITY_CLIMATE)
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
assert state.attributes.get("swing_mode") == "off"
|
assert state.attributes.get("swing_mode") == "off"
|
||||||
|
|
||||||
|
async_fire_mqtt_message(hass, "swing-horizontal-state", "off")
|
||||||
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
|
assert state.attributes.get("swing_horizontal_mode") == "off"
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "swing-state", "bogus state")
|
async_fire_mqtt_message(hass, "swing-state", "bogus state")
|
||||||
state = hass.states.get(ENTITY_CLIMATE)
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
assert state.attributes.get("swing_mode") == "off"
|
assert state.attributes.get("swing_mode") == "off"
|
||||||
|
|
||||||
|
async_fire_mqtt_message(hass, "swing-horizontal-state", "bogus state")
|
||||||
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
|
assert state.attributes.get("swing_horizontal_mode") == "off"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("hass_config", [DEFAULT_CONFIG])
|
@pytest.mark.parametrize("hass_config", [DEFAULT_CONFIG])
|
||||||
async def test_set_swing(
|
async def test_set_swing(
|
||||||
@ -638,6 +692,15 @@ async def test_set_swing(
|
|||||||
mqtt_mock.async_publish.assert_called_once_with("swing-mode-topic", "on", 0, False)
|
mqtt_mock.async_publish.assert_called_once_with("swing-mode-topic", "on", 0, False)
|
||||||
state = hass.states.get(ENTITY_CLIMATE)
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
assert state.attributes.get("swing_mode") == "on"
|
assert state.attributes.get("swing_mode") == "on"
|
||||||
|
mqtt_mock.reset_mock()
|
||||||
|
|
||||||
|
assert state.attributes.get("swing_horizontal_mode") == "off"
|
||||||
|
await common.async_set_swing_horizontal_mode(hass, "on", ENTITY_CLIMATE)
|
||||||
|
mqtt_mock.async_publish.assert_called_once_with(
|
||||||
|
"swing-horizontal-mode-topic", "on", 0, False
|
||||||
|
)
|
||||||
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
|
assert state.attributes.get("swing_horizontal_mode") == "on"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("hass_config", [DEFAULT_CONFIG])
|
@pytest.mark.parametrize("hass_config", [DEFAULT_CONFIG])
|
||||||
@ -1337,6 +1400,7 @@ async def test_get_target_temperature_low_high_with_templates(
|
|||||||
"temperature_low_command_topic": "temperature-low-topic",
|
"temperature_low_command_topic": "temperature-low-topic",
|
||||||
"temperature_high_command_topic": "temperature-high-topic",
|
"temperature_high_command_topic": "temperature-high-topic",
|
||||||
"fan_mode_command_topic": "fan-mode-topic",
|
"fan_mode_command_topic": "fan-mode-topic",
|
||||||
|
"swing_horizontal_mode_command_topic": "swing-horizontal-mode-topic",
|
||||||
"swing_mode_command_topic": "swing-mode-topic",
|
"swing_mode_command_topic": "swing-mode-topic",
|
||||||
"preset_mode_command_topic": "preset-mode-topic",
|
"preset_mode_command_topic": "preset-mode-topic",
|
||||||
"preset_modes": [
|
"preset_modes": [
|
||||||
@ -1359,6 +1423,7 @@ async def test_get_target_temperature_low_high_with_templates(
|
|||||||
"action_topic": "action",
|
"action_topic": "action",
|
||||||
"mode_state_topic": "mode-state",
|
"mode_state_topic": "mode-state",
|
||||||
"fan_mode_state_topic": "fan-state",
|
"fan_mode_state_topic": "fan-state",
|
||||||
|
"swing_horizontal_mode_state_topic": "swing-horizontal-state",
|
||||||
"swing_mode_state_topic": "swing-state",
|
"swing_mode_state_topic": "swing-state",
|
||||||
"temperature_state_topic": "temperature-state",
|
"temperature_state_topic": "temperature-state",
|
||||||
"target_humidity_state_topic": "humidity-state",
|
"target_humidity_state_topic": "humidity-state",
|
||||||
@ -1396,6 +1461,12 @@ async def test_get_with_templates(
|
|||||||
state = hass.states.get(ENTITY_CLIMATE)
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
assert state.attributes.get("swing_mode") == "on"
|
assert state.attributes.get("swing_mode") == "on"
|
||||||
|
|
||||||
|
# Swing Horizontal Mode
|
||||||
|
assert state.attributes.get("swing_horizontal_mode") is None
|
||||||
|
async_fire_mqtt_message(hass, "swing-horizontal-state", '"on"')
|
||||||
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
|
assert state.attributes.get("swing_horizontal_mode") == "on"
|
||||||
|
|
||||||
# Temperature - with valid value
|
# Temperature - with valid value
|
||||||
assert state.attributes.get("temperature") is None
|
assert state.attributes.get("temperature") is None
|
||||||
async_fire_mqtt_message(hass, "temperature-state", '"1031"')
|
async_fire_mqtt_message(hass, "temperature-state", '"1031"')
|
||||||
@ -1495,6 +1566,7 @@ async def test_get_with_templates(
|
|||||||
"temperature_low_command_topic": "temperature-low-topic",
|
"temperature_low_command_topic": "temperature-low-topic",
|
||||||
"temperature_high_command_topic": "temperature-high-topic",
|
"temperature_high_command_topic": "temperature-high-topic",
|
||||||
"fan_mode_command_topic": "fan-mode-topic",
|
"fan_mode_command_topic": "fan-mode-topic",
|
||||||
|
"swing_horizontal_mode_command_topic": "swing-horizontal-mode-topic",
|
||||||
"swing_mode_command_topic": "swing-mode-topic",
|
"swing_mode_command_topic": "swing-mode-topic",
|
||||||
"preset_mode_command_topic": "preset-mode-topic",
|
"preset_mode_command_topic": "preset-mode-topic",
|
||||||
"preset_modes": [
|
"preset_modes": [
|
||||||
@ -1511,6 +1583,7 @@ async def test_get_with_templates(
|
|||||||
"power_command_template": "power: {{ value }}",
|
"power_command_template": "power: {{ value }}",
|
||||||
"preset_mode_command_template": "preset_mode: {{ value }}",
|
"preset_mode_command_template": "preset_mode: {{ value }}",
|
||||||
"mode_command_template": "mode: {{ value }}",
|
"mode_command_template": "mode: {{ value }}",
|
||||||
|
"swing_horizontal_mode_command_template": "swing_horizontal_mode: {{ value }}",
|
||||||
"swing_mode_command_template": "swing_mode: {{ value }}",
|
"swing_mode_command_template": "swing_mode: {{ value }}",
|
||||||
"temperature_command_template": "temp: {{ value }}",
|
"temperature_command_template": "temp: {{ value }}",
|
||||||
"temperature_high_command_template": "temp_hi: {{ value }}",
|
"temperature_high_command_template": "temp_hi: {{ value }}",
|
||||||
@ -1580,6 +1653,15 @@ async def test_set_and_templates(
|
|||||||
state = hass.states.get(ENTITY_CLIMATE)
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
assert state.state == "off"
|
assert state.state == "off"
|
||||||
|
|
||||||
|
# Swing Horizontal Mode
|
||||||
|
await common.async_set_swing_horizontal_mode(hass, "on", ENTITY_CLIMATE)
|
||||||
|
mqtt_mock.async_publish.assert_called_once_with(
|
||||||
|
"swing-horizontal-mode-topic", "swing_horizontal_mode: on", 0, False
|
||||||
|
)
|
||||||
|
mqtt_mock.async_publish.reset_mock()
|
||||||
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
|
assert state.attributes.get("swing_horizontal_mode") == "on"
|
||||||
|
|
||||||
# Swing Mode
|
# Swing Mode
|
||||||
await common.async_set_swing_mode(hass, "on", ENTITY_CLIMATE)
|
await common.async_set_swing_mode(hass, "on", ENTITY_CLIMATE)
|
||||||
mqtt_mock.async_publish.assert_called_once_with(
|
mqtt_mock.async_publish.assert_called_once_with(
|
||||||
@ -1940,6 +2022,7 @@ async def test_unique_id(
|
|||||||
("fan_mode_state_topic", "low", ATTR_FAN_MODE, "low"),
|
("fan_mode_state_topic", "low", ATTR_FAN_MODE, "low"),
|
||||||
("mode_state_topic", "cool", None, None),
|
("mode_state_topic", "cool", None, None),
|
||||||
("mode_state_topic", "fan_only", None, None),
|
("mode_state_topic", "fan_only", None, None),
|
||||||
|
("swing_horizontal_mode_state_topic", "on", ATTR_SWING_HORIZONTAL_MODE, "on"),
|
||||||
("swing_mode_state_topic", "on", ATTR_SWING_MODE, "on"),
|
("swing_mode_state_topic", "on", ATTR_SWING_MODE, "on"),
|
||||||
("temperature_low_state_topic", "19.1", ATTR_TARGET_TEMP_LOW, 19.1),
|
("temperature_low_state_topic", "19.1", ATTR_TARGET_TEMP_LOW, 19.1),
|
||||||
("temperature_high_state_topic", "22.9", ATTR_TARGET_TEMP_HIGH, 22.9),
|
("temperature_high_state_topic", "22.9", ATTR_TARGET_TEMP_HIGH, 22.9),
|
||||||
@ -2178,6 +2261,13 @@ async def test_precision_whole(
|
|||||||
"medium",
|
"medium",
|
||||||
"fan_mode_command_template",
|
"fan_mode_command_template",
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
climate.SERVICE_SET_SWING_HORIZONTAL_MODE,
|
||||||
|
"swing_horizontal_mode_command_topic",
|
||||||
|
{"swing_horizontal_mode": "on"},
|
||||||
|
"on",
|
||||||
|
"swing_horizontal_mode_command_template",
|
||||||
|
),
|
||||||
(
|
(
|
||||||
climate.SERVICE_SET_SWING_MODE,
|
climate.SERVICE_SET_SWING_MODE,
|
||||||
"swing_mode_command_topic",
|
"swing_mode_command_topic",
|
||||||
@ -2378,6 +2468,7 @@ async def test_unload_entry(
|
|||||||
"current_temperature_topic": "current-temperature-topic",
|
"current_temperature_topic": "current-temperature-topic",
|
||||||
"preset_mode_state_topic": "preset-mode-state-topic",
|
"preset_mode_state_topic": "preset-mode-state-topic",
|
||||||
"preset_modes": ["eco", "away"],
|
"preset_modes": ["eco", "away"],
|
||||||
|
"swing_horizontal_mode_state_topic": "swing-horizontal-mode-state-topic",
|
||||||
"swing_mode_state_topic": "swing-mode-state-topic",
|
"swing_mode_state_topic": "swing-mode-state-topic",
|
||||||
"target_humidity_state_topic": "target-humidity-state-topic",
|
"target_humidity_state_topic": "target-humidity-state-topic",
|
||||||
"temperature_high_state_topic": "temperature-high-state-topic",
|
"temperature_high_state_topic": "temperature-high-state-topic",
|
||||||
@ -2399,6 +2490,7 @@ async def test_unload_entry(
|
|||||||
("current-humidity-topic", "45", "46"),
|
("current-humidity-topic", "45", "46"),
|
||||||
("current-temperature-topic", "18.0", "18.1"),
|
("current-temperature-topic", "18.0", "18.1"),
|
||||||
("preset-mode-state-topic", "eco", "away"),
|
("preset-mode-state-topic", "eco", "away"),
|
||||||
|
("swing-horizontal-mode-state-topic", "on", "off"),
|
||||||
("swing-mode-state-topic", "on", "off"),
|
("swing-mode-state-topic", "on", "off"),
|
||||||
("target-humidity-state-topic", "45", "50"),
|
("target-humidity-state-topic", "45", "50"),
|
||||||
("temperature-state-topic", "18", "19"),
|
("temperature-state-topic", "18", "19"),
|
||||||
|
@ -2380,7 +2380,6 @@ ABBREVIATIONS_WHITE_LIST = [
|
|||||||
"CONF_PRECISION",
|
"CONF_PRECISION",
|
||||||
"CONF_QOS",
|
"CONF_QOS",
|
||||||
"CONF_SCHEMA",
|
"CONF_SCHEMA",
|
||||||
"CONF_SWING_MODE_LIST",
|
|
||||||
"CONF_TEMP_STEP",
|
"CONF_TEMP_STEP",
|
||||||
# Removed
|
# Removed
|
||||||
"CONF_WHITE_VALUE",
|
"CONF_WHITE_VALUE",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user