Skip to content
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

Merged
merged 10 commits into from
Dec 26, 2017
28 changes: 8 additions & 20 deletions homeassistant/components/binary_sensor/isy994.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,15 @@

from homeassistant.core import callback
from homeassistant.components.binary_sensor import BinarySensorDevice, DOMAIN
import homeassistant.components.isy994 as isy
from homeassistant.components.isy994 import (ISY994_NODES, ISY994_PROGRAMS,
ISYDevice)
from homeassistant.const import STATE_ON, STATE_OFF
from homeassistant.helpers.typing import ConfigType
from homeassistant.helpers.event import async_track_point_in_utc_time
from homeassistant.util import dt as dt_util

_LOGGER = logging.getLogger(__name__)

UOM = ['2', '78']
STATES = [STATE_OFF, STATE_ON, 'true', 'false']

ISY_DEVICE_TYPES = {
'moisture': ['16.8', '16.13', '16.14'],
'opening': ['16.9', '16.6', '16.7', '16.2', '16.17', '16.20', '16.21'],
Expand All @@ -34,16 +32,11 @@
def setup_platform(hass, config: ConfigType,
add_devices: Callable[[list], None], discovery_info=None):
"""Set up the ISY994 binary sensor 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 = []
devices_by_nid = {}
child_nodes = []

for node in isy.filter_nodes(isy.SENSOR_NODES, units=UOM,
states=STATES):
for node in hass.data[ISY994_NODES][DOMAIN]:
if node.parent_node is None:
device = ISYBinarySensorDevice(node)
devices.append(device)
Expand Down Expand Up @@ -80,13 +73,8 @@ def setup_platform(hass, config: ConfigType,
device = ISYBinarySensorDevice(node)
devices.append(device)

for program in isy.PROGRAMS.get(DOMAIN, []):
try:
status = program[isy.KEY_STATUS]
except (KeyError, AssertionError):
pass
else:
devices.append(ISYBinarySensorProgram(program.name, status))
for name, status, _ in hass.data[ISY994_PROGRAMS][DOMAIN]:
devices.append(ISYBinarySensorProgram(name, status))

add_devices(devices)

Expand All @@ -111,7 +99,7 @@ def _is_val_unknown(val):
return val == -1*float('inf')


class ISYBinarySensorDevice(isy.ISYDevice, BinarySensorDevice):
class ISYBinarySensorDevice(ISYDevice, BinarySensorDevice):
"""Representation of an ISY994 binary sensor device.

Often times, a single device is represented by multiple nodes in the ISY,
Expand Down Expand Up @@ -250,7 +238,7 @@ def device_class(self) -> str:
return self._device_class_from_type


class ISYBinarySensorHeartbeat(isy.ISYDevice, BinarySensorDevice):
class ISYBinarySensorHeartbeat(ISYDevice, BinarySensorDevice):
"""Representation of the battery state of an ISY994 sensor."""

def __init__(self, node, parent_device) -> None:
Expand Down Expand Up @@ -353,7 +341,7 @@ def device_state_attributes(self):
return attr


class ISYBinarySensorProgram(isy.ISYDevice, BinarySensorDevice):
class ISYBinarySensorProgram(ISYDevice, BinarySensorDevice):
"""Representation of an ISY994 binary sensor program.

This does not need all of the subnode logic in the device version of binary
Expand Down
36 changes: 13 additions & 23 deletions homeassistant/components/cover/isy994.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,53 +8,43 @@
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,
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, []):
try:
status = program[isy.KEY_STATUS]
actions = program[isy.KEY_ACTIONS]
assert actions.dtype == 'program', 'Not a program'
except (KeyError, AssertionError):
pass
else:
devices.append(ISYCoverProgram(program.name, status, actions))
for name, status, actions in hass.data[ISY994_PROGRAMS][DOMAIN]:
devices.append(ISYCoverProgram(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)
super().__init__(node)

@property
def current_cover_position(self) -> int:
Expand Down Expand Up @@ -90,7 +80,7 @@ class ISYCoverProgram(ISYCoverDevice):

def __init__(self, name: str, node: object, actions: object) -> None:
"""Initialize the ISY994 cover program."""
ISYCoverDevice.__init__(self, node)
super().__init__(node)
self._name = name
self._actions = actions

Expand Down
58 changes: 20 additions & 38 deletions homeassistant/components/fan/isy994.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,13 @@

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,
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,
Expand All @@ -34,49 +29,36 @@
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, []):
try:
status = program[isy.KEY_STATUS]
actions = program[isy.KEY_ACTIONS]
assert actions.dtype == 'program', 'Not a program'
except (KeyError, AssertionError):
pass
else:
devices.append(ISYFanProgram(program.name, status, actions))
for name, status, actions in hass.data[ISY994_PROGRAMS][DOMAIN]:
devices.append(ISYFanProgram(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)
super().__init__(node)

@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

Expand All @@ -97,32 +79,32 @@ 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."""

def __init__(self, name: str, node, actions) -> None:
"""Initialize the ISY994 fan program."""
ISYFanDevice.__init__(self, node)
super().__init__(node)
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
Loading