Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add observed entities to bayesian sensor #27721

Merged
merged 9 commits into from
Feb 25, 2020
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
55 changes: 53 additions & 2 deletions tests/components/bayesian/test_binary_sensor.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""The test for the bayesian sensor platform."""
import unittest

from homeassistant.setup import setup_component
from homeassistant.components.bayesian import binary_sensor as bayesian
from homeassistant.setup import setup_component

from tests.common import get_test_home_assistant

Expand Down Expand Up @@ -149,7 +149,7 @@ def test_sensor_state(self):
assert state.state == "off"

def test_threshold(self):
"""Test sensor on probabilty threshold limits."""
"""Test sensor on probability threshold limits."""
config = {
"binary_sensor": {
"name": "Test_Binary",
Expand Down 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")
)