Add device registry to MQTT climate

This commit is contained in:
Erik 2018-12-15 17:28:08 +01:00
parent c71a6ee562
commit e874093818
2 changed files with 86 additions and 9 deletions

View File

@ -18,12 +18,13 @@ from homeassistant.components.climate import (
SUPPORT_SWING_MODE, SUPPORT_FAN_MODE, SUPPORT_AWAY_MODE, SUPPORT_HOLD_MODE, SUPPORT_SWING_MODE, SUPPORT_FAN_MODE, SUPPORT_AWAY_MODE, SUPPORT_HOLD_MODE,
SUPPORT_AUX_HEAT, DEFAULT_MIN_TEMP, DEFAULT_MAX_TEMP) SUPPORT_AUX_HEAT, DEFAULT_MIN_TEMP, DEFAULT_MAX_TEMP)
from homeassistant.const import ( from homeassistant.const import (
STATE_ON, STATE_OFF, ATTR_TEMPERATURE, CONF_NAME, CONF_VALUE_TEMPLATE) ATTR_TEMPERATURE, CONF_DEVICE, CONF_NAME, CONF_VALUE_TEMPLATE, STATE_ON,
STATE_OFF)
from homeassistant.components.mqtt import ( from homeassistant.components.mqtt import (
ATTR_DISCOVERY_HASH, CONF_AVAILABILITY_TOPIC, CONF_QOS, CONF_RETAIN, ATTR_DISCOVERY_HASH, CONF_AVAILABILITY_TOPIC, CONF_QOS, CONF_RETAIN,
CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE, CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE,
MQTT_BASE_PLATFORM_SCHEMA, MqttAvailability, MqttDiscoveryUpdate, MQTT_BASE_PLATFORM_SCHEMA, MqttAvailability, MqttDiscoveryUpdate,
subscription) MqttEntityDeviceInfo, subscription)
from homeassistant.components.mqtt.discovery import MQTT_DISCOVERY_NEW from homeassistant.components.mqtt.discovery import MQTT_DISCOVERY_NEW
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
@ -78,6 +79,8 @@ CONF_MIN_TEMP = 'min_temp'
CONF_MAX_TEMP = 'max_temp' CONF_MAX_TEMP = 'max_temp'
CONF_TEMP_STEP = 'temp_step' CONF_TEMP_STEP = 'temp_step'
CONF_UNIQUE_ID = 'unique_id'
TEMPLATE_KEYS = ( TEMPLATE_KEYS = (
CONF_POWER_STATE_TEMPLATE, CONF_POWER_STATE_TEMPLATE,
CONF_MODE_STATE_TEMPLATE, CONF_MODE_STATE_TEMPLATE,
@ -139,8 +142,9 @@ PLATFORM_SCHEMA = SCHEMA_BASE.extend({
vol.Optional(CONF_MIN_TEMP, default=DEFAULT_MIN_TEMP): vol.Coerce(float), vol.Optional(CONF_MIN_TEMP, default=DEFAULT_MIN_TEMP): vol.Coerce(float),
vol.Optional(CONF_MAX_TEMP, default=DEFAULT_MAX_TEMP): vol.Coerce(float), vol.Optional(CONF_MAX_TEMP, default=DEFAULT_MAX_TEMP): vol.Coerce(float),
vol.Optional(CONF_TEMP_STEP, default=1.0): vol.Coerce(float) vol.Optional(CONF_TEMP_STEP, default=1.0): vol.Coerce(float),
vol.Optional(CONF_UNIQUE_ID): cv.string,
vol.Optional(CONF_DEVICE): mqtt.MQTT_ENTITY_DEVICE_INFO_SCHEMA,
}).extend(mqtt.MQTT_AVAILABILITY_SCHEMA.schema) }).extend(mqtt.MQTT_AVAILABILITY_SCHEMA.schema)
@ -174,12 +178,14 @@ async def _async_setup_entity(hass, config, async_add_entities,
)]) )])
class MqttClimate(MqttAvailability, MqttDiscoveryUpdate, ClimateDevice): class MqttClimate(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
ClimateDevice):
"""Representation of an MQTT climate device.""" """Representation of an MQTT climate device."""
def __init__(self, hass, config, discovery_hash): def __init__(self, hass, config, discovery_hash):
"""Initialize the climate device.""" """Initialize the climate device."""
self._config = config self._config = config
self._unique_id = config.get(CONF_UNIQUE_ID)
self._sub_state = None self._sub_state = None
self.hass = hass self.hass = hass
@ -201,11 +207,13 @@ class MqttClimate(MqttAvailability, MqttDiscoveryUpdate, ClimateDevice):
payload_available = config.get(CONF_PAYLOAD_AVAILABLE) payload_available = config.get(CONF_PAYLOAD_AVAILABLE)
payload_not_available = config.get(CONF_PAYLOAD_NOT_AVAILABLE) payload_not_available = config.get(CONF_PAYLOAD_NOT_AVAILABLE)
qos = config.get(CONF_QOS) qos = config.get(CONF_QOS)
device_config = config.get(CONF_DEVICE)
MqttAvailability.__init__(self, availability_topic, qos, MqttAvailability.__init__(self, availability_topic, qos,
payload_available, payload_not_available) payload_available, payload_not_available)
MqttDiscoveryUpdate.__init__(self, discovery_hash, MqttDiscoveryUpdate.__init__(self, discovery_hash,
self.discovery_update) self.discovery_update)
MqttEntityDeviceInfo.__init__(self, device_config)
async def async_added_to_hass(self): async def async_added_to_hass(self):
"""Handle being added to home assistant.""" """Handle being added to home assistant."""
@ -467,6 +475,11 @@ class MqttClimate(MqttAvailability, MqttDiscoveryUpdate, ClimateDevice):
"""Return the name of the climate device.""" """Return the name of the climate device."""
return self._config.get(CONF_NAME) return self._config.get(CONF_NAME)
@property
def unique_id(self):
"""Return a unique ID."""
return self._unique_id
@property @property
def temperature_unit(self): def temperature_unit(self):
"""Return the unit of measurement.""" """Return the unit of measurement."""

