Esempio n. 1
0
    async def list_accessories_and_characteristics(self):
        """
        This retrieves a current set of accessories and characteristics behind this pairing.

        :return: the accessory data as described in the spec on page 73 and following
        :raises AccessoryNotFoundError: if the device can not be found via zeroconf
        """
        await self._ensure_connected()

        response = await self.connection.get_json("/accessories")

        accessories = response["accessories"]

        for accessory in accessories:
            for service in accessory["services"]:
                service["type"] = service["type"].upper()
                try:
                    service["type"] = ServicesTypes.get_uuid(service["type"])
                except KeyError:
                    pass

                for characteristic in service["characteristics"]:
                    characteristic["type"] = characteristic["type"].upper()
                    try:
                        characteristic["type"] = CharacteristicsTypes.get_uuid(
                            characteristic["type"])
                    except KeyError:
                        pass

        self.pairing_data["accessories"] = accessories
        return accessories
Esempio n. 2
0
async def setup_test_component(hass,
                               setup_accessory,
                               capitalize=False,
                               suffix=None):
    """Load a fake homekit accessory based on a homekit accessory model.

    If capitalize is True, property names will be in upper case.

    If suffix is set, entityId will include the suffix
    """
    accessory = Accessory.create_with_info("TestDevice", "example.com", "Test",
                                           "0001", "0.1")
    setup_accessory(accessory)

    domain = None
    for service in accessory.services:
        service_name = ServicesTypes.get_short(service.type)
        if service_name in HOMEKIT_ACCESSORY_DISPATCH:
            domain = HOMEKIT_ACCESSORY_DISPATCH[service_name]
            break

    assert domain, "Cannot map test homekit services to Home Assistant domain"

    config_entry, pairing = await setup_test_accessories(hass, [accessory])
    entity = "testdevice" if suffix is None else f"testdevice_{suffix}"
    return Helper(hass, ".".join((domain, entity)), pairing, accessory,
                  config_entry)
Esempio n. 3
0
def get_accessory_information(accessory):
    """Obtain the accessory information service of a HomeKit device."""
    result = {}
    for service in accessory["services"]:
        stype = service["type"].upper()
        if ServicesTypes.get_short(stype) != "accessory-information":
            continue
        for characteristic in service["characteristics"]:
            ctype = CharacteristicsTypes.get_short(characteristic["type"])
            if "value" in characteristic:
                result[ctype] = characteristic["value"]
    return result
Esempio n. 4
0
    async def async_load_platforms(self):
        """Load any platforms needed by this HomeKit device."""
        for accessory in self.accessories:
            for service in accessory["services"]:
                stype = ServicesTypes.get_short(service["type"].upper())
                if stype in HOMEKIT_ACCESSORY_DISPATCH:
                    platform = HOMEKIT_ACCESSORY_DISPATCH[stype]
                    await self.async_load_platform(platform)

                for char in service["characteristics"]:
                    if char["type"].upper() in CHARACTERISTIC_PLATFORMS:
                        platform = CHARACTERISTIC_PLATFORMS[
                            char["type"].upper()]
                        await self.async_load_platform(platform)
Esempio n. 5
0
    def __init__(self, hass, entity_id, pairing, accessory, config_entry):
        """Create a helper for a given accessory/entity."""
        self.hass = hass
        self.entity_id = entity_id
        self.pairing = pairing
        self.accessory = accessory
        self.config_entry = config_entry

        self.characteristics = {}
        for service in self.accessory.services:
            service_name = ServicesTypes.get_short(service.type)
            for char in service.characteristics:
                char_name = CharacteristicsTypes.get_short(char.type)
                self.characteristics[(service_name, char_name)] = char
Esempio n. 6
0
    def _add_new_entities(self, callbacks):
        for accessory in self.accessories:
            aid = accessory["aid"]
            for service in accessory["services"]:
                iid = service["iid"]
                stype = ServicesTypes.get_short(service["type"].upper())
                service["stype"] = stype

                if (aid, iid) in self.entities:
                    # Don't add the same entity again
                    continue

                for listener in callbacks:
                    if listener(aid, service):
                        self.entities.append((aid, iid))
                        break
