Reduce overhead to fire events (#95163)
This commit is contained in:
parent
9354df975c
commit
5059cee53f
4 changed files with 81 additions and 68 deletions
|
@ -82,7 +82,7 @@ from .exceptions import (
|
||||||
)
|
)
|
||||||
from .helpers.aiohttp_compat import restore_original_aiohttp_cancel_behavior
|
from .helpers.aiohttp_compat import restore_original_aiohttp_cancel_behavior
|
||||||
from .helpers.json import json_dumps
|
from .helpers.json import json_dumps
|
||||||
from .util import dt as dt_util, location, ulid as ulid_util
|
from .util import dt as dt_util, location
|
||||||
from .util.async_ import (
|
from .util.async_ import (
|
||||||
cancelling,
|
cancelling,
|
||||||
run_callback_threadsafe,
|
run_callback_threadsafe,
|
||||||
|
@ -91,6 +91,7 @@ from .util.async_ import (
|
||||||
from .util.json import JsonObjectType
|
from .util.json import JsonObjectType
|
||||||
from .util.read_only_dict import ReadOnlyDict
|
from .util.read_only_dict import ReadOnlyDict
|
||||||
from .util.timeout import TimeoutManager
|
from .util.timeout import TimeoutManager
|
||||||
|
from .util.ulid import ulid, ulid_at_time
|
||||||
from .util.unit_system import (
|
from .util.unit_system import (
|
||||||
_CONF_UNIT_SYSTEM_IMPERIAL,
|
_CONF_UNIT_SYSTEM_IMPERIAL,
|
||||||
_CONF_UNIT_SYSTEM_US_CUSTOMARY,
|
_CONF_UNIT_SYSTEM_US_CUSTOMARY,
|
||||||
|
@ -874,7 +875,7 @@ class Context:
|
||||||
id: str | None = None, # pylint: disable=redefined-builtin
|
id: str | None = None, # pylint: disable=redefined-builtin
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Init the context."""
|
"""Init the context."""
|
||||||
self.id = id or ulid_util.ulid()
|
self.id = id or ulid()
|
||||||
self.user_id = user_id
|
self.user_id = user_id
|
||||||
self.parent_id = parent_id
|
self.parent_id = parent_id
|
||||||
self.origin_event: Event | None = None
|
self.origin_event: Event | None = None
|
||||||
|
@ -926,10 +927,14 @@ class Event:
|
||||||
self.data = data or {}
|
self.data = data or {}
|
||||||
self.origin = origin
|
self.origin = origin
|
||||||
self.time_fired = time_fired or dt_util.utcnow()
|
self.time_fired = time_fired or dt_util.utcnow()
|
||||||
self.context: Context = context or Context(
|
if not context:
|
||||||
id=ulid_util.ulid_at_time(dt_util.utc_to_timestamp(self.time_fired))
|
context = Context(
|
||||||
)
|
id=ulid_at_time(dt_util.utc_to_timestamp(self.time_fired))
|
||||||
|
)
|
||||||
|
self.context = context
|
||||||
self._as_dict: ReadOnlyDict[str, Any] | None = None
|
self._as_dict: ReadOnlyDict[str, Any] | None = None
|
||||||
|
if not context.origin_event:
|
||||||
|
context.origin_event = self
|
||||||
|
|
||||||
def as_dict(self) -> ReadOnlyDict[str, Any]:
|
def as_dict(self) -> ReadOnlyDict[str, Any]:
|
||||||
"""Create a dict representation of this Event.
|
"""Create a dict representation of this Event.
|
||||||
|
@ -973,6 +978,8 @@ class EventBus:
|
||||||
def __init__(self, hass: HomeAssistant) -> None:
|
def __init__(self, hass: HomeAssistant) -> None:
|
||||||
"""Initialize a new event bus."""
|
"""Initialize a new event bus."""
|
||||||
self._listeners: dict[str, list[_FilterableJob]] = {}
|
self._listeners: dict[str, list[_FilterableJob]] = {}
|
||||||
|
self._match_all_listeners: list[_FilterableJob] = []
|
||||||
|
self._listeners[MATCH_ALL] = self._match_all_listeners
|
||||||
self._hass = hass
|
self._hass = hass
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
|
@ -1019,20 +1026,19 @@ class EventBus:
|
||||||
)
|
)
|
||||||
|
|
||||||
listeners = self._listeners.get(event_type, [])
|
listeners = self._listeners.get(event_type, [])
|
||||||
|
match_all_listeners = self._match_all_listeners
|
||||||
|
|
||||||
# EVENT_HOMEASSISTANT_CLOSE should go only to this listeners
|
if not listeners and not match_all_listeners:
|
||||||
match_all_listeners = self._listeners.get(MATCH_ALL)
|
return
|
||||||
if match_all_listeners is not None and event_type != EVENT_HOMEASSISTANT_CLOSE:
|
|
||||||
|
# EVENT_HOMEASSISTANT_CLOSE should not be sent to MATCH_ALL listeners
|
||||||
|
if event_type != EVENT_HOMEASSISTANT_CLOSE:
|
||||||
listeners = match_all_listeners + listeners
|
listeners = match_all_listeners + listeners
|
||||||
|
|
||||||
event = Event(event_type, event_data, origin, time_fired, context)
|
event = Event(event_type, event_data, origin, time_fired, context)
|
||||||
if not event.context.origin_event:
|
|
||||||
event.context.origin_event = event
|
|
||||||
|
|
||||||
_LOGGER.debug("Bus:Handling %s", event)
|
if _LOGGER.isEnabledFor(logging.DEBUG):
|
||||||
|
_LOGGER.debug("Bus:Handling %s", event)
|
||||||
if not listeners:
|
|
||||||
return
|
|
||||||
|
|
||||||
for job, event_filter, run_immediately in listeners:
|
for job, event_filter, run_immediately in listeners:
|
||||||
if event_filter is not None:
|
if event_filter is not None:
|
||||||
|
@ -1195,7 +1201,7 @@ class EventBus:
|
||||||
self._listeners[event_type].remove(filterable_job)
|
self._listeners[event_type].remove(filterable_job)
|
||||||
|
|
||||||
# delete event_type list if empty
|
# delete event_type list if empty
|
||||||
if not self._listeners[event_type]:
|
if not self._listeners[event_type] and event_type != MATCH_ALL:
|
||||||
self._listeners.pop(event_type)
|
self._listeners.pop(event_type)
|
||||||
except (KeyError, ValueError):
|
except (KeyError, ValueError):
|
||||||
# KeyError is key event_type listener did not exist
|
# KeyError is key event_type listener did not exist
|
||||||
|
@ -1630,7 +1636,7 @@ class StateMachine:
|
||||||
# https://github.com/python/cpython/blob/c90a862cdcf55dc1753c6466e5fa4a467a13ae24/Modules/_datetimemodule.c#L6323
|
# https://github.com/python/cpython/blob/c90a862cdcf55dc1753c6466e5fa4a467a13ae24/Modules/_datetimemodule.c#L6323
|
||||||
timestamp = time.time()
|
timestamp = time.time()
|
||||||
now = dt_util.utc_from_timestamp(timestamp)
|
now = dt_util.utc_from_timestamp(timestamp)
|
||||||
context = Context(id=ulid_util.ulid_at_time(timestamp))
|
context = Context(id=ulid_at_time(timestamp))
|
||||||
else:
|
else:
|
||||||
now = dt_util.utcnow()
|
now = dt_util.utcnow()
|
||||||
|
|
||||||
|
|
|
@ -296,6 +296,7 @@ async def test_service_calls_off_mode(
|
||||||
|
|
||||||
device.set_setpoint_heat.reset_mock()
|
device.set_setpoint_heat.reset_mock()
|
||||||
device.set_setpoint_heat.side_effect = aiosomecomfort.SomeComfortError
|
device.set_setpoint_heat.side_effect = aiosomecomfort.SomeComfortError
|
||||||
|
caplog.clear()
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
CLIMATE_DOMAIN,
|
CLIMATE_DOMAIN,
|
||||||
SERVICE_SET_TEMPERATURE,
|
SERVICE_SET_TEMPERATURE,
|
||||||
|
@ -308,8 +309,9 @@ async def test_service_calls_off_mode(
|
||||||
)
|
)
|
||||||
device.set_setpoint_cool.assert_called_with(95)
|
device.set_setpoint_cool.assert_called_with(95)
|
||||||
device.set_setpoint_heat.assert_called_with(77)
|
device.set_setpoint_heat.assert_called_with(77)
|
||||||
assert "Invalid temperature" in caplog.messages[-1]
|
assert "Invalid temperature" in caplog.text
|
||||||
|
|
||||||
|
caplog.clear()
|
||||||
reset_mock(device)
|
reset_mock(device)
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
CLIMATE_DOMAIN,
|
CLIMATE_DOMAIN,
|
||||||
|
@ -436,6 +438,7 @@ async def test_service_calls_cool_mode(
|
||||||
device.set_setpoint_cool.assert_called_with(95)
|
device.set_setpoint_cool.assert_called_with(95)
|
||||||
device.set_setpoint_heat.assert_called_with(77)
|
device.set_setpoint_heat.assert_called_with(77)
|
||||||
|
|
||||||
|
caplog.clear()
|
||||||
device.set_setpoint_cool.reset_mock()
|
device.set_setpoint_cool.reset_mock()
|
||||||
device.set_setpoint_cool.side_effect = aiosomecomfort.SomeComfortError
|
device.set_setpoint_cool.side_effect = aiosomecomfort.SomeComfortError
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
|
@ -450,7 +453,7 @@ async def test_service_calls_cool_mode(
|
||||||
)
|
)
|
||||||
device.set_setpoint_cool.assert_called_with(95)
|
device.set_setpoint_cool.assert_called_with(95)
|
||||||
device.set_setpoint_heat.assert_called_with(77)
|
device.set_setpoint_heat.assert_called_with(77)
|
||||||
assert "Invalid temperature" in caplog.messages[-1]
|
assert "Invalid temperature" in caplog.text
|
||||||
|
|
||||||
reset_mock(device)
|
reset_mock(device)
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
|
@ -467,6 +470,7 @@ async def test_service_calls_cool_mode(
|
||||||
reset_mock(device)
|
reset_mock(device)
|
||||||
|
|
||||||
device.set_hold_cool.side_effect = aiosomecomfort.SomeComfortError
|
device.set_hold_cool.side_effect = aiosomecomfort.SomeComfortError
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
CLIMATE_DOMAIN,
|
CLIMATE_DOMAIN,
|
||||||
|
@ -478,7 +482,7 @@ async def test_service_calls_cool_mode(
|
||||||
device.set_hold_cool.assert_called_once_with(True, 12)
|
device.set_hold_cool.assert_called_once_with(True, 12)
|
||||||
device.set_hold_heat.assert_not_called()
|
device.set_hold_heat.assert_not_called()
|
||||||
device.set_setpoint_heat.assert_not_called()
|
device.set_setpoint_heat.assert_not_called()
|
||||||
assert "Temperature out of range" in caplog.messages[-1]
|
assert "Temperature out of range" in caplog.text
|
||||||
|
|
||||||
reset_mock(device)
|
reset_mock(device)
|
||||||
|
|
||||||
|
@ -512,6 +516,7 @@ async def test_service_calls_cool_mode(
|
||||||
|
|
||||||
device.raw_ui_data["StatusHeat"] = 2
|
device.raw_ui_data["StatusHeat"] = 2
|
||||||
device.raw_ui_data["StatusCool"] = 2
|
device.raw_ui_data["StatusCool"] = 2
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
CLIMATE_DOMAIN,
|
CLIMATE_DOMAIN,
|
||||||
|
@ -521,7 +526,7 @@ async def test_service_calls_cool_mode(
|
||||||
)
|
)
|
||||||
device.set_hold_cool.assert_called_once_with(True)
|
device.set_hold_cool.assert_called_once_with(True)
|
||||||
device.set_hold_heat.assert_not_called()
|
device.set_hold_heat.assert_not_called()
|
||||||
assert "Couldn't set permanent hold" in caplog.messages[-1]
|
assert "Couldn't set permanent hold" in caplog.text
|
||||||
|
|
||||||
reset_mock(device)
|
reset_mock(device)
|
||||||
|
|
||||||
|
@ -536,6 +541,7 @@ async def test_service_calls_cool_mode(
|
||||||
device.set_hold_cool.assert_called_once_with(False)
|
device.set_hold_cool.assert_called_once_with(False)
|
||||||
|
|
||||||
reset_mock(device)
|
reset_mock(device)
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
device.set_hold_cool.side_effect = aiosomecomfort.SomeComfortError
|
device.set_hold_cool.side_effect = aiosomecomfort.SomeComfortError
|
||||||
|
|
||||||
|
@ -548,7 +554,7 @@ async def test_service_calls_cool_mode(
|
||||||
|
|
||||||
device.set_hold_heat.assert_not_called()
|
device.set_hold_heat.assert_not_called()
|
||||||
device.set_hold_cool.assert_called_once_with(False)
|
device.set_hold_cool.assert_called_once_with(False)
|
||||||
assert "Can not stop hold mode" in caplog.messages[-1]
|
assert "Can not stop hold mode" in caplog.text
|
||||||
|
|
||||||
reset_mock(device)
|
reset_mock(device)
|
||||||
|
|
||||||
|
@ -566,6 +572,8 @@ async def test_service_calls_cool_mode(
|
||||||
device.set_hold_heat.assert_not_called()
|
device.set_hold_heat.assert_not_called()
|
||||||
|
|
||||||
reset_mock(device)
|
reset_mock(device)
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
device.set_hold_cool.side_effect = aiosomecomfort.SomeComfortError
|
device.set_hold_cool.side_effect = aiosomecomfort.SomeComfortError
|
||||||
|
|
||||||
device.raw_ui_data["StatusHeat"] = 2
|
device.raw_ui_data["StatusHeat"] = 2
|
||||||
|
@ -580,9 +588,10 @@ async def test_service_calls_cool_mode(
|
||||||
|
|
||||||
device.set_hold_cool.assert_called_once_with(True)
|
device.set_hold_cool.assert_called_once_with(True)
|
||||||
device.set_hold_heat.assert_not_called()
|
device.set_hold_heat.assert_not_called()
|
||||||
assert "Couldn't set permanent hold" in caplog.messages[-1]
|
assert "Couldn't set permanent hold" in caplog.text
|
||||||
|
|
||||||
reset_mock(device)
|
reset_mock(device)
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
device.raw_ui_data["StatusHeat"] = 2
|
device.raw_ui_data["StatusHeat"] = 2
|
||||||
device.raw_ui_data["StatusCool"] = 2
|
device.raw_ui_data["StatusCool"] = 2
|
||||||
|
@ -597,7 +606,7 @@ async def test_service_calls_cool_mode(
|
||||||
|
|
||||||
device.set_hold_cool.assert_not_called()
|
device.set_hold_cool.assert_not_called()
|
||||||
device.set_hold_heat.assert_not_called()
|
device.set_hold_heat.assert_not_called()
|
||||||
assert "Invalid system mode returned" in caplog.messages[-2]
|
assert "Invalid system mode returned" in caplog.text
|
||||||
|
|
||||||
|
|
||||||
async def test_service_calls_heat_mode(
|
async def test_service_calls_heat_mode(
|
||||||
|
@ -638,8 +647,9 @@ async def test_service_calls_heat_mode(
|
||||||
)
|
)
|
||||||
device.set_hold_heat.assert_called_once_with(datetime.time(2, 30), 59)
|
device.set_hold_heat.assert_called_once_with(datetime.time(2, 30), 59)
|
||||||
device.set_hold_heat.reset_mock()
|
device.set_hold_heat.reset_mock()
|
||||||
assert "Invalid temperature" in caplog.messages[-1]
|
assert "Invalid temperature" in caplog.text
|
||||||
|
|
||||||
|
caplog.clear()
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
CLIMATE_DOMAIN,
|
CLIMATE_DOMAIN,
|
||||||
SERVICE_SET_TEMPERATURE,
|
SERVICE_SET_TEMPERATURE,
|
||||||
|
@ -667,7 +677,7 @@ async def test_service_calls_heat_mode(
|
||||||
)
|
)
|
||||||
device.set_setpoint_cool.assert_called_with(95)
|
device.set_setpoint_cool.assert_called_with(95)
|
||||||
device.set_setpoint_heat.assert_called_with(77)
|
device.set_setpoint_heat.assert_called_with(77)
|
||||||
assert "Invalid temperature" in caplog.messages[-1]
|
assert "Invalid temperature" in caplog.text
|
||||||
|
|
||||||
reset_mock(device)
|
reset_mock(device)
|
||||||
device.raw_ui_data["StatusHeat"] = 2
|
device.raw_ui_data["StatusHeat"] = 2
|
||||||
|
@ -696,6 +706,7 @@ async def test_service_calls_heat_mode(
|
||||||
device.set_setpoint_heat.assert_called_once()
|
device.set_setpoint_heat.assert_called_once()
|
||||||
|
|
||||||
reset_mock(device)
|
reset_mock(device)
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
device.set_hold_heat.side_effect = aiosomecomfort.SomeComfortError
|
device.set_hold_heat.side_effect = aiosomecomfort.SomeComfortError
|
||||||
|
|
||||||
|
@ -710,7 +721,7 @@ async def test_service_calls_heat_mode(
|
||||||
)
|
)
|
||||||
device.set_hold_heat.assert_called_once_with(True)
|
device.set_hold_heat.assert_called_once_with(True)
|
||||||
device.set_hold_cool.assert_not_called()
|
device.set_hold_cool.assert_not_called()
|
||||||
assert "Couldn't set permanent hold" in caplog.messages[-1]
|
assert "Couldn't set permanent hold" in caplog.text
|
||||||
|
|
||||||
reset_mock(device)
|
reset_mock(device)
|
||||||
|
|
||||||
|
@ -726,6 +737,7 @@ async def test_service_calls_heat_mode(
|
||||||
device.set_setpoint_cool.assert_not_called()
|
device.set_setpoint_cool.assert_not_called()
|
||||||
|
|
||||||
reset_mock(device)
|
reset_mock(device)
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
device.set_hold_heat.side_effect = aiosomecomfort.SomeComfortError
|
device.set_hold_heat.side_effect = aiosomecomfort.SomeComfortError
|
||||||
|
|
||||||
|
@ -739,9 +751,10 @@ async def test_service_calls_heat_mode(
|
||||||
device.set_hold_heat.assert_called_once_with(True, 22)
|
device.set_hold_heat.assert_called_once_with(True, 22)
|
||||||
device.set_hold_cool.assert_not_called()
|
device.set_hold_cool.assert_not_called()
|
||||||
device.set_setpoint_cool.assert_not_called()
|
device.set_setpoint_cool.assert_not_called()
|
||||||
assert "Temperature out of range" in caplog.messages[-1]
|
assert "Temperature out of range" in caplog.text
|
||||||
|
|
||||||
reset_mock(device)
|
reset_mock(device)
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
CLIMATE_DOMAIN,
|
CLIMATE_DOMAIN,
|
||||||
|
@ -765,7 +778,7 @@ async def test_service_calls_heat_mode(
|
||||||
)
|
)
|
||||||
|
|
||||||
device.set_hold_heat.assert_called_once_with(False)
|
device.set_hold_heat.assert_called_once_with(False)
|
||||||
assert "Can not stop hold mode" in caplog.messages[-1]
|
assert "Can not stop hold mode" in caplog.text
|
||||||
|
|
||||||
reset_mock(device)
|
reset_mock(device)
|
||||||
device.raw_ui_data["StatusHeat"] = 2
|
device.raw_ui_data["StatusHeat"] = 2
|
||||||
|
@ -844,6 +857,7 @@ async def test_service_calls_auto_mode(
|
||||||
device.set_setpoint_heat.assert_called_once_with(77)
|
device.set_setpoint_heat.assert_called_once_with(77)
|
||||||
|
|
||||||
reset_mock(device)
|
reset_mock(device)
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
device.set_hold_cool.side_effect = aiosomecomfort.SomeComfortError
|
device.set_hold_cool.side_effect = aiosomecomfort.SomeComfortError
|
||||||
device.set_hold_heat.side_effect = aiosomecomfort.SomeComfortError
|
device.set_hold_heat.side_effect = aiosomecomfort.SomeComfortError
|
||||||
|
@ -855,9 +869,10 @@ async def test_service_calls_auto_mode(
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
device.set_setpoint_heat.assert_not_called()
|
device.set_setpoint_heat.assert_not_called()
|
||||||
assert "Invalid temperature" in caplog.messages[-1]
|
assert "Invalid temperature" in caplog.text
|
||||||
|
|
||||||
reset_mock(device)
|
reset_mock(device)
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
device.set_setpoint_heat.side_effect = aiosomecomfort.SomeComfortError
|
device.set_setpoint_heat.side_effect = aiosomecomfort.SomeComfortError
|
||||||
device.set_setpoint_cool.side_effect = aiosomecomfort.SomeComfortError
|
device.set_setpoint_cool.side_effect = aiosomecomfort.SomeComfortError
|
||||||
|
@ -872,9 +887,10 @@ async def test_service_calls_auto_mode(
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
device.set_setpoint_heat.assert_not_called()
|
device.set_setpoint_heat.assert_not_called()
|
||||||
assert "Invalid temperature" in caplog.messages[-1]
|
assert "Invalid temperature" in caplog.text
|
||||||
|
|
||||||
reset_mock(device)
|
reset_mock(device)
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
device.set_hold_heat.side_effect = None
|
device.set_hold_heat.side_effect = None
|
||||||
device.set_hold_cool.side_effect = None
|
device.set_hold_cool.side_effect = None
|
||||||
|
@ -893,6 +909,7 @@ async def test_service_calls_auto_mode(
|
||||||
device.set_hold_heat.assert_called_once_with(True)
|
device.set_hold_heat.assert_called_once_with(True)
|
||||||
|
|
||||||
reset_mock(device)
|
reset_mock(device)
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
device.set_hold_heat.side_effect = aiosomecomfort.SomeComfortError
|
device.set_hold_heat.side_effect = aiosomecomfort.SomeComfortError
|
||||||
device.raw_ui_data["StatusHeat"] = 2
|
device.raw_ui_data["StatusHeat"] = 2
|
||||||
|
@ -906,7 +923,7 @@ async def test_service_calls_auto_mode(
|
||||||
)
|
)
|
||||||
device.set_hold_cool.assert_called_once_with(True)
|
device.set_hold_cool.assert_called_once_with(True)
|
||||||
device.set_hold_heat.assert_called_once_with(True)
|
device.set_hold_heat.assert_called_once_with(True)
|
||||||
assert "Couldn't set permanent hold" in caplog.messages[-1]
|
assert "Couldn't set permanent hold" in caplog.text
|
||||||
|
|
||||||
reset_mock(device)
|
reset_mock(device)
|
||||||
device.set_setpoint_heat.side_effect = None
|
device.set_setpoint_heat.side_effect = None
|
||||||
|
@ -923,6 +940,7 @@ async def test_service_calls_auto_mode(
|
||||||
device.set_hold_heat.assert_called_once_with(True, 22)
|
device.set_hold_heat.assert_called_once_with(True, 22)
|
||||||
|
|
||||||
reset_mock(device)
|
reset_mock(device)
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
CLIMATE_DOMAIN,
|
CLIMATE_DOMAIN,
|
||||||
|
@ -946,9 +964,10 @@ async def test_service_calls_auto_mode(
|
||||||
|
|
||||||
device.set_hold_heat.assert_not_called()
|
device.set_hold_heat.assert_not_called()
|
||||||
device.set_hold_cool.assert_called_once_with(False)
|
device.set_hold_cool.assert_called_once_with(False)
|
||||||
assert "Can not stop hold mode" in caplog.messages[-1]
|
assert "Can not stop hold mode" in caplog.text
|
||||||
|
|
||||||
reset_mock(device)
|
reset_mock(device)
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
device.raw_ui_data["StatusHeat"] = 2
|
device.raw_ui_data["StatusHeat"] = 2
|
||||||
device.raw_ui_data["StatusCool"] = 2
|
device.raw_ui_data["StatusCool"] = 2
|
||||||
|
@ -978,7 +997,7 @@ async def test_service_calls_auto_mode(
|
||||||
|
|
||||||
device.set_hold_cool.assert_called_once_with(True)
|
device.set_hold_cool.assert_called_once_with(True)
|
||||||
device.set_hold_heat.assert_not_called()
|
device.set_hold_heat.assert_not_called()
|
||||||
assert "Couldn't set permanent hold" in caplog.messages[-1]
|
assert "Couldn't set permanent hold" in caplog.text
|
||||||
|
|
||||||
|
|
||||||
async def test_async_update_errors(
|
async def test_async_update_errors(
|
||||||
|
|
|
@ -49,7 +49,7 @@ async def test_setup_no_mqtt(
|
||||||
async def test_setup_with_pub(hass: HomeAssistant, mqtt_mock: MqttMockHAClient) -> None:
|
async def test_setup_with_pub(hass: HomeAssistant, mqtt_mock: MqttMockHAClient) -> None:
|
||||||
"""Test the setup with subscription."""
|
"""Test the setup with subscription."""
|
||||||
# Should start off with no listeners for all events
|
# Should start off with no listeners for all events
|
||||||
assert hass.bus.async_listeners().get("*") is None
|
assert not hass.bus.async_listeners().get("*")
|
||||||
|
|
||||||
assert await add_eventstream(hass, pub_topic="bar")
|
assert await add_eventstream(hass, pub_topic="bar")
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
|
@ -11,7 +11,11 @@ from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
from homeassistant.util import dt as dt_util
|
from homeassistant.util import dt as dt_util
|
||||||
|
|
||||||
from tests.common import assert_setup_component, async_fire_time_changed
|
from tests.common import (
|
||||||
|
assert_setup_component,
|
||||||
|
async_capture_events,
|
||||||
|
async_fire_time_changed,
|
||||||
|
)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -222,9 +226,9 @@ async def test_start_stop(mock_pilight_error, hass: HomeAssistant) -> None:
|
||||||
|
|
||||||
|
|
||||||
@patch("pilight.pilight.Client", PilightDaemonSim)
|
@patch("pilight.pilight.Client", PilightDaemonSim)
|
||||||
@patch("homeassistant.core._LOGGER.debug")
|
async def test_receive_code(hass: HomeAssistant) -> None:
|
||||||
async def test_receive_code(mock_debug, hass: HomeAssistant) -> None:
|
|
||||||
"""Check if code receiving via pilight daemon works."""
|
"""Check if code receiving via pilight daemon works."""
|
||||||
|
events = async_capture_events(hass, pilight.EVENT)
|
||||||
with assert_setup_component(4):
|
with assert_setup_component(4):
|
||||||
assert await async_setup_component(hass, pilight.DOMAIN, {pilight.DOMAIN: {}})
|
assert await async_setup_component(hass, pilight.DOMAIN, {pilight.DOMAIN: {}})
|
||||||
|
|
||||||
|
@ -239,18 +243,13 @@ async def test_receive_code(mock_debug, hass: HomeAssistant) -> None:
|
||||||
},
|
},
|
||||||
**PilightDaemonSim.test_message["message"],
|
**PilightDaemonSim.test_message["message"],
|
||||||
)
|
)
|
||||||
debug_log_call = mock_debug.call_args_list[-1]
|
assert events[0].data == expected_message
|
||||||
|
|
||||||
# Check if all message parts are put on event bus
|
|
||||||
for key, value in expected_message.items():
|
|
||||||
assert str(key) in str(debug_log_call)
|
|
||||||
assert str(value) in str(debug_log_call)
|
|
||||||
|
|
||||||
|
|
||||||
@patch("pilight.pilight.Client", PilightDaemonSim)
|
@patch("pilight.pilight.Client", PilightDaemonSim)
|
||||||
@patch("homeassistant.core._LOGGER.debug")
|
async def test_whitelist_exact_match(hass: HomeAssistant) -> None:
|
||||||
async def test_whitelist_exact_match(mock_debug, hass: HomeAssistant) -> None:
|
|
||||||
"""Check whitelist filter with matched data."""
|
"""Check whitelist filter with matched data."""
|
||||||
|
events = async_capture_events(hass, pilight.EVENT)
|
||||||
with assert_setup_component(4):
|
with assert_setup_component(4):
|
||||||
whitelist = {
|
whitelist = {
|
||||||
"protocol": [PilightDaemonSim.test_message["protocol"]],
|
"protocol": [PilightDaemonSim.test_message["protocol"]],
|
||||||
|
@ -272,18 +271,14 @@ async def test_whitelist_exact_match(mock_debug, hass: HomeAssistant) -> None:
|
||||||
},
|
},
|
||||||
**PilightDaemonSim.test_message["message"],
|
**PilightDaemonSim.test_message["message"],
|
||||||
)
|
)
|
||||||
debug_log_call = mock_debug.call_args_list[-1]
|
|
||||||
|
|
||||||
# Check if all message parts are put on event bus
|
# Check if all message parts are put on event bus
|
||||||
for key, value in expected_message.items():
|
assert events[0].data == expected_message
|
||||||
assert str(key) in str(debug_log_call)
|
|
||||||
assert str(value) in str(debug_log_call)
|
|
||||||
|
|
||||||
|
|
||||||
@patch("pilight.pilight.Client", PilightDaemonSim)
|
@patch("pilight.pilight.Client", PilightDaemonSim)
|
||||||
@patch("homeassistant.core._LOGGER.debug")
|
async def test_whitelist_partial_match(hass: HomeAssistant) -> None:
|
||||||
async def test_whitelist_partial_match(mock_debug, hass: HomeAssistant) -> None:
|
|
||||||
"""Check whitelist filter with partially matched data, should work."""
|
"""Check whitelist filter with partially matched data, should work."""
|
||||||
|
events = async_capture_events(hass, pilight.EVENT)
|
||||||
with assert_setup_component(4):
|
with assert_setup_component(4):
|
||||||
whitelist = {
|
whitelist = {
|
||||||
"protocol": [PilightDaemonSim.test_message["protocol"]],
|
"protocol": [PilightDaemonSim.test_message["protocol"]],
|
||||||
|
@ -303,18 +298,15 @@ async def test_whitelist_partial_match(mock_debug, hass: HomeAssistant) -> None:
|
||||||
},
|
},
|
||||||
**PilightDaemonSim.test_message["message"],
|
**PilightDaemonSim.test_message["message"],
|
||||||
)
|
)
|
||||||
debug_log_call = mock_debug.call_args_list[-1]
|
|
||||||
|
|
||||||
# Check if all message parts are put on event bus
|
# Check if all message parts are put on event bus
|
||||||
for key, value in expected_message.items():
|
assert events[0].data == expected_message
|
||||||
assert str(key) in str(debug_log_call)
|
|
||||||
assert str(value) in str(debug_log_call)
|
|
||||||
|
|
||||||
|
|
||||||
@patch("pilight.pilight.Client", PilightDaemonSim)
|
@patch("pilight.pilight.Client", PilightDaemonSim)
|
||||||
@patch("homeassistant.core._LOGGER.debug")
|
async def test_whitelist_or_match(hass: HomeAssistant) -> None:
|
||||||
async def test_whitelist_or_match(mock_debug, hass: HomeAssistant) -> None:
|
|
||||||
"""Check whitelist filter with several subsection, should work."""
|
"""Check whitelist filter with several subsection, should work."""
|
||||||
|
events = async_capture_events(hass, pilight.EVENT)
|
||||||
|
|
||||||
with assert_setup_component(4):
|
with assert_setup_component(4):
|
||||||
whitelist = {
|
whitelist = {
|
||||||
"protocol": [
|
"protocol": [
|
||||||
|
@ -337,18 +329,15 @@ async def test_whitelist_or_match(mock_debug, hass: HomeAssistant) -> None:
|
||||||
},
|
},
|
||||||
**PilightDaemonSim.test_message["message"],
|
**PilightDaemonSim.test_message["message"],
|
||||||
)
|
)
|
||||||
debug_log_call = mock_debug.call_args_list[-1]
|
|
||||||
|
|
||||||
# Check if all message parts are put on event bus
|
# Check if all message parts are put on event bus
|
||||||
for key, value in expected_message.items():
|
assert events[0].data == expected_message
|
||||||
assert str(key) in str(debug_log_call)
|
|
||||||
assert str(value) in str(debug_log_call)
|
|
||||||
|
|
||||||
|
|
||||||
@patch("pilight.pilight.Client", PilightDaemonSim)
|
@patch("pilight.pilight.Client", PilightDaemonSim)
|
||||||
@patch("homeassistant.core._LOGGER.debug")
|
async def test_whitelist_no_match(hass: HomeAssistant) -> None:
|
||||||
async def test_whitelist_no_match(mock_debug, hass: HomeAssistant) -> None:
|
|
||||||
"""Check whitelist filter with unmatched data, should not work."""
|
"""Check whitelist filter with unmatched data, should not work."""
|
||||||
|
events = async_capture_events(hass, pilight.EVENT)
|
||||||
|
|
||||||
with assert_setup_component(4):
|
with assert_setup_component(4):
|
||||||
whitelist = {
|
whitelist = {
|
||||||
"protocol": ["wrong_protocol"],
|
"protocol": ["wrong_protocol"],
|
||||||
|
@ -360,9 +349,8 @@ async def test_whitelist_no_match(mock_debug, hass: HomeAssistant) -> None:
|
||||||
|
|
||||||
await hass.async_start()
|
await hass.async_start()
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
debug_log_call = mock_debug.call_args_list[-1]
|
|
||||||
|
|
||||||
assert "Event pilight_received" not in debug_log_call
|
assert len(events) == 0
|
||||||
|
|
||||||
|
|
||||||
async def test_call_rate_delay_throttle_enabled(hass: HomeAssistant) -> None:
|
async def test_call_rate_delay_throttle_enabled(hass: HomeAssistant) -> None:
|
||||||
|
|
Loading…
Add table
Reference in a new issue