From f3b6575272e3949c7dd02ebdb95a165747e07223 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Mon, 6 Apr 2020 19:25:09 +0200 Subject: [PATCH] Fix MQTT debug info for subscriptions with wildcard. (#33744) --- homeassistant/components/mqtt/__init__.py | 17 +++++++--- homeassistant/components/mqtt/debug_info.py | 2 +- homeassistant/components/mqtt/models.py | 1 + tests/components/mqtt/test_init.py | 37 +++++++++++++++++++++ 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/mqtt/__init__.py b/homeassistant/components/mqtt/__init__.py index 5a4dd701d32..ff99cf59c0b 100644 --- a/homeassistant/components/mqtt/__init__.py +++ b/homeassistant/components/mqtt/__init__.py @@ -388,7 +388,7 @@ def wrap_msg_callback(msg_callback: MessageCallbackType) -> MessageCallbackType: @wraps(msg_callback) async def async_wrapper(msg: Any) -> None: - """Catch and log exception.""" + """Call with deprecated signature.""" await msg_callback(msg.topic, msg.payload, msg.qos) wrapper_func = async_wrapper @@ -396,7 +396,7 @@ def wrap_msg_callback(msg_callback: MessageCallbackType) -> MessageCallbackType: @wraps(msg_callback) def wrapper(msg: Any) -> None: - """Catch and log exception.""" + """Call with deprecated signature.""" msg_callback(msg.topic, msg.payload, msg.qos) wrapper_func = wrapper @@ -808,7 +808,10 @@ class MQTT: if will_message is not None: self._mqttc.will_set( # pylint: disable=no-value-for-parameter - *attr.astuple(will_message) + *attr.astuple( + will_message, + filter=lambda attr, value: attr.name != "subscribed_topic", + ) ) async def async_publish( @@ -940,7 +943,10 @@ class MQTT: if self.birth_message: self.hass.add_job( self.async_publish( # pylint: disable=no-value-for-parameter - *attr.astuple(self.birth_message) + *attr.astuple( + self.birth_message, + filter=lambda attr, value: attr.name != "subscribed_topic", + ) ) ) @@ -976,7 +982,8 @@ class MQTT: continue self.hass.async_run_job( - subscription.callback, Message(msg.topic, payload, msg.qos, msg.retain) + subscription.callback, + Message(msg.topic, payload, msg.qos, msg.retain, subscription.topic), ) def _mqtt_on_disconnect(self, _mqttc, _userdata, result_code: int) -> None: diff --git a/homeassistant/components/mqtt/debug_info.py b/homeassistant/components/mqtt/debug_info.py index ec4ff1676bb..b51ee619a12 100644 --- a/homeassistant/components/mqtt/debug_info.py +++ b/homeassistant/components/mqtt/debug_info.py @@ -21,7 +21,7 @@ def log_messages(hass: HomeAssistantType, entity_id: str) -> MessageCallbackType def _log_message(msg): """Log message.""" debug_info = hass.data[DATA_MQTT_DEBUG_INFO] - messages = debug_info["entities"][entity_id]["topics"][msg.topic] + messages = debug_info["entities"][entity_id]["topics"][msg.subscribed_topic] messages.append(msg.payload) def _decorator(msg_callback: MessageCallbackType): diff --git a/homeassistant/components/mqtt/models.py b/homeassistant/components/mqtt/models.py index cfdecd3383d..3a4add57298 100644 --- a/homeassistant/components/mqtt/models.py +++ b/homeassistant/components/mqtt/models.py @@ -14,6 +14,7 @@ class Message: payload = attr.ib(type=PublishPayloadType) qos = attr.ib(type=int) retain = attr.ib(type=bool) + subscribed_topic = attr.ib(type=str, default=None) MessageCallbackType = Callable[[Message], None] diff --git a/tests/components/mqtt/test_init.py b/tests/components/mqtt/test_init.py index d9686719a82..637cefcf744 100644 --- a/tests/components/mqtt/test_init.py +++ b/tests/components/mqtt/test_init.py @@ -1235,3 +1235,40 @@ async def test_debug_info_non_mqtt(hass, device_reg, entity_reg): debug_info_data = await debug_info.info_for_device(hass, device_entry.id) assert len(debug_info_data["entities"]) == 0 assert len(debug_info_data["triggers"]) == 0 + + +async def test_debug_info_wildcard(hass, mqtt_mock): + """Test debug info.""" + config = { + "device": {"identifiers": ["helloworld"]}, + "platform": "mqtt", + "name": "test", + "state_topic": "sensor/#", + "unique_id": "veryunique", + } + + entry = MockConfigEntry(domain=mqtt.DOMAIN) + entry.add_to_hass(hass) + await async_start(hass, "homeassistant", {}, entry) + registry = await hass.helpers.device_registry.async_get_registry() + + data = json.dumps(config) + async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data) + await hass.async_block_till_done() + + device = registry.async_get_device({("mqtt", "helloworld")}, set()) + assert device is not None + + debug_info_data = await debug_info.info_for_device(hass, device.id) + assert len(debug_info_data["entities"][0]["topics"]) >= 1 + assert {"topic": "sensor/#", "messages": []} in debug_info_data["entities"][0][ + "topics" + ] + + async_fire_mqtt_message(hass, "sensor/abc", "123") + + debug_info_data = await debug_info.info_for_device(hass, device.id) + assert len(debug_info_data["entities"][0]["topics"]) >= 1 + assert {"topic": "sensor/#", "messages": ["123"]} in debug_info_data["entities"][0][ + "topics" + ]