Home Assistant Unofficial Reference 2024.12.1
const.py
Go to the documentation of this file.
1 """Constants for the ISY Platform."""
2 
3 import logging
4 
5 from pyisy.constants import PROP_ON_LEVEL, PROP_RAMP_RATE
6 
7 from homeassistant.components.binary_sensor import BinarySensorDeviceClass
9  FAN_AUTO,
10  FAN_HIGH,
11  FAN_MEDIUM,
12  FAN_ON,
13  PRESET_AWAY,
14  PRESET_BOOST,
15  HVACAction,
16  HVACMode,
17 )
18 from homeassistant.components.lock import LockState
19 from homeassistant.const import (
20  CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
21  CONCENTRATION_PARTS_PER_MILLION,
22  CURRENCY_CENT,
23  CURRENCY_DOLLAR,
24  DEGREE,
25  LIGHT_LUX,
26  PERCENTAGE,
27  REVOLUTIONS_PER_MINUTE,
28  SERVICE_LOCK,
29  SERVICE_UNLOCK,
30  SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
31  STATE_CLOSED,
32  STATE_CLOSING,
33  STATE_OFF,
34  STATE_ON,
35  STATE_OPEN,
36  STATE_OPENING,
37  STATE_PROBLEM,
38  STATE_UNKNOWN,
39  UV_INDEX,
40  Platform,
41  UnitOfApparentPower,
42  UnitOfElectricCurrent,
43  UnitOfElectricPotential,
44  UnitOfEnergy,
45  UnitOfFrequency,
46  UnitOfIrradiance,
47  UnitOfLength,
48  UnitOfMass,
49  UnitOfPower,
50  UnitOfPressure,
51  UnitOfReactivePower,
52  UnitOfSoundPressure,
53  UnitOfSpeed,
54  UnitOfTemperature,
55  UnitOfTime,
56  UnitOfVolume,
57  UnitOfVolumeFlowRate,
58  UnitOfVolumetricFlux,
59 )
60 
61 _LOGGER = logging.getLogger(__package__)
62 
63 DOMAIN = "isy994"
64 
65 MANUFACTURER = "Universal Devices, Inc"
66 
67 CONF_NETWORK = "network"
68 CONF_IGNORE_STRING = "ignore_string"
69 CONF_SENSOR_STRING = "sensor_string"
70 CONF_VAR_SENSOR_STRING = "variable_sensor_string"
71 CONF_TLS_VER = "tls"
72 CONF_RESTORE_LIGHT_STATE = "restore_light_state"
73 
74 DEFAULT_IGNORE_STRING = "{IGNORE ME}"
75 DEFAULT_SENSOR_STRING = "sensor"
76 DEFAULT_RESTORE_LIGHT_STATE = False
77 DEFAULT_TLS_VERSION = 1.1
78 DEFAULT_PROGRAM_STRING = "HA."
79 DEFAULT_VAR_SENSOR_STRING = "HA."
80 
81 KEY_ACTIONS = "actions"
82 KEY_STATUS = "status"
83 
84 NODE_PLATFORMS = [
85  Platform.BINARY_SENSOR,
86  Platform.CLIMATE,
87  Platform.COVER,
88  Platform.FAN,
89  Platform.LIGHT,
90  Platform.LOCK,
91  Platform.SENSOR,
92  Platform.SWITCH,
93 ]
94 NODE_AUX_PROP_PLATFORMS = [
95  Platform.NUMBER,
96  Platform.SELECT,
97  Platform.SENSOR,
98  Platform.SWITCH,
99 ]
100 PROGRAM_PLATFORMS = [
101  Platform.BINARY_SENSOR,
102  Platform.COVER,
103  Platform.FAN,
104  Platform.LOCK,
105  Platform.SWITCH,
106 ]
107 ROOT_NODE_PLATFORMS = [Platform.BUTTON]
108 VARIABLE_PLATFORMS = [Platform.NUMBER, Platform.SENSOR]
109 
110 # Set of all platforms used by integration
111 PLATFORMS = {
112  *NODE_PLATFORMS,
113  *NODE_AUX_PROP_PLATFORMS,
114  *PROGRAM_PLATFORMS,
115  *ROOT_NODE_PLATFORMS,
116  *VARIABLE_PLATFORMS,
117 }
118 
119 SUPPORTED_BIN_SENS_CLASSES = ["moisture", "opening", "motion", "climate"]
120 
121 # ISY Scenes are more like Switches than Home Assistant Scenes
122 # (they can turn off, and report their state)
123 ISY_GROUP_PLATFORM = Platform.SWITCH
124 
125 ISY_CONF_UUID = "uuid"
126 ISY_CONF_NAME = "name"
127 ISY_CONF_MODEL = "model"
128 ISY_CONF_FIRMWARE = "firmware"
129 
130 ISY_CONN_PORT = "port"
131 ISY_CONN_ADDRESS = "addr"
132 ISY_CONN_TLS = "tls"
133 
134 FILTER_UOM = "uom"
135 FILTER_STATES = "states"
136 FILTER_NODE_DEF_ID = "node_def_id"
137 FILTER_INSTEON_TYPE = "insteon_type"
138 FILTER_ZWAVE_CAT = "zwave_cat"
139 
140 # Special Subnodes for some Insteon Devices
141 SUBNODE_CLIMATE_COOL = 2
142 SUBNODE_CLIMATE_HEAT = 3
143 SUBNODE_DUSK_DAWN = 2
144 SUBNODE_EZIO2X4_SENSORS = [9, 10, 11, 12]
145 SUBNODE_FANLINC_LIGHT = 1
146 SUBNODE_HEARTBEAT = 4
147 SUBNODE_IOLINC_RELAY = 2
148 SUBNODE_LOW_BATTERY = 3
149 SUBNODE_MOTION_DISABLED = (13, 19) # Int->13 or Hex->0xD depending on firmware
150 SUBNODE_NEGATIVE = 2
151 SUBNODE_TAMPER = (10, 16) # Int->10 or Hex->0xA depending on firmware
152 
153 # Generic Insteon Type Categories for Filters
154 TYPE_CATEGORY_CONTROLLERS = "0."
155 TYPE_CATEGORY_DIMMABLE = "1."
156 TYPE_CATEGORY_SWITCHED = "2."
157 TYPE_CATEGORY_IRRIGATION = "4."
158 TYPE_CATEGORY_CLIMATE = "5."
159 TYPE_CATEGORY_POOL_CTL = "6."
160 TYPE_CATEGORY_SENSOR_ACTUATORS = "7."
161 TYPE_CATEGORY_ENERGY_MGMT = "9."
162 TYPE_CATEGORY_COVER = "14."
163 TYPE_CATEGORY_LOCK = "15."
164 TYPE_CATEGORY_SAFETY = "16."
165 TYPE_CATEGORY_X10 = "113."
166 
167 TYPE_EZIO2X4 = "7.3.255."
168 TYPE_INSTEON_MOTION = ("16.1.", "16.22.")
169 
170 # Used for discovery
171 UDN_UUID_PREFIX = "uuid:"
172 ISY_URL_POSTFIX = "/desc"
173 EVENTS_SUFFIX = "_ISYSUB"
174 
175 # Special Units of Measure
176 UOM_ISYV4_DEGREES = "degrees"
177 UOM_ISYV4_NONE = "n/a"
178 
179 UOM_ISY_CELSIUS = 1
180 UOM_ISY_FAHRENHEIT = 2
181 
182 UOM_8_BIT_RANGE = "100"
183 UOM_BARRIER = "97"
184 UOM_DOUBLE_TEMP = "101"
185 UOM_HVAC_ACTIONS = "66"
186 UOM_HVAC_MODE_GENERIC = "67"
187 UOM_HVAC_MODE_INSTEON = "98"
188 UOM_FAN_MODES = "99"
189 UOM_INDEX = "25"
190 UOM_ON_OFF = "2"
191 UOM_PERCENTAGE = "51"
192 
193 # Do not use the Home Assistant consts for the states here - we're matching exact API
194 # responses, not using them for Home Assistant states
195 # Insteon Types: https://www.universal-devices.com/developers/wsdk/5.0.4/1_fam.xml
196 # Z-Wave Categories: https://www.universal-devices.com/developers/wsdk/5.0.4/4_fam.xml
197 NODE_FILTERS: dict[Platform, dict[str, list[str]]] = {
198  Platform.BINARY_SENSOR: {
199  FILTER_UOM: [UOM_ON_OFF],
200  FILTER_STATES: [],
201  FILTER_NODE_DEF_ID: [
202  "BinaryAlarm",
203  "BinaryAlarm_ADV",
204  "BinaryControl",
205  "BinaryControl_ADV",
206  "EZIO2x4_Input",
207  "EZRAIN_Input",
208  "OnOffControl",
209  "OnOffControl_ADV",
210  ],
211  FILTER_INSTEON_TYPE: [
212  "7.0.",
213  "7.13.",
214  TYPE_CATEGORY_SAFETY,
215  ], # Does a startswith() match; include the dot
216  FILTER_ZWAVE_CAT: (["104", "112", "138", *map(str, range(148, 180))]),
217  },
218  Platform.SENSOR: {
219  # This is just a more-readable way of including MOST uoms between 1-100
220  # (Remember that range() is non-inclusive of the stop value)
221  FILTER_UOM: (
222  [
223  "1",
224  *map(str, range(3, 11)),
225  *map(str, range(12, 51)),
226  *map(str, range(52, 66)),
227  *map(str, range(69, 78)),
228  "79",
229  *map(str, range(82, 97)),
230  ]
231  ),
232  FILTER_STATES: [],
233  FILTER_NODE_DEF_ID: [
234  "IMETER_SOLO",
235  "EZIO2x4_Input_ADV",
236  "KeypadButton",
237  "KeypadButton_ADV",
238  "RemoteLinc2",
239  "RemoteLinc2_ADV",
240  ],
241  FILTER_INSTEON_TYPE: ["0.16.", "0.17.", "0.18.", "9.0.", "9.7."],
242  FILTER_ZWAVE_CAT: (["118", "143", *map(str, range(180, 186))]),
243  },
244  Platform.LOCK: {
245  FILTER_UOM: ["11"],
246  FILTER_STATES: ["locked", "unlocked"],
247  FILTER_NODE_DEF_ID: ["DoorLock"],
248  FILTER_INSTEON_TYPE: [TYPE_CATEGORY_LOCK, "4.64."],
249  FILTER_ZWAVE_CAT: ["111"],
250  },
251  Platform.FAN: {
252  FILTER_UOM: [],
253  FILTER_STATES: ["off", "low", "med", "high"],
254  FILTER_NODE_DEF_ID: ["FanLincMotor"],
255  FILTER_INSTEON_TYPE: ["1.46."],
256  FILTER_ZWAVE_CAT: [],
257  },
258  Platform.COVER: {
259  FILTER_UOM: [UOM_BARRIER],
260  FILTER_STATES: ["open", "closed", "closing", "opening", "stopped"],
261  FILTER_NODE_DEF_ID: ["DimmerMotorSwitch_ADV"],
262  FILTER_INSTEON_TYPE: [TYPE_CATEGORY_COVER],
263  FILTER_ZWAVE_CAT: ["106", "107"],
264  },
265  Platform.LIGHT: {
266  FILTER_UOM: ["51"],
267  FILTER_STATES: ["on", "off", "%"],
268  FILTER_NODE_DEF_ID: [
269  "BallastRelayLampSwitch",
270  "BallastRelayLampSwitch_ADV",
271  "DimmerLampOnly",
272  "DimmerLampSwitch",
273  "DimmerLampSwitch_ADV",
274  "DimmerSwitchOnly",
275  "DimmerSwitchOnly_ADV",
276  "KeypadDimmer",
277  "KeypadDimmer_ADV",
278  ],
279  FILTER_INSTEON_TYPE: [TYPE_CATEGORY_DIMMABLE],
280  FILTER_ZWAVE_CAT: ["109", "119"],
281  },
282  Platform.SWITCH: {
283  FILTER_UOM: ["78"],
284  FILTER_STATES: ["on", "off"],
285  FILTER_NODE_DEF_ID: [
286  "AlertModuleArmed",
287  "AlertModuleSiren",
288  "AlertModuleSiren_ADV",
289  "EZIO2x4_Output",
290  "EZRAIN_Output",
291  "KeypadRelay",
292  "KeypadRelay_ADV",
293  "RelayLampOnly",
294  "RelayLampOnly_ADV",
295  "RelayLampSwitch",
296  "RelayLampSwitch_ADV",
297  "RelaySwitchOnlyPlusQuery",
298  "RelaySwitchOnlyPlusQuery_ADV",
299  "Siren",
300  "Siren_ADV",
301  "X10",
302  ],
303  FILTER_INSTEON_TYPE: [
304  TYPE_CATEGORY_SWITCHED,
305  "7.3.255.",
306  "9.10.",
307  "9.11.",
308  TYPE_CATEGORY_X10,
309  ],
310  FILTER_ZWAVE_CAT: ["121", "122", "123", "137", "141", "147"],
311  },
312  Platform.CLIMATE: {
313  FILTER_UOM: [UOM_ON_OFF],
314  FILTER_STATES: ["heating", "cooling", "idle", "fan_only", "off"],
315  FILTER_NODE_DEF_ID: ["TempLinc", "Thermostat"],
316  FILTER_INSTEON_TYPE: ["4.8", TYPE_CATEGORY_CLIMATE],
317  FILTER_ZWAVE_CAT: ["140"],
318  },
319 }
320 NODE_AUX_FILTERS: dict[str, Platform] = {
321  PROP_ON_LEVEL: Platform.NUMBER,
322  PROP_RAMP_RATE: Platform.SELECT,
323 }
324 
325 UOM_FRIENDLY_NAME = {
326  "1": UnitOfElectricCurrent.AMPERE,
327  UOM_ON_OFF: "", # Binary, no unit
328  "3": UnitOfPower.BTU_PER_HOUR,
329  "4": UnitOfTemperature.CELSIUS,
330  "5": UnitOfLength.CENTIMETERS,
331  "6": UnitOfVolume.CUBIC_FEET,
332  "7": UnitOfVolumeFlowRate.CUBIC_FEET_PER_MINUTE,
333  "8": UnitOfVolume.CUBIC_METERS,
334  "9": UnitOfTime.DAYS,
335  "10": UnitOfTime.DAYS,
336  "12": UnitOfSoundPressure.DECIBEL,
337  "13": UnitOfSoundPressure.WEIGHTED_DECIBEL_A,
338  "14": DEGREE,
339  "16": "macroseismic",
340  "17": UnitOfTemperature.FAHRENHEIT,
341  "18": UnitOfLength.FEET,
342  "19": UnitOfTime.HOURS,
343  "20": UnitOfTime.HOURS,
344  "21": PERCENTAGE,
345  "22": PERCENTAGE,
346  "23": UnitOfPressure.INHG,
347  "24": UnitOfVolumetricFlux.INCHES_PER_HOUR,
348  UOM_INDEX: UOM_INDEX, # Index type. Use "node.formatted" for value
349  "26": UnitOfTemperature.KELVIN,
350  "27": "keyword",
351  "28": UnitOfMass.KILOGRAMS,
352  "29": "kV",
353  "30": UnitOfPower.KILO_WATT,
354  "31": UnitOfPressure.KPA,
355  "32": UnitOfSpeed.KILOMETERS_PER_HOUR,
356  "33": UnitOfEnergy.KILO_WATT_HOUR,
357  "34": "liedu",
358  "35": UnitOfVolume.LITERS,
359  "36": LIGHT_LUX,
360  "37": "mercalli",
361  "38": UnitOfLength.METERS,
362  "39": UnitOfVolumeFlowRate.CUBIC_METERS_PER_HOUR,
363  "40": UnitOfSpeed.METERS_PER_SECOND,
364  "41": UnitOfElectricCurrent.MILLIAMPERE,
365  "42": UnitOfTime.MILLISECONDS,
366  "43": UnitOfElectricPotential.MILLIVOLT,
367  "44": UnitOfTime.MINUTES,
368  "45": UnitOfTime.MINUTES,
369  "46": UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR,
370  "47": UnitOfTime.MONTHS,
371  "48": UnitOfSpeed.MILES_PER_HOUR,
372  "49": UnitOfSpeed.METERS_PER_SECOND,
373  "50": "Ω",
374  UOM_PERCENTAGE: PERCENTAGE,
375  "52": UnitOfMass.POUNDS,
376  "53": "pf",
377  "54": CONCENTRATION_PARTS_PER_MILLION,
378  "55": "pulse count",
379  "57": UnitOfTime.SECONDS,
380  "58": UnitOfTime.SECONDS,
381  "59": "S/m",
382  "60": "m_b",
383  "61": "M_L",
384  "62": "M_w",
385  "63": "M_S",
386  "64": "shindo",
387  "65": "SML",
388  "69": UnitOfVolume.GALLONS,
389  "71": UV_INDEX,
390  "72": UnitOfElectricPotential.VOLT,
391  "73": UnitOfPower.WATT,
392  "74": UnitOfIrradiance.WATTS_PER_SQUARE_METER,
393  "75": "weekday",
394  "76": DEGREE,
395  "77": UnitOfTime.YEARS,
396  "82": UnitOfLength.MILLIMETERS,
397  "83": UnitOfLength.KILOMETERS,
398  "85": "Ω",
399  "86": "kΩ",
400  "87": f"{UnitOfVolume.CUBIC_METERS}/{UnitOfVolume.CUBIC_METERS}",
401  "88": "Water activity",
402  "89": REVOLUTIONS_PER_MINUTE,
403  "90": UnitOfFrequency.HERTZ,
404  "91": DEGREE,
405  "92": f"{DEGREE} South",
406  UOM_8_BIT_RANGE: "", # Range 0-255, no unit.
407  UOM_DOUBLE_TEMP: UOM_DOUBLE_TEMP,
408  "102": "kWs", # Kilowatt Seconds
409  "103": CURRENCY_DOLLAR,
410  "104": CURRENCY_CENT,
411  "105": UnitOfLength.INCHES,
412  "106": UnitOfVolumetricFlux.MILLIMETERS_PER_DAY,
413  "107": "", # raw 1-byte unsigned value
414  "108": "", # raw 2-byte unsigned value
415  "109": "", # raw 3-byte unsigned value
416  "110": "", # raw 4-byte unsigned value
417  "111": "", # raw 1-byte signed value
418  "112": "", # raw 2-byte signed value
419  "113": "", # raw 3-byte signed value
420  "114": "", # raw 4-byte signed value
421  "116": UnitOfLength.MILES,
422  "117": UnitOfPressure.MBAR,
423  "118": UnitOfPressure.HPA,
424  "119": UnitOfEnergy.WATT_HOUR,
425  "120": UnitOfVolumetricFlux.INCHES_PER_DAY,
426  "122": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, # Microgram per cubic meter
427  "123": f"bq/{UnitOfVolume.CUBIC_METERS}", # Becquerel per cubic meter
428  "124": f"pCi/{UnitOfVolume.LITERS}", # Picocuries per liter
429  "125": "pH",
430  "126": "bpm", # Beats per Minute
431  "127": UnitOfPressure.MMHG,
432  "128": "J",
433  "129": "BMI", # Body Mass Index
434  "130": f"{UnitOfVolume.LITERS}/{UnitOfTime.HOURS}",
435  "131": SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
436  "132": "bpm", # Breaths per minute
437  "133": UnitOfFrequency.KILOHERTZ,
438  "134": f"{UnitOfLength.METERS}/{UnitOfTime.SECONDS}²",
439  "135": UnitOfApparentPower.VOLT_AMPERE, # Volt-Amp
440  "136": UnitOfReactivePower.VOLT_AMPERE_REACTIVE, # VAR = Volt-Amp Reactive
441  "137": "", # NTP DateTime - Number of seconds since 1900
442  "138": UnitOfPressure.PSI,
443  "139": DEGREE, # Degree 0-360
444  "140": f"{UnitOfMass.MILLIGRAMS}/{UnitOfVolume.LITERS}",
445  "141": "N", # Netwon
446  "142": f"{UnitOfVolume.GALLONS}/{UnitOfTime.SECONDS}",
447  "143": "gpm", # Gallon per Minute
448  "144": "gph", # Gallon per Hour
449 }
450 
451 UOM_TO_STATES = {
452  "11": { # Deadbolt Status
453  0: LockState.UNLOCKED,
454  100: LockState.LOCKED,
455  101: STATE_UNKNOWN,
456  102: STATE_PROBLEM,
457  },
458  "15": { # Door Lock Alarm
459  1: "master code changed",
460  2: "tamper code entry limit",
461  3: "escutcheon removed",
462  4: "key/manually locked",
463  5: "locked by touch",
464  6: "key/manually unlocked",
465  7: "remote locking jammed bolt",
466  8: "remotely locked",
467  9: "remotely unlocked",
468  10: "deadbolt jammed",
469  11: "battery too low to operate",
470  12: "critical low battery",
471  13: "low battery",
472  14: "automatically locked",
473  15: "automatic locking jammed bolt",
474  16: "remotely power cycled",
475  17: "lock handling complete",
476  19: "user deleted",
477  20: "user added",
478  21: "duplicate pin",
479  22: "jammed bolt by locking with keypad",
480  23: "locked by keypad",
481  24: "unlocked by keypad",
482  25: "keypad attempt outside schedule",
483  26: "hardware failure",
484  27: "factory reset",
485  },
486  UOM_HVAC_ACTIONS: { # Thermostat Heat/Cool State
487  0: HVACAction.IDLE.value,
488  1: HVACAction.HEATING.value,
489  2: HVACAction.COOLING.value,
490  3: HVACAction.FAN.value,
491  4: HVACAction.HEATING.value, # Pending Heat
492  5: HVACAction.COOLING.value, # Pending Cool
493  # >6 defined in ISY but not implemented, leaving for future expanision.
494  6: HVACAction.IDLE.value,
495  7: HVACAction.HEATING.value,
496  8: HVACAction.HEATING.value,
497  9: HVACAction.COOLING.value,
498  10: HVACAction.HEATING.value,
499  11: HVACAction.HEATING.value,
500  },
501  UOM_HVAC_MODE_GENERIC: { # Thermostat Mode
502  0: HVACMode.OFF.value,
503  1: HVACMode.HEAT.value,
504  2: HVACMode.COOL.value,
505  3: HVACMode.AUTO.value,
506  4: PRESET_BOOST,
507  5: "resume",
508  6: HVACMode.FAN_ONLY.value,
509  7: "furnace",
510  8: HVACMode.DRY.value,
511  9: "moist air",
512  10: "auto changeover",
513  11: "energy save heat",
514  12: "energy save cool",
515  13: PRESET_AWAY,
516  14: HVACMode.AUTO.value,
517  15: HVACMode.AUTO.value,
518  16: HVACMode.AUTO.value,
519  },
520  "68": { # Thermostat Fan Mode
521  0: FAN_AUTO,
522  1: FAN_ON,
523  2: FAN_HIGH, # Auto High
524  3: FAN_HIGH,
525  4: FAN_MEDIUM, # Auto Medium
526  5: FAN_MEDIUM,
527  6: "circulation",
528  7: "humidity circulation",
529  },
530  "78": {0: STATE_OFF, 100: STATE_ON}, # 0-Off 100-On
531  "79": {0: STATE_OPEN, 100: STATE_CLOSED}, # 0-Open 100-Close
532  "80": { # Thermostat Fan Run State
533  0: STATE_OFF,
534  1: STATE_ON,
535  2: "on high",
536  3: "on medium",
537  4: "circulation",
538  5: "humidity circulation",
539  6: "right/left circulation",
540  7: "up/down circulation",
541  8: "quiet circulation",
542  },
543  "84": {0: SERVICE_LOCK, 1: SERVICE_UNLOCK}, # Secure Mode
544  "93": { # Power Management Alarm
545  1: "power applied",
546  2: "ac mains disconnected",
547  3: "ac mains reconnected",
548  4: "surge detection",
549  5: "volt drop or drift",
550  6: "over current detected",
551  7: "over voltage detected",
552  8: "over load detected",
553  9: "load error",
554  10: "replace battery soon",
555  11: "replace battery now",
556  12: "battery is charging",
557  13: "battery is fully charged",
558  14: "charge battery soon",
559  15: "charge battery now",
560  },
561  "94": { # Appliance Alarm
562  1: "program started",
563  2: "program in progress",
564  3: "program completed",
565  4: "replace main filter",
566  5: "failure to set target temperature",
567  6: "supplying water",
568  7: "water supply failure",
569  8: "boiling",
570  9: "boiling failure",
571  10: "washing",
572  11: "washing failure",
573  12: "rinsing",
574  13: "rinsing failure",
575  14: "draining",
576  15: "draining failure",
577  16: "spinning",
578  17: "spinning failure",
579  18: "drying",
580  19: "drying failure",
581  20: "fan failure",
582  21: "compressor failure",
583  },
584  "95": { # Home Health Alarm
585  1: "leaving bed",
586  2: "sitting on bed",
587  3: "lying on bed",
588  4: "posture changed",
589  5: "sitting on edge of bed",
590  },
591  "96": { # VOC Level
592  1: "clean",
593  2: "slightly polluted",
594  3: "moderately polluted",
595  4: "highly polluted",
596  },
597  UOM_BARRIER: { # Barrier Status
598  0: STATE_CLOSED,
599  100: STATE_OPEN,
600  101: STATE_UNKNOWN,
601  102: "stopped",
602  103: STATE_CLOSING,
603  104: STATE_OPENING,
604  **{
605  b: f"{b} %" for a, b in enumerate(list(range(1, 100)))
606  }, # 1-99 are percentage open
607  },
608  UOM_HVAC_MODE_INSTEON: { # Insteon Thermostat Mode
609  0: HVACMode.OFF.value,
610  1: HVACMode.HEAT.value,
611  2: HVACMode.COOL.value,
612  3: HVACMode.HEAT_COOL.value,
613  4: HVACMode.FAN_ONLY.value,
614  5: HVACMode.AUTO.value, # Program Auto
615  6: HVACMode.AUTO.value, # Program Heat-Set @ Local Device Only
616  7: HVACMode.AUTO.value, # Program Cool-Set @ Local Device Only
617  },
618  UOM_FAN_MODES: {7: FAN_ON, 8: FAN_AUTO}, # Insteon Thermostat Fan Mode
619  "115": { # Most recent On style action taken for lamp control
620  0: "on",
621  1: "off",
622  2: "fade up",
623  3: "fade down",
624  4: "fade stop",
625  5: "fast on",
626  6: "fast off",
627  7: "triple press on",
628  8: "triple press off",
629  9: "4x press on",
630  10: "4x press off",
631  11: "5x press on",
632  12: "5x press off",
633  },
634 }
635 
636 ISY_HVAC_MODES = [
637  HVACMode.OFF,
638  HVACMode.HEAT,
639  HVACMode.COOL,
640  HVACMode.HEAT_COOL,
641  HVACMode.AUTO,
642  HVACMode.FAN_ONLY,
643 ]
644 
645 HA_HVAC_TO_ISY = {
646  HVACMode.OFF: "off",
647  HVACMode.HEAT: "heat",
648  HVACMode.COOL: "cool",
649  HVACMode.HEAT_COOL: "auto",
650  HVACMode.FAN_ONLY: "fan_only",
651  HVACMode.AUTO: "program_auto",
652 }
653 
654 HA_FAN_TO_ISY = {FAN_ON: "on", FAN_AUTO: "auto"}
655 
656 BINARY_SENSOR_DEVICE_TYPES_ISY = {
657  BinarySensorDeviceClass.MOISTURE: ["16.8.", "16.13.", "16.14."],
658  BinarySensorDeviceClass.OPENING: [
659  "16.9.",
660  "16.6.",
661  "16.7.",
662  "16.2.",
663  "16.17.",
664  "16.20.",
665  "16.21.",
666  ],
667  BinarySensorDeviceClass.MOTION: ["16.1.", "16.4.", "16.5.", "16.3.", "16.22."],
668 }
669 
670 BINARY_SENSOR_DEVICE_TYPES_ZWAVE = {
671  BinarySensorDeviceClass.SAFETY: ["137", "172", "176", "177", "178"],
672  BinarySensorDeviceClass.SMOKE: ["138", "156"],
673  BinarySensorDeviceClass.PROBLEM: ["148", "149", "157", "158", "164", "174", "175"],
674  BinarySensorDeviceClass.GAS: ["150", "151"],
675  BinarySensorDeviceClass.SOUND: ["153"],
676  BinarySensorDeviceClass.COLD: ["152", "168"],
677  BinarySensorDeviceClass.HEAT: ["154", "166", "167"],
678  BinarySensorDeviceClass.MOISTURE: ["159", "169"],
679  BinarySensorDeviceClass.DOOR: ["160"],
680  BinarySensorDeviceClass.BATTERY: ["162"],
681  BinarySensorDeviceClass.MOTION: ["155"],
682  BinarySensorDeviceClass.VIBRATION: ["173"],
683 }
684 
685 
686 SCHEME_HTTP = "http"
687 HTTP_PORT = 80
688 SCHEME_HTTPS = "https"
689 HTTPS_PORT = 443