mirror of
https://github.com/home-assistant/core.git
synced 2025-11-14 21:40:16 +00:00
Add default device class display precision for Sensor (#145013)
* Add default device class display precision for Sensor * Renaming, docstrings, cleanup * Simplify units list * Fix tests * Fix missing precision when suggested is specified * Update snapshots * Fix when unit of measurement is not valid * Fix tests * Fix deprecated unit usage * Fix goalzero tests The sensor native_value method was accessing the data dict and trowing, since the mock did not have any data for the sensors. Since now the precision is always specified (it was missing for those sensors), the throw was hitting async_update_entity_options in _update_suggested_precision. Previously, async_update_entity_options was not called since it had no precision. * Fix metoffice * Fix smartthings * Add default sensor data for Tesla Wall Connector tests * Update snapshots * Revert spaces * Update smartthings snapshots * Add missing sensor mock for tesla wall connector * Address review comments * Add doc comment * Add cap to doc comment * Update comment * Update snapshots * Update comment
This commit is contained in:
@@ -31,12 +31,25 @@ from homeassistant.const import (
|
||||
PERCENTAGE,
|
||||
STATE_UNKNOWN,
|
||||
EntityCategory,
|
||||
UnitOfApparentPower,
|
||||
UnitOfArea,
|
||||
UnitOfBloodGlucoseConcentration,
|
||||
UnitOfConductivity,
|
||||
UnitOfDataRate,
|
||||
UnitOfElectricCurrent,
|
||||
UnitOfElectricPotential,
|
||||
UnitOfEnergy,
|
||||
UnitOfEnergyDistance,
|
||||
UnitOfFrequency,
|
||||
UnitOfInformation,
|
||||
UnitOfIrradiance,
|
||||
UnitOfLength,
|
||||
UnitOfMass,
|
||||
UnitOfPower,
|
||||
UnitOfPrecipitationDepth,
|
||||
UnitOfPressure,
|
||||
UnitOfReactivePower,
|
||||
UnitOfSoundPressure,
|
||||
UnitOfSpeed,
|
||||
UnitOfTemperature,
|
||||
UnitOfTime,
|
||||
@@ -78,28 +91,28 @@ TEST_DOMAIN = "test"
|
||||
UnitOfTemperature.FAHRENHEIT,
|
||||
UnitOfTemperature.FAHRENHEIT,
|
||||
100,
|
||||
"100",
|
||||
100,
|
||||
),
|
||||
(
|
||||
US_CUSTOMARY_SYSTEM,
|
||||
UnitOfTemperature.CELSIUS,
|
||||
UnitOfTemperature.FAHRENHEIT,
|
||||
38,
|
||||
"100",
|
||||
100.4,
|
||||
),
|
||||
(
|
||||
METRIC_SYSTEM,
|
||||
UnitOfTemperature.FAHRENHEIT,
|
||||
UnitOfTemperature.CELSIUS,
|
||||
100,
|
||||
"38",
|
||||
pytest.approx(37.77778),
|
||||
),
|
||||
(
|
||||
METRIC_SYSTEM,
|
||||
UnitOfTemperature.CELSIUS,
|
||||
UnitOfTemperature.CELSIUS,
|
||||
38,
|
||||
"38",
|
||||
38,
|
||||
),
|
||||
],
|
||||
)
|
||||
@@ -125,7 +138,7 @@ async def test_temperature_conversion(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity0.entity_id)
|
||||
assert state.state == state_value
|
||||
assert float(state.state) == state_value
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == state_unit
|
||||
|
||||
|
||||
@@ -593,6 +606,8 @@ async def test_unit_translation_key_without_platform_raises(
|
||||
"state_unit",
|
||||
"native_value",
|
||||
"custom_state",
|
||||
"rounded_state",
|
||||
"suggested_precision",
|
||||
),
|
||||
[
|
||||
# Smaller to larger unit, InHg is ~33x larger than hPa -> 1 more decimal
|
||||
@@ -602,7 +617,9 @@ async def test_unit_translation_key_without_platform_raises(
|
||||
UnitOfPressure.INHG,
|
||||
UnitOfPressure.INHG,
|
||||
1000.0,
|
||||
pytest.approx(29.52998),
|
||||
"29.53",
|
||||
2,
|
||||
),
|
||||
(
|
||||
SensorDeviceClass.PRESSURE,
|
||||
@@ -610,7 +627,19 @@ async def test_unit_translation_key_without_platform_raises(
|
||||
UnitOfPressure.HPA,
|
||||
UnitOfPressure.HPA,
|
||||
1.234,
|
||||
"12.340",
|
||||
12.34,
|
||||
"12.34",
|
||||
2,
|
||||
),
|
||||
(
|
||||
SensorDeviceClass.PRESSURE,
|
||||
UnitOfPressure.HPA,
|
||||
UnitOfPressure.PA,
|
||||
UnitOfPressure.PA,
|
||||
1.234,
|
||||
123.4,
|
||||
"123",
|
||||
0,
|
||||
),
|
||||
(
|
||||
SensorDeviceClass.ATMOSPHERIC_PRESSURE,
|
||||
@@ -618,7 +647,9 @@ async def test_unit_translation_key_without_platform_raises(
|
||||
UnitOfPressure.MMHG,
|
||||
UnitOfPressure.MMHG,
|
||||
1000,
|
||||
"750",
|
||||
pytest.approx(750.061575),
|
||||
"750.06",
|
||||
2,
|
||||
),
|
||||
(
|
||||
SensorDeviceClass.PRESSURE,
|
||||
@@ -626,7 +657,9 @@ async def test_unit_translation_key_without_platform_raises(
|
||||
UnitOfPressure.MMHG,
|
||||
UnitOfPressure.MMHG,
|
||||
1000,
|
||||
"750",
|
||||
pytest.approx(750.061575),
|
||||
"750.06",
|
||||
2,
|
||||
),
|
||||
# Not a supported pressure unit
|
||||
(
|
||||
@@ -635,7 +668,9 @@ async def test_unit_translation_key_without_platform_raises(
|
||||
"peer_pressure",
|
||||
UnitOfPressure.HPA,
|
||||
1000,
|
||||
"1000",
|
||||
1000,
|
||||
"1000.00",
|
||||
2,
|
||||
),
|
||||
(
|
||||
SensorDeviceClass.TEMPERATURE,
|
||||
@@ -643,7 +678,9 @@ async def test_unit_translation_key_without_platform_raises(
|
||||
UnitOfTemperature.FAHRENHEIT,
|
||||
UnitOfTemperature.FAHRENHEIT,
|
||||
37.5,
|
||||
99.5,
|
||||
"99.5",
|
||||
1,
|
||||
),
|
||||
(
|
||||
SensorDeviceClass.TEMPERATURE,
|
||||
@@ -651,7 +688,9 @@ async def test_unit_translation_key_without_platform_raises(
|
||||
UnitOfTemperature.CELSIUS,
|
||||
UnitOfTemperature.CELSIUS,
|
||||
100,
|
||||
"38",
|
||||
pytest.approx(37.77777),
|
||||
"37.8",
|
||||
1,
|
||||
),
|
||||
(
|
||||
SensorDeviceClass.ATMOSPHERIC_PRESSURE,
|
||||
@@ -659,7 +698,9 @@ async def test_unit_translation_key_without_platform_raises(
|
||||
UnitOfPressure.HPA,
|
||||
UnitOfPressure.HPA,
|
||||
-0.00,
|
||||
"0.0",
|
||||
0.0,
|
||||
"0.00",
|
||||
2,
|
||||
),
|
||||
(
|
||||
SensorDeviceClass.ATMOSPHERIC_PRESSURE,
|
||||
@@ -667,7 +708,9 @@ async def test_unit_translation_key_without_platform_raises(
|
||||
UnitOfPressure.HPA,
|
||||
UnitOfPressure.HPA,
|
||||
-0.00001,
|
||||
"0",
|
||||
pytest.approx(-0.0003386388),
|
||||
"0.00",
|
||||
2,
|
||||
),
|
||||
(
|
||||
SensorDeviceClass.VOLUME_FLOW_RATE,
|
||||
@@ -675,7 +718,9 @@ async def test_unit_translation_key_without_platform_raises(
|
||||
UnitOfVolumeFlowRate.GALLONS_PER_MINUTE,
|
||||
UnitOfVolumeFlowRate.GALLONS_PER_MINUTE,
|
||||
50.0,
|
||||
"13.2",
|
||||
pytest.approx(13.208602),
|
||||
"13",
|
||||
0,
|
||||
),
|
||||
(
|
||||
SensorDeviceClass.VOLUME_FLOW_RATE,
|
||||
@@ -683,7 +728,9 @@ async def test_unit_translation_key_without_platform_raises(
|
||||
UnitOfVolumeFlowRate.LITERS_PER_MINUTE,
|
||||
UnitOfVolumeFlowRate.LITERS_PER_MINUTE,
|
||||
13.0,
|
||||
"49.2",
|
||||
pytest.approx(49.2103531),
|
||||
"49",
|
||||
0,
|
||||
),
|
||||
(
|
||||
SensorDeviceClass.DURATION,
|
||||
@@ -691,7 +738,9 @@ async def test_unit_translation_key_without_platform_raises(
|
||||
UnitOfTime.HOURS,
|
||||
UnitOfTime.HOURS,
|
||||
5400.0,
|
||||
"1.5000",
|
||||
1.5,
|
||||
"1.50",
|
||||
2,
|
||||
),
|
||||
(
|
||||
SensorDeviceClass.DURATION,
|
||||
@@ -699,7 +748,29 @@ async def test_unit_translation_key_without_platform_raises(
|
||||
UnitOfTime.MINUTES,
|
||||
UnitOfTime.MINUTES,
|
||||
0.5,
|
||||
"720.0",
|
||||
720,
|
||||
"720.00",
|
||||
2,
|
||||
),
|
||||
(
|
||||
SensorDeviceClass.BLOOD_GLUCOSE_CONCENTRATION,
|
||||
UnitOfBloodGlucoseConcentration.MILLIGRAMS_PER_DECILITER,
|
||||
UnitOfBloodGlucoseConcentration.MILLIMOLE_PER_LITER,
|
||||
UnitOfBloodGlucoseConcentration.MILLIMOLE_PER_LITER,
|
||||
130,
|
||||
pytest.approx(7.222222),
|
||||
"7.2",
|
||||
1,
|
||||
),
|
||||
(
|
||||
SensorDeviceClass.ENERGY,
|
||||
UnitOfEnergy.WATT_HOUR,
|
||||
UnitOfEnergy.KILO_WATT_HOUR,
|
||||
UnitOfEnergy.KILO_WATT_HOUR,
|
||||
1.1,
|
||||
0.0011,
|
||||
"0.00",
|
||||
2,
|
||||
),
|
||||
],
|
||||
)
|
||||
@@ -712,6 +783,8 @@ async def test_custom_unit(
|
||||
state_unit,
|
||||
native_value,
|
||||
custom_state,
|
||||
rounded_state,
|
||||
suggested_precision,
|
||||
) -> None:
|
||||
"""Test custom unit."""
|
||||
entry = entity_registry.async_get_or_create("sensor", "test", "very_unique")
|
||||
@@ -734,13 +807,17 @@ async def test_custom_unit(
|
||||
|
||||
entity_id = entity0.entity_id
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == custom_state
|
||||
assert float(state.state) == custom_state
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == state_unit
|
||||
|
||||
assert (
|
||||
async_rounded_state(hass, entity_id, hass.states.get(entity_id)) == custom_state
|
||||
async_rounded_state(hass, entity_id, hass.states.get(entity_id))
|
||||
== rounded_state
|
||||
)
|
||||
|
||||
entry = entity_registry.async_get(entity0.entity_id)
|
||||
assert entry.options["sensor"]["suggested_display_precision"] == suggested_precision
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
(
|
||||
@@ -759,8 +836,8 @@ async def test_custom_unit(
|
||||
UnitOfArea.SQUARE_MILES,
|
||||
UnitOfArea.SQUARE_MILES,
|
||||
1000,
|
||||
"1000",
|
||||
"386",
|
||||
1000,
|
||||
pytest.approx(386.102),
|
||||
SensorDeviceClass.AREA,
|
||||
),
|
||||
(
|
||||
@@ -768,8 +845,8 @@ async def test_custom_unit(
|
||||
UnitOfArea.SQUARE_INCHES,
|
||||
UnitOfArea.SQUARE_INCHES,
|
||||
7.24,
|
||||
"7.24",
|
||||
"1.12",
|
||||
7.24,
|
||||
pytest.approx(1.1222022),
|
||||
SensorDeviceClass.AREA,
|
||||
),
|
||||
(
|
||||
@@ -777,8 +854,8 @@ async def test_custom_unit(
|
||||
"peer_distance",
|
||||
UnitOfArea.SQUARE_KILOMETERS,
|
||||
1000,
|
||||
"1000",
|
||||
"1000",
|
||||
1000,
|
||||
1000,
|
||||
SensorDeviceClass.AREA,
|
||||
),
|
||||
# Distance
|
||||
@@ -787,8 +864,8 @@ async def test_custom_unit(
|
||||
UnitOfLength.MILES,
|
||||
UnitOfLength.MILES,
|
||||
1000,
|
||||
"1000",
|
||||
"621",
|
||||
1000,
|
||||
pytest.approx(621.371),
|
||||
SensorDeviceClass.DISTANCE,
|
||||
),
|
||||
(
|
||||
@@ -796,8 +873,8 @@ async def test_custom_unit(
|
||||
UnitOfLength.INCHES,
|
||||
UnitOfLength.INCHES,
|
||||
7.24,
|
||||
"7.24",
|
||||
"2.85",
|
||||
7.24,
|
||||
pytest.approx(2.8503937),
|
||||
SensorDeviceClass.DISTANCE,
|
||||
),
|
||||
(
|
||||
@@ -805,8 +882,8 @@ async def test_custom_unit(
|
||||
"peer_distance",
|
||||
UnitOfLength.KILOMETERS,
|
||||
1000,
|
||||
"1000",
|
||||
"1000",
|
||||
1000,
|
||||
1000,
|
||||
SensorDeviceClass.DISTANCE,
|
||||
),
|
||||
# Energy
|
||||
@@ -815,8 +892,8 @@ async def test_custom_unit(
|
||||
UnitOfEnergy.MEGA_WATT_HOUR,
|
||||
UnitOfEnergy.MEGA_WATT_HOUR,
|
||||
1000,
|
||||
"1000",
|
||||
"1.000",
|
||||
1000,
|
||||
1.000,
|
||||
SensorDeviceClass.ENERGY,
|
||||
),
|
||||
(
|
||||
@@ -824,8 +901,8 @@ async def test_custom_unit(
|
||||
UnitOfEnergy.MEGA_WATT_HOUR,
|
||||
UnitOfEnergy.MEGA_WATT_HOUR,
|
||||
1000,
|
||||
"1000",
|
||||
"278",
|
||||
1000,
|
||||
pytest.approx(277.7778),
|
||||
SensorDeviceClass.ENERGY,
|
||||
),
|
||||
(
|
||||
@@ -833,8 +910,8 @@ async def test_custom_unit(
|
||||
"BTU",
|
||||
UnitOfEnergy.KILO_WATT_HOUR,
|
||||
1000,
|
||||
"1000",
|
||||
"1000",
|
||||
1000,
|
||||
1000,
|
||||
SensorDeviceClass.ENERGY,
|
||||
),
|
||||
# Power factor
|
||||
@@ -843,8 +920,8 @@ async def test_custom_unit(
|
||||
PERCENTAGE,
|
||||
PERCENTAGE,
|
||||
1.0,
|
||||
"1.0",
|
||||
"100.0",
|
||||
1.0,
|
||||
100.0,
|
||||
SensorDeviceClass.POWER_FACTOR,
|
||||
),
|
||||
(
|
||||
@@ -852,8 +929,8 @@ async def test_custom_unit(
|
||||
None,
|
||||
None,
|
||||
100,
|
||||
"100",
|
||||
"1.00",
|
||||
100,
|
||||
1.00,
|
||||
SensorDeviceClass.POWER_FACTOR,
|
||||
),
|
||||
(
|
||||
@@ -861,8 +938,8 @@ async def test_custom_unit(
|
||||
None,
|
||||
"Cos φ",
|
||||
1.0,
|
||||
"1.0",
|
||||
"1.0",
|
||||
1.0,
|
||||
1.0,
|
||||
SensorDeviceClass.POWER_FACTOR,
|
||||
),
|
||||
# Pressure
|
||||
@@ -872,8 +949,8 @@ async def test_custom_unit(
|
||||
UnitOfPressure.INHG,
|
||||
UnitOfPressure.INHG,
|
||||
1000.0,
|
||||
"1000.0",
|
||||
"29.53",
|
||||
1000.0,
|
||||
pytest.approx(29.52998),
|
||||
SensorDeviceClass.PRESSURE,
|
||||
),
|
||||
(
|
||||
@@ -881,8 +958,8 @@ async def test_custom_unit(
|
||||
UnitOfPressure.HPA,
|
||||
UnitOfPressure.HPA,
|
||||
1.234,
|
||||
"1.234",
|
||||
"12.340",
|
||||
1.234,
|
||||
12.340,
|
||||
SensorDeviceClass.PRESSURE,
|
||||
),
|
||||
(
|
||||
@@ -890,8 +967,8 @@ async def test_custom_unit(
|
||||
UnitOfPressure.MMHG,
|
||||
UnitOfPressure.MMHG,
|
||||
1000,
|
||||
"1000",
|
||||
"750",
|
||||
1000,
|
||||
pytest.approx(750.0615),
|
||||
SensorDeviceClass.PRESSURE,
|
||||
),
|
||||
# Not a supported pressure unit
|
||||
@@ -900,8 +977,8 @@ async def test_custom_unit(
|
||||
"peer_pressure",
|
||||
UnitOfPressure.HPA,
|
||||
1000,
|
||||
"1000",
|
||||
"1000",
|
||||
1000,
|
||||
1000,
|
||||
SensorDeviceClass.PRESSURE,
|
||||
),
|
||||
# Speed
|
||||
@@ -910,8 +987,8 @@ async def test_custom_unit(
|
||||
UnitOfSpeed.MILES_PER_HOUR,
|
||||
UnitOfSpeed.MILES_PER_HOUR,
|
||||
100,
|
||||
"100",
|
||||
"62",
|
||||
100,
|
||||
pytest.approx(62.1371),
|
||||
SensorDeviceClass.SPEED,
|
||||
),
|
||||
(
|
||||
@@ -919,8 +996,8 @@ async def test_custom_unit(
|
||||
UnitOfVolumetricFlux.INCHES_PER_HOUR,
|
||||
UnitOfVolumetricFlux.INCHES_PER_HOUR,
|
||||
78,
|
||||
"78",
|
||||
"0.13",
|
||||
78,
|
||||
pytest.approx(0.127952755),
|
||||
SensorDeviceClass.SPEED,
|
||||
),
|
||||
(
|
||||
@@ -928,8 +1005,8 @@ async def test_custom_unit(
|
||||
"peer_distance",
|
||||
UnitOfSpeed.KILOMETERS_PER_HOUR,
|
||||
100,
|
||||
"100",
|
||||
"100",
|
||||
100,
|
||||
100,
|
||||
SensorDeviceClass.SPEED,
|
||||
),
|
||||
# Volume
|
||||
@@ -938,8 +1015,8 @@ async def test_custom_unit(
|
||||
UnitOfVolume.CUBIC_FEET,
|
||||
UnitOfVolume.CUBIC_FEET,
|
||||
100,
|
||||
"100",
|
||||
"3531",
|
||||
100,
|
||||
pytest.approx(3531.4667),
|
||||
SensorDeviceClass.VOLUME,
|
||||
),
|
||||
(
|
||||
@@ -947,8 +1024,8 @@ async def test_custom_unit(
|
||||
UnitOfVolume.FLUID_OUNCES,
|
||||
UnitOfVolume.FLUID_OUNCES,
|
||||
2.3,
|
||||
"2.3",
|
||||
"77.8",
|
||||
2.3,
|
||||
pytest.approx(77.77225),
|
||||
SensorDeviceClass.VOLUME,
|
||||
),
|
||||
(
|
||||
@@ -956,8 +1033,8 @@ async def test_custom_unit(
|
||||
"peer_distance",
|
||||
UnitOfVolume.CUBIC_METERS,
|
||||
100,
|
||||
"100",
|
||||
"100",
|
||||
100,
|
||||
100,
|
||||
SensorDeviceClass.VOLUME,
|
||||
),
|
||||
# Weight
|
||||
@@ -966,8 +1043,8 @@ async def test_custom_unit(
|
||||
UnitOfMass.OUNCES,
|
||||
UnitOfMass.OUNCES,
|
||||
100,
|
||||
"100",
|
||||
"3.5",
|
||||
100,
|
||||
pytest.approx(3.5273962),
|
||||
SensorDeviceClass.WEIGHT,
|
||||
),
|
||||
(
|
||||
@@ -975,8 +1052,8 @@ async def test_custom_unit(
|
||||
UnitOfMass.GRAMS,
|
||||
UnitOfMass.GRAMS,
|
||||
78,
|
||||
"78",
|
||||
"2211",
|
||||
78,
|
||||
pytest.approx(2211.262),
|
||||
SensorDeviceClass.WEIGHT,
|
||||
),
|
||||
(
|
||||
@@ -984,8 +1061,8 @@ async def test_custom_unit(
|
||||
"peer_distance",
|
||||
UnitOfMass.GRAMS,
|
||||
100,
|
||||
"100",
|
||||
"100",
|
||||
100,
|
||||
100,
|
||||
SensorDeviceClass.WEIGHT,
|
||||
),
|
||||
],
|
||||
@@ -1015,7 +1092,7 @@ async def test_custom_unit_change(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity0.entity_id)
|
||||
assert state.state == native_state
|
||||
assert float(state.state) == native_state
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == native_unit
|
||||
|
||||
entity_registry.async_update_entity_options(
|
||||
@@ -1024,7 +1101,7 @@ async def test_custom_unit_change(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity0.entity_id)
|
||||
assert state.state == custom_state
|
||||
assert float(state.state) == custom_state
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == state_unit
|
||||
|
||||
entity_registry.async_update_entity_options(
|
||||
@@ -1033,14 +1110,14 @@ async def test_custom_unit_change(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity0.entity_id)
|
||||
assert state.state == native_state
|
||||
assert float(state.state) == native_state
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == native_unit
|
||||
|
||||
entity_registry.async_update_entity_options("sensor.test", "sensor", None)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity0.entity_id)
|
||||
assert state.state == native_state
|
||||
assert float(state.state) == native_state
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == native_unit
|
||||
|
||||
|
||||
@@ -1067,10 +1144,10 @@ async def test_custom_unit_change(
|
||||
UnitOfLength.METERS,
|
||||
UnitOfLength.YARDS,
|
||||
1000,
|
||||
"1000",
|
||||
"621",
|
||||
"1000000",
|
||||
"1093613",
|
||||
1000,
|
||||
pytest.approx(621.371),
|
||||
1000000,
|
||||
pytest.approx(1093613),
|
||||
SensorDeviceClass.DISTANCE,
|
||||
),
|
||||
# Volume Storage (subclass of Volume)
|
||||
@@ -1081,10 +1158,10 @@ async def test_custom_unit_change(
|
||||
UnitOfVolume.GALLONS,
|
||||
UnitOfVolume.FLUID_OUNCES,
|
||||
1000,
|
||||
"1000",
|
||||
"264",
|
||||
"264",
|
||||
"33814",
|
||||
1000,
|
||||
pytest.approx(264.172),
|
||||
pytest.approx(264.172),
|
||||
pytest.approx(33814.022),
|
||||
SensorDeviceClass.VOLUME_STORAGE,
|
||||
),
|
||||
],
|
||||
@@ -1152,34 +1229,36 @@ async def test_unit_conversion_priority(
|
||||
|
||||
# Registered entity -> Follow automatic unit conversion
|
||||
state = hass.states.get(entity0.entity_id)
|
||||
assert state.state == automatic_state
|
||||
assert float(state.state) == automatic_state
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == automatic_unit
|
||||
# Assert the automatic unit conversion is stored in the registry
|
||||
entry = entity_registry.async_get(entity0.entity_id)
|
||||
assert entry.unit_of_measurement == automatic_unit
|
||||
assert entry.options == {
|
||||
"sensor.private": {"suggested_unit_of_measurement": automatic_unit}
|
||||
}
|
||||
assert (
|
||||
entry.options["sensor.private"]["suggested_unit_of_measurement"]
|
||||
== automatic_unit
|
||||
)
|
||||
|
||||
# Unregistered entity -> Follow native unit
|
||||
state = hass.states.get(entity1.entity_id)
|
||||
assert state.state == native_state
|
||||
assert float(state.state) == native_state
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == native_unit
|
||||
|
||||
# Registered entity with suggested unit
|
||||
state = hass.states.get(entity2.entity_id)
|
||||
assert state.state == suggested_state
|
||||
assert float(state.state) == suggested_state
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == suggested_unit
|
||||
# Assert the suggested unit is stored in the registry
|
||||
entry = entity_registry.async_get(entity2.entity_id)
|
||||
assert entry.unit_of_measurement == suggested_unit
|
||||
assert entry.options == {
|
||||
"sensor.private": {"suggested_unit_of_measurement": suggested_unit}
|
||||
}
|
||||
assert (
|
||||
entry.options["sensor.private"]["suggested_unit_of_measurement"]
|
||||
== suggested_unit
|
||||
)
|
||||
|
||||
# Unregistered entity with suggested unit
|
||||
state = hass.states.get(entity3.entity_id)
|
||||
assert state.state == suggested_state
|
||||
assert float(state.state) == suggested_state
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == suggested_unit
|
||||
|
||||
# Set a custom unit, this should have priority over the automatic unit conversion
|
||||
@@ -1189,7 +1268,7 @@ async def test_unit_conversion_priority(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity0.entity_id)
|
||||
assert state.state == custom_state
|
||||
assert float(state.state) == custom_state
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == custom_unit
|
||||
|
||||
entity_registry.async_update_entity_options(
|
||||
@@ -1198,7 +1277,7 @@ async def test_unit_conversion_priority(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity2.entity_id)
|
||||
assert state.state == custom_state
|
||||
assert float(state.state) == custom_state
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == custom_unit
|
||||
|
||||
|
||||
@@ -1387,7 +1466,6 @@ async def test_unit_conversion_priority_precision(
|
||||
{"display_precision": 4},
|
||||
)
|
||||
entry4 = entity_registry.async_get(entity4.entity_id)
|
||||
assert "suggested_display_precision" not in entry4.options["sensor"]
|
||||
assert entry4.options["sensor"]["display_precision"] == 4
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity4.entity_id)
|
||||
@@ -1479,9 +1557,10 @@ async def test_unit_conversion_priority_suggested_unit_change(
|
||||
# Assert the suggested unit is stored in the registry
|
||||
entry = entity_registry.async_get(entity0.entity_id)
|
||||
assert entry.unit_of_measurement == original_unit
|
||||
assert entry.options == {
|
||||
"sensor.private": {"suggested_unit_of_measurement": original_unit},
|
||||
}
|
||||
assert (
|
||||
entry.options["sensor.private"]["suggested_unit_of_measurement"]
|
||||
== original_unit
|
||||
)
|
||||
|
||||
# Registered entity -> Follow suggested unit the first time the entity was seen
|
||||
state = hass.states.get(entity1.entity_id)
|
||||
@@ -1490,9 +1569,10 @@ async def test_unit_conversion_priority_suggested_unit_change(
|
||||
# Assert the suggested unit is stored in the registry
|
||||
entry = entity_registry.async_get(entity1.entity_id)
|
||||
assert entry.unit_of_measurement == original_unit
|
||||
assert entry.options == {
|
||||
"sensor.private": {"suggested_unit_of_measurement": original_unit},
|
||||
}
|
||||
assert (
|
||||
entry.options["sensor.private"]["suggested_unit_of_measurement"]
|
||||
== original_unit
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -1574,9 +1654,10 @@ async def test_unit_conversion_priority_suggested_unit_change_2(
|
||||
# Assert the suggested unit is stored in the registry
|
||||
entry = entity_registry.async_get(entity0.entity_id)
|
||||
assert entry.unit_of_measurement == native_unit_1
|
||||
assert entry.options == {
|
||||
"sensor.private": {"suggested_unit_of_measurement": native_unit_1},
|
||||
}
|
||||
assert (
|
||||
entry.options["sensor.private"]["suggested_unit_of_measurement"]
|
||||
== native_unit_1
|
||||
)
|
||||
|
||||
# Registered entity -> Follow unit in entity registry
|
||||
state = hass.states.get(entity1.entity_id)
|
||||
@@ -1585,9 +1666,89 @@ async def test_unit_conversion_priority_suggested_unit_change_2(
|
||||
# Assert the suggested unit is stored in the registry
|
||||
entry = entity_registry.async_get(entity0.entity_id)
|
||||
assert entry.unit_of_measurement == native_unit_1
|
||||
assert entry.options == {
|
||||
"sensor.private": {"suggested_unit_of_measurement": native_unit_1},
|
||||
}
|
||||
assert (
|
||||
entry.options["sensor.private"]["suggested_unit_of_measurement"]
|
||||
== native_unit_1
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
(
|
||||
"device_class",
|
||||
"native_unit",
|
||||
"suggested_precision",
|
||||
),
|
||||
[
|
||||
(SensorDeviceClass.APPARENT_POWER, UnitOfApparentPower.VOLT_AMPERE, 0),
|
||||
(SensorDeviceClass.AREA, UnitOfArea.SQUARE_CENTIMETERS, 0),
|
||||
(SensorDeviceClass.ATMOSPHERIC_PRESSURE, UnitOfPressure.PA, 0),
|
||||
(
|
||||
SensorDeviceClass.BLOOD_GLUCOSE_CONCENTRATION,
|
||||
UnitOfBloodGlucoseConcentration.MILLIGRAMS_PER_DECILITER,
|
||||
0,
|
||||
),
|
||||
(SensorDeviceClass.CONDUCTIVITY, UnitOfConductivity.MICROSIEMENS, 1),
|
||||
(SensorDeviceClass.CURRENT, UnitOfElectricCurrent.MILLIAMPERE, 0),
|
||||
(SensorDeviceClass.DATA_RATE, UnitOfDataRate.KILOBITS_PER_SECOND, 0),
|
||||
(SensorDeviceClass.DATA_SIZE, UnitOfInformation.KILOBITS, 0),
|
||||
(SensorDeviceClass.DISTANCE, UnitOfLength.CENTIMETERS, 0),
|
||||
(SensorDeviceClass.DURATION, UnitOfTime.MILLISECONDS, 0),
|
||||
(SensorDeviceClass.ENERGY, UnitOfEnergy.WATT_HOUR, 0),
|
||||
(
|
||||
SensorDeviceClass.ENERGY_DISTANCE,
|
||||
UnitOfEnergyDistance.KM_PER_KILO_WATT_HOUR,
|
||||
0,
|
||||
),
|
||||
(SensorDeviceClass.ENERGY_STORAGE, UnitOfEnergy.WATT_HOUR, 0),
|
||||
(SensorDeviceClass.FREQUENCY, UnitOfFrequency.HERTZ, 0),
|
||||
(SensorDeviceClass.GAS, UnitOfVolume.MILLILITERS, 0),
|
||||
(SensorDeviceClass.IRRADIANCE, UnitOfIrradiance.WATTS_PER_SQUARE_METER, 0),
|
||||
(SensorDeviceClass.POWER, UnitOfPower.WATT, 0),
|
||||
(SensorDeviceClass.PRECIPITATION, UnitOfPrecipitationDepth.CENTIMETERS, 0),
|
||||
(
|
||||
SensorDeviceClass.PRECIPITATION_INTENSITY,
|
||||
UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR,
|
||||
0,
|
||||
),
|
||||
(SensorDeviceClass.PRESSURE, UnitOfPressure.PA, 0),
|
||||
(SensorDeviceClass.REACTIVE_POWER, UnitOfReactivePower.VOLT_AMPERE_REACTIVE, 0),
|
||||
(SensorDeviceClass.SOUND_PRESSURE, UnitOfSoundPressure.DECIBEL, 0),
|
||||
(SensorDeviceClass.SPEED, UnitOfSpeed.MILLIMETERS_PER_SECOND, 0),
|
||||
(SensorDeviceClass.TEMPERATURE, UnitOfTemperature.KELVIN, 1),
|
||||
(SensorDeviceClass.VOLTAGE, UnitOfElectricPotential.VOLT, 0),
|
||||
(SensorDeviceClass.VOLUME, UnitOfVolume.MILLILITERS, 0),
|
||||
(SensorDeviceClass.VOLUME_FLOW_RATE, UnitOfVolumeFlowRate.LITERS_PER_SECOND, 0),
|
||||
(SensorDeviceClass.VOLUME_STORAGE, UnitOfVolume.MILLILITERS, 0),
|
||||
(SensorDeviceClass.WATER, UnitOfVolume.MILLILITERS, 0),
|
||||
(SensorDeviceClass.WEIGHT, UnitOfMass.GRAMS, 0),
|
||||
(SensorDeviceClass.WIND_SPEED, UnitOfSpeed.MILLIMETERS_PER_SECOND, 0),
|
||||
],
|
||||
)
|
||||
async def test_default_precision(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
device_class: str,
|
||||
native_unit: str,
|
||||
suggested_precision: int,
|
||||
) -> None:
|
||||
"""Test default unit precision."""
|
||||
entry = entity_registry.async_get_or_create("sensor", "test", "very_unique")
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity0 = MockSensor(
|
||||
name="Test",
|
||||
native_value="123",
|
||||
native_unit_of_measurement=native_unit,
|
||||
device_class=device_class,
|
||||
unique_id="very_unique",
|
||||
)
|
||||
setup_test_component_platform(hass, sensor.DOMAIN, [entity0])
|
||||
|
||||
assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entry = entity_registry.async_get(entity0.entity_id)
|
||||
assert entry.options["sensor"]["suggested_display_precision"] == suggested_precision
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -1756,39 +1917,6 @@ async def test_suggested_precision_option_update(
|
||||
}
|
||||
|
||||
|
||||
async def test_suggested_precision_option_removal(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> None:
|
||||
"""Test suggested precision stored in the registry is removed."""
|
||||
# Pre-register entities
|
||||
entry = entity_registry.async_get_or_create("sensor", "test", "very_unique")
|
||||
entity_registry.async_update_entity_options(
|
||||
entry.entity_id,
|
||||
"sensor",
|
||||
{
|
||||
"suggested_display_precision": 1,
|
||||
},
|
||||
)
|
||||
|
||||
entity0 = MockSensor(
|
||||
name="Test",
|
||||
device_class=SensorDeviceClass.DURATION,
|
||||
native_unit_of_measurement=UnitOfTime.HOURS,
|
||||
native_value="1.5",
|
||||
suggested_display_precision=None,
|
||||
unique_id="very_unique",
|
||||
)
|
||||
setup_test_component_platform(hass, sensor.DOMAIN, [entity0])
|
||||
|
||||
assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Assert the suggested precision is no longer stored in the registry
|
||||
entry = entity_registry.async_get(entity0.entity_id)
|
||||
assert entry.options.get("sensor", {}).get("suggested_display_precision") is None
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
(
|
||||
"unit_system",
|
||||
@@ -1805,7 +1933,7 @@ async def test_suggested_precision_option_removal(
|
||||
UnitOfLength.KILOMETERS,
|
||||
UnitOfLength.MILES,
|
||||
1000,
|
||||
621.0,
|
||||
621.3711,
|
||||
SensorDeviceClass.DISTANCE,
|
||||
),
|
||||
(
|
||||
@@ -2346,10 +2474,10 @@ async def test_numeric_state_expected_helper(
|
||||
UnitOfLength.METERS,
|
||||
UnitOfLength.YARDS,
|
||||
1000,
|
||||
"621",
|
||||
"1000",
|
||||
"1000000",
|
||||
"1093613",
|
||||
pytest.approx(621.3711),
|
||||
1000,
|
||||
1000000,
|
||||
pytest.approx(1093613),
|
||||
SensorDeviceClass.DISTANCE,
|
||||
),
|
||||
],
|
||||
@@ -2439,40 +2567,40 @@ async def test_unit_conversion_update(
|
||||
|
||||
# Registered entity -> Follow automatic unit conversion
|
||||
state = hass.states.get(entity0.entity_id)
|
||||
assert state.state == automatic_state_1
|
||||
assert float(state.state) == automatic_state_1
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == automatic_unit_1
|
||||
# Assert the automatic unit conversion is stored in the registry
|
||||
entry = entity_registry.async_get(entity0.entity_id)
|
||||
assert entry.options == {
|
||||
"sensor.private": {"suggested_unit_of_measurement": automatic_unit_1}
|
||||
assert entry.options["sensor.private"] == {
|
||||
"suggested_unit_of_measurement": automatic_unit_1
|
||||
}
|
||||
|
||||
state = hass.states.get(entity1.entity_id)
|
||||
assert state.state == automatic_state_1
|
||||
assert float(state.state) == automatic_state_1
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == automatic_unit_1
|
||||
# Assert the automatic unit conversion is stored in the registry
|
||||
entry = entity_registry.async_get(entity1.entity_id)
|
||||
assert entry.options == {
|
||||
"sensor.private": {"suggested_unit_of_measurement": automatic_unit_1}
|
||||
assert entry.options["sensor.private"] == {
|
||||
"suggested_unit_of_measurement": automatic_unit_1
|
||||
}
|
||||
|
||||
# Registered entity with suggested unit
|
||||
state = hass.states.get(entity2.entity_id)
|
||||
assert state.state == suggested_state
|
||||
assert float(state.state) == suggested_state
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == suggested_unit
|
||||
# Assert the suggested unit is stored in the registry
|
||||
entry = entity_registry.async_get(entity2.entity_id)
|
||||
assert entry.options == {
|
||||
"sensor.private": {"suggested_unit_of_measurement": suggested_unit}
|
||||
assert entry.options["sensor.private"] == {
|
||||
"suggested_unit_of_measurement": suggested_unit
|
||||
}
|
||||
|
||||
state = hass.states.get(entity3.entity_id)
|
||||
assert state.state == suggested_state
|
||||
assert float(state.state) == suggested_state
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == suggested_unit
|
||||
# Assert the suggested unit is stored in the registry
|
||||
entry = entity_registry.async_get(entity3.entity_id)
|
||||
assert entry.options == {
|
||||
"sensor.private": {"suggested_unit_of_measurement": suggested_unit}
|
||||
assert entry.options["sensor.private"] == {
|
||||
"suggested_unit_of_measurement": suggested_unit
|
||||
}
|
||||
|
||||
# Set a custom unit, this should have priority over the automatic unit conversion
|
||||
@@ -2482,7 +2610,7 @@ async def test_unit_conversion_update(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity0.entity_id)
|
||||
assert state.state == custom_state
|
||||
assert float(state.state) == custom_state
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == custom_unit
|
||||
|
||||
entity_registry.async_update_entity_options(
|
||||
@@ -2491,7 +2619,7 @@ async def test_unit_conversion_update(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity2.entity_id)
|
||||
assert state.state == custom_state
|
||||
assert float(state.state) == custom_state
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == custom_unit
|
||||
|
||||
# Change unit system, states and units should be unchanged
|
||||
@@ -2499,19 +2627,19 @@ async def test_unit_conversion_update(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity0.entity_id)
|
||||
assert state.state == custom_state
|
||||
assert float(state.state) == custom_state
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == custom_unit
|
||||
|
||||
state = hass.states.get(entity1.entity_id)
|
||||
assert state.state == automatic_state_1
|
||||
assert float(state.state) == automatic_state_1
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == automatic_unit_1
|
||||
|
||||
state = hass.states.get(entity2.entity_id)
|
||||
assert state.state == custom_state
|
||||
assert float(state.state) == custom_state
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == custom_unit
|
||||
|
||||
state = hass.states.get(entity3.entity_id)
|
||||
assert state.state == suggested_state
|
||||
assert float(state.state) == suggested_state
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == suggested_unit
|
||||
|
||||
# Update suggested unit
|
||||
@@ -2522,39 +2650,37 @@ async def test_unit_conversion_update(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity0.entity_id)
|
||||
assert state.state == custom_state
|
||||
assert float(state.state) == custom_state
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == custom_unit
|
||||
|
||||
state = hass.states.get(entity1.entity_id)
|
||||
assert state.state == automatic_state_2
|
||||
assert float(state.state) == automatic_state_2
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == automatic_unit_2
|
||||
|
||||
state = hass.states.get(entity2.entity_id)
|
||||
assert state.state == custom_state
|
||||
assert float(state.state) == custom_state
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == custom_unit
|
||||
|
||||
state = hass.states.get(entity3.entity_id)
|
||||
assert state.state == suggested_state
|
||||
assert float(state.state) == suggested_state
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == suggested_unit
|
||||
|
||||
# Entity 4 still has a pending request to refresh entity options
|
||||
entry = entity_registry.async_get(entity4_entity_id)
|
||||
assert entry.options == {
|
||||
"sensor.private": {
|
||||
"refresh_initial_entity_options": True,
|
||||
"suggested_unit_of_measurement": automatic_unit_1,
|
||||
}
|
||||
assert entry.options["sensor.private"] == {
|
||||
"refresh_initial_entity_options": True,
|
||||
"suggested_unit_of_measurement": automatic_unit_1,
|
||||
}
|
||||
|
||||
# Add entity 4, the pending request to refresh entity options should be handled
|
||||
await entity_platform.async_add_entities((entity4,))
|
||||
|
||||
state = hass.states.get(entity4_entity_id)
|
||||
assert state.state == automatic_state_2
|
||||
assert float(state.state) == automatic_state_2
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == automatic_unit_2
|
||||
|
||||
entry = entity_registry.async_get(entity4_entity_id)
|
||||
assert entry.options == {}
|
||||
assert "sensor.private" not in entry.options
|
||||
|
||||
|
||||
class MockFlow(ConfigFlow):
|
||||
@@ -2763,7 +2889,7 @@ async def test_suggested_unit_guard_invalid_unit(
|
||||
UnitOfTemperature.CELSIUS,
|
||||
10,
|
||||
UnitOfTemperature.KELVIN,
|
||||
283,
|
||||
283.15,
|
||||
),
|
||||
(
|
||||
SensorDeviceClass.DATA_RATE,
|
||||
@@ -2809,8 +2935,8 @@ async def test_suggested_unit_guard_valid_unit(
|
||||
# Assert the suggested unit of measurement is stored in the registry
|
||||
entry = entity_registry.async_get(entity.entity_id)
|
||||
assert entry.unit_of_measurement == suggested_unit
|
||||
assert entry.options == {
|
||||
"sensor.private": {"suggested_unit_of_measurement": suggested_unit},
|
||||
assert entry.options["sensor.private"] == {
|
||||
"suggested_unit_of_measurement": suggested_unit
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user