From f0a1beac5d9187452b04f7d76a73fba108a78cfa Mon Sep 17 00:00:00 2001 From: Mike Megally Date: Thu, 22 Feb 2018 02:19:18 -0800 Subject: [PATCH] Allow ignoring call service events in mqtt_eventstream (#12519) * [WIP] Allow ignoring call service events This allows a setting a configuration value (False by default to continue the current behavior) which will ignore call service events. * extra spaces removed them * updates from PR review * removed print * update spacing * updated allowed events to allow for custom events, and included some tests * hound fixes * Remove unused constant * Lint --- homeassistant/components/mqtt_eventstream.py | 7 +++ tests/components/test_mqtt_eventstream.py | 59 +++++++++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/mqtt_eventstream.py b/homeassistant/components/mqtt_eventstream.py index 40a752807ed..6f6cb312f2b 100644 --- a/homeassistant/components/mqtt_eventstream.py +++ b/homeassistant/components/mqtt_eventstream.py @@ -26,6 +26,7 @@ DEPENDENCIES = ['mqtt'] CONF_PUBLISH_TOPIC = 'publish_topic' CONF_SUBSCRIBE_TOPIC = 'subscribe_topic' CONF_PUBLISH_EVENTSTREAM_RECEIVED = 'publish_eventstream_received' +CONF_IGNORE_EVENT = 'ignore_event' CONFIG_SCHEMA = vol.Schema({ DOMAIN: vol.Schema({ @@ -33,6 +34,7 @@ CONFIG_SCHEMA = vol.Schema({ vol.Optional(CONF_SUBSCRIBE_TOPIC): valid_subscribe_topic, vol.Optional(CONF_PUBLISH_EVENTSTREAM_RECEIVED, default=False): cv.boolean, + vol.Optional(CONF_IGNORE_EVENT, default=[]): cv.ensure_list }), }, extra=vol.ALLOW_EXTRA) @@ -44,6 +46,7 @@ def async_setup(hass, config): conf = config.get(DOMAIN, {}) pub_topic = conf.get(CONF_PUBLISH_TOPIC) sub_topic = conf.get(CONF_SUBSCRIBE_TOPIC) + ignore_event = conf.get(CONF_IGNORE_EVENT) @callback def _event_publisher(event): @@ -53,6 +56,10 @@ def async_setup(hass, config): if event.event_type == EVENT_TIME_CHANGED: return + # User-defined events to ignore + if event.event_type in ignore_event: + return + # Filter out the events that were triggered by publishing # to the MQTT topic, or you will end up in an infinite loop. if event.event_type == EVENT_CALL_SERVICE: diff --git a/tests/components/test_mqtt_eventstream.py b/tests/components/test_mqtt_eventstream.py index 91175024ea6..f4fc3e89ee0 100644 --- a/tests/components/test_mqtt_eventstream.py +++ b/tests/components/test_mqtt_eventstream.py @@ -30,13 +30,16 @@ class TestMqttEventStream(object): """Stop everything that was started.""" self.hass.stop() - def add_eventstream(self, sub_topic=None, pub_topic=None): + def add_eventstream(self, sub_topic=None, pub_topic=None, + ignore_event=None): """Add a mqtt_eventstream component.""" config = {} if sub_topic: config['subscribe_topic'] = sub_topic if pub_topic: config['publish_topic'] = pub_topic + if ignore_event: + config['ignore_event'] = ignore_event return setup_component(self.hass, eventstream.DOMAIN, { eventstream.DOMAIN: config}) @@ -144,3 +147,57 @@ class TestMqttEventStream(object): self.hass.block_till_done() assert 1 == len(calls) + + @patch('homeassistant.components.mqtt.async_publish') + def test_ignored_event_doesnt_send_over_stream(self, mock_pub): + """"Test the ignoring of sending events if defined.""" + assert self.add_eventstream(pub_topic='bar', + ignore_event=['state_changed']) + self.hass.block_till_done() + + e_id = 'entity.test_id' + event = {} + event['event_type'] = EVENT_STATE_CHANGED + new_state = { + "state": "on", + "entity_id": e_id, + "attributes": {}, + } + event['event_data'] = {"new_state": new_state, "entity_id": e_id} + + # Reset the mock because it will have already gotten calls for the + # mqtt_eventstream state change on initialization, etc. + mock_pub.reset_mock() + + # Set a state of an entity + mock_state_change_event(self.hass, State(e_id, 'on')) + self.hass.block_till_done() + + assert not mock_pub.called + + @patch('homeassistant.components.mqtt.async_publish') + def test_wrong_ignored_event_sends_over_stream(self, mock_pub): + """"Test the ignoring of sending events if defined.""" + assert self.add_eventstream(pub_topic='bar', + ignore_event=['statee_changed']) + self.hass.block_till_done() + + e_id = 'entity.test_id' + event = {} + event['event_type'] = EVENT_STATE_CHANGED + new_state = { + "state": "on", + "entity_id": e_id, + "attributes": {}, + } + event['event_data'] = {"new_state": new_state, "entity_id": e_id} + + # Reset the mock because it will have already gotten calls for the + # mqtt_eventstream state change on initialization, etc. + mock_pub.reset_mock() + + # Set a state of an entity + mock_state_change_event(self.hass, State(e_id, 'on')) + self.hass.block_till_done() + + assert mock_pub.called