* strict typing * Detail implication * adds newline * don't change indenting * really dont change indenting * Update homeassistant/components/bayesian/binary_sensor.py Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> * typing in async_setup_platform() + remove arg * less ambiguity * mypy thinks Literal[False] otherwise * clearer log * don't use `and` assignments * observations not values * clarify can be None * observation can't be none * assert we have at least one * make it clearer where we're using UUIDs * remove unnecessary bool Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> * Unnecessary None handling Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> * Better type setting Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> * Reccomended changes. * remove if statement not needed * Not strict until _TrackTemplateResultInfo fixed Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>
72 lines
2.2 KiB
Python
72 lines
2.2 KiB
Python
"""Helpers to deal with bayesian observations."""
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
import uuid
|
|
|
|
from homeassistant.const import (
|
|
CONF_ABOVE,
|
|
CONF_BELOW,
|
|
CONF_ENTITY_ID,
|
|
CONF_PLATFORM,
|
|
CONF_VALUE_TEMPLATE,
|
|
)
|
|
from homeassistant.helpers.template import Template
|
|
|
|
from .const import CONF_P_GIVEN_F, CONF_P_GIVEN_T, CONF_TO_STATE
|
|
|
|
|
|
@dataclass
|
|
class Observation:
|
|
"""Representation of a sensor or template observation.
|
|
|
|
Either entity_id or value_template should be non-None.
|
|
"""
|
|
|
|
entity_id: str | None
|
|
platform: str
|
|
prob_given_true: float
|
|
prob_given_false: float
|
|
to_state: str | None
|
|
above: float | None
|
|
below: float | None
|
|
value_template: Template | None
|
|
observed: bool | None = None
|
|
id: uuid.UUID = field(default_factory=uuid.uuid4)
|
|
|
|
def to_dict(self) -> dict[str, str | float | bool | None]:
|
|
"""Represent Class as a Dict for easier serialization."""
|
|
|
|
# Needed because dataclasses asdict() can't serialize Templates and ignores Properties.
|
|
dic = {
|
|
CONF_PLATFORM: self.platform,
|
|
CONF_ENTITY_ID: self.entity_id,
|
|
CONF_VALUE_TEMPLATE: self.template,
|
|
CONF_TO_STATE: self.to_state,
|
|
CONF_ABOVE: self.above,
|
|
CONF_BELOW: self.below,
|
|
CONF_P_GIVEN_T: self.prob_given_true,
|
|
CONF_P_GIVEN_F: self.prob_given_false,
|
|
"observed": self.observed,
|
|
}
|
|
|
|
for key, value in dic.copy().items():
|
|
if value is None:
|
|
del dic[key]
|
|
|
|
return dic
|
|
|
|
def is_mirror(self, other: Observation) -> bool:
|
|
"""Dectects whether given observation is a mirror of this one."""
|
|
return (
|
|
self.platform == other.platform
|
|
and round(self.prob_given_true + other.prob_given_true, 1) == 1
|
|
and round(self.prob_given_false + other.prob_given_false, 1) == 1
|
|
)
|
|
|
|
@property
|
|
def template(self) -> str | None:
|
|
"""Not all observations have templates and we want to get template strings."""
|
|
if self.value_template is not None:
|
|
return self.value_template.template
|
|
return None
|