-
-
Notifications
You must be signed in to change notification settings - Fork 30.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add HomeKit support for fans #14351
Add HomeKit support for fans #14351
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR is already looking quite good. I didn't had time to test it yet, but nevertheless added a few small comments.
def __init__(self, *args, config): | ||
"""Initialize a new Light accessory object.""" | ||
super().__init__(*args, category=CATEGORY_FAN) | ||
self._domain = split_entity_id(self.entity_id)[0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is their a reason you use split_entity_id
instead of DOMAIN
imported from components.fan
?
As I see it, it should be enough to use the later one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No reason, just copied the base code from type_switches
. I agree though, I've updated to import from components.fan
CHAR_ACTIVE, value=self._state, setter_callback=self.set_state) | ||
|
||
if CHAR_ROTATION_SPEED in self.chars: | ||
speed_list = self.hass.states.get(self.entity_id) \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this change over time? At the moment no homekit type accounts for chnages in supported features, so I think changing this to self.speed_list
would work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, you're correct in that it doesn't change after being initialized at startup.
.attributes.get(ATTR_SPEED_LIST) | ||
speed = speed_list[int(round(value / self.min_step)) - 1] | ||
self.hass.components.fan.turn_on( | ||
self.entity_id, speed=speed) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you use hass.services.call
instead. Also for the ones below.
I just haven't gotten around to harmonize that for the other types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No problem, I can help with updating the other types accordingly too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to do that now. I'm planing to start converting the first methods to async, maybe as soon as this weekend. I can do it then.
That in mind it would be great if we could finish up on #14159 first. As a heads up: I'm rewriting almost all tests at the moment to use pytest
and async
. Should get the PR out in the next few hours. It might require a rebase then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good.
I'll get #14159 wrapped up tonight so that can be closed out.
Regarding tests for this PR, should I wait for your new PR, then rebase and add/update for fans?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just opened the PR #14377
The foundations stayed the same. It might be best if you take a look at one of the new type tests
and write the new tests based on that structure. They should work even without the PR being merged.
However, it is likely that #14159 needs to be rebased once the PR is merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Understood, I'll look at the new tests tonight and update this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just merged the test PR, should be good to rebase now.
"""Set state if call came from HomeKit.""" | ||
_LOGGER.debug('%s: Set direction to %d', self.entity_id, value) | ||
self._flag[CHAR_ROTATION_DIRECTION] = True | ||
direction = HOMEKIT_TO_HASS[value] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use if
instead? Dictionary mapping is a bit much for just to values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No problem, updated.
.attributes.get(ATTR_SUPPORTED_FEATURES) | ||
if self._features & SUPPORT_SET_SPEED: | ||
self.chars.append(CHAR_ROTATION_SPEED) | ||
self._speed = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What reason is their to define it as class variable? As I see it, it's only used in update_state
. Same for self._direction
and self._oscillating
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I just copied the base code from type_lights
. It's not needed so I removed.
direction = new_state.attributes.get(ATTR_DIRECTION) | ||
if not self._flag[CHAR_ROTATION_DIRECTION] and \ | ||
direction in HASS_TO_HOMEKIT: | ||
self._direction = HASS_TO_HOMEKIT[direction] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as before. I think if
is more than enough here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No problem, updated.
acc.char_direction.client_update_value(1) | ||
self.hass.block_till_done() | ||
self.assertEqual(self.events[1].data[ATTR_DOMAIN], DOMAIN) | ||
self.assertEqual(self.events[1].data[ATTR_SERVICE], SERVICE_SET_DIRECTION) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
line too long (82 > 79 characters)
acc.char_direction.client_update_value(0) | ||
self.hass.block_till_done() | ||
self.assertEqual(self.events[0].data[ATTR_DOMAIN], DOMAIN) | ||
self.assertEqual(self.events[0].data[ATTR_SERVICE], SERVICE_SET_DIRECTION) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
line too long (82 > 79 characters)
import unittest | ||
|
||
from homeassistant.core import callback | ||
from homeassistant.components.fan import ( |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
566d839
to
81aa101
Compare
if CHAR_ROTATION_DIRECTION in self.chars: | ||
direction = new_state.attributes.get(ATTR_DIRECTION) | ||
if not self._flag[CHAR_ROTATION_DIRECTION] and \ | ||
direction in (DIRECTION_FORWARD, DIRECTION_REVERSE): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This currently doesn't work if set from the frontend. See home-assistant/frontend#1158
014e350
to
14197ad
Compare
@cdce8p I tested the latest commit, all good here. I also updated description to explain lack of speed support. PR for docs is updated as well. Ready to merge. |
Description:
Adds support for fans in HomeKit. In addition to basic on/off it uses
supported_features
to add additional characteristics fordirection
andoscillation
(in HomeKit,oscillation
=swing_mode
).Support for
speed
is not being implemented yet due to the current architecture ofspeed_list
. Refer to home-assistant/architecture#27 for more details. Once an improved architecture forspeed_list
is set and entities updated, HomeKit will be updated to supportspeed
.Related issue (if applicable): N/A
Pull request in home-assistant.github.io with documentation (if applicable): home-assistant/home-assistant.io#5346
Example entry for
configuration.yaml
(if applicable):Checklist:
tox
. Your PR cannot be merged unless tests passIf user exposed functionality or configuration variables are added/changed:
If the code communicates with devices, web services, or third-party tools:
REQUIREMENTS
variable (example).requirements_all.txt
by runningscript/gen_requirements_all.py
..coveragerc
.If the code does not interact with devices: