mirror of
https://github.com/home-assistant/core.git
synced 2025-04-25 09:47:52 +00:00
Prefilter more logbook events in sql (#36958)
* Prefilter more logbook events in sql Prefilter sensor events in _keep_event before humanify Cache static attribute lookup Reduces logbook execution time by ~35% * fix mocking in benchmark * Update tests for logbook users
This commit is contained in:
parent
29f128eaad
commit
59e43ab6e4
@ -18,11 +18,13 @@ from homeassistant.components.recorder.util import (
|
||||
session_scope,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_DOMAIN,
|
||||
ATTR_ENTITY_ID,
|
||||
ATTR_FRIENDLY_NAME,
|
||||
ATTR_HIDDEN,
|
||||
ATTR_NAME,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
CONF_EXCLUDE,
|
||||
CONF_INCLUDE,
|
||||
EVENT_HOMEASSISTANT_START,
|
||||
@ -52,6 +54,8 @@ DOMAIN = "logbook"
|
||||
|
||||
GROUP_BY_MINUTES = 15
|
||||
|
||||
EMPTY_JSON_OBJECT = "{}"
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{
|
||||
DOMAIN: vol.Schema(
|
||||
@ -194,7 +198,7 @@ class LogbookView(HomeAssistantView):
|
||||
return await hass.async_add_job(json_events)
|
||||
|
||||
|
||||
def humanify(hass, events, prev_states=None):
|
||||
def humanify(hass, events, entity_attr_cache, prev_states=None):
|
||||
"""Generate a converted list of events into Entry objects.
|
||||
|
||||
Will try to group events if possible:
|
||||
@ -257,24 +261,22 @@ def humanify(hass, events, prev_states=None):
|
||||
prev_states[entity_id] = event.state
|
||||
domain = event.domain
|
||||
|
||||
if domain in CONTINUOUS_DOMAINS:
|
||||
if (
|
||||
domain in CONTINUOUS_DOMAINS
|
||||
and event != last_sensor_event[entity_id]
|
||||
):
|
||||
# Skip all but the last sensor state
|
||||
if event != last_sensor_event[entity_id]:
|
||||
continue
|
||||
continue
|
||||
|
||||
# Don't show continuous sensor value changes in the logbook
|
||||
if _get_attribute(hass, entity_id, event, "unit_of_measurement"):
|
||||
continue
|
||||
|
||||
name = _get_attribute(
|
||||
hass, entity_id, event, ATTR_FRIENDLY_NAME
|
||||
name = entity_attr_cache.get(
|
||||
entity_id, ATTR_FRIENDLY_NAME, event
|
||||
) or split_entity_id(entity_id)[1].replace("_", " ")
|
||||
|
||||
yield {
|
||||
"when": event.time_fired,
|
||||
"name": name,
|
||||
"message": _entry_message_from_event(
|
||||
hass, entity_id, domain, event
|
||||
hass, entity_id, domain, event, entity_attr_cache
|
||||
),
|
||||
"domain": domain,
|
||||
"entity_id": entity_id,
|
||||
@ -375,12 +377,13 @@ def _generate_filter_from_config(config):
|
||||
def _get_events(hass, config, start_day, end_day, entity_id=None):
|
||||
"""Get events for a period of time."""
|
||||
entities_filter = _generate_filter_from_config(config)
|
||||
entity_attr_cache = EntityAttributeCache(hass)
|
||||
|
||||
def yield_events(query):
|
||||
"""Yield Events that are not filtered away."""
|
||||
for row in query.yield_per(1000):
|
||||
event = LazyEventPartialState(row)
|
||||
if _keep_event(hass, event, entities_filter):
|
||||
if _keep_event(hass, event, entities_filter, entity_attr_cache):
|
||||
yield event
|
||||
|
||||
with session_scope(hass=hass) as session:
|
||||
@ -409,6 +412,24 @@ def _get_events(hass, config, start_day, end_day, entity_id=None):
|
||||
.order_by(Events.time_fired)
|
||||
.outerjoin(States, (Events.event_id == States.event_id))
|
||||
.outerjoin(old_state, (States.old_state_id == old_state.state_id))
|
||||
# The below filter, removes state change events that do not have
|
||||
# and old_state, new_state, or the old and
|
||||
# new state are the same for v8 schema or later.
|
||||
#
|
||||
# If the events/states were stored before v8 schema, we relay on the
|
||||
# prev_states dict to remove them.
|
||||
#
|
||||
# When all data is schema v8 or later, the check for EMPTY_JSON_OBJECT
|
||||
# can be removed.
|
||||
.filter(
|
||||
(Events.event_type != EVENT_STATE_CHANGED)
|
||||
| (Events.event_data != EMPTY_JSON_OBJECT)
|
||||
| (
|
||||
(States.state_id.isnot(None))
|
||||
& (old_state.state_id.isnot(None))
|
||||
& (States.state != old_state.state)
|
||||
)
|
||||
)
|
||||
.filter(
|
||||
Events.event_type.in_(ALL_EVENT_TYPES + list(hass.data.get(DOMAIN, {})))
|
||||
)
|
||||
@ -429,18 +450,12 @@ def _get_events(hass, config, start_day, end_day, entity_id=None):
|
||||
| (States.state_id.is_(None))
|
||||
)
|
||||
|
||||
# When all data is schema v8 or later, prev_states can be removed
|
||||
prev_states = {}
|
||||
return list(humanify(hass, yield_events(query), prev_states))
|
||||
return list(humanify(hass, yield_events(query), entity_attr_cache, prev_states))
|
||||
|
||||
|
||||
def _get_attribute(hass, entity_id, event, attribute):
|
||||
current_state = hass.states.get(entity_id)
|
||||
if not current_state:
|
||||
return event.attributes.get(attribute)
|
||||
return current_state.attributes.get(attribute, None)
|
||||
|
||||
|
||||
def _keep_event(hass, event, entities_filter):
|
||||
def _keep_event(hass, event, entities_filter, entity_attr_cache):
|
||||
|
||||
if event.event_type == EVENT_STATE_CHANGED:
|
||||
entity_id = event.entity_id
|
||||
@ -456,6 +471,11 @@ def _keep_event(hass, event, entities_filter):
|
||||
if event.hidden:
|
||||
return False
|
||||
|
||||
if event.domain in CONTINUOUS_DOMAINS and entity_attr_cache.get(
|
||||
entity_id, ATTR_UNIT_OF_MEASUREMENT, event
|
||||
):
|
||||
# Don't show continuous sensor value changes in the logbook
|
||||
return False
|
||||
elif event.event_type == EVENT_LOGBOOK_ENTRY:
|
||||
event_data = event.data
|
||||
domain = event_data.get(ATTR_DOMAIN)
|
||||
@ -478,7 +498,7 @@ def _keep_event(hass, event, entities_filter):
|
||||
return not entity_id or entities_filter(entity_id)
|
||||
|
||||
|
||||
def _entry_message_from_event(hass, entity_id, domain, event):
|
||||
def _entry_message_from_event(hass, entity_id, domain, event, entity_attr_cache):
|
||||
"""Convert a state to a message for the logbook."""
|
||||
# We pass domain in so we don't have to split entity_id again
|
||||
state_state = event.state
|
||||
@ -494,7 +514,7 @@ def _entry_message_from_event(hass, entity_id, domain, event):
|
||||
return "has set"
|
||||
|
||||
if domain == "binary_sensor":
|
||||
device_class = _get_attribute(hass, entity_id, event, "device_class")
|
||||
device_class = entity_attr_cache.get(entity_id, ATTR_DEVICE_CLASS, event)
|
||||
if device_class == "battery":
|
||||
if state_state == STATE_ON:
|
||||
return "is low"
|
||||
@ -600,7 +620,10 @@ class LazyEventPartialState:
|
||||
def attributes(self):
|
||||
"""State attributes."""
|
||||
if not self._attributes:
|
||||
if self._row.attributes is None or self._row.attributes == "{}":
|
||||
if (
|
||||
self._row.attributes is None
|
||||
or self._row.attributes == EMPTY_JSON_OBJECT
|
||||
):
|
||||
self._attributes = {}
|
||||
else:
|
||||
self._attributes = json.loads(self._row.attributes)
|
||||
@ -611,7 +634,7 @@ class LazyEventPartialState:
|
||||
"""Event data."""
|
||||
|
||||
if not self._event_data:
|
||||
if self._row.event_data == "{}":
|
||||
if self._row.event_data == EMPTY_JSON_OBJECT:
|
||||
self._event_data = {}
|
||||
else:
|
||||
self._event_data = json.loads(self._row.event_data)
|
||||
@ -634,9 +657,15 @@ class LazyEventPartialState:
|
||||
@property
|
||||
def has_old_and_new_state(self):
|
||||
"""Check the json data to see if new_state and old_state is present without decoding."""
|
||||
if self._row.event_data == "{}":
|
||||
|
||||
# Delete this check once all states are saved in the v8 schema
|
||||
# format or later (they have the old_state_id column).
|
||||
|
||||
# New events in v8 schema format
|
||||
if self._row.event_data == EMPTY_JSON_OBJECT:
|
||||
return self._row.state_id is not None and self._row.old_state_id is not None
|
||||
|
||||
# Old events not in v8 schema format
|
||||
return (
|
||||
'"old_state": {' in self._row.event_data
|
||||
and '"new_state": {' in self._row.event_data
|
||||
@ -648,3 +677,38 @@ class LazyEventPartialState:
|
||||
if '"hidden":' in self._row.attributes:
|
||||
return self.attributes.get(ATTR_HIDDEN, False)
|
||||
return False
|
||||
|
||||
|
||||
class EntityAttributeCache:
|
||||
"""A cache to lookup static entity_id attribute.
|
||||
|
||||
This class should not be used to lookup attributes
|
||||
that are expected to change state.
|
||||
"""
|
||||
|
||||
def __init__(self, hass):
|
||||
"""Init the cache."""
|
||||
self._hass = hass
|
||||
self._cache = {}
|
||||
|
||||
def get(self, entity_id, attribute, event):
|
||||
"""Lookup an attribute for an entity or get it from the cache."""
|
||||
if entity_id in self._cache:
|
||||
if attribute in self._cache[entity_id]:
|
||||
return self._cache[entity_id][attribute]
|
||||
else:
|
||||
self._cache[entity_id] = {}
|
||||
|
||||
current_state = self._hass.states.get(entity_id)
|
||||
if current_state:
|
||||
# Try the current state as its faster than decoding the
|
||||
# attributes
|
||||
self._cache[entity_id][attribute] = current_state.attributes.get(
|
||||
attribute, None
|
||||
)
|
||||
else:
|
||||
# If the entity has been removed, decode the attributes
|
||||
# instead
|
||||
self._cache[entity_id][attribute] = event.attributes.get(attribute)
|
||||
|
||||
return self._cache[entity_id][attribute]
|
||||
|
@ -1,8 +1,10 @@
|
||||
"""Script to run benchmarks."""
|
||||
import argparse
|
||||
import asyncio
|
||||
import collections
|
||||
from contextlib import suppress
|
||||
from datetime import datetime
|
||||
import json
|
||||
import logging
|
||||
from timeit import default_timer as timer
|
||||
from typing import Callable, Dict, TypeVar
|
||||
@ -10,6 +12,7 @@ from typing import Callable, Dict, TypeVar
|
||||
from homeassistant import core
|
||||
from homeassistant.components.websocket_api.const import JSON_DUMP
|
||||
from homeassistant.const import ATTR_NOW, EVENT_STATE_CHANGED, EVENT_TIME_CHANGED
|
||||
from homeassistant.helpers.json import JSONEncoder
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
# mypy: allow-untyped-calls, allow-untyped-defs, no-check-untyped-defs
|
||||
@ -169,21 +172,22 @@ async def _logbook_filtering(hass, last_changed, last_updated):
|
||||
"last_changed": last_changed,
|
||||
}
|
||||
|
||||
event = core.Event(
|
||||
EVENT_STATE_CHANGED,
|
||||
{"entity_id": entity_id, "old_state": old_state, "new_state": new_state},
|
||||
event = _create_state_changed_event_from_old_new(
|
||||
entity_id, dt_util.utcnow(), old_state, new_state
|
||||
)
|
||||
|
||||
entity_attr_cache = logbook.EntityAttributeCache(hass)
|
||||
|
||||
def yield_events(event):
|
||||
# pylint: disable=protected-access
|
||||
entities_filter = logbook._generate_filter_from_config({})
|
||||
for _ in range(10 ** 5):
|
||||
if logbook._keep_event(hass, event, entities_filter):
|
||||
if logbook._keep_event(hass, event, entities_filter, entity_attr_cache):
|
||||
yield event
|
||||
|
||||
start = timer()
|
||||
|
||||
list(logbook.humanify(hass, yield_events(event)))
|
||||
list(logbook.humanify(hass, yield_events(event), entity_attr_cache))
|
||||
|
||||
return timer() - start
|
||||
|
||||
@ -208,3 +212,48 @@ async def json_serialize_states(hass):
|
||||
start = timer()
|
||||
JSON_DUMP(states)
|
||||
return timer() - start
|
||||
|
||||
|
||||
def _create_state_changed_event_from_old_new(
|
||||
entity_id, event_time_fired, old_state, new_state
|
||||
):
|
||||
"""Create a state changed event from a old and new state."""
|
||||
attributes = {}
|
||||
if new_state is not None:
|
||||
attributes = new_state.get("attributes")
|
||||
attributes_json = json.dumps(attributes, cls=JSONEncoder)
|
||||
if attributes_json == "null":
|
||||
attributes_json = "{}"
|
||||
row = collections.namedtuple(
|
||||
"Row",
|
||||
[
|
||||
"event_type"
|
||||
"event_data"
|
||||
"time_fired"
|
||||
"context_id"
|
||||
"context_user_id"
|
||||
"state"
|
||||
"entity_id"
|
||||
"domain"
|
||||
"attributes"
|
||||
"state_id",
|
||||
"old_state_id",
|
||||
],
|
||||
)
|
||||
|
||||
row.event_type = EVENT_STATE_CHANGED
|
||||
row.event_data = "{}"
|
||||
row.attributes = attributes_json
|
||||
row.time_fired = event_time_fired
|
||||
row.state = new_state and new_state.get("state")
|
||||
row.entity_id = entity_id
|
||||
row.domain = entity_id and core.split_entity_id(entity_id)[0]
|
||||
row.context_id = None
|
||||
row.context_user_id = None
|
||||
row.old_state_id = old_state and 1
|
||||
row.state_id = new_state and 1
|
||||
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from homeassistant.components import logbook
|
||||
|
||||
return logbook.LazyEventPartialState(row)
|
||||
|
@ -10,6 +10,7 @@ async def test_humanify_alexa_event(hass):
|
||||
"""Test humanifying Alexa event."""
|
||||
await async_setup_component(hass, "alexa", {})
|
||||
hass.states.async_set("light.kitchen", "on", {"friendly_name": "Kitchen Light"})
|
||||
entity_attr_cache = logbook.EntityAttributeCache(hass)
|
||||
|
||||
results = list(
|
||||
logbook.humanify(
|
||||
@ -40,6 +41,7 @@ async def test_humanify_alexa_event(hass):
|
||||
},
|
||||
),
|
||||
],
|
||||
entity_attr_cache,
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -1040,6 +1040,7 @@ async def test_extraction_functions(hass):
|
||||
async def test_logbook_humanify_automation_triggered_event(hass):
|
||||
"""Test humanifying Automation Trigger event."""
|
||||
await async_setup_component(hass, automation.DOMAIN, {})
|
||||
entity_attr_cache = logbook.EntityAttributeCache(hass)
|
||||
|
||||
event1, event2 = list(
|
||||
logbook.humanify(
|
||||
@ -1054,6 +1055,7 @@ async def test_logbook_humanify_automation_triggered_event(hass):
|
||||
{ATTR_ENTITY_ID: "automation.bye", ATTR_NAME: "Bye Automation"},
|
||||
),
|
||||
],
|
||||
entity_attr_cache,
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -17,6 +17,7 @@ async def test_humanify_homekit_changed_event(hass, hk_driver):
|
||||
"""Test humanifying HomeKit changed event."""
|
||||
with patch("homeassistant.components.homekit.HomeKit"):
|
||||
assert await async_setup_component(hass, "homekit", {"homekit": {}})
|
||||
entity_attr_cache = logbook.EntityAttributeCache(hass)
|
||||
|
||||
event1, event2 = list(
|
||||
logbook.humanify(
|
||||
@ -40,6 +41,7 @@ async def test_humanify_homekit_changed_event(hass, hk_driver):
|
||||
},
|
||||
),
|
||||
],
|
||||
entity_attr_cache,
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -121,12 +121,15 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA = dt_util.utcnow().replace(minute=2)
|
||||
pointB = pointA.replace(minute=5)
|
||||
pointC = pointA + timedelta(minutes=logbook.GROUP_BY_MINUTES)
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
eventA = self.create_state_changed_event(pointA, entity_id, 10)
|
||||
eventB = self.create_state_changed_event(pointB, entity_id, 20)
|
||||
eventC = self.create_state_changed_event(pointC, entity_id, 30)
|
||||
|
||||
entries = list(logbook.humanify(self.hass, (eventA, eventB, eventC)))
|
||||
entries = list(
|
||||
logbook.humanify(self.hass, (eventA, eventB, eventC), entity_attr_cache)
|
||||
)
|
||||
|
||||
assert len(entries) == 2
|
||||
self.assert_entry(
|
||||
@ -141,12 +144,15 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
"""Test remove continuous sensor events from logbook."""
|
||||
entity_id = "sensor.bla"
|
||||
pointA = dt_util.utcnow()
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
attributes = {"unit_of_measurement": "foo"}
|
||||
eventA = self.create_state_changed_event(pointA, entity_id, 10, attributes)
|
||||
|
||||
entries = list(logbook.humanify(self.hass, (eventA,)))
|
||||
|
||||
assert len(entries) == 0
|
||||
entities_filter = logbook._generate_filter_from_config({})
|
||||
assert (
|
||||
logbook._keep_event(self.hass, eventA, entities_filter, entity_attr_cache)
|
||||
is False
|
||||
)
|
||||
|
||||
def test_exclude_new_entities(self):
|
||||
"""Test if events are excluded on first update."""
|
||||
@ -154,6 +160,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
entity_id2 = "sensor.blu"
|
||||
pointA = dt_util.utcnow()
|
||||
pointB = pointA + timedelta(minutes=logbook.GROUP_BY_MINUTES)
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
state_on = ha.State(
|
||||
entity_id, "on", {"brightness": 200}, pointA, pointA
|
||||
@ -172,9 +179,9 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
eventA,
|
||||
eventB,
|
||||
)
|
||||
if logbook._keep_event(self.hass, e, entities_filter)
|
||||
if logbook._keep_event(self.hass, e, entities_filter, entity_attr_cache)
|
||||
]
|
||||
entries = list(logbook.humanify(self.hass, events))
|
||||
entries = list(logbook.humanify(self.hass, events, entity_attr_cache))
|
||||
|
||||
assert len(entries) == 2
|
||||
self.assert_entry(
|
||||
@ -190,6 +197,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
entity_id2 = "sensor.blu"
|
||||
pointA = dt_util.utcnow()
|
||||
pointB = pointA + timedelta(minutes=logbook.GROUP_BY_MINUTES)
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
state_on = ha.State(
|
||||
entity_id, "on", {"brightness": 200}, pointA, pointA
|
||||
@ -207,9 +215,9 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
eventA,
|
||||
eventB,
|
||||
)
|
||||
if logbook._keep_event(self.hass, e, entities_filter)
|
||||
if logbook._keep_event(self.hass, e, entities_filter, entity_attr_cache)
|
||||
]
|
||||
entries = list(logbook.humanify(self.hass, events))
|
||||
entries = list(logbook.humanify(self.hass, events, entity_attr_cache))
|
||||
|
||||
assert len(entries) == 2
|
||||
self.assert_entry(
|
||||
@ -225,6 +233,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
entity_id2 = "sensor.blu"
|
||||
pointA = dt_util.utcnow()
|
||||
pointB = pointA + timedelta(minutes=logbook.GROUP_BY_MINUTES)
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, entity_id, 10, {ATTR_HIDDEN: "true"}
|
||||
@ -239,9 +248,9 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
eventA,
|
||||
eventB,
|
||||
)
|
||||
if logbook._keep_event(self.hass, e, entities_filter)
|
||||
if logbook._keep_event(self.hass, e, entities_filter, entity_attr_cache)
|
||||
]
|
||||
entries = list(logbook.humanify(self.hass, events))
|
||||
entries = list(logbook.humanify(self.hass, events, entity_attr_cache))
|
||||
|
||||
assert len(entries) == 2
|
||||
self.assert_entry(
|
||||
@ -257,6 +266,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
entity_id2 = "sensor.blu"
|
||||
pointA = dt_util.utcnow()
|
||||
pointB = pointA + timedelta(minutes=logbook.GROUP_BY_MINUTES)
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
eventA = self.create_state_changed_event(pointA, entity_id, 10)
|
||||
eventB = self.create_state_changed_event(pointB, entity_id2, 20)
|
||||
@ -277,9 +287,9 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
eventA,
|
||||
eventB,
|
||||
)
|
||||
if logbook._keep_event(self.hass, e, entities_filter)
|
||||
if logbook._keep_event(self.hass, e, entities_filter, entity_attr_cache)
|
||||
]
|
||||
entries = list(logbook.humanify(self.hass, events))
|
||||
entries = list(logbook.humanify(self.hass, events, entity_attr_cache))
|
||||
|
||||
assert len(entries) == 2
|
||||
self.assert_entry(
|
||||
@ -295,6 +305,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
entity_id2 = "sensor.blu"
|
||||
pointA = dt_util.utcnow()
|
||||
pointB = pointA + timedelta(minutes=logbook.GROUP_BY_MINUTES)
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
eventA = self.create_state_changed_event(pointA, entity_id, 10)
|
||||
eventB = self.create_state_changed_event(pointB, entity_id2, 20)
|
||||
@ -316,9 +327,9 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
eventA,
|
||||
eventB,
|
||||
)
|
||||
if logbook._keep_event(self.hass, e, entities_filter)
|
||||
if logbook._keep_event(self.hass, e, entities_filter, entity_attr_cache)
|
||||
]
|
||||
entries = list(logbook.humanify(self.hass, events))
|
||||
entries = list(logbook.humanify(self.hass, events, entity_attr_cache))
|
||||
|
||||
assert len(entries) == 2
|
||||
self.assert_entry(
|
||||
@ -334,6 +345,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
entity_id2 = "sensor.blu"
|
||||
pointA = dt_util.utcnow()
|
||||
pointB = pointA + timedelta(minutes=logbook.GROUP_BY_MINUTES)
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
eventA = self.create_state_changed_event(pointA, entity_id, 10)
|
||||
eventB = self.create_state_changed_event(pointB, entity_id2, 20)
|
||||
@ -354,9 +366,9 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
eventA,
|
||||
eventB,
|
||||
)
|
||||
if logbook._keep_event(self.hass, e, entities_filter)
|
||||
if logbook._keep_event(self.hass, e, entities_filter, entity_attr_cache)
|
||||
]
|
||||
entries = list(logbook.humanify(self.hass, events))
|
||||
entries = list(logbook.humanify(self.hass, events, entity_attr_cache))
|
||||
|
||||
assert len(entries) == 2
|
||||
self.assert_entry(
|
||||
@ -373,6 +385,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
entity_id2 = "sensor.blu"
|
||||
pointA = dt_util.utcnow()
|
||||
pointB = pointA + timedelta(minutes=logbook.GROUP_BY_MINUTES)
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
event_alexa = MockLazyEventPartialState(
|
||||
EVENT_ALEXA_SMART_HOME,
|
||||
@ -399,9 +412,9 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
eventA,
|
||||
eventB,
|
||||
)
|
||||
if logbook._keep_event(self.hass, e, entities_filter)
|
||||
if logbook._keep_event(self.hass, e, entities_filter, entity_attr_cache)
|
||||
]
|
||||
entries = list(logbook.humanify(self.hass, events))
|
||||
entries = list(logbook.humanify(self.hass, events, entity_attr_cache))
|
||||
|
||||
assert len(entries) == 3
|
||||
self.assert_entry(
|
||||
@ -419,6 +432,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
entity_id3 = "sensor.bli"
|
||||
pointA = dt_util.utcnow()
|
||||
pointB = pointA + timedelta(minutes=logbook.GROUP_BY_MINUTES)
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
eventA1 = self.create_state_changed_event(pointA, entity_id, 10)
|
||||
eventA2 = self.create_state_changed_event(pointA, entity_id2, 10)
|
||||
@ -452,9 +466,9 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
eventB1,
|
||||
eventB2,
|
||||
)
|
||||
if logbook._keep_event(self.hass, e, entities_filter)
|
||||
if logbook._keep_event(self.hass, e, entities_filter, entity_attr_cache)
|
||||
]
|
||||
entries = list(logbook.humanify(self.hass, events))
|
||||
entries = list(logbook.humanify(self.hass, events, entity_attr_cache))
|
||||
|
||||
assert len(entries) == 5
|
||||
self.assert_entry(
|
||||
@ -478,6 +492,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA = dt_util.utcnow()
|
||||
pointB = pointA + timedelta(minutes=1)
|
||||
pointC = pointB + timedelta(minutes=1)
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
state_off = ha.State("light.kitchen", "off", {}, pointA, pointA).as_dict()
|
||||
state_100 = ha.State(
|
||||
@ -498,9 +513,9 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
events = [
|
||||
e
|
||||
for e in (eventA, eventB)
|
||||
if logbook._keep_event(self.hass, e, entities_filter)
|
||||
if logbook._keep_event(self.hass, e, entities_filter, entity_attr_cache)
|
||||
]
|
||||
entries = list(logbook.humanify(self.hass, events))
|
||||
entries = list(logbook.humanify(self.hass, events, entity_attr_cache))
|
||||
|
||||
assert len(entries) == 1
|
||||
self.assert_entry(
|
||||
@ -512,6 +527,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
|
||||
Events that are occurring in the same minute.
|
||||
"""
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
entries = list(
|
||||
logbook.humanify(
|
||||
self.hass,
|
||||
@ -519,7 +535,8 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
MockLazyEventPartialState(EVENT_HOMEASSISTANT_STOP),
|
||||
MockLazyEventPartialState(EVENT_HOMEASSISTANT_START),
|
||||
),
|
||||
)
|
||||
entity_attr_cache,
|
||||
),
|
||||
)
|
||||
|
||||
assert len(entries) == 1
|
||||
@ -531,6 +548,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
"""Test if HA start is not filtered or converted into a restart."""
|
||||
entity_id = "switch.bla"
|
||||
pointA = dt_util.utcnow()
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
entries = list(
|
||||
logbook.humanify(
|
||||
@ -539,6 +557,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
MockLazyEventPartialState(EVENT_HOMEASSISTANT_START),
|
||||
self.create_state_changed_event(pointA, entity_id, 10),
|
||||
),
|
||||
entity_attr_cache,
|
||||
)
|
||||
)
|
||||
|
||||
@ -556,76 +575,79 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
Especially test if the special handling for turn on/off events is done.
|
||||
"""
|
||||
pointA = dt_util.utcnow()
|
||||
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
# message for a device state change
|
||||
eventA = self.create_state_changed_event(pointA, "switch.bla", 10)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "changed to 10"
|
||||
|
||||
# message for a switch turned on
|
||||
eventA = self.create_state_changed_event(pointA, "switch.bla", STATE_ON)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "turned on"
|
||||
|
||||
# message for a switch turned off
|
||||
eventA = self.create_state_changed_event(pointA, "switch.bla", STATE_OFF)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "turned off"
|
||||
|
||||
def test_entry_message_from_event_device_tracker(self):
|
||||
"""Test if logbook message is correctly created for device tracker."""
|
||||
pointA = dt_util.utcnow()
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a device tracker "not home" state
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, "device_tracker.john", STATE_NOT_HOME
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "is away"
|
||||
|
||||
# message for a device tracker "home" state
|
||||
eventA = self.create_state_changed_event(pointA, "device_tracker.john", "work")
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "is at work"
|
||||
|
||||
def test_entry_message_from_event_person(self):
|
||||
"""Test if logbook message is correctly created for a person."""
|
||||
pointA = dt_util.utcnow()
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a device tracker "not home" state
|
||||
eventA = self.create_state_changed_event(pointA, "person.john", STATE_NOT_HOME)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "is away"
|
||||
|
||||
# message for a device tracker "home" state
|
||||
eventA = self.create_state_changed_event(pointA, "person.john", "work")
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "is at work"
|
||||
|
||||
def test_entry_message_from_event_sun(self):
|
||||
"""Test if logbook message is correctly created for sun."""
|
||||
pointA = dt_util.utcnow()
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a sun rise
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, "sun.sun", sun.STATE_ABOVE_HORIZON
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "has risen"
|
||||
|
||||
@ -634,7 +656,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA, "sun.sun", sun.STATE_BELOW_HORIZON
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "has set"
|
||||
|
||||
@ -642,13 +664,14 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
"""Test if logbook message is correctly created for a binary_sensor."""
|
||||
pointA = dt_util.utcnow()
|
||||
attributes = {"device_class": "battery"}
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a binary_sensor battery "low" state
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, "binary_sensor.battery", STATE_ON, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "is low"
|
||||
|
||||
@ -657,7 +680,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA, "binary_sensor.battery", STATE_OFF, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "is normal"
|
||||
|
||||
@ -665,13 +688,14 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
"""Test if logbook message is correctly created for a binary_sensor."""
|
||||
pointA = dt_util.utcnow()
|
||||
attributes = {"device_class": "connectivity"}
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a binary_sensor connectivity "connected" state
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, "binary_sensor.connectivity", STATE_ON, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "is connected"
|
||||
|
||||
@ -680,7 +704,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA, "binary_sensor.connectivity", STATE_OFF, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "is disconnected"
|
||||
|
||||
@ -688,13 +712,14 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
"""Test if logbook message is correctly created for a binary_sensor."""
|
||||
pointA = dt_util.utcnow()
|
||||
attributes = {"device_class": "door"}
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a binary_sensor door "open" state
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, "binary_sensor.door", STATE_ON, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "is opened"
|
||||
|
||||
@ -703,7 +728,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA, "binary_sensor.door", STATE_OFF, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "is closed"
|
||||
|
||||
@ -711,13 +736,14 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
"""Test if logbook message is correctly created for a binary_sensor."""
|
||||
pointA = dt_util.utcnow()
|
||||
attributes = {"device_class": "garage_door"}
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a binary_sensor garage_door "open" state
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, "binary_sensor.garage_door", STATE_ON, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "is opened"
|
||||
|
||||
@ -726,7 +752,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA, "binary_sensor.garage_door", STATE_OFF, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "is closed"
|
||||
|
||||
@ -734,13 +760,14 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
"""Test if logbook message is correctly created for a binary_sensor."""
|
||||
pointA = dt_util.utcnow()
|
||||
attributes = {"device_class": "opening"}
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a binary_sensor opening "open" state
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, "binary_sensor.opening", STATE_ON, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "is opened"
|
||||
|
||||
@ -749,7 +776,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA, "binary_sensor.opening", STATE_OFF, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "is closed"
|
||||
|
||||
@ -757,13 +784,14 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
"""Test if logbook message is correctly created for a binary_sensor."""
|
||||
pointA = dt_util.utcnow()
|
||||
attributes = {"device_class": "window"}
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a binary_sensor window "open" state
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, "binary_sensor.window", STATE_ON, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "is opened"
|
||||
|
||||
@ -772,7 +800,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA, "binary_sensor.window", STATE_OFF, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "is closed"
|
||||
|
||||
@ -780,13 +808,14 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
"""Test if logbook message is correctly created for a binary_sensor."""
|
||||
pointA = dt_util.utcnow()
|
||||
attributes = {"device_class": "lock"}
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a binary_sensor lock "unlocked" state
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, "binary_sensor.lock", STATE_ON, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "is unlocked"
|
||||
|
||||
@ -795,7 +824,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA, "binary_sensor.lock", STATE_OFF, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "is locked"
|
||||
|
||||
@ -803,13 +832,14 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
"""Test if logbook message is correctly created for a binary_sensor."""
|
||||
pointA = dt_util.utcnow()
|
||||
attributes = {"device_class": "plug"}
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a binary_sensor plug "unpluged" state
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, "binary_sensor.plug", STATE_ON, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "is plugged in"
|
||||
|
||||
@ -818,7 +848,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA, "binary_sensor.plug", STATE_OFF, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "is unplugged"
|
||||
|
||||
@ -826,13 +856,14 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
"""Test if logbook message is correctly created for a binary_sensor."""
|
||||
pointA = dt_util.utcnow()
|
||||
attributes = {"device_class": "presence"}
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a binary_sensor presence "home" state
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, "binary_sensor.presence", STATE_ON, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "is at home"
|
||||
|
||||
@ -841,7 +872,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA, "binary_sensor.presence", STATE_OFF, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "is away"
|
||||
|
||||
@ -849,13 +880,14 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
"""Test if logbook message is correctly created for a binary_sensor."""
|
||||
pointA = dt_util.utcnow()
|
||||
attributes = {"device_class": "safety"}
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a binary_sensor safety "unsafe" state
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, "binary_sensor.safety", STATE_ON, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "is unsafe"
|
||||
|
||||
@ -864,7 +896,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA, "binary_sensor.safety", STATE_OFF, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "is safe"
|
||||
|
||||
@ -872,13 +904,14 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
"""Test if logbook message is correctly created for a binary_sensor."""
|
||||
pointA = dt_util.utcnow()
|
||||
attributes = {"device_class": "cold"}
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a binary_sensor cold "detected" state
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, "binary_sensor.cold", STATE_ON, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "detected cold"
|
||||
|
||||
@ -887,7 +920,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA, "binary_sensor.cold", STATE_OFF, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "cleared (no cold detected)"
|
||||
|
||||
@ -895,13 +928,14 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
"""Test if logbook message is correctly created for a binary_sensor."""
|
||||
pointA = dt_util.utcnow()
|
||||
attributes = {"device_class": "gas"}
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a binary_sensor gas "detected" state
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, "binary_sensor.gas", STATE_ON, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "detected gas"
|
||||
|
||||
@ -910,7 +944,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA, "binary_sensor.gas", STATE_OFF, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "cleared (no gas detected)"
|
||||
|
||||
@ -918,13 +952,14 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
"""Test if logbook message is correctly created for a binary_sensor."""
|
||||
pointA = dt_util.utcnow()
|
||||
attributes = {"device_class": "heat"}
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a binary_sensor heat "detected" state
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, "binary_sensor.heat", STATE_ON, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "detected heat"
|
||||
|
||||
@ -933,7 +968,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA, "binary_sensor.heat", STATE_OFF, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "cleared (no heat detected)"
|
||||
|
||||
@ -941,13 +976,14 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
"""Test if logbook message is correctly created for a binary_sensor."""
|
||||
pointA = dt_util.utcnow()
|
||||
attributes = {"device_class": "light"}
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a binary_sensor light "detected" state
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, "binary_sensor.light", STATE_ON, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "detected light"
|
||||
|
||||
@ -956,7 +992,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA, "binary_sensor.light", STATE_OFF, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "cleared (no light detected)"
|
||||
|
||||
@ -964,13 +1000,14 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
"""Test if logbook message is correctly created for a binary_sensor."""
|
||||
pointA = dt_util.utcnow()
|
||||
attributes = {"device_class": "moisture"}
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a binary_sensor moisture "detected" state
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, "binary_sensor.moisture", STATE_ON, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "detected moisture"
|
||||
|
||||
@ -979,7 +1016,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA, "binary_sensor.moisture", STATE_OFF, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "cleared (no moisture detected)"
|
||||
|
||||
@ -987,13 +1024,14 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
"""Test if logbook message is correctly created for a binary_sensor."""
|
||||
pointA = dt_util.utcnow()
|
||||
attributes = {"device_class": "motion"}
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a binary_sensor motion "detected" state
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, "binary_sensor.motion", STATE_ON, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "detected motion"
|
||||
|
||||
@ -1002,7 +1040,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA, "binary_sensor.motion", STATE_OFF, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "cleared (no motion detected)"
|
||||
|
||||
@ -1010,13 +1048,14 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
"""Test if logbook message is correctly created for a binary_sensor."""
|
||||
pointA = dt_util.utcnow()
|
||||
attributes = {"device_class": "occupancy"}
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a binary_sensor occupancy "detected" state
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, "binary_sensor.occupancy", STATE_ON, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "detected occupancy"
|
||||
|
||||
@ -1025,7 +1064,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA, "binary_sensor.occupancy", STATE_OFF, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "cleared (no occupancy detected)"
|
||||
|
||||
@ -1033,13 +1072,14 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
"""Test if logbook message is correctly created for a binary_sensor."""
|
||||
pointA = dt_util.utcnow()
|
||||
attributes = {"device_class": "power"}
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a binary_sensor power "detected" state
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, "binary_sensor.power", STATE_ON, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "detected power"
|
||||
|
||||
@ -1048,7 +1088,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA, "binary_sensor.power", STATE_OFF, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "cleared (no power detected)"
|
||||
|
||||
@ -1056,13 +1096,14 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
"""Test if logbook message is correctly created for a binary_sensor."""
|
||||
pointA = dt_util.utcnow()
|
||||
attributes = {"device_class": "problem"}
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a binary_sensor problem "detected" state
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, "binary_sensor.problem", STATE_ON, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "detected problem"
|
||||
|
||||
@ -1071,7 +1112,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA, "binary_sensor.problem", STATE_OFF, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "cleared (no problem detected)"
|
||||
|
||||
@ -1079,13 +1120,14 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
"""Test if logbook message is correctly created for a binary_sensor."""
|
||||
pointA = dt_util.utcnow()
|
||||
attributes = {"device_class": "smoke"}
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a binary_sensor smoke "detected" state
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, "binary_sensor.smoke", STATE_ON, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "detected smoke"
|
||||
|
||||
@ -1094,7 +1136,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA, "binary_sensor.smoke", STATE_OFF, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "cleared (no smoke detected)"
|
||||
|
||||
@ -1102,13 +1144,14 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
"""Test if logbook message is correctly created for a binary_sensor."""
|
||||
pointA = dt_util.utcnow()
|
||||
attributes = {"device_class": "sound"}
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a binary_sensor sound "detected" state
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, "binary_sensor.sound", STATE_ON, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "detected sound"
|
||||
|
||||
@ -1117,7 +1160,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA, "binary_sensor.sound", STATE_OFF, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "cleared (no sound detected)"
|
||||
|
||||
@ -1125,13 +1168,14 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
"""Test if logbook message is correctly created for a binary_sensor."""
|
||||
pointA = dt_util.utcnow()
|
||||
attributes = {"device_class": "vibration"}
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
# message for a binary_sensor vibration "detected" state
|
||||
eventA = self.create_state_changed_event(
|
||||
pointA, "binary_sensor.vibration", STATE_ON, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "detected vibration"
|
||||
|
||||
@ -1140,7 +1184,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
pointA, "binary_sensor.vibration", STATE_OFF, attributes
|
||||
)
|
||||
message = logbook._entry_message_from_event(
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA
|
||||
self.hass, eventA.entity_id, eventA.domain, eventA, entity_attr_cache
|
||||
)
|
||||
assert message == "cleared (no vibration detected)"
|
||||
|
||||
@ -1149,6 +1193,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
name = "Nice name"
|
||||
message = "has a custom entry"
|
||||
entity_id = "sun.sun"
|
||||
entity_attr_cache = logbook.EntityAttributeCache(self.hass)
|
||||
|
||||
entries = list(
|
||||
logbook.humanify(
|
||||
@ -1163,6 +1208,7 @@ class TestComponentLogbook(unittest.TestCase):
|
||||
},
|
||||
),
|
||||
),
|
||||
entity_attr_cache,
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -473,6 +473,7 @@ async def test_config(hass):
|
||||
async def test_logbook_humanify_script_started_event(hass):
|
||||
"""Test humanifying script started event."""
|
||||
await async_setup_component(hass, DOMAIN, {})
|
||||
entity_attr_cache = logbook.EntityAttributeCache(hass)
|
||||
|
||||
event1, event2 = list(
|
||||
logbook.humanify(
|
||||
@ -487,6 +488,7 @@ async def test_logbook_humanify_script_started_event(hass):
|
||||
{ATTR_ENTITY_ID: "script.bye", ATTR_NAME: "Bye Script"},
|
||||
),
|
||||
],
|
||||
entity_attr_cache,
|
||||
)
|
||||
)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user