From 08adfd87f7df4f04d4d748fcf3a2f3dd79e15aa0 Mon Sep 17 00:00:00 2001 From: Marius <ciotlos@gmail.com> Date: Wed, 13 Jun 2018 17:20:38 +0300 Subject: [PATCH] Add unique_id for mqtt binary sensor (#14929) * Added unique_id for mqtt binary sensor * Added missing mqtt message fire in test --- .../components/binary_sensor/mqtt.py | 18 +++++++++++++++--- tests/components/binary_sensor/test_mqtt.py | 19 +++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/binary_sensor/mqtt.py b/homeassistant/components/binary_sensor/mqtt.py index e033355f655..d2533eb8f5b 100644 --- a/homeassistant/components/binary_sensor/mqtt.py +++ b/homeassistant/components/binary_sensor/mqtt.py @@ -6,6 +6,7 @@ https://home-assistant.io/components/binary_sensor.mqtt/ """ import asyncio import logging +from typing import Optional import voluptuous as vol @@ -24,7 +25,7 @@ import homeassistant.helpers.config_validation as cv _LOGGER = logging.getLogger(__name__) DEFAULT_NAME = 'MQTT Binary sensor' - +CONF_UNIQUE_ID = 'unique_id' DEFAULT_PAYLOAD_OFF = 'OFF' DEFAULT_PAYLOAD_ON = 'ON' DEFAULT_FORCE_UPDATE = False @@ -37,6 +38,9 @@ PLATFORM_SCHEMA = mqtt.MQTT_RO_PLATFORM_SCHEMA.extend({ vol.Optional(CONF_PAYLOAD_ON, default=DEFAULT_PAYLOAD_ON): cv.string, vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA, vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE): cv.boolean, + # Integrations shouldn't never expose unique_id through configuration + # this here is an exception because MQTT is a msg transport, not a protocol + vol.Optional(CONF_UNIQUE_ID): cv.string, }).extend(mqtt.MQTT_AVAILABILITY_SCHEMA.schema) @@ -61,7 +65,8 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): config.get(CONF_PAYLOAD_OFF), config.get(CONF_PAYLOAD_AVAILABLE), config.get(CONF_PAYLOAD_NOT_AVAILABLE), - value_template + value_template, + config.get(CONF_UNIQUE_ID), )]) @@ -70,7 +75,8 @@ class MqttBinarySensor(MqttAvailability, BinarySensorDevice): def __init__(self, name, state_topic, availability_topic, device_class, qos, force_update, payload_on, payload_off, payload_available, - payload_not_available, value_template): + payload_not_available, value_template, + unique_id: Optional[str]): """Initialize the MQTT binary sensor.""" super().__init__(availability_topic, qos, payload_available, payload_not_available) @@ -83,6 +89,7 @@ class MqttBinarySensor(MqttAvailability, BinarySensorDevice): self._qos = qos self._force_update = force_update self._template = value_template + self._unique_id = unique_id @asyncio.coroutine def async_added_to_hass(self): @@ -134,3 +141,8 @@ class MqttBinarySensor(MqttAvailability, BinarySensorDevice): def force_update(self): """Force update.""" return self._force_update + + @property + def unique_id(self): + """Return a unique ID.""" + return self._unique_id diff --git a/tests/components/binary_sensor/test_mqtt.py b/tests/components/binary_sensor/test_mqtt.py index 9b5cf7aa736..71eba2df950 100644 --- a/tests/components/binary_sensor/test_mqtt.py +++ b/tests/components/binary_sensor/test_mqtt.py @@ -77,6 +77,25 @@ class TestSensorMQTT(unittest.TestCase): state = self.hass.states.get('binary_sensor.test') self.assertIsNone(state) + def test_unique_id(self): + """Test unique id option only creates one sensor per unique_id.""" + assert setup_component(self.hass, binary_sensor.DOMAIN, { + binary_sensor.DOMAIN: [{ + 'platform': 'mqtt', + 'name': 'Test 1', + 'state_topic': 'test-topic', + 'unique_id': 'TOTALLY_UNIQUE' + }, { + 'platform': 'mqtt', + 'name': 'Test 2', + 'state_topic': 'test-topic', + 'unique_id': 'TOTALLY_UNIQUE' + }] + }) + fire_mqtt_message(self.hass, 'test-topic', 'payload') + self.hass.block_till_done() + assert len(self.hass.states.all()) == 1 + def test_availability_without_topic(self): """Test availability without defined availability topic.""" self.assertTrue(setup_component(self.hass, binary_sensor.DOMAIN, { -- GitLab