mirror of
https://github.com/home-assistant/core.git
synced 2025-07-13 00:07:10 +00:00
parent
cf681cd921
commit
635d8c01fb
@ -23,6 +23,7 @@ _STATISTIC_MEASURES = [
|
||||
selector.SelectOptionDict(value="median", label="Median"),
|
||||
selector.SelectOptionDict(value="last", label="Most recently updated"),
|
||||
selector.SelectOptionDict(value="range", label="Statistical range"),
|
||||
selector.SelectOptionDict(value="sum", label="Sum"),
|
||||
]
|
||||
|
||||
|
||||
|
@ -48,6 +48,7 @@ ATTR_MEDIAN = "median"
|
||||
ATTR_LAST = "last"
|
||||
ATTR_LAST_ENTITY_ID = "last_entity_id"
|
||||
ATTR_RANGE = "range"
|
||||
ATTR_SUM = "sum"
|
||||
|
||||
ICON = "mdi:calculator"
|
||||
|
||||
@ -58,6 +59,7 @@ SENSOR_TYPES = {
|
||||
ATTR_MEDIAN: "median",
|
||||
ATTR_LAST: "last",
|
||||
ATTR_RANGE: "range",
|
||||
ATTR_SUM: "sum",
|
||||
}
|
||||
SENSOR_TYPE_TO_ATTR = {v: k for k, v in SENSOR_TYPES.items()}
|
||||
|
||||
@ -188,6 +190,18 @@ def calc_range(sensor_values: list[tuple[str, Any]], round_digits: int) -> float
|
||||
return value
|
||||
|
||||
|
||||
def calc_sum(sensor_values: list[tuple[str, Any]], round_digits: int) -> float | None:
|
||||
"""Calculate a sum of values, not honoring unknown states."""
|
||||
result = 0
|
||||
for _, sensor_value in sensor_values:
|
||||
if sensor_value in [STATE_UNKNOWN, STATE_UNAVAILABLE]:
|
||||
return None
|
||||
result += sensor_value
|
||||
|
||||
value: float = round(result, round_digits)
|
||||
return value
|
||||
|
||||
|
||||
class MinMaxSensor(SensorEntity):
|
||||
"""Representation of a min/max sensor."""
|
||||
|
||||
@ -222,6 +236,7 @@ class MinMaxSensor(SensorEntity):
|
||||
self.last: float | None = None
|
||||
self.median: float | None = None
|
||||
self.range: float | None = None
|
||||
self.sum: float | None = None
|
||||
self.min_entity_id: str | None = None
|
||||
self.max_entity_id: str | None = None
|
||||
self.last_entity_id: str | None = None
|
||||
@ -336,3 +351,4 @@ class MinMaxSensor(SensorEntity):
|
||||
self.mean = calc_mean(sensor_values, self._round_digits)
|
||||
self.median = calc_median(sensor_values, self._round_digits)
|
||||
self.range = calc_range(sensor_values, self._round_digits)
|
||||
self.sum = calc_sum(sensor_values, self._round_digits)
|
||||
|
@ -1,10 +1,10 @@
|
||||
{
|
||||
"title": "Min / max / mean / median sensor",
|
||||
"title": "Combine the state of several sensors",
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Add min / max / mean / median sensor",
|
||||
"description": "Create a sensor that calculates a min, max, mean or median value from a list of input sensors.",
|
||||
"title": "Combine the state of several sensors",
|
||||
"description": "Create a sensor that calculates a min, max, mean, median or sum from a list of input sensors.",
|
||||
"data": {
|
||||
"entity_ids": "Input entities",
|
||||
"name": "Name",
|
||||
@ -12,7 +12,7 @@
|
||||
"type": "Statistic characteristic"
|
||||
},
|
||||
"data_description": {
|
||||
"round_digits": "Controls the number of decimal digits in the output when the statistics characteristic is mean or median."
|
||||
"round_digits": "Controls the number of decimal digits in the output when the statistics characteristic is mean, median or sum."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,10 +9,10 @@
|
||||
"type": "Statistic characteristic"
|
||||
},
|
||||
"data_description": {
|
||||
"round_digits": "Controls the number of decimal digits in the output when the statistics characteristic is mean or median."
|
||||
"round_digits": "Controls the number of decimal digits in the output when the statistics characteristic is mean, median or sum."
|
||||
},
|
||||
"description": "Create a sensor that calculates a min, max, mean or median value from a list of input sensors.",
|
||||
"title": "Add min / max / mean / median sensor"
|
||||
"description": "Create a sensor that calculates a min, max, mean, median or sum from a list of input sensors.",
|
||||
"title": "Combine the state of several sensors"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -25,10 +25,10 @@
|
||||
"type": "Statistic characteristic"
|
||||
},
|
||||
"data_description": {
|
||||
"round_digits": "Controls the number of decimal digits in the output when the statistics characteristic is mean or median."
|
||||
"round_digits": "Controls the number of decimal digits in the output when the statistics characteristic is mean, median or sum."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"title": "Min / max / mean / median sensor"
|
||||
"title": "Combine the state of several sensors"
|
||||
}
|
@ -33,6 +33,7 @@ MEAN_4_DIGITS = round(sum(VALUES) / COUNT, 4)
|
||||
MEDIAN = round(statistics.median(VALUES), 2)
|
||||
RANGE_1_DIGIT = round(max(VALUES) - min(VALUES), 1)
|
||||
RANGE_4_DIGITS = round(max(VALUES) - min(VALUES), 4)
|
||||
SUM_VALUE = sum(VALUES)
|
||||
|
||||
|
||||
async def test_default_name_sensor(hass: HomeAssistant) -> None:
|
||||
@ -466,3 +467,60 @@ async def test_sensor_incorrect_state(
|
||||
|
||||
assert state.state == "15.3"
|
||||
assert "Unable to store state. Only numerical states are supported" in caplog.text
|
||||
|
||||
|
||||
async def test_sum_sensor(hass: HomeAssistant) -> None:
|
||||
"""Test the sum sensor."""
|
||||
config = {
|
||||
"sensor": {
|
||||
"platform": "min_max",
|
||||
"name": "test_sum",
|
||||
"type": "sum",
|
||||
"entity_ids": ["sensor.test_1", "sensor.test_2", "sensor.test_3"],
|
||||
"unique_id": "very_unique_id_sum_sensor",
|
||||
}
|
||||
}
|
||||
|
||||
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.test_sum")
|
||||
|
||||
assert str(float(SUM_VALUE)) == state.state
|
||||
assert state.attributes.get(ATTR_STATE_CLASS) == SensorStateClass.MEASUREMENT
|
||||
|
||||
entity_reg = er.async_get(hass)
|
||||
entity = entity_reg.async_get("sensor.test_sum")
|
||||
assert entity.unique_id == "very_unique_id_sum_sensor"
|
||||
|
||||
|
||||
async def test_sum_sensor_no_state(hass: HomeAssistant) -> None:
|
||||
"""Test the sum sensor with no state ."""
|
||||
config = {
|
||||
"sensor": {
|
||||
"platform": "min_max",
|
||||
"name": "test_sum",
|
||||
"type": "sum",
|
||||
"entity_ids": ["sensor.test_1", "sensor.test_2", "sensor.test_3"],
|
||||
"unique_id": "very_unique_id_sum_sensor",
|
||||
}
|
||||
}
|
||||
|
||||
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_ERROR)).items():
|
||||
hass.states.async_set(entity_id, value)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("sensor.test_sum")
|
||||
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
Loading…
x
Reference in New Issue
Block a user