mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 01:08:12 +00:00
Add door, opening and motion sensors to Xiaomi-ble (#84990)
This commit is contained in:
parent
b5664f9eaf
commit
171e114ec1
@ -5,6 +5,7 @@ from typing import Optional
|
||||
|
||||
from xiaomi_ble.parser import (
|
||||
BinarySensorDeviceClass as XiaomiBinarySensorDeviceClass,
|
||||
ExtendedBinarySensorDeviceClass,
|
||||
SensorUpdate,
|
||||
)
|
||||
|
||||
@ -28,20 +29,48 @@ from .const import DOMAIN
|
||||
from .device import device_key_to_bluetooth_entity_key
|
||||
|
||||
BINARY_SENSOR_DESCRIPTIONS = {
|
||||
XiaomiBinarySensorDeviceClass.MOTION: BinarySensorEntityDescription(
|
||||
key=XiaomiBinarySensorDeviceClass.MOTION,
|
||||
device_class=BinarySensorDeviceClass.MOTION,
|
||||
XiaomiBinarySensorDeviceClass.DOOR: BinarySensorEntityDescription(
|
||||
key=XiaomiBinarySensorDeviceClass.DOOR,
|
||||
device_class=BinarySensorDeviceClass.DOOR,
|
||||
),
|
||||
XiaomiBinarySensorDeviceClass.LIGHT: BinarySensorEntityDescription(
|
||||
key=XiaomiBinarySensorDeviceClass.LIGHT,
|
||||
device_class=BinarySensorDeviceClass.LIGHT,
|
||||
),
|
||||
XiaomiBinarySensorDeviceClass.MOISTURE: BinarySensorEntityDescription(
|
||||
key=XiaomiBinarySensorDeviceClass.MOISTURE,
|
||||
device_class=BinarySensorDeviceClass.MOISTURE,
|
||||
),
|
||||
XiaomiBinarySensorDeviceClass.MOTION: BinarySensorEntityDescription(
|
||||
key=XiaomiBinarySensorDeviceClass.MOTION,
|
||||
device_class=BinarySensorDeviceClass.MOTION,
|
||||
),
|
||||
XiaomiBinarySensorDeviceClass.OPENING: BinarySensorEntityDescription(
|
||||
key=XiaomiBinarySensorDeviceClass.OPENING,
|
||||
device_class=BinarySensorDeviceClass.OPENING,
|
||||
),
|
||||
XiaomiBinarySensorDeviceClass.SMOKE: BinarySensorEntityDescription(
|
||||
key=XiaomiBinarySensorDeviceClass.SMOKE,
|
||||
device_class=BinarySensorDeviceClass.SMOKE,
|
||||
),
|
||||
XiaomiBinarySensorDeviceClass.MOISTURE: BinarySensorEntityDescription(
|
||||
key=XiaomiBinarySensorDeviceClass.MOISTURE,
|
||||
ExtendedBinarySensorDeviceClass.DEVICE_FORCIBLY_REMOVED: BinarySensorEntityDescription(
|
||||
key=ExtendedBinarySensorDeviceClass.DEVICE_FORCIBLY_REMOVED,
|
||||
device_class=BinarySensorDeviceClass.PROBLEM,
|
||||
),
|
||||
ExtendedBinarySensorDeviceClass.DOOR_LEFT_OPEN: BinarySensorEntityDescription(
|
||||
key=ExtendedBinarySensorDeviceClass.DOOR_LEFT_OPEN,
|
||||
device_class=BinarySensorDeviceClass.PROBLEM,
|
||||
),
|
||||
ExtendedBinarySensorDeviceClass.DOOR_STUCK: BinarySensorEntityDescription(
|
||||
key=ExtendedBinarySensorDeviceClass.DOOR_STUCK,
|
||||
device_class=BinarySensorDeviceClass.PROBLEM,
|
||||
),
|
||||
ExtendedBinarySensorDeviceClass.KNOCK_ON_THE_DOOR: BinarySensorEntityDescription(
|
||||
key=ExtendedBinarySensorDeviceClass.KNOCK_ON_THE_DOOR,
|
||||
),
|
||||
ExtendedBinarySensorDeviceClass.PRY_THE_DOOR: BinarySensorEntityDescription(
|
||||
key=ExtendedBinarySensorDeviceClass.PRY_THE_DOOR,
|
||||
device_class=BinarySensorDeviceClass.TAMPER,
|
||||
),
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
"service_data_uuid": "0000fe95-0000-1000-8000-00805f9b34fb"
|
||||
}
|
||||
],
|
||||
"requirements": ["xiaomi-ble==0.12.2"],
|
||||
"requirements": ["xiaomi-ble==0.14.3"],
|
||||
"dependencies": ["bluetooth"],
|
||||
"codeowners": ["@Jc2k", "@Ernst79"],
|
||||
"iot_class": "local_push"
|
||||
|
@ -2597,7 +2597,7 @@ xbox-webapi==2.0.11
|
||||
xboxapi==2.0.1
|
||||
|
||||
# homeassistant.components.xiaomi_ble
|
||||
xiaomi-ble==0.12.2
|
||||
xiaomi-ble==0.14.3
|
||||
|
||||
# homeassistant.components.knx
|
||||
xknx==2.2.0
|
||||
|
@ -1816,7 +1816,7 @@ wolf_smartset==0.1.11
|
||||
xbox-webapi==2.0.11
|
||||
|
||||
# homeassistant.components.xiaomi_ble
|
||||
xiaomi-ble==0.12.2
|
||||
xiaomi-ble==0.14.3
|
||||
|
||||
# homeassistant.components.knx
|
||||
xknx==2.2.0
|
||||
|
@ -9,12 +9,12 @@ from tests.common import MockConfigEntry
|
||||
from tests.components.bluetooth import inject_bluetooth_service_info_bleak
|
||||
|
||||
|
||||
async def test_smoke_sensor(hass):
|
||||
"""Test setting up a smoke sensor."""
|
||||
async def test_door_problem_sensors(hass):
|
||||
"""Test setting up a door binary sensor with additional problem sensors."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
unique_id="54:EF:44:E3:9C:BC",
|
||||
data={"bindkey": "5b51a7c91cde6707c9ef18dfda143a58"},
|
||||
unique_id="EE:89:73:44:BE:98",
|
||||
data={"bindkey": "2c3795afa33019a8afdc17ba99e6f217"},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
@ -25,24 +25,72 @@ async def test_smoke_sensor(hass):
|
||||
inject_bluetooth_service_info_bleak(
|
||||
hass,
|
||||
make_advertisement(
|
||||
"54:EF:44:E3:9C:BC",
|
||||
b"XY\x97\tf\xbc\x9c\xe3D\xefT\x01" b"\x08\x12\x05\x00\x00\x00q^\xbe\x90",
|
||||
"EE:89:73:44:BE:98",
|
||||
b"HU9\x0e3\x9cq\xc0$\x1f\xff\xee\x80S\x00\x00\x02\xb4\xc59",
|
||||
),
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.states.async_all()) == 1
|
||||
assert len(hass.states.async_all()) == 3
|
||||
|
||||
smoke_sensor = hass.states.get("binary_sensor.thermometer_9cbc_smoke")
|
||||
smoke_sensor_attribtes = smoke_sensor.attributes
|
||||
assert smoke_sensor.state == "on"
|
||||
assert smoke_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Thermometer 9CBC Smoke"
|
||||
door_sensor = hass.states.get("binary_sensor.door_lock_be98_door")
|
||||
door_sensor_attribtes = door_sensor.attributes
|
||||
assert door_sensor.state == "off"
|
||||
assert door_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Door Lock BE98 Door"
|
||||
|
||||
door_left_open = hass.states.get("binary_sensor.door_lock_be98_door_left_open")
|
||||
door_left_open_attribtes = door_left_open.attributes
|
||||
assert door_left_open.state == "off"
|
||||
assert (
|
||||
door_left_open_attribtes[ATTR_FRIENDLY_NAME] == "Door Lock BE98 Door left open"
|
||||
)
|
||||
|
||||
pry_the_door = hass.states.get("binary_sensor.door_lock_be98_pry_the_door")
|
||||
pry_the_door_attribtes = pry_the_door.attributes
|
||||
assert pry_the_door.state == "off"
|
||||
assert pry_the_door_attribtes[ATTR_FRIENDLY_NAME] == "Door Lock BE98 Pry the door"
|
||||
|
||||
assert await hass.config_entries.async_unload(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
||||
async def test_light_motion(hass):
|
||||
"""Test setting up a light and motion binary sensor."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
unique_id="58:2D:34:35:93:21",
|
||||
)
|
||||
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_bleak(
|
||||
hass,
|
||||
make_advertisement(
|
||||
"58:2D:34:35:93:21",
|
||||
b"P \xf6\x07\xda!\x9354-X\x0f\x00\x03\x01\x00\x00",
|
||||
),
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.states.async_all()) == 2
|
||||
|
||||
motion_sensor = hass.states.get("binary_sensor.nightlight_9321_motion")
|
||||
motion_sensor_attribtes = motion_sensor.attributes
|
||||
assert motion_sensor.state == "on"
|
||||
assert motion_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Nightlight 9321 Motion"
|
||||
|
||||
light_sensor = hass.states.get("binary_sensor.nightlight_9321_light")
|
||||
light_sensor_attribtes = light_sensor.attributes
|
||||
assert light_sensor.state == "off"
|
||||
assert light_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Nightlight 9321 Light"
|
||||
|
||||
assert await hass.config_entries.async_unload(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
||||
async def test_moisture(hass):
|
||||
"""Make sure that formldehyde sensors are correctly mapped."""
|
||||
"""Test setting up a moisture binary sensor."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
unique_id="C4:7C:8D:6A:3E:7A",
|
||||
@ -73,3 +121,125 @@ async def test_moisture(hass):
|
||||
|
||||
assert await hass.config_entries.async_unload(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
||||
async def test_opening(hass):
|
||||
"""Test setting up a opening binary sensor."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
unique_id="A4:C1:38:66:E5:67",
|
||||
data={"bindkey": "0fdcc30fe9289254876b5ef7c11ef1f0"},
|
||||
)
|
||||
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_bleak(
|
||||
hass,
|
||||
make_advertisement(
|
||||
"A4:C1:38:66:E5:67",
|
||||
b"XY\x89\x18\x9ag\xe5f8\xc1\xa4\x9d\xd9z\xf3&\x00\x00\xc8\xa6\x0b\xd5",
|
||||
),
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
opening_sensor = hass.states.get("binary_sensor.door_window_sensor_e567_opening")
|
||||
opening_sensor_attribtes = opening_sensor.attributes
|
||||
assert opening_sensor.state == "on"
|
||||
assert (
|
||||
opening_sensor_attribtes[ATTR_FRIENDLY_NAME]
|
||||
== "Door/Window Sensor E567 Opening"
|
||||
)
|
||||
|
||||
assert await hass.config_entries.async_unload(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
||||
async def test_opening_problem_sensors(hass):
|
||||
"""Test setting up a opening binary sensor with additional problem sensors."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
unique_id="A4:C1:38:66:E5:67",
|
||||
data={"bindkey": "0fdcc30fe9289254876b5ef7c11ef1f0"},
|
||||
)
|
||||
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_bleak(
|
||||
hass,
|
||||
make_advertisement(
|
||||
"A4:C1:38:66:E5:67",
|
||||
b"XY\x89\x18ug\xe5f8\xc1\xa4i\xdd\xf3\xa1&\x00\x00\xa2J\x1bE",
|
||||
),
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.states.async_all()) == 3
|
||||
|
||||
opening_sensor = hass.states.get("binary_sensor.door_window_sensor_e567_opening")
|
||||
opening_sensor_attribtes = opening_sensor.attributes
|
||||
assert opening_sensor.state == "off"
|
||||
assert (
|
||||
opening_sensor_attribtes[ATTR_FRIENDLY_NAME]
|
||||
== "Door/Window Sensor E567 Opening"
|
||||
)
|
||||
|
||||
door_left_open = hass.states.get(
|
||||
"binary_sensor.door_window_sensor_e567_door_left_open"
|
||||
)
|
||||
door_left_open_attribtes = door_left_open.attributes
|
||||
assert door_left_open.state == "off"
|
||||
assert (
|
||||
door_left_open_attribtes[ATTR_FRIENDLY_NAME]
|
||||
== "Door/Window Sensor E567 Door left open"
|
||||
)
|
||||
|
||||
device_forcibly_removed = hass.states.get(
|
||||
"binary_sensor.door_window_sensor_e567_device_forcibly_removed"
|
||||
)
|
||||
device_forcibly_removed_attribtes = device_forcibly_removed.attributes
|
||||
assert device_forcibly_removed.state == "off"
|
||||
assert (
|
||||
device_forcibly_removed_attribtes[ATTR_FRIENDLY_NAME]
|
||||
== "Door/Window Sensor E567 Device forcibly removed"
|
||||
)
|
||||
|
||||
assert await hass.config_entries.async_unload(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
||||
async def test_smoke(hass):
|
||||
"""Test setting up a smoke binary sensor."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
unique_id="54:EF:44:E3:9C:BC",
|
||||
data={"bindkey": "5b51a7c91cde6707c9ef18dfda143a58"},
|
||||
)
|
||||
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_bleak(
|
||||
hass,
|
||||
make_advertisement(
|
||||
"54:EF:44:E3:9C:BC",
|
||||
b"XY\x97\tf\xbc\x9c\xe3D\xefT\x01" b"\x08\x12\x05\x00\x00\x00q^\xbe\x90",
|
||||
),
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
smoke_sensor = hass.states.get("binary_sensor.thermometer_9cbc_smoke")
|
||||
smoke_sensor_attribtes = smoke_sensor.attributes
|
||||
assert smoke_sensor.state == "on"
|
||||
assert smoke_sensor_attribtes[ATTR_FRIENDLY_NAME] == "Thermometer 9CBC Smoke"
|
||||
|
||||
assert await hass.config_entries.async_unload(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
Loading…
x
Reference in New Issue
Block a user