mirror of
https://github.com/home-assistant/core.git
synced 2025-07-17 02:07:09 +00:00
Allow adding new devices to an Aqara hub via homekit_controller (#62600)
This commit is contained in:
parent
6e13605cad
commit
06eec7adfc
@ -48,6 +48,9 @@ HOMEKIT_ACCESSORY_DISPATCH = {
|
|||||||
|
|
||||||
CHARACTERISTIC_PLATFORMS = {
|
CHARACTERISTIC_PLATFORMS = {
|
||||||
CharacteristicsTypes.Vendor.AQARA_GATEWAY_VOLUME: "number",
|
CharacteristicsTypes.Vendor.AQARA_GATEWAY_VOLUME: "number",
|
||||||
|
CharacteristicsTypes.Vendor.AQARA_E1_GATEWAY_VOLUME: "number",
|
||||||
|
CharacteristicsTypes.Vendor.AQARA_PAIRING_MODE: "switch",
|
||||||
|
CharacteristicsTypes.Vendor.AQARA_E1_PAIRING_MODE: "switch",
|
||||||
CharacteristicsTypes.Vendor.EVE_ENERGY_WATT: "sensor",
|
CharacteristicsTypes.Vendor.EVE_ENERGY_WATT: "sensor",
|
||||||
CharacteristicsTypes.Vendor.EVE_DEGREE_AIR_PRESSURE: "sensor",
|
CharacteristicsTypes.Vendor.EVE_DEGREE_AIR_PRESSURE: "sensor",
|
||||||
CharacteristicsTypes.Vendor.EVE_DEGREE_ELEVATION: "number",
|
CharacteristicsTypes.Vendor.EVE_DEGREE_ELEVATION: "number",
|
||||||
|
@ -75,10 +75,9 @@ class HomeKitNumber(CharacteristicEntity, NumberEntity):
|
|||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
"""Return the name of the device if any."""
|
"""Return the name of the device if any."""
|
||||||
prefix = ""
|
if prefix := super().name:
|
||||||
if name := super().name:
|
|
||||||
prefix = f"{name} -"
|
|
||||||
return f"{prefix} {self.entity_description.name}"
|
return f"{prefix} {self.entity_description.name}"
|
||||||
|
return self.entity_description.name
|
||||||
|
|
||||||
def get_characteristic_types(self):
|
def get_characteristic_types(self):
|
||||||
"""Define the homekit characteristics the entity is tracking."""
|
"""Define the homekit characteristics the entity is tracking."""
|
||||||
|
@ -1,15 +1,21 @@
|
|||||||
"""Support for Homekit switches."""
|
"""Support for Homekit switches."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
from aiohomekit.model.characteristics import (
|
from aiohomekit.model.characteristics import (
|
||||||
|
Characteristic,
|
||||||
CharacteristicsTypes,
|
CharacteristicsTypes,
|
||||||
InUseValues,
|
InUseValues,
|
||||||
IsConfiguredValues,
|
IsConfiguredValues,
|
||||||
)
|
)
|
||||||
from aiohomekit.model.services import ServicesTypes
|
from aiohomekit.model.services import ServicesTypes
|
||||||
|
|
||||||
from homeassistant.components.switch import SwitchEntity
|
from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
|
from homeassistant.helpers.entity import EntityCategory
|
||||||
|
|
||||||
from . import KNOWN_DEVICES, HomeKitEntity
|
from . import KNOWN_DEVICES, CharacteristicEntity, HomeKitEntity
|
||||||
|
|
||||||
OUTLET_IN_USE = "outlet_in_use"
|
OUTLET_IN_USE = "outlet_in_use"
|
||||||
|
|
||||||
@ -18,6 +24,30 @@ ATTR_IS_CONFIGURED = "is_configured"
|
|||||||
ATTR_REMAINING_DURATION = "remaining_duration"
|
ATTR_REMAINING_DURATION = "remaining_duration"
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DeclarativeSwitchEntityDescription(SwitchEntityDescription):
|
||||||
|
"""Describes Homekit button."""
|
||||||
|
|
||||||
|
true_value: bool = True
|
||||||
|
false_value: bool = False
|
||||||
|
|
||||||
|
|
||||||
|
SWITCH_ENTITIES: dict[str, DeclarativeSwitchEntityDescription] = {
|
||||||
|
CharacteristicsTypes.Vendor.AQARA_PAIRING_MODE: DeclarativeSwitchEntityDescription(
|
||||||
|
key=CharacteristicsTypes.Vendor.AQARA_PAIRING_MODE,
|
||||||
|
name="Pairing Mode",
|
||||||
|
icon="mdi:lock-open",
|
||||||
|
entity_category=EntityCategory.CONFIG,
|
||||||
|
),
|
||||||
|
CharacteristicsTypes.Vendor.AQARA_E1_PAIRING_MODE: DeclarativeSwitchEntityDescription(
|
||||||
|
key=CharacteristicsTypes.Vendor.AQARA_E1_PAIRING_MODE,
|
||||||
|
name="Pairing Mode",
|
||||||
|
icon="mdi:lock-open",
|
||||||
|
entity_category=EntityCategory.CONFIG,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class HomeKitSwitch(HomeKitEntity, SwitchEntity):
|
class HomeKitSwitch(HomeKitEntity, SwitchEntity):
|
||||||
"""Representation of a Homekit switch."""
|
"""Representation of a Homekit switch."""
|
||||||
|
|
||||||
@ -96,6 +126,49 @@ class HomeKitValve(HomeKitEntity, SwitchEntity):
|
|||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
|
|
||||||
|
class DeclarativeCharacteristicSwitch(CharacteristicEntity, SwitchEntity):
|
||||||
|
"""Representation of a Homekit switch backed by a single characteristic."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
conn,
|
||||||
|
info,
|
||||||
|
char,
|
||||||
|
description: DeclarativeSwitchEntityDescription,
|
||||||
|
):
|
||||||
|
"""Initialise a HomeKit switch."""
|
||||||
|
self.entity_description = description
|
||||||
|
super().__init__(conn, info, char)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self) -> str:
|
||||||
|
"""Return the name of the device if any."""
|
||||||
|
if prefix := super().name:
|
||||||
|
return f"{prefix} {self.entity_description.name}"
|
||||||
|
return self.entity_description.name
|
||||||
|
|
||||||
|
def get_characteristic_types(self):
|
||||||
|
"""Define the homekit characteristics the entity cares about."""
|
||||||
|
return [self._char.type]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_on(self):
|
||||||
|
"""Return true if device is on."""
|
||||||
|
return self._char.value == self.entity_description.true_value
|
||||||
|
|
||||||
|
async def async_turn_on(self, **kwargs):
|
||||||
|
"""Turn the specified switch on."""
|
||||||
|
await self.async_put_characteristics(
|
||||||
|
{self._char.type: self.entity_description.true_value}
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_turn_off(self, **kwargs):
|
||||||
|
"""Turn the specified switch off."""
|
||||||
|
await self.async_put_characteristics(
|
||||||
|
{self._char.type: self.entity_description.false_value}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
ENTITY_TYPES = {
|
ENTITY_TYPES = {
|
||||||
ServicesTypes.SWITCH: HomeKitSwitch,
|
ServicesTypes.SWITCH: HomeKitSwitch,
|
||||||
ServicesTypes.OUTLET: HomeKitSwitch,
|
ServicesTypes.OUTLET: HomeKitSwitch,
|
||||||
@ -117,3 +190,16 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
conn.add_listener(async_add_service)
|
conn.add_listener(async_add_service)
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_add_characteristic(char: Characteristic):
|
||||||
|
if not (description := SWITCH_ENTITIES.get(char.type)):
|
||||||
|
return False
|
||||||
|
|
||||||
|
info = {"aid": char.service.accessory.aid, "iid": char.service.iid}
|
||||||
|
async_add_entities(
|
||||||
|
[DeclarativeCharacteristicSwitch(conn, info, char, description)], True
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
|
conn.add_char_factory(async_add_characteristic)
|
||||||
|
646
tests/components/homekit_controller/fixtures/aqara_e1.json
Normal file
646
tests/components/homekit_controller/fixtures/aqara_e1.json
Normal file
@ -0,0 +1,646 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"aid": 1,
|
||||||
|
"services": [
|
||||||
|
{
|
||||||
|
"iid": 1,
|
||||||
|
"type": "0000003E-0000-1000-8000-0026BB765291",
|
||||||
|
"primary": false,
|
||||||
|
"hidden": false,
|
||||||
|
"characteristics": [
|
||||||
|
{
|
||||||
|
"iid": 65537,
|
||||||
|
"type": "00000014-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "bool",
|
||||||
|
"perms": [
|
||||||
|
"pw"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 65538,
|
||||||
|
"type": "00000020-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "string",
|
||||||
|
"value": "Aqara",
|
||||||
|
"perms": [
|
||||||
|
"pr"
|
||||||
|
],
|
||||||
|
"ev": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 65539,
|
||||||
|
"type": "00000021-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "string",
|
||||||
|
"value": "HE1-G01",
|
||||||
|
"perms": [
|
||||||
|
"pr"
|
||||||
|
],
|
||||||
|
"ev": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 65540,
|
||||||
|
"type": "00000023-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "string",
|
||||||
|
"value": "Aqara-Hub-E1-00A0",
|
||||||
|
"perms": [
|
||||||
|
"pr"
|
||||||
|
],
|
||||||
|
"ev": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 65541,
|
||||||
|
"type": "00000030-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "string",
|
||||||
|
"value": "00aa00000a0",
|
||||||
|
"perms": [
|
||||||
|
"pr"
|
||||||
|
],
|
||||||
|
"ev": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 65542,
|
||||||
|
"type": "00000052-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "string",
|
||||||
|
"value": "3.3.0",
|
||||||
|
"perms": [
|
||||||
|
"pr"
|
||||||
|
],
|
||||||
|
"ev": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 65543,
|
||||||
|
"type": "00000053-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "string",
|
||||||
|
"value": "1.0",
|
||||||
|
"perms": [
|
||||||
|
"pr"
|
||||||
|
],
|
||||||
|
"ev": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 65544,
|
||||||
|
"type": "34AB8811-AC7F-4340-BAC3-FD6A85F9943B",
|
||||||
|
"format": "string",
|
||||||
|
"value": "5.0;dfeceb3a",
|
||||||
|
"perms": [
|
||||||
|
"pr",
|
||||||
|
"hd"
|
||||||
|
],
|
||||||
|
"ev": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 65545,
|
||||||
|
"type": "220",
|
||||||
|
"format": "data",
|
||||||
|
"value": "xDsGO4QdTEA=",
|
||||||
|
"perms": [
|
||||||
|
"pr"
|
||||||
|
],
|
||||||
|
"ev": false,
|
||||||
|
"maxDataLen": 8
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 2,
|
||||||
|
"type": "000000A2-0000-1000-8000-0026BB765291",
|
||||||
|
"primary": false,
|
||||||
|
"hidden": false,
|
||||||
|
"characteristics": [
|
||||||
|
{
|
||||||
|
"iid": 131074,
|
||||||
|
"type": "00000037-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "string",
|
||||||
|
"value": "1.1.0",
|
||||||
|
"perms": [
|
||||||
|
"pr"
|
||||||
|
],
|
||||||
|
"ev": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 4,
|
||||||
|
"type": "22A",
|
||||||
|
"primary": false,
|
||||||
|
"hidden": false,
|
||||||
|
"characteristics": [
|
||||||
|
{
|
||||||
|
"iid": 262145,
|
||||||
|
"type": "22B",
|
||||||
|
"format": "bool",
|
||||||
|
"value": 1,
|
||||||
|
"perms": [
|
||||||
|
"pr"
|
||||||
|
],
|
||||||
|
"ev": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 262146,
|
||||||
|
"type": "22C",
|
||||||
|
"format": "uint32",
|
||||||
|
"value": 9,
|
||||||
|
"perms": [
|
||||||
|
"pr"
|
||||||
|
],
|
||||||
|
"ev": false,
|
||||||
|
"minValue": 0,
|
||||||
|
"maxValue": 15,
|
||||||
|
"minStep": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 262147,
|
||||||
|
"type": "22D",
|
||||||
|
"format": "tlv8",
|
||||||
|
"value": "",
|
||||||
|
"perms": [
|
||||||
|
"pr",
|
||||||
|
"pw",
|
||||||
|
"ev",
|
||||||
|
"tw",
|
||||||
|
"wr"
|
||||||
|
],
|
||||||
|
"ev": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 16,
|
||||||
|
"type": "0000007E-0000-1000-8000-0026BB765291",
|
||||||
|
"primary": true,
|
||||||
|
"hidden": false,
|
||||||
|
"characteristics": [
|
||||||
|
{
|
||||||
|
"iid": 1048578,
|
||||||
|
"type": "00000023-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "string",
|
||||||
|
"value": "Security System",
|
||||||
|
"perms": [
|
||||||
|
"pr"
|
||||||
|
],
|
||||||
|
"ev": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 1048579,
|
||||||
|
"type": "00000066-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "uint8",
|
||||||
|
"value": 3,
|
||||||
|
"perms": [
|
||||||
|
"pr",
|
||||||
|
"ev"
|
||||||
|
],
|
||||||
|
"ev": true,
|
||||||
|
"minValue": 0,
|
||||||
|
"maxValue": 4,
|
||||||
|
"minStep": 1,
|
||||||
|
"valid-values": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 1048580,
|
||||||
|
"type": "00000067-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "uint8",
|
||||||
|
"value": 3,
|
||||||
|
"perms": [
|
||||||
|
"pr",
|
||||||
|
"pw",
|
||||||
|
"ev"
|
||||||
|
],
|
||||||
|
"ev": true,
|
||||||
|
"minValue": 0,
|
||||||
|
"maxValue": 3,
|
||||||
|
"minStep": 1,
|
||||||
|
"valid-values": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 1048581,
|
||||||
|
"type": "60CDDE6C-42B6-4C72-9719-AB2740EABE2A",
|
||||||
|
"format": "tlv8",
|
||||||
|
"value": "AAA=",
|
||||||
|
"perms": [
|
||||||
|
"pr",
|
||||||
|
"pw"
|
||||||
|
],
|
||||||
|
"ev": false,
|
||||||
|
"description": "Stay Arm Trigger Devices"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 1048582,
|
||||||
|
"type": "4AB2460A-41E4-4F05-97C3-CCFDAE1BE324",
|
||||||
|
"format": "tlv8",
|
||||||
|
"value": "AAA=",
|
||||||
|
"perms": [
|
||||||
|
"pr",
|
||||||
|
"pw"
|
||||||
|
],
|
||||||
|
"ev": false,
|
||||||
|
"description": "Alarm Trigger Devices"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 1048583,
|
||||||
|
"type": "F8296386-5A30-4AA7-838C-ED0DA9D807DF",
|
||||||
|
"format": "tlv8",
|
||||||
|
"value": "AAA=",
|
||||||
|
"perms": [
|
||||||
|
"pr",
|
||||||
|
"pw"
|
||||||
|
],
|
||||||
|
"ev": false,
|
||||||
|
"description": "Night Arm Trigger Devices"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 17,
|
||||||
|
"type": "9715BF53-AB63-4449-8DC7-2785D617390A",
|
||||||
|
"primary": false,
|
||||||
|
"hidden": true,
|
||||||
|
"characteristics": [
|
||||||
|
{
|
||||||
|
"iid": 1114114,
|
||||||
|
"type": "00000023-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "string",
|
||||||
|
"value": "Gateway",
|
||||||
|
"perms": [
|
||||||
|
"pr"
|
||||||
|
],
|
||||||
|
"ev": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 1114115,
|
||||||
|
"type": "4CB28907-66DF-4D9C-962C-9971ABF30EDC",
|
||||||
|
"format": "string",
|
||||||
|
"value": "1970-01-01 21:01:22+8",
|
||||||
|
"perms": [
|
||||||
|
"pr",
|
||||||
|
"pw",
|
||||||
|
"hd"
|
||||||
|
],
|
||||||
|
"ev": false,
|
||||||
|
"description": "Date and Time"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 1114116,
|
||||||
|
"type": "EE56B186-B0D3-488E-8C79-C21FC9BCF437",
|
||||||
|
"format": "int",
|
||||||
|
"value": 40,
|
||||||
|
"perms": [
|
||||||
|
"pr",
|
||||||
|
"pw",
|
||||||
|
"ev",
|
||||||
|
"hd"
|
||||||
|
],
|
||||||
|
"ev": false,
|
||||||
|
"description": "Gateway Volume",
|
||||||
|
"unit": "percentage",
|
||||||
|
"minValue": 0,
|
||||||
|
"maxValue": 100,
|
||||||
|
"minStep": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 1114117,
|
||||||
|
"type": "B1C09E4C-E202-4827-B863-B0F32F727CFF",
|
||||||
|
"format": "bool",
|
||||||
|
"value": 0,
|
||||||
|
"perms": [
|
||||||
|
"pr",
|
||||||
|
"pw",
|
||||||
|
"ev",
|
||||||
|
"hd"
|
||||||
|
],
|
||||||
|
"ev": false,
|
||||||
|
"description": "New Accessory Permission"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 1114118,
|
||||||
|
"type": "2CB22739-1E4C-4798-A761-BC2FAF51AFC3",
|
||||||
|
"format": "string",
|
||||||
|
"value": "",
|
||||||
|
"perms": [
|
||||||
|
"pr",
|
||||||
|
"ev",
|
||||||
|
"hd"
|
||||||
|
],
|
||||||
|
"ev": false,
|
||||||
|
"description": "Accessory Joined"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 1114119,
|
||||||
|
"type": "75D19FA9-218B-4943-997E-341E5D1C60CC",
|
||||||
|
"format": "string",
|
||||||
|
"perms": [
|
||||||
|
"pw",
|
||||||
|
"hd"
|
||||||
|
],
|
||||||
|
"description": "Remove Accessory"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 1114120,
|
||||||
|
"type": "7D943F6A-E052-4E96-A176-D17BF00E32CB",
|
||||||
|
"format": "int",
|
||||||
|
"value": -1,
|
||||||
|
"perms": [
|
||||||
|
"pr",
|
||||||
|
"ev",
|
||||||
|
"hd"
|
||||||
|
],
|
||||||
|
"ev": false,
|
||||||
|
"description": "Firmware Update Status",
|
||||||
|
"minValue": -65535,
|
||||||
|
"maxValue": 65535,
|
||||||
|
"minStep": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 1114121,
|
||||||
|
"type": "A45EFD52-0DB5-4C1A-9727-513FBCD8185F",
|
||||||
|
"format": "string",
|
||||||
|
"perms": [
|
||||||
|
"pw",
|
||||||
|
"hd"
|
||||||
|
],
|
||||||
|
"description": "Firmware Update URL",
|
||||||
|
"maxLen": 256
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 1114122,
|
||||||
|
"type": "40F0124A-579D-40E4-865E-0EF6740EA64B",
|
||||||
|
"format": "string",
|
||||||
|
"perms": [
|
||||||
|
"pw",
|
||||||
|
"hd"
|
||||||
|
],
|
||||||
|
"description": "Firmware Update Checksum"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 1114123,
|
||||||
|
"type": "E1C20B22-E3A7-4B92-8BA3-C16E778648A7",
|
||||||
|
"format": "string",
|
||||||
|
"value": "",
|
||||||
|
"perms": [
|
||||||
|
"pr",
|
||||||
|
"ev",
|
||||||
|
"hd"
|
||||||
|
],
|
||||||
|
"ev": false,
|
||||||
|
"description": "Identify Accessory"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 1114124,
|
||||||
|
"type": "4CF1436A-755C-4377-BDB8-30BE29EB8620",
|
||||||
|
"format": "string",
|
||||||
|
"value": "Chinese",
|
||||||
|
"perms": [
|
||||||
|
"pr",
|
||||||
|
"pw",
|
||||||
|
"ev",
|
||||||
|
"hd"
|
||||||
|
],
|
||||||
|
"ev": false,
|
||||||
|
"description": "Language"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 1114125,
|
||||||
|
"type": "25D889CB-7135-4A29-B5B4-C1FFD6D2DD5C",
|
||||||
|
"format": "string",
|
||||||
|
"value": "",
|
||||||
|
"perms": [
|
||||||
|
"pr",
|
||||||
|
"pw",
|
||||||
|
"hd"
|
||||||
|
],
|
||||||
|
"ev": false,
|
||||||
|
"description": "Country Domain"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 1114126,
|
||||||
|
"type": "C7EECAA7-91D9-40EB-AD0C-FFDDE3143CB9",
|
||||||
|
"format": "string",
|
||||||
|
"value": "lumi1.00aa00000a0",
|
||||||
|
"perms": [
|
||||||
|
"pr",
|
||||||
|
"hd"
|
||||||
|
],
|
||||||
|
"ev": false,
|
||||||
|
"description": "Lumi Did"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 1114127,
|
||||||
|
"type": "80FA747E-CB45-45A4-B7BE-AA7D9964859E",
|
||||||
|
"format": "string",
|
||||||
|
"perms": [
|
||||||
|
"pw",
|
||||||
|
"hd"
|
||||||
|
],
|
||||||
|
"description": "Lumi Bindkey"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 1114128,
|
||||||
|
"type": "C3B8A329-EF0C-4739-B773-E5B7AEA52C71",
|
||||||
|
"format": "bool",
|
||||||
|
"value": 0,
|
||||||
|
"perms": [
|
||||||
|
"pr",
|
||||||
|
"hd"
|
||||||
|
],
|
||||||
|
"ev": false,
|
||||||
|
"description": "Lumi Bindstate"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"aid": 33,
|
||||||
|
"services": [
|
||||||
|
{
|
||||||
|
"iid": 1,
|
||||||
|
"type": "0000003E-0000-1000-8000-0026BB765291",
|
||||||
|
"primary": false,
|
||||||
|
"hidden": false,
|
||||||
|
"characteristics": [
|
||||||
|
{
|
||||||
|
"iid": 65537,
|
||||||
|
"type": "00000014-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "bool",
|
||||||
|
"perms": [
|
||||||
|
"pw"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 65538,
|
||||||
|
"type": "00000020-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "string",
|
||||||
|
"value": "Aqara",
|
||||||
|
"perms": [
|
||||||
|
"pr"
|
||||||
|
],
|
||||||
|
"ev": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 65539,
|
||||||
|
"type": "00000021-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "string",
|
||||||
|
"value": "AS006",
|
||||||
|
"perms": [
|
||||||
|
"pr"
|
||||||
|
],
|
||||||
|
"ev": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 65540,
|
||||||
|
"type": "00000023-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "string",
|
||||||
|
"value": "Contact Sensor",
|
||||||
|
"perms": [
|
||||||
|
"pr"
|
||||||
|
],
|
||||||
|
"ev": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 65541,
|
||||||
|
"type": "00000030-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "string",
|
||||||
|
"value": "158d0007c59c6a",
|
||||||
|
"perms": [
|
||||||
|
"pr"
|
||||||
|
],
|
||||||
|
"ev": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 65542,
|
||||||
|
"type": "00000052-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "string",
|
||||||
|
"value": "0",
|
||||||
|
"perms": [
|
||||||
|
"pr"
|
||||||
|
],
|
||||||
|
"ev": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 65543,
|
||||||
|
"type": "00000053-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "string",
|
||||||
|
"value": "1.0",
|
||||||
|
"perms": [
|
||||||
|
"pr"
|
||||||
|
],
|
||||||
|
"ev": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 4,
|
||||||
|
"type": "00000080-0000-1000-8000-0026BB765291",
|
||||||
|
"primary": true,
|
||||||
|
"hidden": false,
|
||||||
|
"characteristics": [
|
||||||
|
{
|
||||||
|
"iid": 262146,
|
||||||
|
"type": "00000023-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "string",
|
||||||
|
"value": "Contact Sensor",
|
||||||
|
"perms": [
|
||||||
|
"pr"
|
||||||
|
],
|
||||||
|
"ev": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 262147,
|
||||||
|
"type": "0000006A-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "uint8",
|
||||||
|
"value": 0,
|
||||||
|
"perms": [
|
||||||
|
"pr",
|
||||||
|
"ev"
|
||||||
|
],
|
||||||
|
"ev": true,
|
||||||
|
"minValue": 0,
|
||||||
|
"maxValue": 1,
|
||||||
|
"minStep": 1,
|
||||||
|
"valid-values": [
|
||||||
|
0,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 5,
|
||||||
|
"type": "00000096-0000-1000-8000-0026BB765291",
|
||||||
|
"primary": false,
|
||||||
|
"hidden": false,
|
||||||
|
"characteristics": [
|
||||||
|
{
|
||||||
|
"iid": 327682,
|
||||||
|
"type": "00000023-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "string",
|
||||||
|
"value": "Battery Sensor",
|
||||||
|
"perms": [
|
||||||
|
"pr"
|
||||||
|
],
|
||||||
|
"ev": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 327683,
|
||||||
|
"type": "00000068-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "uint8",
|
||||||
|
"value": 100,
|
||||||
|
"perms": [
|
||||||
|
"pr",
|
||||||
|
"ev"
|
||||||
|
],
|
||||||
|
"ev": true,
|
||||||
|
"unit": "percentage",
|
||||||
|
"minValue": 0,
|
||||||
|
"maxValue": 100,
|
||||||
|
"minStep": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 327685,
|
||||||
|
"type": "00000079-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "uint8",
|
||||||
|
"value": 0,
|
||||||
|
"perms": [
|
||||||
|
"pr",
|
||||||
|
"ev"
|
||||||
|
],
|
||||||
|
"ev": true,
|
||||||
|
"minValue": 0,
|
||||||
|
"maxValue": 1,
|
||||||
|
"minStep": 1,
|
||||||
|
"valid-values": [
|
||||||
|
0,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"iid": 327684,
|
||||||
|
"type": "0000008F-0000-1000-8000-0026BB765291",
|
||||||
|
"format": "uint8",
|
||||||
|
"value": 2,
|
||||||
|
"perms": [
|
||||||
|
"pr",
|
||||||
|
"ev"
|
||||||
|
],
|
||||||
|
"ev": true,
|
||||||
|
"minValue": 2,
|
||||||
|
"maxValue": 2,
|
||||||
|
"minStep": 1,
|
||||||
|
"valid-values": [
|
||||||
|
2
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
@ -45,7 +45,14 @@ async def test_aqara_gateway_setup(hass):
|
|||||||
(
|
(
|
||||||
"number.aqara_hub_1563_volume",
|
"number.aqara_hub_1563_volume",
|
||||||
"homekit-0000000123456789-aid:1-sid:65536-cid:65541",
|
"homekit-0000000123456789-aid:1-sid:65536-cid:65541",
|
||||||
"Aqara Hub-1563 - Volume",
|
"Aqara Hub-1563 Volume",
|
||||||
|
None,
|
||||||
|
EntityCategory.CONFIG,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"switch.aqara_hub_1563_pairing_mode",
|
||||||
|
"homekit-0000000123456789-aid:1-sid:65536-cid:65538",
|
||||||
|
"Aqara Hub-1563 Pairing Mode",
|
||||||
None,
|
None,
|
||||||
EntityCategory.CONFIG,
|
EntityCategory.CONFIG,
|
||||||
),
|
),
|
||||||
@ -80,3 +87,66 @@ async def test_aqara_gateway_setup(hass):
|
|||||||
|
|
||||||
# All entities should be part of same device
|
# All entities should be part of same device
|
||||||
assert len(device_ids) == 1
|
assert len(device_ids) == 1
|
||||||
|
|
||||||
|
|
||||||
|
async def test_aqara_gateway_e1_setup(hass):
|
||||||
|
"""Test that an Aqara E1 Gateway can be correctly setup in HA."""
|
||||||
|
accessories = await setup_accessories_from_file(hass, "aqara_e1.json")
|
||||||
|
config_entry, pairing = await setup_test_accessories(hass, accessories)
|
||||||
|
|
||||||
|
entity_registry = er.async_get(hass)
|
||||||
|
device_registry = dr.async_get(hass)
|
||||||
|
|
||||||
|
sensors = [
|
||||||
|
(
|
||||||
|
"alarm_control_panel.aqara_hub_e1_00a0",
|
||||||
|
"homekit-00aa00000a0-16",
|
||||||
|
"Aqara-Hub-E1-00A0",
|
||||||
|
SUPPORT_ALARM_ARM_NIGHT | SUPPORT_ALARM_ARM_HOME | SUPPORT_ALARM_ARM_AWAY,
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"number.aqara_hub_e1_00a0_volume",
|
||||||
|
"homekit-00aa00000a0-aid:1-sid:17-cid:1114116",
|
||||||
|
"Aqara-Hub-E1-00A0 Volume",
|
||||||
|
None,
|
||||||
|
EntityCategory.CONFIG,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"switch.aqara_hub_e1_00a0_pairing_mode",
|
||||||
|
"homekit-00aa00000a0-aid:1-sid:17-cid:1114117",
|
||||||
|
"Aqara-Hub-E1-00A0 Pairing Mode",
|
||||||
|
None,
|
||||||
|
EntityCategory.CONFIG,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
device_ids = set()
|
||||||
|
|
||||||
|
for (entity_id, unique_id, friendly_name, supported_features, category) in sensors:
|
||||||
|
entry = entity_registry.async_get(entity_id)
|
||||||
|
assert entry.unique_id == unique_id
|
||||||
|
assert entry.entity_category == category
|
||||||
|
|
||||||
|
helper = Helper(
|
||||||
|
hass,
|
||||||
|
entity_id,
|
||||||
|
pairing,
|
||||||
|
accessories[0],
|
||||||
|
config_entry,
|
||||||
|
)
|
||||||
|
state = await helper.poll_and_get_state()
|
||||||
|
assert state.attributes["friendly_name"] == friendly_name
|
||||||
|
assert state.attributes.get("supported_features") == supported_features
|
||||||
|
|
||||||
|
device = device_registry.async_get(entry.device_id)
|
||||||
|
assert device.manufacturer == "Aqara"
|
||||||
|
assert device.name == "Aqara-Hub-E1-00A0"
|
||||||
|
assert device.model == "HE1-G01"
|
||||||
|
assert device.sw_version == "3.3.0"
|
||||||
|
assert device.via_device_id is None
|
||||||
|
|
||||||
|
device_ids.add(entry.device_id)
|
||||||
|
|
||||||
|
# All entities should be part of same device
|
||||||
|
assert len(device_ids) == 1
|
||||||
|
@ -41,7 +41,7 @@ async def test_eve_degree_setup(hass):
|
|||||||
(
|
(
|
||||||
"number.eve_degree_aa11_elevation",
|
"number.eve_degree_aa11_elevation",
|
||||||
"homekit-AA00A0A00000-aid:1-sid:30-cid:33",
|
"homekit-AA00A0A00000-aid:1-sid:30-cid:33",
|
||||||
"Eve Degree AA11 - Elevation",
|
"Eve Degree AA11 Elevation",
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -31,8 +31,7 @@ async def test_vocolinc_flowerbud_setup(hass):
|
|||||||
)
|
)
|
||||||
state = await helper.poll_and_get_state()
|
state = await helper.poll_and_get_state()
|
||||||
assert (
|
assert (
|
||||||
state.attributes["friendly_name"]
|
state.attributes["friendly_name"] == "VOCOlinc-Flowerbud-0d324b Spray Quantity"
|
||||||
== "VOCOlinc-Flowerbud-0d324b - Spray Quantity"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
device = device_registry.async_get(entry.device_id)
|
device = device_registry.async_get(entry.device_id)
|
||||||
|
@ -38,6 +38,14 @@ def create_valve_service(accessory):
|
|||||||
remaining.value = 99
|
remaining.value = 99
|
||||||
|
|
||||||
|
|
||||||
|
def create_char_switch_service(accessory):
|
||||||
|
"""Define swtch characteristics."""
|
||||||
|
service = accessory.add_service(ServicesTypes.OUTLET)
|
||||||
|
|
||||||
|
on_char = service.add_char(CharacteristicsTypes.Vendor.AQARA_PAIRING_MODE)
|
||||||
|
on_char.value = False
|
||||||
|
|
||||||
|
|
||||||
async def test_switch_change_outlet_state(hass, utcnow):
|
async def test_switch_change_outlet_state(hass, utcnow):
|
||||||
"""Test that we can turn a HomeKit outlet on and off again."""
|
"""Test that we can turn a HomeKit outlet on and off again."""
|
||||||
helper = await setup_test_component(hass, create_switch_service)
|
helper = await setup_test_component(hass, create_switch_service)
|
||||||
@ -122,3 +130,51 @@ async def test_valve_read_state(hass, utcnow):
|
|||||||
helper.characteristics[("valve", "in-use")].value = InUseValues.NOT_IN_USE
|
helper.characteristics[("valve", "in-use")].value = InUseValues.NOT_IN_USE
|
||||||
switch_1 = await helper.poll_and_get_state()
|
switch_1 = await helper.poll_and_get_state()
|
||||||
assert switch_1.attributes["in_use"] is False
|
assert switch_1.attributes["in_use"] is False
|
||||||
|
|
||||||
|
|
||||||
|
async def test_char_switch_change_state(hass, utcnow):
|
||||||
|
"""Test that we can turn a characteristic on and off again."""
|
||||||
|
helper = await setup_test_component(
|
||||||
|
hass, create_char_switch_service, suffix="pairing_mode"
|
||||||
|
)
|
||||||
|
svc = helper.accessory.services.first(service_type=ServicesTypes.OUTLET)
|
||||||
|
pairing_mode = svc[CharacteristicsTypes.Vendor.AQARA_PAIRING_MODE]
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
"switch",
|
||||||
|
"turn_on",
|
||||||
|
{"entity_id": "switch.testdevice_pairing_mode"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
assert pairing_mode.value is True
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
"switch",
|
||||||
|
"turn_off",
|
||||||
|
{"entity_id": "switch.testdevice_pairing_mode"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
assert pairing_mode.value is False
|
||||||
|
|
||||||
|
|
||||||
|
async def test_char_switch_read_state(hass, utcnow):
|
||||||
|
"""Test that we can read the state of a HomeKit characteristic switch."""
|
||||||
|
helper = await setup_test_component(
|
||||||
|
hass, create_char_switch_service, suffix="pairing_mode"
|
||||||
|
)
|
||||||
|
svc = helper.accessory.services.first(service_type=ServicesTypes.OUTLET)
|
||||||
|
pairing_mode = svc[CharacteristicsTypes.Vendor.AQARA_PAIRING_MODE]
|
||||||
|
|
||||||
|
# Initial state is that the switch is off
|
||||||
|
switch_1 = await helper.poll_and_get_state()
|
||||||
|
assert switch_1.state == "off"
|
||||||
|
|
||||||
|
# Simulate that someone switched on the device in the real world not via HA
|
||||||
|
pairing_mode.set_value(True)
|
||||||
|
switch_1 = await helper.poll_and_get_state()
|
||||||
|
assert switch_1.state == "on"
|
||||||
|
|
||||||
|
# Simulate that device switched off in the real world not via HA
|
||||||
|
pairing_mode.set_value(False)
|
||||||
|
switch_1 = await helper.poll_and_get_state()
|
||||||
|
assert switch_1.state == "off"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user