Support reloading the universal platform (#39248)
This commit is contained in:
parent
63ebea1706
commit
90842fcb84
18 changed files with 300 additions and 82 deletions
|
@ -2,65 +2,26 @@
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from homeassistant import config as conf_util
|
|
||||||
from homeassistant.const import SERVICE_RELOAD
|
from homeassistant.const import SERVICE_RELOAD
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.helpers.reload import async_reload_integration_platforms
|
||||||
from homeassistant.helpers import config_per_platform, entity_platform
|
|
||||||
from homeassistant.loader import async_get_integration
|
|
||||||
|
|
||||||
from .const import DOMAIN, EVENT_TEMPLATE_RELOADED, PLATFORM_STORAGE_KEY
|
from .const import DOMAIN, EVENT_TEMPLATE_RELOADED, PLATFORMS
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
async def _async_setup_reload_service(hass):
|
async def async_setup_reload_service(hass):
|
||||||
|
"""Create the reload service for the template domain."""
|
||||||
|
|
||||||
if hass.services.has_service(DOMAIN, SERVICE_RELOAD):
|
if hass.services.has_service(DOMAIN, SERVICE_RELOAD):
|
||||||
return
|
return
|
||||||
|
|
||||||
async def _reload_config(call):
|
async def _reload_config(call):
|
||||||
"""Reload the template platform config."""
|
"""Reload the template platform config."""
|
||||||
|
|
||||||
try:
|
await async_reload_integration_platforms(hass, DOMAIN, PLATFORMS)
|
||||||
unprocessed_conf = await conf_util.async_hass_config_yaml(hass)
|
|
||||||
except HomeAssistantError as err:
|
|
||||||
_LOGGER.error(err)
|
|
||||||
return
|
|
||||||
|
|
||||||
for platform in hass.data[PLATFORM_STORAGE_KEY]:
|
|
||||||
|
|
||||||
integration = await async_get_integration(hass, platform.domain)
|
|
||||||
|
|
||||||
conf = await conf_util.async_process_component_config(
|
|
||||||
hass, unprocessed_conf, integration
|
|
||||||
)
|
|
||||||
|
|
||||||
if not conf:
|
|
||||||
continue
|
|
||||||
|
|
||||||
await platform.async_reset()
|
|
||||||
|
|
||||||
# Extract only the config for template, ignore the rest.
|
|
||||||
for p_type, p_config in config_per_platform(conf, platform.domain):
|
|
||||||
if p_type != DOMAIN:
|
|
||||||
continue
|
|
||||||
|
|
||||||
entities = await platform.platform.async_create_entities(hass, p_config)
|
|
||||||
|
|
||||||
await platform.async_add_entities(entities)
|
|
||||||
|
|
||||||
hass.bus.async_fire(EVENT_TEMPLATE_RELOADED, context=call.context)
|
hass.bus.async_fire(EVENT_TEMPLATE_RELOADED, context=call.context)
|
||||||
|
|
||||||
hass.helpers.service.async_register_admin_service(
|
hass.helpers.service.async_register_admin_service(
|
||||||
DOMAIN, SERVICE_RELOAD, _reload_config
|
DOMAIN, SERVICE_RELOAD, _reload_config
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_platform_reloadable(hass):
|
|
||||||
"""Template platform with reloadability."""
|
|
||||||
|
|
||||||
await _async_setup_reload_service(hass)
|
|
||||||
|
|
||||||
platform = entity_platform.current_platform.get()
|
|
||||||
|
|
||||||
if platform not in hass.data.setdefault(PLATFORM_STORAGE_KEY, []):
|
|
||||||
hass.data[PLATFORM_STORAGE_KEY].append(platform)
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.entity import async_generate_entity_id
|
from homeassistant.helpers.entity import async_generate_entity_id
|
||||||
from homeassistant.helpers.script import Script
|
from homeassistant.helpers.script import Script
|
||||||
|
|
||||||
from . import async_setup_platform_reloadable
|
from . import async_setup_reload_service
|
||||||
from .template_entity import TemplateEntity
|
from .template_entity import TemplateEntity
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
@ -76,7 +76,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_create_entities(hass, config):
|
async def _async_create_entities(hass, config):
|
||||||
"""Create Template Alarm Control Panels."""
|
"""Create Template Alarm Control Panels."""
|
||||||
|
|
||||||
alarm_control_panels = []
|
alarm_control_panels = []
|
||||||
|
@ -112,8 +112,8 @@ async def async_create_entities(hass, config):
|
||||||
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 the Template Alarm Control Panels."""
|
"""Set up the Template Alarm Control Panels."""
|
||||||
|
|
||||||
await async_setup_platform_reloadable(hass)
|
await async_setup_reload_service(hass)
|
||||||
async_add_entities(await async_create_entities(hass, config))
|
async_add_entities(await _async_create_entities(hass, config))
|
||||||
|
|
||||||
|
|
||||||
class AlarmControlPanelTemplate(TemplateEntity, AlarmControlPanelEntity):
|
class AlarmControlPanelTemplate(TemplateEntity, AlarmControlPanelEntity):
|
||||||
|
|
|
@ -26,7 +26,7 @@ from homeassistant.helpers.entity import async_generate_entity_id
|
||||||
from homeassistant.helpers.event import async_call_later
|
from homeassistant.helpers.event import async_call_later
|
||||||
from homeassistant.helpers.template import result_as_boolean
|
from homeassistant.helpers.template import result_as_boolean
|
||||||
|
|
||||||
from . import async_setup_platform_reloadable
|
from . import async_setup_reload_service
|
||||||
from .const import CONF_AVAILABILITY_TEMPLATE
|
from .const import CONF_AVAILABILITY_TEMPLATE
|
||||||
from .template_entity import TemplateEntity
|
from .template_entity import TemplateEntity
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_create_entities(hass, config):
|
async def _async_create_entities(hass, config):
|
||||||
"""Create the template binary sensors."""
|
"""Create the template binary sensors."""
|
||||||
sensors = []
|
sensors = []
|
||||||
|
|
||||||
|
@ -97,8 +97,8 @@ async def async_create_entities(hass, config):
|
||||||
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 the template binary sensors."""
|
"""Set up the template binary sensors."""
|
||||||
|
|
||||||
await async_setup_platform_reloadable(hass)
|
await async_setup_reload_service(hass)
|
||||||
async_add_entities(await async_create_entities(hass, config))
|
async_add_entities(await _async_create_entities(hass, config))
|
||||||
|
|
||||||
|
|
||||||
class BinarySensorTemplate(TemplateEntity, BinarySensorEntity):
|
class BinarySensorTemplate(TemplateEntity, BinarySensorEntity):
|
||||||
|
|
|
@ -7,3 +7,15 @@ DOMAIN = "template"
|
||||||
PLATFORM_STORAGE_KEY = "template_platforms"
|
PLATFORM_STORAGE_KEY = "template_platforms"
|
||||||
|
|
||||||
EVENT_TEMPLATE_RELOADED = "event_template_reloaded"
|
EVENT_TEMPLATE_RELOADED = "event_template_reloaded"
|
||||||
|
|
||||||
|
PLATFORMS = [
|
||||||
|
"alarm_control_panel",
|
||||||
|
"binary_sensor",
|
||||||
|
"cover",
|
||||||
|
"fan",
|
||||||
|
"light",
|
||||||
|
"lock",
|
||||||
|
"sensor",
|
||||||
|
"switch",
|
||||||
|
"vacuum",
|
||||||
|
]
|
||||||
|
|
|
@ -37,7 +37,7 @@ import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.entity import async_generate_entity_id
|
from homeassistant.helpers.entity import async_generate_entity_id
|
||||||
from homeassistant.helpers.script import Script
|
from homeassistant.helpers.script import Script
|
||||||
|
|
||||||
from . import async_setup_platform_reloadable
|
from . import async_setup_reload_service
|
||||||
from .const import CONF_AVAILABILITY_TEMPLATE
|
from .const import CONF_AVAILABILITY_TEMPLATE
|
||||||
from .template_entity import TemplateEntity
|
from .template_entity import TemplateEntity
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_create_entities(hass, config):
|
async def _async_create_entities(hass, config):
|
||||||
"""Create the Template cover."""
|
"""Create the Template cover."""
|
||||||
covers = []
|
covers = []
|
||||||
|
|
||||||
|
@ -152,8 +152,8 @@ async def async_create_entities(hass, config):
|
||||||
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 the Template cover."""
|
"""Set up the Template cover."""
|
||||||
|
|
||||||
await async_setup_platform_reloadable(hass)
|
await async_setup_reload_service(hass)
|
||||||
async_add_entities(await async_create_entities(hass, config))
|
async_add_entities(await _async_create_entities(hass, config))
|
||||||
|
|
||||||
|
|
||||||
class CoverTemplate(TemplateEntity, CoverEntity):
|
class CoverTemplate(TemplateEntity, CoverEntity):
|
||||||
|
|
|
@ -34,7 +34,7 @@ import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.entity import async_generate_entity_id
|
from homeassistant.helpers.entity import async_generate_entity_id
|
||||||
from homeassistant.helpers.script import Script
|
from homeassistant.helpers.script import Script
|
||||||
|
|
||||||
from . import async_setup_platform_reloadable
|
from . import async_setup_reload_service
|
||||||
from .const import CONF_AVAILABILITY_TEMPLATE
|
from .const import CONF_AVAILABILITY_TEMPLATE
|
||||||
from .template_entity import TemplateEntity
|
from .template_entity import TemplateEntity
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_create_entities(hass, config):
|
async def _async_create_entities(hass, config):
|
||||||
"""Create the Template Fans."""
|
"""Create the Template Fans."""
|
||||||
fans = []
|
fans = []
|
||||||
|
|
||||||
|
@ -129,8 +129,8 @@ async def async_create_entities(hass, config):
|
||||||
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 the template fans."""
|
"""Set up the template fans."""
|
||||||
|
|
||||||
await async_setup_platform_reloadable(hass)
|
await async_setup_reload_service(hass)
|
||||||
async_add_entities(await async_create_entities(hass, config))
|
async_add_entities(await _async_create_entities(hass, config))
|
||||||
|
|
||||||
|
|
||||||
class TemplateFan(TemplateEntity, FanEntity):
|
class TemplateFan(TemplateEntity, FanEntity):
|
||||||
|
|
|
@ -33,7 +33,7 @@ from homeassistant.helpers.config_validation import PLATFORM_SCHEMA
|
||||||
from homeassistant.helpers.entity import async_generate_entity_id
|
from homeassistant.helpers.entity import async_generate_entity_id
|
||||||
from homeassistant.helpers.script import Script
|
from homeassistant.helpers.script import Script
|
||||||
|
|
||||||
from . import async_setup_platform_reloadable
|
from . import async_setup_reload_service
|
||||||
from .const import CONF_AVAILABILITY_TEMPLATE
|
from .const import CONF_AVAILABILITY_TEMPLATE
|
||||||
from .template_entity import TemplateEntity
|
from .template_entity import TemplateEntity
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_create_entities(hass, config):
|
async def _async_create_entities(hass, config):
|
||||||
"""Create the Template Lights."""
|
"""Create the Template Lights."""
|
||||||
lights = []
|
lights = []
|
||||||
|
|
||||||
|
@ -135,8 +135,8 @@ async def async_create_entities(hass, config):
|
||||||
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 the template lights."""
|
"""Set up the template lights."""
|
||||||
|
|
||||||
await async_setup_platform_reloadable(hass)
|
await async_setup_reload_service(hass)
|
||||||
async_add_entities(await async_create_entities(hass, config))
|
async_add_entities(await _async_create_entities(hass, config))
|
||||||
|
|
||||||
|
|
||||||
class LightTemplate(TemplateEntity, LightEntity):
|
class LightTemplate(TemplateEntity, LightEntity):
|
||||||
|
|
|
@ -17,7 +17,7 @@ from homeassistant.exceptions import TemplateError
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.script import Script
|
from homeassistant.helpers.script import Script
|
||||||
|
|
||||||
from . import async_setup_platform_reloadable
|
from . import async_setup_reload_service
|
||||||
from .const import CONF_AVAILABILITY_TEMPLATE
|
from .const import CONF_AVAILABILITY_TEMPLATE
|
||||||
from .template_entity import TemplateEntity
|
from .template_entity import TemplateEntity
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_create_entities(hass, config):
|
async def _async_create_entities(hass, config):
|
||||||
"""Create the Template lock."""
|
"""Create the Template lock."""
|
||||||
device = config.get(CONF_NAME)
|
device = config.get(CONF_NAME)
|
||||||
value_template = config.get(CONF_VALUE_TEMPLATE)
|
value_template = config.get(CONF_VALUE_TEMPLATE)
|
||||||
|
@ -65,8 +65,8 @@ async def async_create_entities(hass, config):
|
||||||
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 the template lock."""
|
"""Set up the template lock."""
|
||||||
|
|
||||||
await async_setup_platform_reloadable(hass)
|
await async_setup_reload_service(hass)
|
||||||
async_add_entities(await async_create_entities(hass, config))
|
async_add_entities(await _async_create_entities(hass, config))
|
||||||
|
|
||||||
|
|
||||||
class TemplateLock(TemplateEntity, LockEntity):
|
class TemplateLock(TemplateEntity, LockEntity):
|
||||||
|
|
|
@ -26,7 +26,7 @@ from homeassistant.exceptions import TemplateError
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.entity import Entity, async_generate_entity_id
|
from homeassistant.helpers.entity import Entity, async_generate_entity_id
|
||||||
|
|
||||||
from . import async_setup_platform_reloadable
|
from . import async_setup_reload_service
|
||||||
from .const import CONF_AVAILABILITY_TEMPLATE
|
from .const import CONF_AVAILABILITY_TEMPLATE
|
||||||
from .template_entity import TemplateEntity
|
from .template_entity import TemplateEntity
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_create_entities(hass, config):
|
async def _async_create_entities(hass, config):
|
||||||
"""Create the template sensors."""
|
"""Create the template sensors."""
|
||||||
|
|
||||||
sensors = []
|
sensors = []
|
||||||
|
@ -97,8 +97,8 @@ async def async_create_entities(hass, config):
|
||||||
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 the template sensors."""
|
"""Set up the template sensors."""
|
||||||
|
|
||||||
await async_setup_platform_reloadable(hass)
|
await async_setup_reload_service(hass)
|
||||||
async_add_entities(await async_create_entities(hass, config))
|
async_add_entities(await _async_create_entities(hass, config))
|
||||||
|
|
||||||
|
|
||||||
class SensorTemplate(TemplateEntity, Entity):
|
class SensorTemplate(TemplateEntity, Entity):
|
||||||
|
|
|
@ -26,7 +26,7 @@ from homeassistant.helpers.entity import async_generate_entity_id
|
||||||
from homeassistant.helpers.restore_state import RestoreEntity
|
from homeassistant.helpers.restore_state import RestoreEntity
|
||||||
from homeassistant.helpers.script import Script
|
from homeassistant.helpers.script import Script
|
||||||
|
|
||||||
from . import async_setup_platform_reloadable
|
from . import async_setup_reload_service
|
||||||
from .const import CONF_AVAILABILITY_TEMPLATE
|
from .const import CONF_AVAILABILITY_TEMPLATE
|
||||||
from .template_entity import TemplateEntity
|
from .template_entity import TemplateEntity
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_create_entities(hass, config):
|
async def _async_create_entities(hass, config):
|
||||||
"""Create the Template switches."""
|
"""Create the Template switches."""
|
||||||
switches = []
|
switches = []
|
||||||
|
|
||||||
|
@ -90,8 +90,8 @@ async def async_create_entities(hass, config):
|
||||||
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 the template switches."""
|
"""Set up the template switches."""
|
||||||
|
|
||||||
await async_setup_platform_reloadable(hass)
|
await async_setup_reload_service(hass)
|
||||||
async_add_entities(await async_create_entities(hass, config))
|
async_add_entities(await _async_create_entities(hass, config))
|
||||||
|
|
||||||
|
|
||||||
class SwitchTemplate(TemplateEntity, SwitchEntity, RestoreEntity):
|
class SwitchTemplate(TemplateEntity, SwitchEntity, RestoreEntity):
|
||||||
|
|
|
@ -43,7 +43,7 @@ import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.entity import async_generate_entity_id
|
from homeassistant.helpers.entity import async_generate_entity_id
|
||||||
from homeassistant.helpers.script import Script
|
from homeassistant.helpers.script import Script
|
||||||
|
|
||||||
from . import async_setup_platform_reloadable
|
from . import async_setup_reload_service
|
||||||
from .const import CONF_AVAILABILITY_TEMPLATE
|
from .const import CONF_AVAILABILITY_TEMPLATE
|
||||||
from .template_entity import TemplateEntity
|
from .template_entity import TemplateEntity
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_create_entities(hass, config):
|
async def _async_create_entities(hass, config):
|
||||||
"""Create the Template Vacuums."""
|
"""Create the Template Vacuums."""
|
||||||
vacuums = []
|
vacuums = []
|
||||||
|
|
||||||
|
@ -145,8 +145,8 @@ async def async_create_entities(hass, config):
|
||||||
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 the template vacuums."""
|
"""Set up the template vacuums."""
|
||||||
|
|
||||||
await async_setup_platform_reloadable(hass)
|
await async_setup_reload_service(hass)
|
||||||
async_add_entities(await async_create_entities(hass, config))
|
async_add_entities(await _async_create_entities(hass, config))
|
||||||
|
|
||||||
|
|
||||||
class TemplateVacuum(TemplateEntity, StateVacuumEntity):
|
class TemplateVacuum(TemplateEntity, StateVacuumEntity):
|
||||||
|
|
|
@ -56,6 +56,7 @@ from homeassistant.const import (
|
||||||
SERVICE_MEDIA_PREVIOUS_TRACK,
|
SERVICE_MEDIA_PREVIOUS_TRACK,
|
||||||
SERVICE_MEDIA_SEEK,
|
SERVICE_MEDIA_SEEK,
|
||||||
SERVICE_MEDIA_STOP,
|
SERVICE_MEDIA_STOP,
|
||||||
|
SERVICE_RELOAD,
|
||||||
SERVICE_SHUFFLE_SET,
|
SERVICE_SHUFFLE_SET,
|
||||||
SERVICE_TURN_OFF,
|
SERVICE_TURN_OFF,
|
||||||
SERVICE_TURN_ON,
|
SERVICE_TURN_ON,
|
||||||
|
@ -71,6 +72,7 @@ from homeassistant.const import (
|
||||||
from homeassistant.core import EVENT_HOMEASSISTANT_START, callback
|
from homeassistant.core import EVENT_HOMEASSISTANT_START, callback
|
||||||
from homeassistant.exceptions import TemplateError
|
from homeassistant.exceptions import TemplateError
|
||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
|
from homeassistant.helpers.reload import async_reload_integration_platforms
|
||||||
from homeassistant.helpers.service import async_call_from_config
|
from homeassistant.helpers.service import async_call_from_config
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
@ -102,9 +104,31 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||||
extra=vol.REMOVE_EXTRA,
|
extra=vol.REMOVE_EXTRA,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
EVENT_UNIVERSAL_RELOADED = "event_universal_reloaded"
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_reload_service(hass):
|
||||||
|
"""Create the reload service for the universal domain."""
|
||||||
|
|
||||||
|
if hass.services.has_service("universal", SERVICE_RELOAD):
|
||||||
|
return
|
||||||
|
|
||||||
|
async def _reload_config(call):
|
||||||
|
"""Reload the template universal config."""
|
||||||
|
|
||||||
|
await async_reload_integration_platforms(hass, "universal", ["media_player"])
|
||||||
|
hass.bus.async_fire(EVENT_UNIVERSAL_RELOADED, context=call.context)
|
||||||
|
|
||||||
|
hass.helpers.service.async_register_admin_service(
|
||||||
|
"universal", SERVICE_RELOAD, _reload_config
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
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 the universal media players."""
|
"""Set up the universal media players."""
|
||||||
|
|
||||||
|
await async_setup_reload_service(hass)
|
||||||
|
|
||||||
player = UniversalMediaPlayer(
|
player = UniversalMediaPlayer(
|
||||||
hass,
|
hass,
|
||||||
config.get(CONF_NAME),
|
config.get(CONF_NAME),
|
||||||
|
@ -157,7 +181,6 @@ class UniversalMediaPlayer(MediaPlayerEntity):
|
||||||
result = self.hass.helpers.event.async_track_template_result(
|
result = self.hass.helpers.event.async_track_template_result(
|
||||||
self._state_template, _async_on_template_update
|
self._state_template, _async_on_template_update
|
||||||
)
|
)
|
||||||
|
|
||||||
self.hass.bus.async_listen_once(
|
self.hass.bus.async_listen_once(
|
||||||
EVENT_HOMEASSISTANT_START, callback(lambda _: result.async_refresh())
|
EVENT_HOMEASSISTANT_START, callback(lambda _: result.async_refresh())
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
reload:
|
||||||
|
description: Reload all universal entities.
|
70
homeassistant/helpers/reload.py
Normal file
70
homeassistant/helpers/reload.py
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
"""Class to reload platforms."""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from homeassistant import config as conf_util
|
||||||
|
from homeassistant.core import callback
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
|
from homeassistant.helpers import config_per_platform
|
||||||
|
from homeassistant.helpers.entity_platform import DATA_ENTITY_PLATFORM, EntityPlatform
|
||||||
|
from homeassistant.helpers.typing import HomeAssistantType
|
||||||
|
from homeassistant.loader import async_get_integration
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_reload_integration_platforms(
|
||||||
|
hass: HomeAssistantType, integration_name: str, integration_platforms: str
|
||||||
|
) -> None:
|
||||||
|
"""Reload an integration's platforms.
|
||||||
|
|
||||||
|
The platform must support being re-setup.
|
||||||
|
|
||||||
|
This functionality is only intended to be used for integrations that process
|
||||||
|
Home Assistant data and make this available to other integrations.
|
||||||
|
|
||||||
|
Examples are template, stats, derivative, utility meter.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
unprocessed_conf = await conf_util.async_hass_config_yaml(hass)
|
||||||
|
except HomeAssistantError as err:
|
||||||
|
_LOGGER.error(err)
|
||||||
|
return
|
||||||
|
|
||||||
|
for integration_platform in integration_platforms:
|
||||||
|
platform = async_get_platform(hass, integration_name, integration_platform)
|
||||||
|
|
||||||
|
if not platform:
|
||||||
|
continue
|
||||||
|
|
||||||
|
integration = await async_get_integration(hass, integration_platform)
|
||||||
|
|
||||||
|
conf = await conf_util.async_process_component_config(
|
||||||
|
hass, unprocessed_conf, integration
|
||||||
|
)
|
||||||
|
|
||||||
|
if not conf:
|
||||||
|
continue
|
||||||
|
|
||||||
|
await platform.async_reset()
|
||||||
|
|
||||||
|
# Extract only the config for template, ignore the rest.
|
||||||
|
for p_type, p_config in config_per_platform(conf, integration_platform):
|
||||||
|
if p_type != integration_name:
|
||||||
|
continue
|
||||||
|
|
||||||
|
await platform.async_setup(p_config) # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_get_platform(
|
||||||
|
hass: HomeAssistantType, integration_name: str, integration_platform_name: str
|
||||||
|
) -> Optional[EntityPlatform]:
|
||||||
|
"""Find an existing platform."""
|
||||||
|
for integration_platform in hass.data[DATA_ENTITY_PLATFORM][integration_name]:
|
||||||
|
if integration_platform.domain == integration_platform_name:
|
||||||
|
platform: EntityPlatform = integration_platform
|
||||||
|
return platform
|
||||||
|
|
||||||
|
return None
|
|
@ -1,10 +1,13 @@
|
||||||
"""The tests for the Universal Media player platform."""
|
"""The tests for the Universal Media player platform."""
|
||||||
import asyncio
|
import asyncio
|
||||||
from copy import copy
|
from copy import copy
|
||||||
|
from os import path
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
from asynctest.mock import patch
|
||||||
from voluptuous.error import MultipleInvalid
|
from voluptuous.error import MultipleInvalid
|
||||||
|
|
||||||
|
from homeassistant import config as hass_config
|
||||||
import homeassistant.components.input_number as input_number
|
import homeassistant.components.input_number as input_number
|
||||||
import homeassistant.components.input_select as input_select
|
import homeassistant.components.input_select as input_select
|
||||||
import homeassistant.components.media_player as media_player
|
import homeassistant.components.media_player as media_player
|
||||||
|
@ -812,3 +815,64 @@ async def test_master_state_with_template(hass):
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
hass.states.get("media_player.tv").state == STATE_OFF
|
hass.states.get("media_player.tv").state == STATE_OFF
|
||||||
|
|
||||||
|
|
||||||
|
async def test_reload(hass):
|
||||||
|
"""Test the state_template option."""
|
||||||
|
hass.states.async_set("input_boolean.test", STATE_OFF)
|
||||||
|
hass.states.async_set("media_player.mock1", STATE_OFF)
|
||||||
|
|
||||||
|
templ = (
|
||||||
|
'{% if states.input_boolean.test.state == "off" %}on'
|
||||||
|
"{% else %}{{ states.media_player.mock1.state }}{% endif %}"
|
||||||
|
)
|
||||||
|
|
||||||
|
await async_setup_component(
|
||||||
|
hass,
|
||||||
|
"media_player",
|
||||||
|
{
|
||||||
|
"media_player": {
|
||||||
|
"platform": "universal",
|
||||||
|
"name": "tv",
|
||||||
|
"state_template": templ,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(hass.states.async_all()) == 3
|
||||||
|
await hass.async_start()
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
hass.states.get("media_player.tv").state == STATE_ON
|
||||||
|
|
||||||
|
hass.states.async_set("input_boolean.test", STATE_ON)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
hass.states.get("media_player.tv").state == STATE_OFF
|
||||||
|
|
||||||
|
hass.states.async_set("media_player.master_bedroom_2", STATE_OFF)
|
||||||
|
hass.states.async_set(
|
||||||
|
"remote.alexander_master_bedroom",
|
||||||
|
STATE_ON,
|
||||||
|
{"activity_list": ["act1", "act2"], "current_activity": "act2"},
|
||||||
|
)
|
||||||
|
|
||||||
|
yaml_path = path.join(
|
||||||
|
_get_fixtures_base_path(), "fixtures", "universal/configuration.yaml",
|
||||||
|
)
|
||||||
|
with patch.object(hass_config, "YAML_CONFIG_FILE", yaml_path):
|
||||||
|
await hass.services.async_call(
|
||||||
|
"universal", universal.SERVICE_RELOAD, {}, blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert len(hass.states.async_all()) == 5
|
||||||
|
|
||||||
|
assert hass.states.get("media_player.tv") is None
|
||||||
|
assert hass.states.get("media_player.master_bed_tv").state == "on"
|
||||||
|
assert hass.states.get("media_player.master_bed_tv").attributes["source"] == "act2"
|
||||||
|
|
||||||
|
|
||||||
|
def _get_fixtures_base_path():
|
||||||
|
return path.dirname(path.dirname(path.dirname(__file__)))
|
||||||
|
|
14
tests/fixtures/helpers/reload_configuration.yaml
vendored
Normal file
14
tests/fixtures/helpers/reload_configuration.yaml
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
test_domain:
|
||||||
|
- platform: test_platform
|
||||||
|
sensors:
|
||||||
|
combined_sensor_energy_usage:
|
||||||
|
friendly_name: Combined Sense Energy Usage
|
||||||
|
unit_of_measurement: kW
|
||||||
|
value_template: '{{ ((states(''sensor.energy_usage'') | float) + (states(''sensor.energy_usage_2'')
|
||||||
|
| float)) / 1000 }}'
|
||||||
|
watching_tv_in_master_bedroom:
|
||||||
|
friendly_name: Watching TV in Master Bedroom
|
||||||
|
value_template: '{% if state_attr("remote.alexander_master_bedroom","current_activity")
|
||||||
|
== "Watch TV" or state_attr("remote.alexander_master_bedroom","current_activity")
|
||||||
|
== "Watch Apple TV" %}on{% else %}off{% endif %}'
|
||||||
|
|
9
tests/fixtures/universal/configuration.yaml
vendored
Normal file
9
tests/fixtures/universal/configuration.yaml
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
media_player:
|
||||||
|
- platform: universal
|
||||||
|
name: Master Bed TV
|
||||||
|
children:
|
||||||
|
- media_player.master_bedroom_2
|
||||||
|
attributes:
|
||||||
|
state: remote.alexander_master_bedroom
|
||||||
|
source_list: remote.alexander_master_bedroom|activity_list
|
||||||
|
source: remote.alexander_master_bedroom|current_activity
|
63
tests/helpers/test_reload.py
Normal file
63
tests/helpers/test_reload.py
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
"""Tests for the reload helper."""
|
||||||
|
import logging
|
||||||
|
from os import path
|
||||||
|
|
||||||
|
from homeassistant import config
|
||||||
|
from homeassistant.helpers.entity_component import EntityComponent
|
||||||
|
from homeassistant.helpers.reload import (
|
||||||
|
async_get_platform,
|
||||||
|
async_reload_integration_platforms,
|
||||||
|
)
|
||||||
|
|
||||||
|
from tests.async_mock import Mock, patch
|
||||||
|
from tests.common import (
|
||||||
|
MockModule,
|
||||||
|
MockPlatform,
|
||||||
|
mock_entity_platform,
|
||||||
|
mock_integration,
|
||||||
|
)
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
DOMAIN = "test_domain"
|
||||||
|
PLATFORM = "test_platform"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_reload_platform(hass):
|
||||||
|
"""Test the polling of only updated entities."""
|
||||||
|
component_setup = Mock(return_value=True)
|
||||||
|
|
||||||
|
setup_called = []
|
||||||
|
|
||||||
|
async def setup_platform(*args):
|
||||||
|
setup_called.append(args)
|
||||||
|
|
||||||
|
mock_integration(hass, MockModule(DOMAIN, setup=component_setup))
|
||||||
|
mock_integration(hass, MockModule(PLATFORM, dependencies=[DOMAIN]))
|
||||||
|
|
||||||
|
mock_platform = MockPlatform(async_setup_platform=setup_platform)
|
||||||
|
mock_entity_platform(hass, f"{DOMAIN}.{PLATFORM}", mock_platform)
|
||||||
|
|
||||||
|
component = EntityComponent(_LOGGER, DOMAIN, hass)
|
||||||
|
|
||||||
|
await component.async_setup({DOMAIN: {"platform": PLATFORM, "sensors": None}})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert component_setup.called
|
||||||
|
|
||||||
|
assert f"{DOMAIN}.{PLATFORM}" in hass.config.components
|
||||||
|
assert len(setup_called) == 1
|
||||||
|
|
||||||
|
platform = async_get_platform(hass, PLATFORM, DOMAIN)
|
||||||
|
assert platform.platform_name == PLATFORM
|
||||||
|
assert platform.domain == DOMAIN
|
||||||
|
|
||||||
|
yaml_path = path.join(
|
||||||
|
_get_fixtures_base_path(), "fixtures", "helpers/reload_configuration.yaml",
|
||||||
|
)
|
||||||
|
with patch.object(config, "YAML_CONFIG_FILE", yaml_path):
|
||||||
|
await async_reload_integration_platforms(hass, PLATFORM, [DOMAIN])
|
||||||
|
|
||||||
|
assert len(setup_called) == 2
|
||||||
|
|
||||||
|
|
||||||
|
def _get_fixtures_base_path():
|
||||||
|
return path.dirname(path.dirname(__file__))
|
Loading…
Add table
Reference in a new issue