diff --git a/homeassistant/components/bayesian/binary_sensor.py b/homeassistant/components/bayesian/binary_sensor.py index 1d3720f6723..c2e9e220a20 100644 --- a/homeassistant/components/bayesian/binary_sensor.py +++ b/homeassistant/components/bayesian/binary_sensor.py @@ -1,5 +1,6 @@ """Use Bayesian Inference to trigger a binary sensor.""" from collections import OrderedDict +from itertools import chain import voluptuous as vol @@ -21,6 +22,7 @@ import homeassistant.helpers.config_validation as cv from homeassistant.helpers.event import async_track_state_change ATTR_OBSERVATIONS = "observations" +ATTR_OCCURRED_OBSERVATION_ENTITIES = "occurred_observation_entities" ATTR_PROBABILITY = "probability" ATTR_PROBABILITY_THRESHOLD = "probability_threshold" @@ -126,6 +128,15 @@ class BayesianBinarySensor(BinarySensorDevice): self.probability = prior 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() for obs in self._observations: @@ -251,6 +262,13 @@ class BayesianBinarySensor(BinarySensorDevice): """Return the state attributes of the sensor.""" return { 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_THRESHOLD: self._probability_threshold, } diff --git a/tests/components/bayesian/test_binary_sensor.py b/tests/components/bayesian/test_binary_sensor.py index c8a23517ae1..fb9bc7d5e5c 100644 --- a/tests/components/bayesian/test_binary_sensor.py +++ b/tests/components/bayesian/test_binary_sensor.py @@ -259,3 +259,54 @@ class TestBayesianBinarySensor(unittest.TestCase): prior = bayesian.update_probability(prior, pt, pf) 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") + )