From c4c21d3e99fa1a84ca3d9a5be1e02a06bcd2e2c7 Mon Sep 17 00:00:00 2001 From: zewelor Date: Wed, 4 Sep 2019 16:15:40 +0200 Subject: [PATCH] Add device to mqtt camera (#26238) * Add device to mqtt camera * Support discovery device info update and add tests --- homeassistant/components/mqtt/camera.py | 29 +++++++--- tests/components/mqtt/test_camera.py | 77 +++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/mqtt/camera.py b/homeassistant/components/mqtt/camera.py index 1df635bbde4..f3ae36c5746 100644 --- a/homeassistant/components/mqtt/camera.py +++ b/homeassistant/components/mqtt/camera.py @@ -7,13 +7,19 @@ import voluptuous as vol from homeassistant.components import camera, mqtt from homeassistant.components.camera import PLATFORM_SCHEMA, Camera -from homeassistant.const import CONF_NAME +from homeassistant.const import CONF_NAME, CONF_DEVICE from homeassistant.core import callback from homeassistant.helpers import config_validation as cv from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.typing import ConfigType, HomeAssistantType -from . import ATTR_DISCOVERY_HASH, CONF_UNIQUE_ID, MqttDiscoveryUpdate, subscription +from . import ( + ATTR_DISCOVERY_HASH, + CONF_UNIQUE_ID, + MqttDiscoveryUpdate, + MqttEntityDeviceInfo, + subscription, +) from .discovery import MQTT_DISCOVERY_NEW, clear_discovery_hash _LOGGER = logging.getLogger(__name__) @@ -26,6 +32,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Required(CONF_TOPIC): mqtt.valid_subscribe_topic, vol.Optional(CONF_UNIQUE_ID): cv.string, + vol.Optional(CONF_DEVICE): mqtt.MQTT_ENTITY_DEVICE_INFO_SCHEMA, } ) @@ -45,7 +52,9 @@ async def async_setup_entry(hass, config_entry, async_add_entities): try: discovery_hash = discovery_payload.pop(ATTR_DISCOVERY_HASH) config = PLATFORM_SCHEMA(discovery_payload) - await _async_setup_entity(config, async_add_entities, discovery_hash) + await _async_setup_entity( + config, async_add_entities, config_entry, discovery_hash + ) except Exception: if discovery_hash: clear_discovery_hash(hass, discovery_hash) @@ -56,15 +65,17 @@ async def async_setup_entry(hass, config_entry, async_add_entities): ) -async def _async_setup_entity(config, async_add_entities, discovery_hash=None): +async def _async_setup_entity( + config, async_add_entities, config_entry=None, discovery_hash=None +): """Set up the MQTT Camera.""" - async_add_entities([MqttCamera(config, discovery_hash)]) + async_add_entities([MqttCamera(config, config_entry, discovery_hash)]) -class MqttCamera(MqttDiscoveryUpdate, Camera): +class MqttCamera(MqttDiscoveryUpdate, MqttEntityDeviceInfo, Camera): """representation of a MQTT camera.""" - def __init__(self, config, discovery_hash): + def __init__(self, config, config_entry, discovery_hash): """Initialize the MQTT Camera.""" self._config = config self._unique_id = config.get(CONF_UNIQUE_ID) @@ -73,8 +84,11 @@ class MqttCamera(MqttDiscoveryUpdate, Camera): self._qos = 0 self._last_image = None + device_config = config.get(CONF_DEVICE) + Camera.__init__(self) MqttDiscoveryUpdate.__init__(self, discovery_hash, self.discovery_update) + MqttEntityDeviceInfo.__init__(self, device_config, config_entry) async def async_added_to_hass(self): """Subscribe MQTT events.""" @@ -85,6 +99,7 @@ class MqttCamera(MqttDiscoveryUpdate, Camera): """Handle updated discovery message.""" config = PLATFORM_SCHEMA(discovery_payload) self._config = config + await self.device_info_discovery_update(config) await self._subscribe_topics() self.async_write_ha_state() diff --git a/tests/components/mqtt/test_camera.py b/tests/components/mqtt/test_camera.py index ecc54e0e209..70b5e941fe3 100644 --- a/tests/components/mqtt/test_camera.py +++ b/tests/components/mqtt/test_camera.py @@ -1,5 +1,6 @@ """The tests for mqtt camera component.""" from unittest.mock import ANY +import json from homeassistant.components import camera, mqtt from homeassistant.components.mqtt.discovery import async_start @@ -167,3 +168,79 @@ async def test_entity_id_update(hass, mqtt_mock): assert state is not None assert mock_mqtt.async_subscribe.call_count == 1 mock_mqtt.async_subscribe.assert_any_call("test-topic", ANY, 0, None) + + +async def test_entity_device_info_with_identifier(hass, mqtt_mock): + """Test MQTT camera 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", + "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/camera/bla/config", data) + 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" + + +async def test_entity_device_info_update(hass, mqtt_mock): + """Test device registry update.""" + 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() + + config = { + "platform": "mqtt", + "name": "Test 1", + "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", + } + + data = json.dumps(config) + async_fire_mqtt_message(hass, "homeassistant/camera/bla/config", data) + await hass.async_block_till_done() + + device = registry.async_get_device({("mqtt", "helloworld")}, set()) + assert device is not None + assert device.name == "Beer" + + config["device"]["name"] = "Milk" + data = json.dumps(config) + async_fire_mqtt_message(hass, "homeassistant/camera/bla/config", data) + await hass.async_block_till_done() + + device = registry.async_get_device({("mqtt", "helloworld")}, set()) + assert device is not None + assert device.name == "Milk"