1
mirror of https://github.com/home-assistant/core synced 2024-08-15 18:25:44 +02:00

Add repair for missing Bayesian prob_given_false (#79303)

This commit is contained in:
HarvsG 2022-09-29 17:24:06 +00:00 committed by GitHub
parent 114db26fcf
commit f645965172
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 91 additions and 5 deletions

View File

@ -3,6 +3,7 @@ from __future__ import annotations
from collections import OrderedDict
import logging
from typing import Any
import voluptuous as vol
@ -34,7 +35,7 @@ from homeassistant.helpers.template import result_as_boolean
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from . import DOMAIN, PLATFORMS
from .repairs import raise_mirrored_entries
from .repairs import raise_mirrored_entries, raise_no_prob_given_false
ATTR_OBSERVATIONS = "observations"
ATTR_OCCURRED_OBSERVATION_ENTITIES = "occurred_observation_entities"
@ -62,7 +63,7 @@ NUMERIC_STATE_SCHEMA = vol.Schema(
vol.Optional(CONF_ABOVE): vol.Coerce(float),
vol.Optional(CONF_BELOW): vol.Coerce(float),
vol.Required(CONF_P_GIVEN_T): vol.Coerce(float),
vol.Required(CONF_P_GIVEN_F): vol.Coerce(float),
vol.Optional(CONF_P_GIVEN_F): vol.Coerce(float),
},
required=True,
)
@ -73,7 +74,7 @@ STATE_SCHEMA = vol.Schema(
vol.Required(CONF_ENTITY_ID): cv.entity_id,
vol.Required(CONF_TO_STATE): cv.string,
vol.Required(CONF_P_GIVEN_T): vol.Coerce(float),
vol.Required(CONF_P_GIVEN_F): vol.Coerce(float),
vol.Optional(CONF_P_GIVEN_F): vol.Coerce(float),
},
required=True,
)
@ -83,7 +84,7 @@ TEMPLATE_SCHEMA = vol.Schema(
CONF_PLATFORM: CONF_TEMPLATE,
vol.Required(CONF_VALUE_TEMPLATE): cv.template,
vol.Required(CONF_P_GIVEN_T): vol.Coerce(float),
vol.Required(CONF_P_GIVEN_F): vol.Coerce(float),
vol.Optional(CONF_P_GIVEN_F): vol.Coerce(float),
},
required=True,
)
@ -128,6 +129,16 @@ async def async_setup_platform(
probability_threshold = config[CONF_PROBABILITY_THRESHOLD]
device_class = config.get(CONF_DEVICE_CLASS)
# Should deprecate in some future version (2022.10 at time of writing) & make prob_given_false required in schemas.
broken_observations: list[dict[str, Any]] = []
for observation in observations:
if CONF_P_GIVEN_F not in observation:
text: str = f"{name}/{observation.get(CONF_ENTITY_ID,'')}{observation.get(CONF_VALUE_TEMPLATE,'')}"
raise_no_prob_given_false(hass, observation, text)
_LOGGER.error("Missing prob_given_false YAML entry for %s", text)
broken_observations.append(observation)
observations = [x for x in observations if x not in broken_observations]
async_add_entities(
[
BayesianBinarySensor(

View File

@ -31,9 +31,24 @@ def raise_mirrored_entries(hass: HomeAssistant, observations, text: str = "") ->
"mirrored_entry/" + text,
breaks_in_ha_version="2022.10.0",
is_fixable=False,
is_persistent=False,
severity=issue_registry.IssueSeverity.WARNING,
translation_key="manual_migration",
translation_placeholders={"entity": text},
learn_more_url="https://github.com/home-assistant/core/pull/67631",
)
# Should deprecate in some future version (2022.10 at time of writing) & make prob_given_false required in schemas.
def raise_no_prob_given_false(hass: HomeAssistant, observation, text: str) -> None:
"""In previous 2022.9 and earlier, prob_given_false was optional and had a default version."""
issue_registry.async_create_issue(
hass,
DOMAIN,
f"no_prob_given_false/{text}",
breaks_in_ha_version="2022.10.0",
is_fixable=False,
severity=issue_registry.IssueSeverity.ERROR,
translation_key="no_prob_given_false",
translation_placeholders={"entity": text},
learn_more_url="https://github.com/home-assistant/core/pull/67631",
)

View File

@ -0,0 +1,12 @@
{
"issues": {
"manual_migration": {
"description": "The Bayesian integration now also updates the probability if the observed `to_state`, `above`, `below`, or `value_template` evaluates to `False` rather than only `True`. So it is no longer required to have duplicate, complementary entries for each binary state. Please remove the mirrored entry for `{entity}`.",
"title": "Manual YAML fix required for Bayesian"
},
"no_prob_given_false": {
"description": "In the Bayesian integration `prob_given_false` is now a required configuration variable as there was no mathematical rationale for the previous default value. Please add this to your `configuration.yml` for `bayesian/{entity}`. These observations will be ignored until you do.",
"title": "Manual YAML addition required for Bayesian"
}
}
}

View File

@ -3,6 +3,10 @@
"manual_migration": {
"description": "The Bayesian integration now also updates the probability if the observed `to_state`, `above`, `below`, or `value_template` evaluates to `False` rather than only `True`. So it is no longer required to have duplicate, complementary entries for each binary state. Please remove the mirrored entry for `{entity}`.",
"title": "Manual YAML fix required for Bayesian"
},
"no_prob_given_false": {
"description": "In the Bayesian integration `prob_given_false` is now a required configuration variable as there was no mathematical rationale for the previous default value. Please add this to your `configuration.yml` for `bayesian/{entity}`. These observations will be ignored until you do.",
"title": "Manual YAML addition required for Bayesian"
}
}
}

View File

@ -587,6 +587,50 @@ async def test_mirrored_observations(hass):
)
async def test_missing_prob_given_false(hass):
"""Test whether missing prob_given_false are detected and appropriate issues are created."""
config = {
"binary_sensor": {
"platform": "bayesian",
"name": "missingpgf",
"observations": [
{
"platform": "state",
"entity_id": "binary_sensor.test_monitored",
"to_state": "on",
"prob_given_true": 0.8,
},
{
"platform": "template",
"value_template": "{{states('sensor.test_monitored2') == 'off'}}",
"prob_given_true": 0.79,
},
{
"platform": "numeric_state",
"entity_id": "sensor.test_monitored1",
"above": 5,
"prob_given_true": 0.7,
},
],
"prior": 0.1,
}
}
assert len(async_get(hass).issues) == 0
assert await async_setup_component(hass, "binary_sensor", config)
await hass.async_block_till_done()
hass.states.async_set("sensor.test_monitored2", "on")
await hass.async_block_till_done()
assert len(async_get(hass).issues) == 3
assert (
async_get(hass).issues[
("bayesian", "no_prob_given_false/missingpgf/sensor.test_monitored1")
]
is not None
)
async def test_probability_updates(hass):
"""Test probability update function."""
prob_given_true = [0.3, 0.6, 0.8]