Support reloading mqtt yaml configuration (#39531)

This commit is contained in:
J. Nick Koston 2020-09-02 20:16:21 -05:00 committed by GitHub
parent 56e76a3265
commit 65e53b8251
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 107 additions and 1 deletions

View file

@ -136,6 +136,20 @@ CONNECTION_FAILED_RECOVERABLE = "connection_failed_recoverable"
DISCOVERY_COOLDOWN = 2 DISCOVERY_COOLDOWN = 2
TIMEOUT_ACK = 1 TIMEOUT_ACK = 1
PLATFORMS = [
"alarm_control_panel",
"binary_sensor",
"camera",
"climate",
"cover",
"fan",
"light",
"lock",
"sensor",
"switch",
"vacuum",
]
def validate_device_has_at_least_one_identifier(value: ConfigType) -> ConfigType: def validate_device_has_at_least_one_identifier(value: ConfigType) -> ConfigType:
"""Validate that a device info entry has at least one identifying value.""" """Validate that a device info entry has at least one identifying value."""

View file

@ -31,6 +31,7 @@ from homeassistant.const import (
from homeassistant.core import callback from homeassistant.core import callback
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
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.typing import ConfigType, HomeAssistantType from homeassistant.helpers.typing import ConfigType, HomeAssistantType
from . import ( from . import (
@ -39,6 +40,8 @@ from . import (
CONF_QOS, CONF_QOS,
CONF_RETAIN, CONF_RETAIN,
CONF_STATE_TOPIC, CONF_STATE_TOPIC,
DOMAIN,
PLATFORMS,
MqttAttributes, MqttAttributes,
MqttAvailability, MqttAvailability,
MqttDiscoveryUpdate, MqttDiscoveryUpdate,
@ -100,6 +103,7 @@ async def async_setup_platform(
hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info=None hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info=None
): ):
"""Set up MQTT alarm control panel through configuration.yaml.""" """Set up MQTT alarm control panel through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(config, async_add_entities) await _async_setup_entity(config, async_add_entities)

View file

@ -24,6 +24,7 @@ import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
import homeassistant.helpers.event as evt import homeassistant.helpers.event as evt
from homeassistant.helpers.event import async_track_point_in_utc_time from homeassistant.helpers.event import async_track_point_in_utc_time
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.typing import ConfigType, HomeAssistantType from homeassistant.helpers.typing import ConfigType, HomeAssistantType
from homeassistant.util import dt as dt_util from homeassistant.util import dt as dt_util
@ -31,6 +32,8 @@ from . import (
ATTR_DISCOVERY_HASH, ATTR_DISCOVERY_HASH,
CONF_QOS, CONF_QOS,
CONF_STATE_TOPIC, CONF_STATE_TOPIC,
DOMAIN,
PLATFORMS,
MqttAttributes, MqttAttributes,
MqttAvailability, MqttAvailability,
MqttDiscoveryUpdate, MqttDiscoveryUpdate,
@ -72,6 +75,7 @@ async def async_setup_platform(
hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info=None hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info=None
): ):
"""Set up MQTT binary sensor through configuration.yaml.""" """Set up MQTT binary sensor through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(config, async_add_entities) await _async_setup_entity(config, async_add_entities)

View file

@ -9,11 +9,14 @@ from homeassistant.const import CONF_DEVICE, CONF_NAME, CONF_UNIQUE_ID
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.helpers import config_validation as cv from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.typing import ConfigType, HomeAssistantType from homeassistant.helpers.typing import ConfigType, HomeAssistantType
from . import ( from . import (
ATTR_DISCOVERY_HASH, ATTR_DISCOVERY_HASH,
CONF_QOS, CONF_QOS,
DOMAIN,
PLATFORMS,
MqttAttributes, MqttAttributes,
MqttAvailability, MqttAvailability,
MqttDiscoveryUpdate, MqttDiscoveryUpdate,
@ -46,6 +49,7 @@ async def async_setup_platform(
hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info=None hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info=None
): ):
"""Set up MQTT camera through configuration.yaml.""" """Set up MQTT camera through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(config, async_add_entities) await _async_setup_entity(config, async_add_entities)

View file

@ -48,13 +48,16 @@ from homeassistant.const import (
from homeassistant.core import callback from homeassistant.core import callback
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
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.typing import ConfigType, HomeAssistantType from homeassistant.helpers.typing import ConfigType, HomeAssistantType
from . import ( from . import (
ATTR_DISCOVERY_HASH, ATTR_DISCOVERY_HASH,
CONF_QOS, CONF_QOS,
CONF_RETAIN, CONF_RETAIN,
DOMAIN,
MQTT_BASE_PLATFORM_SCHEMA, MQTT_BASE_PLATFORM_SCHEMA,
PLATFORMS,
MqttAttributes, MqttAttributes,
MqttAvailability, MqttAvailability,
MqttDiscoveryUpdate, MqttDiscoveryUpdate,
@ -239,6 +242,7 @@ async def async_setup_platform(
hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info=None hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info=None
): ):
"""Set up MQTT climate device through configuration.yaml.""" """Set up MQTT climate device through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(hass, config, async_add_entities) await _async_setup_entity(hass, config, async_add_entities)

View file

@ -34,6 +34,7 @@ from homeassistant.const import (
from homeassistant.core import callback from homeassistant.core import callback
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
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.typing import ConfigType, HomeAssistantType from homeassistant.helpers.typing import ConfigType, HomeAssistantType
from . import ( from . import (
@ -42,6 +43,8 @@ from . import (
CONF_QOS, CONF_QOS,
CONF_RETAIN, CONF_RETAIN,
CONF_STATE_TOPIC, CONF_STATE_TOPIC,
DOMAIN,
PLATFORMS,
MqttAttributes, MqttAttributes,
MqttAvailability, MqttAvailability,
MqttDiscoveryUpdate, MqttDiscoveryUpdate,
@ -170,6 +173,7 @@ async def async_setup_platform(
hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info=None hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info=None
): ):
"""Set up MQTT cover through configuration.yaml.""" """Set up MQTT cover through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(config, async_add_entities) await _async_setup_entity(config, async_add_entities)

View file

@ -26,6 +26,7 @@ from homeassistant.const import (
from homeassistant.core import callback from homeassistant.core import callback
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
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.typing import ConfigType, HomeAssistantType from homeassistant.helpers.typing import ConfigType, HomeAssistantType
from . import ( from . import (
@ -34,6 +35,8 @@ from . import (
CONF_QOS, CONF_QOS,
CONF_RETAIN, CONF_RETAIN,
CONF_STATE_TOPIC, CONF_STATE_TOPIC,
DOMAIN,
PLATFORMS,
MqttAttributes, MqttAttributes,
MqttAvailability, MqttAvailability,
MqttDiscoveryUpdate, MqttDiscoveryUpdate,
@ -111,6 +114,7 @@ async def async_setup_platform(
hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info=None hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info=None
): ):
"""Set up MQTT fan through configuration.yaml.""" """Set up MQTT fan through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(config, async_add_entities) await _async_setup_entity(config, async_add_entities)

View file

@ -10,8 +10,10 @@ from homeassistant.components.mqtt.discovery import (
clear_discovery_hash, clear_discovery_hash,
) )
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.typing import ConfigType, HomeAssistantType from homeassistant.helpers.typing import ConfigType, HomeAssistantType
from .. import DOMAIN, PLATFORMS
from .schema import CONF_SCHEMA, MQTT_LIGHT_SCHEMA_SCHEMA from .schema import CONF_SCHEMA, MQTT_LIGHT_SCHEMA_SCHEMA
from .schema_basic import PLATFORM_SCHEMA_BASIC, async_setup_entity_basic from .schema_basic import PLATFORM_SCHEMA_BASIC, async_setup_entity_basic
from .schema_json import PLATFORM_SCHEMA_JSON, async_setup_entity_json from .schema_json import PLATFORM_SCHEMA_JSON, async_setup_entity_json
@ -39,6 +41,7 @@ async def async_setup_platform(
hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info=None hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info=None
): ):
"""Set up MQTT light through configuration.yaml.""" """Set up MQTT light through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(hass, config, async_add_entities) await _async_setup_entity(hass, config, async_add_entities)

View file

@ -15,6 +15,7 @@ from homeassistant.const import (
from homeassistant.core import callback from homeassistant.core import callback
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
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.typing import ConfigType, HomeAssistantType from homeassistant.helpers.typing import ConfigType, HomeAssistantType
from . import ( from . import (
@ -23,6 +24,8 @@ from . import (
CONF_QOS, CONF_QOS,
CONF_RETAIN, CONF_RETAIN,
CONF_STATE_TOPIC, CONF_STATE_TOPIC,
DOMAIN,
PLATFORMS,
MqttAttributes, MqttAttributes,
MqttAvailability, MqttAvailability,
MqttDiscoveryUpdate, MqttDiscoveryUpdate,
@ -73,6 +76,7 @@ async def async_setup_platform(
hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info=None hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info=None
): ):
"""Set up MQTT lock panel through configuration.yaml.""" """Set up MQTT lock panel through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(config, async_add_entities) await _async_setup_entity(config, async_add_entities)

View file

@ -22,6 +22,7 @@ import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
from homeassistant.helpers.event import async_track_point_in_utc_time from homeassistant.helpers.event import async_track_point_in_utc_time
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.typing import ConfigType, HomeAssistantType from homeassistant.helpers.typing import ConfigType, HomeAssistantType
from homeassistant.util import dt as dt_util from homeassistant.util import dt as dt_util
@ -29,6 +30,8 @@ from . import (
ATTR_DISCOVERY_HASH, ATTR_DISCOVERY_HASH,
CONF_QOS, CONF_QOS,
CONF_STATE_TOPIC, CONF_STATE_TOPIC,
DOMAIN,
PLATFORMS,
MqttAttributes, MqttAttributes,
MqttAvailability, MqttAvailability,
MqttDiscoveryUpdate, MqttDiscoveryUpdate,
@ -66,6 +69,7 @@ async def async_setup_platform(
hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info=None hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info=None
): ):
"""Set up MQTT sensors through configuration.yaml.""" """Set up MQTT sensors through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(config, async_add_entities) await _async_setup_entity(config, async_add_entities)

View file

@ -35,3 +35,6 @@ dump:
description: how long we should listen for messages in seconds description: how long we should listen for messages in seconds
example: 5 example: 5
default: 5 default: 5
reload:
description: Reload all mqtt entities from yaml.

View file

@ -19,6 +19,7 @@ from homeassistant.const import (
from homeassistant.core import callback from homeassistant.core import callback
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
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.restore_state import RestoreEntity from homeassistant.helpers.restore_state import RestoreEntity
from homeassistant.helpers.typing import ConfigType, HomeAssistantType from homeassistant.helpers.typing import ConfigType, HomeAssistantType
@ -28,6 +29,8 @@ from . import (
CONF_QOS, CONF_QOS,
CONF_RETAIN, CONF_RETAIN,
CONF_STATE_TOPIC, CONF_STATE_TOPIC,
DOMAIN,
PLATFORMS,
MqttAttributes, MqttAttributes,
MqttAvailability, MqttAvailability,
MqttDiscoveryUpdate, MqttDiscoveryUpdate,
@ -69,6 +72,7 @@ async def async_setup_platform(
hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info=None hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info=None
): ):
"""Set up MQTT switch through configuration.yaml.""" """Set up MQTT switch through configuration.yaml."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
await _async_setup_entity(config, async_add_entities, discovery_info) await _async_setup_entity(config, async_add_entities, discovery_info)

View file

@ -10,7 +10,9 @@ from homeassistant.components.mqtt.discovery import (
) )
from homeassistant.components.vacuum import DOMAIN from homeassistant.components.vacuum import DOMAIN
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.reload import async_setup_reload_service
from .. import DOMAIN as MQTT_DOMAIN, PLATFORMS
from .schema import CONF_SCHEMA, LEGACY, MQTT_VACUUM_SCHEMA, STATE from .schema import CONF_SCHEMA, LEGACY, MQTT_VACUUM_SCHEMA, STATE
from .schema_legacy import PLATFORM_SCHEMA_LEGACY, async_setup_entity_legacy from .schema_legacy import PLATFORM_SCHEMA_LEGACY, async_setup_entity_legacy
from .schema_state import PLATFORM_SCHEMA_STATE, async_setup_entity_state from .schema_state import PLATFORM_SCHEMA_STATE, async_setup_entity_state
@ -31,6 +33,7 @@ PLATFORM_SCHEMA = vol.All(
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Set up MQTT vacuum through configuration.yaml.""" """Set up MQTT vacuum through configuration.yaml."""
await async_setup_reload_service(hass, MQTT_DOMAIN, PLATFORMS)
await _async_setup_entity(config, async_add_entities, discovery_info) await _async_setup_entity(config, async_add_entities, discovery_info)

View file

@ -153,11 +153,14 @@ light:
payload_off: "off" payload_off: "off"
""" """
from os import path
import pytest import pytest
from homeassistant import config as hass_config
from homeassistant.components import light, mqtt from homeassistant.components import light, mqtt
from homeassistant.components.mqtt.discovery import async_start from homeassistant.components.mqtt.discovery import async_start
from homeassistant.const import ATTR_ASSUMED_STATE, STATE_OFF, STATE_ON from homeassistant.const import ATTR_ASSUMED_STATE, SERVICE_RELOAD, STATE_OFF, STATE_ON
import homeassistant.core as ha import homeassistant.core as ha
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
@ -1558,3 +1561,43 @@ async def test_max_mireds(hass, mqtt_mock):
state = hass.states.get("light.test") state = hass.states.get("light.test")
assert state.attributes.get("min_mireds") == 153 assert state.attributes.get("min_mireds") == 153
assert state.attributes.get("max_mireds") == 370 assert state.attributes.get("max_mireds") == 370
async def test_reloadable(hass, mqtt_mock):
"""Test reloading an mqtt light."""
config = {
light.DOMAIN: {
"platform": "mqtt",
"name": "test",
"command_topic": "test/set",
}
}
assert await async_setup_component(hass, light.DOMAIN, config)
await hass.async_block_till_done()
assert hass.states.get("light.test")
assert len(hass.states.async_all()) == 1
yaml_path = path.join(
_get_fixtures_base_path(),
"fixtures",
"mqtt/configuration.yaml",
)
with patch.object(hass_config, "YAML_CONFIG_FILE", yaml_path):
await hass.services.async_call(
"mqtt",
SERVICE_RELOAD,
{},
blocking=True,
)
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 1
assert hass.states.get("light.test") is None
assert hass.states.get("light.reload")
def _get_fixtures_base_path():
return path.dirname(path.dirname(path.dirname(__file__)))

View file

@ -0,0 +1,4 @@
light:
- platform: mqtt
name: reload
command_topic: "test/set"