Esempio n. 7
0
    async def async_load_platforms(self):
        """Load any platforms needed by this HomeKit device."""
        for accessory in self.accessories:
            for service in accessory["services"]:
                stype = ServicesTypes.get_short(service["type"].upper())
                if stype not in HOMEKIT_ACCESSORY_DISPATCH:
                    continue

                platform = HOMEKIT_ACCESSORY_DISPATCH[stype]
                if platform in self.platforms:
                    continue

                self.platforms.add(platform)
                try:
                    await self.hass.config_entries.async_forward_entry_setup(
                        self.config_entry, platform)
                except Exception:
                    self.platforms.remove(platform)
                    raise
Esempio n. 8
0
    },
    CharacteristicsTypes.Vendor.EVE_DEGREE_AIR_PRESSURE: {
        "name": "Air Pressure",
        "device_class": DEVICE_CLASS_PRESSURE,
        "state_class": STATE_CLASS_MEASUREMENT,
        "unit": PRESSURE_HPA,
    },
    CharacteristicsTypes.get_uuid(CharacteristicsTypes.TEMPERATURE_CURRENT): {
        "name": "Current Temperature",
        "device_class": DEVICE_CLASS_TEMPERATURE,
        "state_class": STATE_CLASS_MEASUREMENT,
        "unit": TEMP_CELSIUS,
        # This sensor is only for temperature characteristics that are not part
        # of a temperature sensor service.
        "probe": lambda char: char.service.type
        != ServicesTypes.get_uuid(ServicesTypes.TEMPERATURE_SENSOR),
    },
    CharacteristicsTypes.get_uuid(CharacteristicsTypes.RELATIVE_HUMIDITY_CURRENT): {
        "name": "Current Humidity",
        "device_class": DEVICE_CLASS_HUMIDITY,
        "state_class": STATE_CLASS_MEASUREMENT,
        "unit": PERCENTAGE,
        # This sensor is only for humidity characteristics that are not part
        # of a humidity sensor service.
        "probe": lambda char: char.service.type
        != ServicesTypes.get_uuid(ServicesTypes.HUMIDITY_SENSOR),
    },
}


class HomeKitHumiditySensor(HomeKitEntity, SensorEntity):
Esempio n. 9
0
def test_get_short_no_service():
    assert (
        ServicesTypes.get_short("00000023-0000-1000-8000-0026BB765291")
        == "Unknown Service: 00000023-0000-1000-8000-0026BB765291"
    )
Esempio n. 10
0
def test_get_short_no_baseid():
    assert (
        ServicesTypes.get_short("00000023-0000-1000-8000-NOTBASEID")
        == "Unknown Service: 00000023-0000-1000-8000-NOTBASEID"
    )
Esempio n. 11
0
def test_get_uuid():
    assert (
        ServicesTypes.get_uuid("public.hap.service.doorbell")
        == "00000121-0000-1000-8000-0026BB765291"
    )
