Add auto slider/box mode to number entity (#57737)

This commit is contained in:
Franck Nijhof 2021-10-21 07:20:39 +02:00 committed by GitHub
parent 3bdc637d1b
commit dcaa689023
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 64 additions and 3 deletions

View File

@ -1,7 +1,10 @@
"""Demo platform that offers a fake Number entity.""" """Demo platform that offers a fake Number entity."""
from __future__ import annotations from __future__ import annotations
from typing import Literal
from homeassistant.components.number import NumberEntity from homeassistant.components.number import NumberEntity
from homeassistant.components.number.const import MODE_AUTO, MODE_BOX, MODE_SLIDER
from homeassistant.const import DEVICE_DEFAULT_NAME from homeassistant.const import DEVICE_DEFAULT_NAME
from . import DOMAIN from . import DOMAIN
@ -17,6 +20,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
42.0, 42.0,
"mdi:volume-high", "mdi:volume-high",
False, False,
mode=MODE_SLIDER,
), ),
DemoNumber( DemoNumber(
"pwm1", "pwm1",
@ -27,6 +31,27 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
0.0, 0.0,
1.0, 1.0,
0.01, 0.01,
MODE_BOX,
),
DemoNumber(
"large_range",
"Large Range",
500,
"mdi:square-wave",
False,
1,
1000,
1,
),
DemoNumber(
"small_range",
"Small Range",
128,
"mdi:square-wave",
False,
1,
255,
1,
), ),
] ]
) )
@ -51,7 +76,8 @@ class DemoNumber(NumberEntity):
assumed: bool, assumed: bool,
min_value: float | None = None, min_value: float | None = None,
max_value: float | None = None, max_value: float | None = None,
step=None, step: float | None = None,
mode: Literal["auto", "box", "slider"] = MODE_AUTO,
) -> None: ) -> None:
"""Initialize the Demo Number entity.""" """Initialize the Demo Number entity."""
self._attr_assumed_state = assumed self._attr_assumed_state = assumed
@ -59,6 +85,7 @@ class DemoNumber(NumberEntity):
self._attr_name = name or DEVICE_DEFAULT_NAME self._attr_name = name or DEVICE_DEFAULT_NAME
self._attr_unique_id = unique_id self._attr_unique_id = unique_id
self._attr_value = state self._attr_value = state
self._attr_mode = mode
if min_value is not None: if min_value is not None:
self._attr_min_value = min_value self._attr_min_value = min_value

View File

@ -4,11 +4,12 @@ from __future__ import annotations
from dataclasses import dataclass from dataclasses import dataclass
from datetime import timedelta from datetime import timedelta
import logging import logging
from typing import Any, final from typing import Any, Literal, final
import voluptuous as vol import voluptuous as vol
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_MODE
from homeassistant.core import HomeAssistant, ServiceCall from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.helpers.config_validation import ( # noqa: F401 from homeassistant.helpers.config_validation import ( # noqa: F401
PLATFORM_SCHEMA, PLATFORM_SCHEMA,
@ -27,6 +28,7 @@ from .const import (
DEFAULT_MIN_VALUE, DEFAULT_MIN_VALUE,
DEFAULT_STEP, DEFAULT_STEP,
DOMAIN, DOMAIN,
MODE_AUTO,
SERVICE_SET_VALUE, SERVICE_SET_VALUE,
) )
@ -90,6 +92,7 @@ class NumberEntity(Entity):
_attr_min_value: float = DEFAULT_MIN_VALUE _attr_min_value: float = DEFAULT_MIN_VALUE
_attr_state: None = None _attr_state: None = None
_attr_step: float _attr_step: float
_attr_mode: Literal["auto", "slider", "box"] = MODE_AUTO
_attr_value: float _attr_value: float
@property @property
@ -99,6 +102,7 @@ class NumberEntity(Entity):
ATTR_MIN: self.min_value, ATTR_MIN: self.min_value,
ATTR_MAX: self.max_value, ATTR_MAX: self.max_value,
ATTR_STEP: self.step, ATTR_STEP: self.step,
ATTR_MODE: self.mode,
} }
@property @property
@ -123,6 +127,11 @@ class NumberEntity(Entity):
step /= 10.0 step /= 10.0
return step return step
@property
def mode(self) -> Literal["auto", "slider", "box"]:
"""Return the mode of the entity."""
return self._attr_mode
@property @property
@final @final
def state(self) -> float | None: def state(self) -> float | None:

