-
-
Notifications
You must be signed in to change notification settings - Fork 32.3k
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
Huge ISY994 platform cleanup, fixes support for 5.0.10 firmware #11243
Changes from 1 commit
172e7c1
df10d7a
742beb2
eacbf10
614b581
519aae9
cc000d5
b9f1812
61db17c
7185a65
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,53 +8,52 @@ | |
from typing import Callable # noqa | ||
|
||
from homeassistant.components.cover import CoverDevice, DOMAIN | ||
import homeassistant.components.isy994 as isy | ||
from homeassistant.const import STATE_OPEN, STATE_CLOSED, STATE_UNKNOWN | ||
from homeassistant.components.isy994 import (ISY994_NODES, ISY994_PROGRAMS, | ||
KEY_STATUS, KEY_ACTIONS, | ||
ISYDevice) | ||
from homeassistant.const import ( | ||
STATE_OPEN, STATE_CLOSED, STATE_OPENING, STATE_CLOSING, STATE_UNKNOWN) | ||
from homeassistant.helpers.typing import ConfigType | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
VALUE_TO_STATE = { | ||
0: STATE_CLOSED, | ||
101: STATE_UNKNOWN, | ||
102: 'stopped', | ||
103: STATE_CLOSING, | ||
104: STATE_OPENING | ||
} | ||
|
||
UOM = ['97'] | ||
STATES = [STATE_OPEN, STATE_CLOSED, 'closing', 'opening', 'stopped'] | ||
|
||
|
||
# pylint: disable=unused-argument | ||
def setup_platform(hass, config: ConfigType, | ||
add_devices: Callable[[list], None], discovery_info=None): | ||
"""Set up the ISY994 cover platform.""" | ||
if isy.ISY is None or not isy.ISY.connected: | ||
_LOGGER.error("A connection has not been made to the ISY controller") | ||
return False | ||
|
||
devices = [] | ||
|
||
for node in isy.filter_nodes(isy.NODES, units=UOM, states=STATES): | ||
for node in hass.data[ISY994_NODES][DOMAIN]: | ||
devices.append(ISYCoverDevice(node)) | ||
|
||
for program in isy.PROGRAMS.get(DOMAIN, []): | ||
for program in hass.data[ISY994_PROGRAMS].get(DOMAIN, []): | ||
try: | ||
status = program[isy.KEY_STATUS] | ||
actions = program[isy.KEY_ACTIONS] | ||
status = program[KEY_STATUS] | ||
actions = program[KEY_ACTIONS] | ||
assert actions.dtype == 'program', 'Not a program' | ||
except (KeyError, AssertionError): | ||
pass | ||
except (AttributeError, KeyError, AssertionError): | ||
_LOGGER.warning("Program entity '%s' not loaded due to" | ||
"incompatible folder structure.", program.name) | ||
else: | ||
devices.append(ISYCoverProgram(program.name, status, actions)) | ||
|
||
add_devices(devices) | ||
|
||
|
||
class ISYCoverDevice(isy.ISYDevice, CoverDevice): | ||
class ISYCoverDevice(ISYDevice, CoverDevice): | ||
"""Representation of an ISY994 cover device.""" | ||
|
||
def __init__(self, node: object): | ||
"""Initialize the ISY994 cover device.""" | ||
isy.ISYDevice.__init__(self, node) | ||
ISYDevice.__init__(self, node) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. super().__init__(node) |
||
|
||
@property | ||
def current_cover_position(self) -> int: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,18 +9,14 @@ | |
|
||
from homeassistant.components.fan import (FanEntity, DOMAIN, SPEED_OFF, | ||
SPEED_LOW, SPEED_MEDIUM, | ||
SPEED_HIGH) | ||
import homeassistant.components.isy994 as isy | ||
from homeassistant.const import STATE_ON, STATE_OFF | ||
SPEED_HIGH, SUPPORT_SET_SPEED) | ||
from homeassistant.components.isy994 import (ISY994_NODES, ISY994_PROGRAMS, | ||
KEY_STATUS, KEY_ACTIONS, | ||
ISYDevice) | ||
from homeassistant.helpers.typing import ConfigType | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
# Define term used for medium speed. This must be set as the fan component uses | ||
# 'medium' which the ISY does not understand | ||
ISY_SPEED_MEDIUM = 'med' | ||
|
||
|
||
VALUE_TO_STATE = { | ||
0: SPEED_OFF, | ||
63: SPEED_LOW, | ||
|
@@ -34,49 +30,44 @@ | |
for key in VALUE_TO_STATE: | ||
STATE_TO_VALUE[VALUE_TO_STATE[key]] = key | ||
|
||
STATES = [SPEED_OFF, SPEED_LOW, ISY_SPEED_MEDIUM, SPEED_HIGH] | ||
|
||
|
||
# pylint: disable=unused-argument | ||
def setup_platform(hass, config: ConfigType, | ||
add_devices: Callable[[list], None], discovery_info=None): | ||
"""Set up the ISY994 fan platform.""" | ||
if isy.ISY is None or not isy.ISY.connected: | ||
_LOGGER.error("A connection has not been made to the ISY controller") | ||
return False | ||
|
||
devices = [] | ||
|
||
for node in isy.filter_nodes(isy.NODES, states=STATES): | ||
for node in hass.data[ISY994_NODES][DOMAIN]: | ||
devices.append(ISYFanDevice(node)) | ||
|
||
for program in isy.PROGRAMS.get(DOMAIN, []): | ||
for program in hass.data[ISY994_PROGRAMS].get(DOMAIN, []): | ||
try: | ||
status = program[isy.KEY_STATUS] | ||
actions = program[isy.KEY_ACTIONS] | ||
status = program[KEY_STATUS] | ||
actions = program[KEY_ACTIONS] | ||
assert actions.dtype == 'program', 'Not a program' | ||
except (KeyError, AssertionError): | ||
pass | ||
except (AttributeError, KeyError, AssertionError): | ||
_LOGGER.warning("Program entity '%s' not loaded due to" | ||
"incompatible folder structure.", program.name) | ||
else: | ||
devices.append(ISYFanProgram(program.name, status, actions)) | ||
|
||
add_devices(devices) | ||
|
||
|
||
class ISYFanDevice(isy.ISYDevice, FanEntity): | ||
class ISYFanDevice(ISYDevice, FanEntity): | ||
"""Representation of an ISY994 fan device.""" | ||
|
||
def __init__(self, node) -> None: | ||
"""Initialize the ISY994 fan device.""" | ||
isy.ISYDevice.__init__(self, node) | ||
ISYDevice.__init__(self, node) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above. |
||
|
||
@property | ||
def speed(self) -> str: | ||
"""Return the current speed.""" | ||
return VALUE_TO_STATE.get(self.value) | ||
|
||
@property | ||
def is_on(self) -> str: | ||
def is_on(self) -> bool: | ||
"""Get if the fan is on.""" | ||
return self.value != 0 | ||
|
||
|
@@ -97,6 +88,11 @@ def speed_list(self) -> list: | |
"""Get the list of available speeds.""" | ||
return [SPEED_OFF, SPEED_LOW, SPEED_MEDIUM, SPEED_HIGH] | ||
|
||
@property | ||
def supported_features(self) -> int: | ||
"""Flag supported features.""" | ||
return SUPPORT_SET_SPEED | ||
|
||
|
||
class ISYFanProgram(ISYFanDevice): | ||
"""Representation of an ISY994 fan program.""" | ||
|
@@ -106,23 +102,18 @@ def __init__(self, name: str, node, actions) -> None: | |
ISYFanDevice.__init__(self, node) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above. |
||
self._name = name | ||
self._actions = actions | ||
self.speed = STATE_ON if self.is_on else STATE_OFF | ||
|
||
@property | ||
def state(self) -> str: | ||
"""Get the state of the ISY994 fan program.""" | ||
return STATE_ON if bool(self.value) else STATE_OFF | ||
|
||
def turn_off(self, **kwargs) -> None: | ||
"""Send the turn on command to ISY994 fan program.""" | ||
if not self._actions.runThen(): | ||
_LOGGER.error("Unable to turn off the fan") | ||
else: | ||
self.speed = STATE_ON if self.is_on else STATE_OFF | ||
|
||
def turn_on(self, **kwargs) -> None: | ||
"""Send the turn off command to ISY994 fan program.""" | ||
if not self._actions.runElse(): | ||
_LOGGER.error("Unable to turn on the fan") | ||
else: | ||
self.speed = STATE_ON if self.is_on else STATE_OFF | ||
|
||
@property | ||
def supported_features(self) -> int: | ||
"""Flag supported features.""" | ||
return 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.
There doesn't seem to be an assertion check within this try...except.
Would it be possible to move all these try...except blocks for program out of the platforms and into the
_categorize_programs
function in the component? The aim would be that all programs inISY994_PROGRAMS
should be programs that should be added as entities. That would save a lot of near duplicated code. I see the block here in the binary sensor doesn't access theKEY_ACTIONS
key onprogram
. But that should be solvable in_categorize_programs
by checking the domain.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.
Yeah, I agree that's a much better way for this to work. I'll move it over.