From 969fe1f3b9a716a27cb83740e40ab79c04afecfc Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 10 Aug 2015 18:12:22 -0700 Subject: [PATCH 1/2] Fix MQTT wildcard topic subscriptions --- homeassistant/components/mqtt.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/mqtt.py b/homeassistant/components/mqtt.py index 7f6b0c11b5f..be50cc31175 100644 --- a/homeassistant/components/mqtt.py +++ b/homeassistant/components/mqtt.py @@ -92,8 +92,8 @@ def publish(hass, topic, payload): def subscribe(hass, topic, callback, qos=0): """ Subscribe to a topic. """ def mqtt_topic_subscriber(event): - """ Subscribes to a specific MQTT topic. """ - if event.data[ATTR_TOPIC] == topic: + """ Match subscribed MQTT topic. """ + if _match_topic(topic, event.data[ATTR_TOPIC]): callback(topic, event.data[ATTR_PAYLOAD], event.data[ATTR_QOS]) hass.bus.listen(EVENT_MQTT_MESSAGE_RECEIVED, mqtt_topic_subscriber) @@ -240,3 +240,11 @@ def _raise_on_error(result): """ Raise error if error result. """ if result != 0: raise HomeAssistantError('Error talking to MQTT: {}'.format(result)) + + +def _match_topic(subscription, topic): + """ Returns if topic matches subscription. """ + if not subscription.endswith('#'): + return subscription == topic + + return subscription[:-2] == topic or topic.startswith(subscription[:-1]) From f79567f7dba5234968d1885a24293fb580aa76b8 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 10 Aug 2015 21:49:19 -0700 Subject: [PATCH 2/2] MQTT: add support for + wildcard in subscribe --- homeassistant/components/mqtt.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/mqtt.py b/homeassistant/components/mqtt.py index be50cc31175..98612e2bd13 100644 --- a/homeassistant/components/mqtt.py +++ b/homeassistant/components/mqtt.py @@ -94,7 +94,8 @@ def subscribe(hass, topic, callback, qos=0): def mqtt_topic_subscriber(event): """ Match subscribed MQTT topic. """ if _match_topic(topic, event.data[ATTR_TOPIC]): - callback(topic, event.data[ATTR_PAYLOAD], event.data[ATTR_QOS]) + callback(event.data[ATTR_TOPIC], event.data[ATTR_PAYLOAD], + event.data[ATTR_QOS]) hass.bus.listen(EVENT_MQTT_MESSAGE_RECEIVED, mqtt_topic_subscriber) @@ -244,7 +245,12 @@ def _raise_on_error(result): def _match_topic(subscription, topic): """ Returns if topic matches subscription. """ - if not subscription.endswith('#'): - return subscription == topic + if subscription.endswith('#'): + return (subscription[:-2] == topic or + topic.startswith(subscription[:-1])) - return subscription[:-2] == topic or topic.startswith(subscription[:-1]) + sub_parts = subscription.split('/') + topic_parts = topic.split('/') + + return (len(sub_parts) == len(topic_parts) and + all(a == b for a, b in zip(sub_parts, topic_parts) if a != '+'))