mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 12:17:07 +00:00
Add availability to command_line (#105300)
* Add availability to command_line * Add tests * freezer
This commit is contained in:
parent
6a9fdaae7a
commit
749ef45727
@ -55,6 +55,7 @@ import homeassistant.helpers.config_validation as cv
|
||||
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.trigger_template_entity import CONF_AVAILABILITY
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
from .const import CONF_COMMAND_TIMEOUT, DEFAULT_TIMEOUT, DOMAIN
|
||||
@ -90,6 +91,7 @@ BINARY_SENSOR_SCHEMA = vol.Schema(
|
||||
vol.Optional(
|
||||
CONF_SCAN_INTERVAL, default=BINARY_SENSOR_DEFAULT_SCAN_INTERVAL
|
||||
): vol.All(cv.time_period, cv.positive_timedelta),
|
||||
vol.Optional(CONF_AVAILABILITY): cv.template,
|
||||
}
|
||||
)
|
||||
COVER_SCHEMA = vol.Schema(
|
||||
@ -105,6 +107,7 @@ COVER_SCHEMA = vol.Schema(
|
||||
vol.Optional(CONF_SCAN_INTERVAL, default=COVER_DEFAULT_SCAN_INTERVAL): vol.All(
|
||||
cv.time_period, cv.positive_timedelta
|
||||
),
|
||||
vol.Optional(CONF_AVAILABILITY): cv.template,
|
||||
}
|
||||
)
|
||||
NOTIFY_SCHEMA = vol.Schema(
|
||||
@ -129,6 +132,7 @@ SENSOR_SCHEMA = vol.Schema(
|
||||
vol.Optional(CONF_SCAN_INTERVAL, default=SENSOR_DEFAULT_SCAN_INTERVAL): vol.All(
|
||||
cv.time_period, cv.positive_timedelta
|
||||
),
|
||||
vol.Optional(CONF_AVAILABILITY): cv.template,
|
||||
}
|
||||
)
|
||||
SWITCH_SCHEMA = vol.Schema(
|
||||
@ -144,6 +148,7 @@ SWITCH_SCHEMA = vol.Schema(
|
||||
vol.Optional(CONF_SCAN_INTERVAL, default=SWITCH_DEFAULT_SCAN_INTERVAL): vol.All(
|
||||
cv.time_period, cv.positive_timedelta
|
||||
),
|
||||
vol.Optional(CONF_AVAILABILITY): cv.template,
|
||||
}
|
||||
)
|
||||
COMBINED_SCHEMA = vol.Schema(
|
||||
|
@ -24,7 +24,10 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.event import async_track_time_interval
|
||||
from homeassistant.helpers.template import Template
|
||||
from homeassistant.helpers.trigger_template_entity import ManualTriggerEntity
|
||||
from homeassistant.helpers.trigger_template_entity import (
|
||||
CONF_AVAILABILITY,
|
||||
ManualTriggerEntity,
|
||||
)
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
@ -63,6 +66,7 @@ async def async_setup_platform(
|
||||
scan_interval: timedelta = binary_sensor_config.get(
|
||||
CONF_SCAN_INTERVAL, SCAN_INTERVAL
|
||||
)
|
||||
availability: Template | None = binary_sensor_config.get(CONF_AVAILABILITY)
|
||||
if value_template is not None:
|
||||
value_template.hass = hass
|
||||
data = CommandSensorData(hass, command, command_timeout)
|
||||
@ -72,6 +76,7 @@ async def async_setup_platform(
|
||||
CONF_NAME: Template(name, hass),
|
||||
CONF_DEVICE_CLASS: device_class,
|
||||
CONF_ICON: icon,
|
||||
CONF_AVAILABILITY: availability,
|
||||
}
|
||||
|
||||
async_add_entities(
|
||||
|
@ -20,7 +20,10 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.event import async_track_time_interval
|
||||
from homeassistant.helpers.template import Template
|
||||
from homeassistant.helpers.trigger_template_entity import ManualTriggerEntity
|
||||
from homeassistant.helpers.trigger_template_entity import (
|
||||
CONF_AVAILABILITY,
|
||||
ManualTriggerEntity,
|
||||
)
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
from homeassistant.util import dt as dt_util, slugify
|
||||
|
||||
@ -50,6 +53,7 @@ async def async_setup_platform(
|
||||
trigger_entity_config = {
|
||||
CONF_UNIQUE_ID: device_config.get(CONF_UNIQUE_ID),
|
||||
CONF_NAME: Template(device_config.get(CONF_NAME, device_name), hass),
|
||||
CONF_AVAILABILITY: device_config.get(CONF_AVAILABILITY),
|
||||
}
|
||||
|
||||
covers.append(
|
||||
|
@ -20,7 +20,10 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.event import async_track_time_interval
|
||||
from homeassistant.helpers.template import Template
|
||||
from homeassistant.helpers.trigger_template_entity import ManualTriggerEntity
|
||||
from homeassistant.helpers.trigger_template_entity import (
|
||||
CONF_AVAILABILITY,
|
||||
ManualTriggerEntity,
|
||||
)
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
from homeassistant.util import dt as dt_util, slugify
|
||||
|
||||
@ -48,6 +51,7 @@ async def async_setup_platform(
|
||||
CONF_UNIQUE_ID: device_config.get(CONF_UNIQUE_ID),
|
||||
CONF_NAME: Template(device_config.get(CONF_NAME, object_id), hass),
|
||||
CONF_ICON: device_config.get(CONF_ICON),
|
||||
CONF_AVAILABILITY: device_config.get(CONF_AVAILABILITY),
|
||||
}
|
||||
|
||||
value_template: Template | None = device_config.get(CONF_VALUE_TEMPLATE)
|
||||
|
@ -6,6 +6,7 @@ from datetime import timedelta
|
||||
from typing import Any
|
||||
from unittest.mock import patch
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
import pytest
|
||||
|
||||
from homeassistant import setup
|
||||
@ -15,7 +16,7 @@ from homeassistant.components.homeassistant import (
|
||||
DOMAIN as HA_DOMAIN,
|
||||
SERVICE_UPDATE_ENTITY,
|
||||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, STATE_ON
|
||||
from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, STATE_ON, STATE_UNAVAILABLE
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.util import dt as dt_util
|
||||
@ -289,3 +290,53 @@ async def test_updating_manually(
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert called
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"get_config",
|
||||
[
|
||||
{
|
||||
"command_line": [
|
||||
{
|
||||
"binary_sensor": {
|
||||
"name": "Test",
|
||||
"command": "echo 10",
|
||||
"payload_on": "1.0",
|
||||
"payload_off": "0",
|
||||
"value_template": "{{ value | multiply(0.1) }}",
|
||||
"availability": '{{ states("sensor.input1")=="on" }}',
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
)
|
||||
async def test_availability(
|
||||
hass: HomeAssistant,
|
||||
load_yaml_integration: None,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Test availability."""
|
||||
|
||||
hass.states.async_set("sensor.input1", "on")
|
||||
freezer.tick(timedelta(minutes=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_state = hass.states.get("binary_sensor.test")
|
||||
assert entity_state
|
||||
assert entity_state.state == STATE_ON
|
||||
|
||||
hass.states.async_set("sensor.input1", "off")
|
||||
await hass.async_block_till_done()
|
||||
with patch(
|
||||
"homeassistant.components.command_line.utils.subprocess.check_output",
|
||||
return_value=b"0",
|
||||
):
|
||||
freezer.tick(timedelta(minutes=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_state = hass.states.get("binary_sensor.test")
|
||||
assert entity_state
|
||||
assert entity_state.state == STATE_UNAVAILABLE
|
||||
|
@ -7,6 +7,7 @@ import os
|
||||
import tempfile
|
||||
from unittest.mock import patch
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
import pytest
|
||||
|
||||
from homeassistant import setup
|
||||
@ -22,6 +23,8 @@ from homeassistant.const import (
|
||||
SERVICE_CLOSE_COVER,
|
||||
SERVICE_OPEN_COVER,
|
||||
SERVICE_STOP_COVER,
|
||||
STATE_OPEN,
|
||||
STATE_UNAVAILABLE,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
@ -340,3 +343,50 @@ async def test_updating_manually(
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert called
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"get_config",
|
||||
[
|
||||
{
|
||||
"command_line": [
|
||||
{
|
||||
"cover": {
|
||||
"command_state": "echo 10",
|
||||
"name": "Test",
|
||||
"availability": '{{ states("sensor.input1")=="on" }}',
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
)
|
||||
async def test_availability(
|
||||
hass: HomeAssistant,
|
||||
load_yaml_integration: None,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Test availability."""
|
||||
|
||||
hass.states.async_set("sensor.input1", "on")
|
||||
freezer.tick(timedelta(minutes=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_state = hass.states.get("cover.test")
|
||||
assert entity_state
|
||||
assert entity_state.state == STATE_OPEN
|
||||
|
||||
hass.states.async_set("sensor.input1", "off")
|
||||
await hass.async_block_till_done()
|
||||
with patch(
|
||||
"homeassistant.components.command_line.utils.subprocess.check_output",
|
||||
return_value=b"50\n",
|
||||
):
|
||||
freezer.tick(timedelta(minutes=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_state = hass.states.get("cover.test")
|
||||
assert entity_state
|
||||
assert entity_state.state == STATE_UNAVAILABLE
|
||||
|
@ -7,6 +7,7 @@ import subprocess
|
||||
from typing import Any
|
||||
from unittest.mock import patch
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
import pytest
|
||||
|
||||
from homeassistant import setup
|
||||
@ -16,7 +17,7 @@ from homeassistant.components.homeassistant import (
|
||||
DOMAIN as HA_DOMAIN,
|
||||
SERVICE_UPDATE_ENTITY,
|
||||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID, STATE_UNKNOWN
|
||||
from homeassistant.const import ATTR_ENTITY_ID, STATE_UNAVAILABLE, STATE_UNKNOWN
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.util import dt as dt_util
|
||||
@ -708,3 +709,52 @@ async def test_template_not_error_when_data_is_none(
|
||||
"Template variable error: 'None' has no attribute 'split' when rendering"
|
||||
not in caplog.text
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"get_config",
|
||||
[
|
||||
{
|
||||
"command_line": [
|
||||
{
|
||||
"sensor": {
|
||||
"name": "Test",
|
||||
"command": "echo January 17, 2022",
|
||||
"device_class": "date",
|
||||
"value_template": "{{ strptime(value, '%B %d, %Y').strftime('%Y-%m-%d') }}",
|
||||
"availability": '{{ states("sensor.input1")=="on" }}',
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
)
|
||||
async def test_availability(
|
||||
hass: HomeAssistant,
|
||||
load_yaml_integration: None,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Test availability."""
|
||||
|
||||
hass.states.async_set("sensor.input1", "on")
|
||||
freezer.tick(timedelta(minutes=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_state = hass.states.get("sensor.test")
|
||||
assert entity_state
|
||||
assert entity_state.state == "2022-01-17"
|
||||
|
||||
hass.states.async_set("sensor.input1", "off")
|
||||
await hass.async_block_till_done()
|
||||
with patch(
|
||||
"homeassistant.components.command_line.utils.subprocess.check_output",
|
||||
return_value=b"January 17, 2022",
|
||||
):
|
||||
freezer.tick(timedelta(minutes=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_state = hass.states.get("sensor.test")
|
||||
assert entity_state
|
||||
assert entity_state.state == STATE_UNAVAILABLE
|
||||
|
@ -9,6 +9,7 @@ import subprocess
|
||||
import tempfile
|
||||
from unittest.mock import patch
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
import pytest
|
||||
|
||||
from homeassistant import setup
|
||||
@ -25,6 +26,7 @@ from homeassistant.const import (
|
||||
SERVICE_TURN_ON,
|
||||
STATE_OFF,
|
||||
STATE_ON,
|
||||
STATE_UNAVAILABLE,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
@ -710,3 +712,52 @@ async def test_updating_manually(
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert called
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"get_config",
|
||||
[
|
||||
{
|
||||
"command_line": [
|
||||
{
|
||||
"switch": {
|
||||
"command_state": "echo 1",
|
||||
"command_on": "echo 2",
|
||||
"command_off": "echo 3",
|
||||
"name": "Test",
|
||||
"availability": '{{ states("sensor.input1")=="on" }}',
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
)
|
||||
async def test_availability(
|
||||
hass: HomeAssistant,
|
||||
load_yaml_integration: None,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Test availability."""
|
||||
|
||||
hass.states.async_set("sensor.input1", "on")
|
||||
freezer.tick(timedelta(minutes=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_state = hass.states.get("switch.test")
|
||||
assert entity_state
|
||||
assert entity_state.state == STATE_ON
|
||||
|
||||
hass.states.async_set("sensor.input1", "off")
|
||||
await hass.async_block_till_done()
|
||||
with patch(
|
||||
"homeassistant.components.command_line.utils.subprocess.check_output",
|
||||
return_value=b"50\n",
|
||||
):
|
||||
freezer.tick(timedelta(minutes=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_state = hass.states.get("switch.test")
|
||||
assert entity_state
|
||||
assert entity_state.state == STATE_UNAVAILABLE
|
||||
|
Loading…
x
Reference in New Issue
Block a user