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

Add to issue registry if user has mirrored entries for breaking in #67631 (#79208)

Co-authored-by: Diogo Gomes <diogogomes@gmail.com>
This commit is contained in:
HarvsG 2022-09-29 01:39:15 +00:00 committed by GitHub
parent 3884b4b6bf
commit 768b83139f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 156 additions and 0 deletions

View File

@ -34,6 +34,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
ATTR_OBSERVATIONS = "observations"
ATTR_OCCURRED_OBSERVATION_ENTITIES = "occurred_observation_entities"
@ -245,6 +246,22 @@ class BayesianBinarySensor(BinarySensorEntity):
self.probability = self._calculate_new_probability()
self._attr_is_on = bool(self.probability >= self._probability_threshold)
# detect mirrored entries
for entity, observations in self.observations_by_entity.items():
raise_mirrored_entries(
self.hass, observations, text=f"{self._attr_name}/{entity}"
)
all_template_observations = []
for value in self.observations_by_template.values():
all_template_observations.append(value[0])
if len(all_template_observations) == 2:
raise_mirrored_entries(
self.hass,
all_template_observations,
text=f"{self._attr_name}/{all_template_observations[0]['value_template']}",
)
@callback
def _recalculate_and_write_state(self):
self.probability = self._calculate_new_probability()

View File

@ -0,0 +1,39 @@
"""Helpers for generating repairs."""
from __future__ import annotations
from homeassistant.core import HomeAssistant
from homeassistant.helpers import issue_registry
from . import DOMAIN
def raise_mirrored_entries(hass: HomeAssistant, observations, text: str = "") -> None:
"""If there are mirrored entries, the user is probably using a workaround for a patched bug."""
if len(observations) != 2:
return
true_sums_1: bool = (
round(
observations[0]["prob_given_true"] + observations[1]["prob_given_true"], 1
)
== 1.0
)
false_sums_1: bool = (
round(
observations[0]["prob_given_false"] + observations[1]["prob_given_false"], 1
)
== 1.0
)
same_states: bool = observations[0]["platform"] == observations[1]["platform"]
if true_sums_1 & false_sums_1 & same_states:
issue_registry.async_create_issue(
hass,
DOMAIN,
"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",
)

View File

@ -0,0 +1,8 @@
{
"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"
}
}
}

View File

@ -18,6 +18,7 @@ from homeassistant.const import (
)
from homeassistant.core import Context, callback
from homeassistant.helpers.event import async_track_state_change_event
from homeassistant.helpers.issue_registry import async_get
from homeassistant.setup import async_setup_component
from tests.common import get_fixture_path
@ -184,6 +185,8 @@ async def test_sensor_numeric_state(hass):
assert state.state == "off"
assert len(async_get(hass).issues) == 0
async def test_sensor_state(hass):
"""Test sensor on state platform observations."""
@ -341,6 +344,7 @@ async def test_threshold(hass):
assert round(abs(1.0 - state.attributes.get("probability")), 7) == 0
assert state.state == "on"
assert len(async_get(hass).issues) == 0
async def test_multiple_observations(hass):
@ -495,6 +499,94 @@ async def test_multiple_numeric_observations(hass):
assert state.attributes.get("observations")[1]["platform"] == "numeric_state"
async def test_mirrored_observations(hass):
"""Test whether mirrored entries are detected and appropriate issues are created."""
config = {
"binary_sensor": {
"platform": "bayesian",
"name": "Test_Binary",
"observations": [
{
"platform": "state",
"entity_id": "binary_sensor.test_monitored",
"to_state": "on",
"prob_given_true": 0.8,
"prob_given_false": 0.4,
},
{
"platform": "state",
"entity_id": "binary_sensor.test_monitored",
"to_state": "off",
"prob_given_true": 0.2,
"prob_given_false": 0.59,
},
{
"platform": "numeric_state",
"entity_id": "sensor.test_monitored1",
"above": 5,
"prob_given_true": 0.7,
"prob_given_false": 0.4,
},
{
"platform": "numeric_state",
"entity_id": "sensor.test_monitored1",
"below": 5,
"prob_given_true": 0.3,
"prob_given_false": 0.6,
},
{
"platform": "template",
"value_template": "{{states('sensor.test_monitored2') == 'off'}}",
"prob_given_true": 0.79,
"prob_given_false": 0.4,
},
{
"platform": "template",
"value_template": "{{states('sensor.test_monitored2') == 'on'}}",
"prob_given_true": 0.2,
"prob_given_false": 0.6,
},
{
"platform": "state",
"entity_id": "sensor.colour",
"to_state": "blue",
"prob_given_true": 0.33,
"prob_given_false": 0.8,
},
{
"platform": "state",
"entity_id": "sensor.colour",
"to_state": "green",
"prob_given_true": 0.3,
"prob_given_false": 0.15,
},
{
"platform": "state",
"entity_id": "sensor.colour",
"to_state": "red",
"prob_given_true": 0.4,
"prob_given_false": 0.05,
},
],
"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", "mirrored_entry/Test_Binary/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]