View File

@ -1,6 +1,7 @@
"""The tests for the mqtt climate component.""" """The tests for the mqtt climate component."""
import unittest
import copy import copy
import json
import unittest
import pytest import pytest
import voluptuous as vol import voluptuous as vol
@ -16,9 +17,10 @@ from homeassistant.components.climate import (
SUPPORT_FAN_MODE, SUPPORT_SWING_MODE, SUPPORT_HOLD_MODE, SUPPORT_FAN_MODE, SUPPORT_SWING_MODE, SUPPORT_HOLD_MODE,
SUPPORT_AWAY_MODE, SUPPORT_AUX_HEAT, DEFAULT_MIN_TEMP, DEFAULT_MAX_TEMP) SUPPORT_AWAY_MODE, SUPPORT_AUX_HEAT, DEFAULT_MIN_TEMP, DEFAULT_MAX_TEMP)
from homeassistant.components.mqtt.discovery import async_start from homeassistant.components.mqtt.discovery import async_start
from tests.common import (get_test_home_assistant, mock_mqtt_component, from tests.common import (
async_fire_mqtt_message, fire_mqtt_message, async_fire_mqtt_message, async_mock_mqtt_component, async_setup_component,
mock_component, MockConfigEntry) fire_mqtt_message, get_test_home_assistant, mock_component,
mock_mqtt_component, MockConfigEntry)
from tests.components.climate import common from tests.components.climate import common
ENTITY_CLIMATE = 'climate.test' ENTITY_CLIMATE = 'climate.test'
@ -671,6 +673,29 @@ class TestMQTTClimate(unittest.TestCase):
assert 0.01 == temp_step assert 0.01 == temp_step
async def test_unique_id(hass):
"""Test unique id option only creates one climate per unique_id."""
await async_mock_mqtt_component(hass)
assert await async_setup_component(hass, climate.DOMAIN, {
climate.DOMAIN: [{
'platform': 'mqtt',
'name': 'Test 1',
'status_topic': 'test-topic',
'command_topic': 'test_topic',
'unique_id': 'TOTALLY_UNIQUE'
}, {
'platform': 'mqtt',
'name': 'Test 2',
'status_topic': 'test-topic',
'command_topic': 'test_topic',
'unique_id': 'TOTALLY_UNIQUE'
}]
})
async_fire_mqtt_message(hass, 'test-topic', 'payload')
await hass.async_block_till_done()
assert len(hass.states.async_entity_ids(climate.DOMAIN)) == 1
async def test_discovery_removal_climate(hass, mqtt_mock, caplog): async def test_discovery_removal_climate(hass, mqtt_mock, caplog):
"""Test removal of discovered climate.""" """Test removal of discovered climate."""
entry = MockConfigEntry(domain=mqtt.DOMAIN) entry = MockConfigEntry(domain=mqtt.DOMAIN)
@ -721,3 +746,42 @@ async def test_discovery_update_climate(hass, mqtt_mock, caplog):
state = hass.states.get('climate.milk') state = hass.states.get('climate.milk')
assert state is None assert state is None
async def test_entity_device_info_with_identifier(hass, mqtt_mock):
"""Test MQTT climate device registry integration."""
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({
'platform': 'mqtt',
'name': 'Test 1',
'state_topic': 'test-topic',
'command_topic': 'test-topic',
'device': {
'identifiers': ['helloworld'],
'connections': [
["mac", "02:5b:26:a8:dc:12"],
],
'manufacturer': 'Whatever',
'name': 'Beer',
'model': 'Glass',
'sw_version': '0.1-beta',
},
'unique_id': 'veryunique'
})
async_fire_mqtt_message(hass, 'homeassistant/climate/bla/config',
data)
await hass.async_block_till_done()
await hass.async_block_till_done()
device = registry.async_get_device({('mqtt', 'helloworld')}, set())
assert device is not None
assert device.identifiers == {('mqtt', 'helloworld')}
assert device.connections == {('mac', "02:5b:26:a8:dc:12")}
assert device.manufacturer == 'Whatever'
assert device.name == 'Beer'
assert device.model == 'Glass'
assert device.sw_version == '0.1-beta'