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:
J. Nick Koston 2020-06-21 12:50:58 -05:00 committed by GitHub
parent 29f128eaad
commit 59e43ab6e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 275 additions and 108 deletions

View File

@ -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]

View File

@ -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)

View File

@ -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,
)
)

View File

@ -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,
)
)

View File

@ -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,
)
)

View File

@ -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,
)
)

View File

@ -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,
)
)