mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 20:57:21 +00:00
Add scaling utils for brightness and fanspeed (#104753)
Co-authored-by: Robert Resch <robert@resch.dev>
This commit is contained in:
parent
7222e2b2d6
commit
e8475b9b33
@ -21,10 +21,10 @@ from homeassistant.exceptions import HomeAssistantError
|
|||||||
from homeassistant.helpers import entity_platform
|
from homeassistant.helpers import entity_platform
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.util.percentage import (
|
from homeassistant.util.percentage import (
|
||||||
int_states_in_range,
|
|
||||||
percentage_to_ranged_value,
|
percentage_to_ranged_value,
|
||||||
ranged_value_to_percentage,
|
ranged_value_to_percentage,
|
||||||
)
|
)
|
||||||
|
from homeassistant.util.scaling import int_states_in_range
|
||||||
|
|
||||||
from .const import DOMAIN, SERVICE_SET_FAN_SPEED_TRACKED_STATE
|
from .const import DOMAIN, SERVICE_SET_FAN_SPEED_TRACKED_STATE
|
||||||
from .entity import BondEntity
|
from .entity import BondEntity
|
||||||
|
@ -22,10 +22,10 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
|||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||||
from homeassistant.util.percentage import (
|
from homeassistant.util.percentage import (
|
||||||
int_states_in_range,
|
|
||||||
percentage_to_ranged_value,
|
percentage_to_ranged_value,
|
||||||
ranged_value_to_percentage,
|
ranged_value_to_percentage,
|
||||||
)
|
)
|
||||||
|
from homeassistant.util.scaling import int_states_in_range
|
||||||
|
|
||||||
from . import DOMAIN, SIGNAL_COMFOCONNECT_UPDATE_RECEIVED, ComfoConnectBridge
|
from . import DOMAIN, SIGNAL_COMFOCONNECT_UPDATE_RECEIVED, ComfoConnectBridge
|
||||||
|
|
||||||
|
@ -13,10 +13,10 @@ from homeassistant.core import HomeAssistant
|
|||||||
from homeassistant.helpers.device_registry import DeviceInfo
|
from homeassistant.helpers.device_registry import DeviceInfo
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.util.percentage import (
|
from homeassistant.util.percentage import (
|
||||||
int_states_in_range,
|
|
||||||
percentage_to_ranged_value,
|
percentage_to_ranged_value,
|
||||||
ranged_value_to_percentage,
|
ranged_value_to_percentage,
|
||||||
)
|
)
|
||||||
|
from homeassistant.util.scaling import int_states_in_range
|
||||||
|
|
||||||
from .const import _LOGGER, DOMAIN
|
from .const import _LOGGER, DOMAIN
|
||||||
from .entity import ISYNodeEntity, ISYProgramEntity
|
from .entity import ISYNodeEntity, ISYProgramEntity
|
||||||
|
@ -14,10 +14,10 @@ from homeassistant.core import HomeAssistant
|
|||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
from homeassistant.util.percentage import (
|
from homeassistant.util.percentage import (
|
||||||
int_states_in_range,
|
|
||||||
percentage_to_ranged_value,
|
percentage_to_ranged_value,
|
||||||
ranged_value_to_percentage,
|
ranged_value_to_percentage,
|
||||||
)
|
)
|
||||||
|
from homeassistant.util.scaling import int_states_in_range
|
||||||
|
|
||||||
from .const import DATA_KNX_CONFIG, DOMAIN, KNX_ADDRESS
|
from .const import DATA_KNX_CONFIG, DOMAIN, KNX_ADDRESS
|
||||||
from .knx_entity import KnxEntity
|
from .knx_entity import KnxEntity
|
||||||
|
@ -12,10 +12,10 @@ from homeassistant.core import HomeAssistant
|
|||||||
from homeassistant.helpers import entity_platform
|
from homeassistant.helpers import entity_platform
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.util.percentage import (
|
from homeassistant.util.percentage import (
|
||||||
int_states_in_range,
|
|
||||||
percentage_to_ranged_value,
|
percentage_to_ranged_value,
|
||||||
ranged_value_to_percentage,
|
ranged_value_to_percentage,
|
||||||
)
|
)
|
||||||
|
from homeassistant.util.scaling import int_states_in_range
|
||||||
|
|
||||||
from . import (
|
from . import (
|
||||||
ModernFormsDataUpdateCoordinator,
|
ModernFormsDataUpdateCoordinator,
|
||||||
|
@ -31,10 +31,10 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|||||||
from homeassistant.helpers.template import Template
|
from homeassistant.helpers.template import Template
|
||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
from homeassistant.util.percentage import (
|
from homeassistant.util.percentage import (
|
||||||
int_states_in_range,
|
|
||||||
percentage_to_ranged_value,
|
percentage_to_ranged_value,
|
||||||
ranged_value_to_percentage,
|
ranged_value_to_percentage,
|
||||||
)
|
)
|
||||||
|
from homeassistant.util.scaling import int_states_in_range
|
||||||
|
|
||||||
from . import subscription
|
from . import subscription
|
||||||
from .config import MQTT_RW_SCHEMA
|
from .config import MQTT_RW_SCHEMA
|
||||||
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from contextlib import suppress
|
from contextlib import suppress
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, cast
|
from typing import TYPE_CHECKING, Any, cast
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
@ -367,10 +367,10 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
|
|||||||
if brightness_supported(self.supported_color_modes):
|
if brightness_supported(self.supported_color_modes):
|
||||||
try:
|
try:
|
||||||
if brightness := values["brightness"]:
|
if brightness := values["brightness"]:
|
||||||
scale = self._config[CONF_BRIGHTNESS_SCALE]
|
if TYPE_CHECKING:
|
||||||
self._attr_brightness = min(
|
assert isinstance(brightness, float)
|
||||||
255,
|
self._attr_brightness = color_util.value_to_brightness(
|
||||||
round(brightness * 255 / scale), # type: ignore[operator]
|
(1, self._config[CONF_BRIGHTNESS_SCALE]), brightness
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
@ -591,13 +591,12 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
|
|||||||
self._set_flash_and_transition(message, **kwargs)
|
self._set_flash_and_transition(message, **kwargs)
|
||||||
|
|
||||||
if ATTR_BRIGHTNESS in kwargs and self._config[CONF_BRIGHTNESS]:
|
if ATTR_BRIGHTNESS in kwargs and self._config[CONF_BRIGHTNESS]:
|
||||||
brightness_normalized = kwargs[ATTR_BRIGHTNESS] / DEFAULT_BRIGHTNESS_SCALE
|
device_brightness = color_util.brightness_to_value(
|
||||||
brightness_scale = self._config[CONF_BRIGHTNESS_SCALE]
|
(1, self._config[CONF_BRIGHTNESS_SCALE]),
|
||||||
device_brightness = min(
|
kwargs[ATTR_BRIGHTNESS],
|
||||||
round(brightness_normalized * brightness_scale), brightness_scale
|
|
||||||
)
|
)
|
||||||
# Make sure the brightness is not rounded down to 0
|
# Make sure the brightness is not rounded down to 0
|
||||||
device_brightness = max(device_brightness, 1)
|
device_brightness = max(round(device_brightness), 1)
|
||||||
message["brightness"] = device_brightness
|
message["brightness"] = device_brightness
|
||||||
|
|
||||||
if self._optimistic:
|
if self._optimistic:
|
||||||
|
@ -13,10 +13,10 @@ from homeassistant.config_entries import ConfigEntry
|
|||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.util.percentage import (
|
from homeassistant.util.percentage import (
|
||||||
int_states_in_range,
|
|
||||||
percentage_to_ranged_value,
|
percentage_to_ranged_value,
|
||||||
ranged_value_to_percentage,
|
ranged_value_to_percentage,
|
||||||
)
|
)
|
||||||
|
from homeassistant.util.scaling import int_states_in_range
|
||||||
|
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
from .coordinator import RensonCoordinator
|
from .coordinator import RensonCoordinator
|
||||||
|
@ -12,10 +12,10 @@ from homeassistant.config_entries import ConfigEntry
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.util.percentage import (
|
from homeassistant.util.percentage import (
|
||||||
int_states_in_range,
|
|
||||||
percentage_to_ranged_value,
|
percentage_to_ranged_value,
|
||||||
ranged_value_to_percentage,
|
ranged_value_to_percentage,
|
||||||
)
|
)
|
||||||
|
from homeassistant.util.scaling import int_states_in_range
|
||||||
|
|
||||||
from . import SmartThingsEntity
|
from . import SmartThingsEntity
|
||||||
from .const import DATA_BROKERS, DOMAIN
|
from .const import DATA_BROKERS, DOMAIN
|
||||||
|
@ -14,10 +14,10 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
|||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||||
from homeassistant.util.percentage import (
|
from homeassistant.util.percentage import (
|
||||||
int_states_in_range,
|
|
||||||
percentage_to_ranged_value,
|
percentage_to_ranged_value,
|
||||||
ranged_value_to_percentage,
|
ranged_value_to_percentage,
|
||||||
)
|
)
|
||||||
|
from homeassistant.util.scaling import int_states_in_range
|
||||||
|
|
||||||
from . import DOMAIN, SIGNAL_UPDATE_SMARTY
|
from . import DOMAIN, SIGNAL_UPDATE_SMARTY
|
||||||
|
|
||||||
|
@ -11,10 +11,10 @@ from homeassistant.core import HomeAssistant, callback
|
|||||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.util.percentage import (
|
from homeassistant.util.percentage import (
|
||||||
int_states_in_range,
|
|
||||||
percentage_to_ranged_value,
|
percentage_to_ranged_value,
|
||||||
ranged_value_to_percentage,
|
ranged_value_to_percentage,
|
||||||
)
|
)
|
||||||
|
from homeassistant.util.scaling import int_states_in_range
|
||||||
|
|
||||||
from .common import VeSyncDevice
|
from .common import VeSyncDevice
|
||||||
from .const import DEV_TYPE_TO_HA, DOMAIN, SKU_TO_BASE_DEVICE, VS_DISCOVERY, VS_FANS
|
from .const import DEV_TYPE_TO_HA, DOMAIN, SKU_TO_BASE_DEVICE, VS_DISCOVERY, VS_FANS
|
||||||
|
@ -14,10 +14,10 @@ from homeassistant.core import HomeAssistant, callback
|
|||||||
from homeassistant.helpers import entity_platform
|
from homeassistant.helpers import entity_platform
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.util.percentage import (
|
from homeassistant.util.percentage import (
|
||||||
int_states_in_range,
|
|
||||||
percentage_to_ranged_value,
|
percentage_to_ranged_value,
|
||||||
ranged_value_to_percentage,
|
ranged_value_to_percentage,
|
||||||
)
|
)
|
||||||
|
from homeassistant.util.scaling import int_states_in_range
|
||||||
|
|
||||||
from . import async_wemo_dispatcher_connect
|
from . import async_wemo_dispatcher_connect
|
||||||
from .const import SERVICE_RESET_FILTER_LIFE, SERVICE_SET_HUMIDITY
|
from .const import SERVICE_RESET_FILTER_LIFE, SERVICE_SET_HUMIDITY
|
||||||
|
@ -20,10 +20,10 @@ from homeassistant.core import HomeAssistant, State, callback
|
|||||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.util.percentage import (
|
from homeassistant.util.percentage import (
|
||||||
int_states_in_range,
|
|
||||||
percentage_to_ranged_value,
|
percentage_to_ranged_value,
|
||||||
ranged_value_to_percentage,
|
ranged_value_to_percentage,
|
||||||
)
|
)
|
||||||
|
from homeassistant.util.scaling import int_states_in_range
|
||||||
|
|
||||||
from .core import discovery
|
from .core import discovery
|
||||||
from .core.cluster_handlers import wrap_zigpy_exceptions
|
from .core.cluster_handlers import wrap_zigpy_exceptions
|
||||||
|
@ -7,6 +7,8 @@ from typing import NamedTuple
|
|||||||
|
|
||||||
import attr
|
import attr
|
||||||
|
|
||||||
|
from .scaling import scale_to_ranged_value
|
||||||
|
|
||||||
|
|
||||||
class RGBColor(NamedTuple):
|
class RGBColor(NamedTuple):
|
||||||
"""RGB hex values."""
|
"""RGB hex values."""
|
||||||
@ -744,3 +746,38 @@ def check_valid_gamut(Gamut: GamutType) -> bool:
|
|||||||
)
|
)
|
||||||
|
|
||||||
return not_on_line and red_valid and green_valid and blue_valid
|
return not_on_line and red_valid and green_valid and blue_valid
|
||||||
|
|
||||||
|
|
||||||
|
def brightness_to_value(low_high_range: tuple[float, float], brightness: int) -> float:
|
||||||
|
"""Given a brightness_scale convert a brightness to a single value.
|
||||||
|
|
||||||
|
Do not include 0 if the light is off for value 0.
|
||||||
|
|
||||||
|
Given a brightness low_high_range of (1,100) this function
|
||||||
|
will return:
|
||||||
|
|
||||||
|
255: 100.0
|
||||||
|
127: ~49.8039
|
||||||
|
10: ~3.9216
|
||||||
|
"""
|
||||||
|
return scale_to_ranged_value((1, 255), low_high_range, brightness)
|
||||||
|
|
||||||
|
|
||||||
|
def value_to_brightness(low_high_range: tuple[float, float], value: float) -> int:
|
||||||
|
"""Given a brightness_scale convert a single value to a brightness.
|
||||||
|
|
||||||
|
Do not include 0 if the light is off for value 0.
|
||||||
|
|
||||||
|
Given a brightness low_high_range of (1,100) this function
|
||||||
|
will return:
|
||||||
|
|
||||||
|
100: 255
|
||||||
|
50: 128
|
||||||
|
4: 10
|
||||||
|
|
||||||
|
The value will be clamped between 1..255 to ensure valid value.
|
||||||
|
"""
|
||||||
|
return min(
|
||||||
|
255,
|
||||||
|
max(1, round(scale_to_ranged_value(low_high_range, (1, 255), value))),
|
||||||
|
)
|
||||||
|
@ -3,6 +3,13 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from typing import TypeVar
|
from typing import TypeVar
|
||||||
|
|
||||||
|
from .scaling import ( # noqa: F401
|
||||||
|
int_states_in_range,
|
||||||
|
scale_ranged_value_to_int_range,
|
||||||
|
scale_to_ranged_value,
|
||||||
|
states_in_range,
|
||||||
|
)
|
||||||
|
|
||||||
_T = TypeVar("_T")
|
_T = TypeVar("_T")
|
||||||
|
|
||||||
|
|
||||||
@ -69,8 +76,7 @@ def ranged_value_to_percentage(
|
|||||||
(1,255), 127: 50
|
(1,255), 127: 50
|
||||||
(1,255), 10: 4
|
(1,255), 10: 4
|
||||||
"""
|
"""
|
||||||
offset = low_high_range[0] - 1
|
return scale_ranged_value_to_int_range(low_high_range, (1, 100), value)
|
||||||
return int(((value - offset) * 100) // states_in_range(low_high_range))
|
|
||||||
|
|
||||||
|
|
||||||
def percentage_to_ranged_value(
|
def percentage_to_ranged_value(
|
||||||
@ -87,15 +93,4 @@ def percentage_to_ranged_value(
|
|||||||
(1,255), 50: 127.5
|
(1,255), 50: 127.5
|
||||||
(1,255), 4: 10.2
|
(1,255), 4: 10.2
|
||||||
"""
|
"""
|
||||||
offset = low_high_range[0] - 1
|
return scale_to_ranged_value((1, 100), low_high_range, percentage)
|
||||||
return states_in_range(low_high_range) * percentage / 100 + offset
|
|
||||||
|
|
||||||
|
|
||||||
def states_in_range(low_high_range: tuple[float, float]) -> float:
|
|
||||||
"""Given a range of low and high values return how many states exist."""
|
|
||||||
return low_high_range[1] - low_high_range[0] + 1
|
|
||||||
|
|
||||||
|
|
||||||
def int_states_in_range(low_high_range: tuple[float, float]) -> int:
|
|
||||||
"""Given a range of low and high values return how many integer states exist."""
|
|
||||||
return int(states_in_range(low_high_range))
|
|
||||||
|
62
homeassistant/util/scaling.py
Normal file
62
homeassistant/util/scaling.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
"""Scaling util functions."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
|
||||||
|
def scale_ranged_value_to_int_range(
|
||||||
|
source_low_high_range: tuple[float, float],
|
||||||
|
target_low_high_range: tuple[float, float],
|
||||||
|
value: float,
|
||||||
|
) -> int:
|
||||||
|
"""Given a range of low and high values convert a single value to another range.
|
||||||
|
|
||||||
|
Given a source low value of 1 and a high value of 255 and
|
||||||
|
a target range from 1 to 100 this function
|
||||||
|
will return:
|
||||||
|
|
||||||
|
(1,255), (1,100), 255: 100
|
||||||
|
(1,255), (1,100), 127: 49
|
||||||
|
(1,255), (1,100), 10: 3
|
||||||
|
"""
|
||||||
|
source_offset = source_low_high_range[0] - 1
|
||||||
|
target_offset = target_low_high_range[0] - 1
|
||||||
|
return int(
|
||||||
|
(value - source_offset)
|
||||||
|
* states_in_range(target_low_high_range)
|
||||||
|
// states_in_range(source_low_high_range)
|
||||||
|
+ target_offset
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def scale_to_ranged_value(
|
||||||
|
source_low_high_range: tuple[float, float],
|
||||||
|
target_low_high_range: tuple[float, float],
|
||||||
|
value: float,
|
||||||
|
) -> float:
|
||||||
|
"""Given a range of low and high values convert a single value to another range.
|
||||||
|
|
||||||
|
Do not include 0 in a range if 0 means off,
|
||||||
|
e.g. for brightness or fan speed.
|
||||||
|
|
||||||
|
Given a source low value of 1 and a high value of 255 and
|
||||||
|
a target range from 1 to 100 this function
|
||||||
|
will return:
|
||||||
|
|
||||||
|
(1,255), 255: 100
|
||||||
|
(1,255), 127: ~49.8039
|
||||||
|
(1,255), 10: ~3.9216
|
||||||
|
"""
|
||||||
|
source_offset = source_low_high_range[0] - 1
|
||||||
|
target_offset = target_low_high_range[0] - 1
|
||||||
|
return (value - source_offset) * (
|
||||||
|
states_in_range(target_low_high_range)
|
||||||
|
) / states_in_range(source_low_high_range) + target_offset
|
||||||
|
|
||||||
|
|
||||||
|
def states_in_range(low_high_range: tuple[float, float]) -> float:
|
||||||
|
"""Given a range of low and high values return how many states exist."""
|
||||||
|
return low_high_range[1] - low_high_range[0] + 1
|
||||||
|
|
||||||
|
|
||||||
|
def int_states_in_range(low_high_range: tuple[float, float]) -> int:
|
||||||
|
"""Given a range of low and high values return how many integer states exist."""
|
||||||
|
return int(states_in_range(low_high_range))
|
519
tests/util/snapshots/test_color.ambr
Normal file
519
tests/util/snapshots/test_color.ambr
Normal file
@ -0,0 +1,519 @@
|
|||||||
|
# serializer version: 1
|
||||||
|
# name: test_brightness_to_254_range
|
||||||
|
dict({
|
||||||
|
1: 0.996078431372549,
|
||||||
|
2: 1.992156862745098,
|
||||||
|
3: 2.988235294117647,
|
||||||
|
4: 3.984313725490196,
|
||||||
|
5: 4.980392156862745,
|
||||||
|
6: 5.976470588235294,
|
||||||
|
7: 6.972549019607843,
|
||||||
|
8: 7.968627450980392,
|
||||||
|
9: 8.964705882352941,
|
||||||
|
10: 9.96078431372549,
|
||||||
|
11: 10.95686274509804,
|
||||||
|
12: 11.952941176470588,
|
||||||
|
13: 12.949019607843137,
|
||||||
|
14: 13.945098039215686,
|
||||||
|
15: 14.941176470588236,
|
||||||
|
16: 15.937254901960785,
|
||||||
|
17: 16.933333333333334,
|
||||||
|
18: 17.929411764705883,
|
||||||
|
19: 18.92549019607843,
|
||||||
|
20: 19.92156862745098,
|
||||||
|
21: 20.91764705882353,
|
||||||
|
22: 21.91372549019608,
|
||||||
|
23: 22.909803921568628,
|
||||||
|
24: 23.905882352941177,
|
||||||
|
25: 24.901960784313726,
|
||||||
|
26: 25.898039215686275,
|
||||||
|
27: 26.894117647058824,
|
||||||
|
28: 27.890196078431373,
|
||||||
|
29: 28.886274509803922,
|
||||||
|
30: 29.88235294117647,
|
||||||
|
31: 30.87843137254902,
|
||||||
|
32: 31.87450980392157,
|
||||||
|
33: 32.870588235294115,
|
||||||
|
34: 33.86666666666667,
|
||||||
|
35: 34.86274509803921,
|
||||||
|
36: 35.858823529411765,
|
||||||
|
37: 36.85490196078431,
|
||||||
|
38: 37.85098039215686,
|
||||||
|
39: 38.84705882352941,
|
||||||
|
40: 39.84313725490196,
|
||||||
|
41: 40.83921568627451,
|
||||||
|
42: 41.83529411764706,
|
||||||
|
43: 42.831372549019605,
|
||||||
|
44: 43.82745098039216,
|
||||||
|
45: 44.8235294117647,
|
||||||
|
46: 45.819607843137256,
|
||||||
|
47: 46.8156862745098,
|
||||||
|
48: 47.811764705882354,
|
||||||
|
49: 48.8078431372549,
|
||||||
|
50: 49.80392156862745,
|
||||||
|
51: 50.8,
|
||||||
|
52: 51.79607843137255,
|
||||||
|
53: 52.792156862745095,
|
||||||
|
54: 53.78823529411765,
|
||||||
|
55: 54.78431372549019,
|
||||||
|
56: 55.780392156862746,
|
||||||
|
57: 56.77647058823529,
|
||||||
|
58: 57.772549019607844,
|
||||||
|
59: 58.76862745098039,
|
||||||
|
60: 59.76470588235294,
|
||||||
|
61: 60.76078431372549,
|
||||||
|
62: 61.75686274509804,
|
||||||
|
63: 62.752941176470586,
|
||||||
|
64: 63.74901960784314,
|
||||||
|
65: 64.74509803921569,
|
||||||
|
66: 65.74117647058823,
|
||||||
|
67: 66.73725490196078,
|
||||||
|
68: 67.73333333333333,
|
||||||
|
69: 68.72941176470589,
|
||||||
|
70: 69.72549019607843,
|
||||||
|
71: 70.72156862745098,
|
||||||
|
72: 71.71764705882353,
|
||||||
|
73: 72.71372549019608,
|
||||||
|
74: 73.70980392156862,
|
||||||
|
75: 74.70588235294117,
|
||||||
|
76: 75.70196078431373,
|
||||||
|
77: 76.69803921568628,
|
||||||
|
78: 77.69411764705882,
|
||||||
|
79: 78.69019607843137,
|
||||||
|
80: 79.68627450980392,
|
||||||
|
81: 80.68235294117648,
|
||||||
|
82: 81.67843137254901,
|
||||||
|
83: 82.67450980392157,
|
||||||
|
84: 83.67058823529412,
|
||||||
|
85: 84.66666666666667,
|
||||||
|
86: 85.66274509803921,
|
||||||
|
87: 86.65882352941176,
|
||||||
|
88: 87.65490196078431,
|
||||||
|
89: 88.65098039215687,
|
||||||
|
90: 89.6470588235294,
|
||||||
|
91: 90.64313725490196,
|
||||||
|
92: 91.63921568627451,
|
||||||
|
93: 92.63529411764706,
|
||||||
|
94: 93.6313725490196,
|
||||||
|
95: 94.62745098039215,
|
||||||
|
96: 95.62352941176471,
|
||||||
|
97: 96.61960784313726,
|
||||||
|
98: 97.6156862745098,
|
||||||
|
99: 98.61176470588235,
|
||||||
|
100: 99.6078431372549,
|
||||||
|
101: 100.60392156862746,
|
||||||
|
102: 101.6,
|
||||||
|
103: 102.59607843137255,
|
||||||
|
104: 103.5921568627451,
|
||||||
|
105: 104.58823529411765,
|
||||||
|
106: 105.58431372549019,
|
||||||
|
107: 106.58039215686274,
|
||||||
|
108: 107.5764705882353,
|
||||||
|
109: 108.57254901960785,
|
||||||
|
110: 109.56862745098039,
|
||||||
|
111: 110.56470588235294,
|
||||||
|
112: 111.56078431372549,
|
||||||
|
113: 112.55686274509804,
|
||||||
|
114: 113.55294117647058,
|
||||||
|
115: 114.54901960784314,
|
||||||
|
116: 115.54509803921569,
|
||||||
|
117: 116.54117647058824,
|
||||||
|
118: 117.53725490196078,
|
||||||
|
119: 118.53333333333333,
|
||||||
|
120: 119.52941176470588,
|
||||||
|
121: 120.52549019607844,
|
||||||
|
122: 121.52156862745097,
|
||||||
|
123: 122.51764705882353,
|
||||||
|
124: 123.51372549019608,
|
||||||
|
125: 124.50980392156863,
|
||||||
|
126: 125.50588235294117,
|
||||||
|
127: 126.50196078431372,
|
||||||
|
128: 127.49803921568628,
|
||||||
|
129: 128.49411764705883,
|
||||||
|
130: 129.49019607843138,
|
||||||
|
131: 130.48627450980393,
|
||||||
|
132: 131.48235294117646,
|
||||||
|
133: 132.478431372549,
|
||||||
|
134: 133.47450980392156,
|
||||||
|
135: 134.47058823529412,
|
||||||
|
136: 135.46666666666667,
|
||||||
|
137: 136.46274509803922,
|
||||||
|
138: 137.45882352941177,
|
||||||
|
139: 138.45490196078433,
|
||||||
|
140: 139.45098039215685,
|
||||||
|
141: 140.4470588235294,
|
||||||
|
142: 141.44313725490196,
|
||||||
|
143: 142.4392156862745,
|
||||||
|
144: 143.43529411764706,
|
||||||
|
145: 144.4313725490196,
|
||||||
|
146: 145.42745098039217,
|
||||||
|
147: 146.42352941176472,
|
||||||
|
148: 147.41960784313724,
|
||||||
|
149: 148.4156862745098,
|
||||||
|
150: 149.41176470588235,
|
||||||
|
151: 150.4078431372549,
|
||||||
|
152: 151.40392156862745,
|
||||||
|
153: 152.4,
|
||||||
|
154: 153.39607843137256,
|
||||||
|
155: 154.3921568627451,
|
||||||
|
156: 155.38823529411764,
|
||||||
|
157: 156.3843137254902,
|
||||||
|
158: 157.38039215686274,
|
||||||
|
159: 158.3764705882353,
|
||||||
|
160: 159.37254901960785,
|
||||||
|
161: 160.3686274509804,
|
||||||
|
162: 161.36470588235295,
|
||||||
|
163: 162.3607843137255,
|
||||||
|
164: 163.35686274509803,
|
||||||
|
165: 164.35294117647058,
|
||||||
|
166: 165.34901960784313,
|
||||||
|
167: 166.34509803921569,
|
||||||
|
168: 167.34117647058824,
|
||||||
|
169: 168.3372549019608,
|
||||||
|
170: 169.33333333333334,
|
||||||
|
171: 170.3294117647059,
|
||||||
|
172: 171.32549019607842,
|
||||||
|
173: 172.32156862745097,
|
||||||
|
174: 173.31764705882352,
|
||||||
|
175: 174.31372549019608,
|
||||||
|
176: 175.30980392156863,
|
||||||
|
177: 176.30588235294118,
|
||||||
|
178: 177.30196078431374,
|
||||||
|
179: 178.2980392156863,
|
||||||
|
180: 179.2941176470588,
|
||||||
|
181: 180.29019607843136,
|
||||||
|
182: 181.28627450980392,
|
||||||
|
183: 182.28235294117647,
|
||||||
|
184: 183.27843137254902,
|
||||||
|
185: 184.27450980392157,
|
||||||
|
186: 185.27058823529413,
|
||||||
|
187: 186.26666666666668,
|
||||||
|
188: 187.2627450980392,
|
||||||
|
189: 188.25882352941176,
|
||||||
|
190: 189.2549019607843,
|
||||||
|
191: 190.25098039215686,
|
||||||
|
192: 191.24705882352941,
|
||||||
|
193: 192.24313725490197,
|
||||||
|
194: 193.23921568627452,
|
||||||
|
195: 194.23529411764707,
|
||||||
|
196: 195.2313725490196,
|
||||||
|
197: 196.22745098039215,
|
||||||
|
198: 197.2235294117647,
|
||||||
|
199: 198.21960784313725,
|
||||||
|
200: 199.2156862745098,
|
||||||
|
201: 200.21176470588236,
|
||||||
|
202: 201.2078431372549,
|
||||||
|
203: 202.20392156862746,
|
||||||
|
204: 203.2,
|
||||||
|
205: 204.19607843137254,
|
||||||
|
206: 205.1921568627451,
|
||||||
|
207: 206.18823529411765,
|
||||||
|
208: 207.1843137254902,
|
||||||
|
209: 208.18039215686275,
|
||||||
|
210: 209.1764705882353,
|
||||||
|
211: 210.17254901960786,
|
||||||
|
212: 211.16862745098038,
|
||||||
|
213: 212.16470588235293,
|
||||||
|
214: 213.1607843137255,
|
||||||
|
215: 214.15686274509804,
|
||||||
|
216: 215.1529411764706,
|
||||||
|
217: 216.14901960784314,
|
||||||
|
218: 217.1450980392157,
|
||||||
|
219: 218.14117647058825,
|
||||||
|
220: 219.13725490196077,
|
||||||
|
221: 220.13333333333333,
|
||||||
|
222: 221.12941176470588,
|
||||||
|
223: 222.12549019607843,
|
||||||
|
224: 223.12156862745098,
|
||||||
|
225: 224.11764705882354,
|
||||||
|
226: 225.1137254901961,
|
||||||
|
227: 226.10980392156864,
|
||||||
|
228: 227.10588235294117,
|
||||||
|
229: 228.10196078431372,
|
||||||
|
230: 229.09803921568627,
|
||||||
|
231: 230.09411764705882,
|
||||||
|
232: 231.09019607843138,
|
||||||
|
233: 232.08627450980393,
|
||||||
|
234: 233.08235294117648,
|
||||||
|
235: 234.07843137254903,
|
||||||
|
236: 235.07450980392156,
|
||||||
|
237: 236.0705882352941,
|
||||||
|
238: 237.06666666666666,
|
||||||
|
239: 238.06274509803922,
|
||||||
|
240: 239.05882352941177,
|
||||||
|
241: 240.05490196078432,
|
||||||
|
242: 241.05098039215687,
|
||||||
|
243: 242.04705882352943,
|
||||||
|
244: 243.04313725490195,
|
||||||
|
245: 244.0392156862745,
|
||||||
|
246: 245.03529411764706,
|
||||||
|
247: 246.0313725490196,
|
||||||
|
248: 247.02745098039216,
|
||||||
|
249: 248.0235294117647,
|
||||||
|
250: 249.01960784313727,
|
||||||
|
251: 250.01568627450982,
|
||||||
|
252: 251.01176470588234,
|
||||||
|
253: 252.0078431372549,
|
||||||
|
254: 253.00392156862745,
|
||||||
|
255: 254.0,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_brightness_to_254_range.1
|
||||||
|
dict({
|
||||||
|
0.996078431372549: 1,
|
||||||
|
1.992156862745098: 2,
|
||||||
|
2.988235294117647: 3,
|
||||||
|
3.984313725490196: 4,
|
||||||
|
4.980392156862745: 5,
|
||||||
|
5.976470588235294: 6,
|
||||||
|
6.972549019607843: 7,
|
||||||
|
7.968627450980392: 8,
|
||||||
|
8.964705882352941: 9,
|
||||||
|
9.96078431372549: 10,
|
||||||
|
10.95686274509804: 11,
|
||||||
|
11.952941176470588: 12,
|
||||||
|
12.949019607843137: 13,
|
||||||
|
13.945098039215686: 14,
|
||||||
|
14.941176470588236: 15,
|
||||||
|
15.937254901960785: 16,
|
||||||
|
16.933333333333334: 17,
|
||||||
|
17.929411764705883: 18,
|
||||||
|
18.92549019607843: 19,
|
||||||
|
19.92156862745098: 20,
|
||||||
|
20.91764705882353: 21,
|
||||||
|
21.91372549019608: 22,
|
||||||
|
22.909803921568628: 23,
|
||||||
|
23.905882352941177: 24,
|
||||||
|
24.901960784313726: 25,
|
||||||
|
25.898039215686275: 26,
|
||||||
|
26.894117647058824: 27,
|
||||||
|
27.890196078431373: 28,
|
||||||
|
28.886274509803922: 29,
|
||||||
|
29.88235294117647: 30,
|
||||||
|
30.87843137254902: 31,
|
||||||
|
31.87450980392157: 32,
|
||||||
|
32.870588235294115: 33,
|
||||||
|
33.86666666666667: 34,
|
||||||
|
34.86274509803921: 35,
|
||||||
|
35.858823529411765: 36,
|
||||||
|
36.85490196078431: 37,
|
||||||
|
37.85098039215686: 38,
|
||||||
|
38.84705882352941: 39,
|
||||||
|
39.84313725490196: 40,
|
||||||
|
40.83921568627451: 41,
|
||||||
|
41.83529411764706: 42,
|
||||||
|
42.831372549019605: 43,
|
||||||
|
43.82745098039216: 44,
|
||||||
|
44.8235294117647: 45,
|
||||||
|
45.819607843137256: 46,
|
||||||
|
46.8156862745098: 47,
|
||||||
|
47.811764705882354: 48,
|
||||||
|
48.8078431372549: 49,
|
||||||
|
49.80392156862745: 50,
|
||||||
|
50.8: 51,
|
||||||
|
51.79607843137255: 52,
|
||||||
|
52.792156862745095: 53,
|
||||||
|
53.78823529411765: 54,
|
||||||
|
54.78431372549019: 55,
|
||||||
|
55.780392156862746: 56,
|
||||||
|
56.77647058823529: 57,
|
||||||
|
57.772549019607844: 58,
|
||||||
|
58.76862745098039: 59,
|
||||||
|
59.76470588235294: 60,
|
||||||
|
60.76078431372549: 61,
|
||||||
|
61.75686274509804: 62,
|
||||||
|
62.752941176470586: 63,
|
||||||
|
63.74901960784314: 64,
|
||||||
|
64.74509803921569: 65,
|
||||||
|
65.74117647058823: 66,
|
||||||
|
66.73725490196078: 67,
|
||||||
|
67.73333333333333: 68,
|
||||||
|
68.72941176470589: 69,
|
||||||
|
69.72549019607843: 70,
|
||||||
|
70.72156862745098: 71,
|
||||||
|
71.71764705882353: 72,
|
||||||
|
72.71372549019608: 73,
|
||||||
|
73.70980392156862: 74,
|
||||||
|
74.70588235294117: 75,
|
||||||
|
75.70196078431373: 76,
|
||||||
|
76.69803921568628: 77,
|
||||||
|
77.69411764705882: 78,
|
||||||
|
78.69019607843137: 79,
|
||||||
|
79.68627450980392: 80,
|
||||||
|
80.68235294117648: 81,
|
||||||
|
81.67843137254901: 82,
|
||||||
|
82.67450980392157: 83,
|
||||||
|
83.67058823529412: 84,
|
||||||
|
84.66666666666667: 85,
|
||||||
|
85.66274509803921: 86,
|
||||||
|
86.65882352941176: 87,
|
||||||
|
87.65490196078431: 88,
|
||||||
|
88.65098039215687: 89,
|
||||||
|
89.6470588235294: 90,
|
||||||
|
90.64313725490196: 91,
|
||||||
|
91.63921568627451: 92,
|
||||||
|
92.63529411764706: 93,
|
||||||
|
93.6313725490196: 94,
|
||||||
|
94.62745098039215: 95,
|
||||||
|
95.62352941176471: 96,
|
||||||
|
96.61960784313726: 97,
|
||||||
|
97.6156862745098: 98,
|
||||||
|
98.61176470588235: 99,
|
||||||
|
99.6078431372549: 100,
|
||||||
|
100.60392156862746: 101,
|
||||||
|
101.6: 102,
|
||||||
|
102.59607843137255: 103,
|
||||||
|
103.5921568627451: 104,
|
||||||
|
104.58823529411765: 105,
|
||||||
|
105.58431372549019: 106,
|
||||||
|
106.58039215686274: 107,
|
||||||
|
107.5764705882353: 108,
|
||||||
|
108.57254901960785: 109,
|
||||||
|
109.56862745098039: 110,
|
||||||
|
110.56470588235294: 111,
|
||||||
|
111.56078431372549: 112,
|
||||||
|
112.55686274509804: 113,
|
||||||
|
113.55294117647058: 114,
|
||||||
|
114.54901960784314: 115,
|
||||||
|
115.54509803921569: 116,
|
||||||
|
116.54117647058824: 117,
|
||||||
|
117.53725490196078: 118,
|
||||||
|
118.53333333333333: 119,
|
||||||
|
119.52941176470588: 120,
|
||||||
|
120.52549019607844: 121,
|
||||||
|
121.52156862745097: 122,
|
||||||
|
122.51764705882353: 123,
|
||||||
|
123.51372549019608: 124,
|
||||||
|
124.50980392156863: 125,
|
||||||
|
125.50588235294117: 126,
|
||||||
|
126.50196078431372: 127,
|
||||||
|
127.49803921568628: 128,
|
||||||
|
128.49411764705883: 129,
|
||||||
|
129.49019607843138: 130,
|
||||||
|
130.48627450980393: 131,
|
||||||
|
131.48235294117646: 132,
|
||||||
|
132.478431372549: 133,
|
||||||
|
133.47450980392156: 134,
|
||||||
|
134.47058823529412: 135,
|
||||||
|
135.46666666666667: 136,
|
||||||
|
136.46274509803922: 137,
|
||||||
|
137.45882352941177: 138,
|
||||||
|
138.45490196078433: 139,
|
||||||
|
139.45098039215685: 140,
|
||||||
|
140.4470588235294: 141,
|
||||||
|
141.44313725490196: 142,
|
||||||
|
142.4392156862745: 143,
|
||||||
|
143.43529411764706: 144,
|
||||||
|
144.4313725490196: 145,
|
||||||
|
145.42745098039217: 146,
|
||||||
|
146.42352941176472: 147,
|
||||||
|
147.41960784313724: 148,
|
||||||
|
148.4156862745098: 149,
|
||||||
|
149.41176470588235: 150,
|
||||||
|
150.4078431372549: 151,
|
||||||
|
151.40392156862745: 152,
|
||||||
|
152.4: 153,
|
||||||
|
153.39607843137256: 154,
|
||||||
|
154.3921568627451: 155,
|
||||||
|
155.38823529411764: 156,
|
||||||
|
156.3843137254902: 157,
|
||||||
|
157.38039215686274: 158,
|
||||||
|
158.3764705882353: 159,
|
||||||
|
159.37254901960785: 160,
|
||||||
|
160.3686274509804: 161,
|
||||||
|
161.36470588235295: 162,
|
||||||
|
162.3607843137255: 163,
|
||||||
|
163.35686274509803: 164,
|
||||||
|
164.35294117647058: 165,
|
||||||
|
165.34901960784313: 166,
|
||||||
|
166.34509803921569: 167,
|
||||||
|
167.34117647058824: 168,
|
||||||
|
168.3372549019608: 169,
|
||||||
|
169.33333333333334: 170,
|
||||||
|
170.3294117647059: 171,
|
||||||
|
171.32549019607842: 172,
|
||||||
|
172.32156862745097: 173,
|
||||||
|
173.31764705882352: 174,
|
||||||
|
174.31372549019608: 175,
|
||||||
|
175.30980392156863: 176,
|
||||||
|
176.30588235294118: 177,
|
||||||
|
177.30196078431374: 178,
|
||||||
|
178.2980392156863: 179,
|
||||||
|
179.2941176470588: 180,
|
||||||
|
180.29019607843136: 181,
|
||||||
|
181.28627450980392: 182,
|
||||||
|
182.28235294117647: 183,
|
||||||
|
183.27843137254902: 184,
|
||||||
|
184.27450980392157: 185,
|
||||||
|
185.27058823529413: 186,
|
||||||
|
186.26666666666668: 187,
|
||||||
|
187.2627450980392: 188,
|
||||||
|
188.25882352941176: 189,
|
||||||
|
189.2549019607843: 190,
|
||||||
|
190.25098039215686: 191,
|
||||||
|
191.24705882352941: 192,
|
||||||
|
192.24313725490197: 193,
|
||||||
|
193.23921568627452: 194,
|
||||||
|
194.23529411764707: 195,
|
||||||
|
195.2313725490196: 196,
|
||||||
|
196.22745098039215: 197,
|
||||||
|
197.2235294117647: 198,
|
||||||
|
198.21960784313725: 199,
|
||||||
|
199.2156862745098: 200,
|
||||||
|
200.21176470588236: 201,
|
||||||
|
201.2078431372549: 202,
|
||||||
|
202.20392156862746: 203,
|
||||||
|
203.2: 204,
|
||||||
|
204.19607843137254: 205,
|
||||||
|
205.1921568627451: 206,
|
||||||
|
206.18823529411765: 207,
|
||||||
|
207.1843137254902: 208,
|
||||||
|
208.18039215686275: 209,
|
||||||
|
209.1764705882353: 210,
|
||||||
|
210.17254901960786: 211,
|
||||||
|
211.16862745098038: 212,
|
||||||
|
212.16470588235293: 213,
|
||||||
|
213.1607843137255: 214,
|
||||||
|
214.15686274509804: 215,
|
||||||
|
215.1529411764706: 216,
|
||||||
|
216.14901960784314: 217,
|
||||||
|
217.1450980392157: 218,
|
||||||
|
218.14117647058825: 219,
|
||||||
|
219.13725490196077: 220,
|
||||||
|
220.13333333333333: 221,
|
||||||
|
221.12941176470588: 222,
|
||||||
|
222.12549019607843: 223,
|
||||||
|
223.12156862745098: 224,
|
||||||
|
224.11764705882354: 225,
|
||||||
|
225.1137254901961: 226,
|
||||||
|
226.10980392156864: 227,
|
||||||
|
227.10588235294117: 228,
|
||||||
|
228.10196078431372: 229,
|
||||||
|
229.09803921568627: 230,
|
||||||
|
230.09411764705882: 231,
|
||||||
|
231.09019607843138: 232,
|
||||||
|
232.08627450980393: 233,
|
||||||
|
233.08235294117648: 234,
|
||||||
|
234.07843137254903: 235,
|
||||||
|
235.07450980392156: 236,
|
||||||
|
236.0705882352941: 237,
|
||||||
|
237.06666666666666: 238,
|
||||||
|
238.06274509803922: 239,
|
||||||
|
239.05882352941177: 240,
|
||||||
|
240.05490196078432: 241,
|
||||||
|
241.05098039215687: 242,
|
||||||
|
242.04705882352943: 243,
|
||||||
|
243.04313725490195: 244,
|
||||||
|
244.0392156862745: 245,
|
||||||
|
245.03529411764706: 246,
|
||||||
|
246.0313725490196: 247,
|
||||||
|
247.02745098039216: 248,
|
||||||
|
248.0235294117647: 249,
|
||||||
|
249.01960784313727: 250,
|
||||||
|
250.01568627450982: 251,
|
||||||
|
251.01176470588234: 252,
|
||||||
|
252.0078431372549: 253,
|
||||||
|
253.00392156862745: 254,
|
||||||
|
254.0: 255,
|
||||||
|
})
|
||||||
|
# ---
|
@ -1,5 +1,8 @@
|
|||||||
"""Test Home Assistant color util methods."""
|
"""Test Home Assistant color util methods."""
|
||||||
|
import math
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from syrupy.assertion import SnapshotAssertion
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
import homeassistant.util.color as color_util
|
import homeassistant.util.color as color_util
|
||||||
@ -587,3 +590,137 @@ def test_white_levels_to_color_temperature() -> None:
|
|||||||
2000,
|
2000,
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("value", "brightness"),
|
||||||
|
[
|
||||||
|
(530, 255), # test min==255 clamp
|
||||||
|
(511, 255),
|
||||||
|
(255, 127),
|
||||||
|
(49, 24),
|
||||||
|
(1, 1),
|
||||||
|
(0, 1), # test max==1 clamp
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_ranged_value_to_brightness_large(value: float, brightness: int) -> None:
|
||||||
|
"""Test a large scale and clamping and convert a single value to a brightness."""
|
||||||
|
scale = (1, 511)
|
||||||
|
|
||||||
|
assert color_util.value_to_brightness(scale, value) == brightness
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("brightness", "value", "math_ceil"),
|
||||||
|
[
|
||||||
|
(255, 511.0, 511),
|
||||||
|
(127, 254.49803921568628, 255),
|
||||||
|
(24, 48.09411764705882, 49),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_brightness_to_ranged_value_large(
|
||||||
|
brightness: int, value: float, math_ceil: int
|
||||||
|
) -> None:
|
||||||
|
"""Test a large scale and convert a brightness to a single value."""
|
||||||
|
scale = (1, 511)
|
||||||
|
|
||||||
|
assert color_util.brightness_to_value(scale, brightness) == value
|
||||||
|
|
||||||
|
assert math.ceil(color_util.brightness_to_value(scale, brightness)) == math_ceil
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("scale", "value", "brightness"),
|
||||||
|
[
|
||||||
|
((1, 4), 1, 64),
|
||||||
|
((1, 4), 2, 128),
|
||||||
|
((1, 4), 3, 191),
|
||||||
|
((1, 4), 4, 255),
|
||||||
|
((1, 6), 1, 42),
|
||||||
|
((1, 6), 2, 85),
|
||||||
|
((1, 6), 3, 128),
|
||||||
|
((1, 6), 4, 170),
|
||||||
|
((1, 6), 5, 212),
|
||||||
|
((1, 6), 6, 255),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_ranged_value_to_brightness_small(
|
||||||
|
scale: tuple[float, float], value: float, brightness: int
|
||||||
|
) -> None:
|
||||||
|
"""Test a small scale and convert a single value to a brightness."""
|
||||||
|
assert color_util.value_to_brightness(scale, value) == brightness
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("scale", "brightness", "value"),
|
||||||
|
[
|
||||||
|
((1, 4), 63, 1),
|
||||||
|
((1, 4), 127, 2),
|
||||||
|
((1, 4), 191, 3),
|
||||||
|
((1, 4), 255, 4),
|
||||||
|
((1, 6), 42, 1),
|
||||||
|
((1, 6), 85, 2),
|
||||||
|
((1, 6), 127, 3),
|
||||||
|
((1, 6), 170, 4),
|
||||||
|
((1, 6), 212, 5),
|
||||||
|
((1, 6), 255, 6),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_brightness_to_ranged_value_small(
|
||||||
|
scale: tuple[float, float], brightness: int, value: float
|
||||||
|
) -> None:
|
||||||
|
"""Test a small scale and convert a brightness to a single value."""
|
||||||
|
assert math.ceil(color_util.brightness_to_value(scale, brightness)) == value
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("value", "brightness"),
|
||||||
|
[
|
||||||
|
(101, 2),
|
||||||
|
(139, 64),
|
||||||
|
(178, 128),
|
||||||
|
(217, 192),
|
||||||
|
(255, 255),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_ranged_value_to_brightness_starting_high(
|
||||||
|
value: float, brightness: int
|
||||||
|
) -> None:
|
||||||
|
"""Test a range that does not start with 1."""
|
||||||
|
scale = (101, 255)
|
||||||
|
|
||||||
|
assert color_util.value_to_brightness(scale, value) == brightness
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("value", "brightness"),
|
||||||
|
[
|
||||||
|
(0, 64),
|
||||||
|
(1, 128),
|
||||||
|
(2, 191),
|
||||||
|
(3, 255),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_ranged_value_to_brightness_starting_zero(
|
||||||
|
value: float, brightness: int
|
||||||
|
) -> None:
|
||||||
|
"""Test a range that starts with 0."""
|
||||||
|
scale = (0, 3)
|
||||||
|
|
||||||
|
assert color_util.value_to_brightness(scale, value) == brightness
|
||||||
|
|
||||||
|
|
||||||
|
async def test_brightness_to_254_range(snapshot: SnapshotAssertion) -> None:
|
||||||
|
"""Test brightness scaling to a 254 range and back."""
|
||||||
|
brightness_range = range(1, 256) # (1..255)
|
||||||
|
scale = (1, 254)
|
||||||
|
scaled_values = {
|
||||||
|
brightness: color_util.brightness_to_value(scale, brightness)
|
||||||
|
for brightness in brightness_range
|
||||||
|
}
|
||||||
|
assert scaled_values == snapshot
|
||||||
|
restored_values = {}
|
||||||
|
for expected_brightness, value in scaled_values.items():
|
||||||
|
restored_values[value] = color_util.value_to_brightness(scale, value)
|
||||||
|
assert color_util.value_to_brightness(scale, value) == expected_brightness
|
||||||
|
assert restored_values == snapshot
|
||||||
|
249
tests/util/test_scaling.py
Normal file
249
tests/util/test_scaling.py
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
"""Test Home Assistant scaling utils."""
|
||||||
|
|
||||||
|
import math
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant.util.percentage import (
|
||||||
|
scale_ranged_value_to_int_range,
|
||||||
|
scale_to_ranged_value,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("input_val", "output_val"),
|
||||||
|
[
|
||||||
|
(255, 100),
|
||||||
|
(127, 49),
|
||||||
|
(10, 3),
|
||||||
|
(1, 0),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_ranged_value_to_int_range_large(
|
||||||
|
input_val: float, output_val: int
|
||||||
|
) -> None:
|
||||||
|
"""Test a large range of low and high values convert a single value to a percentage."""
|
||||||
|
source_range = (1, 255)
|
||||||
|
dest_range = (1, 100)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
scale_ranged_value_to_int_range(source_range, dest_range, input_val)
|
||||||
|
== output_val
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("input_val", "output_val", "math_ceil"),
|
||||||
|
[
|
||||||
|
(100, 255, 255),
|
||||||
|
(50, 127.5, 128),
|
||||||
|
(4, 10.2, 11),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_scale_to_ranged_value_large(
|
||||||
|
input_val: float, output_val: float, math_ceil: int
|
||||||
|
) -> None:
|
||||||
|
"""Test a large range of low and high values convert an int to a single value."""
|
||||||
|
source_range = (1, 100)
|
||||||
|
dest_range = (1, 255)
|
||||||
|
|
||||||
|
assert scale_to_ranged_value(source_range, dest_range, input_val) == output_val
|
||||||
|
|
||||||
|
assert (
|
||||||
|
math.ceil(scale_to_ranged_value(source_range, dest_range, input_val))
|
||||||
|
== math_ceil
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("input_val", "output_val"),
|
||||||
|
[
|
||||||
|
(1, 16),
|
||||||
|
(2, 33),
|
||||||
|
(3, 50),
|
||||||
|
(4, 66),
|
||||||
|
(5, 83),
|
||||||
|
(6, 100),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_scale_ranged_value_to_int_range_small(
|
||||||
|
input_val: float, output_val: int
|
||||||
|
) -> None:
|
||||||
|
"""Test a small range of low and high values convert a single value to a percentage."""
|
||||||
|
source_range = (1, 6)
|
||||||
|
dest_range = (1, 100)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
scale_ranged_value_to_int_range(source_range, dest_range, input_val)
|
||||||
|
== output_val
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("input_val", "output_val"),
|
||||||
|
[
|
||||||
|
(16, 1),
|
||||||
|
(33, 2),
|
||||||
|
(50, 3),
|
||||||
|
(66, 4),
|
||||||
|
(83, 5),
|
||||||
|
(100, 6),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_scale_to_ranged_value_small(input_val: float, output_val: int) -> None:
|
||||||
|
"""Test a small range of low and high values convert an int to a single value."""
|
||||||
|
source_range = (1, 100)
|
||||||
|
dest_range = (1, 6)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
math.ceil(scale_to_ranged_value(source_range, dest_range, input_val))
|
||||||
|
== output_val
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("input_val", "output_val"),
|
||||||
|
[
|
||||||
|
(1, 25),
|
||||||
|
(2, 50),
|
||||||
|
(3, 75),
|
||||||
|
(4, 100),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_scale_ranged_value_to_int_range_starting_at_one(
|
||||||
|
input_val: float, output_val: int
|
||||||
|
) -> None:
|
||||||
|
"""Test a range that starts with 1."""
|
||||||
|
source_range = (1, 4)
|
||||||
|
dest_range = (1, 100)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
scale_ranged_value_to_int_range(source_range, dest_range, input_val)
|
||||||
|
== output_val
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("input_val", "output_val"),
|
||||||
|
[
|
||||||
|
(101, 0),
|
||||||
|
(139, 25),
|
||||||
|
(178, 50),
|
||||||
|
(217, 75),
|
||||||
|
(255, 100),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_scale_ranged_value_to_int_range_starting_high(
|
||||||
|
input_val: float, output_val: int
|
||||||
|
) -> None:
|
||||||
|
"""Test a range that does not start with 1."""
|
||||||
|
source_range = (101, 255)
|
||||||
|
dest_range = (1, 100)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
scale_ranged_value_to_int_range(source_range, dest_range, input_val)
|
||||||
|
== output_val
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("input_val", "output_int", "output_float"),
|
||||||
|
[
|
||||||
|
(0.0, 25, 25.0),
|
||||||
|
(1.0, 50, 50.0),
|
||||||
|
(2.0, 75, 75.0),
|
||||||
|
(3.0, 100, 100.0),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_scale_ranged_value_to_scaled_range_starting_zero(
|
||||||
|
input_val: float, output_int: int, output_float: float
|
||||||
|
) -> None:
|
||||||
|
"""Test a range that starts with 0."""
|
||||||
|
source_range = (0, 3)
|
||||||
|
dest_range = (1, 100)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
scale_ranged_value_to_int_range(source_range, dest_range, input_val)
|
||||||
|
== output_int
|
||||||
|
)
|
||||||
|
assert scale_to_ranged_value(source_range, dest_range, input_val) == output_float
|
||||||
|
assert scale_ranged_value_to_int_range(
|
||||||
|
dest_range, source_range, output_float
|
||||||
|
) == int(input_val)
|
||||||
|
assert scale_to_ranged_value(dest_range, source_range, output_float) == input_val
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("input_val", "output_val"),
|
||||||
|
[
|
||||||
|
(101, 100),
|
||||||
|
(139, 125),
|
||||||
|
(178, 150),
|
||||||
|
(217, 175),
|
||||||
|
(255, 200),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_scale_ranged_value_to_int_range_starting_high_with_offset(
|
||||||
|
input_val: float, output_val: int
|
||||||
|
) -> None:
|
||||||
|
"""Test a ranges that do not start with 1."""
|
||||||
|
source_range = (101, 255)
|
||||||
|
dest_range = (101, 200)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
scale_ranged_value_to_int_range(source_range, dest_range, input_val)
|
||||||
|
== output_val
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("input_val", "output_val"),
|
||||||
|
[
|
||||||
|
(0, 125),
|
||||||
|
(1, 150),
|
||||||
|
(2, 175),
|
||||||
|
(3, 200),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_scale_ranged_value_to_int_range_starting_zero_with_offset(
|
||||||
|
input_val: float, output_val: int
|
||||||
|
) -> None:
|
||||||
|
"""Test a range that starts with 0 and an other starting high."""
|
||||||
|
source_range = (0, 3)
|
||||||
|
dest_range = (101, 200)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
scale_ranged_value_to_int_range(source_range, dest_range, input_val)
|
||||||
|
== output_val
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("input_val", "output_int", "output_float"),
|
||||||
|
[
|
||||||
|
(0.0, 1, 1.0),
|
||||||
|
(1.0, 3, 3.0),
|
||||||
|
(2.0, 5, 5.0),
|
||||||
|
(3.0, 7, 7.0),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_scale_ranged_value_to_int_range_starting_zero_with_zero_offset(
|
||||||
|
input_val: float, output_int: int, output_float: float
|
||||||
|
) -> None:
|
||||||
|
"""Test a ranges that start with 0.
|
||||||
|
|
||||||
|
In case a range starts with 0, this means value 0 is the first value,
|
||||||
|
and the values shift -1.
|
||||||
|
"""
|
||||||
|
source_range = (0, 3)
|
||||||
|
dest_range = (0, 7)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
scale_ranged_value_to_int_range(source_range, dest_range, input_val)
|
||||||
|
== output_int
|
||||||
|
)
|
||||||
|
assert scale_to_ranged_value(source_range, dest_range, input_val) == output_float
|
||||||
|
assert scale_ranged_value_to_int_range(dest_range, source_range, output_int) == int(
|
||||||
|
input_val
|
||||||
|
)
|
||||||
|
assert scale_to_ranged_value(dest_range, source_range, output_float) == input_val
|
Loading…
x
Reference in New Issue
Block a user