View File

@ -1,10 +1,16 @@
"""Provides the constants needed for the component.""" """Provides the constants needed for the component."""
from typing import Final
ATTR_VALUE = "value" ATTR_VALUE = "value"
ATTR_MIN = "min" ATTR_MIN = "min"
ATTR_MAX = "max" ATTR_MAX = "max"
ATTR_STEP = "step" ATTR_STEP = "step"
MODE_AUTO: Final = "auto"
MODE_BOX: Final = "box"
MODE_SLIDER: Final = "slider"
DEFAULT_MIN_VALUE = 0.0 DEFAULT_MIN_VALUE = 0.0
DEFAULT_MAX_VALUE = 100.0 DEFAULT_MAX_VALUE = 100.0
DEFAULT_STEP = 1.0 DEFAULT_STEP = 1.0

View File

@ -9,13 +9,18 @@ from homeassistant.components.number.const import (
ATTR_STEP, ATTR_STEP,
ATTR_VALUE, ATTR_VALUE,
DOMAIN, DOMAIN,
MODE_AUTO,
MODE_BOX,
MODE_SLIDER,
SERVICE_SET_VALUE, SERVICE_SET_VALUE,
) )
from homeassistant.const import ATTR_ENTITY_ID from homeassistant.const import ATTR_ENTITY_ID, ATTR_MODE
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
ENTITY_VOLUME = "number.volume" ENTITY_VOLUME = "number.volume"
ENTITY_PWM = "number.pwm_1" ENTITY_PWM = "number.pwm_1"
ENTITY_LARGE_RANGE = "number.large_range"
ENTITY_SMALL_RANGE = "number.small_range"
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
@ -37,11 +42,25 @@ def test_default_setup_params(hass):
assert state.attributes.get(ATTR_MIN) == 0.0 assert state.attributes.get(ATTR_MIN) == 0.0
assert state.attributes.get(ATTR_MAX) == 100.0 assert state.attributes.get(ATTR_MAX) == 100.0
assert state.attributes.get(ATTR_STEP) == 1.0 assert state.attributes.get(ATTR_STEP) == 1.0
assert state.attributes.get(ATTR_MODE) == MODE_SLIDER
state = hass.states.get(ENTITY_PWM) state = hass.states.get(ENTITY_PWM)
assert state.attributes.get(ATTR_MIN) == 0.0 assert state.attributes.get(ATTR_MIN) == 0.0
assert state.attributes.get(ATTR_MAX) == 1.0 assert state.attributes.get(ATTR_MAX) == 1.0
assert state.attributes.get(ATTR_STEP) == 0.01 assert state.attributes.get(ATTR_STEP) == 0.01
assert state.attributes.get(ATTR_MODE) == MODE_BOX
state = hass.states.get(ENTITY_LARGE_RANGE)
assert state.attributes.get(ATTR_MIN) == 1.0
assert state.attributes.get(ATTR_MAX) == 1000.0
assert state.attributes.get(ATTR_STEP) == 1.0
assert state.attributes.get(ATTR_MODE) == MODE_AUTO
state = hass.states.get(ENTITY_SMALL_RANGE)
assert state.attributes.get(ATTR_MIN) == 1.0
assert state.attributes.get(ATTR_MAX) == 255.0
assert state.attributes.get(ATTR_STEP) == 1.0
assert state.attributes.get(ATTR_MODE) == MODE_AUTO
async def test_set_value_bad_attr(hass): async def test_set_value_bad_attr(hass):