Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion homeassistant/components/sensor/mqtt.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import logging
import json
from datetime import timedelta
from typing import Optional

import voluptuous as vol

Expand All @@ -28,6 +29,7 @@

CONF_EXPIRE_AFTER = 'expire_after'
CONF_JSON_ATTRS = 'json_attributes'
CONF_UNIQUE_ID = 'unique_id'

DEFAULT_NAME = 'MQTT Sensor'
DEFAULT_FORCE_UPDATE = False
Expand All @@ -40,6 +42,9 @@
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)


Expand All @@ -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),
Expand All @@ -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,
Expand All @@ -90,6 +97,7 @@ def __init__(self, name, state_topic, qos, unit_of_measurement,
self._icon = icon
self._expiration_trigger = None
self._json_attributes = set(json_attributes)
self._unique_id = unique_id
self._attributes = None

@asyncio.coroutine
Expand Down Expand Up @@ -174,6 +182,11 @@ def device_state_attributes(self):
"""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."""
Expand Down
21 changes: 21 additions & 0 deletions tests/components/sensor/test_mqtt.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,3 +329,24 @@ def test_update_with_json_attrs_and_template(self):
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