mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 03:07:37 +00:00
Add Climate Platform Support to ISY994 (#35440)
* ISY994 Add support for climate platform Remove services from Climate (not added yet) * Incorporate suggestions based on review. * Collect string literals to Const. Rename device to entity * Fix merge error
This commit is contained in:
parent
a97460d1ab
commit
8947ce5053
@ -37,7 +37,16 @@ from .const import (
|
|||||||
DOMAIN as ISY994_DOMAIN,
|
DOMAIN as ISY994_DOMAIN,
|
||||||
ISY994_NODES,
|
ISY994_NODES,
|
||||||
ISY994_PROGRAMS,
|
ISY994_PROGRAMS,
|
||||||
|
SUBNODE_CLIMATE_COOL,
|
||||||
|
SUBNODE_CLIMATE_HEAT,
|
||||||
|
SUBNODE_DUSK_DAWN,
|
||||||
|
SUBNODE_HEARTBEAT,
|
||||||
|
SUBNODE_LOW_BATTERY,
|
||||||
|
SUBNODE_MOTION_DISABLED,
|
||||||
|
SUBNODE_NEGATIVE,
|
||||||
|
SUBNODE_TAMPER,
|
||||||
TYPE_CATEGORY_CLIMATE,
|
TYPE_CATEGORY_CLIMATE,
|
||||||
|
TYPE_INSTEON_MOTION,
|
||||||
)
|
)
|
||||||
from .entity import ISYNodeEntity, ISYProgramEntity
|
from .entity import ISYNodeEntity, ISYProgramEntity
|
||||||
from .helpers import migrate_old_unique_ids
|
from .helpers import migrate_old_unique_ids
|
||||||
@ -48,17 +57,6 @@ DEVICE_PARENT_REQUIRED = [
|
|||||||
DEVICE_CLASS_MOTION,
|
DEVICE_CLASS_MOTION,
|
||||||
]
|
]
|
||||||
|
|
||||||
SUBNODE_CLIMATE_COOL = 2
|
|
||||||
SUBNODE_CLIMATE_HEAT = 3
|
|
||||||
SUBNODE_NEGATIVE = 2
|
|
||||||
SUBNODE_HEARTBEAT = 4
|
|
||||||
SUBNODE_DUSK_DAWN = 2
|
|
||||||
SUBNODE_LOW_BATTERY = 3
|
|
||||||
SUBNODE_TAMPER = (10, 16) # Int->10 or Hex->0xA depending on firmware
|
|
||||||
SUBNODE_MOTION_DISABLED = (13, 19) # Int->13 or Hex->0xD depending on firmware
|
|
||||||
|
|
||||||
TYPE_INSTEON_MOTION = ("16.1.", "16.22.")
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistantType,
|
hass: HomeAssistantType,
|
||||||
|
260
homeassistant/components/isy994/climate.py
Normal file
260
homeassistant/components/isy994/climate.py
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
"""Support for Insteon Thermostats via ISY994 Platform."""
|
||||||
|
from typing import Callable, List, Optional, Union
|
||||||
|
|
||||||
|
from pyisy.constants import (
|
||||||
|
CMD_CLIMATE_FAN_SETTING,
|
||||||
|
CMD_CLIMATE_MODE,
|
||||||
|
ISY_VALUE_UNKNOWN,
|
||||||
|
PROP_HEAT_COOL_STATE,
|
||||||
|
PROP_HUMIDITY,
|
||||||
|
PROP_SETPOINT_COOL,
|
||||||
|
PROP_SETPOINT_HEAT,
|
||||||
|
PROP_UOM,
|
||||||
|
PROTO_INSTEON,
|
||||||
|
)
|
||||||
|
|
||||||
|
from homeassistant.components.climate import ClimateEntity
|
||||||
|
from homeassistant.components.climate.const import (
|
||||||
|
ATTR_TARGET_TEMP_HIGH,
|
||||||
|
ATTR_TARGET_TEMP_LOW,
|
||||||
|
DOMAIN as CLIMATE,
|
||||||
|
FAN_AUTO,
|
||||||
|
FAN_ON,
|
||||||
|
HVAC_MODE_COOL,
|
||||||
|
HVAC_MODE_HEAT,
|
||||||
|
SUPPORT_FAN_MODE,
|
||||||
|
SUPPORT_TARGET_TEMPERATURE,
|
||||||
|
SUPPORT_TARGET_TEMPERATURE_RANGE,
|
||||||
|
)
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import (
|
||||||
|
ATTR_TEMPERATURE,
|
||||||
|
PRECISION_TENTHS,
|
||||||
|
TEMP_CELSIUS,
|
||||||
|
TEMP_FAHRENHEIT,
|
||||||
|
)
|
||||||
|
from homeassistant.helpers.typing import HomeAssistantType
|
||||||
|
|
||||||
|
from .const import (
|
||||||
|
_LOGGER,
|
||||||
|
DOMAIN as ISY994_DOMAIN,
|
||||||
|
HA_FAN_TO_ISY,
|
||||||
|
HA_HVAC_TO_ISY,
|
||||||
|
ISY994_NODES,
|
||||||
|
ISY_HVAC_MODES,
|
||||||
|
UOM_DOUBLE_TEMP,
|
||||||
|
UOM_FAN_MODES,
|
||||||
|
UOM_HVAC_ACTIONS,
|
||||||
|
UOM_HVAC_MODE_GENERIC,
|
||||||
|
UOM_HVAC_MODE_INSTEON,
|
||||||
|
UOM_ISY_CELSIUS,
|
||||||
|
UOM_ISY_FAHRENHEIT,
|
||||||
|
UOM_ISYV4_DEGREES,
|
||||||
|
UOM_ISYV4_NONE,
|
||||||
|
UOM_TO_STATES,
|
||||||
|
)
|
||||||
|
from .entity import ISYNodeEntity
|
||||||
|
from .helpers import migrate_old_unique_ids
|
||||||
|
|
||||||
|
ISY_SUPPORTED_FEATURES = (
|
||||||
|
SUPPORT_FAN_MODE | SUPPORT_TARGET_TEMPERATURE | SUPPORT_TARGET_TEMPERATURE_RANGE
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistantType,
|
||||||
|
entry: ConfigEntry,
|
||||||
|
async_add_entities: Callable[[list], None],
|
||||||
|
) -> bool:
|
||||||
|
"""Set up the ISY994 thermostat platform."""
|
||||||
|
entities = []
|
||||||
|
|
||||||
|
hass_isy_data = hass.data[ISY994_DOMAIN][entry.entry_id]
|
||||||
|
for node in hass_isy_data[ISY994_NODES][CLIMATE]:
|
||||||
|
entities.append(ISYThermostatEntity(node))
|
||||||
|
|
||||||
|
await migrate_old_unique_ids(hass, CLIMATE, entities)
|
||||||
|
async_add_entities(entities)
|
||||||
|
|
||||||
|
|
||||||
|
def convert_isy_temp_to_hass(
|
||||||
|
temp: Union[int, float, None], uom: str, precision: str
|
||||||
|
) -> float:
|
||||||
|
"""Fix Insteon Thermostats' Reported Temperature.
|
||||||
|
|
||||||
|
Insteon Thermostats report temperature in 0.5-deg precision as an int
|
||||||
|
by sending a value of 2 times the Temp. Correct by dividing by 2 here.
|
||||||
|
|
||||||
|
Z-Wave Thermostats report temps in tenths as an integer and precision.
|
||||||
|
Correct by shifting the decimal place left by the value of precision.
|
||||||
|
"""
|
||||||
|
if temp is None or temp == ISY_VALUE_UNKNOWN:
|
||||||
|
return None
|
||||||
|
if uom in [UOM_DOUBLE_TEMP, UOM_ISYV4_DEGREES]:
|
||||||
|
return round(float(temp) / 2.0, 1)
|
||||||
|
if precision != "0":
|
||||||
|
return round(float(temp) / 10 ** int(precision), int(precision))
|
||||||
|
return round(float(temp), 1)
|
||||||
|
|
||||||
|
|
||||||
|
class ISYThermostatEntity(ISYNodeEntity, ClimateEntity):
|
||||||
|
"""Representation of an ISY994 thermostat entity."""
|
||||||
|
|
||||||
|
def __init__(self, node) -> None:
|
||||||
|
"""Initialize the ISY Thermostat entity."""
|
||||||
|
super().__init__(node)
|
||||||
|
self._node = node
|
||||||
|
self._uom = self._node.uom
|
||||||
|
if isinstance(self._uom, list):
|
||||||
|
self._uom = self._node.uom[0]
|
||||||
|
self._hvac_action = None
|
||||||
|
self._hvac_mode = None
|
||||||
|
self._fan_mode = None
|
||||||
|
self._temp_unit = None
|
||||||
|
self._current_humidity = 0
|
||||||
|
self._target_temp_low = 0
|
||||||
|
self._target_temp_high = 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def supported_features(self) -> int:
|
||||||
|
"""Return the list of supported features."""
|
||||||
|
return ISY_SUPPORTED_FEATURES
|
||||||
|
|
||||||
|
@property
|
||||||
|
def precision(self) -> str:
|
||||||
|
"""Return the precision of the system."""
|
||||||
|
return PRECISION_TENTHS
|
||||||
|
|
||||||
|
@property
|
||||||
|
def temperature_unit(self) -> str:
|
||||||
|
"""Return the unit of measurement."""
|
||||||
|
uom = self._node.aux_properties.get(PROP_UOM)
|
||||||
|
if not uom:
|
||||||
|
return self.hass.config.units.temperature_unit
|
||||||
|
if uom.value == UOM_ISY_CELSIUS:
|
||||||
|
return TEMP_CELSIUS
|
||||||
|
if uom.value == UOM_ISY_FAHRENHEIT:
|
||||||
|
return TEMP_FAHRENHEIT
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current_humidity(self) -> Optional[int]:
|
||||||
|
"""Return the current humidity."""
|
||||||
|
humidity = self._node.aux_properties.get(PROP_HUMIDITY)
|
||||||
|
if not humidity:
|
||||||
|
return None
|
||||||
|
return int(humidity.value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def hvac_mode(self) -> Optional[str]:
|
||||||
|
"""Return hvac operation ie. heat, cool mode."""
|
||||||
|
hvac_mode = self._node.aux_properties.get(CMD_CLIMATE_MODE)
|
||||||
|
if not hvac_mode:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Which state values used depends on the mode property's UOM:
|
||||||
|
uom = hvac_mode.uom
|
||||||
|
# Handle special case for ISYv4 Firmware:
|
||||||
|
if uom == UOM_ISYV4_NONE:
|
||||||
|
uom = (
|
||||||
|
UOM_HVAC_MODE_INSTEON
|
||||||
|
if self._node.protocol == PROTO_INSTEON
|
||||||
|
else UOM_HVAC_MODE_GENERIC
|
||||||
|
)
|
||||||
|
return UOM_TO_STATES[uom].get(hvac_mode.value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def hvac_modes(self) -> List[str]:
|
||||||
|
"""Return the list of available hvac operation modes."""
|
||||||
|
return ISY_HVAC_MODES
|
||||||
|
|
||||||
|
@property
|
||||||
|
def hvac_action(self) -> Optional[str]:
|
||||||
|
"""Return the current running hvac operation if supported."""
|
||||||
|
hvac_action = self._node.aux_properties.get(PROP_HEAT_COOL_STATE)
|
||||||
|
if not hvac_action:
|
||||||
|
return None
|
||||||
|
return UOM_TO_STATES[UOM_HVAC_ACTIONS].get(hvac_action.value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current_temperature(self) -> Optional[float]:
|
||||||
|
"""Return the current temperature."""
|
||||||
|
return convert_isy_temp_to_hass(self._node.status, self._uom, self._node.prec)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def target_temperature_step(self) -> Optional[float]:
|
||||||
|
"""Return the supported step of target temperature."""
|
||||||
|
return 1.0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def target_temperature(self) -> Optional[float]:
|
||||||
|
"""Return the temperature we try to reach."""
|
||||||
|
if self.hvac_mode == HVAC_MODE_COOL:
|
||||||
|
return self.target_temperature_high
|
||||||
|
if self.hvac_mode == HVAC_MODE_HEAT:
|
||||||
|
return self.target_temperature_low
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def target_temperature_high(self) -> Optional[float]:
|
||||||
|
"""Return the highbound target temperature we try to reach."""
|
||||||
|
target = self._node.aux_properties.get(PROP_SETPOINT_COOL)
|
||||||
|
if not target:
|
||||||
|
return None
|
||||||
|
return convert_isy_temp_to_hass(target.value, target.uom, target.prec)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def target_temperature_low(self) -> Optional[float]:
|
||||||
|
"""Return the lowbound target temperature we try to reach."""
|
||||||
|
target = self._node.aux_properties.get(PROP_SETPOINT_HEAT)
|
||||||
|
if not target:
|
||||||
|
return None
|
||||||
|
return convert_isy_temp_to_hass(target.value, target.uom, target.prec)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def fan_modes(self):
|
||||||
|
"""Return the list of available fan modes."""
|
||||||
|
return [FAN_AUTO, FAN_ON]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def fan_mode(self) -> str:
|
||||||
|
"""Return the current fan mode ie. auto, on."""
|
||||||
|
fan_mode = self._node.aux_properties.get(CMD_CLIMATE_FAN_SETTING)
|
||||||
|
if not fan_mode:
|
||||||
|
return None
|
||||||
|
return UOM_TO_STATES[UOM_FAN_MODES].get(fan_mode.value)
|
||||||
|
|
||||||
|
def set_temperature(self, **kwargs) -> None:
|
||||||
|
"""Set new target temperature."""
|
||||||
|
target_temp = kwargs.get(ATTR_TEMPERATURE)
|
||||||
|
target_temp_low = kwargs.get(ATTR_TARGET_TEMP_LOW)
|
||||||
|
target_temp_high = kwargs.get(ATTR_TARGET_TEMP_HIGH)
|
||||||
|
if target_temp is not None:
|
||||||
|
if self.hvac_mode == HVAC_MODE_COOL:
|
||||||
|
target_temp_high = target_temp
|
||||||
|
if self.hvac_mode == HVAC_MODE_HEAT:
|
||||||
|
target_temp_low = target_temp
|
||||||
|
if target_temp_low is not None:
|
||||||
|
self._node.set_climate_setpoint_heat(int(target_temp_low))
|
||||||
|
# Presumptive setting--event stream will correct if cmd fails:
|
||||||
|
self._target_temp_low = target_temp_low
|
||||||
|
if target_temp_high is not None:
|
||||||
|
self._node.set_climate_setpoint_cool(int(target_temp_high))
|
||||||
|
# Presumptive setting--event stream will correct if cmd fails:
|
||||||
|
self._target_temp_high = target_temp_high
|
||||||
|
self.schedule_update_ha_state()
|
||||||
|
|
||||||
|
def set_fan_mode(self, fan_mode: str) -> None:
|
||||||
|
"""Set new target fan mode."""
|
||||||
|
_LOGGER.debug("Requested fan mode %s", fan_mode)
|
||||||
|
self._node.set_fan_mode(HA_FAN_TO_ISY.get(fan_mode))
|
||||||
|
# Presumptive setting--event stream will correct if cmd fails:
|
||||||
|
self._fan_mode = fan_mode
|
||||||
|
self.schedule_update_ha_state()
|
||||||
|
|
||||||
|
def set_hvac_mode(self, hvac_mode: str) -> None:
|
||||||
|
"""Set new target hvac mode."""
|
||||||
|
_LOGGER.debug("Requested operation mode %s", hvac_mode)
|
||||||
|
self._node.set_climate_mode(HA_HVAC_TO_ISY.get(hvac_mode))
|
||||||
|
# Presumptive setting--event stream will correct if cmd fails:
|
||||||
|
self._hvac_mode = hvac_mode
|
||||||
|
self.schedule_update_ha_state()
|
@ -22,6 +22,7 @@ from homeassistant.components.climate.const import (
|
|||||||
CURRENT_HVAC_FAN,
|
CURRENT_HVAC_FAN,
|
||||||
CURRENT_HVAC_HEAT,
|
CURRENT_HVAC_HEAT,
|
||||||
CURRENT_HVAC_IDLE,
|
CURRENT_HVAC_IDLE,
|
||||||
|
DOMAIN as CLIMATE,
|
||||||
FAN_AUTO,
|
FAN_AUTO,
|
||||||
FAN_HIGH,
|
FAN_HIGH,
|
||||||
FAN_MEDIUM,
|
FAN_MEDIUM,
|
||||||
@ -109,7 +110,7 @@ DEFAULT_PROGRAM_STRING = "HA."
|
|||||||
KEY_ACTIONS = "actions"
|
KEY_ACTIONS = "actions"
|
||||||
KEY_STATUS = "status"
|
KEY_STATUS = "status"
|
||||||
|
|
||||||
SUPPORTED_PLATFORMS = [BINARY_SENSOR, SENSOR, LOCK, FAN, COVER, LIGHT, SWITCH]
|
SUPPORTED_PLATFORMS = [BINARY_SENSOR, SENSOR, LOCK, FAN, COVER, LIGHT, SWITCH, CLIMATE]
|
||||||
SUPPORTED_PROGRAM_PLATFORMS = [BINARY_SENSOR, LOCK, FAN, COVER, SWITCH]
|
SUPPORTED_PROGRAM_PLATFORMS = [BINARY_SENSOR, LOCK, FAN, COVER, SWITCH]
|
||||||
|
|
||||||
SUPPORTED_BIN_SENS_CLASSES = ["moisture", "opening", "motion", "climate"]
|
SUPPORTED_BIN_SENS_CLASSES = ["moisture", "opening", "motion", "climate"]
|
||||||
@ -128,6 +129,19 @@ FILTER_NODE_DEF_ID = "node_def_id"
|
|||||||
FILTER_INSTEON_TYPE = "insteon_type"
|
FILTER_INSTEON_TYPE = "insteon_type"
|
||||||
FILTER_ZWAVE_CAT = "zwave_cat"
|
FILTER_ZWAVE_CAT = "zwave_cat"
|
||||||
|
|
||||||
|
# Special Subnodes for some Insteon Devices
|
||||||
|
SUBNODE_CLIMATE_COOL = 2
|
||||||
|
SUBNODE_CLIMATE_HEAT = 3
|
||||||
|
SUBNODE_DUSK_DAWN = 2
|
||||||
|
SUBNODE_EZIO2X4_SENSORS = [9, 10, 11, 12]
|
||||||
|
SUBNODE_FANLINC_LIGHT = 1
|
||||||
|
SUBNODE_HEARTBEAT = 4
|
||||||
|
SUBNODE_IOLINC_RELAY = 2
|
||||||
|
SUBNODE_LOW_BATTERY = 3
|
||||||
|
SUBNODE_MOTION_DISABLED = (13, 19) # Int->13 or Hex->0xD depending on firmware
|
||||||
|
SUBNODE_NEGATIVE = 2
|
||||||
|
SUBNODE_TAMPER = (10, 16) # Int->10 or Hex->0xA depending on firmware
|
||||||
|
|
||||||
# Generic Insteon Type Categories for Filters
|
# Generic Insteon Type Categories for Filters
|
||||||
TYPE_CATEGORY_CONTROLLERS = "0."
|
TYPE_CATEGORY_CONTROLLERS = "0."
|
||||||
TYPE_CATEGORY_DIMMABLE = "1."
|
TYPE_CATEGORY_DIMMABLE = "1."
|
||||||
@ -142,6 +156,9 @@ TYPE_CATEGORY_LOCK = "15."
|
|||||||
TYPE_CATEGORY_SAFETY = "16."
|
TYPE_CATEGORY_SAFETY = "16."
|
||||||
TYPE_CATEGORY_X10 = "113."
|
TYPE_CATEGORY_X10 = "113."
|
||||||
|
|
||||||
|
TYPE_EZIO2X4 = "7.3.255."
|
||||||
|
TYPE_INSTEON_MOTION = ("16.1.", "16.22.")
|
||||||
|
|
||||||
UNDO_UPDATE_LISTENER = "undo_update_listener"
|
UNDO_UPDATE_LISTENER = "undo_update_listener"
|
||||||
|
|
||||||
# Do not use the Home Assistant consts for the states here - we're matching exact API
|
# Do not use the Home Assistant consts for the states here - we're matching exact API
|
||||||
@ -261,8 +278,27 @@ NODE_FILTERS = {
|
|||||||
],
|
],
|
||||||
FILTER_ZWAVE_CAT: ["121", "122", "123", "137", "141", "147"],
|
FILTER_ZWAVE_CAT: ["121", "122", "123", "137", "141", "147"],
|
||||||
},
|
},
|
||||||
|
CLIMATE: {
|
||||||
|
FILTER_UOM: ["2"],
|
||||||
|
FILTER_STATES: ["heating", "cooling", "idle", "fan_only", "off"],
|
||||||
|
FILTER_NODE_DEF_ID: ["TempLinc", "Thermostat"],
|
||||||
|
FILTER_INSTEON_TYPE: ["4.8", TYPE_CATEGORY_CLIMATE],
|
||||||
|
FILTER_ZWAVE_CAT: ["140"],
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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_FRIENDLY_NAME = {
|
UOM_FRIENDLY_NAME = {
|
||||||
"1": "A",
|
"1": "A",
|
||||||
"3": f"btu/{TIME_HOURS}",
|
"3": f"btu/{TIME_HOURS}",
|
||||||
@ -400,7 +436,7 @@ UOM_TO_STATES = {
|
|||||||
26: "hardware failure",
|
26: "hardware failure",
|
||||||
27: "factory reset",
|
27: "factory reset",
|
||||||
},
|
},
|
||||||
"66": { # Thermostat Heat/Cool State
|
UOM_HVAC_ACTIONS: { # Thermostat Heat/Cool State
|
||||||
0: CURRENT_HVAC_IDLE,
|
0: CURRENT_HVAC_IDLE,
|
||||||
1: CURRENT_HVAC_HEAT,
|
1: CURRENT_HVAC_HEAT,
|
||||||
2: CURRENT_HVAC_COOL,
|
2: CURRENT_HVAC_COOL,
|
||||||
@ -415,7 +451,7 @@ UOM_TO_STATES = {
|
|||||||
10: CURRENT_HVAC_HEAT,
|
10: CURRENT_HVAC_HEAT,
|
||||||
11: CURRENT_HVAC_HEAT,
|
11: CURRENT_HVAC_HEAT,
|
||||||
},
|
},
|
||||||
"67": { # Thermostat Mode
|
UOM_HVAC_MODE_GENERIC: { # Thermostat Mode
|
||||||
0: HVAC_MODE_OFF,
|
0: HVAC_MODE_OFF,
|
||||||
1: HVAC_MODE_HEAT,
|
1: HVAC_MODE_HEAT,
|
||||||
2: HVAC_MODE_COOL,
|
2: HVAC_MODE_COOL,
|
||||||
@ -524,7 +560,7 @@ UOM_TO_STATES = {
|
|||||||
b: f"{b} %" for a, b in enumerate(list(range(1, 100)))
|
b: f"{b} %" for a, b in enumerate(list(range(1, 100)))
|
||||||
}, # 1-99 are percentage open
|
}, # 1-99 are percentage open
|
||||||
},
|
},
|
||||||
"98": { # Insteon Thermostat Mode
|
UOM_HVAC_MODE_INSTEON: { # Insteon Thermostat Mode
|
||||||
0: HVAC_MODE_OFF,
|
0: HVAC_MODE_OFF,
|
||||||
1: HVAC_MODE_HEAT,
|
1: HVAC_MODE_HEAT,
|
||||||
2: HVAC_MODE_COOL,
|
2: HVAC_MODE_COOL,
|
||||||
@ -534,7 +570,7 @@ UOM_TO_STATES = {
|
|||||||
6: HVAC_MODE_AUTO, # Program Heat-Set @ Local Device Only
|
6: HVAC_MODE_AUTO, # Program Heat-Set @ Local Device Only
|
||||||
7: HVAC_MODE_AUTO, # Program Cool-Set @ Local Device Only
|
7: HVAC_MODE_AUTO, # Program Cool-Set @ Local Device Only
|
||||||
},
|
},
|
||||||
"99": {7: FAN_ON, 8: FAN_AUTO}, # Insteon Thermostat Fan Mode
|
UOM_FAN_MODES: {7: FAN_ON, 8: FAN_AUTO}, # Insteon Thermostat Fan Mode
|
||||||
"115": { # Most recent On style action taken for lamp control
|
"115": { # Most recent On style action taken for lamp control
|
||||||
0: "on",
|
0: "on",
|
||||||
1: "off",
|
1: "off",
|
||||||
@ -552,6 +588,26 @@ UOM_TO_STATES = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ISY_HVAC_MODES = [
|
||||||
|
HVAC_MODE_OFF,
|
||||||
|
HVAC_MODE_HEAT,
|
||||||
|
HVAC_MODE_COOL,
|
||||||
|
HVAC_MODE_HEAT_COOL,
|
||||||
|
HVAC_MODE_AUTO,
|
||||||
|
HVAC_MODE_FAN_ONLY,
|
||||||
|
]
|
||||||
|
|
||||||
|
HA_HVAC_TO_ISY = {
|
||||||
|
HVAC_MODE_OFF: "off",
|
||||||
|
HVAC_MODE_HEAT: "heat",
|
||||||
|
HVAC_MODE_COOL: "cool",
|
||||||
|
HVAC_MODE_HEAT_COOL: "auto",
|
||||||
|
HVAC_MODE_FAN_ONLY: "fan_only",
|
||||||
|
HVAC_MODE_AUTO: "program_auto",
|
||||||
|
}
|
||||||
|
|
||||||
|
HA_FAN_TO_ISY = {FAN_ON: "on", FAN_AUTO: "auto"}
|
||||||
|
|
||||||
BINARY_SENSOR_DEVICE_TYPES_ISY = {
|
BINARY_SENSOR_DEVICE_TYPES_ISY = {
|
||||||
DEVICE_CLASS_MOISTURE: ["16.8.", "16.13.", "16.14."],
|
DEVICE_CLASS_MOISTURE: ["16.8.", "16.13.", "16.14."],
|
||||||
DEVICE_CLASS_OPENING: [
|
DEVICE_CLASS_OPENING: [
|
||||||
|
@ -12,6 +12,7 @@ from pyisy.nodes import Group, Node, Nodes
|
|||||||
from pyisy.programs import Programs
|
from pyisy.programs import Programs
|
||||||
|
|
||||||
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR
|
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR
|
||||||
|
from homeassistant.components.climate.const import DOMAIN as CLIMATE
|
||||||
from homeassistant.components.fan import DOMAIN as FAN
|
from homeassistant.components.fan import DOMAIN as FAN
|
||||||
from homeassistant.components.light import DOMAIN as LIGHT
|
from homeassistant.components.light import DOMAIN as LIGHT
|
||||||
from homeassistant.components.sensor import DOMAIN as SENSOR
|
from homeassistant.components.sensor import DOMAIN as SENSOR
|
||||||
@ -34,20 +35,20 @@ from .const import (
|
|||||||
KEY_ACTIONS,
|
KEY_ACTIONS,
|
||||||
KEY_STATUS,
|
KEY_STATUS,
|
||||||
NODE_FILTERS,
|
NODE_FILTERS,
|
||||||
|
SUBNODE_CLIMATE_COOL,
|
||||||
|
SUBNODE_CLIMATE_HEAT,
|
||||||
|
SUBNODE_EZIO2X4_SENSORS,
|
||||||
|
SUBNODE_FANLINC_LIGHT,
|
||||||
|
SUBNODE_IOLINC_RELAY,
|
||||||
SUPPORTED_PLATFORMS,
|
SUPPORTED_PLATFORMS,
|
||||||
SUPPORTED_PROGRAM_PLATFORMS,
|
SUPPORTED_PROGRAM_PLATFORMS,
|
||||||
TYPE_CATEGORY_SENSOR_ACTUATORS,
|
TYPE_CATEGORY_SENSOR_ACTUATORS,
|
||||||
|
TYPE_EZIO2X4,
|
||||||
)
|
)
|
||||||
|
|
||||||
BINARY_SENSOR_UOMS = ["2", "78"]
|
BINARY_SENSOR_UOMS = ["2", "78"]
|
||||||
BINARY_SENSOR_ISY_STATES = ["on", "off"]
|
BINARY_SENSOR_ISY_STATES = ["on", "off"]
|
||||||
|
|
||||||
TYPE_EZIO2X4 = "7.3.255."
|
|
||||||
|
|
||||||
SUBNODE_EZIO2X4_SENSORS = [9, 10, 11, 12]
|
|
||||||
SUBNODE_FANLINC_LIGHT = 1
|
|
||||||
SUBNODE_IOLINC_RELAY = 2
|
|
||||||
|
|
||||||
|
|
||||||
def _check_for_node_def(
|
def _check_for_node_def(
|
||||||
hass_isy_data: dict, node: Union[Group, Node], single_platform: str = None
|
hass_isy_data: dict, node: Union[Group, Node], single_platform: str = None
|
||||||
@ -107,6 +108,14 @@ def _check_for_insteon_type(
|
|||||||
hass_isy_data[ISY994_NODES][LIGHT].append(node)
|
hass_isy_data[ISY994_NODES][LIGHT].append(node)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
# Thermostats, which has a "Heat" and "Cool" sub-node on address 2 and 3
|
||||||
|
if platform == CLIMATE and subnode_id in [
|
||||||
|
SUBNODE_CLIMATE_COOL,
|
||||||
|
SUBNODE_CLIMATE_HEAT,
|
||||||
|
]:
|
||||||
|
hass_isy_data[ISY994_NODES][BINARY_SENSOR].append(node)
|
||||||
|
return True
|
||||||
|
|
||||||
# IOLincs which have a sensor and relay on 2 different nodes
|
# IOLincs which have a sensor and relay on 2 different nodes
|
||||||
if (
|
if (
|
||||||
platform == BINARY_SENSOR
|
platform == BINARY_SENSOR
|
||||||
|
Loading…
x
Reference in New Issue
Block a user