Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix manual update for Command Line #94433

Merged
merged 1 commit into from
Jun 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions homeassistant/components/command_line/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from homeassistant.helpers.template import Template
from homeassistant.helpers.template_entity import ManualTriggerEntity
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util import dt as dt_util

from .const import CONF_COMMAND_TIMEOUT, DEFAULT_TIMEOUT, DOMAIN, LOGGER
from .sensor import CommandSensorData
Expand Down Expand Up @@ -185,3 +186,10 @@ async def _async_update(self) -> None:

self._process_manual_data(value)
self.async_write_ha_state()

async def async_update(self) -> None:
"""Update the entity.

Only used by the generic entity update service.
"""
await self._update_entity_state(dt_util.now())
9 changes: 8 additions & 1 deletion homeassistant/components/command_line/cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
from homeassistant.helpers.template import Template
from homeassistant.helpers.template_entity import ManualTriggerEntity
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util import slugify
from homeassistant.util import dt as dt_util, slugify

from .const import CONF_COMMAND_TIMEOUT, DEFAULT_TIMEOUT, DOMAIN, LOGGER
from .utils import call_shell_with_timeout, check_output_or_log
Expand Down Expand Up @@ -224,6 +224,13 @@ async def _async_update(self) -> None:
self._process_manual_data(payload)
await self.async_update_ha_state(True)

async def async_update(self) -> None:
"""Update the entity.

Only used by the generic entity update service.
"""
await self._update_entity_state(dt_util.now())

async def async_open_cover(self, **kwargs: Any) -> None:
"""Open the cover."""
await self.hass.async_add_executor_job(self._move_cover, self._command_open)
Expand Down
8 changes: 8 additions & 0 deletions homeassistant/components/command_line/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
from homeassistant.helpers.template import Template
from homeassistant.helpers.template_entity import ManualTriggerEntity
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util import dt as dt_util

from .const import CONF_COMMAND_TIMEOUT, DEFAULT_TIMEOUT, DOMAIN, LOGGER
from .utils import check_output_or_log
Expand Down Expand Up @@ -216,6 +217,13 @@ async def _async_update(self) -> None:
self._process_manual_data(value)
self.async_write_ha_state()

async def async_update(self) -> None:
"""Update the entity.

Only used by the generic entity update service.
"""
await self._update_entity_state(dt_util.now())


class CommandSensorData:
"""The class for handling the data retrieval."""
Expand Down
9 changes: 8 additions & 1 deletion homeassistant/components/command_line/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
from homeassistant.helpers.template import Template
from homeassistant.helpers.template_entity import ManualTriggerEntity
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util import slugify
from homeassistant.util import dt as dt_util, slugify

from .const import CONF_COMMAND_TIMEOUT, DEFAULT_TIMEOUT, DOMAIN, LOGGER
from .utils import call_shell_with_timeout, check_output_or_log
Expand Down Expand Up @@ -240,6 +240,13 @@ async def _async_update(self) -> None:
self._process_manual_data(payload)
await self.async_update_ha_state(True)

async def async_update(self) -> None:
"""Update the entity.

Only used by the generic entity update service.
"""
await self._update_entity_state(dt_util.now())

