ElkM1 integration updates for new version of base library (#71508)

Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
Glenn Waters 2022-05-11 22:32:19 -04:00 committed by GitHub
parent 19168227eb
commit a03a4b0d13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 82 additions and 88 deletions

View File

@ -205,18 +205,18 @@ class ElkArea(ElkAttachedEntity, AlarmControlPanelEntity, RestoreEntity):
def _element_changed(self, element: Element, changeset: dict[str, Any]) -> None:
elk_state_to_hass_state = {
ArmedStatus.DISARMED.value: STATE_ALARM_DISARMED,
ArmedStatus.ARMED_AWAY.value: STATE_ALARM_ARMED_AWAY,
ArmedStatus.ARMED_STAY.value: STATE_ALARM_ARMED_HOME,
ArmedStatus.ARMED_STAY_INSTANT.value: STATE_ALARM_ARMED_HOME,
ArmedStatus.ARMED_TO_NIGHT.value: STATE_ALARM_ARMED_NIGHT,
ArmedStatus.ARMED_TO_NIGHT_INSTANT.value: STATE_ALARM_ARMED_NIGHT,
ArmedStatus.ARMED_TO_VACATION.value: STATE_ALARM_ARMED_AWAY,
ArmedStatus.DISARMED: STATE_ALARM_DISARMED,
ArmedStatus.ARMED_AWAY: STATE_ALARM_ARMED_AWAY,
ArmedStatus.ARMED_STAY: STATE_ALARM_ARMED_HOME,
ArmedStatus.ARMED_STAY_INSTANT: STATE_ALARM_ARMED_HOME,
ArmedStatus.ARMED_TO_NIGHT: STATE_ALARM_ARMED_NIGHT,
ArmedStatus.ARMED_TO_NIGHT_INSTANT: STATE_ALARM_ARMED_NIGHT,
ArmedStatus.ARMED_TO_VACATION: STATE_ALARM_ARMED_AWAY,
}
if self._element.alarm_state is None:
self._state = None
elif self._element.alarm_state >= AlarmState.FIRE_ALARM.value:
elif self._element.in_alarm_state():
# Area is in alarm state
self._state = STATE_ALARM_TRIGGERED
elif self._entry_exit_timer_is_running():
@ -239,32 +239,32 @@ class ElkArea(ElkAttachedEntity, AlarmControlPanelEntity, RestoreEntity):
async def async_alarm_arm_home(self, code: str | None = None) -> None:
"""Send arm home command."""
if code is not None:
self._element.arm(ArmLevel.ARMED_STAY.value, int(code))
self._element.arm(ArmLevel.ARMED_STAY, int(code))
async def async_alarm_arm_away(self, code: str | None = None) -> None:
"""Send arm away command."""
if code is not None:
self._element.arm(ArmLevel.ARMED_AWAY.value, int(code))
self._element.arm(ArmLevel.ARMED_AWAY, int(code))
async def async_alarm_arm_night(self, code: str | None = None) -> None:
"""Send arm night command."""
if code is not None:
self._element.arm(ArmLevel.ARMED_NIGHT.value, int(code))
self._element.arm(ArmLevel.ARMED_NIGHT, int(code))
async def async_alarm_arm_home_instant(self, code: str | None = None) -> None:
"""Send arm stay instant command."""
if code is not None:
self._element.arm(ArmLevel.ARMED_STAY_INSTANT.value, int(code))
self._element.arm(ArmLevel.ARMED_STAY_INSTANT, int(code))
async def async_alarm_arm_night_instant(self, code: str | None = None) -> None:
"""Send arm night instant command."""
if code is not None:
self._element.arm(ArmLevel.ARMED_NIGHT_INSTANT.value, int(code))
self._element.arm(ArmLevel.ARMED_NIGHT_INSTANT, int(code))
async def async_alarm_arm_vacation(self, code: str | None = None) -> None:
"""Send arm vacation command."""
if code is not None:
self._element.arm(ArmLevel.ARMED_VACATION.value, int(code))
self._element.arm(ArmLevel.ARMED_VACATION, int(code))
async def async_display_message(
self, clear: int, beep: bool, timeout: int, line1: str, line2: str

View File

@ -33,26 +33,26 @@ SUPPORT_HVAC = [
HVACMode.FAN_ONLY,
]
HASS_TO_ELK_HVAC_MODES = {
HVACMode.OFF: (ThermostatMode.OFF.value, ThermostatFan.AUTO.value),
HVACMode.HEAT: (ThermostatMode.HEAT.value, None),
HVACMode.COOL: (ThermostatMode.COOL.value, None),
HVACMode.HEAT_COOL: (ThermostatMode.AUTO.value, None),
HVACMode.FAN_ONLY: (ThermostatMode.OFF.value, ThermostatFan.ON.value),
HVACMode.OFF: (ThermostatMode.OFF, ThermostatFan.AUTO),
HVACMode.HEAT: (ThermostatMode.HEAT, None),
HVACMode.COOL: (ThermostatMode.COOL, None),
HVACMode.HEAT_COOL: (ThermostatMode.AUTO, None),
HVACMode.FAN_ONLY: (ThermostatMode.OFF, ThermostatFan.ON),
}
ELK_TO_HASS_HVAC_MODES = {
ThermostatMode.OFF.value: HVACMode.OFF,
ThermostatMode.COOL.value: HVACMode.COOL,
ThermostatMode.HEAT.value: HVACMode.HEAT,
ThermostatMode.EMERGENCY_HEAT.value: HVACMode.HEAT,
ThermostatMode.AUTO.value: HVACMode.HEAT_COOL,
ThermostatMode.OFF: HVACMode.OFF,
ThermostatMode.COOL: HVACMode.COOL,
ThermostatMode.HEAT: HVACMode.HEAT,
ThermostatMode.EMERGENCY_HEAT: HVACMode.HEAT,
ThermostatMode.AUTO: HVACMode.HEAT_COOL,
}
HASS_TO_ELK_FAN_MODES = {
FAN_AUTO: (None, ThermostatFan.AUTO.value),
FAN_ON: (None, ThermostatFan.ON.value),
FAN_AUTO: (None, ThermostatFan.AUTO),
FAN_ON: (None, ThermostatFan.ON),
}
ELK_TO_HASS_FAN_MODES = {
ThermostatFan.AUTO.value: FAN_AUTO,
ThermostatFan.ON.value: FAN_ON,
ThermostatFan.AUTO: FAN_AUTO,
ThermostatFan.ON: FAN_ON,
}
@ -84,7 +84,7 @@ class ElkThermostat(ElkEntity, ClimateEntity):
def __init__(self, element: Element, elk: Elk, elk_data: dict[str, Any]) -> None:
"""Initialize climate entity."""
super().__init__(element, elk, elk_data)
self._state: str = HVACMode.OFF
self._state: str | None = None
@property
def temperature_unit(self) -> str:
@ -100,11 +100,11 @@ class ElkThermostat(ElkEntity, ClimateEntity):
def target_temperature(self) -> float | None:
"""Return the temperature we are trying to reach."""
if self._element.mode in (
ThermostatMode.HEAT.value,
ThermostatMode.EMERGENCY_HEAT.value,
ThermostatMode.HEAT,
ThermostatMode.EMERGENCY_HEAT,
):
return self._element.heat_setpoint
if self._element.mode == ThermostatMode.COOL.value:
if self._element.mode == ThermostatMode.COOL:
return self._element.cool_setpoint
return None
@ -129,7 +129,7 @@ class ElkThermostat(ElkEntity, ClimateEntity):
return self._element.humidity
@property
def hvac_mode(self) -> str:
def hvac_mode(self) -> str | None:
"""Return current operation ie. heat, cool, idle."""
return self._state
@ -146,7 +146,7 @@ class ElkThermostat(ElkEntity, ClimateEntity):
@property
def is_aux_heat(self) -> bool:
"""Return if aux heater is on."""
return self._element.mode == ThermostatMode.EMERGENCY_HEAT.value
return self._element.mode == ThermostatMode.EMERGENCY_HEAT
@property
def min_temp(self) -> float:
@ -159,15 +159,17 @@ class ElkThermostat(ElkEntity, ClimateEntity):
return 99
@property
def fan_mode(self) -> str:
def fan_mode(self) -> str | None:
"""Return the fan setting."""
if self._element.fan is None:
return None
return ELK_TO_HASS_FAN_MODES[self._element.fan]
def _elk_set(self, mode: int | None, fan: int | None) -> None:
def _elk_set(self, mode: ThermostatMode | None, fan: ThermostatFan | None) -> None:
if mode is not None:
self._element.set(ThermostatSetting.MODE.value, mode)
self._element.set(ThermostatSetting.MODE, mode)
if fan is not None:
self._element.set(ThermostatSetting.FAN.value, fan)
self._element.set(ThermostatSetting.FAN, fan)
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
"""Set thermostat operation mode."""
@ -176,11 +178,11 @@ class ElkThermostat(ElkEntity, ClimateEntity):
async def async_turn_aux_heat_on(self) -> None:
"""Turn auxiliary heater on."""
self._elk_set(ThermostatMode.EMERGENCY_HEAT.value, None)
self._elk_set(ThermostatMode.EMERGENCY_HEAT, None)
async def async_turn_aux_heat_off(self) -> None:
"""Turn auxiliary heater off."""
self._elk_set(ThermostatMode.HEAT.value, None)
self._elk_set(ThermostatMode.HEAT, None)
@property
def fan_modes(self) -> list[str]:
@ -197,11 +199,14 @@ class ElkThermostat(ElkEntity, ClimateEntity):
low_temp = kwargs.get(ATTR_TARGET_TEMP_LOW)
high_temp = kwargs.get(ATTR_TARGET_TEMP_HIGH)
if low_temp is not None:
self._element.set(ThermostatSetting.HEAT_SETPOINT.value, round(low_temp))
self._element.set(ThermostatSetting.HEAT_SETPOINT, round(low_temp))
if high_temp is not None:
self._element.set(ThermostatSetting.COOL_SETPOINT.value, round(high_temp))
self._element.set(ThermostatSetting.COOL_SETPOINT, round(high_temp))
def _element_changed(self, element: Element, changeset: Any) -> None:
if self._element.mode is None:
self._state = None
else:
self._state = ELK_TO_HASS_HVAC_MODES[self._element.mode]
if self._state == HVACMode.OFF and self._element.fan == ThermostatFan.ON.value:
if self._state == HVACMode.OFF and self._element.fan == ThermostatFan.ON:
self._state = HVACMode.FAN_ONLY

View File

@ -2,7 +2,7 @@
"domain": "elkm1",
"name": "Elk-M1 Control",
"documentation": "https://www.home-assistant.io/integrations/elkm1",
"requirements": ["elkm1-lib==1.3.5"],
"requirements": ["elkm1-lib==2.0.0"],
"dhcp": [{ "registered_devices": true }, { "macaddress": "00409D*" }],
"codeowners": ["@gwww", "@bdraco"],
"dependencies": ["network"],

View File

@ -3,12 +3,7 @@ from __future__ import annotations
from typing import Any
from elkm1_lib.const import (
SettingFormat,
ZoneLogicalStatus,
ZonePhysicalStatus,
ZoneType,
)
from elkm1_lib.const import SettingFormat, ZoneType
from elkm1_lib.counters import Counter
from elkm1_lib.elements import Element
from elkm1_lib.elk import Elk
@ -237,25 +232,25 @@ class ElkZone(ElkSensor):
def icon(self) -> str:
"""Icon to use in the frontend."""
zone_icons = {
ZoneType.FIRE_ALARM.value: "fire",
ZoneType.FIRE_VERIFIED.value: "fire",
ZoneType.FIRE_SUPERVISORY.value: "fire",
ZoneType.KEYFOB.value: "key",
ZoneType.NON_ALARM.value: "alarm-off",
ZoneType.MEDICAL_ALARM.value: "medical-bag",
ZoneType.POLICE_ALARM.value: "alarm-light",
ZoneType.POLICE_NO_INDICATION.value: "alarm-light",
ZoneType.KEY_MOMENTARY_ARM_DISARM.value: "power",
ZoneType.KEY_MOMENTARY_ARM_AWAY.value: "power",
ZoneType.KEY_MOMENTARY_ARM_STAY.value: "power",
ZoneType.KEY_MOMENTARY_DISARM.value: "power",
ZoneType.KEY_ON_OFF.value: "toggle-switch",
ZoneType.MUTE_AUDIBLES.value: "volume-mute",
ZoneType.POWER_SUPERVISORY.value: "power-plug",
ZoneType.TEMPERATURE.value: "thermometer-lines",
ZoneType.ANALOG_ZONE.value: "speedometer",
ZoneType.PHONE_KEY.value: "phone-classic",
ZoneType.INTERCOM_KEY.value: "deskphone",
ZoneType.FIRE_ALARM: "fire",
ZoneType.FIRE_VERIFIED: "fire",
ZoneType.FIRE_SUPERVISORY: "fire",
ZoneType.KEYFOB: "key",
ZoneType.NON_ALARM: "alarm-off",
ZoneType.MEDICAL_ALARM: "medical-bag",
ZoneType.POLICE_ALARM: "alarm-light",
ZoneType.POLICE_NO_INDICATION: "alarm-light",
ZoneType.KEY_MOMENTARY_ARM_DISARM: "power",
ZoneType.KEY_MOMENTARY_ARM_AWAY: "power",
ZoneType.KEY_MOMENTARY_ARM_STAY: "power",
ZoneType.KEY_MOMENTARY_DISARM: "power",
ZoneType.KEY_ON_OFF: "toggle-switch",
ZoneType.MUTE_AUDIBLES: "volume-mute",
ZoneType.POWER_SUPERVISORY: "power-plug",
ZoneType.TEMPERATURE: "thermometer-lines",
ZoneType.ANALOG_ZONE: "speedometer",
ZoneType.PHONE_KEY: "phone-classic",
ZoneType.INTERCOM_KEY: "deskphone",
}
return f"mdi:{zone_icons.get(self._element.definition, 'alarm-bell')}"
@ -263,13 +258,9 @@ class ElkZone(ElkSensor):
def extra_state_attributes(self) -> dict[str, Any]:
"""Attributes of the sensor."""
attrs: dict[str, Any] = self.initial_attrs()
attrs["physical_status"] = ZonePhysicalStatus(
self._element.physical_status
).name.lower()
attrs["logical_status"] = ZoneLogicalStatus(
self._element.logical_status
).name.lower()
attrs["definition"] = ZoneType(self._element.definition).name.lower()
attrs["physical_status"] = self._element.physical_status.name.lower()
attrs["logical_status"] = self._element.logical_status.name.lower()
attrs["definition"] = self._element.definition.name.lower()
attrs["area"] = self._element.area + 1
attrs["triggered_alarm"] = self._element.triggered_alarm
return attrs
@ -277,27 +268,25 @@ class ElkZone(ElkSensor):
@property
def temperature_unit(self) -> str | None:
"""Return the temperature unit."""
if self._element.definition == ZoneType.TEMPERATURE.value:
if self._element.definition == ZoneType.TEMPERATURE:
return self._temperature_unit
return None
@property
def native_unit_of_measurement(self) -> str | None:
"""Return the unit of measurement."""
if self._element.definition == ZoneType.TEMPERATURE.value:
if self._element.definition == ZoneType.TEMPERATURE:
return self._temperature_unit
if self._element.definition == ZoneType.ANALOG_ZONE.value:
if self._element.definition == ZoneType.ANALOG_ZONE:
return ELECTRIC_POTENTIAL_VOLT
return None
def _element_changed(self, _: Element, changeset: Any) -> None:
if self._element.definition == ZoneType.TEMPERATURE.value:
if self._element.definition == ZoneType.TEMPERATURE:
self._state = temperature_to_state(
self._element.temperature, UNDEFINED_TEMPERATURE
)
elif self._element.definition == ZoneType.ANALOG_ZONE.value:
elif self._element.definition == ZoneType.ANALOG_ZONE:
self._state = f"{self._element.voltage}"
else:
self._state = pretty_const(
ZoneLogicalStatus(self._element.logical_status).name
)
self._state = pretty_const(self._element.logical_status.name)

View File

@ -584,7 +584,7 @@ elgato==3.0.0
eliqonline==1.2.2
# homeassistant.components.elkm1
elkm1-lib==1.3.5
elkm1-lib==2.0.0
# homeassistant.components.elmax
elmax_api==0.0.2

View File

@ -418,7 +418,7 @@ dynalite_devices==0.1.46
elgato==3.0.0
# homeassistant.components.elkm1
elkm1-lib==1.3.5
elkm1-lib==2.0.0
# homeassistant.components.elmax
elmax_api==0.0.2