diff --git a/homeassistant/components/togrill/__init__.py b/homeassistant/components/togrill/__init__.py index fcacc851dd9..696b7395f1e 100644 --- a/homeassistant/components/togrill/__init__.py +++ b/homeassistant/components/togrill/__init__.py @@ -8,7 +8,7 @@ from homeassistant.exceptions import ConfigEntryNotReady from .coordinator import DeviceNotFound, ToGrillConfigEntry, ToGrillCoordinator -_PLATFORMS: list[Platform] = [Platform.SENSOR, Platform.NUMBER] +_PLATFORMS: list[Platform] = [Platform.EVENT, Platform.SENSOR, Platform.NUMBER] async def async_setup_entry(hass: HomeAssistant, entry: ToGrillConfigEntry) -> bool: diff --git a/homeassistant/components/togrill/coordinator.py b/homeassistant/components/togrill/coordinator.py index b2f20963fc8..75964067de7 100644 --- a/homeassistant/components/togrill/coordinator.py +++ b/homeassistant/components/togrill/coordinator.py @@ -2,6 +2,7 @@ from __future__ import annotations +from collections.abc import Callable from datetime import timedelta import logging from typing import TypeVar @@ -78,6 +79,7 @@ class ToGrillCoordinator(DataUpdateCoordinator[dict[tuple[int, int | None], Pack self.device_info = DeviceInfo( connections={(CONNECTION_BLUETOOTH, self.address)} ) + self._packet_listeners: list[Callable[[Packet], None]] = [] config_entry.async_on_unload( async_register_callback( @@ -88,6 +90,23 @@ class ToGrillCoordinator(DataUpdateCoordinator[dict[tuple[int, int | None], Pack ) ) + @callback + def async_add_packet_listener( + self, packet_callback: Callable[[Packet], None] + ) -> Callable[[], None]: + """Add a listener for a given packet type.""" + + def _unregister(): + self._packet_listeners.remove(packet_callback) + + self._packet_listeners.append(packet_callback) + return _unregister + + def async_update_packet_listeners(self, packet: Packet): + """Update all packet listeners.""" + for listener in self._packet_listeners: + listener(packet) + async def _connect_and_update_registry(self) -> Client: """Update device registry data.""" device = bluetooth.async_ble_device_from_address( @@ -151,6 +170,7 @@ class ToGrillCoordinator(DataUpdateCoordinator[dict[tuple[int, int | None], Pack def _notify_callback(self, packet: Packet): probe = getattr(packet, "probe", None) self.data[(packet.type, probe)] = packet + self.async_update_packet_listeners(packet) self.async_update_listeners() async def _async_update_data(self) -> dict[tuple[int, int | None], Packet]: diff --git a/homeassistant/components/togrill/event.py b/homeassistant/components/togrill/event.py new file mode 100644 index 00000000000..eb0cc502080 --- /dev/null +++ b/homeassistant/components/togrill/event.py @@ -0,0 +1,59 @@ +"""Support for event entities.""" + +from __future__ import annotations + +from togrill_bluetooth.packets import Packet, PacketA5Notify + +from homeassistant.components.event import EventEntity +from homeassistant.core import HomeAssistant, callback +from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback +from homeassistant.util import slugify + +from . import ToGrillConfigEntry +from .const import CONF_PROBE_COUNT +from .coordinator import ToGrillCoordinator +from .entity import ToGrillEntity + +PARALLEL_UPDATES = 0 + + +async def async_setup_entry( + hass: HomeAssistant, + config_entry: ToGrillConfigEntry, + async_add_entities: AddConfigEntryEntitiesCallback, +) -> None: + """Set up event platform.""" + async_add_entities( + ToGrillEventEntity(config_entry.runtime_data, probe_number=probe_number) + for probe_number in range(1, config_entry.data[CONF_PROBE_COUNT] + 1) + ) + + +class ToGrillEventEntity(ToGrillEntity, EventEntity): + """Representation of a Hue Event entity from a button resource.""" + + def __init__(self, coordinator: ToGrillCoordinator, probe_number: int) -> None: + """Initialize the entity.""" + super().__init__(coordinator=coordinator) + + self._attr_translation_key = "event" + self._attr_translation_placeholders = {"probe_number": f"{probe_number}"} + self._attr_unique_id = f"{coordinator.address}_{probe_number}" + self._probe_number = probe_number + + self._attr_event_types: list[str] = [ + slugify(event.name) for event in PacketA5Notify.Message + ] + + self.async_on_remove(coordinator.async_add_packet_listener(self._handle_event)) + + @callback + def _handle_event(self, packet: Packet) -> None: + if not isinstance(packet, PacketA5Notify): + return + + try: + message = PacketA5Notify.Message(packet.message) + except ValueError: + return + self._trigger_event(slugify(message.name)) diff --git a/homeassistant/components/togrill/strings.json b/homeassistant/components/togrill/strings.json index a49b6613d3c..309ac65f54c 100644 --- a/homeassistant/components/togrill/strings.json +++ b/homeassistant/components/togrill/strings.json @@ -46,6 +46,20 @@ "alarm_interval": { "name": "Alarm interval" } + }, + "event": { + "event": { + "name": "Probe {probe_number}", + "state_attributes": { + "event_type": { + "state": { + "probe_acknowledge": "Alarm acknowledged", + "probe_alarm": "Alarm triggered", + "probe_disconnected": "Probe disconnected" + } + } + } + } } } } diff --git a/tests/components/togrill/snapshots/test_event.ambr b/tests/components/togrill/snapshots/test_event.ambr new file mode 100644 index 00000000000..18b175e7513 --- /dev/null +++ b/tests/components/togrill/snapshots/test_event.ambr @@ -0,0 +1,721 @@ +# serializer version: 1 +# name: test_events[0][event.pro_05_probe_1-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'event_types': list([ + 'probe_acknowledge', + 'probe_alarm', + 'probe_disconnected', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'event', + 'entity_category': None, + 'entity_id': 'event.pro_05_probe_1', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Probe 1', + 'platform': 'togrill', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'event', + 'unique_id': '00000000-0000-0000-0000-000000000001_1', + 'unit_of_measurement': None, + }) +# --- +# name: test_events[0][event.pro_05_probe_1-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'event_type': 'probe_acknowledge', + 'event_types': list([ + 'probe_acknowledge', + 'probe_alarm', + 'probe_disconnected', + ]), + 'friendly_name': 'Pro-05 Probe 1', + }), + 'context': , + 'entity_id': 'event.pro_05_probe_1', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '2023-10-21T00:00:00.000+00:00', + }) +# --- +# name: test_events[0][event.pro_05_probe_2-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'event_types': list([ + 'probe_acknowledge', + 'probe_alarm', + 'probe_disconnected', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'event', + 'entity_category': None, + 'entity_id': 'event.pro_05_probe_2', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Probe 2', + 'platform': 'togrill', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'event', + 'unique_id': '00000000-0000-0000-0000-000000000001_2', + 'unit_of_measurement': None, + }) +# --- +# name: test_events[0][event.pro_05_probe_2-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'event_type': 'probe_acknowledge', + 'event_types': list([ + 'probe_acknowledge', + 'probe_alarm', + 'probe_disconnected', + ]), + 'friendly_name': 'Pro-05 Probe 2', + }), + 'context': , + 'entity_id': 'event.pro_05_probe_2', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '2023-10-21T00:00:00.000+00:00', + }) +# --- +# name: test_events[5][event.pro_05_probe_1-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'event_types': list([ + 'probe_acknowledge', + 'probe_alarm', + 'probe_disconnected', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'event', + 'entity_category': None, + 'entity_id': 'event.pro_05_probe_1', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Probe 1', + 'platform': 'togrill', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'event', + 'unique_id': '00000000-0000-0000-0000-000000000001_1', + 'unit_of_measurement': None, + }) +# --- +# name: test_events[5][event.pro_05_probe_1-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'event_type': 'probe_alarm', + 'event_types': list([ + 'probe_acknowledge', + 'probe_alarm', + 'probe_disconnected', + ]), + 'friendly_name': 'Pro-05 Probe 1', + }), + 'context': , + 'entity_id': 'event.pro_05_probe_1', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '2023-10-21T00:00:00.000+00:00', + }) +# --- +# name: test_events[5][event.pro_05_probe_2-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'event_types': list([ + 'probe_acknowledge', + 'probe_alarm', + 'probe_disconnected', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'event', + 'entity_category': None, + 'entity_id': 'event.pro_05_probe_2', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Probe 2', + 'platform': 'togrill', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'event', + 'unique_id': '00000000-0000-0000-0000-000000000001_2', + 'unit_of_measurement': None, + }) +# --- +# name: test_events[5][event.pro_05_probe_2-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'event_type': 'probe_alarm', + 'event_types': list([ + 'probe_acknowledge', + 'probe_alarm', + 'probe_disconnected', + ]), + 'friendly_name': 'Pro-05 Probe 2', + }), + 'context': , + 'entity_id': 'event.pro_05_probe_2', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '2023-10-21T00:00:00.000+00:00', + }) +# --- +# name: test_events[6][event.pro_05_probe_1-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'event_types': list([ + 'probe_acknowledge', + 'probe_alarm', + 'probe_disconnected', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'event', + 'entity_category': None, + 'entity_id': 'event.pro_05_probe_1', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Probe 1', + 'platform': 'togrill', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'event', + 'unique_id': '00000000-0000-0000-0000-000000000001_1', + 'unit_of_measurement': None, + }) +# --- +# name: test_events[6][event.pro_05_probe_1-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'event_type': 'probe_disconnected', + 'event_types': list([ + 'probe_acknowledge', + 'probe_alarm', + 'probe_disconnected', + ]), + 'friendly_name': 'Pro-05 Probe 1', + }), + 'context': , + 'entity_id': 'event.pro_05_probe_1', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '2023-10-21T00:00:00.000+00:00', + }) +# --- +# name: test_events[6][event.pro_05_probe_2-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'event_types': list([ + 'probe_acknowledge', + 'probe_alarm', + 'probe_disconnected', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'event', + 'entity_category': None, + 'entity_id': 'event.pro_05_probe_2', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Probe 2', + 'platform': 'togrill', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'event', + 'unique_id': '00000000-0000-0000-0000-000000000001_2', + 'unit_of_measurement': None, + }) +# --- +# name: test_events[6][event.pro_05_probe_2-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'event_type': 'probe_disconnected', + 'event_types': list([ + 'probe_acknowledge', + 'probe_alarm', + 'probe_disconnected', + ]), + 'friendly_name': 'Pro-05 Probe 2', + }), + 'context': , + 'entity_id': 'event.pro_05_probe_2', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '2023-10-21T00:00:00.000+00:00', + }) +# --- +# name: test_setup[no_data][event.pro_05_probe_1-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'event_types': list([ + 'probe_acknowledge', + 'probe_alarm', + 'probe_disconnected', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'event', + 'entity_category': None, + 'entity_id': 'event.pro_05_probe_1', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Probe 1', + 'platform': 'togrill', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'event', + 'unique_id': '00000000-0000-0000-0000-000000000001_1', + 'unit_of_measurement': None, + }) +# --- +# name: test_setup[no_data][event.pro_05_probe_1-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'event_type': None, + 'event_types': list([ + 'probe_acknowledge', + 'probe_alarm', + 'probe_disconnected', + ]), + 'friendly_name': 'Pro-05 Probe 1', + }), + 'context': , + 'entity_id': 'event.pro_05_probe_1', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- +# name: test_setup[no_data][event.pro_05_probe_2-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'event_types': list([ + 'probe_acknowledge', + 'probe_alarm', + 'probe_disconnected', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'event', + 'entity_category': None, + 'entity_id': 'event.pro_05_probe_2', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Probe 2', + 'platform': 'togrill', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'event', + 'unique_id': '00000000-0000-0000-0000-000000000001_2', + 'unit_of_measurement': None, + }) +# --- +# name: test_setup[no_data][event.pro_05_probe_2-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'event_type': None, + 'event_types': list([ + 'probe_acknowledge', + 'probe_alarm', + 'probe_disconnected', + ]), + 'friendly_name': 'Pro-05 Probe 2', + }), + 'context': , + 'entity_id': 'event.pro_05_probe_2', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- +# name: test_setup[non_event_packet][event.pro_05_probe_1-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'event_types': list([ + 'probe_acknowledge', + 'probe_alarm', + 'probe_disconnected', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'event', + 'entity_category': None, + 'entity_id': 'event.pro_05_probe_1', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Probe 1', + 'platform': 'togrill', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'event', + 'unique_id': '00000000-0000-0000-0000-000000000001_1', + 'unit_of_measurement': None, + }) +# --- +# name: test_setup[non_event_packet][event.pro_05_probe_1-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'event_type': None, + 'event_types': list([ + 'probe_acknowledge', + 'probe_alarm', + 'probe_disconnected', + ]), + 'friendly_name': 'Pro-05 Probe 1', + }), + 'context': , + 'entity_id': 'event.pro_05_probe_1', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- +# name: test_setup[non_event_packet][event.pro_05_probe_2-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'event_types': list([ + 'probe_acknowledge', + 'probe_alarm', + 'probe_disconnected', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'event', + 'entity_category': None, + 'entity_id': 'event.pro_05_probe_2', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Probe 2', + 'platform': 'togrill', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'event', + 'unique_id': '00000000-0000-0000-0000-000000000001_2', + 'unit_of_measurement': None, + }) +# --- +# name: test_setup[non_event_packet][event.pro_05_probe_2-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'event_type': None, + 'event_types': list([ + 'probe_acknowledge', + 'probe_alarm', + 'probe_disconnected', + ]), + 'friendly_name': 'Pro-05 Probe 2', + }), + 'context': , + 'entity_id': 'event.pro_05_probe_2', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- +# name: test_setup[non_known_message][event.pro_05_probe_1-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'event_types': list([ + 'probe_acknowledge', + 'probe_alarm', + 'probe_disconnected', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'event', + 'entity_category': None, + 'entity_id': 'event.pro_05_probe_1', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Probe 1', + 'platform': 'togrill', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'event', + 'unique_id': '00000000-0000-0000-0000-000000000001_1', + 'unit_of_measurement': None, + }) +# --- +# name: test_setup[non_known_message][event.pro_05_probe_1-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'event_type': None, + 'event_types': list([ + 'probe_acknowledge', + 'probe_alarm', + 'probe_disconnected', + ]), + 'friendly_name': 'Pro-05 Probe 1', + }), + 'context': , + 'entity_id': 'event.pro_05_probe_1', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- +# name: test_setup[non_known_message][event.pro_05_probe_2-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'event_types': list([ + 'probe_acknowledge', + 'probe_alarm', + 'probe_disconnected', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'event', + 'entity_category': None, + 'entity_id': 'event.pro_05_probe_2', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Probe 2', + 'platform': 'togrill', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'event', + 'unique_id': '00000000-0000-0000-0000-000000000001_2', + 'unit_of_measurement': None, + }) +# --- +# name: test_setup[non_known_message][event.pro_05_probe_2-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'event_type': None, + 'event_types': list([ + 'probe_acknowledge', + 'probe_alarm', + 'probe_disconnected', + ]), + 'friendly_name': 'Pro-05 Probe 2', + }), + 'context': , + 'entity_id': 'event.pro_05_probe_2', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- diff --git a/tests/components/togrill/test_event.py b/tests/components/togrill/test_event.py new file mode 100644 index 00000000000..932e6e93433 --- /dev/null +++ b/tests/components/togrill/test_event.py @@ -0,0 +1,69 @@ +"""Test events for ToGrill integration.""" + +from unittest.mock import Mock + +import pytest +from syrupy.assertion import SnapshotAssertion +from togrill_bluetooth.packets import PacketA1Notify, PacketA5Notify + +from homeassistant.const import Platform +from homeassistant.core import HomeAssistant +from homeassistant.helpers import entity_registry as er + +from . import TOGRILL_SERVICE_INFO, setup_entry + +from tests.common import MockConfigEntry, snapshot_platform +from tests.components.bluetooth import inject_bluetooth_service_info + + +@pytest.mark.freeze_time("2023-10-21") +@pytest.mark.parametrize( + "packets", + [ + pytest.param([], id="no_data"), + pytest.param([PacketA1Notify([10, None])], id="non_event_packet"), + pytest.param([PacketA5Notify(probe=1, message=99)], id="non_known_message"), + ], +) +async def test_setup( + hass: HomeAssistant, + entity_registry: er.EntityRegistry, + snapshot: SnapshotAssertion, + mock_entry: MockConfigEntry, + mock_client: Mock, + packets, +) -> None: + """Test standard events.""" + + inject_bluetooth_service_info(hass, TOGRILL_SERVICE_INFO) + + await setup_entry(hass, mock_entry, [Platform.EVENT]) + + for packet in packets: + mock_client.mocked_notify(packet) + + await snapshot_platform(hass, entity_registry, snapshot, mock_entry.entry_id) + + +@pytest.mark.freeze_time("2023-10-21") +@pytest.mark.parametrize( + "message", + list(PacketA5Notify.Message), +) +async def test_events( + hass: HomeAssistant, + entity_registry: er.EntityRegistry, + snapshot: SnapshotAssertion, + mock_entry: MockConfigEntry, + mock_client: Mock, + message, +) -> None: + """Test all possible events.""" + + inject_bluetooth_service_info(hass, TOGRILL_SERVICE_INFO) + + await setup_entry(hass, mock_entry, [Platform.EVENT]) + + mock_client.mocked_notify(PacketA5Notify(probe=1, message=message)) + + await snapshot_platform(hass, entity_registry, snapshot, mock_entry.entry_id)