1
0
mirror of https://github.com/home-assistant/core.git synced 2026-05-14 20:41:24 +01:00
Files
core/tests/components/switchbot/test_event.py
T
2026-04-14 16:32:03 +02:00

130 lines
4.4 KiB
Python

"""Test the switchbot event entities."""
from collections.abc import Callable
from datetime import timedelta
from unittest.mock import patch
from freezegun.api import FrozenDateTimeFactory
import pytest
from homeassistant.components.bluetooth import BluetoothServiceInfoBleak
from homeassistant.components.switchbot.const import DOMAIN
from homeassistant.const import STATE_UNKNOWN
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from . import KEYPAD_VISION_PRO_INFO
from tests.common import MockConfigEntry
from tests.components.bluetooth import (
generate_advertisement_data,
generate_ble_device,
inject_bluetooth_service_info,
)
def _with_doorbell_seq(
info: BluetoothServiceInfoBleak, seq: int = 1
) -> BluetoothServiceInfoBleak:
"""Return a BLE service info with the doorbell seq bits set."""
mfr_data = bytearray(info.manufacturer_data[2409])
mfr_data[12] = (mfr_data[12] & 0b11111000) | (seq & 0b00000111)
updated_mfr_data = {2409: bytes(mfr_data)}
return BluetoothServiceInfoBleak(
name=info.name,
manufacturer_data=updated_mfr_data,
service_data=info.service_data,
service_uuids=info.service_uuids,
address=info.address,
rssi=info.rssi,
source=info.source,
advertisement=generate_advertisement_data(
local_name=info.name,
manufacturer_data=updated_mfr_data,
service_data=info.service_data,
service_uuids=info.service_uuids,
),
device=generate_ble_device(info.address, info.name),
time=info.time,
connectable=info.connectable,
tx_power=info.tx_power,
)
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_keypad_vision_pro_doorbell_event(
hass: HomeAssistant,
mock_entry_encrypted_factory: Callable[[str], MockConfigEntry],
freezer: FrozenDateTimeFactory,
) -> None:
"""Test keypad vision pro doorbell event uses doorbell_seq for detection."""
await async_setup_component(hass, DOMAIN, {})
inject_bluetooth_service_info(hass, KEYPAD_VISION_PRO_INFO)
entry = mock_entry_encrypted_factory(sensor_type="keypad_vision_pro")
entry.add_to_hass(hass)
with patch(
"homeassistant.components.switchbot.sensor.switchbot.SwitchbotKeypadVision.update",
return_value=True,
):
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
entity_id = "event.test_name_doorbell"
state = hass.states.get(entity_id)
assert state
assert state.state == STATE_UNKNOWN
# First ring: seq changes from 0 → 1
freezer.tick(timedelta(seconds=1))
inject_bluetooth_service_info(
hass, _with_doorbell_seq(KEYPAD_VISION_PRO_INFO, 1)
)
await hass.async_block_till_done()
state = hass.states.get(entity_id)
assert state
assert state.state != STATE_UNKNOWN
assert state.attributes["event_type"] == "ring"
first_ring_state = state.state
# Same seq repeated — no new ring event
freezer.tick(timedelta(seconds=1))
inject_bluetooth_service_info(
hass, _with_doorbell_seq(KEYPAD_VISION_PRO_INFO, 1)
)
await hass.async_block_till_done()
assert hass.states.get(entity_id).state == first_ring_state
# Second ring: seq changes from 1 → 2
freezer.tick(timedelta(seconds=1))
inject_bluetooth_service_info(
hass, _with_doorbell_seq(KEYPAD_VISION_PRO_INFO, 2)
)
await hass.async_block_till_done()
state = hass.states.get(entity_id)
assert state.state != first_ring_state
assert state.attributes["event_type"] == "ring"
# Seq wraps from 7 → 1 — still a ring
freezer.tick(timedelta(seconds=1))
inject_bluetooth_service_info(
hass, _with_doorbell_seq(KEYPAD_VISION_PRO_INFO, 7)
)
await hass.async_block_till_done()
third_ring_state = hass.states.get(entity_id).state
freezer.tick(timedelta(seconds=1))
inject_bluetooth_service_info(
hass, _with_doorbell_seq(KEYPAD_VISION_PRO_INFO, 1)
)
await hass.async_block_till_done()
state = hass.states.get(entity_id)
assert state.state != third_ring_state
assert state.attributes["event_type"] == "ring"