mirror of
https://github.com/home-assistant/core.git
synced 2025-07-15 01:07:10 +00:00
Reconfigure MQTT climate component if discovery info is changed (#18174)
This commit is contained in:
parent
986ca23934
commit
e41af133fc
@ -22,7 +22,8 @@ from homeassistant.const import (
|
|||||||
from homeassistant.components.mqtt import (
|
from homeassistant.components.mqtt import (
|
||||||
ATTR_DISCOVERY_HASH, CONF_AVAILABILITY_TOPIC, CONF_QOS, CONF_RETAIN,
|
ATTR_DISCOVERY_HASH, CONF_AVAILABILITY_TOPIC, CONF_QOS, CONF_RETAIN,
|
||||||
CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE,
|
CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE,
|
||||||
MQTT_BASE_PLATFORM_SCHEMA, MqttAvailability, MqttDiscoveryUpdate)
|
MQTT_BASE_PLATFORM_SCHEMA, MqttAvailability, MqttDiscoveryUpdate,
|
||||||
|
subscription)
|
||||||
from homeassistant.components.mqtt.discovery import MQTT_DISCOVERY_NEW
|
from homeassistant.components.mqtt.discovery import MQTT_DISCOVERY_NEW
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
@ -77,6 +78,18 @@ CONF_MIN_TEMP = 'min_temp'
|
|||||||
CONF_MAX_TEMP = 'max_temp'
|
CONF_MAX_TEMP = 'max_temp'
|
||||||
CONF_TEMP_STEP = 'temp_step'
|
CONF_TEMP_STEP = 'temp_step'
|
||||||
|
|
||||||
|
TEMPLATE_KEYS = (
|
||||||
|
CONF_POWER_STATE_TEMPLATE,
|
||||||
|
CONF_MODE_STATE_TEMPLATE,
|
||||||
|
CONF_TEMPERATURE_STATE_TEMPLATE,
|
||||||
|
CONF_FAN_MODE_STATE_TEMPLATE,
|
||||||
|
CONF_SWING_MODE_STATE_TEMPLATE,
|
||||||
|
CONF_AWAY_MODE_STATE_TEMPLATE,
|
||||||
|
CONF_HOLD_STATE_TEMPLATE,
|
||||||
|
CONF_AUX_STATE_TEMPLATE,
|
||||||
|
CONF_CURRENT_TEMPERATURE_TEMPLATE
|
||||||
|
)
|
||||||
|
|
||||||
SCHEMA_BASE = CLIMATE_PLATFORM_SCHEMA.extend(MQTT_BASE_PLATFORM_SCHEMA.schema)
|
SCHEMA_BASE = CLIMATE_PLATFORM_SCHEMA.extend(MQTT_BASE_PLATFORM_SCHEMA.schema)
|
||||||
PLATFORM_SCHEMA = SCHEMA_BASE.extend({
|
PLATFORM_SCHEMA = SCHEMA_BASE.extend({
|
||||||
vol.Optional(CONF_POWER_COMMAND_TOPIC): mqtt.valid_publish_topic,
|
vol.Optional(CONF_POWER_COMMAND_TOPIC): mqtt.valid_publish_topic,
|
||||||
@ -153,69 +166,10 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||||||
async def _async_setup_entity(hass, config, async_add_entities,
|
async def _async_setup_entity(hass, config, async_add_entities,
|
||||||
discovery_hash=None):
|
discovery_hash=None):
|
||||||
"""Set up the MQTT climate devices."""
|
"""Set up the MQTT climate devices."""
|
||||||
template_keys = (
|
|
||||||
CONF_POWER_STATE_TEMPLATE,
|
|
||||||
CONF_MODE_STATE_TEMPLATE,
|
|
||||||
CONF_TEMPERATURE_STATE_TEMPLATE,
|
|
||||||
CONF_FAN_MODE_STATE_TEMPLATE,
|
|
||||||
CONF_SWING_MODE_STATE_TEMPLATE,
|
|
||||||
CONF_AWAY_MODE_STATE_TEMPLATE,
|
|
||||||
CONF_HOLD_STATE_TEMPLATE,
|
|
||||||
CONF_AUX_STATE_TEMPLATE,
|
|
||||||
CONF_CURRENT_TEMPERATURE_TEMPLATE
|
|
||||||
)
|
|
||||||
value_templates = {}
|
|
||||||
if CONF_VALUE_TEMPLATE in config:
|
|
||||||
value_template = config.get(CONF_VALUE_TEMPLATE)
|
|
||||||
value_template.hass = hass
|
|
||||||
value_templates = {key: value_template for key in template_keys}
|
|
||||||
for key in template_keys & config.keys():
|
|
||||||
value_templates[key] = config.get(key)
|
|
||||||
value_templates[key].hass = hass
|
|
||||||
|
|
||||||
async_add_entities([
|
async_add_entities([
|
||||||
MqttClimate(
|
MqttClimate(
|
||||||
hass,
|
hass,
|
||||||
config.get(CONF_NAME),
|
config,
|
||||||
{
|
|
||||||
key: config.get(key) for key in (
|
|
||||||
CONF_POWER_COMMAND_TOPIC,
|
|
||||||
CONF_MODE_COMMAND_TOPIC,
|
|
||||||
CONF_TEMPERATURE_COMMAND_TOPIC,
|
|
||||||
CONF_FAN_MODE_COMMAND_TOPIC,
|
|
||||||
CONF_SWING_MODE_COMMAND_TOPIC,
|
|
||||||
CONF_AWAY_MODE_COMMAND_TOPIC,
|
|
||||||
CONF_HOLD_COMMAND_TOPIC,
|
|
||||||
CONF_AUX_COMMAND_TOPIC,
|
|
||||||
CONF_POWER_STATE_TOPIC,
|
|
||||||
CONF_MODE_STATE_TOPIC,
|
|
||||||
CONF_TEMPERATURE_STATE_TOPIC,
|
|
||||||
CONF_FAN_MODE_STATE_TOPIC,
|
|
||||||
CONF_SWING_MODE_STATE_TOPIC,
|
|
||||||
CONF_AWAY_MODE_STATE_TOPIC,
|
|
||||||
CONF_HOLD_STATE_TOPIC,
|
|
||||||
CONF_AUX_STATE_TOPIC,
|
|
||||||
CONF_CURRENT_TEMPERATURE_TOPIC
|
|
||||||
)
|
|
||||||
},
|
|
||||||
value_templates,
|
|
||||||
config.get(CONF_QOS),
|
|
||||||
config.get(CONF_RETAIN),
|
|
||||||
config.get(CONF_MODE_LIST),
|
|
||||||
config.get(CONF_FAN_MODE_LIST),
|
|
||||||
config.get(CONF_SWING_MODE_LIST),
|
|
||||||
config.get(CONF_INITIAL),
|
|
||||||
False, None, SPEED_LOW,
|
|
||||||
STATE_OFF, STATE_OFF, False,
|
|
||||||
config.get(CONF_SEND_IF_OFF),
|
|
||||||
config.get(CONF_PAYLOAD_ON),
|
|
||||||
config.get(CONF_PAYLOAD_OFF),
|
|
||||||
config.get(CONF_AVAILABILITY_TOPIC),
|
|
||||||
config.get(CONF_PAYLOAD_AVAILABLE),
|
|
||||||
config.get(CONF_PAYLOAD_NOT_AVAILABLE),
|
|
||||||
config.get(CONF_MIN_TEMP),
|
|
||||||
config.get(CONF_MAX_TEMP),
|
|
||||||
config.get(CONF_TEMP_STEP),
|
|
||||||
discovery_hash,
|
discovery_hash,
|
||||||
)])
|
)])
|
||||||
|
|
||||||
@ -223,54 +177,130 @@ async def _async_setup_entity(hass, config, async_add_entities,
|
|||||||
class MqttClimate(MqttAvailability, MqttDiscoveryUpdate, ClimateDevice):
|
class MqttClimate(MqttAvailability, MqttDiscoveryUpdate, ClimateDevice):
|
||||||
"""Representation of an MQTT climate device."""
|
"""Representation of an MQTT climate device."""
|
||||||
|
|
||||||
def __init__(self, hass, name, topic, value_templates, qos, retain,
|
def __init__(self, hass, config, discovery_hash):
|
||||||
mode_list, fan_mode_list, swing_mode_list,
|
|
||||||
target_temperature, away, hold, current_fan_mode,
|
|
||||||
current_swing_mode, current_operation, aux, send_if_off,
|
|
||||||
payload_on, payload_off, availability_topic,
|
|
||||||
payload_available, payload_not_available,
|
|
||||||
min_temp, max_temp, temp_step, discovery_hash):
|
|
||||||
"""Initialize the climate device."""
|
"""Initialize the climate device."""
|
||||||
MqttAvailability.__init__(self, availability_topic, qos,
|
self._config = config
|
||||||
payload_available, payload_not_available)
|
self._sub_state = None
|
||||||
MqttDiscoveryUpdate.__init__(self, discovery_hash)
|
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
self._name = name
|
self._name = None
|
||||||
self._topic = topic
|
self._topic = None
|
||||||
self._value_templates = value_templates
|
self._value_templates = None
|
||||||
self._qos = qos
|
self._qos = None
|
||||||
self._retain = retain
|
self._retain = None
|
||||||
# set to None in non-optimistic mode
|
self._target_temperature = None
|
||||||
self._target_temperature = self._current_fan_mode = \
|
self._current_fan_mode = None
|
||||||
self._current_operation = self._current_swing_mode = None
|
self._current_operation = None
|
||||||
if self._topic[CONF_TEMPERATURE_STATE_TOPIC] is None:
|
self._current_swing_mode = None
|
||||||
self._target_temperature = target_temperature
|
|
||||||
self._unit_of_measurement = hass.config.units.temperature_unit
|
self._unit_of_measurement = hass.config.units.temperature_unit
|
||||||
self._away = away
|
self._away = False
|
||||||
self._hold = hold
|
self._hold = None
|
||||||
self._current_temperature = None
|
self._current_temperature = None
|
||||||
if self._topic[CONF_FAN_MODE_STATE_TOPIC] is None:
|
self._aux = False
|
||||||
self._current_fan_mode = current_fan_mode
|
self._fan_list = None
|
||||||
if self._topic[CONF_MODE_STATE_TOPIC] is None:
|
self._operation_list = None
|
||||||
self._current_operation = current_operation
|
self._swing_list = None
|
||||||
self._aux = aux
|
self._target_temperature_step = None
|
||||||
if self._topic[CONF_SWING_MODE_STATE_TOPIC] is None:
|
self._send_if_off = None
|
||||||
self._current_swing_mode = current_swing_mode
|
self._payload_on = None
|
||||||
self._fan_list = fan_mode_list
|
self._payload_off = None
|
||||||
self._operation_list = mode_list
|
self._min_temp = None
|
||||||
self._swing_list = swing_mode_list
|
self._max_temp = None
|
||||||
self._target_temperature_step = temp_step
|
|
||||||
self._send_if_off = send_if_off
|
# Load config
|
||||||
self._payload_on = payload_on
|
self._setup_from_config(config)
|
||||||
self._payload_off = payload_off
|
|
||||||
self._min_temp = min_temp
|
availability_topic = config.get(CONF_AVAILABILITY_TOPIC)
|
||||||
self._max_temp = max_temp
|
payload_available = config.get(CONF_PAYLOAD_AVAILABLE)
|
||||||
self._discovery_hash = discovery_hash
|
payload_not_available = config.get(CONF_PAYLOAD_NOT_AVAILABLE)
|
||||||
|
|
||||||
|
MqttAvailability.__init__(self, availability_topic, self._qos,
|
||||||
|
payload_available, payload_not_available)
|
||||||
|
MqttDiscoveryUpdate.__init__(self, discovery_hash,
|
||||||
|
self.discovery_update)
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self):
|
||||||
"""Handle being added to home assistant."""
|
"""Handle being added to home assistant."""
|
||||||
await MqttAvailability.async_added_to_hass(self)
|
await MqttAvailability.async_added_to_hass(self)
|
||||||
await MqttDiscoveryUpdate.async_added_to_hass(self)
|
await MqttDiscoveryUpdate.async_added_to_hass(self)
|
||||||
|
await self._subscribe_topics()
|
||||||
|
|
||||||
|
async def discovery_update(self, discovery_payload):
|
||||||
|
"""Handle updated discovery message."""
|
||||||
|
config = PLATFORM_SCHEMA(discovery_payload)
|
||||||
|
self._setup_from_config(config)
|
||||||
|
await self.availability_discovery_update(config)
|
||||||
|
await self._subscribe_topics()
|
||||||
|
self.async_schedule_update_ha_state()
|
||||||
|
|
||||||
|
def _setup_from_config(self, config):
|
||||||
|
"""(Re)Setup the entity."""
|
||||||
|
self._name = config.get(CONF_NAME)
|
||||||
|
self._topic = {
|
||||||
|
key: config.get(key) for key in (
|
||||||
|
CONF_POWER_COMMAND_TOPIC,
|
||||||
|
CONF_MODE_COMMAND_TOPIC,
|
||||||
|
CONF_TEMPERATURE_COMMAND_TOPIC,
|
||||||
|
CONF_FAN_MODE_COMMAND_TOPIC,
|
||||||
|
CONF_SWING_MODE_COMMAND_TOPIC,
|
||||||
|
CONF_AWAY_MODE_COMMAND_TOPIC,
|
||||||
|
CONF_HOLD_COMMAND_TOPIC,
|
||||||
|
CONF_AUX_COMMAND_TOPIC,
|
||||||
|
CONF_POWER_STATE_TOPIC,
|
||||||
|
CONF_MODE_STATE_TOPIC,
|
||||||
|
CONF_TEMPERATURE_STATE_TOPIC,
|
||||||
|
CONF_FAN_MODE_STATE_TOPIC,
|
||||||
|
CONF_SWING_MODE_STATE_TOPIC,
|
||||||
|
CONF_AWAY_MODE_STATE_TOPIC,
|
||||||
|
CONF_HOLD_STATE_TOPIC,
|
||||||
|
CONF_AUX_STATE_TOPIC,
|
||||||
|
CONF_CURRENT_TEMPERATURE_TOPIC
|
||||||
|
)
|
||||||
|
}
|
||||||
|
self._qos = config.get(CONF_QOS)
|
||||||
|
self._retain = config.get(CONF_RETAIN)
|
||||||
|
self._operation_list = config.get(CONF_MODE_LIST)
|
||||||
|
self._fan_list = config.get(CONF_FAN_MODE_LIST)
|
||||||
|
self._swing_list = config.get(CONF_SWING_MODE_LIST)
|
||||||
|
|
||||||
|
# set to None in non-optimistic mode
|
||||||
|
self._target_temperature = self._current_fan_mode = \
|
||||||
|
self._current_operation = self._current_swing_mode = None
|
||||||
|
if self._topic[CONF_TEMPERATURE_STATE_TOPIC] is None:
|
||||||
|
self._target_temperature = config.get(CONF_INITIAL)
|
||||||
|
if self._topic[CONF_FAN_MODE_STATE_TOPIC] is None:
|
||||||
|
self._current_fan_mode = SPEED_LOW
|
||||||
|
if self._topic[CONF_SWING_MODE_STATE_TOPIC] is None:
|
||||||
|
self._current_swing_mode = STATE_OFF
|
||||||
|
if self._topic[CONF_MODE_STATE_TOPIC] is None:
|
||||||
|
self._current_operation = STATE_OFF
|
||||||
|
self._away = False
|
||||||
|
self._hold = None
|
||||||
|
self._aux = False
|
||||||
|
self._send_if_off = config.get(CONF_SEND_IF_OFF)
|
||||||
|
self._payload_on = config.get(CONF_PAYLOAD_ON)
|
||||||
|
self._payload_off = config.get(CONF_PAYLOAD_OFF)
|
||||||
|
self._min_temp = config.get(CONF_MIN_TEMP)
|
||||||
|
self._max_temp = config.get(CONF_MAX_TEMP)
|
||||||
|
self._target_temperature_step = config.get(CONF_TEMP_STEP)
|
||||||
|
|
||||||
|
config.get(CONF_AVAILABILITY_TOPIC)
|
||||||
|
config.get(CONF_PAYLOAD_AVAILABLE)
|
||||||
|
config.get(CONF_PAYLOAD_NOT_AVAILABLE)
|
||||||
|
|
||||||
|
value_templates = {}
|
||||||
|
if CONF_VALUE_TEMPLATE in config:
|
||||||
|
value_template = config.get(CONF_VALUE_TEMPLATE)
|
||||||
|
value_template.hass = self.hass
|
||||||
|
value_templates = {key: value_template for key in TEMPLATE_KEYS}
|
||||||
|
for key in TEMPLATE_KEYS & config.keys():
|
||||||
|
value_templates[key] = config.get(key)
|
||||||
|
value_templates[key].hass = self.hass
|
||||||
|
self._value_templates = value_templates
|
||||||
|
|
||||||
|
async def _subscribe_topics(self):
|
||||||
|
"""(Re)Subscribe to topics."""
|
||||||
|
topics = {}
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def handle_current_temp_received(topic, payload, qos):
|
def handle_current_temp_received(topic, payload, qos):
|
||||||
@ -287,9 +317,10 @@ class MqttClimate(MqttAvailability, MqttDiscoveryUpdate, ClimateDevice):
|
|||||||
_LOGGER.error("Could not parse temperature from %s", payload)
|
_LOGGER.error("Could not parse temperature from %s", payload)
|
||||||
|
|
||||||
if self._topic[CONF_CURRENT_TEMPERATURE_TOPIC] is not None:
|
if self._topic[CONF_CURRENT_TEMPERATURE_TOPIC] is not None:
|
||||||
await mqtt.async_subscribe(
|
topics[CONF_CURRENT_TEMPERATURE_TOPIC] = {
|
||||||
self.hass, self._topic[CONF_CURRENT_TEMPERATURE_TOPIC],
|
'topic': self._topic[CONF_CURRENT_TEMPERATURE_TOPIC],
|
||||||
handle_current_temp_received, self._qos)
|
'msg_callback': handle_current_temp_received,
|
||||||
|
'qos': self._qos}
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def handle_mode_received(topic, payload, qos):
|
def handle_mode_received(topic, payload, qos):
|
||||||
@ -305,9 +336,10 @@ class MqttClimate(MqttAvailability, MqttDiscoveryUpdate, ClimateDevice):
|
|||||||
self.async_schedule_update_ha_state()
|
self.async_schedule_update_ha_state()
|
||||||
|
|
||||||
if self._topic[CONF_MODE_STATE_TOPIC] is not None:
|
if self._topic[CONF_MODE_STATE_TOPIC] is not None:
|
||||||
await mqtt.async_subscribe(
|
topics[CONF_MODE_STATE_TOPIC] = {
|
||||||
self.hass, self._topic[CONF_MODE_STATE_TOPIC],
|
'topic': self._topic[CONF_MODE_STATE_TOPIC],
|
||||||
handle_mode_received, self._qos)
|
'msg_callback': handle_mode_received,
|
||||||
|
'qos': self._qos}
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def handle_temperature_received(topic, payload, qos):
|
def handle_temperature_received(topic, payload, qos):
|
||||||
@ -324,9 +356,10 @@ class MqttClimate(MqttAvailability, MqttDiscoveryUpdate, ClimateDevice):
|
|||||||
_LOGGER.error("Could not parse temperature from %s", payload)
|
_LOGGER.error("Could not parse temperature from %s", payload)
|
||||||
|
|
||||||
if self._topic[CONF_TEMPERATURE_STATE_TOPIC] is not None:
|
if self._topic[CONF_TEMPERATURE_STATE_TOPIC] is not None:
|
||||||
await mqtt.async_subscribe(
|
topics[CONF_TEMPERATURE_STATE_TOPIC] = {
|
||||||
self.hass, self._topic[CONF_TEMPERATURE_STATE_TOPIC],
|
'topic': self._topic[CONF_TEMPERATURE_STATE_TOPIC],
|
||||||
handle_temperature_received, self._qos)
|
'msg_callback': handle_temperature_received,
|
||||||
|
'qos': self._qos}
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def handle_fan_mode_received(topic, payload, qos):
|
def handle_fan_mode_received(topic, payload, qos):
|
||||||
@ -343,9 +376,10 @@ class MqttClimate(MqttAvailability, MqttDiscoveryUpdate, ClimateDevice):
|
|||||||
self.async_schedule_update_ha_state()
|
self.async_schedule_update_ha_state()
|
||||||
|
|
||||||
if self._topic[CONF_FAN_MODE_STATE_TOPIC] is not None:
|
if self._topic[CONF_FAN_MODE_STATE_TOPIC] is not None:
|
||||||
await mqtt.async_subscribe(
|
topics[CONF_FAN_MODE_STATE_TOPIC] = {
|
||||||
self.hass, self._topic[CONF_FAN_MODE_STATE_TOPIC],
|
'topic': self._topic[CONF_FAN_MODE_STATE_TOPIC],
|
||||||
handle_fan_mode_received, self._qos)
|
'msg_callback': handle_fan_mode_received,
|
||||||
|
'qos': self._qos}
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def handle_swing_mode_received(topic, payload, qos):
|
def handle_swing_mode_received(topic, payload, qos):
|
||||||
@ -362,9 +396,10 @@ class MqttClimate(MqttAvailability, MqttDiscoveryUpdate, ClimateDevice):
|
|||||||
self.async_schedule_update_ha_state()
|
self.async_schedule_update_ha_state()
|
||||||
|
|
||||||
if self._topic[CONF_SWING_MODE_STATE_TOPIC] is not None:
|
if self._topic[CONF_SWING_MODE_STATE_TOPIC] is not None:
|
||||||
await mqtt.async_subscribe(
|
topics[CONF_SWING_MODE_STATE_TOPIC] = {
|
||||||
self.hass, self._topic[CONF_SWING_MODE_STATE_TOPIC],
|
'topic': self._topic[CONF_SWING_MODE_STATE_TOPIC],
|
||||||
handle_swing_mode_received, self._qos)
|
'msg_callback': handle_swing_mode_received,
|
||||||
|
'qos': self._qos}
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def handle_away_mode_received(topic, payload, qos):
|
def handle_away_mode_received(topic, payload, qos):
|
||||||
@ -388,9 +423,10 @@ class MqttClimate(MqttAvailability, MqttDiscoveryUpdate, ClimateDevice):
|
|||||||
self.async_schedule_update_ha_state()
|
self.async_schedule_update_ha_state()
|
||||||
|
|
||||||
if self._topic[CONF_AWAY_MODE_STATE_TOPIC] is not None:
|
if self._topic[CONF_AWAY_MODE_STATE_TOPIC] is not None:
|
||||||
await mqtt.async_subscribe(
|
topics[CONF_AWAY_MODE_STATE_TOPIC] = {
|
||||||
self.hass, self._topic[CONF_AWAY_MODE_STATE_TOPIC],
|
'topic': self._topic[CONF_AWAY_MODE_STATE_TOPIC],
|
||||||
handle_away_mode_received, self._qos)
|
'msg_callback': handle_away_mode_received,
|
||||||
|
'qos': self._qos}
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def handle_aux_mode_received(topic, payload, qos):
|
def handle_aux_mode_received(topic, payload, qos):
|
||||||
@ -413,9 +449,10 @@ class MqttClimate(MqttAvailability, MqttDiscoveryUpdate, ClimateDevice):
|
|||||||
self.async_schedule_update_ha_state()
|
self.async_schedule_update_ha_state()
|
||||||
|
|
||||||
if self._topic[CONF_AUX_STATE_TOPIC] is not None:
|
if self._topic[CONF_AUX_STATE_TOPIC] is not None:
|
||||||
await mqtt.async_subscribe(
|
topics[CONF_AUX_STATE_TOPIC] = {
|
||||||
self.hass, self._topic[CONF_AUX_STATE_TOPIC],
|
'topic': self._topic[CONF_AUX_STATE_TOPIC],
|
||||||
handle_aux_mode_received, self._qos)
|
'msg_callback': handle_aux_mode_received,
|
||||||
|
'qos': self._qos}
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def handle_hold_mode_received(topic, payload, qos):
|
def handle_hold_mode_received(topic, payload, qos):
|
||||||
@ -428,9 +465,19 @@ class MqttClimate(MqttAvailability, MqttDiscoveryUpdate, ClimateDevice):
|
|||||||
self.async_schedule_update_ha_state()
|
self.async_schedule_update_ha_state()
|
||||||
|
|
||||||
if self._topic[CONF_HOLD_STATE_TOPIC] is not None:
|
if self._topic[CONF_HOLD_STATE_TOPIC] is not None:
|
||||||
await mqtt.async_subscribe(
|
topics[CONF_HOLD_STATE_TOPIC] = {
|
||||||
self.hass, self._topic[CONF_HOLD_STATE_TOPIC],
|
'topic': self._topic[CONF_HOLD_STATE_TOPIC],
|
||||||
handle_hold_mode_received, self._qos)
|
'msg_callback': handle_hold_mode_received,
|
||||||
|
'qos': self._qos}
|
||||||
|
|
||||||
|
self._sub_state = await subscription.async_subscribe_topics(
|
||||||
|
self.hass, self._sub_state,
|
||||||
|
topics)
|
||||||
|
|
||||||
|
async def async_will_remove_from_hass(self):
|
||||||
|
"""Unsubscribe when removed."""
|
||||||
|
await subscription.async_unsubscribe_topics(self.hass, self._sub_state)
|
||||||
|
await MqttAvailability.async_will_remove_from_hass(self)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def should_poll(self):
|
def should_poll(self):
|
||||||
|
@ -684,3 +684,34 @@ async def test_discovery_removal_climate(hass, mqtt_mock, caplog):
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
state = hass.states.get('climate.beer')
|
state = hass.states.get('climate.beer')
|
||||||
assert state is None
|
assert state is None
|
||||||
|
|
||||||
|
|
||||||
|
async def test_discovery_update_climate(hass, mqtt_mock, caplog):
|
||||||
|
"""Test removal of discovered climate."""
|
||||||
|
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||||
|
await async_start(hass, 'homeassistant', {}, entry)
|
||||||
|
data1 = (
|
||||||
|
'{ "name": "Beer" }'
|
||||||
|
)
|
||||||
|
data2 = (
|
||||||
|
'{ "name": "Milk" }'
|
||||||
|
)
|
||||||
|
async_fire_mqtt_message(hass, 'homeassistant/climate/bla/config',
|
||||||
|
data1)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get('climate.beer')
|
||||||
|
assert state is not None
|
||||||
|
assert state.name == 'Beer'
|
||||||
|
|
||||||
|
async_fire_mqtt_message(hass, 'homeassistant/climate/bla/config',
|
||||||
|
data2)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get('climate.beer')
|
||||||
|
assert state is not None
|
||||||
|
assert state.name == 'Milk'
|
||||||
|
|
||||||
|
state = hass.states.get('climate.milk')
|
||||||
|
assert state is None
|
||||||
|
Loading…
x
Reference in New Issue
Block a user