async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the device on."""
if await self._switch(self._command_on) and not self._command_state:
Expand Down
59 changes: 58 additions & 1 deletion tests/components/command_line/test_binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
from homeassistant.components.command_line.binary_sensor import CommandBinarySensor
from homeassistant.components.command_line.const import DOMAIN
from homeassistant.const import STATE_OFF, STATE_ON
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.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
import homeassistant.helpers.issue_registry as ir
Expand Down Expand Up @@ -252,3 +256,56 @@ async def _async_update(self) -> None:
)

await asyncio.sleep(0.2)


async def test_updating_manually(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
) -> None:
"""Test handling manual updating using homeassistant udate_entity service."""
await setup.async_setup_component(hass, HA_DOMAIN, {})
called = []

class MockCommandBinarySensor(CommandBinarySensor):
"""Mock entity that updates slow."""

async def _async_update(self) -> None:
"""Update slow."""
called.append(1)
# Add waiting time
await asyncio.sleep(1)

with patch(
"homeassistant.components.command_line.binary_sensor.CommandBinarySensor",
side_effect=MockCommandBinarySensor,
):
await setup.async_setup_component(
hass,
DOMAIN,
{
"command_line": [
{
"binary_sensor": {
"name": "Test",
"command": "echo 1",
"payload_on": "1",
"payload_off": "0",
"scan_interval": 10,
}
}
]
},
)
await hass.async_block_till_done()

assert len(called) == 1

await hass.services.async_call(
HA_DOMAIN,
SERVICE_UPDATE_ENTITY,
{ATTR_ENTITY_ID: ["binary_sensor.test"]},
blocking=True,
)
await hass.async_block_till_done()
assert len(called) == 2

await asyncio.sleep(0.2)
58 changes: 58 additions & 0 deletions tests/components/command_line/test_cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
from homeassistant.components.command_line import DOMAIN
from homeassistant.components.command_line.cover import CommandCover
from homeassistant.components.cover import DOMAIN as COVER_DOMAIN, SCAN_INTERVAL
from homeassistant.components.homeassistant import (
DOMAIN as HA_DOMAIN,
SERVICE_UPDATE_ENTITY,
)
from homeassistant.const import (
ATTR_ENTITY_ID,
SERVICE_CLOSE_COVER,
Expand Down Expand Up @@ -378,3 +382,57 @@ async def _async_update(self) -> None:
)

await asyncio.sleep(0.2)


async def test_updating_manually(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
) -> None:
"""Test handling manual updating using homeassistant udate_entity service."""
await setup.async_setup_component(hass, HA_DOMAIN, {})
called = []

class MockCommandCover(CommandCover):
"""Mock entity that updates slow."""

async def _async_update(self) -> None:
"""Update slow."""
called.append(1)
# Add waiting time
await asyncio.sleep(1)

with patch(
"homeassistant.components.command_line.cover.CommandCover",
side_effect=MockCommandCover,
):
await setup.async_setup_component(
hass,
DOMAIN,
{
"command_line": [
{
"cover": {
"command_state": "echo 1",
"value_template": "{{ value }}",
"name": "Test",
"scan_interval": 10,
}
}
]
},
)
await hass.async_block_till_done()

async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=10))
await hass.async_block_till_done()
assert len(called) == 1

await hass.services.async_call(
HA_DOMAIN,
SERVICE_UPDATE_ENTITY,
{ATTR_ENTITY_ID: ["cover.test"]},
blocking=True,
)
await hass.async_block_till_done()
assert len(called) == 2

await asyncio.sleep(0.2)
56 changes: 56 additions & 0 deletions tests/components/command_line/test_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@
from homeassistant import setup
from homeassistant.components.command_line import DOMAIN
from homeassistant.components.command_line.sensor import CommandSensor
from homeassistant.components.homeassistant import (
DOMAIN as HA_DOMAIN,
SERVICE_UPDATE_ENTITY,
)
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
import homeassistant.helpers.issue_registry as ir
Expand Down Expand Up @@ -586,3 +591,54 @@ async def _async_update(self) -> None:
)

await asyncio.sleep(0.2)


async def test_updating_manually(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
) -> None:
"""Test handling manual updating using homeassistant udate_entity service."""
await setup.async_setup_component(hass, HA_DOMAIN, {})
called = []

class MockCommandSensor(CommandSensor):
"""Mock entity that updates slow."""

async def _async_update(self) -> None:
"""Update slow."""
called.append(1)
# Add waiting time
await asyncio.sleep(1)

with patch(
"homeassistant.components.command_line.sensor.CommandSensor",
side_effect=MockCommandSensor,
):
await setup.async_setup_component(
hass,
DOMAIN,
{
"command_line": [
{
"sensor": {
"name": "Test",
"command": "echo 1",
"scan_interval": 10,
}
}
]
},
)
await hass.async_block_till_done()

assert len(called) == 1

await hass.services.async_call(
HA_DOMAIN,
SERVICE_UPDATE_ENTITY,
{ATTR_ENTITY_ID: ["sensor.test"]},
blocking=True,
)
await hass.async_block_till_done()
assert len(called) == 2

await asyncio.sleep(0.2)
59 changes: 59 additions & 0 deletions tests/components/command_line/test_switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
from homeassistant import setup
from homeassistant.components.command_line import DOMAIN
from homeassistant.components.command_line.switch import CommandSwitch
from homeassistant.components.homeassistant import (
DOMAIN as HA_DOMAIN,
SERVICE_UPDATE_ENTITY,
)
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN, SCAN_INTERVAL
from homeassistant.const import (
ATTR_ENTITY_ID,
Expand Down Expand Up @@ -696,3 +700,58 @@ async def _async_update(self) -> None:
)

await asyncio.sleep(0.2)


async def test_updating_manually(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
) -> None:
"""Test handling manual updating using homeassistant udate_entity service."""
await setup.async_setup_component(hass, HA_DOMAIN, {})
called = []

class MockCommandSwitch(CommandSwitch):
"""Mock entity that updates slow."""

async def _async_update(self) -> None:
"""Update slow."""
called.append(1)
# Add waiting time
await asyncio.sleep(1)

with patch(
"homeassistant.components.command_line.switch.CommandSwitch",
side_effect=MockCommandSwitch,
):
await setup.async_setup_component(
hass,
DOMAIN,
{
"command_line": [
{
"switch": {
"command_state": "echo 1",
"command_on": "echo 2",
"command_off": "echo 3",
"name": "Test",
"scan_interval": 10,
}
}
]
},
)
await hass.async_block_till_done()

async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=10))
await hass.async_block_till_done()
assert len(called) == 1

await hass.services.async_call(
HA_DOMAIN,
SERVICE_UPDATE_ENTITY,
{ATTR_ENTITY_ID: ["switch.test"]},
blocking=True,
)
await hass.async_block_till_done()
assert len(called) == 2

await asyncio.sleep(0.2)