mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 20:57:21 +00:00
Make MQTT platforms config entries (#16904)
* Make MQTT platforms config entries * Fix tests * Address Comment * Rework tests * Undo style auto-reformat style changes
This commit is contained in:
parent
8d65230a36
commit
d1ad2cc225
@ -13,6 +13,7 @@ from homeassistant.components.mqtt import CONF_STATE_TOPIC, ATTR_DISCOVERY_HASH
|
||||
from homeassistant.const import CONF_PLATFORM
|
||||
from homeassistant.helpers.discovery import async_load_platform
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@ -38,11 +39,18 @@ ALLOWED_PLATFORMS = {
|
||||
'alarm_control_panel': ['mqtt'],
|
||||
}
|
||||
|
||||
CONFIG_ENTRY_PLATFORMS = {
|
||||
'sensor': ['mqtt'],
|
||||
}
|
||||
|
||||
ALREADY_DISCOVERED = 'mqtt_discovered_components'
|
||||
CONFIG_ENTRY_IS_SETUP = 'mqtt_config_entry_is_setup'
|
||||
MQTT_DISCOVERY_UPDATED = 'mqtt_discovery_updated_{}'
|
||||
MQTT_DISCOVERY_NEW = 'mqtt_discovery_new_{}_{}'
|
||||
|
||||
|
||||
async def async_start(hass, discovery_topic, hass_config):
|
||||
async def async_start(hass: HomeAssistantType, discovery_topic, hass_config,
|
||||
config_entry=None) -> bool:
|
||||
"""Initialize of MQTT Discovery."""
|
||||
async def async_device_message_received(topic, payload, qos):
|
||||
"""Process the received message."""
|
||||
@ -98,8 +106,21 @@ async def async_start(hass, discovery_topic, hass_config):
|
||||
|
||||
_LOGGER.info("Found new component: %s %s", component, discovery_id)
|
||||
|
||||
await async_load_platform(
|
||||
hass, component, platform, payload, hass_config)
|
||||
if platform not in CONFIG_ENTRY_PLATFORMS.get(component, []):
|
||||
await async_load_platform(
|
||||
hass, component, platform, payload, hass_config)
|
||||
return
|
||||
|
||||
config_entries_key = '{}.{}'.format(component, platform)
|
||||
if config_entries_key not in hass.data[CONFIG_ENTRY_IS_SETUP]:
|
||||
await hass.config_entries.async_forward_entry_setup(
|
||||
config_entry, component)
|
||||
hass.data[CONFIG_ENTRY_IS_SETUP].add(config_entries_key)
|
||||
|
||||
async_dispatcher_send(hass, MQTT_DISCOVERY_NEW.format(
|
||||
component, platform), payload)
|
||||
|
||||
hass.data[CONFIG_ENTRY_IS_SETUP] = set()
|
||||
|
||||
await mqtt.async_subscribe(
|
||||
hass, discovery_topic + '/#', async_device_message_received, 0)
|
||||
|
@ -12,10 +12,12 @@ from typing import Optional
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.components import sensor
|
||||
from homeassistant.components.mqtt import (
|
||||
ATTR_DISCOVERY_HASH, CONF_AVAILABILITY_TOPIC, CONF_STATE_TOPIC,
|
||||
CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE, CONF_QOS,
|
||||
MqttAvailability, MqttDiscoveryUpdate)
|
||||
from homeassistant.components.mqtt.discovery import MQTT_DISCOVERY_NEW
|
||||
from homeassistant.components.sensor import DEVICE_CLASSES_SCHEMA
|
||||
from homeassistant.const import (
|
||||
CONF_FORCE_UPDATE, CONF_NAME, CONF_VALUE_TEMPLATE, STATE_UNKNOWN,
|
||||
@ -24,6 +26,7 @@ from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.components import mqtt
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.typing import HomeAssistantType, ConfigType
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.event import async_track_point_in_utc_time
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
@ -53,7 +56,24 @@ PLATFORM_SCHEMA = mqtt.MQTT_RO_PLATFORM_SCHEMA.extend({
|
||||
|
||||
async def async_setup_platform(hass: HomeAssistantType, config: ConfigType,
|
||||
async_add_entities, discovery_info=None):
|
||||
"""Set up MQTT Sensor."""
|
||||
"""Set up MQTT sensors through configuration.yaml."""
|
||||
await _async_setup_platform(hass, config, async_add_entities,
|
||||
discovery_info)
|
||||
|
||||
|
||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||
"""Set up MQTT sensors dynamically through MQTT discovery."""
|
||||
async def async_discover_sensor(config):
|
||||
"""Discover and add a discovered MQTT sensor."""
|
||||
await _async_setup_platform(hass, {}, async_add_entities, config)
|
||||
|
||||
async_dispatcher_connect(hass,
|
||||
MQTT_DISCOVERY_NEW.format(sensor.DOMAIN, 'mqtt'),
|
||||
async_discover_sensor)
|
||||
|
||||
|
||||
async def _async_setup_platform(hass: HomeAssistantType, config: ConfigType,
|
||||
async_add_entities, discovery_info=None):
|
||||
if discovery_info is not None:
|
||||
config = PLATFORM_SCHEMA(discovery_info)
|
||||
|
||||
|
@ -2,18 +2,23 @@
|
||||
import asyncio
|
||||
from unittest.mock import patch
|
||||
|
||||
from homeassistant.components import mqtt
|
||||
from homeassistant.components.mqtt.discovery import async_start, \
|
||||
ALREADY_DISCOVERED
|
||||
|
||||
from tests.common import async_fire_mqtt_message, mock_coro
|
||||
from tests.common import async_fire_mqtt_message, mock_coro, MockConfigEntry
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_subscribing_config_topic(hass, mqtt_mock):
|
||||
"""Test setting up discovery."""
|
||||
entry = MockConfigEntry(domain=mqtt.DOMAIN, data={
|
||||
mqtt.CONF_BROKER: 'test-broker'
|
||||
})
|
||||
|
||||
hass_config = {}
|
||||
discovery_topic = 'homeassistant'
|
||||
yield from async_start(hass, discovery_topic, hass_config)
|
||||
yield from async_start(hass, discovery_topic, hass_config, entry)
|
||||
|
||||
assert mqtt_mock.async_subscribe.called
|
||||
call_args = mqtt_mock.async_subscribe.mock_calls[0][1]
|
||||
@ -25,8 +30,12 @@ def test_subscribing_config_topic(hass, mqtt_mock):
|
||||
@asyncio.coroutine
|
||||
def test_invalid_topic(mock_load_platform, hass, mqtt_mock):
|
||||
"""Test sending to invalid topic."""
|
||||
entry = MockConfigEntry(domain=mqtt.DOMAIN, data={
|
||||
mqtt.CONF_BROKER: 'test-broker'
|
||||
})
|
||||
|
||||
mock_load_platform.return_value = mock_coro()
|
||||
yield from async_start(hass, 'homeassistant', {})
|
||||
yield from async_start(hass, 'homeassistant', {}, entry)
|
||||
|
||||
async_fire_mqtt_message(hass, 'homeassistant/binary_sensor/bla/not_config',
|
||||
'{}')
|
||||
@ -38,8 +47,12 @@ def test_invalid_topic(mock_load_platform, hass, mqtt_mock):
|
||||
@asyncio.coroutine
|
||||
def test_invalid_json(mock_load_platform, hass, mqtt_mock, caplog):
|
||||
"""Test sending in invalid JSON."""
|
||||
entry = MockConfigEntry(domain=mqtt.DOMAIN, data={
|
||||
mqtt.CONF_BROKER: 'test-broker'
|
||||
})
|
||||
|
||||
mock_load_platform.return_value = mock_coro()
|
||||
yield from async_start(hass, 'homeassistant', {})
|
||||
yield from async_start(hass, 'homeassistant', {}, entry)
|
||||
|
||||
async_fire_mqtt_message(hass, 'homeassistant/binary_sensor/bla/config',
|
||||
'not json')
|
||||
@ -52,10 +65,12 @@ def test_invalid_json(mock_load_platform, hass, mqtt_mock, caplog):
|
||||
@asyncio.coroutine
|
||||
def test_only_valid_components(mock_load_platform, hass, mqtt_mock, caplog):
|
||||
"""Test for a valid component."""
|
||||
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||
|
||||
invalid_component = "timer"
|
||||
|
||||
mock_load_platform.return_value = mock_coro()
|
||||
yield from async_start(hass, 'homeassistant', {})
|
||||
yield from async_start(hass, 'homeassistant', {}, entry)
|
||||
|
||||
async_fire_mqtt_message(hass, 'homeassistant/{}/bla/config'.format(
|
||||
invalid_component
|
||||
@ -73,7 +88,9 @@ def test_only_valid_components(mock_load_platform, hass, mqtt_mock, caplog):
|
||||
@asyncio.coroutine
|
||||
def test_correct_config_discovery(hass, mqtt_mock, caplog):
|
||||
"""Test sending in correct JSON."""
|
||||
yield from async_start(hass, 'homeassistant', {})
|
||||
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||
|
||||
yield from async_start(hass, 'homeassistant', {}, entry)
|
||||
|
||||
async_fire_mqtt_message(hass, 'homeassistant/binary_sensor/bla/config',
|
||||
'{ "name": "Beer" }')
|
||||
@ -89,7 +106,9 @@ def test_correct_config_discovery(hass, mqtt_mock, caplog):
|
||||
@asyncio.coroutine
|
||||
def test_discover_fan(hass, mqtt_mock, caplog):
|
||||
"""Test discovering an MQTT fan."""
|
||||
yield from async_start(hass, 'homeassistant', {})
|
||||
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||
|
||||
yield from async_start(hass, 'homeassistant', {}, entry)
|
||||
|
||||
async_fire_mqtt_message(hass, 'homeassistant/fan/bla/config',
|
||||
('{ "name": "Beer",'
|
||||
@ -106,7 +125,9 @@ def test_discover_fan(hass, mqtt_mock, caplog):
|
||||
@asyncio.coroutine
|
||||
def test_discover_climate(hass, mqtt_mock, caplog):
|
||||
"""Test discovering an MQTT climate component."""
|
||||
yield from async_start(hass, 'homeassistant', {})
|
||||
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||
|
||||
yield from async_start(hass, 'homeassistant', {}, entry)
|
||||
|
||||
data = (
|
||||
'{ "name": "ClimateTest",'
|
||||
@ -127,7 +148,9 @@ def test_discover_climate(hass, mqtt_mock, caplog):
|
||||
@asyncio.coroutine
|
||||
def test_discover_alarm_control_panel(hass, mqtt_mock, caplog):
|
||||
"""Test discovering an MQTT alarm control panel component."""
|
||||
yield from async_start(hass, 'homeassistant', {})
|
||||
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||
|
||||
yield from async_start(hass, 'homeassistant', {}, entry)
|
||||
|
||||
data = (
|
||||
'{ "name": "AlarmControlPanelTest",'
|
||||
@ -149,7 +172,9 @@ def test_discover_alarm_control_panel(hass, mqtt_mock, caplog):
|
||||
@asyncio.coroutine
|
||||
def test_discovery_incl_nodeid(hass, mqtt_mock, caplog):
|
||||
"""Test sending in correct JSON with optional node_id included."""
|
||||
yield from async_start(hass, 'homeassistant', {})
|
||||
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||
|
||||
yield from async_start(hass, 'homeassistant', {}, entry)
|
||||
|
||||
async_fire_mqtt_message(hass, 'homeassistant/binary_sensor/my_node_id/bla'
|
||||
'/config', '{ "name": "Beer" }')
|
||||
@ -165,7 +190,9 @@ def test_discovery_incl_nodeid(hass, mqtt_mock, caplog):
|
||||
@asyncio.coroutine
|
||||
def test_non_duplicate_discovery(hass, mqtt_mock, caplog):
|
||||
"""Test for a non duplicate component."""
|
||||
yield from async_start(hass, 'homeassistant', {})
|
||||
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||
|
||||
yield from async_start(hass, 'homeassistant', {}, entry)
|
||||
|
||||
async_fire_mqtt_message(hass, 'homeassistant/binary_sensor/bla/config',
|
||||
'{ "name": "Beer" }')
|
||||
|
@ -6,6 +6,7 @@ from unittest.mock import patch
|
||||
|
||||
import homeassistant.core as ha
|
||||
from homeassistant.setup import setup_component, async_setup_component
|
||||
from homeassistant.components import mqtt
|
||||
from homeassistant.components.mqtt.discovery import async_start
|
||||
import homeassistant.components.sensor as sensor
|
||||
from homeassistant.const import EVENT_STATE_CHANGED, STATE_UNAVAILABLE
|
||||
@ -13,7 +14,7 @@ import homeassistant.util.dt as dt_util
|
||||
|
||||
from tests.common import mock_mqtt_component, fire_mqtt_message, \
|
||||
assert_setup_component, async_fire_mqtt_message, \
|
||||
async_mock_mqtt_component
|
||||
async_mock_mqtt_component, MockConfigEntry
|
||||
from tests.common import get_test_home_assistant, mock_component
|
||||
|
||||
|
||||
@ -392,7 +393,8 @@ async def test_unique_id(hass):
|
||||
|
||||
async def test_discovery_removal_sensor(hass, mqtt_mock, caplog):
|
||||
"""Test removal of discovered sensor."""
|
||||
await async_start(hass, 'homeassistant', {})
|
||||
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||
await async_start(hass, 'homeassistant', {}, entry)
|
||||
data = (
|
||||
'{ "name": "Beer",'
|
||||
' "status_topic": "test_topic" }'
|
||||
|
Loading…
x
Reference in New Issue
Block a user