Fix reload service in Command Line (#94436)
* Fix reload in Command Line * Add read new yaml
This commit is contained in:
parent
f931cc3d1c
commit
bd74f03d0b
5 changed files with 101 additions and 58 deletions
|
@ -46,12 +46,15 @@ from homeassistant.const import (
|
||||||
CONF_UNIQUE_ID,
|
CONF_UNIQUE_ID,
|
||||||
CONF_UNIT_OF_MEASUREMENT,
|
CONF_UNIT_OF_MEASUREMENT,
|
||||||
CONF_VALUE_TEMPLATE,
|
CONF_VALUE_TEMPLATE,
|
||||||
|
SERVICE_RELOAD,
|
||||||
Platform,
|
Platform,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import Event, HomeAssistant, ServiceCall
|
||||||
from homeassistant.helpers import discovery
|
from homeassistant.helpers import discovery
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.reload import async_setup_reload_service
|
from homeassistant.helpers.entity_platform import async_get_platforms
|
||||||
|
from homeassistant.helpers.reload import async_integration_yaml_config
|
||||||
|
from homeassistant.helpers.service import async_register_admin_service
|
||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
|
|
||||||
from .const import CONF_COMMAND_TIMEOUT, DEFAULT_TIMEOUT, DOMAIN
|
from .const import CONF_COMMAND_TIMEOUT, DEFAULT_TIMEOUT, DOMAIN
|
||||||
|
@ -163,14 +166,39 @@ CONFIG_SCHEMA = vol.Schema(
|
||||||
|
|
||||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||||
"""Set up Command Line from yaml config."""
|
"""Set up Command Line from yaml config."""
|
||||||
command_line_config: list[dict[str, dict[str, Any]]] = config.get(DOMAIN, [])
|
|
||||||
|
async def _reload_config(call: Event | ServiceCall) -> None:
|
||||||
|
"""Reload Command Line."""
|
||||||
|
reload_config = await async_integration_yaml_config(hass, "command_line")
|
||||||
|
reset_platforms = async_get_platforms(hass, "command_line")
|
||||||
|
for reset_platform in reset_platforms:
|
||||||
|
_LOGGER.debug("Reload resetting platform: %s", reset_platform.domain)
|
||||||
|
await reset_platform.async_reset()
|
||||||
|
if not reload_config:
|
||||||
|
return
|
||||||
|
await async_load_platforms(hass, reload_config.get(DOMAIN, []), reload_config)
|
||||||
|
|
||||||
|
async_register_admin_service(hass, DOMAIN, SERVICE_RELOAD, _reload_config)
|
||||||
|
|
||||||
|
await async_load_platforms(hass, config.get(DOMAIN, []), config)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def async_load_platforms(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
command_line_config: list[dict[str, dict[str, Any]]],
|
||||||
|
config: ConfigType,
|
||||||
|
) -> None:
|
||||||
|
"""Load platforms from yaml."""
|
||||||
if not command_line_config:
|
if not command_line_config:
|
||||||
return True
|
return
|
||||||
|
|
||||||
_LOGGER.debug("Full config loaded: %s", command_line_config)
|
_LOGGER.debug("Full config loaded: %s", command_line_config)
|
||||||
|
|
||||||
load_coroutines: list[Coroutine[Any, Any, None]] = []
|
load_coroutines: list[Coroutine[Any, Any, None]] = []
|
||||||
platforms: list[Platform] = []
|
platforms: list[Platform] = []
|
||||||
|
reload_configs: list[tuple] = []
|
||||||
for platform_config in command_line_config:
|
for platform_config in command_line_config:
|
||||||
for platform, _config in platform_config.items():
|
for platform, _config in platform_config.items():
|
||||||
if (mapped_platform := PLATFORM_MAPPING[platform]) not in platforms:
|
if (mapped_platform := PLATFORM_MAPPING[platform]) not in platforms:
|
||||||
|
@ -180,6 +208,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||||
platform_config,
|
platform_config,
|
||||||
PLATFORM_MAPPING[platform],
|
PLATFORM_MAPPING[platform],
|
||||||
)
|
)
|
||||||
|
reload_configs.append((PLATFORM_MAPPING[platform], _config))
|
||||||
load_coroutines.append(
|
load_coroutines.append(
|
||||||
discovery.async_load_platform(
|
discovery.async_load_platform(
|
||||||
hass,
|
hass,
|
||||||
|
@ -190,10 +219,6 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
await async_setup_reload_service(hass, DOMAIN, platforms)
|
|
||||||
|
|
||||||
if load_coroutines:
|
if load_coroutines:
|
||||||
_LOGGER.debug("Loading platforms: %s", platforms)
|
_LOGGER.debug("Loading platforms: %s", platforms)
|
||||||
await asyncio.gather(*load_coroutines)
|
await asyncio.gather(*load_coroutines)
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
cover:
|
command_line:
|
||||||
- platform: command_line
|
- "binary_sensor":
|
||||||
covers:
|
"name": "Test"
|
||||||
from_yaml:
|
"command": "echo 1"
|
||||||
command_state: "echo closed"
|
"payload_on": "1"
|
||||||
value_template: "{{ value }}"
|
"payload_off": "0"
|
||||||
|
"command_timeout": 15
|
||||||
|
|
|
@ -9,7 +9,7 @@ from unittest.mock import patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant import config as hass_config, setup
|
from homeassistant import setup
|
||||||
from homeassistant.components.command_line import DOMAIN
|
from homeassistant.components.command_line import DOMAIN
|
||||||
from homeassistant.components.command_line.cover import CommandCover
|
from homeassistant.components.command_line.cover import CommandCover
|
||||||
from homeassistant.components.cover import DOMAIN as COVER_DOMAIN, SCAN_INTERVAL
|
from homeassistant.components.cover import DOMAIN as COVER_DOMAIN, SCAN_INTERVAL
|
||||||
|
@ -21,7 +21,6 @@ from homeassistant.const import (
|
||||||
ATTR_ENTITY_ID,
|
ATTR_ENTITY_ID,
|
||||||
SERVICE_CLOSE_COVER,
|
SERVICE_CLOSE_COVER,
|
||||||
SERVICE_OPEN_COVER,
|
SERVICE_OPEN_COVER,
|
||||||
SERVICE_RELOAD,
|
|
||||||
SERVICE_STOP_COVER,
|
SERVICE_STOP_COVER,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
@ -29,7 +28,7 @@ from homeassistant.helpers import entity_registry as er
|
||||||
import homeassistant.helpers.issue_registry as ir
|
import homeassistant.helpers.issue_registry as ir
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
|
|
||||||
from tests.common import async_fire_time_changed, get_fixture_path
|
from tests.common import async_fire_time_changed
|
||||||
|
|
||||||
|
|
||||||
async def test_no_covers_platform_yaml(
|
async def test_no_covers_platform_yaml(
|
||||||
|
@ -214,45 +213,6 @@ async def test_state_value(hass: HomeAssistant) -> None:
|
||||||
assert entity_state.state == "closed"
|
assert entity_state.state == "closed"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"get_config",
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"command_line": [
|
|
||||||
{
|
|
||||||
"cover": {
|
|
||||||
"command_state": "echo open",
|
|
||||||
"value_template": "{{ value }}",
|
|
||||||
"name": "Test",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
)
|
|
||||||
async def test_reload(hass: HomeAssistant, load_yaml_integration: None) -> None:
|
|
||||||
"""Verify we can reload command_line covers."""
|
|
||||||
|
|
||||||
entity_state = hass.states.get("cover.test")
|
|
||||||
assert entity_state
|
|
||||||
assert entity_state.state == "unknown"
|
|
||||||
|
|
||||||
yaml_path = get_fixture_path("configuration.yaml", "command_line")
|
|
||||||
with patch.object(hass_config, "YAML_CONFIG_FILE", yaml_path):
|
|
||||||
await hass.services.async_call(
|
|
||||||
"command_line",
|
|
||||||
SERVICE_RELOAD,
|
|
||||||
{},
|
|
||||||
blocking=True,
|
|
||||||
)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
assert len(hass.states.async_all()) == 1
|
|
||||||
|
|
||||||
assert not hass.states.get("cover.test")
|
|
||||||
assert hass.states.get("cover.from_yaml")
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"get_config",
|
"get_config",
|
||||||
[
|
[
|
||||||
|
|
|
@ -2,12 +2,17 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
from homeassistant.const import STATE_ON, STATE_OPEN
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant import config as hass_config
|
||||||
|
from homeassistant.components.command_line.const import DOMAIN
|
||||||
|
from homeassistant.const import SERVICE_RELOAD, STATE_ON, STATE_OPEN
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
|
|
||||||
from tests.common import async_fire_time_changed
|
from tests.common import async_fire_time_changed, get_fixture_path
|
||||||
|
|
||||||
|
|
||||||
async def test_setup_config(hass: HomeAssistant, load_yaml_integration: None) -> None:
|
async def test_setup_config(hass: HomeAssistant, load_yaml_integration: None) -> None:
|
||||||
|
@ -25,3 +30,55 @@ async def test_setup_config(hass: HomeAssistant, load_yaml_integration: None) ->
|
||||||
assert state_sensor.state == "5"
|
assert state_sensor.state == "5"
|
||||||
assert state_cover.state == STATE_OPEN
|
assert state_cover.state == STATE_OPEN
|
||||||
assert state_switch.state == STATE_ON
|
assert state_switch.state == STATE_ON
|
||||||
|
|
||||||
|
|
||||||
|
async def test_reload_service(
|
||||||
|
hass: HomeAssistant, load_yaml_integration: None, caplog: pytest.LogCaptureFixture
|
||||||
|
) -> None:
|
||||||
|
"""Test reload serviice."""
|
||||||
|
|
||||||
|
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(minutes=10))
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state_binary_sensor = hass.states.get("binary_sensor.test")
|
||||||
|
state_sensor = hass.states.get("sensor.test")
|
||||||
|
assert state_binary_sensor.state == STATE_ON
|
||||||
|
assert state_sensor.state == "5"
|
||||||
|
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
|
yaml_path = get_fixture_path("configuration.yaml", "command_line")
|
||||||
|
with patch.object(hass_config, "YAML_CONFIG_FILE", yaml_path):
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_RELOAD,
|
||||||
|
{},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert "Loading config" in caplog.text
|
||||||
|
|
||||||
|
state_binary_sensor = hass.states.get("binary_sensor.test")
|
||||||
|
state_sensor = hass.states.get("sensor.test")
|
||||||
|
assert state_binary_sensor.state == STATE_ON
|
||||||
|
assert not state_sensor
|
||||||
|
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
|
yaml_path = get_fixture_path("configuration_empty.yaml", "command_line")
|
||||||
|
with patch.object(hass_config, "YAML_CONFIG_FILE", yaml_path):
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_RELOAD,
|
||||||
|
{},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state_binary_sensor = hass.states.get("binary_sensor.test")
|
||||||
|
state_sensor = hass.states.get("sensor.test")
|
||||||
|
assert not state_binary_sensor
|
||||||
|
assert not state_sensor
|
||||||
|
|
||||||
|
assert "Loading config" not in caplog.text
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue