Add counter.set_value service (#92863)

This commit is contained in:
Franck Nijhof 2023-05-10 18:52:10 +02:00 committed by GitHub
parent 98b91bcad9
commit 97cac66195
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 132 additions and 3 deletions

View File

@ -44,6 +44,7 @@ SERVICE_DECREMENT = "decrement"
SERVICE_INCREMENT = "increment"
SERVICE_RESET = "reset"
SERVICE_CONFIGURE = "configure"
SERVICE_SET_VALUE = "set_value"
STORAGE_KEY = DOMAIN
STORAGE_VERSION = 1
@ -124,6 +125,11 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
component.async_register_entity_service(SERVICE_INCREMENT, {}, "async_increment")
component.async_register_entity_service(SERVICE_DECREMENT, {}, "async_decrement")
component.async_register_entity_service(SERVICE_RESET, {}, "async_reset")
component.async_register_entity_service(
SERVICE_SET_VALUE,
{vol.Required(VALUE): cv.positive_int},
"async_set_value",
)
component.async_register_entity_service(
SERVICE_CONFIGURE,
{
@ -261,6 +267,27 @@ class Counter(collection.CollectionEntity, RestoreEntity):
self._state = self.compute_next_state(self._config[CONF_INITIAL])
self.async_write_ha_state()
@callback
def async_set_value(self, value: int) -> None:
"""Set counter to value."""
if (maximum := self._config.get(CONF_MAXIMUM)) is not None and value > maximum:
raise ValueError(
f"Value {value} for {self.entity_id} exceeding the maximum value of {maximum}"
)
if (minimum := self._config.get(CONF_MINIMUM)) is not None and value < minimum:
raise ValueError(
f"Value {value} for {self.entity_id} exceeding the minimum value of {minimum}"
)
if (step := self._config.get(CONF_STEP)) is not None and value % step != 0:
raise ValueError(
f"Value {value} for {self.entity_id} is not a multiple of the step size {step}"
)
self._state = value
self.async_write_ha_state()
@callback
def async_configure(self, **kwargs) -> None:
"""Change the counter's settings with a service."""

View File

@ -21,6 +21,23 @@ reset:
entity:
domain: counter
set_value:
name: Set
description: Set the counter value
target:
entity:
domain: counter
fields:
value:
name: Value
required: true
description: The new counter value the entity should be set to.
selector:
number:
min: 0
max: 9223372036854775807
mode: box
configure:
name: Configure
description: Change counter parameters.

View File

@ -11,14 +11,18 @@ from homeassistant.components.counter import (
ATTR_STEP,
CONF_ICON,
CONF_INITIAL,
CONF_MAXIMUM,
CONF_MINIMUM,
CONF_NAME,
CONF_RESTORE,
CONF_STEP,
DEFAULT_INITIAL,
DEFAULT_STEP,
DOMAIN,
SERVICE_SET_VALUE,
VALUE,
)
from homeassistant.const import ATTR_FRIENDLY_NAME, ATTR_ICON, ATTR_NAME
from homeassistant.const import ATTR_ENTITY_ID, ATTR_FRIENDLY_NAME, ATTR_ICON, ATTR_NAME
from homeassistant.core import Context, CoreState, HomeAssistant, State
from homeassistant.helpers import entity_registry as er
from homeassistant.setup import async_setup_component
@ -124,7 +128,7 @@ async def test_config_options(hass: HomeAssistant) -> None:
async def test_methods(hass: HomeAssistant) -> None:
"""Test increment, decrement, and reset methods."""
"""Test increment, decrement, set value, and reset methods."""
config = {DOMAIN: {"test_1": {}}}
assert await async_setup_component(hass, "counter", config)
@ -158,11 +162,31 @@ async def test_methods(hass: HomeAssistant) -> None:
state = hass.states.get(entity_id)
assert int(state.state) == 0
await hass.services.async_call(
DOMAIN,
SERVICE_SET_VALUE,
{
ATTR_ENTITY_ID: entity_id,
VALUE: 5,
},
blocking=True,
)
state = hass.states.get(entity_id)
assert state.state == "5"
async def test_methods_with_config(hass: HomeAssistant) -> None:
"""Test increment, decrement, and reset methods with configuration."""
config = {
DOMAIN: {"test": {CONF_NAME: "Hello World", CONF_INITIAL: 10, CONF_STEP: 5}}
DOMAIN: {
"test": {
CONF_NAME: "Hello World",
CONF_INITIAL: 10,
CONF_STEP: 5,
CONF_MINIMUM: 5,
CONF_MAXIMUM: 20,
}
}
}
assert await async_setup_component(hass, "counter", config)
@ -190,6 +214,67 @@ async def test_methods_with_config(hass: HomeAssistant) -> None:
state = hass.states.get(entity_id)
assert int(state.state) == 15
await hass.services.async_call(
DOMAIN,
SERVICE_SET_VALUE,
{
ATTR_ENTITY_ID: entity_id,
VALUE: 5,
},
blocking=True,
)
state = hass.states.get(entity_id)
assert state.state == "5"
with pytest.raises(
ValueError, match=r"Value 25 for counter.test exceeding the maximum value of 20"
):
await hass.services.async_call(
DOMAIN,
SERVICE_SET_VALUE,
{
ATTR_ENTITY_ID: entity_id,
VALUE: 25,
},
blocking=True,
)
state = hass.states.get(entity_id)
assert state.state == "5"
with pytest.raises(
ValueError, match=r"Value 0 for counter.test exceeding the minimum value of 5"
):
await hass.services.async_call(
DOMAIN,
SERVICE_SET_VALUE,
{
ATTR_ENTITY_ID: entity_id,
VALUE: 0,
},
blocking=True,
)
state = hass.states.get(entity_id)
assert state.state == "5"
with pytest.raises(
ValueError,
match=r"Value 6 for counter.test is not a multiple of the step size 5",
):
await hass.services.async_call(
DOMAIN,
SERVICE_SET_VALUE,
{
ATTR_ENTITY_ID: entity_id,
VALUE: 6,
},
blocking=True,
)
state = hass.states.get(entity_id)
assert state.state == "5"
async def test_initial_state_overrules_restore_state(hass: HomeAssistant) -> None:
"""Ensure states are restored on startup."""