Esempio n. 12
0
     key=CharacteristicsTypes.Vendor.VOCOLINC_OUTLET_ENERGY,
     name="Power",
     device_class=SensorDeviceClass.POWER,
     state_class=SensorStateClass.MEASUREMENT,
     native_unit_of_measurement=POWER_WATT,
 ),
 CharacteristicsTypes.TEMPERATURE_CURRENT:
 HomeKitSensorEntityDescription(
     key=CharacteristicsTypes.TEMPERATURE_CURRENT,
     name="Current Temperature",
     device_class=SensorDeviceClass.TEMPERATURE,
     state_class=SensorStateClass.MEASUREMENT,
     native_unit_of_measurement=TEMP_CELSIUS,
     # This sensor is only for temperature characteristics that are not part
     # of a temperature sensor service.
     probe=(lambda char: char.service.type != ServicesTypes.get_uuid(
         ServicesTypes.TEMPERATURE_SENSOR)),
 ),
 CharacteristicsTypes.RELATIVE_HUMIDITY_CURRENT:
 HomeKitSensorEntityDescription(
     key=CharacteristicsTypes.RELATIVE_HUMIDITY_CURRENT,
     name="Current Humidity",
     device_class=SensorDeviceClass.HUMIDITY,
     state_class=SensorStateClass.MEASUREMENT,
     native_unit_of_measurement=PERCENTAGE,
     # This sensor is only for humidity characteristics that are not part
     # of a humidity sensor service.
     probe=(lambda char: char.service.type != ServicesTypes.get_uuid(
         ServicesTypes.HUMIDITY_SENSOR)),
 ),
 CharacteristicsTypes.AIR_QUALITY:
 HomeKitSensorEntityDescription(
Esempio n. 13
0
    },
    CharacteristicsTypes.Vendor.KOOGEEK_REALTIME_ENERGY: {
        "name": "Real Time Energy",
        "device_class": DEVICE_CLASS_POWER,
        "state_class": STATE_CLASS_MEASUREMENT,
        "unit": "watts",
    },
    CharacteristicsTypes.get_uuid(CharacteristicsTypes.TEMPERATURE_CURRENT): {
        "name": "Current Temperature",
        "device_class": DEVICE_CLASS_TEMPERATURE,
        "state_class": STATE_CLASS_MEASUREMENT,
        "unit": TEMP_CELSIUS,
        # This sensor is only for temperature characteristics that are not part
        # of a temperature sensor service.
        "probe": lambda char: char.service.type
        != ServicesTypes.get_uuid(ServicesTypes.TEMPERATURE_SENSOR),
    },
}


class HomeKitHumiditySensor(HomeKitEntity, SensorEntity):
    """Representation of a Homekit humidity sensor."""

    _attr_device_class = DEVICE_CLASS_HUMIDITY
    _attr_unit_of_measurement = PERCENTAGE

    def get_characteristic_types(self):
        """Define the homekit characteristics the entity is tracking."""
        return [CharacteristicsTypes.RELATIVE_HUMIDITY_CURRENT]

    @property
Esempio n. 14
0
def test_get_uuid_no_service():
    with pytest.raises(Exception):
        ServicesTypes.get_uuid("public.hap.service.NO_A_SERVICE")
Esempio n. 15
0
def test_get_short_lowercase():
    assert (
        ServicesTypes.get_short("00000086-0000-1000-8000-0026bb765291") == "occupancy"
    )
Esempio n. 16
0
def test_get_short_uuid_from_uuid():
    assert ServicesTypes.get_short_uuid("00000086-0000-1000-8000-0026BB765291") == "86"
Esempio n. 17
0
def test_get_short_uuid_from_name():
    assert ServicesTypes.get_short_uuid("public.hap.service.doorbell") == "121"
Esempio n. 18
0
with open("aiohomekit/model/characteristics/data.py", "w") as fp:
    fp.write(
        textwrap.dedent("""
    # AUTOGENERATED, DO NOT EDIT

    characteristics = 
    """).strip())
    fp.write(" " + json.dumps(characteristics, indent=4))
    fp.write("\n")

from aiohomekit.model.services import ServicesTypes

for serv in data.get('Services', []):
    name = serv['Name'].replace(" ", "_").upper()
    short = ServicesTypes.get_short_uuid(serv['UUID'])
    print(f'{name} = "{short}"')

services = {}

for serv in data.get('Services', []):
    name = serv['Name'].replace(" ", "_").upper()

    s = services[serv['UUID']] = {
        'name': name,
        'description': serv['Name'],
        'required': serv.get("RequiredCharacteristics", []),
        'optional': serv.get("OptionalCharacteristics", []),
    }

with open("aiohomekit/model/services/data.py", "w") as fp:
Esempio n. 19
0
def test_get_short():
    assert (
        ServicesTypes.get_short("00000086-0000-1000-8000-0026BB765291") == "occupancy"
    )