mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 16:57:53 +00:00
Adjust suggested_display_precision according to unit conversion (#87614)
This commit is contained in:
parent
ea29cdfe83
commit
8f2a764a43
@ -8,7 +8,7 @@ from dataclasses import dataclass
|
||||
from datetime import date, datetime, timedelta, timezone
|
||||
from decimal import Decimal, InvalidOperation as DecimalInvalidOperation
|
||||
import logging
|
||||
from math import floor, log10
|
||||
from math import ceil, floor, log10
|
||||
import re
|
||||
from typing import Any, Final, cast, final
|
||||
|
||||
@ -679,11 +679,40 @@ class SensorEntity(Entity):
|
||||
"""Update suggested display precision stored in registry."""
|
||||
assert self.registry_entry
|
||||
|
||||
device_class = self.device_class
|
||||
display_precision = self.suggested_display_precision
|
||||
default_unit_of_measurement = (
|
||||
self.suggested_unit_of_measurement or self.native_unit_of_measurement
|
||||
)
|
||||
unit_of_measurement = self.unit_of_measurement
|
||||
|
||||
if (
|
||||
sensor_options := self.registry_entry.options.get(DOMAIN, {})
|
||||
) and sensor_options.get("suggested_display_precision") == display_precision:
|
||||
display_precision is not None
|
||||
and default_unit_of_measurement != unit_of_measurement
|
||||
and device_class in UNIT_CONVERTERS
|
||||
):
|
||||
converter = UNIT_CONVERTERS[device_class]
|
||||
|
||||
# Scale the precision when converting to a larger or smaller unit
|
||||
# For example 1.1 Wh should be rendered as 0.0011 kWh, not 0.0 kWh
|
||||
ratio_log = log10(
|
||||
converter.get_unit_ratio(
|
||||
default_unit_of_measurement, unit_of_measurement
|
||||
)
|
||||
)
|
||||
ratio_log = floor(ratio_log) if ratio_log > 0 else ceil(ratio_log)
|
||||
display_precision = max(0, display_precision + ratio_log)
|
||||
|
||||
if display_precision is None and (
|
||||
DOMAIN not in self.registry_entry.options
|
||||
or "suggested_display_precision" not in self.registry_entry.options
|
||||
):
|
||||
return
|
||||
sensor_options = self.registry_entry.options.get(DOMAIN, {})
|
||||
if (
|
||||
"suggested_display_precision" in sensor_options
|
||||
and sensor_options["suggested_display_precision"] == display_precision
|
||||
):
|
||||
return
|
||||
|
||||
registry = er.async_get(self.hass)
|
||||
@ -716,6 +745,7 @@ class SensorEntity(Entity):
|
||||
def async_registry_entry_updated(self) -> None:
|
||||
"""Run when the entity registry entry has been updated."""
|
||||
self._async_read_entity_options()
|
||||
self._update_suggested_precision()
|
||||
|
||||
@callback
|
||||
def _async_read_entity_options(self) -> None:
|
||||
|
@ -1143,27 +1143,46 @@ async def test_unit_conversion_priority_suggested_unit_change(
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"native_unit, suggested_precision, native_value, device_class",
|
||||
"unit_system, native_unit, integration_suggested_precision,"
|
||||
"options_suggested_precision, native_value, device_class, extra_options",
|
||||
[
|
||||
# Distance
|
||||
(
|
||||
METRIC_SYSTEM,
|
||||
UnitOfLength.KILOMETERS,
|
||||
4,
|
||||
4,
|
||||
1000,
|
||||
SensorDeviceClass.DISTANCE,
|
||||
{},
|
||||
),
|
||||
# Air pressure
|
||||
(
|
||||
US_CUSTOMARY_SYSTEM,
|
||||
UnitOfPressure.HPA,
|
||||
0,
|
||||
1,
|
||||
1000,
|
||||
SensorDeviceClass.ATMOSPHERIC_PRESSURE,
|
||||
{"sensor.private": {"suggested_unit_of_measurement": "inHg"}},
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_suggested_precision_option(
|
||||
hass,
|
||||
enable_custom_integrations,
|
||||
unit_system,
|
||||
native_unit,
|
||||
suggested_precision,
|
||||
integration_suggested_precision,
|
||||
options_suggested_precision,
|
||||
native_value,
|
||||
device_class,
|
||||
extra_options,
|
||||
):
|
||||
"""Test suggested precision is stored in the registry."""
|
||||
|
||||
hass.config.units = unit_system
|
||||
|
||||
entity_registry = er.async_get(hass)
|
||||
platform = getattr(hass.components, "test.sensor")
|
||||
platform.init(empty=True)
|
||||
@ -1173,7 +1192,7 @@ async def test_suggested_precision_option(
|
||||
device_class=device_class,
|
||||
native_unit_of_measurement=native_unit,
|
||||
native_value=str(native_value),
|
||||
suggested_display_precision=suggested_precision,
|
||||
suggested_display_precision=integration_suggested_precision,
|
||||
unique_id="very_unique",
|
||||
)
|
||||
entity0 = platform.ENTITIES["0"]
|
||||
@ -1183,34 +1202,58 @@ async def test_suggested_precision_option(
|
||||
|
||||
# Assert the suggested precision is stored in the registry
|
||||
entry = entity_registry.async_get(entity0.entity_id)
|
||||
assert entry.options == {
|
||||
"sensor": {"suggested_display_precision": suggested_precision}
|
||||
assert entry.options == extra_options | {
|
||||
"sensor": {"suggested_display_precision": options_suggested_precision}
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"native_unit, old_precision, new_precision, native_value, device_class",
|
||||
"unit_system, native_unit, suggested_unit, old_precision, new_precision,"
|
||||
"opt_precision, native_value, device_class, extra_options",
|
||||
[
|
||||
# Distance
|
||||
(
|
||||
METRIC_SYSTEM,
|
||||
UnitOfLength.KILOMETERS,
|
||||
UnitOfLength.KILOMETERS,
|
||||
4,
|
||||
1,
|
||||
1,
|
||||
1000,
|
||||
SensorDeviceClass.DISTANCE,
|
||||
{},
|
||||
),
|
||||
# Air pressure
|
||||
(
|
||||
US_CUSTOMARY_SYSTEM,
|
||||
UnitOfPressure.HPA,
|
||||
UnitOfPressure.INHG,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
1000,
|
||||
SensorDeviceClass.ATMOSPHERIC_PRESSURE,
|
||||
{"sensor.private": {"suggested_unit_of_measurement": "inHg"}},
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_suggested_precision_option_update(
|
||||
hass,
|
||||
enable_custom_integrations,
|
||||
unit_system,
|
||||
native_unit,
|
||||
suggested_unit,
|
||||
old_precision,
|
||||
new_precision,
|
||||
opt_precision,
|
||||
native_value,
|
||||
device_class,
|
||||
extra_options,
|
||||
):
|
||||
"""Test suggested precision stored in the registry is updated."""
|
||||
|
||||
hass.config.units = unit_system
|
||||
|
||||
entity_registry = er.async_get(hass)
|
||||
platform = getattr(hass.components, "test.sensor")
|
||||
platform.init(empty=True)
|
||||
@ -1228,7 +1271,7 @@ async def test_suggested_precision_option_update(
|
||||
entry.entity_id,
|
||||
"sensor.private",
|
||||
{
|
||||
"suggested_unit_of_measurement": native_unit,
|
||||
"suggested_unit_of_measurement": suggested_unit,
|
||||
},
|
||||
)
|
||||
|
||||
@ -1249,10 +1292,10 @@ async def test_suggested_precision_option_update(
|
||||
entry = entity_registry.async_get(entity0.entity_id)
|
||||
assert entry.options == {
|
||||
"sensor": {
|
||||
"suggested_display_precision": new_precision,
|
||||
"suggested_display_precision": opt_precision,
|
||||
},
|
||||
"sensor.private": {
|
||||
"suggested_unit_of_measurement": native_unit,
|
||||
"suggested_unit_of_measurement": suggested_unit,
|
||||
},
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user