Fix discovery update of MQTT state templates (#39901)

pull/39926/head
Erik Montnemery 2020-09-10 20:52:23 +02:00 committed by GitHub
parent fd8a4182d9
commit 4d6e694d14
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 853 additions and 128 deletions

View File

@ -1305,7 +1305,7 @@ class MqttDiscoveryUpdate(Entity):
debug_info.add_entity_discovery_data(
self.hass, self._discovery_data, self.entity_id
)
# Set in case the entity has been removed and is re-added
# Set in case the entity has been removed and is re-added, for example when changing entity_id
set_discovery_hash(self.hass, discovery_hash)
self._remove_signal = async_dispatcher_connect(
self.hass,

View File

@ -104,7 +104,7 @@ async def async_setup_platform(
):
"""Set up MQTT alarm control panel through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(config, async_add_entities)
await _async_setup_entity(hass, config, async_add_entities)
async def async_setup_entry(hass, config_entry, async_add_entities):
@ -116,7 +116,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
try:
config = PLATFORM_SCHEMA(discovery_payload)
await _async_setup_entity(
config, async_add_entities, config_entry, discovery_data
hass, config, async_add_entities, config_entry, discovery_data
)
except Exception:
clear_discovery_hash(hass, discovery_data[ATTR_DISCOVERY_HASH])
@ -128,10 +128,10 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
async def _async_setup_entity(
config, async_add_entities, config_entry=None, discovery_data=None
hass, config, async_add_entities, config_entry=None, discovery_data=None
):
"""Set up the MQTT Alarm Control Panel platform."""
async_add_entities([MqttAlarm(config, config_entry, discovery_data)])
async_add_entities([MqttAlarm(hass, config, config_entry, discovery_data)])
class MqttAlarm(
@ -143,13 +143,16 @@ class MqttAlarm(
):
"""Representation of a MQTT alarm status."""
def __init__(self, config, config_entry, discovery_data):
def __init__(self, hass, config, config_entry, discovery_data):
"""Init the MQTT Alarm Control Panel."""
self.hass = hass
self._state = None
self._config = config
self._unique_id = config.get(CONF_UNIQUE_ID)
self._sub_state = None
# Load config
self._setup_from_config(config)
device_config = config.get(CONF_DEVICE)
MqttAttributes.__init__(self, config)
@ -165,26 +168,30 @@ class MqttAlarm(
async def discovery_update(self, discovery_payload):
"""Handle updated discovery message."""
config = PLATFORM_SCHEMA(discovery_payload)
self._config = config
self._setup_from_config(config)
await self.attributes_discovery_update(config)
await self.availability_discovery_update(config)
await self.device_info_discovery_update(config)
await self._subscribe_topics()
self.async_write_ha_state()
async def _subscribe_topics(self):
"""(Re)Subscribe to topics."""
def _setup_from_config(self, config):
self._config = config
value_template = self._config.get(CONF_VALUE_TEMPLATE)
if value_template is not None:
value_template.hass = self.hass
command_template = self._config[CONF_COMMAND_TEMPLATE]
command_template.hass = self.hass
async def _subscribe_topics(self):
"""(Re)Subscribe to topics."""
@callback
@log_messages(self.hass, self.entity_id)
def message_received(msg):
"""Run when new MQTT message has been received."""
payload = msg.payload
value_template = self._config.get(CONF_VALUE_TEMPLATE)
if value_template is not None:
payload = value_template.async_render_with_possible_json_value(
msg.payload, self._state

View File

@ -76,7 +76,7 @@ async def async_setup_platform(
):
"""Set up MQTT binary sensor through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(config, async_add_entities)
await _async_setup_entity(hass, config, async_add_entities)
async def async_setup_entry(hass, config_entry, async_add_entities):
@ -88,7 +88,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
try:
config = PLATFORM_SCHEMA(discovery_payload)
await _async_setup_entity(
config, async_add_entities, config_entry, discovery_data
hass, config, async_add_entities, config_entry, discovery_data
)
except Exception:
clear_discovery_hash(hass, discovery_data[ATTR_DISCOVERY_HASH])
@ -100,10 +100,10 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
async def _async_setup_entity(
config, async_add_entities, config_entry=None, discovery_data=None
hass, config, async_add_entities, config_entry=None, discovery_data=None
):
"""Set up the MQTT binary sensor."""
async_add_entities([MqttBinarySensor(config, config_entry, discovery_data)])
async_add_entities([MqttBinarySensor(hass, config, config_entry, discovery_data)])
class MqttBinarySensor(
@ -115,9 +115,9 @@ class MqttBinarySensor(
):
"""Representation a binary sensor that is updated by MQTT."""
def __init__(self, config, config_entry, discovery_data):
def __init__(self, hass, config, config_entry, discovery_data):
"""Initialize the MQTT binary sensor."""
self._config = config
self.hass = hass
self._unique_id = config.get(CONF_UNIQUE_ID)
self._state = None
self._sub_state = None
@ -128,6 +128,10 @@ class MqttBinarySensor(
self._expired = True
else:
self._expired = None
# Load config
self._setup_from_config(config)
device_config = config.get(CONF_DEVICE)
MqttAttributes.__init__(self, config)
@ -143,19 +147,22 @@ class MqttBinarySensor(
async def discovery_update(self, discovery_payload):
"""Handle updated discovery message."""
config = PLATFORM_SCHEMA(discovery_payload)
self._config = config
self._setup_from_config(config)
await self.attributes_discovery_update(config)
await self.availability_discovery_update(config)
await self.device_info_discovery_update(config)
await self._subscribe_topics()
self.async_write_ha_state()
async def _subscribe_topics(self):
"""(Re)Subscribe to topics."""
def _setup_from_config(self, config):
self._config = config
value_template = self._config.get(CONF_VALUE_TEMPLATE)
if value_template is not None:
value_template.hass = self.hass
async def _subscribe_topics(self):
"""(Re)Subscribe to topics."""
@callback
def off_delay_listener(now):
"""Switch device off after a delay."""

View File

@ -174,7 +174,7 @@ async def async_setup_platform(
):
"""Set up MQTT cover through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(config, async_add_entities)
await _async_setup_entity(hass, config, async_add_entities)
async def async_setup_entry(hass, config_entry, async_add_entities):
@ -186,7 +186,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
try:
config = PLATFORM_SCHEMA(discovery_payload)
await _async_setup_entity(
config, async_add_entities, config_entry, discovery_data
hass, config, async_add_entities, config_entry, discovery_data
)
except Exception:
clear_discovery_hash(hass, discovery_data[ATTR_DISCOVERY_HASH])
@ -198,10 +198,10 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
async def _async_setup_entity(
config, async_add_entities, config_entry=None, discovery_data=None
hass, config, async_add_entities, config_entry=None, discovery_data=None
):
"""Set up the MQTT Cover."""
async_add_entities([MqttCover(config, config_entry, discovery_data)])
async_add_entities([MqttCover(hass, config, config_entry, discovery_data)])
class MqttCover(
@ -213,8 +213,9 @@ class MqttCover(
):
"""Representation of a cover that can be controlled using MQTT."""
def __init__(self, config, config_entry, discovery_data):
def __init__(self, hass, config, config_entry, discovery_data):
"""Initialize the cover."""
self.hass = hass
self._unique_id = config.get(CONF_UNIQUE_ID)
self._position = None
self._state = None
@ -257,8 +258,6 @@ class MqttCover(
)
self._tilt_optimistic = config[CONF_TILT_STATE_OPTIMISTIC]
async def _subscribe_topics(self):
"""(Re)Subscribe to topics."""
template = self._config.get(CONF_VALUE_TEMPLATE)
if template is not None:
template.hass = self.hass
@ -269,6 +268,8 @@ class MqttCover(
if tilt_status_template is not None:
tilt_status_template.hass = self.hass
async def _subscribe_topics(self):
"""(Re)Subscribe to topics."""
topics = {}
@callback
@ -276,6 +277,7 @@ class MqttCover(
def tilt_message_received(msg):
"""Handle tilt updates."""
payload = msg.payload
tilt_status_template = self._config.get(CONF_TILT_STATUS_TEMPLATE)
if tilt_status_template is not None:
payload = tilt_status_template.async_render_with_possible_json_value(
payload
@ -296,6 +298,7 @@ class MqttCover(
def state_message_received(msg):
"""Handle new MQTT state messages."""
payload = msg.payload
template = self._config.get(CONF_VALUE_TEMPLATE)
if template is not None:
payload = template.async_render_with_possible_json_value(payload)
@ -321,6 +324,7 @@ class MqttCover(
def position_message_received(msg):
"""Handle new MQTT state messages."""
payload = msg.payload
template = self._config.get(CONF_VALUE_TEMPLATE)
if template is not None:
payload = template.async_render_with_possible_json_value(payload)

View File

@ -115,7 +115,7 @@ async def async_setup_platform(
):
"""Set up MQTT fan through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(config, async_add_entities)
await _async_setup_entity(hass, config, async_add_entities)
async def async_setup_entry(hass, config_entry, async_add_entities):
@ -127,7 +127,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
try:
config = PLATFORM_SCHEMA(discovery_payload)
await _async_setup_entity(
config, async_add_entities, config_entry, discovery_data
hass, config, async_add_entities, config_entry, discovery_data
)
except Exception:
clear_discovery_hash(hass, discovery_data[ATTR_DISCOVERY_HASH])
@ -139,10 +139,10 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
async def _async_setup_entity(
config, async_add_entities, config_entry=None, discovery_data=None
hass, config, async_add_entities, config_entry=None, discovery_data=None
):
"""Set up the MQTT fan."""
async_add_entities([MqttFan(config, config_entry, discovery_data)])
async_add_entities([MqttFan(hass, config, config_entry, discovery_data)])
class MqttFan(
@ -154,8 +154,9 @@ class MqttFan(
):
"""A MQTT fan component."""
def __init__(self, config, config_entry, discovery_data):
def __init__(self, hass, config, config_entry, discovery_data):
"""Initialize the MQTT fan."""
self.hass = hass
self._unique_id = config.get(CONF_UNIQUE_ID)
self._state = False
self._speed = None
@ -242,22 +243,22 @@ class MqttFan(
self._topic[CONF_SPEED_COMMAND_TOPIC] is not None and SUPPORT_SET_SPEED
)
for key, tpl in list(self._templates.items()):
if tpl is None:
self._templates[key] = lambda value: value
else:
tpl.hass = self.hass
self._templates[key] = tpl.async_render_with_possible_json_value
async def _subscribe_topics(self):
"""(Re)Subscribe to topics."""
topics = {}
templates = {}
for key, tpl in list(self._templates.items()):
if tpl is None:
templates[key] = lambda value: value
else:
tpl.hass = self.hass
templates[key] = tpl.async_render_with_possible_json_value
@callback
@log_messages(self.hass, self.entity_id)
def state_received(msg):
"""Handle new received MQTT message."""
payload = templates[CONF_STATE](msg.payload)
payload = self._templates[CONF_STATE](msg.payload)
if payload == self._payload["STATE_ON"]:
self._state = True
elif payload == self._payload["STATE_OFF"]:
@ -275,7 +276,7 @@ class MqttFan(
@log_messages(self.hass, self.entity_id)
def speed_received(msg):
"""Handle new received MQTT message for the speed."""
payload = templates[ATTR_SPEED](msg.payload)
payload = self._templates[ATTR_SPEED](msg.payload)
if payload == self._payload["SPEED_LOW"]:
self._speed = SPEED_LOW
elif payload == self._payload["SPEED_MEDIUM"]:
@ -298,7 +299,7 @@ class MqttFan(
@log_messages(self.hass, self.entity_id)
def oscillation_received(msg):
"""Handle new received MQTT message for the oscillation."""
payload = templates[OSCILLATION](msg.payload)
payload = self._templates[OSCILLATION](msg.payload)
if payload == self._payload["OSCILLATE_ON_PAYLOAD"]:
self._oscillation = True
elif payload == self._payload["OSCILLATE_OFF_PAYLOAD"]:

View File

@ -254,7 +254,7 @@ class MqttLight(
value_templates = {}
for key in VALUE_TEMPLATE_KEYS:
value_templates[key] = lambda value: value
value_templates[key] = lambda value, _: value
for key in VALUE_TEMPLATE_KEYS & config.keys():
tpl = config[key]
value_templates[key] = tpl.async_render_with_possible_json_value
@ -304,7 +304,9 @@ class MqttLight(
@log_messages(self.hass, self.entity_id)
def state_received(msg):
"""Handle new MQTT messages."""
payload = self._value_templates[CONF_STATE_VALUE_TEMPLATE](msg.payload)
payload = self._value_templates[CONF_STATE_VALUE_TEMPLATE](
msg.payload, None
)
if not payload:
_LOGGER.debug("Ignoring empty state message from '%s'", msg.topic)
return
@ -328,7 +330,9 @@ class MqttLight(
@log_messages(self.hass, self.entity_id)
def brightness_received(msg):
"""Handle new MQTT messages for the brightness."""
payload = self._value_templates[CONF_BRIGHTNESS_VALUE_TEMPLATE](msg.payload)
payload = self._value_templates[CONF_BRIGHTNESS_VALUE_TEMPLATE](
msg.payload, None
)
if not payload:
_LOGGER.debug("Ignoring empty brightness message from '%s'", msg.topic)
return
@ -360,7 +364,7 @@ class MqttLight(
@log_messages(self.hass, self.entity_id)
def rgb_received(msg):
"""Handle new MQTT messages for RGB."""
payload = self._value_templates[CONF_RGB_VALUE_TEMPLATE](msg.payload)
payload = self._value_templates[CONF_RGB_VALUE_TEMPLATE](msg.payload, None)
if not payload:
_LOGGER.debug("Ignoring empty rgb message from '%s'", msg.topic)
return
@ -392,7 +396,9 @@ class MqttLight(
@log_messages(self.hass, self.entity_id)
def color_temp_received(msg):
"""Handle new MQTT messages for color temperature."""
payload = self._value_templates[CONF_COLOR_TEMP_VALUE_TEMPLATE](msg.payload)
payload = self._value_templates[CONF_COLOR_TEMP_VALUE_TEMPLATE](
msg.payload, None
)
if not payload:
_LOGGER.debug("Ignoring empty color temp message from '%s'", msg.topic)
return
@ -422,7 +428,9 @@ class MqttLight(
@log_messages(self.hass, self.entity_id)
def effect_received(msg):
"""Handle new MQTT messages for effect."""
payload = self._value_templates[CONF_EFFECT_VALUE_TEMPLATE](msg.payload)
payload = self._value_templates[CONF_EFFECT_VALUE_TEMPLATE](
msg.payload, None
)
if not payload:
_LOGGER.debug("Ignoring empty effect message from '%s'", msg.topic)
return
@ -452,7 +460,7 @@ class MqttLight(
@log_messages(self.hass, self.entity_id)
def hs_received(msg):
"""Handle new MQTT messages for hs color."""
payload = self._value_templates[CONF_HS_VALUE_TEMPLATE](msg.payload)
payload = self._value_templates[CONF_HS_VALUE_TEMPLATE](msg.payload, None)
if not payload:
_LOGGER.debug("Ignoring empty hs message from '%s'", msg.topic)
return
@ -484,7 +492,9 @@ class MqttLight(
@log_messages(self.hass, self.entity_id)
def white_value_received(msg):
"""Handle new MQTT messages for white value."""
payload = self._value_templates[CONF_WHITE_VALUE_TEMPLATE](msg.payload)
payload = self._value_templates[CONF_WHITE_VALUE_TEMPLATE](
msg.payload, None
)
if not payload:
_LOGGER.debug("Ignoring empty white value message from '%s'", msg.topic)
return
@ -516,7 +526,7 @@ class MqttLight(
@log_messages(self.hass, self.entity_id)
def xy_received(msg):
"""Handle new MQTT messages for xy color."""
payload = self._value_templates[CONF_XY_VALUE_TEMPLATE](msg.payload)
payload = self._value_templates[CONF_XY_VALUE_TEMPLATE](msg.payload, None)
if not payload:
_LOGGER.debug("Ignoring empty xy-color message from '%s'", msg.topic)
return

View File

@ -77,7 +77,7 @@ async def async_setup_platform(
):
"""Set up MQTT lock panel through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(config, async_add_entities)
await _async_setup_entity(hass, config, async_add_entities)
async def async_setup_entry(hass, config_entry, async_add_entities):
@ -89,7 +89,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
try:
config = PLATFORM_SCHEMA(discovery_payload)
await _async_setup_entity(
config, async_add_entities, config_entry, discovery_data
hass, config, async_add_entities, config_entry, discovery_data
)
except Exception:
clear_discovery_hash(hass, discovery_data[ATTR_DISCOVERY_HASH])
@ -101,10 +101,10 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
async def _async_setup_entity(
config, async_add_entities, config_entry=None, discovery_data=None
hass, config, async_add_entities, config_entry=None, discovery_data=None
):
"""Set up the MQTT Lock platform."""
async_add_entities([MqttLock(config, config_entry, discovery_data)])
async_add_entities([MqttLock(hass, config, config_entry, discovery_data)])
class MqttLock(
@ -116,8 +116,9 @@ class MqttLock(
):
"""Representation of a lock that can be toggled using MQTT."""
def __init__(self, config, config_entry, discovery_data):
def __init__(self, hass, config, config_entry, discovery_data):
"""Initialize the lock."""
self.hass = hass
self._unique_id = config.get(CONF_UNIQUE_ID)
self._state = False
self._sub_state = None
@ -154,17 +155,19 @@ class MqttLock(
self._optimistic = config[CONF_OPTIMISTIC]
async def _subscribe_topics(self):
"""(Re)Subscribe to topics."""
value_template = self._config.get(CONF_VALUE_TEMPLATE)
if value_template is not None:
value_template.hass = self.hass
async def _subscribe_topics(self):
"""(Re)Subscribe to topics."""
@callback
@log_messages(self.hass, self.entity_id)
def message_received(msg):
"""Handle new MQTT messages."""
payload = msg.payload
value_template = self._config.get(CONF_VALUE_TEMPLATE)
if value_template is not None:
payload = value_template.async_render_with_possible_json_value(payload)
if payload == self._config[CONF_STATE_LOCKED]:

View File

@ -70,7 +70,7 @@ async def async_setup_platform(
):
"""Set up MQTT sensors through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(config, async_add_entities)
await _async_setup_entity(hass, config, async_add_entities)
async def async_setup_entry(hass, config_entry, async_add_entities):
@ -82,7 +82,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
try:
config = PLATFORM_SCHEMA(discovery_payload)
await _async_setup_entity(
config, async_add_entities, config_entry, discovery_data
hass, config, async_add_entities, config_entry, discovery_data
)
except Exception:
clear_discovery_hash(hass, discovery_data[ATTR_DISCOVERY_HASH])
@ -94,10 +94,10 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
async def _async_setup_entity(
config: ConfigType, async_add_entities, config_entry=None, discovery_data=None
hass, config: ConfigType, async_add_entities, config_entry=None, discovery_data=None
):
"""Set up MQTT sensor."""
async_add_entities([MqttSensor(config, config_entry, discovery_data)])
async_add_entities([MqttSensor(hass, config, config_entry, discovery_data)])
class MqttSensor(
@ -105,9 +105,9 @@ class MqttSensor(
):
"""Representation of a sensor that can be updated using MQTT."""
def __init__(self, config, config_entry, discovery_data):
def __init__(self, hass, config, config_entry, discovery_data):
"""Initialize the sensor."""
self._config = config
self.hass = hass
self._unique_id = config.get(CONF_UNIQUE_ID)
self._state = None
self._sub_state = None
@ -118,6 +118,10 @@ class MqttSensor(
self._expired = True
else:
self._expired = None
# Load config
self._setup_from_config(config)
device_config = config.get(CONF_DEVICE)
MqttAttributes.__init__(self, config)
@ -133,19 +137,23 @@ class MqttSensor(
async def discovery_update(self, discovery_payload):
"""Handle updated discovery message."""
config = PLATFORM_SCHEMA(discovery_payload)
self._config = config
self._setup_from_config(config)
await self.attributes_discovery_update(config)
await self.availability_discovery_update(config)
await self.device_info_discovery_update(config)
await self._subscribe_topics()
self.async_write_ha_state()
async def _subscribe_topics(self):
"""(Re)Subscribe to topics."""
def _setup_from_config(self, config):
"""(Re)Setup the entity."""
self._config = config
template = self._config.get(CONF_VALUE_TEMPLATE)
if template is not None:
template.hass = self.hass
async def _subscribe_topics(self):
"""(Re)Subscribe to topics."""
@callback
@log_messages(self.hass, self.entity_id)
def message_received(msg):
@ -169,6 +177,7 @@ class MqttSensor(
self.hass, self._value_is_expired, expiration_at
)
template = self._config.get(CONF_VALUE_TEMPLATE)
if template is not None:
payload = template.async_render_with_possible_json_value(
payload, self._state

View File

@ -73,7 +73,7 @@ async def async_setup_platform(
):
"""Set up MQTT switch through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(config, async_add_entities, discovery_info)
await _async_setup_entity(hass, config, async_add_entities, discovery_info)
async def async_setup_entry(hass, config_entry, async_add_entities):
@ -85,7 +85,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
try:
config = PLATFORM_SCHEMA(discovery_payload)
await _async_setup_entity(
config, async_add_entities, config_entry, discovery_data
hass, config, async_add_entities, config_entry, discovery_data
)
except Exception:
clear_discovery_hash(hass, discovery_data[ATTR_DISCOVERY_HASH])
@ -97,10 +97,10 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
async def _async_setup_entity(
config, async_add_entities, config_entry=None, discovery_data=None
hass, config, async_add_entities, config_entry=None, discovery_data=None
):
"""Set up the MQTT switch."""
async_add_entities([MqttSwitch(config, config_entry, discovery_data)])
async_add_entities([MqttSwitch(hass, config, config_entry, discovery_data)])
class MqttSwitch(
@ -113,8 +113,9 @@ class MqttSwitch(
):
"""Representation of a switch that can be toggled using MQTT."""
def __init__(self, config, config_entry, discovery_data):
def __init__(self, hass, config, config_entry, discovery_data):
"""Initialize the MQTT switch."""
self.hass = hass
self._state = False
self._sub_state = None
@ -160,17 +161,19 @@ class MqttSwitch(
self._optimistic = config[CONF_OPTIMISTIC]
async def _subscribe_topics(self):
"""(Re)Subscribe to topics."""
template = self._config.get(CONF_VALUE_TEMPLATE)
if template is not None:
template.hass = self.hass
async def _subscribe_topics(self):
"""(Re)Subscribe to topics."""
@callback
@log_messages(self.hass, self.entity_id)
def state_message_received(msg):
"""Handle new MQTT state messages."""
payload = msg.payload
template = self._config.get(CONF_VALUE_TEMPLATE)
if template is not None:
payload = template.async_render_with_possible_json_value(payload)
if payload == self._state_on:

View File

@ -603,17 +603,71 @@ async def test_discovery_removal_alarm(hass, mqtt_mock, caplog):
)
async def test_discovery_update_alarm(hass, mqtt_mock, caplog):
async def test_discovery_update_alarm_topic_and_template(hass, mqtt_mock, caplog):
"""Test update of discovered alarm_control_panel."""
config1 = copy.deepcopy(DEFAULT_CONFIG[alarm_control_panel.DOMAIN])
config2 = copy.deepcopy(DEFAULT_CONFIG[alarm_control_panel.DOMAIN])
config1["name"] = "Beer"
config2["name"] = "Milk"
config1["state_topic"] = "alarm/state1"
config2["state_topic"] = "alarm/state2"
config1["value_template"] = "{{ value_json.state1.state }}"
config2["value_template"] = "{{ value_json.state2.state }}"
state_data1 = [
([("alarm/state1", '{"state1":{"state":"armed_away"}}')], "armed_away", None),
]
state_data2 = [
([("alarm/state1", '{"state1":{"state":"triggered"}}')], "armed_away", None),
([("alarm/state1", '{"state2":{"state":"triggered"}}')], "armed_away", None),
([("alarm/state2", '{"state1":{"state":"triggered"}}')], "armed_away", None),
([("alarm/state2", '{"state2":{"state":"triggered"}}')], "triggered", None),
]
data1 = json.dumps(config1)
data2 = json.dumps(config2)
await help_test_discovery_update(
hass, mqtt_mock, caplog, alarm_control_panel.DOMAIN, data1, data2
hass,
mqtt_mock,
caplog,
alarm_control_panel.DOMAIN,
data1,
data2,
state_data1=state_data1,
state_data2=state_data2,
)
async def test_discovery_update_alarm_template(hass, mqtt_mock, caplog):
"""Test update of discovered alarm_control_panel."""
config1 = copy.deepcopy(DEFAULT_CONFIG[alarm_control_panel.DOMAIN])
config2 = copy.deepcopy(DEFAULT_CONFIG[alarm_control_panel.DOMAIN])
config1["name"] = "Beer"
config2["name"] = "Milk"
config1["state_topic"] = "alarm/state1"
config2["state_topic"] = "alarm/state1"
config1["value_template"] = "{{ value_json.state1.state }}"
config2["value_template"] = "{{ value_json.state2.state }}"
state_data1 = [
([("alarm/state1", '{"state1":{"state":"armed_away"}}')], "armed_away", None),
]
state_data2 = [
([("alarm/state1", '{"state1":{"state":"triggered"}}')], "armed_away", None),
([("alarm/state1", '{"state2":{"state":"triggered"}}')], "triggered", None),
]
data1 = json.dumps(config1)
data2 = json.dumps(config2)
await help_test_discovery_update(
hass,
mqtt_mock,
caplog,
alarm_control_panel.DOMAIN,
data1,
data2,
state_data1=state_data1,
state_data2=state_data2,
)

View File

@ -580,17 +580,75 @@ async def test_discovery_removal_binary_sensor(hass, mqtt_mock, caplog):
)
async def test_discovery_update_binary_sensor(hass, mqtt_mock, caplog):
async def test_discovery_update_binary_sensor_topic_template(hass, mqtt_mock, caplog):
"""Test update of discovered binary_sensor."""
config1 = copy.deepcopy(DEFAULT_CONFIG[binary_sensor.DOMAIN])
config2 = copy.deepcopy(DEFAULT_CONFIG[binary_sensor.DOMAIN])
config1["name"] = "Beer"
config2["name"] = "Milk"
config1["state_topic"] = "sensor/state1"
config2["state_topic"] = "sensor/state2"
config1["value_template"] = "{{ value_json.state1.state }}"
config2["value_template"] = "{{ value_json.state2.state }}"
state_data1 = [
([("sensor/state1", '{"state1":{"state":"ON"}}')], "on", None),
]
state_data2 = [
([("sensor/state2", '{"state2":{"state":"OFF"}}')], "off", None),
([("sensor/state2", '{"state2":{"state":"ON"}}')], "on", None),
([("sensor/state1", '{"state1":{"state":"OFF"}}')], "on", None),
([("sensor/state1", '{"state2":{"state":"OFF"}}')], "on", None),
([("sensor/state2", '{"state1":{"state":"OFF"}}')], "on", None),
([("sensor/state2", '{"state2":{"state":"OFF"}}')], "off", None),
]
data1 = json.dumps(config1)
data2 = json.dumps(config2)
await help_test_discovery_update(
hass, mqtt_mock, caplog, binary_sensor.DOMAIN, data1, data2
hass,
mqtt_mock,
caplog,
binary_sensor.DOMAIN,
data1,
data2,
state_data1=state_data1,
state_data2=state_data2,
)
async def test_discovery_update_binary_sensor_template(hass, mqtt_mock, caplog):
"""Test update of discovered binary_sensor."""
config1 = copy.deepcopy(DEFAULT_CONFIG[binary_sensor.DOMAIN])
config2 = copy.deepcopy(DEFAULT_CONFIG[binary_sensor.DOMAIN])
config1["name"] = "Beer"
config2["name"] = "Milk"
config1["state_topic"] = "sensor/state1"
config2["state_topic"] = "sensor/state1"
config1["value_template"] = "{{ value_json.state1.state }}"
config2["value_template"] = "{{ value_json.state2.state }}"
state_data1 = [
([("sensor/state1", '{"state1":{"state":"ON"}}')], "on", None),
]
state_data2 = [
([("sensor/state1", '{"state2":{"state":"OFF"}}')], "off", None),
([("sensor/state1", '{"state2":{"state":"ON"}}')], "on", None),
([("sensor/state1", '{"state1":{"state":"OFF"}}')], "on", None),
([("sensor/state1", '{"state2":{"state":"OFF"}}')], "off", None),
]
data1 = json.dumps(config1)
data2 = json.dumps(config2)
await help_test_discovery_update(
hass,
mqtt_mock,
caplog,
binary_sensor.DOMAIN,
data1,
data2,
state_data1=state_data1,
state_data2=state_data2,
)

View File

@ -512,10 +512,6 @@ async def help_test_discovery_update(
discovery_data2,
state_data1=None,
state_data2=None,
state1=None,
state2=None,
attributes1=None,
attributes2=None,
):
"""Test update of discovered component.
@ -527,32 +523,38 @@ async def help_test_discovery_update(
async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", discovery_data1)
await hass.async_block_till_done()
if state_data1:
for (topic, data) in state_data1:
async_fire_mqtt_message(hass, topic, data)
state = hass.states.get(f"{domain}.beer")
assert state is not None
assert state.name == "Beer"
if state1:
assert state.state == state1
if attributes1:
for (attr, value) in attributes1:
assert state.attributes.get(attr) == value
if state_data1:
for (mqtt_messages, expected_state, attributes) in state_data1:
for (topic, data) in mqtt_messages:
async_fire_mqtt_message(hass, topic, data)
state = hass.states.get(f"{domain}.beer")
if expected_state:
assert state.state == expected_state
if attributes:
for (attr, value) in attributes:
assert state.attributes.get(attr) == value
async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", discovery_data2)
await hass.async_block_till_done()
if state_data2:
for (topic, data) in state_data2:
async_fire_mqtt_message(hass, topic, data)
state = hass.states.get(f"{domain}.beer")
assert state is not None
assert state.name == "Milk"
if state2:
assert state.state == state2
if attributes2:
for (attr, value) in attributes2:
assert state.attributes.get(attr) == value
if state_data2:
for (mqtt_messages, expected_state, attributes) in state_data2:
for (topic, data) in mqtt_messages:
async_fire_mqtt_message(hass, topic, data)
state = hass.states.get(f"{domain}.beer")
if expected_state:
assert state.state == expected_state
if attributes:
for (attr, value) in attributes:
assert state.attributes.get(attr) == value
state = hass.states.get(f"{domain}.milk")
assert state is None

View File

@ -1397,6 +1397,7 @@ async def test_tilt_position_altered_range(hass, mqtt_mock):
async def test_find_percentage_in_range_defaults(hass, mqtt_mock):
"""Test find percentage in range with default range."""
mqtt_cover = MqttCover(
hass,
{
"name": "cover.test",
"state_topic": "state-topic",
@ -1440,6 +1441,7 @@ async def test_find_percentage_in_range_defaults(hass, mqtt_mock):
async def test_find_percentage_in_range_altered(hass, mqtt_mock):
"""Test find percentage in range with altered range."""
mqtt_cover = MqttCover(
hass,
{
"name": "cover.test",
"state_topic": "state-topic",
@ -1483,6 +1485,7 @@ async def test_find_percentage_in_range_altered(hass, mqtt_mock):
async def test_find_percentage_in_range_defaults_inverted(hass, mqtt_mock):
"""Test find percentage in range with default range but inverted."""
mqtt_cover = MqttCover(
hass,
{
"name": "cover.test",
"state_topic": "state-topic",
@ -1526,6 +1529,7 @@ async def test_find_percentage_in_range_defaults_inverted(hass, mqtt_mock):
async def test_find_percentage_in_range_altered_inverted(hass, mqtt_mock):
"""Test find percentage in range with altered range and inverted."""
mqtt_cover = MqttCover(
hass,
{
"name": "cover.test",
"state_topic": "state-topic",
@ -1569,6 +1573,7 @@ async def test_find_percentage_in_range_altered_inverted(hass, mqtt_mock):
async def test_find_in_range_defaults(hass, mqtt_mock):
"""Test find in range with default range."""
mqtt_cover = MqttCover(
hass,
{
"name": "cover.test",
"state_topic": "state-topic",
@ -1612,6 +1617,7 @@ async def test_find_in_range_defaults(hass, mqtt_mock):
async def test_find_in_range_altered(hass, mqtt_mock):
"""Test find in range with altered range."""
mqtt_cover = MqttCover(
hass,
{
"name": "cover.test",
"state_topic": "state-topic",
@ -1655,6 +1661,7 @@ async def test_find_in_range_altered(hass, mqtt_mock):
async def test_find_in_range_defaults_inverted(hass, mqtt_mock):
"""Test find in range with default range but inverted."""
mqtt_cover = MqttCover(
hass,
{
"name": "cover.test",
"state_topic": "state-topic",
@ -1698,6 +1705,7 @@ async def test_find_in_range_defaults_inverted(hass, mqtt_mock):
async def test_find_in_range_altered_inverted(hass, mqtt_mock):
"""Test find in range with altered range and inverted."""
mqtt_cover = MqttCover(
hass,
{
"name": "cover.test",
"state_topic": "state-topic",

View File

@ -153,6 +153,7 @@ light:
payload_off: "off"
"""
import json
from os import path
import pytest
@ -1466,20 +1467,249 @@ async def test_discovery_deprecated(hass, mqtt_mock, caplog):
assert state.name == "Beer"
async def test_discovery_update_light(hass, mqtt_mock, caplog):
async def test_discovery_update_light_topic_and_template(hass, mqtt_mock, caplog):
"""Test update of discovered light."""
data1 = (
'{ "name": "Beer",'
' "state_topic": "test_topic",'
' "command_topic": "test_topic",'
' "state_value_template": "{{value_json.power1}}" }'
data1 = json.dumps(
{
"name": "Beer",
"state_topic": "test_light_rgb/state1",
"command_topic": "test_light_rgb/set",
"brightness_command_topic": "test_light_rgb/state1",
"rgb_command_topic": "test_light_rgb/rgb/set",
"color_temp_command_topic": "test_light_rgb/state1",
"effect_command_topic": "test_light_rgb/effect/set",
"hs_command_topic": "test_light_rgb/hs/set",
"white_value_command_topic": "test_light_rgb/white_value/set",
"xy_command_topic": "test_light_rgb/xy/set",
"brightness_state_topic": "test_light_rgb/state1",
"color_temp_state_topic": "test_light_rgb/state1",
"effect_state_topic": "test_light_rgb/state1",
"hs_state_topic": "test_light_rgb/state1",
"rgb_state_topic": "test_light_rgb/state1",
"white_value_state_topic": "test_light_rgb/state1",
"xy_state_topic": "test_light_rgb/state1",
"state_value_template": "{{ value_json.state1.state }}",
"brightness_value_template": "{{ value_json.state1.brightness }}",
"color_temp_value_template": "{{ value_json.state1.ct }}",
"effect_value_template": "{{ value_json.state1.fx }}",
"hs_value_template": "{{ value_json.state1.hs }}",
"rgb_value_template": "{{ value_json.state1.rgb }}",
"white_value_template": "{{ value_json.state1.white }}",
"xy_value_template": "{{ value_json.state1.xy }}",
}
)
data2 = (
'{ "name": "Milk",'
' "state_topic": "test_topic",'
' "command_topic": "test_topic",'
' "state_value_template": "{{value_json.power2}}" }'
data2 = json.dumps(
{
"name": "Milk",
"state_topic": "test_light_rgb/state2",
"command_topic": "test_light_rgb/set",
"brightness_command_topic": "test_light_rgb/state2",
"rgb_command_topic": "test_light_rgb/rgb/set",
"color_temp_command_topic": "test_light_rgb/state2",
"effect_command_topic": "test_light_rgb/effect/set",
"hs_command_topic": "test_light_rgb/hs/set",
"white_value_command_topic": "test_light_rgb/white_value/set",
"xy_command_topic": "test_light_rgb/xy/set",
"brightness_state_topic": "test_light_rgb/state2",
"color_temp_state_topic": "test_light_rgb/state2",
"effect_state_topic": "test_light_rgb/state2",
"hs_state_topic": "test_light_rgb/state2",
"rgb_state_topic": "test_light_rgb/state2",
"white_value_state_topic": "test_light_rgb/state2",
"xy_state_topic": "test_light_rgb/state2",
"state_value_template": "{{ value_json.state2.state }}",
"brightness_value_template": "{{ value_json.state2.brightness }}",
"color_temp_value_template": "{{ value_json.state2.ct }}",
"effect_value_template": "{{ value_json.state2.fx }}",
"hs_value_template": "{{ value_json.state2.hs }}",
"rgb_value_template": "{{ value_json.state2.rgb }}",
"white_value_template": "{{ value_json.state2.white }}",
"xy_value_template": "{{ value_json.state2.xy }}",
}
)
state_data1 = [
(
[
(
"test_light_rgb/state1",
'{"state1":{"state":"ON", "brightness":100, "ct":123, "fx":"cycle"}}',
)
],
"on",
[("brightness", 100), ("color_temp", 123), ("effect", "cycle")],
),
(
[("test_light_rgb/state1", '{"state1":{"state":"OFF"}}')],
"off",
None,
),
(
[
(
"test_light_rgb/state1",
'{"state1":{"state":"ON", "hs":"1,2"}}',
)
],
"on",
[("hs_color", (1, 2))],
),
(
[
(
"test_light_rgb/state1",
'{"state1":{"rgb":"255,127,63"}}',
)
],
"on",
[("rgb_color", (255, 127, 63))],
),
(
[
(
"test_light_rgb/state1",
'{"state1":{"white":50, "xy":"0.3, 0.4"}}',
)
],
"on",
[("white_value", 50), ("xy_color", (0.3, 0.401))],
),
]
state_data2 = [
(
[
(
"test_light_rgb/state2",
'{"state2":{"state":"ON", "brightness":50, "ct":200, "fx":"loop"}}',
)
],
"on",
[("brightness", 50), ("color_temp", 200), ("effect", "loop")],
),
(
[
(
"test_light_rgb/state1",
'{"state1":{"state":"ON", "brightness":100, "ct":123, "fx":"cycle"}}',
),
(
"test_light_rgb/state1",
'{"state2":{"state":"ON", "brightness":100, "ct":123, "fx":"cycle"}}',
),
(
"test_light_rgb/state2",
'{"state1":{"state":"ON", "brightness":100, "ct":123, "fx":"cycle"}}',
),
],
"on",
[("brightness", 50), ("color_temp", 200), ("effect", "loop")],
),
(
[("test_light_rgb/state1", '{"state1":{"state":"OFF"}}')],
"on",
None,
),
(
[("test_light_rgb/state1", '{"state2":{"state":"OFF"}}')],
"on",
None,
),
(
[("test_light_rgb/state2", '{"state1":{"state":"OFF"}}')],
"on",
None,
),
(
[("test_light_rgb/state2", '{"state2":{"state":"OFF"}}')],
"off",
None,
),
(
[
(
"test_light_rgb/state2",
'{"state2":{"state":"ON", "hs":"1.2,2.2"}}',
)
],
"on",
[("hs_color", (1.2, 2.2))],
),
(
[
(
"test_light_rgb/state1",
'{"state1":{"state":"ON", "hs":"1,2"}}',
),
(
"test_light_rgb/state1",
'{"state2":{"state":"ON", "hs":"1,2"}}',
),
(
"test_light_rgb/state2",
'{"state1":{"state":"ON", "hs":"1,2"}}',
),
],
"on",
[("hs_color", (1.2, 2.2))],
),
(
[
(
"test_light_rgb/state2",
'{"state2":{"rgb":"63,127,255"}}',
)
],
"on",
[("rgb_color", (63, 127, 255))],
),
(
[
(
"test_light_rgb/state1",
'{"state1":{"rgb":"255,127,63"}}',
),
(
"test_light_rgb/state1",
'{"state2":{"rgb":"255,127,63"}}',
),
(
"test_light_rgb/state2",
'{"state1":{"rgb":"255,127,63"}}',
),
],
"on",
[("rgb_color", (63, 127, 255))],
),
(
[
(
"test_light_rgb/state2",
'{"state2":{"white":75, "xy":"0.4, 0.3"}}',
)
],
"on",
[("white_value", 75), ("xy_color", (0.4, 0.3))],
),
(
[
(
"test_light_rgb/state1",
'{"state1":{"white":50, "xy":"0.3, 0.4"}}',
),
(
"test_light_rgb/state1",
'{"state2":{"white":50, "xy":"0.3, 0.4"}}',
),
(
"test_light_rgb/state2",
'{"state1":{"white":50, "xy":"0.3, 0.4"}}',
),
],
"on",
[("white_value", 75), ("xy_color", (0.4, 0.3))],
),
]
await help_test_discovery_update(
hass,
mqtt_mock,
@ -1487,10 +1717,221 @@ async def test_discovery_update_light(hass, mqtt_mock, caplog):
light.DOMAIN,
data1,
data2,
state_data1=[("test_topic", '{"power1":"ON"}')],
state1="on",
state_data2=[("test_topic", '{"power2":"OFF"}')],
state2="off",
state_data1=state_data1,
state_data2=state_data2,
)
async def test_discovery_update_light_template(hass, mqtt_mock, caplog):
"""Test update of discovered light."""
data1 = json.dumps(
{
"name": "Beer",
"state_topic": "test_light_rgb/state1",
"command_topic": "test_light_rgb/set",
"brightness_command_topic": "test_light_rgb/state1",
"rgb_command_topic": "test_light_rgb/rgb/set",
"color_temp_command_topic": "test_light_rgb/state1",
"effect_command_topic": "test_light_rgb/effect/set",
"hs_command_topic": "test_light_rgb/hs/set",
"white_value_command_topic": "test_light_rgb/white_value/set",
"xy_command_topic": "test_light_rgb/xy/set",
"brightness_state_topic": "test_light_rgb/state1",
"color_temp_state_topic": "test_light_rgb/state1",
"effect_state_topic": "test_light_rgb/state1",
"hs_state_topic": "test_light_rgb/state1",
"rgb_state_topic": "test_light_rgb/state1",
"white_value_state_topic": "test_light_rgb/state1",
"xy_state_topic": "test_light_rgb/state1",
"state_value_template": "{{ value_json.state1.state }}",
"brightness_value_template": "{{ value_json.state1.brightness }}",
"color_temp_value_template": "{{ value_json.state1.ct }}",
"effect_value_template": "{{ value_json.state1.fx }}",
"hs_value_template": "{{ value_json.state1.hs }}",
"rgb_value_template": "{{ value_json.state1.rgb }}",
"white_value_template": "{{ value_json.state1.white }}",
"xy_value_template": "{{ value_json.state1.xy }}",
}
)
data2 = json.dumps(
{
"name": "Milk",
"state_topic": "test_light_rgb/state1",
"command_topic": "test_light_rgb/set",
"brightness_command_topic": "test_light_rgb/state1",
"rgb_command_topic": "test_light_rgb/rgb/set",
"color_temp_command_topic": "test_light_rgb/state1",
"effect_command_topic": "test_light_rgb/effect/set",
"hs_command_topic": "test_light_rgb/hs/set",
"white_value_command_topic": "test_light_rgb/white_value/set",
"xy_command_topic": "test_light_rgb/xy/set",
"brightness_state_topic": "test_light_rgb/state1",
"color_temp_state_topic": "test_light_rgb/state1",
"effect_state_topic": "test_light_rgb/state1",
"hs_state_topic": "test_light_rgb/state1",
"rgb_state_topic": "test_light_rgb/state1",
"white_value_state_topic": "test_light_rgb/state1",
"xy_state_topic": "test_light_rgb/state1",
"state_value_template": "{{ value_json.state2.state }}",
"brightness_value_template": "{{ value_json.state2.brightness }}",
"color_temp_value_template": "{{ value_json.state2.ct }}",
"effect_value_template": "{{ value_json.state2.fx }}",
"hs_value_template": "{{ value_json.state2.hs }}",
"rgb_value_template": "{{ value_json.state2.rgb }}",
"white_value_template": "{{ value_json.state2.white }}",
"xy_value_template": "{{ value_json.state2.xy }}",
}
)
state_data1 = [
(
[
(
"test_light_rgb/state1",
'{"state1":{"state":"ON", "brightness":100, "ct":123, "fx":"cycle"}}',
)
],
"on",
[("brightness", 100), ("color_temp", 123), ("effect", "cycle")],
),
(
[("test_light_rgb/state1", '{"state1":{"state":"OFF"}}')],
"off",
None,
),
(
[
(
"test_light_rgb/state1",
'{"state1":{"state":"ON", "hs":"1,2"}}',
)
],
"on",
[("hs_color", (1, 2))],
),
(
[
(
"test_light_rgb/state1",
'{"state1":{"rgb":"255,127,63"}}',
)
],
"on",
[("rgb_color", (255, 127, 63))],
),
(
[
(
"test_light_rgb/state1",
'{"state1":{"white":50, "xy":"0.3, 0.4"}}',
)
],
"on",
[("white_value", 50), ("xy_color", (0.3, 0.401))],
),
]
state_data2 = [
(
[
(
"test_light_rgb/state1",
'{"state2":{"state":"ON", "brightness":50, "ct":200, "fx":"loop"}}',
)
],
"on",
[("brightness", 50), ("color_temp", 200), ("effect", "loop")],
),
(
[
(
"test_light_rgb/state1",
'{"state1":{"state":"ON", "brightness":100, "ct":123, "fx":"cycle"}}',
),
],
"on",
[("brightness", 50), ("color_temp", 200), ("effect", "loop")],
),
(
[("test_light_rgb/state1", '{"state1":{"state":"OFF"}}')],
"on",
None,
),
(
[("test_light_rgb/state1", '{"state2":{"state":"OFF"}}')],
"off",
None,
),
(
[
(
"test_light_rgb/state1",
'{"state2":{"state":"ON", "hs":"1.2,2.2"}}',
)
],
"on",
[("hs_color", (1.2, 2.2))],
),
(
[
(
"test_light_rgb/state1",
'{"state1":{"state":"ON", "hs":"1,2"}}',
)
],
"on",
[("hs_color", (1.2, 2.2))],
),
(
[
(
"test_light_rgb/state1",
'{"state2":{"rgb":"63,127,255"}}',
)
],
"on",
[("rgb_color", (63, 127, 255))],
),
(
[
(
"test_light_rgb/state1",
'{"state1":{"rgb":"255,127,63"}}',
)
],
"on",
[("rgb_color", (63, 127, 255))],
),
(
[
(
"test_light_rgb/state1",
'{"state2":{"white":75, "xy":"0.4, 0.3"}}',
)
],
"on",
[("white_value", 75), ("xy_color", (0.4, 0.3))],
),
(
[
(
"test_light_rgb/state1",
'{"state1":{"white":50, "xy":"0.3, 0.4"}}',
)
],
"on",
[("white_value", 75), ("xy_color", (0.4, 0.3))],
),
]
await help_test_discovery_update(
hass,
mqtt_mock,
caplog,
light.DOMAIN,
data1,
data2,
state_data1=state_data1,
state_data2=state_data2,
)

View File

@ -1,4 +1,5 @@
"""The tests for the MQTT sensor platform."""
import copy
from datetime import datetime, timedelta
import json
@ -430,12 +431,71 @@ async def test_discovery_removal_sensor(hass, mqtt_mock, caplog):
await help_test_discovery_removal(hass, mqtt_mock, caplog, sensor.DOMAIN, data)
async def test_discovery_update_sensor(hass, mqtt_mock, caplog):
async def test_discovery_update_sensor_topic_template(hass, mqtt_mock, caplog):
"""Test update of discovered sensor."""
data1 = '{ "name": "Beer", "state_topic": "test_topic" }'
data2 = '{ "name": "Milk", "state_topic": "test_topic" }'
config = {"name": "test", "state_topic": "test_topic"}
config1 = copy.deepcopy(config)
config2 = copy.deepcopy(config)
config1["name"] = "Beer"
config2["name"] = "Milk"
config1["state_topic"] = "sensor/state1"
config2["state_topic"] = "sensor/state2"
config1["value_template"] = "{{ value_json.state | int }}"
config2["value_template"] = "{{ value_json.state | int * 2 }}"
state_data1 = [
([("sensor/state1", '{"state":100}')], "100", None),
]
state_data2 = [
([("sensor/state1", '{"state":1000}')], "100", None),
([("sensor/state1", '{"state":1000}')], "100", None),
([("sensor/state2", '{"state":100}')], "200", None),
]
data1 = json.dumps(config1)
data2 = json.dumps(config2)
await help_test_discovery_update(
hass, mqtt_mock, caplog, sensor.DOMAIN, data1, data2
hass,
mqtt_mock,
caplog,
sensor.DOMAIN,
data1,
data2,
state_data1=state_data1,
state_data2=state_data2,
)
async def test_discovery_update_sensor_template(hass, mqtt_mock, caplog):
"""Test update of discovered sensor."""
config = {"name": "test", "state_topic": "test_topic"}
config1 = copy.deepcopy(config)
config2 = copy.deepcopy(config)
config1["name"] = "Beer"
config2["name"] = "Milk"
config1["state_topic"] = "sensor/state1"
config2["state_topic"] = "sensor/state1"
config1["value_template"] = "{{ value_json.state | int }}"
config2["value_template"] = "{{ value_json.state | int * 2 }}"
state_data1 = [
([("sensor/state1", '{"state":100}')], "100", None),
]
state_data2 = [
([("sensor/state1", '{"state":100}')], "200", None),
]
data1 = json.dumps(config1)
data2 = json.dumps(config2)
await help_test_discovery_update(
hass,
mqtt_mock,
caplog,
sensor.DOMAIN,
data1,
data2,
state_data1=state_data1,
state_data2=state_data2,
)

View File

@ -1,4 +1,7 @@
"""The tests for the MQTT switch platform."""
import copy
import json
import pytest
from homeassistant.components import switch
@ -304,20 +307,75 @@ async def test_discovery_removal_switch(hass, mqtt_mock, caplog):
await help_test_discovery_removal(hass, mqtt_mock, caplog, switch.DOMAIN, data)
async def test_discovery_update_switch(hass, mqtt_mock, caplog):
async def test_discovery_update_switch_topic_template(hass, mqtt_mock, caplog):
"""Test update of discovered switch."""
data1 = (
'{ "name": "Beer",'
' "state_topic": "test_topic",'
' "command_topic": "test_topic" }'
)
data2 = (
'{ "name": "Milk",'
' "state_topic": "test_topic",'
' "command_topic": "test_topic" }'
)
config1 = copy.deepcopy(DEFAULT_CONFIG[switch.DOMAIN])
config2 = copy.deepcopy(DEFAULT_CONFIG[switch.DOMAIN])
config1["name"] = "Beer"
config2["name"] = "Milk"
config1["state_topic"] = "switch/state1"
config2["state_topic"] = "switch/state2"
config1["value_template"] = "{{ value_json.state1.state }}"
config2["value_template"] = "{{ value_json.state2.state }}"
state_data1 = [
([("switch/state1", '{"state1":{"state":"ON"}}')], "on", None),
]
state_data2 = [
([("switch/state2", '{"state2":{"state":"OFF"}}')], "off", None),
([("switch/state2", '{"state2":{"state":"ON"}}')], "on", None),
([("switch/state1", '{"state1":{"state":"OFF"}}')], "on", None),
([("switch/state1", '{"state2":{"state":"OFF"}}')], "on", None),
([("switch/state2", '{"state1":{"state":"OFF"}}')], "on", None),
([("switch/state2", '{"state2":{"state":"OFF"}}')], "off", None),
]
data1 = json.dumps(config1)
data2 = json.dumps(config2)
await help_test_discovery_update(
hass, mqtt_mock, caplog, switch.DOMAIN, data1, data2
hass,
mqtt_mock,
caplog,
switch.DOMAIN,
data1,
data2,
state_data1=state_data1,
state_data2=state_data2,
)
async def test_discovery_update_switch_template(hass, mqtt_mock, caplog):
"""Test update of discovered switch."""
config1 = copy.deepcopy(DEFAULT_CONFIG[switch.DOMAIN])
config2 = copy.deepcopy(DEFAULT_CONFIG[switch.DOMAIN])
config1["name"] = "Beer"
config2["name"] = "Milk"
config1["state_topic"] = "switch/state1"
config2["state_topic"] = "switch/state1"
config1["value_template"] = "{{ value_json.state1.state }}"
config2["value_template"] = "{{ value_json.state2.state }}"
state_data1 = [
([("switch/state1", '{"state1":{"state":"ON"}}')], "on", None),
]
state_data2 = [
([("switch/state1", '{"state2":{"state":"OFF"}}')], "off", None),
([("switch/state1", '{"state2":{"state":"ON"}}')], "on", None),
([("switch/state1", '{"state1":{"state":"OFF"}}')], "on", None),
([("switch/state1", '{"state2":{"state":"OFF"}}')], "off", None),
]
data1 = json.dumps(config1)
data2 = json.dumps(config2)
await help_test_discovery_update(
hass,
mqtt_mock,
caplog,
switch.DOMAIN,
data1,
data2,
state_data1=state_data1,
state_data2=state_data2,
)