From ce19e6367ff0ff6f77d40b813e25158d312d70e2 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 14 Oct 2016 21:08:44 -0700 Subject: [PATCH] Catch MQTT encoding errors (#3749) * added error handling to mqtt message receive if payload is not utf-8 unicode added mqtt test for above code as well * change permission back to 644 * attempting to test new code * changed exception to AttributeError fixed test for above * fixed lint errors I made in tests....mqtt/test_init.py * more lint fixes for my added test * remove dual decode of MQTT payload * convert if to try, except, else statement for mqtt payload decode * rework mqtt unicode testing code to properly check for log file entriy on unicode decode exception * fixed lint error * Update test_init.py --- homeassistant/components/mqtt/__init__.py | 21 +++++++++++++------- tests/components/mqtt/test_init.py | 24 +++++++++++++++++++++++ 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/mqtt/__init__.py b/homeassistant/components/mqtt/__init__.py index 3edd0ffc500..bc7977ae129 100644 --- a/homeassistant/components/mqtt/__init__.py +++ b/homeassistant/components/mqtt/__init__.py @@ -401,13 +401,20 @@ class MQTT(object): def _mqtt_on_message(self, _mqttc, _userdata, msg): """Message received callback.""" - _LOGGER.debug("received message on %s: %s", - msg.topic, msg.payload.decode('utf-8')) - self.hass.bus.fire(EVENT_MQTT_MESSAGE_RECEIVED, { - ATTR_TOPIC: msg.topic, - ATTR_QOS: msg.qos, - ATTR_PAYLOAD: msg.payload.decode('utf-8'), - }) + try: + payload = msg.payload.decode('utf-8') + except AttributeError: + _LOGGER.error("Illegal utf-8 unicode payload from " + "MQTT topic: %s, Payload: %s", msg.topic, + msg.payload) + else: + _LOGGER.debug("received message on %s: %s", + msg.topic, payload) + self.hass.bus.fire(EVENT_MQTT_MESSAGE_RECEIVED, { + ATTR_TOPIC: msg.topic, + ATTR_QOS: msg.qos, + ATTR_PAYLOAD: payload, + }) def _mqtt_on_unsubscribe(self, _mqttc, _userdata, mid, granted_qos): """Unsubscribe successful callback.""" diff --git a/tests/components/mqtt/test_init.py b/tests/components/mqtt/test_init.py index bb7b09c5112..cfa0766c8ed 100644 --- a/tests/components/mqtt/test_init.py +++ b/tests/components/mqtt/test_init.py @@ -316,3 +316,27 @@ class TestMQTTCallbacks(unittest.TestCase): def test_invalid_mqtt_topics(self): self.assertRaises(vol.Invalid, mqtt.valid_publish_topic, 'bad+topic') self.assertRaises(vol.Invalid, mqtt.valid_subscribe_topic, 'bad\0one') + + def test_receiving_non_utf8_message_gets_logged(self): + """Test receiving a non utf8 encoded message.""" + calls = [] + + def record(event): + """Helper to record calls.""" + calls.append(event) + + payload = 0x9a + topic = 'test_topic' + self.hass.bus.listen_once(mqtt.EVENT_MQTT_MESSAGE_RECEIVED, record) + MQTTMessage = namedtuple('MQTTMessage', ['topic', 'qos', 'payload']) + message = MQTTMessage(topic, 1, payload) + with self.assertLogs(level='ERROR') as test_handle: + mqtt.MQTT_CLIENT._mqtt_on_message( + None, + {'hass': self.hass}, + message) + self.hass.block_till_done() + self.assertIn( + "ERROR:homeassistant.components.mqtt:Illegal utf-8 unicode " + "payload from MQTT topic: %s, Payload: " % topic, + test_handle.output[0])