Add observed entities to bayesian sensor (#27721)
* Add observed entities to bayesian sensor * Update binary_sensor.py to comply with style guidelines and test_binary_sensor.py to verify the entity_id * Update binary_sensor.py and test_binary_sensor.py to include an additional attribute for observed entities * Use of ATTR_ENTITY_ID and numeric key of observed entity * Update binary_sensor.py * Update test_binary_sensor.py to verify behavior * Update to return a list without duplicates in the state attribute * Update binary_sensor.py: rename of ATTR_ENTITY_ID into ATTR_OBSERVED_ENTITIES * Rename new attribute into ATTR_OCCURRED_OBSERVATION_ENTITIES and fix test
This commit is contained in:
parent
5776b9f17d
commit
0e6a48c688
2 changed files with 69 additions and 0 deletions
|
@ -1,5 +1,6 @@
|
||||||
"""Use Bayesian Inference to trigger a binary sensor."""
|
"""Use Bayesian Inference to trigger a binary sensor."""
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
from itertools import chain
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
|
@ -21,6 +22,7 @@ import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.event import async_track_state_change
|
from homeassistant.helpers.event import async_track_state_change
|
||||||
|
|
||||||
ATTR_OBSERVATIONS = "observations"
|
ATTR_OBSERVATIONS = "observations"
|
||||||
|
ATTR_OCCURRED_OBSERVATION_ENTITIES = "occurred_observation_entities"
|
||||||
ATTR_PROBABILITY = "probability"
|
ATTR_PROBABILITY = "probability"
|
||||||
ATTR_PROBABILITY_THRESHOLD = "probability_threshold"
|
ATTR_PROBABILITY_THRESHOLD = "probability_threshold"
|
||||||
|
|
||||||
|
@ -126,6 +128,15 @@ class BayesianBinarySensor(BinarySensorDevice):
|
||||||
self.probability = prior
|
self.probability = prior
|
||||||
|
|
||||||
self.current_obs = OrderedDict({})
|
self.current_obs = OrderedDict({})
|
||||||
|
self.entity_obs_dict = []
|
||||||
|
|
||||||
|
for obs in self._observations:
|
||||||
|
if "entity_id" in obs:
|
||||||
|
self.entity_obs_dict.append([obs.get("entity_id")])
|
||||||
|
if "value_template" in obs:
|
||||||
|
self.entity_obs_dict.append(
|
||||||
|
list(obs.get(CONF_VALUE_TEMPLATE).extract_entities())
|
||||||
|
)
|
||||||
|
|
||||||
to_observe = set()
|
to_observe = set()
|
||||||
for obs in self._observations:
|
for obs in self._observations:
|
||||||
|
@ -251,6 +262,13 @@ class BayesianBinarySensor(BinarySensorDevice):
|
||||||
"""Return the state attributes of the sensor."""
|
"""Return the state attributes of the sensor."""
|
||||||
return {
|
return {
|
||||||
ATTR_OBSERVATIONS: list(self.current_obs.values()),
|
ATTR_OBSERVATIONS: list(self.current_obs.values()),
|
||||||
|
ATTR_OCCURRED_OBSERVATION_ENTITIES: list(
|
||||||
|
set(
|
||||||
|
chain.from_iterable(
|
||||||
|
self.entity_obs_dict[obs] for obs in self.current_obs.keys()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
ATTR_PROBABILITY: round(self.probability, 2),
|
ATTR_PROBABILITY: round(self.probability, 2),
|
||||||
ATTR_PROBABILITY_THRESHOLD: self._probability_threshold,
|
ATTR_PROBABILITY_THRESHOLD: self._probability_threshold,
|
||||||
}
|
}
|
||||||
|
|
|
@ -259,3 +259,54 @@ class TestBayesianBinarySensor(unittest.TestCase):
|
||||||
prior = bayesian.update_probability(prior, pt, pf)
|
prior = bayesian.update_probability(prior, pt, pf)
|
||||||
|
|
||||||
assert round(abs(0.9130434782608695 - prior), 7) == 0
|
assert round(abs(0.9130434782608695 - prior), 7) == 0
|
||||||
|
|
||||||
|
def test_observed_entities(self):
|
||||||
|
"""Test sensor on observed entities."""
|
||||||
|
config = {
|
||||||
|
"binary_sensor": {
|
||||||
|
"name": "Test_Binary",
|
||||||
|
"platform": "bayesian",
|
||||||
|
"observations": [
|
||||||
|
{
|
||||||
|
"platform": "state",
|
||||||
|
"entity_id": "sensor.test_monitored",
|
||||||
|
"to_state": "off",
|
||||||
|
"prob_given_true": 0.8,
|
||||||
|
"prob_given_false": 0.4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"platform": "template",
|
||||||
|
"value_template": "{{is_state('sensor.test_monitored1','on') and is_state('sensor.test_monitored','off')}}",
|
||||||
|
"prob_given_true": 0.9,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"prior": 0.2,
|
||||||
|
"probability_threshold": 0.32,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert setup_component(self.hass, "binary_sensor", config)
|
||||||
|
|
||||||
|
self.hass.states.set("sensor.test_monitored", "on")
|
||||||
|
self.hass.block_till_done()
|
||||||
|
self.hass.states.set("sensor.test_monitored1", "off")
|
||||||
|
self.hass.block_till_done()
|
||||||
|
|
||||||
|
state = self.hass.states.get("binary_sensor.test_binary")
|
||||||
|
assert [] == state.attributes.get("occurred_observation_entities")
|
||||||
|
|
||||||
|
self.hass.states.set("sensor.test_monitored", "off")
|
||||||
|
self.hass.block_till_done()
|
||||||
|
|
||||||
|
state = self.hass.states.get("binary_sensor.test_binary")
|
||||||
|
assert ["sensor.test_monitored"] == state.attributes.get(
|
||||||
|
"occurred_observation_entities"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.hass.states.set("sensor.test_monitored1", "on")
|
||||||
|
self.hass.block_till_done()
|
||||||
|
|
||||||
|
state = self.hass.states.get("binary_sensor.test_binary")
|
||||||
|
assert ["sensor.test_monitored", "sensor.test_monitored1"] == sorted(
|
||||||
|
state.attributes.get("occurred_observation_entities")
|
||||||
|
)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue