291 files

This commit is contained in:
Home Assistant Version Control
2026-10-14 18:10:18 +00:00
parent c4e0178d8a
commit 280501d2e8
291 changed files with 32540 additions and 3280 deletions
@@ -1,50 +1 @@
"""Spook - Your homie."""
from __future__ import annotations
from typing import TYPE_CHECKING
from homeassistant.exceptions import HomeAssistantError
from ....const import DOMAIN
if TYPE_CHECKING:
from homeassistant.components.number import NumberEntity
def shown_value_as_float(entity: NumberEntity) -> float:
"""Return the value of a number entity, as it shows it, as a float.
In the units it shows, which are not always the units it works in: a
thermostat that keeps Celsius can be shown in Fahrenheit. Stepping from
this means stepping in what somebody sees, and the result has to go back
through `async_set_shown_value` to land in the units the entity keeps.
"""
try:
return float(entity.value)
except (TypeError, ValueError) as err:
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="value_not_a_number",
translation_placeholders={
"value": repr(entity.value),
"entity_id": entity.entity_id,
},
) from err
async def async_set_shown_value(entity: NumberEntity, value: float) -> None:
"""Set a value given in the units the number shows, the way core does.
Converted to the units the entity works in, and kept within the limits
it has there. Handing the shown value over as it is set a thermostat
showing 68 °F to 69 °C on a step of one degree.
"""
try:
native_value = entity.convert_to_native_value(value)
native_value = min(
max(native_value, entity.native_min_value), entity.native_max_value
)
await entity.async_set_native_value(native_value)
except NotImplementedError:
await entity.async_set_value(value)
@@ -2,7 +2,6 @@
from __future__ import annotations
import math
from typing import TYPE_CHECKING
import voluptuous as vol
@@ -10,7 +9,7 @@ import voluptuous as vol
from homeassistant.components.number import DOMAIN, NumberEntity
from ....services import AbstractSpookEntityComponentService
from . import async_set_shown_value, shown_value_as_float
from ..stepping import async_set_shown_value, shown_value_as_float, step_amount
if TYPE_CHECKING:
from homeassistant.core import ServiceCall
@@ -29,22 +28,7 @@ class SpookService(AbstractSpookEntityComponentService[NumberEntity]):
call: ServiceCall,
) -> None:
"""Handle the service call."""
step = entity.step or 1
amount = call.data.get("amount", step)
remainder = amount % step
# Float modulo wraps around just short of the step, 0.3 % 0.1 is
# 0.09999999999999998, so a remainder against either end is a clean multiple.
if not (
math.isclose(remainder, 0, rel_tol=0, abs_tol=1e-9)
or math.isclose(remainder, step, rel_tol=0, abs_tol=1e-9)
):
msg = (
f"Amount {amount} not valid for {entity.entity_id}, "
f"it needs to be a multiple of {step}"
)
raise ValueError(msg)
value = shown_value_as_float(entity) - amount
value = shown_value_as_float(entity) - step_amount(entity, call)
if entity.min_value is not None:
value = max(value, entity.min_value)
@@ -2,7 +2,6 @@
from __future__ import annotations
import math
from typing import TYPE_CHECKING
import voluptuous as vol
@@ -10,7 +9,7 @@ import voluptuous as vol
from homeassistant.components.number import DOMAIN, NumberEntity
from ....services import AbstractSpookEntityComponentService
from . import async_set_shown_value, shown_value_as_float
from ..stepping import async_set_shown_value, shown_value_as_float, step_amount
if TYPE_CHECKING:
from homeassistant.core import ServiceCall
@@ -29,22 +28,7 @@ class SpookService(AbstractSpookEntityComponentService[NumberEntity]):
call: ServiceCall,
) -> None:
"""Handle the service call."""
step = entity.step or 1
amount = call.data.get("amount", step)
remainder = amount % step
# Float modulo wraps around just short of the step, 0.3 % 0.1 is
# 0.09999999999999998, so a remainder against either end is a clean multiple.
if not (
math.isclose(remainder, 0, rel_tol=0, abs_tol=1e-9)
or math.isclose(remainder, step, rel_tol=0, abs_tol=1e-9)
):
msg = (
f"Amount {amount} not valid for {entity.entity_id}, "
f"it needs to be a multiple of {step}"
)
raise ValueError(msg)
value = shown_value_as_float(entity) + amount
value = shown_value_as_float(entity) + step_amount(entity, call)
if entity.max_value is not None:
value = min(value, entity.max_value)