Only set attributes based on the configured type for min_max sensors (#70142)

This commit is contained in:
J. Nick Koston 2022-04-17 19:53:49 -10:00 committed by GitHub
parent b4ef150339
commit 40eb1554d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 36 additions and 63 deletions

View File

@ -31,24 +31,11 @@ ATTR_MIN_VALUE = "min_value"
ATTR_MIN_ENTITY_ID = "min_entity_id" ATTR_MIN_ENTITY_ID = "min_entity_id"
ATTR_MAX_VALUE = "max_value" ATTR_MAX_VALUE = "max_value"
ATTR_MAX_ENTITY_ID = "max_entity_id" ATTR_MAX_ENTITY_ID = "max_entity_id"
ATTR_COUNT_SENSORS = "count_sensors"
ATTR_MEAN = "mean" ATTR_MEAN = "mean"
ATTR_MEDIAN = "median" ATTR_MEDIAN = "median"
ATTR_LAST = "last" ATTR_LAST = "last"
ATTR_LAST_ENTITY_ID = "last_entity_id" ATTR_LAST_ENTITY_ID = "last_entity_id"
ATTR_TO_PROPERTY = [
ATTR_COUNT_SENSORS,
ATTR_MAX_VALUE,
ATTR_MAX_ENTITY_ID,
ATTR_MEAN,
ATTR_MEDIAN,
ATTR_MIN_VALUE,
ATTR_MIN_ENTITY_ID,
ATTR_LAST,
ATTR_LAST_ENTITY_ID,
]
ICON = "mdi:calculator" ICON = "mdi:calculator"
SENSOR_TYPES = { SENSOR_TYPES = {
@ -58,6 +45,7 @@ SENSOR_TYPES = {
ATTR_MEDIAN: "median", ATTR_MEDIAN: "median",
ATTR_LAST: "last", ATTR_LAST: "last",
} }
SENSOR_TYPE_TO_ATTR = {v: k for k, v in SENSOR_TYPES.items()}
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{ {
@ -179,7 +167,8 @@ class MinMaxSensor(SensorEntity):
if name: if name:
self._name = name self._name = name
else: else:
self._name = f"{next(v for k, v in SENSOR_TYPES.items() if self._sensor_type == v)} sensor".capitalize() self._name = f"{sensor_type} sensor".capitalize()
self._sensor_attr = SENSOR_TYPE_TO_ATTR[self._sensor_type]
self._unit_of_measurement = None self._unit_of_measurement = None
self._unit_of_measurement_mismatch = False self._unit_of_measurement_mismatch = False
self.min_value = self.max_value = self.mean = self.last = self.median = None self.min_value = self.max_value = self.mean = self.last = self.median = None
@ -213,9 +202,7 @@ class MinMaxSensor(SensorEntity):
"""Return the state of the sensor.""" """Return the state of the sensor."""
if self._unit_of_measurement_mismatch: if self._unit_of_measurement_mismatch:
return None return None
return getattr( return getattr(self, self._sensor_attr)
self, next(k for k, v in SENSOR_TYPES.items() if self._sensor_type == v)
)
@property @property
def native_unit_of_measurement(self): def native_unit_of_measurement(self):
@ -232,11 +219,13 @@ class MinMaxSensor(SensorEntity):
@property @property
def extra_state_attributes(self): def extra_state_attributes(self):
"""Return the state attributes of the sensor.""" """Return the state attributes of the sensor."""
return { if self._sensor_type == "min":
attr: getattr(self, attr) return {ATTR_MIN_ENTITY_ID: self.min_entity_id}
for attr in ATTR_TO_PROPERTY if self._sensor_type == "max":
if getattr(self, attr) is not None return {ATTR_MAX_ENTITY_ID: self.max_entity_id}
} if self._sensor_type == "last":
return {ATTR_LAST_ENTITY_ID: self.last_entity_id}
return None
@property @property
def icon(self): def icon(self):

View File

@ -132,4 +132,3 @@ async def test_options(hass: HomeAssistant, platform) -> None:
# Check the state of the entity has changed as expected # Check the state of the entity has changed as expected
state = hass.states.get(f"{platform}.my_min_max") state = hass.states.get(f"{platform}.my_min_max")
assert state.state == "21.1" assert state.state == "21.1"
assert state.attributes["count_sensors"] == 3

View File

@ -44,7 +44,6 @@ async def test_setup_and_remove_config_entry(
# Check the platform is setup correctly # Check the platform is setup correctly
state = hass.states.get(min_max_entity_id) state = hass.states.get(min_max_entity_id)
assert state.state == "20.0" assert state.state == "20.0"
assert state.attributes["count_sensors"] == 2
# Remove the config entry # Remove the config entry
assert await hass.config_entries.async_remove(config_entry.entry_id) assert await hass.config_entries.async_remove(config_entry.entry_id)

View File

@ -27,6 +27,31 @@ MEAN_4_DIGITS = round(sum(VALUES) / COUNT, 4)
MEDIAN = round(statistics.median(VALUES), 2) MEDIAN = round(statistics.median(VALUES), 2)
async def test_default_name_sensor(hass):
"""Test the min sensor with a default name."""
config = {
"sensor": {
"platform": "min_max",
"type": "min",
"entity_ids": ["sensor.test_1", "sensor.test_2", "sensor.test_3"],
}
}
assert await async_setup_component(hass, "sensor", config)
await hass.async_block_till_done()
entity_ids = config["sensor"]["entity_ids"]
for entity_id, value in dict(zip(entity_ids, VALUES)).items():
hass.states.async_set(entity_id, value)
await hass.async_block_till_done()
state = hass.states.get("sensor.min_sensor")
assert str(float(MIN_VALUE)) == state.state
assert entity_ids[2] == state.attributes.get("min_entity_id")
async def test_min_sensor(hass): async def test_min_sensor(hass):
"""Test the min sensor.""" """Test the min sensor."""
config = { config = {
@ -51,10 +76,6 @@ async def test_min_sensor(hass):
assert str(float(MIN_VALUE)) == state.state assert str(float(MIN_VALUE)) == state.state
assert entity_ids[2] == state.attributes.get("min_entity_id") assert entity_ids[2] == state.attributes.get("min_entity_id")
assert state.attributes.get("max_value") == MAX_VALUE
assert entity_ids[1] == state.attributes.get("max_entity_id")
assert state.attributes.get("mean") == MEAN
assert state.attributes.get("median") == MEDIAN
async def test_max_sensor(hass): async def test_max_sensor(hass):
@ -80,11 +101,7 @@ async def test_max_sensor(hass):
state = hass.states.get("sensor.test_max") state = hass.states.get("sensor.test_max")
assert str(float(MAX_VALUE)) == state.state assert str(float(MAX_VALUE)) == state.state
assert entity_ids[2] == state.attributes.get("min_entity_id")
assert state.attributes.get("min_value") == MIN_VALUE
assert entity_ids[1] == state.attributes.get("max_entity_id") assert entity_ids[1] == state.attributes.get("max_entity_id")
assert state.attributes.get("mean") == MEAN
assert state.attributes.get("median") == MEDIAN
async def test_mean_sensor(hass): async def test_mean_sensor(hass):
@ -110,11 +127,6 @@ async def test_mean_sensor(hass):
state = hass.states.get("sensor.test_mean") state = hass.states.get("sensor.test_mean")
assert str(float(MEAN)) == state.state assert str(float(MEAN)) == state.state
assert state.attributes.get("min_value") == MIN_VALUE
assert entity_ids[2] == state.attributes.get("min_entity_id")
assert state.attributes.get("max_value") == MAX_VALUE
assert entity_ids[1] == state.attributes.get("max_entity_id")
assert state.attributes.get("median") == MEDIAN
async def test_mean_1_digit_sensor(hass): async def test_mean_1_digit_sensor(hass):
@ -141,11 +153,6 @@ async def test_mean_1_digit_sensor(hass):
state = hass.states.get("sensor.test_mean") state = hass.states.get("sensor.test_mean")
assert str(float(MEAN_1_DIGIT)) == state.state assert str(float(MEAN_1_DIGIT)) == state.state
assert state.attributes.get("min_value") == MIN_VALUE
assert entity_ids[2] == state.attributes.get("min_entity_id")
assert state.attributes.get("max_value") == MAX_VALUE
assert entity_ids[1] == state.attributes.get("max_entity_id")
assert state.attributes.get("median") == MEDIAN
async def test_mean_4_digit_sensor(hass): async def test_mean_4_digit_sensor(hass):
@ -172,11 +179,6 @@ async def test_mean_4_digit_sensor(hass):
state = hass.states.get("sensor.test_mean") state = hass.states.get("sensor.test_mean")
assert str(float(MEAN_4_DIGITS)) == state.state assert str(float(MEAN_4_DIGITS)) == state.state
assert state.attributes.get("min_value") == MIN_VALUE
assert entity_ids[2] == state.attributes.get("min_entity_id")
assert state.attributes.get("max_value") == MAX_VALUE
assert entity_ids[1] == state.attributes.get("max_entity_id")
assert state.attributes.get("median") == MEDIAN
async def test_median_sensor(hass): async def test_median_sensor(hass):
@ -202,11 +204,6 @@ async def test_median_sensor(hass):
state = hass.states.get("sensor.test_median") state = hass.states.get("sensor.test_median")
assert str(float(MEDIAN)) == state.state assert str(float(MEDIAN)) == state.state
assert state.attributes.get("min_value") == MIN_VALUE
assert entity_ids[2] == state.attributes.get("min_entity_id")
assert state.attributes.get("max_value") == MAX_VALUE
assert entity_ids[1] == state.attributes.get("max_entity_id")
assert state.attributes.get("mean") == MEAN
async def test_not_enough_sensor_value(hass): async def test_not_enough_sensor_value(hass):
@ -241,20 +238,14 @@ async def test_not_enough_sensor_value(hass):
state = hass.states.get("sensor.test_max") state = hass.states.get("sensor.test_max")
assert STATE_UNKNOWN != state.state assert STATE_UNKNOWN != state.state
assert entity_ids[1] == state.attributes.get("min_entity_id")
assert VALUES[1] == state.attributes.get("min_value")
assert entity_ids[1] == state.attributes.get("max_entity_id") assert entity_ids[1] == state.attributes.get("max_entity_id")
assert VALUES[1] == state.attributes.get("max_value")
hass.states.async_set(entity_ids[2], STATE_UNKNOWN) hass.states.async_set(entity_ids[2], STATE_UNKNOWN)
await hass.async_block_till_done() await hass.async_block_till_done()
state = hass.states.get("sensor.test_max") state = hass.states.get("sensor.test_max")
assert STATE_UNKNOWN != state.state assert STATE_UNKNOWN != state.state
assert entity_ids[1] == state.attributes.get("min_entity_id")
assert VALUES[1] == state.attributes.get("min_value")
assert entity_ids[1] == state.attributes.get("max_entity_id") assert entity_ids[1] == state.attributes.get("max_entity_id")
assert VALUES[1] == state.attributes.get("max_value")
hass.states.async_set(entity_ids[1], STATE_UNAVAILABLE) hass.states.async_set(entity_ids[1], STATE_UNAVAILABLE)
await hass.async_block_till_done() await hass.async_block_till_done()
@ -337,11 +328,6 @@ async def test_last_sensor(hass):
assert str(float(value)) == state.state assert str(float(value)) == state.state
assert entity_id == state.attributes.get("last_entity_id") assert entity_id == state.attributes.get("last_entity_id")
assert state.attributes.get("min_value") == MIN_VALUE
assert state.attributes.get("max_value") == MAX_VALUE
assert state.attributes.get("mean") == MEAN
assert state.attributes.get("median") == MEDIAN
async def test_reload(hass): async def test_reload(hass):
"""Verify we can reload filter sensors.""" """Verify we can reload filter sensors."""