mirror of https://github.com/home-assistant/core
296 lines
9.6 KiB
Python
296 lines
9.6 KiB
Python
"""Test the Xiaomi BLE events."""
|
|
|
|
import pytest
|
|
|
|
from homeassistant.components.event import ATTR_EVENT_TYPE
|
|
from homeassistant.components.xiaomi_ble.const import DOMAIN
|
|
from homeassistant.const import ATTR_FRIENDLY_NAME, STATE_ON, STATE_UNAVAILABLE
|
|
from homeassistant.core import HomeAssistant
|
|
|
|
from . import make_advertisement
|
|
|
|
from tests.common import MockConfigEntry
|
|
from tests.components.bluetooth import (
|
|
BluetoothServiceInfoBleak,
|
|
inject_bluetooth_service_info,
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("mac_address", "advertisement", "bind_key", "result"),
|
|
[
|
|
(
|
|
"54:EF:44:E3:9C:BC",
|
|
make_advertisement(
|
|
"54:EF:44:E3:9C:BC",
|
|
b'XY\x97\td\xbc\x9c\xe3D\xefT" `'
|
|
b"\x88\xfd\x00\x00\x00\x00:\x14\x8f\xb3",
|
|
),
|
|
"5b51a7c91cde6707c9ef18dfda143a58",
|
|
[
|
|
{
|
|
"entity": "event.smoke_detector_9cbc_button",
|
|
ATTR_FRIENDLY_NAME: "Smoke Detector 9CBC Button",
|
|
ATTR_EVENT_TYPE: "press",
|
|
}
|
|
],
|
|
),
|
|
(
|
|
"DC:ED:83:87:12:73",
|
|
make_advertisement(
|
|
"DC:ED:83:87:12:73",
|
|
b"XYI\x19Os\x12\x87\x83\xed\xdc\x0b48\n\x02\x00\x00\x8dI\xae(",
|
|
),
|
|
"b93eb3787eabda352edd94b667f5d5a9",
|
|
[
|
|
{
|
|
"entity": "event.switch_double_button_1273_button_right",
|
|
ATTR_FRIENDLY_NAME: "Switch (double button) 1273 Button right",
|
|
ATTR_EVENT_TYPE: "press",
|
|
}
|
|
],
|
|
),
|
|
(
|
|
"F8:24:41:E9:50:74",
|
|
make_advertisement(
|
|
"F8:24:41:E9:50:74",
|
|
b"P0S\x01?tP\xe9A$\xf8\x01\x10\x03\x04\x00\x02",
|
|
),
|
|
None,
|
|
[
|
|
{
|
|
"entity": "event.remote_control_5074_button_m",
|
|
ATTR_FRIENDLY_NAME: "Remote Control 5074 Button M",
|
|
ATTR_EVENT_TYPE: "long_press",
|
|
}
|
|
],
|
|
),
|
|
(
|
|
"F8:24:41:E9:50:74",
|
|
make_advertisement(
|
|
"F8:24:41:E9:50:74",
|
|
b"P0S\x01?tP\xe9A$\xf8\x01\x10\x03\x03\x00\x00",
|
|
),
|
|
None,
|
|
[
|
|
{
|
|
"entity": "event.remote_control_5074_button_plus",
|
|
ATTR_FRIENDLY_NAME: "Remote Control 5074 Button plus",
|
|
ATTR_EVENT_TYPE: "press",
|
|
}
|
|
],
|
|
),
|
|
(
|
|
"DE:70:E8:B2:39:0C",
|
|
make_advertisement(
|
|
"DE:70:E8:B2:39:0C",
|
|
b"@0\xdd\x03$\x03\x00\x01\x01",
|
|
),
|
|
None,
|
|
[
|
|
{
|
|
"entity": "event.nightlight_390c_motion",
|
|
ATTR_FRIENDLY_NAME: "Nightlight 390C Motion",
|
|
ATTR_EVENT_TYPE: "motion_detected",
|
|
}
|
|
],
|
|
),
|
|
(
|
|
"E2:53:30:E6:D3:54",
|
|
make_advertisement(
|
|
"E2:53:30:E6:D3:54",
|
|
b"P0\xe1\x04\x8eT\xd3\xe60S\xe2\x01\x10\x03\x01\x00\x00",
|
|
),
|
|
None,
|
|
[
|
|
{
|
|
"entity": "event.magic_cube_d354_cube",
|
|
ATTR_FRIENDLY_NAME: "Magic Cube D354 Cube",
|
|
ATTR_EVENT_TYPE: "rotate_left",
|
|
}
|
|
],
|
|
),
|
|
(
|
|
"F8:24:41:C5:98:8B",
|
|
make_advertisement(
|
|
"F8:24:41:C5:98:8B",
|
|
b"X0\xb6\x036\x8b\x98\xc5A$\xf8\x8b\xb8\xf2f" b"\x13Q\x00\x00\x00\xd6",
|
|
),
|
|
"b853075158487ca39a5b5ea9",
|
|
[
|
|
{
|
|
"entity": "event.dimmer_switch_988b_dimmer",
|
|
ATTR_FRIENDLY_NAME: "Dimmer Switch 988B Dimmer",
|
|
ATTR_EVENT_TYPE: "rotate_left",
|
|
"event_properties": {"steps": 1},
|
|
}
|
|
],
|
|
),
|
|
(
|
|
"F8:24:41:C5:98:8B",
|
|
make_advertisement(
|
|
"F8:24:41:C5:98:8B",
|
|
b"X0\xb6\x03\xd2\x8b\x98\xc5A$\xf8\xc3I\x14vu~\x00\x00\x00\x99",
|
|
),
|
|
"b853075158487ca39a5b5ea9",
|
|
[
|
|
{
|
|
"entity": "event.dimmer_switch_988b_dimmer",
|
|
ATTR_FRIENDLY_NAME: "Dimmer Switch 988B Dimmer",
|
|
ATTR_EVENT_TYPE: "press",
|
|
"event_properties": {"duration": 2},
|
|
}
|
|
],
|
|
),
|
|
],
|
|
)
|
|
async def test_events(
|
|
hass: HomeAssistant,
|
|
mac_address: str,
|
|
advertisement: BluetoothServiceInfoBleak,
|
|
bind_key: str | None,
|
|
result: list[dict[str, str]],
|
|
) -> None:
|
|
"""Test the different Xiaomi BLE events."""
|
|
entry = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
unique_id=mac_address,
|
|
data={"bindkey": bind_key},
|
|
)
|
|
entry.add_to_hass(hass)
|
|
|
|
assert await hass.config_entries.async_setup(entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
assert len(hass.states.async_all()) == 0
|
|
|
|
inject_bluetooth_service_info(
|
|
hass,
|
|
advertisement,
|
|
)
|
|
await hass.async_block_till_done()
|
|
assert len(hass.states.async_all()) == len(result)
|
|
|
|
for meas in result:
|
|
state = hass.states.get(meas["entity"])
|
|
attributes = state.attributes
|
|
assert attributes[ATTR_FRIENDLY_NAME] == meas[ATTR_FRIENDLY_NAME]
|
|
assert attributes[ATTR_EVENT_TYPE] == meas[ATTR_EVENT_TYPE]
|
|
assert await hass.config_entries.async_unload(entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
assert await hass.config_entries.async_setup(entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
# Ensure entities are restored
|
|
for meas in result:
|
|
state = hass.states.get(meas["entity"])
|
|
assert state != STATE_UNAVAILABLE
|
|
|
|
# Now inject again
|
|
inject_bluetooth_service_info(
|
|
hass,
|
|
advertisement,
|
|
)
|
|
await hass.async_block_till_done()
|
|
assert len(hass.states.async_all()) == len(result)
|
|
|
|
for meas in result:
|
|
state = hass.states.get(meas["entity"])
|
|
attributes = state.attributes
|
|
assert attributes[ATTR_FRIENDLY_NAME] == meas[ATTR_FRIENDLY_NAME]
|
|
assert attributes[ATTR_EVENT_TYPE] == meas[ATTR_EVENT_TYPE]
|
|
assert await hass.config_entries.async_unload(entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
async def test_xiaomi_fingerprint(hass: HomeAssistant) -> None:
|
|
"""Make sure that fingerprint reader events are correctly mapped."""
|
|
entry = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
unique_id="D7:1F:44:EB:8A:91",
|
|
)
|
|
entry.add_to_hass(hass)
|
|
|
|
assert await hass.config_entries.async_setup(entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
assert len(hass.states.async_all()) == 0
|
|
|
|
inject_bluetooth_service_info(
|
|
hass,
|
|
make_advertisement(
|
|
"D7:1F:44:EB:8A:91",
|
|
b"PD\x9e\x06B\x91\x8a\xebD\x1f\xd7" b"\x06\x00\x05\xff\xff\xff\xff\x00",
|
|
),
|
|
)
|
|
|
|
await hass.async_block_till_done()
|
|
assert len(hass.states.async_all()) == 3
|
|
|
|
sensor = hass.states.get("sensor.door_lock_8a91_key_id")
|
|
sensor_attr = sensor.attributes
|
|
assert sensor.state == "unknown operator"
|
|
assert sensor_attr[ATTR_FRIENDLY_NAME] == "Door Lock 8A91 Key id"
|
|
|
|
binary_sensor = hass.states.get("binary_sensor.door_lock_8a91_fingerprint")
|
|
binary_sensor_attribtes = binary_sensor.attributes
|
|
assert binary_sensor.state == STATE_ON
|
|
assert binary_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Door Lock 8A91 Fingerprint"
|
|
|
|
event = hass.states.get("event.door_lock_8a91_fingerprint")
|
|
event_attr = event.attributes
|
|
assert event_attr[ATTR_FRIENDLY_NAME] == "Door Lock 8A91 Fingerprint"
|
|
assert event_attr[ATTR_EVENT_TYPE] == "match_successful"
|
|
|
|
assert await hass.config_entries.async_unload(entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
async def test_xiaomi_lock(hass: HomeAssistant) -> None:
|
|
"""Make sure that lock events are correctly mapped."""
|
|
entry = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
unique_id="D7:1F:44:EB:8A:91",
|
|
)
|
|
entry.add_to_hass(hass)
|
|
|
|
assert await hass.config_entries.async_setup(entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
assert len(hass.states.async_all()) == 0
|
|
|
|
inject_bluetooth_service_info(
|
|
hass,
|
|
make_advertisement(
|
|
"D7:1F:44:EB:8A:91",
|
|
b"PD\x9e\x06C\x91\x8a\xebD\x1f\xd7\x0b\x00\t" b" \x02\x00\x01\x80|D/a",
|
|
),
|
|
)
|
|
|
|
await hass.async_block_till_done()
|
|
assert len(hass.states.async_all()) == 4
|
|
|
|
event = hass.states.get("event.door_lock_8a91_lock")
|
|
event_attr = event.attributes
|
|
assert event_attr[ATTR_FRIENDLY_NAME] == "Door Lock 8A91 Lock"
|
|
assert event_attr[ATTR_EVENT_TYPE] == "unlock_outside_the_door"
|
|
|
|
sensor = hass.states.get("sensor.door_lock_8a91_lock_method")
|
|
sensor_attr = sensor.attributes
|
|
assert sensor.state == "biometrics"
|
|
assert sensor_attr[ATTR_FRIENDLY_NAME] == "Door Lock 8A91 Lock method"
|
|
|
|
sensor = hass.states.get("sensor.door_lock_8a91_key_id")
|
|
sensor_attr = sensor.attributes
|
|
assert sensor.state == "Fingerprint key id 2"
|
|
assert sensor_attr[ATTR_FRIENDLY_NAME] == "Door Lock 8A91 Key id"
|
|
|
|
binary_sensor = hass.states.get("binary_sensor.door_lock_8a91_lock")
|
|
binary_sensor_attribtes = binary_sensor.attributes
|
|
assert binary_sensor.state == STATE_ON
|
|
assert binary_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Door Lock 8A91 Lock"
|
|
|
|
assert await hass.config_entries.async_unload(entry.entry_id)
|
|
await hass.async_block_till_done()
|