Skip to content

Commit

Permalink
Add observed entities to bayesian sensor (#27721)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
paolog89 committed Feb 25, 2020
1 parent 5776b9f commit 0e6a48c
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 0 deletions.
18 changes: 18 additions & 0 deletions homeassistant/components/bayesian/binary_sensor.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Use Bayesian Inference to trigger a binary sensor."""
from collections import OrderedDict
from itertools import chain

import voluptuous as vol

Expand All @@ -21,6 +22,7 @@
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"

Expand Down Expand Up @@ -126,6 +128,15 @@ def __init__(self, name, prior, observations, probability_threshold, device_clas
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:
Expand Down Expand Up @@ -251,6 +262,13 @@ def device_state_attributes(self):
"""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,
}
Expand Down
51 changes: 51 additions & 0 deletions tests/components/bayesian/test_binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,3 +259,54 @@ def test_probability_updates(self):
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")
)

0 comments on commit 0e6a48c

Please sign in to comment.