Add support for Insteon 2444-222 to ISY994 (#36212)

* Add support for Insteon 2444-222 Micro Open/Close Module

* Avoid breaking changes on cover

* Update homeassistant/components/isy994/cover.py

Co-authored-by: J. Nick Koston <nick@koston.org>

Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
shbatm 2020-05-28 08:51:56 -05:00 committed by GitHub
parent 03f4202796
commit 5c516ad013
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 24 deletions

View File

@ -168,6 +168,23 @@ UNDO_UPDATE_LISTENER = "undo_update_listener"
UDN_UUID_PREFIX = "uuid:"
ISY_URL_POSTFIX = "/desc"
# Special Units of Measure
UOM_ISYV4_DEGREES = "degrees"
UOM_ISYV4_NONE = "n/a"
UOM_ISY_CELSIUS = 1
UOM_ISY_FAHRENHEIT = 2
UOM_8_BIT_RANGE = "100"
UOM_BARRIER = "97"
UOM_DOUBLE_TEMP = "101"
UOM_HVAC_ACTIONS = "66"
UOM_HVAC_MODE_GENERIC = "67"
UOM_HVAC_MODE_INSTEON = "98"
UOM_FAN_MODES = "99"
UOM_INDEX = "25"
UOM_ON_OFF = "2"
# Do not use the Home Assistant consts for the states here - we're matching exact API
# responses, not using them for Home Assistant states
# Insteon Types: https://www.universal-devices.com/developers/wsdk/5.0.4/1_fam.xml
@ -232,10 +249,10 @@ NODE_FILTERS = {
FILTER_ZWAVE_CAT: [],
},
COVER: {
FILTER_UOM: ["97"],
FILTER_UOM: [UOM_BARRIER],
FILTER_STATES: ["open", "closed", "closing", "opening", "stopped"],
FILTER_NODE_DEF_ID: [],
FILTER_INSTEON_TYPE: [],
FILTER_NODE_DEF_ID: ["DimmerMotorSwitch_ADV"],
FILTER_INSTEON_TYPE: [TYPE_CATEGORY_COVER],
FILTER_ZWAVE_CAT: [],
},
LIGHT: {
@ -256,7 +273,7 @@ NODE_FILTERS = {
FILTER_ZWAVE_CAT: ["109", "119"],
},
SWITCH: {
FILTER_UOM: ["2", "78"],
FILTER_UOM: [UOM_ON_OFF, "78"],
FILTER_STATES: ["on", "off"],
FILTER_NODE_DEF_ID: [
"AlertModuleArmed",
@ -286,7 +303,7 @@ NODE_FILTERS = {
FILTER_ZWAVE_CAT: ["121", "122", "123", "137", "141", "147"],
},
CLIMATE: {
FILTER_UOM: ["2"],
FILTER_UOM: [UOM_ON_OFF],
FILTER_STATES: ["heating", "cooling", "idle", "fan_only", "off"],
FILTER_NODE_DEF_ID: ["TempLinc", "Thermostat"],
FILTER_INSTEON_TYPE: ["4.8", TYPE_CATEGORY_CLIMATE],
@ -294,20 +311,6 @@ NODE_FILTERS = {
},
}
UOM_ISYV4_DEGREES = "degrees"
UOM_ISYV4_NONE = "n/a"
UOM_ISY_CELSIUS = 1
UOM_ISY_FAHRENHEIT = 2
UOM_DOUBLE_TEMP = "101"
UOM_HVAC_ACTIONS = "66"
UOM_HVAC_MODE_GENERIC = "67"
UOM_HVAC_MODE_INSTEON = "98"
UOM_FAN_MODES = "99"
UOM_INDEX = "25"
UOM_ON_OFF = "2"
UOM_FRIENDLY_NAME = {
"1": "A",
"3": f"btu/{TIME_HOURS}",
@ -388,7 +391,7 @@ UOM_FRIENDLY_NAME = {
"90": FREQUENCY_HERTZ,
"91": DEGREE,
"92": f"{DEGREE} South",
"100": "", # Range 0-255, no unit.
UOM_8_BIT_RANGE: "", # Range 0-255, no unit.
UOM_DOUBLE_TEMP: UOM_DOUBLE_TEMP,
"102": "kWs",
"103": "$",
@ -556,7 +559,7 @@ UOM_TO_STATES = {
3: "moderately polluted",
4: "highly polluted",
},
"97": { # Barrier Status
UOM_BARRIER: { # Barrier Status
**{
0: STATE_CLOSED,
100: STATE_OPEN,

View File

@ -3,11 +3,25 @@ from typing import Callable
from pyisy.constants import ISY_VALUE_UNKNOWN
from homeassistant.components.cover import DOMAIN as COVER, CoverEntity
from homeassistant.components.cover import (
ATTR_POSITION,
DOMAIN as COVER,
SUPPORT_CLOSE,
SUPPORT_OPEN,
SUPPORT_SET_POSITION,
CoverEntity,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.helpers.typing import HomeAssistantType
from .const import _LOGGER, DOMAIN as ISY994_DOMAIN, ISY994_NODES, ISY994_PROGRAMS
from .const import (
_LOGGER,
DOMAIN as ISY994_DOMAIN,
ISY994_NODES,
ISY994_PROGRAMS,
UOM_8_BIT_RANGE,
UOM_BARRIER,
)
from .entity import ISYNodeEntity, ISYProgramEntity
from .helpers import migrate_old_unique_ids
from .services import async_setup_device_services
@ -40,6 +54,8 @@ class ISYCoverEntity(ISYNodeEntity, CoverEntity):
"""Return the current cover position."""
if self._node.status == ISY_VALUE_UNKNOWN:
return None
if self._node.uom == UOM_8_BIT_RANGE:
return int(self._node.status * 100 / 255)
return sorted((0, self._node.status, 100))[1]
@property
@ -49,9 +65,15 @@ class ISYCoverEntity(ISYNodeEntity, CoverEntity):
return None
return self._node.status == 0
@property
def supported_features(self):
"""Flag supported features."""
return SUPPORT_OPEN | SUPPORT_CLOSE | SUPPORT_SET_POSITION
def open_cover(self, **kwargs) -> None:
"""Send the open cover command to the ISY994 cover device."""
if not self._node.turn_on(val=100):
val = 100 if self._node.uom == UOM_BARRIER else None
if not self._node.turn_on(val=val):
_LOGGER.error("Unable to open the cover")
def close_cover(self, **kwargs) -> None:
@ -59,6 +81,14 @@ class ISYCoverEntity(ISYNodeEntity, CoverEntity):
if not self._node.turn_off():
_LOGGER.error("Unable to close the cover")
def set_cover_position(self, **kwargs):
"""Move the cover to a specific position."""
position = kwargs.get(ATTR_POSITION)
if position and self._node.uom == UOM_8_BIT_RANGE:
position = int(position * 255 / 100)
if not self._node.turn_on(val=position):
_LOGGER.error("Unable to set cover position")
class ISYCoverProgramEntity(ISYProgramEntity, CoverEntity):
"""Representation of an ISY994 cover program."""