Use EventType for state changed [h-m] (#97117)

This commit is contained in:
Marc Mueller 2023-07-24 08:01:50 +02:00 committed by GitHub
parent 40382f0caa
commit 5b73bd2f8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 104 additions and 57 deletions

View File

@ -10,7 +10,6 @@ from homeassistant import exceptions
from homeassistant.const import CONF_ATTRIBUTE, CONF_FOR, CONF_PLATFORM, MATCH_ALL from homeassistant.const import CONF_ATTRIBUTE, CONF_FOR, CONF_PLATFORM, MATCH_ALL
from homeassistant.core import ( from homeassistant.core import (
CALLBACK_TYPE, CALLBACK_TYPE,
Event,
HassJob, HassJob,
HomeAssistant, HomeAssistant,
State, State,
@ -22,12 +21,13 @@ from homeassistant.helpers import (
template, template,
) )
from homeassistant.helpers.event import ( from homeassistant.helpers.event import (
EventStateChangedData,
async_track_same_state, async_track_same_state,
async_track_state_change_event, async_track_state_change_event,
process_state_match, process_state_match,
) )
from homeassistant.helpers.trigger import TriggerActionType, TriggerInfo from homeassistant.helpers.trigger import TriggerActionType, TriggerInfo
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType, EventType
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -129,11 +129,11 @@ async def async_attach_trigger(
_variables = trigger_info["variables"] or {} _variables = trigger_info["variables"] or {}
@callback @callback
def state_automation_listener(event: Event): def state_automation_listener(event: EventType[EventStateChangedData]):
"""Listen for state changes and calls action.""" """Listen for state changes and calls action."""
entity: str = event.data["entity_id"] entity = event.data["entity_id"]
from_s: State | None = event.data.get("old_state") from_s = event.data["old_state"]
to_s: State | None = event.data.get("new_state") to_s = event.data["new_state"]
if from_s is None: if from_s is None:
old_value = None old_value = None

View File

@ -12,15 +12,16 @@ from homeassistant.const import (
STATE_UNAVAILABLE, STATE_UNAVAILABLE,
STATE_UNKNOWN, STATE_UNKNOWN,
) )
from homeassistant.core import CALLBACK_TYPE, HassJob, HomeAssistant, callback from homeassistant.core import CALLBACK_TYPE, HassJob, HomeAssistant, State, callback
from homeassistant.helpers import config_validation as cv from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.event import ( from homeassistant.helpers.event import (
EventStateChangedData,
async_track_point_in_time, async_track_point_in_time,
async_track_state_change_event, async_track_state_change_event,
async_track_time_change, async_track_time_change,
) )
from homeassistant.helpers.trigger import TriggerActionType, TriggerInfo from homeassistant.helpers.trigger import TriggerActionType, TriggerInfo
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType, EventType
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
_TIME_TRIGGER_SCHEMA = vol.Any( _TIME_TRIGGER_SCHEMA = vol.Any(
@ -48,7 +49,7 @@ async def async_attach_trigger(
"""Listen for state changes based on configuration.""" """Listen for state changes based on configuration."""
trigger_data = trigger_info["trigger_data"] trigger_data = trigger_info["trigger_data"]
entities: dict[str, CALLBACK_TYPE] = {} entities: dict[str, CALLBACK_TYPE] = {}
removes = [] removes: list[CALLBACK_TYPE] = []
job = HassJob(action, f"time trigger {trigger_info}") job = HassJob(action, f"time trigger {trigger_info}")
@callback @callback
@ -68,12 +69,12 @@ async def async_attach_trigger(
) )
@callback @callback
def update_entity_trigger_event(event): def update_entity_trigger_event(event: EventType[EventStateChangedData]) -> None:
"""update_entity_trigger from the event.""" """update_entity_trigger from the event."""
return update_entity_trigger(event.data["entity_id"], event.data["new_state"]) return update_entity_trigger(event.data["entity_id"], event.data["new_state"])
@callback @callback
def update_entity_trigger(entity_id, new_state=None): def update_entity_trigger(entity_id: str, new_state: State | None = None) -> None:
"""Update the entity trigger for the entity_id.""" """Update the entity trigger for the entity_id."""
# If a listener was already set up for entity, remove it. # If a listener was already set up for entity, remove it.
if remove := entities.pop(entity_id, None): if remove := entities.pop(entity_id, None):
@ -83,6 +84,8 @@ async def async_attach_trigger(
if not new_state: if not new_state:
return return
trigger_dt: datetime | None
# Check state of entity. If valid, set up a listener. # Check state of entity. If valid, set up a listener.
if new_state.domain == "input_datetime": if new_state.domain == "input_datetime":
if has_date := new_state.attributes["has_date"]: if has_date := new_state.attributes["has_date"]:
@ -155,7 +158,7 @@ async def async_attach_trigger(
if remove: if remove:
entities[entity_id] = remove entities[entity_id] = remove
to_track = [] to_track: list[str] = []
for at_time in config[CONF_AT]: for at_time in config[CONF_AT]:
if isinstance(at_time, str): if isinstance(at_time, str):

View File

@ -41,13 +41,16 @@ from homeassistant.const import (
from homeassistant.core import ( from homeassistant.core import (
CALLBACK_TYPE, CALLBACK_TYPE,
Context, Context,
Event,
HomeAssistant, HomeAssistant,
State, State,
callback as ha_callback, callback as ha_callback,
split_entity_id, split_entity_id,
) )
from homeassistant.helpers.event import async_track_state_change_event from homeassistant.helpers.event import (
EventStateChangedData,
async_track_state_change_event,
)
from homeassistant.helpers.typing import EventType
from homeassistant.util.decorator import Registry from homeassistant.util.decorator import Registry
from .const import ( from .const import (
@ -450,9 +453,11 @@ class HomeAccessory(Accessory): # type: ignore[misc]
self.async_update_battery(battery_state, battery_charging_state) self.async_update_battery(battery_state, battery_charging_state)
@ha_callback @ha_callback
def async_update_event_state_callback(self, event: Event) -> None: def async_update_event_state_callback(
self, event: EventType[EventStateChangedData]
) -> None:
"""Handle state change event listener callback.""" """Handle state change event listener callback."""
self.async_update_state_callback(event.data.get("new_state")) self.async_update_state_callback(event.data["new_state"])
@ha_callback @ha_callback
def async_update_state_callback(self, new_state: State | None) -> None: def async_update_state_callback(self, new_state: State | None) -> None:
@ -477,9 +482,11 @@ class HomeAccessory(Accessory): # type: ignore[misc]
self.async_update_state(new_state) self.async_update_state(new_state)
@ha_callback @ha_callback
def async_update_linked_battery_callback(self, event: Event) -> None: def async_update_linked_battery_callback(
self, event: EventType[EventStateChangedData]
) -> None:
"""Handle linked battery sensor state change listener callback.""" """Handle linked battery sensor state change listener callback."""
if (new_state := event.data.get("new_state")) is None: if (new_state := event.data["new_state"]) is None:
return return
if self.linked_battery_charging_sensor: if self.linked_battery_charging_sensor:
battery_charging_state = None battery_charging_state = None
@ -488,9 +495,11 @@ class HomeAccessory(Accessory): # type: ignore[misc]
self.async_update_battery(new_state.state, battery_charging_state) self.async_update_battery(new_state.state, battery_charging_state)
@ha_callback @ha_callback
def async_update_linked_battery_charging_callback(self, event: Event) -> None: def async_update_linked_battery_charging_callback(
self, event: EventType[EventStateChangedData]
) -> None:
"""Handle linked battery charging sensor state change listener callback.""" """Handle linked battery charging sensor state change listener callback."""
if (new_state := event.data.get("new_state")) is None: if (new_state := event.data["new_state"]) is None:
return return
self.async_update_battery(None, new_state.state == STATE_ON) self.async_update_battery(None, new_state.state == STATE_ON)

View File

@ -14,11 +14,13 @@ from pyhap.const import CATEGORY_CAMERA
from homeassistant.components import camera from homeassistant.components import camera
from homeassistant.components.ffmpeg import get_ffmpeg_manager from homeassistant.components.ffmpeg import get_ffmpeg_manager
from homeassistant.const import STATE_ON from homeassistant.const import STATE_ON
from homeassistant.core import Event, callback from homeassistant.core import State, callback
from homeassistant.helpers.event import ( from homeassistant.helpers.event import (
EventStateChangedData,
async_track_state_change_event, async_track_state_change_event,
async_track_time_interval, async_track_time_interval,
) )
from homeassistant.helpers.typing import EventType
from .accessories import TYPES, HomeAccessory from .accessories import TYPES, HomeAccessory
from .const import ( from .const import (
@ -266,13 +268,15 @@ class Camera(HomeAccessory, PyhapCamera):
await super().run() await super().run()
@callback @callback
def _async_update_motion_state_event(self, event: Event) -> None: def _async_update_motion_state_event(
self, event: EventType[EventStateChangedData]
) -> None:
"""Handle state change event listener callback.""" """Handle state change event listener callback."""
if not state_changed_event_is_same_state(event): if not state_changed_event_is_same_state(event):
self._async_update_motion_state(event.data.get("new_state")) self._async_update_motion_state(event.data["new_state"])
@callback @callback
def _async_update_motion_state(self, new_state): def _async_update_motion_state(self, new_state: State | None) -> None:
"""Handle link motion sensor state change to update HomeKit value.""" """Handle link motion sensor state change to update HomeKit value."""
if not new_state: if not new_state:
return return
@ -290,13 +294,15 @@ class Camera(HomeAccessory, PyhapCamera):
) )
@callback @callback
def _async_update_doorbell_state_event(self, event: Event) -> None: def _async_update_doorbell_state_event(
self, event: EventType[EventStateChangedData]
) -> None:
"""Handle state change event listener callback.""" """Handle state change event listener callback."""
if not state_changed_event_is_same_state(event): if not state_changed_event_is_same_state(event):
self._async_update_doorbell_state(event.data.get("new_state")) self._async_update_doorbell_state(event.data["new_state"])
@callback @callback
def _async_update_doorbell_state(self, new_state): def _async_update_doorbell_state(self, new_state: State | None) -> None:
"""Handle link doorbell sensor state change to update HomeKit value.""" """Handle link doorbell sensor state change to update HomeKit value."""
if not new_state: if not new_state:
return return

View File

@ -31,7 +31,11 @@ from homeassistant.const import (
STATE_OPENING, STATE_OPENING,
) )
from homeassistant.core import State, callback from homeassistant.core import State, callback
from homeassistant.helpers.event import async_track_state_change_event from homeassistant.helpers.event import (
EventStateChangedData,
async_track_state_change_event,
)
from homeassistant.helpers.typing import EventType
from .accessories import TYPES, HomeAccessory from .accessories import TYPES, HomeAccessory
from .const import ( from .const import (
@ -135,12 +139,14 @@ class GarageDoorOpener(HomeAccessory):
await super().run() await super().run()
@callback @callback
def _async_update_obstruction_event(self, event): def _async_update_obstruction_event(
self, event: EventType[EventStateChangedData]
) -> None:
"""Handle state change event listener callback.""" """Handle state change event listener callback."""
self._async_update_obstruction_state(event.data.get("new_state")) self._async_update_obstruction_state(event.data["new_state"])
@callback @callback
def _async_update_obstruction_state(self, new_state): def _async_update_obstruction_state(self, new_state: State | None) -> None:
"""Handle linked obstruction sensor state change to update HomeKit value.""" """Handle linked obstruction sensor state change to update HomeKit value."""
if not new_state: if not new_state:
return return

View File

@ -21,8 +21,12 @@ from homeassistant.const import (
SERVICE_TURN_ON, SERVICE_TURN_ON,
STATE_ON, STATE_ON,
) )
from homeassistant.core import callback from homeassistant.core import State, callback
from homeassistant.helpers.event import async_track_state_change_event from homeassistant.helpers.event import (
EventStateChangedData,
async_track_state_change_event,
)
from homeassistant.helpers.typing import EventType
from .accessories import TYPES, HomeAccessory from .accessories import TYPES, HomeAccessory
from .const import ( from .const import (
@ -157,12 +161,14 @@ class HumidifierDehumidifier(HomeAccessory):
await super().run() await super().run()
@callback @callback
def async_update_current_humidity_event(self, event): def async_update_current_humidity_event(
self, event: EventType[EventStateChangedData]
) -> None:
"""Handle state change event listener callback.""" """Handle state change event listener callback."""
self._async_update_current_humidity(event.data.get("new_state")) self._async_update_current_humidity(event.data["new_state"])
@callback @callback
def _async_update_current_humidity(self, new_state): def _async_update_current_humidity(self, new_state: State | None) -> None:
"""Handle linked humidity sensor state change to update HomeKit value.""" """Handle linked humidity sensor state change to update HomeKit value."""
if new_state is None: if new_state is None:
_LOGGER.error( _LOGGER.error(

View File

@ -26,7 +26,7 @@ from homeassistant.const import (
STATE_UNKNOWN, STATE_UNKNOWN,
UnitOfTime, UnitOfTime,
) )
from homeassistant.core import Event, HomeAssistant, State, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import ( from homeassistant.helpers import (
config_validation as cv, config_validation as cv,
device_registry as dr, device_registry as dr,
@ -34,8 +34,11 @@ from homeassistant.helpers import (
) )
from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.event import async_track_state_change_event from homeassistant.helpers.event import (
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType EventStateChangedData,
async_track_state_change_event,
)
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType, EventType
from .const import ( from .const import (
CONF_ROUND_DIGITS, CONF_ROUND_DIGITS,
@ -290,10 +293,10 @@ class IntegrationSensor(RestoreSensor):
self._unit_of_measurement = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) self._unit_of_measurement = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
@callback @callback
def calc_integration(event: Event) -> None: def calc_integration(event: EventType[EventStateChangedData]) -> None:
"""Handle the sensor state changes.""" """Handle the sensor state changes."""
old_state: State | None = event.data.get("old_state") old_state = event.data["old_state"]
new_state: State | None = event.data.get("new_state") new_state = event.data["new_state"]
# We may want to update our state before an early return, # We may want to update our state before an early return,
# based on the source sensor's unit_of_measurement # based on the source sensor's unit_of_measurement

View File

@ -17,9 +17,12 @@ from homeassistant.const import (
STATE_UNAVAILABLE, STATE_UNAVAILABLE,
STATE_UNKNOWN, STATE_UNKNOWN,
) )
from homeassistant.core import Event, HomeAssistant, State, callback from homeassistant.core import HomeAssistant, State, callback
from homeassistant.helpers.event import async_track_state_change_event from homeassistant.helpers.event import (
from homeassistant.helpers.typing import ConfigType, StateType EventStateChangedData,
async_track_state_change_event,
)
from homeassistant.helpers.typing import ConfigType, EventType, StateType
from .const import CONF_RESPOND_TO_READ, KNX_ADDRESS from .const import CONF_RESPOND_TO_READ, KNX_ADDRESS
from .schema import ExposeSchema from .schema import ExposeSchema
@ -145,12 +148,14 @@ class KNXExposeSensor:
return str(value)[:14] return str(value)[:14]
return value return value
async def _async_entity_changed(self, event: Event) -> None: async def _async_entity_changed(
self, event: EventType[EventStateChangedData]
) -> None:
"""Handle entity change.""" """Handle entity change."""
new_state = event.data.get("new_state") new_state = event.data["new_state"]
if (new_value := self._get_expose_value(new_state)) is None: if (new_value := self._get_expose_value(new_state)) is None:
return return
old_state = event.data.get("old_state") old_state = event.data["old_state"]
# don't use default value for comparison on first state change (old_state is None) # don't use default value for comparison on first state change (old_state is None)
old_value = self._get_expose_value(old_state) if old_state is not None else None old_value = self._get_expose_value(old_state) if old_state is not None else None
# don't send same value sequentially # don't send same value sequentially

View File

@ -33,10 +33,11 @@ from homeassistant.exceptions import HomeAssistantError
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.event import ( from homeassistant.helpers.event import (
EventStateChangedData,
async_track_point_in_time, async_track_point_in_time,
async_track_state_change_event, async_track_state_change_event,
) )
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType, EventType
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -481,9 +482,11 @@ class ManualMQTTAlarm(alarm.AlarmControlPanelEntity):
self.hass, self._command_topic, message_received, self._qos self.hass, self._command_topic, message_received, self._qos
) )
async def _async_state_changed_listener(self, event): async def _async_state_changed_listener(
self, event: EventType[EventStateChangedData]
) -> None:
"""Publish state change to MQTT.""" """Publish state change to MQTT."""
if (new_state := event.data.get("new_state")) is None: if (new_state := event.data["new_state"]) is None:
return return
await mqtt.async_publish( await mqtt.async_publish(
self.hass, self._state_topic, new_state.state, self._qos, True self.hass, self._state_topic, new_state.state, self._qos, True

View File

@ -22,14 +22,18 @@ from homeassistant.const import (
STATE_UNAVAILABLE, STATE_UNAVAILABLE,
STATE_UNKNOWN, STATE_UNKNOWN,
) )
from homeassistant.core import Event, HomeAssistant, State, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import config_validation as cv, entity_registry as er from homeassistant.helpers import config_validation as cv, entity_registry as er
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.event import async_track_state_change_event from homeassistant.helpers.event import (
EventStateChangedData,
async_track_state_change_event,
)
from homeassistant.helpers.reload import async_setup_reload_service from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.typing import ( from homeassistant.helpers.typing import (
ConfigType, ConfigType,
DiscoveryInfoType, DiscoveryInfoType,
EventType,
StateType, StateType,
) )
@ -253,7 +257,9 @@ class MinMaxSensor(SensorEntity):
# Replay current state of source entities # Replay current state of source entities
for entity_id in self._entity_ids: for entity_id in self._entity_ids:
state = self.hass.states.get(entity_id) state = self.hass.states.get(entity_id)
state_event = Event("", {"entity_id": entity_id, "new_state": state}) state_event: EventType[EventStateChangedData] = EventType(
"", {"entity_id": entity_id, "new_state": state, "old_state": None}
)
self._async_min_max_sensor_state_listener(state_event, update_state=False) self._async_min_max_sensor_state_listener(state_event, update_state=False)
self._calc_values() self._calc_values()
@ -286,11 +292,11 @@ class MinMaxSensor(SensorEntity):
@callback @callback
def _async_min_max_sensor_state_listener( def _async_min_max_sensor_state_listener(
self, event: Event, update_state: bool = True self, event: EventType[EventStateChangedData], update_state: bool = True
) -> None: ) -> None:
"""Handle the sensor state changes.""" """Handle the sensor state changes."""
new_state: State | None = event.data.get("new_state") new_state = event.data["new_state"]
entity: str = event.data["entity_id"] entity = event.data["entity_id"]
if ( if (
new_state is None new_state is None