Add MQTT Sensor unique_id (#13318)

* Add MQTT Sensor unique_id

* Add test

* Update comment
pull/13756/head
Otto Winter 2018-04-08 04:32:09 +02:00 committed by Paulus Schoutsen
parent 99f4509c2b
commit 81b1d08d35
2 changed files with 35 additions and 1 deletions

View File

@ -8,6 +8,7 @@ import asyncio
import logging
import json
from datetime import timedelta
from typing import Optional
import voluptuous as vol
@ -28,6 +29,7 @@ _LOGGER = logging.getLogger(__name__)
CONF_EXPIRE_AFTER = 'expire_after'
CONF_JSON_ATTRS = 'json_attributes'
CONF_UNIQUE_ID = 'unique_id'
DEFAULT_NAME = 'MQTT Sensor'
DEFAULT_FORCE_UPDATE = False
@ -40,6 +42,9 @@ PLATFORM_SCHEMA = mqtt.MQTT_RO_PLATFORM_SCHEMA.extend({
vol.Optional(CONF_JSON_ATTRS, default=[]): cv.ensure_list_csv,
vol.Optional(CONF_EXPIRE_AFTER): cv.positive_int,
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)
@ -63,6 +68,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
config.get(CONF_ICON),
value_template,
config.get(CONF_JSON_ATTRS),
config.get(CONF_UNIQUE_ID),
config.get(CONF_AVAILABILITY_TOPIC),
config.get(CONF_PAYLOAD_AVAILABLE),
config.get(CONF_PAYLOAD_NOT_AVAILABLE),
@ -74,7 +80,8 @@ class MqttSensor(MqttAvailability, Entity):
def __init__(self, name, state_topic, qos, unit_of_measurement,
force_update, expire_after, icon, value_template,
json_attributes, availability_topic, payload_available,
json_attributes, unique_id: Optional[str],
availability_topic, payload_available,
payload_not_available):
"""Initialize the sensor."""
super().__init__(availability_topic, qos, payload_available,
@ -90,6 +97,7 @@ class MqttSensor(MqttAvailability, Entity):
self._icon = icon
self._expiration_trigger = None
self._json_attributes = set(json_attributes)
self._unique_id = unique_id
self._attributes = None
@asyncio.coroutine
@ -174,6 +182,11 @@ class MqttSensor(MqttAvailability, Entity):
"""Return the state attributes."""
return self._attributes
@property
def unique_id(self):
"""Return a unique ID."""
return self._unique_id
@property
def icon(self):
"""Return the icon."""

View File

@ -329,3 +329,24 @@ class TestSensorMQTT(unittest.TestCase):
self.assertEqual('100',
state.attributes.get('val'))
self.assertEqual('100', state.state)
def test_unique_id(self):
"""Test unique id option only creates one sensor per unique_id."""
assert setup_component(self.hass, sensor.DOMAIN, {
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