Refactor how entities are created for homekit_controller services (#43242)

This commit is contained in:
Jc2k 2020-11-16 23:11:39 +00:00 committed by GitHub
parent d11d1343a8
commit 3e1f2a5103
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 94 additions and 116 deletions

View file

@ -1,5 +1,6 @@
"""Support for HomeKit Controller air quality sensors.""" """Support for HomeKit Controller air quality sensors."""
from aiohomekit.model.characteristics import CharacteristicsTypes from aiohomekit.model.characteristics import CharacteristicsTypes
from aiohomekit.model.services import ServicesTypes
from homeassistant.components.air_quality import AirQualityEntity from homeassistant.components.air_quality import AirQualityEntity
from homeassistant.core import callback from homeassistant.core import callback
@ -85,10 +86,10 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
conn = hass.data[KNOWN_DEVICES][hkid] conn = hass.data[KNOWN_DEVICES][hkid]
@callback @callback
def async_add_service(aid, service): def async_add_service(service):
if service["stype"] != "air-quality": if service.short_type != ServicesTypes.AIR_QUALITY_SENSOR:
return False return False
info = {"aid": aid, "iid": service["iid"]} info = {"aid": service.accessory.aid, "iid": service.iid}
async_add_entities([HomeAirQualitySensor(conn, info)], True) async_add_entities([HomeAirQualitySensor(conn, info)], True)
return True return True

View file

@ -1,5 +1,6 @@
"""Support for Homekit Alarm Control Panel.""" """Support for Homekit Alarm Control Panel."""
from aiohomekit.model.characteristics import CharacteristicsTypes from aiohomekit.model.characteristics import CharacteristicsTypes
from aiohomekit.model.services import ServicesTypes
from homeassistant.components.alarm_control_panel import AlarmControlPanelEntity from homeassistant.components.alarm_control_panel import AlarmControlPanelEntity
from homeassistant.components.alarm_control_panel.const import ( from homeassistant.components.alarm_control_panel.const import (
@ -43,10 +44,10 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
conn = hass.data[KNOWN_DEVICES][hkid] conn = hass.data[KNOWN_DEVICES][hkid]
@callback @callback
def async_add_service(aid, service): def async_add_service(service):
if service["stype"] != "security-system": if service.short_type != ServicesTypes.SECURITY_SYSTEM:
return False return False
info = {"aid": aid, "iid": service["iid"]} info = {"aid": service.accessory.aid, "iid": service.iid}
async_add_entities([HomeKitAlarmControlPanelEntity(conn, info)], True) async_add_entities([HomeKitAlarmControlPanelEntity(conn, info)], True)
return True return True

View file

@ -1,5 +1,6 @@
"""Support for Homekit motion sensors.""" """Support for Homekit motion sensors."""
from aiohomekit.model.characteristics import CharacteristicsTypes from aiohomekit.model.characteristics import CharacteristicsTypes
from aiohomekit.model.services import ServicesTypes
from homeassistant.components.binary_sensor import ( from homeassistant.components.binary_sensor import (
DEVICE_CLASS_GAS, DEVICE_CLASS_GAS,
@ -124,12 +125,12 @@ class HomeKitLeakSensor(HomeKitEntity, BinarySensorEntity):
ENTITY_TYPES = { ENTITY_TYPES = {
"motion": HomeKitMotionSensor, ServicesTypes.MOTION_SENSOR: HomeKitMotionSensor,
"contact": HomeKitContactSensor, ServicesTypes.CONTACT_SENSOR: HomeKitContactSensor,
"smoke": HomeKitSmokeSensor, ServicesTypes.SMOKE_SENSOR: HomeKitSmokeSensor,
"carbon-monoxide": HomeKitCarbonMonoxideSensor, ServicesTypes.CARBON_MONOXIDE_SENSOR: HomeKitCarbonMonoxideSensor,
"occupancy": HomeKitOccupancySensor, ServicesTypes.OCCUPANCY_SENSOR: HomeKitOccupancySensor,
"leak": HomeKitLeakSensor, ServicesTypes.LEAK_SENSOR: HomeKitLeakSensor,
} }
@ -139,11 +140,11 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
conn = hass.data[KNOWN_DEVICES][hkid] conn = hass.data[KNOWN_DEVICES][hkid]
@callback @callback
def async_add_service(aid, service): def async_add_service(service):
entity_class = ENTITY_TYPES.get(service["stype"]) entity_class = ENTITY_TYPES.get(service.short_type)
if not entity_class: if not entity_class:
return False return False
info = {"aid": aid, "iid": service["iid"]} info = {"aid": service.accessory.aid, "iid": service.iid}
async_add_entities([entity_class(conn, info)], True) async_add_entities([entity_class(conn, info)], True)
return True return True

View file

@ -10,6 +10,7 @@ from aiohomekit.model.characteristics import (
SwingModeValues, SwingModeValues,
TargetHeaterCoolerStateValues, TargetHeaterCoolerStateValues,
) )
from aiohomekit.model.services import ServicesTypes
from aiohomekit.utils import clamp_enum_to_char from aiohomekit.utils import clamp_enum_to_char
from homeassistant.components.climate import ( from homeassistant.components.climate import (
@ -87,11 +88,11 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
conn = hass.data[KNOWN_DEVICES][hkid] conn = hass.data[KNOWN_DEVICES][hkid]
@callback @callback
def async_add_service(aid, service): def async_add_service(service):
entity_class = ENTITY_TYPES.get(service["stype"]) entity_class = ENTITY_TYPES.get(service.short_type)
if not entity_class: if not entity_class:
return False return False
info = {"aid": aid, "iid": service["iid"]} info = {"aid": service.accessory.aid, "iid": service.iid}
async_add_entities([entity_class(conn, info)], True) async_add_entities([entity_class(conn, info)], True)
return True return True
@ -454,6 +455,6 @@ class HomeKitClimateEntity(HomeKitEntity, ClimateEntity):
ENTITY_TYPES = { ENTITY_TYPES = {
"heater-cooler": HomeKitHeaterCoolerEntity, ServicesTypes.HEATER_COOLER: HomeKitHeaterCoolerEntity,
"thermostat": HomeKitClimateEntity, ServicesTypes.THERMOSTAT: HomeKitClimateEntity,
} }

View file

@ -317,19 +317,17 @@ class HKDevice:
self._add_new_entities_for_accessory(self.accessory_factories) self._add_new_entities_for_accessory(self.accessory_factories)
def _add_new_entities(self, callbacks): def _add_new_entities(self, callbacks):
for accessory in self.accessories: for accessory in self.entity_map.accessories:
aid = accessory["aid"] aid = accessory.aid
for service in accessory["services"]: for service in accessory.services:
iid = service["iid"] iid = service.iid
stype = ServicesTypes.get_short(service["type"].upper())
service["stype"] = stype
if (aid, iid) in self.entities: if (aid, iid) in self.entities:
# Don't add the same entity again # Don't add the same entity again
continue continue
for listener in callbacks: for listener in callbacks:
if listener(aid, service): if listener(service):
self.entities.append((aid, iid)) self.entities.append((aid, iid))
break break

View file

@ -1,5 +1,6 @@
"""Support for Homekit covers.""" """Support for Homekit covers."""
from aiohomekit.model.characteristics import CharacteristicsTypes from aiohomekit.model.characteristics import CharacteristicsTypes
from aiohomekit.model.services import ServicesTypes
from homeassistant.components.cover import ( from homeassistant.components.cover import (
ATTR_POSITION, ATTR_POSITION,
@ -39,17 +40,13 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
conn = hass.data[KNOWN_DEVICES][hkid] conn = hass.data[KNOWN_DEVICES][hkid]
@callback @callback
def async_add_service(aid, service): def async_add_service(service):
info = {"aid": aid, "iid": service["iid"]} entity_class = ENTITY_TYPES.get(service.short_type)
if service["stype"] == "garage-door-opener": if not entity_class:
async_add_entities([HomeKitGarageDoorCover(conn, info)], True)
return True
if service["stype"] in ("window-covering", "window"):
async_add_entities([HomeKitWindowCover(conn, info)], True)
return True
return False return False
info = {"aid": service.accessory.aid, "iid": service.iid}
async_add_entities([entity_class(conn, info)], True)
return True
conn.add_listener(async_add_service) conn.add_listener(async_add_service)
@ -246,3 +243,9 @@ class HomeKitWindowCover(HomeKitEntity, CoverEntity):
if not obstruction_detected: if not obstruction_detected:
return {} return {}
return {"obstruction-detected": obstruction_detected} return {"obstruction-detected": obstruction_detected}
ENTITY_TYPES = {
ServicesTypes.GARAGE_DOOR_OPENER: HomeKitGarageDoorCover,
ServicesTypes.WINDOW_COVERING: HomeKitWindowCover,
}

View file

@ -174,9 +174,9 @@ def enumerate_doorbell(service):
TRIGGER_FINDERS = { TRIGGER_FINDERS = {
"service-label": enumerate_stateless_switch_group, ServicesTypes.SERVICE_LABEL: enumerate_stateless_switch_group,
"stateless-programmable-switch": enumerate_stateless_switch, ServicesTypes.STATELESS_PROGRAMMABLE_SWITCH: enumerate_stateless_switch,
"doorbell": enumerate_doorbell, ServicesTypes.DOORBELL: enumerate_doorbell,
} }
@ -186,8 +186,9 @@ async def async_setup_triggers_for_entry(hass: HomeAssistant, config_entry):
conn = hass.data[KNOWN_DEVICES][hkid] conn = hass.data[KNOWN_DEVICES][hkid]
@callback @callback
def async_add_service(aid, service_dict): def async_add_service(service):
service_type = service_dict["stype"] aid = service.accessory.aid
service_type = service.short_type
# If not a known service type then we can't handle any stateless events for it # If not a known service type then we can't handle any stateless events for it
if service_type not in TRIGGER_FINDERS: if service_type not in TRIGGER_FINDERS:
@ -201,11 +202,6 @@ async def async_setup_triggers_for_entry(hass: HomeAssistant, config_entry):
if device_id in hass.data[TRIGGERS]: if device_id in hass.data[TRIGGERS]:
return False return False
# At the moment add_listener calls us with the raw service dict, rather than
# a service model. So turn it into a service ourselves.
accessory = conn.entity_map.aid(aid)
service = accessory.services.iid(service_dict["iid"])
# Just because we recognise the service type doesn't mean we can actually # Just because we recognise the service type doesn't mean we can actually
# extract any triggers - so only proceed if we can # extract any triggers - so only proceed if we can
triggers = TRIGGER_FINDERS[service_type](service) triggers = TRIGGER_FINDERS[service_type](service)

View file

@ -1,5 +1,6 @@
"""Support for Homekit fans.""" """Support for Homekit fans."""
from aiohomekit.model.characteristics import CharacteristicsTypes from aiohomekit.model.characteristics import CharacteristicsTypes
from aiohomekit.model.services import ServicesTypes
from homeassistant.components.fan import ( from homeassistant.components.fan import (
DIRECTION_FORWARD, DIRECTION_FORWARD,
@ -161,8 +162,8 @@ class HomeKitFanV2(BaseHomeKitFan):
ENTITY_TYPES = { ENTITY_TYPES = {
"fan": HomeKitFanV1, ServicesTypes.FAN: HomeKitFanV1,
"fanv2": HomeKitFanV2, ServicesTypes.FAN_V2: HomeKitFanV2,
} }
@ -172,11 +173,11 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
conn = hass.data[KNOWN_DEVICES][hkid] conn = hass.data[KNOWN_DEVICES][hkid]
@callback @callback
def async_add_service(aid, service): def async_add_service(service):
entity_class = ENTITY_TYPES.get(service["stype"]) entity_class = ENTITY_TYPES.get(service.short_type)
if not entity_class: if not entity_class:
return False return False
info = {"aid": aid, "iid": service["iid"]} info = {"aid": service.accessory.aid, "iid": service.iid}
async_add_entities([entity_class(conn, info)], True) async_add_entities([entity_class(conn, info)], True)
return True return True

View file

@ -2,6 +2,7 @@
from typing import List, Optional from typing import List, Optional
from aiohomekit.model.characteristics import CharacteristicsTypes from aiohomekit.model.characteristics import CharacteristicsTypes
from aiohomekit.model.services import ServicesTypes
from homeassistant.components.humidifier import HumidifierEntity from homeassistant.components.humidifier import HumidifierEntity
from homeassistant.components.humidifier.const import ( from homeassistant.components.humidifier.const import (
@ -253,51 +254,22 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
hkid = config_entry.data["AccessoryPairingID"] hkid = config_entry.data["AccessoryPairingID"]
conn = hass.data[KNOWN_DEVICES][hkid] conn = hass.data[KNOWN_DEVICES][hkid]
def get_accessory(conn, aid):
for acc in conn.accessories:
if acc.get("aid") == aid:
return acc
return None
def get_service(acc, iid):
for serv in acc.get("services"):
if serv.get("iid") == iid:
return serv
return None
def get_char(serv, iid):
try:
type_name = CharacteristicsTypes[iid]
type_uuid = CharacteristicsTypes.get_uuid(type_name)
for char in serv.get("characteristics"):
if char.get("type") == type_uuid:
return char
except KeyError:
return None
return None
@callback @callback
def async_add_service(aid, service): def async_add_service(service):
if service["stype"] != "humidifier-dehumidifier": if service.short_type != ServicesTypes.HUMIDIFIER_DEHUMIDIFIER:
return False return False
info = {"aid": aid, "iid": service["iid"]}
acc = get_accessory(conn, aid) info = {"aid": service.accessory.aid, "iid": service.iid}
serv = get_service(acc, service["iid"])
if ( entities = []
get_char(serv, CharacteristicsTypes.RELATIVE_HUMIDITY_HUMIDIFIER_THRESHOLD)
is not None
):
async_add_entities([HomeKitHumidifier(conn, info)], True)
if ( if service.has(CharacteristicsTypes.RELATIVE_HUMIDITY_HUMIDIFIER_THRESHOLD):
get_char( entities.append(HomeKitHumidifier(conn, info))
serv, CharacteristicsTypes.RELATIVE_HUMIDITY_DEHUMIDIFIER_THRESHOLD
) if service.has(CharacteristicsTypes.RELATIVE_HUMIDITY_DEHUMIDIFIER_THRESHOLD):
is not None entities.append(HomeKitDehumidifier(conn, info))
):
async_add_entities([HomeKitDehumidifier(conn, info)], True) async_add_entities(entities, True)
return True return True

View file

@ -1,5 +1,6 @@
"""Support for Homekit lights.""" """Support for Homekit lights."""
from aiohomekit.model.characteristics import CharacteristicsTypes from aiohomekit.model.characteristics import CharacteristicsTypes
from aiohomekit.model.services import ServicesTypes
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_BRIGHTNESS,
@ -21,10 +22,10 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
conn = hass.data[KNOWN_DEVICES][hkid] conn = hass.data[KNOWN_DEVICES][hkid]
@callback @callback
def async_add_service(aid, service): def async_add_service(service):
if service["stype"] != "lightbulb": if service.short_type != ServicesTypes.LIGHTBULB:
return False return False
info = {"aid": aid, "iid": service["iid"]} info = {"aid": service.accessory.aid, "iid": service.iid}
async_add_entities([HomeKitLight(conn, info)], True) async_add_entities([HomeKitLight(conn, info)], True)
return True return True

View file

@ -1,5 +1,6 @@
"""Support for HomeKit Controller locks.""" """Support for HomeKit Controller locks."""
from aiohomekit.model.characteristics import CharacteristicsTypes from aiohomekit.model.characteristics import CharacteristicsTypes
from aiohomekit.model.services import ServicesTypes
from homeassistant.components.lock import LockEntity from homeassistant.components.lock import LockEntity
from homeassistant.const import ATTR_BATTERY_LEVEL, STATE_LOCKED, STATE_UNLOCKED from homeassistant.const import ATTR_BATTERY_LEVEL, STATE_LOCKED, STATE_UNLOCKED
@ -20,10 +21,10 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
conn = hass.data[KNOWN_DEVICES][hkid] conn = hass.data[KNOWN_DEVICES][hkid]
@callback @callback
def async_add_service(aid, service): def async_add_service(service):
if service["stype"] != "lock-mechanism": if service.short_type != ServicesTypes.LOCK_MECHANISM:
return False return False
info = {"aid": aid, "iid": service["iid"]} info = {"aid": service.accessory.aid, "iid": service.iid}
async_add_entities([HomeKitLock(conn, info)], True) async_add_entities([HomeKitLock(conn, info)], True)
return True return True

View file

@ -44,10 +44,10 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
conn = hass.data[KNOWN_DEVICES][hkid] conn = hass.data[KNOWN_DEVICES][hkid]
@callback @callback
def async_add_service(aid, service): def async_add_service(service):
if service["stype"] != "television": if service.short_type != ServicesTypes.TELEVISION:
return False return False
info = {"aid": aid, "iid": service["iid"]} info = {"aid": service.accessory.aid, "iid": service.iid}
async_add_entities([HomeKitTelevision(conn, info)], True) async_add_entities([HomeKitTelevision(conn, info)], True)
return True return True

View file

@ -1,5 +1,6 @@
"""Support for Homekit sensors.""" """Support for Homekit sensors."""
from aiohomekit.model.characteristics import CharacteristicsTypes from aiohomekit.model.characteristics import CharacteristicsTypes
from aiohomekit.model.services import ServicesTypes
from homeassistant.const import ( from homeassistant.const import (
CONCENTRATION_PARTS_PER_MILLION, CONCENTRATION_PARTS_PER_MILLION,
@ -216,11 +217,11 @@ class HomeKitBatterySensor(HomeKitEntity):
ENTITY_TYPES = { ENTITY_TYPES = {
"humidity": HomeKitHumiditySensor, ServicesTypes.HUMIDITY_SENSOR: HomeKitHumiditySensor,
"temperature": HomeKitTemperatureSensor, ServicesTypes.TEMPERATURE_SENSOR: HomeKitTemperatureSensor,
"light": HomeKitLightSensor, ServicesTypes.LIGHT_SENSOR: HomeKitLightSensor,
"carbon-dioxide": HomeKitCarbonDioxideSensor, ServicesTypes.CARBON_DIOXIDE_SENSOR: HomeKitCarbonDioxideSensor,
"battery": HomeKitBatterySensor, ServicesTypes.BATTERY_SERVICE: HomeKitBatterySensor,
} }
@ -230,11 +231,11 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
conn = hass.data[KNOWN_DEVICES][hkid] conn = hass.data[KNOWN_DEVICES][hkid]
@callback @callback
def async_add_service(aid, service): def async_add_service(service):
entity_class = ENTITY_TYPES.get(service["stype"]) entity_class = ENTITY_TYPES.get(service.short_type)
if not entity_class: if not entity_class:
return False return False
info = {"aid": aid, "iid": service["iid"]} info = {"aid": service.accessory.aid, "iid": service.iid}
async_add_entities([entity_class(conn, info)], True) async_add_entities([entity_class(conn, info)], True)
return True return True

View file

@ -4,6 +4,7 @@ from aiohomekit.model.characteristics import (
InUseValues, InUseValues,
IsConfiguredValues, IsConfiguredValues,
) )
from aiohomekit.model.services import ServicesTypes
from homeassistant.components.switch import SwitchEntity from homeassistant.components.switch import SwitchEntity
from homeassistant.core import callback from homeassistant.core import callback
@ -96,9 +97,9 @@ class HomeKitValve(HomeKitEntity, SwitchEntity):
ENTITY_TYPES = { ENTITY_TYPES = {
"switch": HomeKitSwitch, ServicesTypes.SWITCH: HomeKitSwitch,
"outlet": HomeKitSwitch, ServicesTypes.OUTLET: HomeKitSwitch,
"valve": HomeKitValve, ServicesTypes.VALVE: HomeKitValve,
} }
@ -108,11 +109,11 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
conn = hass.data[KNOWN_DEVICES][hkid] conn = hass.data[KNOWN_DEVICES][hkid]
@callback @callback
def async_add_service(aid, service): def async_add_service(service):
entity_class = ENTITY_TYPES.get(service["stype"]) entity_class = ENTITY_TYPES.get(service.short_type)
if not entity_class: if not entity_class:
return False return False
info = {"aid": aid, "iid": service["iid"]} info = {"aid": service.accessory.aid, "iid": service.iid}
async_add_entities([entity_class(conn, info)], True) async_add_entities([entity_class(conn, info)], True)
return True return True