mirror of
https://github.com/home-assistant/core.git
synced 2025-07-15 17:27:10 +00:00
Have statistics functions return a meaningful, non-none result even if only one value is available (#127305)
* have statistics functions return a meaningful, non-none result even if only one value is available * improved code coverage
This commit is contained in:
parent
487593af38
commit
9ec4881d8d
@ -735,6 +735,8 @@ class StatisticsSensor(SensorEntity):
|
||||
# Statistics for numeric sensor
|
||||
|
||||
def _stat_average_linear(self) -> StateType:
|
||||
if len(self.states) == 1:
|
||||
return self.states[0]
|
||||
if len(self.states) >= 2:
|
||||
area: float = 0
|
||||
for i in range(1, len(self.states)):
|
||||
@ -748,6 +750,8 @@ class StatisticsSensor(SensorEntity):
|
||||
return None
|
||||
|
||||
def _stat_average_step(self) -> StateType:
|
||||
if len(self.states) == 1:
|
||||
return self.states[0]
|
||||
if len(self.states) >= 2:
|
||||
area: float = 0
|
||||
for i in range(1, len(self.states)):
|
||||
@ -803,12 +807,12 @@ class StatisticsSensor(SensorEntity):
|
||||
return None
|
||||
|
||||
def _stat_distance_95_percent_of_values(self) -> StateType:
|
||||
if len(self.states) >= 2:
|
||||
if len(self.states) >= 1:
|
||||
return 2 * 1.96 * cast(float, self._stat_standard_deviation())
|
||||
return None
|
||||
|
||||
def _stat_distance_99_percent_of_values(self) -> StateType:
|
||||
if len(self.states) >= 2:
|
||||
if len(self.states) >= 1:
|
||||
return 2 * 2.58 * cast(float, self._stat_standard_deviation())
|
||||
return None
|
||||
|
||||
@ -835,17 +839,23 @@ class StatisticsSensor(SensorEntity):
|
||||
return None
|
||||
|
||||
def _stat_noisiness(self) -> StateType:
|
||||
if len(self.states) == 1:
|
||||
return 0.0
|
||||
if len(self.states) >= 2:
|
||||
return cast(float, self._stat_sum_differences()) / (len(self.states) - 1)
|
||||
return None
|
||||
|
||||
def _stat_percentile(self) -> StateType:
|
||||
if len(self.states) == 1:
|
||||
return self.states[0]
|
||||
if len(self.states) >= 2:
|
||||
percentiles = statistics.quantiles(self.states, n=100, method="exclusive")
|
||||
return percentiles[self._percentile - 1]
|
||||
return None
|
||||
|
||||
def _stat_standard_deviation(self) -> StateType:
|
||||
if len(self.states) == 1:
|
||||
return 0.0
|
||||
if len(self.states) >= 2:
|
||||
return statistics.stdev(self.states)
|
||||
return None
|
||||
@ -856,6 +866,8 @@ class StatisticsSensor(SensorEntity):
|
||||
return None
|
||||
|
||||
def _stat_sum_differences(self) -> StateType:
|
||||
if len(self.states) == 1:
|
||||
return 0.0
|
||||
if len(self.states) >= 2:
|
||||
return sum(
|
||||
abs(j - i)
|
||||
@ -864,6 +876,8 @@ class StatisticsSensor(SensorEntity):
|
||||
return None
|
||||
|
||||
def _stat_sum_differences_nonnegative(self) -> StateType:
|
||||
if len(self.states) == 1:
|
||||
return 0.0
|
||||
if len(self.states) >= 2:
|
||||
return sum(
|
||||
(j - i if j >= i else j - 0)
|
||||
@ -885,6 +899,8 @@ class StatisticsSensor(SensorEntity):
|
||||
return None
|
||||
|
||||
def _stat_variance(self) -> StateType:
|
||||
if len(self.states) == 1:
|
||||
return 0.0
|
||||
if len(self.states) >= 2:
|
||||
return statistics.variance(self.states)
|
||||
return None
|
||||
@ -892,6 +908,8 @@ class StatisticsSensor(SensorEntity):
|
||||
# Statistics for binary sensor
|
||||
|
||||
def _stat_binary_average_step(self) -> StateType:
|
||||
if len(self.states) == 1:
|
||||
return 100.0 * int(self.states[0] is True)
|
||||
if len(self.states) >= 2:
|
||||
on_seconds: float = 0
|
||||
for i in range(1, len(self.states)):
|
||||
|
@ -1013,7 +1013,7 @@ async def test_state_characteristics(hass: HomeAssistant) -> None:
|
||||
"source_sensor_domain": "sensor",
|
||||
"name": "average_linear",
|
||||
"value_0": STATE_UNKNOWN,
|
||||
"value_1": STATE_UNKNOWN,
|
||||
"value_1": 6.0,
|
||||
"value_9": 10.68,
|
||||
"unit": "°C",
|
||||
},
|
||||
@ -1021,7 +1021,7 @@ async def test_state_characteristics(hass: HomeAssistant) -> None:
|
||||
"source_sensor_domain": "sensor",
|
||||
"name": "average_step",
|
||||
"value_0": STATE_UNKNOWN,
|
||||
"value_1": STATE_UNKNOWN,
|
||||
"value_1": 6.0,
|
||||
"value_9": 11.36,
|
||||
"unit": "°C",
|
||||
},
|
||||
@ -1113,7 +1113,7 @@ async def test_state_characteristics(hass: HomeAssistant) -> None:
|
||||
"source_sensor_domain": "sensor",
|
||||
"name": "distance_95_percent_of_values",
|
||||
"value_0": STATE_UNKNOWN,
|
||||
"value_1": STATE_UNKNOWN,
|
||||
"value_1": 0.0,
|
||||
"value_9": float(round(2 * 1.96 * statistics.stdev(VALUES_NUMERIC), 2)),
|
||||
"unit": "°C",
|
||||
},
|
||||
@ -1121,7 +1121,7 @@ async def test_state_characteristics(hass: HomeAssistant) -> None:
|
||||
"source_sensor_domain": "sensor",
|
||||
"name": "distance_99_percent_of_values",
|
||||
"value_0": STATE_UNKNOWN,
|
||||
"value_1": STATE_UNKNOWN,
|
||||
"value_1": 0.0,
|
||||
"value_9": float(round(2 * 2.58 * statistics.stdev(VALUES_NUMERIC), 2)),
|
||||
"unit": "°C",
|
||||
},
|
||||
@ -1161,7 +1161,7 @@ async def test_state_characteristics(hass: HomeAssistant) -> None:
|
||||
"source_sensor_domain": "sensor",
|
||||
"name": "noisiness",
|
||||
"value_0": STATE_UNKNOWN,
|
||||
"value_1": STATE_UNKNOWN,
|
||||
"value_1": 0.0,
|
||||
"value_9": float(round(sum([3, 4.8, 10.2, 1.2, 5.4, 2.5, 7.3, 8]) / 8, 2)),
|
||||
"unit": "°C",
|
||||
},
|
||||
@ -1169,7 +1169,7 @@ async def test_state_characteristics(hass: HomeAssistant) -> None:
|
||||
"source_sensor_domain": "sensor",
|
||||
"name": "percentile",
|
||||
"value_0": STATE_UNKNOWN,
|
||||
"value_1": STATE_UNKNOWN,
|
||||
"value_1": 6.0,
|
||||
"value_9": 9.2,
|
||||
"unit": "°C",
|
||||
},
|
||||
@ -1177,7 +1177,7 @@ async def test_state_characteristics(hass: HomeAssistant) -> None:
|
||||
"source_sensor_domain": "sensor",
|
||||
"name": "standard_deviation",
|
||||
"value_0": STATE_UNKNOWN,
|
||||
"value_1": STATE_UNKNOWN,
|
||||
"value_1": 0.0,
|
||||
"value_9": float(round(statistics.stdev(VALUES_NUMERIC), 2)),
|
||||
"unit": "°C",
|
||||
},
|
||||
@ -1193,7 +1193,7 @@ async def test_state_characteristics(hass: HomeAssistant) -> None:
|
||||
"source_sensor_domain": "sensor",
|
||||
"name": "sum_differences",
|
||||
"value_0": STATE_UNKNOWN,
|
||||
"value_1": STATE_UNKNOWN,
|
||||
"value_1": 0.0,
|
||||
"value_9": float(
|
||||
sum(
|
||||
[
|
||||
@ -1214,7 +1214,7 @@ async def test_state_characteristics(hass: HomeAssistant) -> None:
|
||||
"source_sensor_domain": "sensor",
|
||||
"name": "sum_differences_nonnegative",
|
||||
"value_0": STATE_UNKNOWN,
|
||||
"value_1": STATE_UNKNOWN,
|
||||
"value_1": 0.0,
|
||||
"value_9": float(
|
||||
sum(
|
||||
[
|
||||
@ -1259,7 +1259,7 @@ async def test_state_characteristics(hass: HomeAssistant) -> None:
|
||||
"source_sensor_domain": "sensor",
|
||||
"name": "variance",
|
||||
"value_0": STATE_UNKNOWN,
|
||||
"value_1": STATE_UNKNOWN,
|
||||
"value_1": 0.0,
|
||||
"value_9": float(round(statistics.variance(VALUES_NUMERIC), 2)),
|
||||
"unit": "°C²",
|
||||
},
|
||||
@ -1267,7 +1267,7 @@ async def test_state_characteristics(hass: HomeAssistant) -> None:
|
||||
"source_sensor_domain": "binary_sensor",
|
||||
"name": "average_step",
|
||||
"value_0": STATE_UNKNOWN,
|
||||
"value_1": STATE_UNKNOWN,
|
||||
"value_1": 100.0,
|
||||
"value_9": 50.0,
|
||||
"unit": "%",
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user