Skip to content

Refactor how entities are created for homekit_controller services#43242

Merged
Jc2k merged 1 commit intohome-assistant:devfrom
Jc2k:homekit_controller_refactor
Nov 16, 2020
Merged

Refactor how entities are created for homekit_controller services#43242
Jc2k merged 1 commit intohome-assistant:devfrom
Jc2k:homekit_controller_refactor

Conversation

@Jc2k
Copy link
Copy Markdown
Member

@Jc2k Jc2k commented Nov 14, 2020

Proposed change

#42676 and #43100 highlighted something i've been thinking about for a while. The way HomeKit services are enumerated and turned into entities is currently not only too limiting but also awkward because you have to directly parse the JSON data from HomeKit.

This PR allows the functions that create entities to instead operate on the aiohomekit entity map abstraction which is already used in the entity implementations themselves.

It turns something like this:

    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):

        if len(iid) == 36:
            type_uuid = iid
        else:
            try:
                type_name = CharacteristicsTypes[iid]
                type_uuid = CharacteristicsTypes.get_uuid(type_name)
            except KeyError:
                return None

        for char in serv.get("characteristics"):
            if char.get("type") == type_uuid:
                return char
        return None

    @callback
    def async_add_service(aid, service):
        if service["stype"] != "humidifier-dehumidifier":
            return False
        info = {"aid": aid, "iid": service["iid"]}

        acc = get_accessory(conn, aid)
        serv = get_service(acc, service["iid"])


        if (
            get_char(serv, CharacteristicsTypes.Vendor.VOCOLINC_HUMIDIFIER_SPRAY_LEVEL)
            is not None
        ):
            async_add_entities([VocolincFlowerbud(conn, info)], True)
        else:
            if (
                get_char(
                    serv, CharacteristicsTypes.RELATIVE_HUMIDITY_HUMIDIFIER_THRESHOLD
                )
                is not None
            ):
                async_add_entities([HomeKitHumidifier(conn, info)], True)

            if (
                get_char(
                    serv, CharacteristicsTypes.RELATIVE_HUMIDITY_DEHUMIDIFIER_THRESHOLD
                )
                is not None
            ):
                async_add_entities([HomeKitDehumidifier(conn, info)], True)

        return True

Into:

    @callback
    def async_add_service(service):
        if service.short_type != ServicesTypes.HUMIDIFIER_DEHUMIDIFIER:
            return False

        info = {"aid": service.accessory.aid, "iid": service.iid}
        entities = []

        if service.has(CharacteristicsTypes.Vendor.VOCOLINC_HUMIDIFIER_SPRAY_LEVEL):
            entities.append(VocolincFlowerbud(conn, info))
        else:
            if services.has(RELATIVE_HUMIDITY_HUMIDIFIER_THRESHOLD):
                entities.append(HomeKitHumidifier(conn, info))
            if services.has(RELATIVE_HUMIDITY_DEHUMIDIFIER_THRESHOLD):
                entities.append(HomeKitDehumidifier(conn, info))

        async_add_entities([entities], True)
        return True

It also means we can use the aiohomekit constants for service types.

No new tests - but this bit of code is already exercised quite well by the existing ones.

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New integration (thank you!)
  • New feature (which adds functionality to an existing integration)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Example entry for configuration.yaml:

N/A

Additional information

Checklist

  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • The code has been formatted using Black (black --fast homeassistant tests)
  • Tests have been added to verify that the new code works.

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • The manifest file has all fields filled out correctly.
    Updated and included derived files by running: python3 -m script.hassfest.
  • New or updated dependencies have been added to requirements_all.txt.
    Updated by running python3 -m script.gen_requirements_all.
  • Untested files have been added to .coveragerc.

The integration reached or maintains the following Integration Quality Scale:

  • No score or internal
  • 🥈 Silver
  • 🥇 Gold
  • 🏆 Platinum

To help with the load of incoming pull requests:

@Jc2k Jc2k changed the title Refactor how entities are created for services Refactor how entities are created for homekit_controller services Nov 14, 2020
@Jc2k Jc2k mentioned this pull request Nov 14, 2020
21 tasks
Copy link
Copy Markdown
Contributor

@davet2001 davet2001 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me. Code quality seems fine and new appears to replicate functionality of old. I tried the tests locally and they seem fine.
I don't fully understand this integration, but this does look to be an improvement, replacing dict/string lookups with constants.

The only suggestion I could make is perhaps to add some type hints to the function definitions, but no reason that couldn't be a separate PR.

@Jc2k
Copy link
Copy Markdown
Member Author

Jc2k commented Nov 16, 2020

Cheers for the review! I have a few more rounds of clean up planned for this part of the code so i'll keep your type hint suggestion in mind!

@Jc2k Jc2k merged commit 3e1f2a5 into home-assistant:dev Nov 16, 2020
@Jc2k Jc2k deleted the homekit_controller_refactor branch November 16, 2020 23:11
KJonline pushed a commit to Pyhass/core that referenced this pull request Nov 17, 2020
* 'dev' of https://github.com/home-assistant/core: (77 commits)
  Fix kodi media_player unavailable at start (home-assistant#41714)
  Add an option to template delay_on/off in template binary sensor (home-assistant#43259)
  Bump hatasmota to 0.0.31 (home-assistant#43319)
  Update cloud integration to 0.38.0 (home-assistant#43314)
  Add progress translation key to hassfest (home-assistant#43311)
  Bump codecov/codecov-action from v1.0.14 to v1.0.15 (home-assistant#43304)
  Improvement to allow parsing of station ID in vasttrafik integration. Addresses home-assistant#34851 (home-assistant#43136)
  Abort vizio discovery flow without unique ID (home-assistant#43303)
  Update directv to 0.4.0 (home-assistant#43302)
  Add notification binary_sensor to Plugwise integration (home-assistant#41473)
  [ci skip] Translation update
  Bump bimmer_connected to 0.7.13 (home-assistant#43294)
  Bump aioguardian to 1.0.4 (home-assistant#43299)
  Refactor how entities are created for homekit_controller services (home-assistant#43242)
  Updated frontend to 20201111.1 (home-assistant#43298)
  Update pytradfri to 7.0.4 (home-assistant#43297)
  Remove pts adjustments in stream (home-assistant#42399)
  Fix Enigma2 available entity property (home-assistant#43292)
  Make MQTT climate return PRESET_NONE when no preset is set (home-assistant#43257)
  Bump env_canada to 0.2.4, fix config validation (home-assistant#43251)
  ...
@github-actions github-actions bot locked and limited conversation to collaborators Nov 18, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants