From b52c348dd252fb11c78a889b1c8b223c8c193147 Mon Sep 17 00:00:00 2001 From: Mick Vleeshouwer Date: Sun, 20 Feb 2022 22:16:20 +0100 Subject: [PATCH 01/10] Bump pyoverkiz --- custom_components/tahoma/manifest.json | 4 ++-- requirements.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/custom_components/tahoma/manifest.json b/custom_components/tahoma/manifest.json index b3034c08..b05f31ff 100644 --- a/custom_components/tahoma/manifest.json +++ b/custom_components/tahoma/manifest.json @@ -5,7 +5,7 @@ "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/tahoma", "requirements": [ - "pyoverkiz==1.3.3" + "pyoverkiz==1.3.5" ], "codeowners": [ "@imicknl", @@ -23,4 +23,4 @@ "macaddress": "F8811A*" } ] -} +} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 725d48f6..13438c05 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -pyoverkiz==1.3.3 \ No newline at end of file +pyoverkiz==1.3.5 \ No newline at end of file From 93e192e0793528b3d091875e6521fda642236813 Mon Sep 17 00:00:00 2001 From: Mick Vleeshouwer Date: Sun, 20 Feb 2022 22:27:08 +0100 Subject: [PATCH 02/10] Add alarm control panel --- .../tahoma/alarm_control_panel.py | 189 +----------------- .../tahoma/alarm_entities/__init__.py | 8 + .../stateful_alarm_controller.py | 72 +++++++ .../alarm_entities/tsk_alarm_controller.py | 70 +++++++ 4 files changed, 158 insertions(+), 181 deletions(-) create mode 100644 custom_components/tahoma/alarm_entities/__init__.py create mode 100644 custom_components/tahoma/alarm_entities/stateful_alarm_controller.py create mode 100644 custom_components/tahoma/alarm_entities/tsk_alarm_controller.py diff --git a/custom_components/tahoma/alarm_control_panel.py b/custom_components/tahoma/alarm_control_panel.py index 6fb45af7..816c9e13 100644 --- a/custom_components/tahoma/alarm_control_panel.py +++ b/custom_components/tahoma/alarm_control_panel.py @@ -1,201 +1,28 @@ -"""Support for Overkiz alarm control panels.""" +"""Support for Overkiz Alarms.""" from __future__ import annotations -from homeassistant.components.alarm_control_panel import AlarmControlPanelEntity -from homeassistant.components.alarm_control_panel.const import ( - SUPPORT_ALARM_ARM_AWAY, - SUPPORT_ALARM_ARM_CUSTOM_BYPASS, - SUPPORT_ALARM_ARM_HOME, - SUPPORT_ALARM_ARM_NIGHT, - SUPPORT_ALARM_TRIGGER, -) from homeassistant.config_entries import ConfigEntry -from homeassistant.const import ( - STATE_ALARM_ARMED_AWAY, - STATE_ALARM_ARMED_HOME, - STATE_ALARM_ARMED_NIGHT, - STATE_ALARM_DISARMED, - STATE_ALARM_PENDING, - STATE_ALARM_TRIGGERED, - Platform, -) +from homeassistant.const import Platform from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from . import HomeAssistantOverkizData +from .alarm_entities import WIDGET_TO_ALARM_ENTITY from .const import DOMAIN -from .entity import OverkizEntity - -COMMAND_ALARM_OFF = "alarmOff" -COMMAND_ALARM_ON = "alarmOn" -COMMAND_ALARM_PARTIAL_1 = "alarmPartial1" -COMMAND_ALARM_PARTIAL_2 = "alarmPartial2" -COMMAND_ARM = "arm" -COMMAND_ARM_PARTIAL_DAY = "armPartialDay" -COMMAND_ARM_PARTIAL_NIGHT = "armPartialNight" -COMMAND_DISARM = "disarm" -COMMAND_PARTIAL = "partial" -COMMAND_SET_ALARM_STATUS = "setAlarmStatus" - -CORE_INTRUSION_STATE = "core:IntrusionState" -INTERNAL_CURRENT_ALARM_MODE_STATE = "internal:CurrentAlarmModeState" -INTERNAL_TARGET_ALARM_MODE_STATE = "internal:TargetAlarmModeState" -INTERNAL_INTRUSION_DETECTED_STATE = "internal:IntrusionDetectedState" -MYFOX_ALARM_STATUS_STATE = "myfox:AlarmStatusState" -VERISURE_ALARM_PANEL_MAIN_ARM_TYPE_STATE = "verisure:AlarmPanelMainArmTypeState" - -STATE_ARMED = "armed" -STATE_ARMED_DAY = "armedDay" -STATE_ARMED_NIGHT = "armedNight" -STATE_DETECTED = "detected" -STATE_DISARMED = "disarmed" -STATE_OFF = "off" -STATE_PARTIAL = "partial" -STATE_ZONE_1 = "zone1" -STATE_ZONE_2 = "zone2" -STATE_PENDING = "pending" -STATE_TOTAL = "total" -STATE_UNDETECTED = "undetected" - -MAP_MYFOX_STATUS_STATE = { - STATE_ARMED: STATE_ALARM_ARMED_AWAY, - STATE_DISARMED: STATE_ALARM_DISARMED, - STATE_PARTIAL: STATE_ALARM_ARMED_NIGHT, -} - -MAP_INTERNAL_STATUS_STATE = { - STATE_OFF: STATE_ALARM_DISARMED, - STATE_ZONE_1: STATE_ALARM_ARMED_HOME, - STATE_ZONE_2: STATE_ALARM_ARMED_NIGHT, - STATE_TOTAL: STATE_ALARM_ARMED_AWAY, -} - -MAP_VERISURE_STATUS_STATE = { - STATE_ARMED: STATE_ALARM_ARMED_AWAY, - STATE_DISARMED: STATE_ALARM_DISARMED, - STATE_ARMED_DAY: STATE_ALARM_ARMED_HOME, - STATE_ARMED_NIGHT: STATE_ALARM_ARMED_NIGHT, -} async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback, -): - """Set up the Overkiz alarm control panels from a config entry.""" +) -> None: + """Set up the Overkiz switch from a config entry.""" data: HomeAssistantOverkizData = hass.data[DOMAIN][entry.entry_id] entities = [ - OverkizAlarmControlPanel(device.device_url, data.coordinator) + WIDGET_TO_ALARM_ENTITY[device.widget](device.device_url, data.coordinator) for device in data.platforms[Platform.ALARM_CONTROL_PANEL] + if device.widget in WIDGET_TO_ALARM_ENTITY ] - async_add_entities(entities) - - -class OverkizAlarmControlPanel(OverkizEntity, AlarmControlPanelEntity): - """Representation of a Overkiz Alarm Control Panel.""" - - @property - def state(self): - """Return the state of the device.""" - if self.executor.has_state( - CORE_INTRUSION_STATE, INTERNAL_INTRUSION_DETECTED_STATE - ): - state = self.executor.select_state( - CORE_INTRUSION_STATE, INTERNAL_INTRUSION_DETECTED_STATE - ) - if state == STATE_DETECTED: - return STATE_ALARM_TRIGGERED - elif state == STATE_PENDING: - return STATE_ALARM_PENDING - - if ( - self.executor.has_state(INTERNAL_CURRENT_ALARM_MODE_STATE) - and self.executor.has_state(INTERNAL_TARGET_ALARM_MODE_STATE) - and self.executor.select_state(INTERNAL_CURRENT_ALARM_MODE_STATE) - != self.executor.select_state(INTERNAL_TARGET_ALARM_MODE_STATE) - ): - return STATE_ALARM_PENDING - - if self.executor.has_state(MYFOX_ALARM_STATUS_STATE): - return MAP_MYFOX_STATUS_STATE[ - self.executor.select_state(MYFOX_ALARM_STATUS_STATE) - ] - - if self.executor.has_state(INTERNAL_CURRENT_ALARM_MODE_STATE): - return MAP_INTERNAL_STATUS_STATE[ - self.executor.select_state(INTERNAL_CURRENT_ALARM_MODE_STATE) - ] - - if self.executor.has_state(VERISURE_ALARM_PANEL_MAIN_ARM_TYPE_STATE): - return MAP_VERISURE_STATUS_STATE[ - self.executor.select_state(VERISURE_ALARM_PANEL_MAIN_ARM_TYPE_STATE) - ] - return None - - @property - def supported_features(self) -> int: - """Return the list of supported features.""" - supported_features = 0 - - if self.executor.has_command(COMMAND_ARM, COMMAND_ALARM_ON): - supported_features |= SUPPORT_ALARM_ARM_AWAY - - if self.executor.has_command(COMMAND_ALARM_PARTIAL_1, COMMAND_ARM_PARTIAL_DAY): - supported_features |= SUPPORT_ALARM_ARM_HOME - - if self.executor.has_command( - COMMAND_PARTIAL, COMMAND_ALARM_PARTIAL_2, COMMAND_ARM_PARTIAL_NIGHT - ): - supported_features |= SUPPORT_ALARM_ARM_NIGHT - - if self.executor.has_command(COMMAND_SET_ALARM_STATUS): - supported_features |= SUPPORT_ALARM_TRIGGER - supported_features |= SUPPORT_ALARM_ARM_CUSTOM_BYPASS - - return supported_features - - async def async_alarm_disarm(self, code=None): - """Send disarm command.""" - await self.executor.async_execute_command( - self.executor.select_command(COMMAND_DISARM, COMMAND_ALARM_OFF) - ) - - async def async_alarm_arm_home(self, code=None): - """Send arm home command.""" - await self.executor.async_execute_command( - COMMAND_ALARM_PARTIAL_1, COMMAND_ARM_PARTIAL_DAY - ) - - async def async_alarm_arm_night(self, code=None): - """Send arm night command.""" - await self.executor.async_execute_command( - self.executor.select_command( - COMMAND_PARTIAL, COMMAND_ALARM_PARTIAL_2, COMMAND_ARM_PARTIAL_NIGHT - ) - ) - - async def async_alarm_arm_away(self, code=None): - """Send arm away command.""" - await self.executor.async_execute_command( - self.executor.select_command(COMMAND_ARM, COMMAND_ALARM_ON) - ) - - async def async_alarm_trigger(self, code=None) -> None: - """Send alarm trigger command.""" - await self.executor.async_execute_command( - self.executor.select_command(COMMAND_SET_ALARM_STATUS, STATE_DETECTED) - ) - - async def async_alarm_arm_custom_bypass(self, code=None) -> None: - """Send arm custom bypass command.""" - await self.executor.async_execute_command( - self.executor.select_command(COMMAND_SET_ALARM_STATUS, STATE_UNDETECTED) - ) - - @property - def entity_registry_enabled_default(self) -> bool: - """Return if the entity should be enabled when first added to the entity registry.""" - return self.device.widget != "TSKAlarmController" + async_add_entities(entities) diff --git a/custom_components/tahoma/alarm_entities/__init__.py b/custom_components/tahoma/alarm_entities/__init__.py new file mode 100644 index 00000000..d467765a --- /dev/null +++ b/custom_components/tahoma/alarm_entities/__init__.py @@ -0,0 +1,8 @@ +"""Alarm Control Panel entities.""" +from pyoverkiz.enums.ui import UIWidget + +from .tsk_alarm_controller import TSKAlarmController + +WIDGET_TO_ALARM_ENTITY = { + UIWidget.TSKALARM_CONTROLLER: TSKAlarmController, +} diff --git a/custom_components/tahoma/alarm_entities/stateful_alarm_controller.py b/custom_components/tahoma/alarm_entities/stateful_alarm_controller.py new file mode 100644 index 00000000..b4f8b41d --- /dev/null +++ b/custom_components/tahoma/alarm_entities/stateful_alarm_controller.py @@ -0,0 +1,72 @@ +"""Support for Overkiz StatefulAlarmController.""" +from __future__ import annotations + +from pyoverkiz.enums import OverkizCommand, OverkizCommandParam, OverkizState + +from homeassistant.components.alarm_control_panel import AlarmControlPanelEntity +from homeassistant.components.alarm_control_panel.const import ( + SUPPORT_ALARM_ARM_AWAY, + SUPPORT_ALARM_ARM_HOME, + SUPPORT_ALARM_ARM_NIGHT, +) +from homeassistant.const import ( + STATE_ALARM_ARMED_AWAY, + STATE_ALARM_ARMED_HOME, + STATE_ALARM_ARMED_NIGHT, + STATE_ALARM_DISARMED, +) + +from ..entity import OverkizEntity + + +class StatefulAlarmController(OverkizEntity, AlarmControlPanelEntity): + """Representation of a Overkiz Alarm Control Panel.""" + + _attr_supported_features = ( + SUPPORT_ALARM_ARM_AWAY | SUPPORT_ALARM_ARM_HOME | SUPPORT_ALARM_ARM_NIGHT + ) + + @property + def state(self): + """Return the state of the device.""" + state = self.executor.select_state(OverkizState.CORE_ACTIVE_ZONES) + + if [ + OverkizCommandParam.A, + OverkizCommandParam.B, + OverkizCommandParam.C, + ] in state: + return STATE_ALARM_ARMED_AWAY + + if [OverkizCommandParam.A, OverkizCommandParam.B] in state: + return STATE_ALARM_ARMED_NIGHT + + if [OverkizCommandParam.A] in state: + return STATE_ALARM_ARMED_HOME + + return STATE_ALARM_DISARMED + + async def async_alarm_disarm(self, code=None): + """Send disarm command.""" + await self.executor.async_execute_command(OverkizCommand.DISARM) + + async def async_alarm_arm_home(self, code=None): + """Send arm home command.""" + await self.executor.async_execute_command( + OverkizCommand.ALARM_ZONE_ON, + [OverkizCommandParam.A], + ) + + async def async_alarm_arm_night(self, code=None): + """Send arm night command.""" + await self.executor.async_execute_command( + OverkizCommand.ALARM_ZONE_ON, + [OverkizCommandParam.A, OverkizCommandParam.B], + ) + + async def async_alarm_arm_away(self, code=None): + """Send arm away command.""" + await self.executor.async_execute_command( + OverkizCommand.ALARM_ZONE_ON, + [OverkizCommandParam.A, OverkizCommandParam.B, OverkizCommandParam.C], + ) diff --git a/custom_components/tahoma/alarm_entities/tsk_alarm_controller.py b/custom_components/tahoma/alarm_entities/tsk_alarm_controller.py new file mode 100644 index 00000000..93c273dd --- /dev/null +++ b/custom_components/tahoma/alarm_entities/tsk_alarm_controller.py @@ -0,0 +1,70 @@ +"""Support for Overkiz TSKAlarmController.""" +from __future__ import annotations + +from pyoverkiz.enums import OverkizCommand, OverkizCommandParam, OverkizState + +from homeassistant.components.alarm_control_panel import AlarmControlPanelEntity +from homeassistant.components.alarm_control_panel.const import ( + SUPPORT_ALARM_ARM_AWAY, + SUPPORT_ALARM_ARM_HOME, + SUPPORT_ALARM_ARM_NIGHT, +) +from homeassistant.const import ( + STATE_ALARM_ARMED_AWAY, + STATE_ALARM_ARMED_HOME, + STATE_ALARM_ARMED_NIGHT, + STATE_ALARM_DISARMED, + STATE_ALARM_PENDING, +) + +from ..entity import OverkizEntity + + +class TSKAlarmController(OverkizEntity, AlarmControlPanelEntity): + """Representation of a Overkiz Alarm Control Panel.""" + + _attr_supported_features = ( + SUPPORT_ALARM_ARM_AWAY | SUPPORT_ALARM_ARM_HOME | SUPPORT_ALARM_ARM_NIGHT + ) + _attr_entity_registry_enabled_default = False + + @property + def state(self): + """Return the state of the device.""" + if self.executor.select_state( + OverkizState.INTERNAL_CURRENT_ALARM_MODE + ) != self.executor.select_state(OverkizState.INTERNAL_TARGET_ALARM_MODE): + return STATE_ALARM_PENDING + + MAP_INTERNAL_STATUS_STATE = { + OverkizCommandParam.OFF: STATE_ALARM_DISARMED, + "zone1": STATE_ALARM_ARMED_HOME, + "zone2": STATE_ALARM_ARMED_NIGHT, + OverkizCommandParam.TOTAL: STATE_ALARM_ARMED_AWAY, + } + + return MAP_INTERNAL_STATUS_STATE[ + self.executor.select_state(OverkizState.INTERNAL_TARGET_ALARM_MODE) + ] + + async def async_alarm_disarm(self, code=None): + """Send disarm command.""" + await self.executor.async_execute_command(OverkizCommand.ALARM_OFF) + + async def async_alarm_arm_home(self, code=None): + """Send arm home command.""" + await self.executor.async_execute_command("setTargetAlarmMode", "partial1") + + async def async_alarm_arm_night(self, code=None): + """Send arm night command.""" + await self.executor.async_execute_command("setTargetAlarmMode", "partial2") + + async def async_alarm_arm_away(self, code=None): + """Send arm away command.""" + await self.executor.async_execute_command( + "setTargetAlarmMode", OverkizCommandParam.TOTAL + ) + + async def async_alarm_trigger(self, code=None) -> None: + """Send alarm trigger command.""" + await self.executor.async_execute_command(OverkizCommand.ALARM_ON) From 652f6810dbc77b239762607f141f5855a42eac69 Mon Sep 17 00:00:00 2001 From: Mick Vleeshouwer Date: Sun, 20 Feb 2022 22:28:52 +0100 Subject: [PATCH 03/10] Add extra controller --- .../tahoma/alarm_entities/__init__.py | 4 ++ .../alarm_entities/alarm_panel_controller.py | 72 +++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 custom_components/tahoma/alarm_entities/alarm_panel_controller.py diff --git a/custom_components/tahoma/alarm_entities/__init__.py b/custom_components/tahoma/alarm_entities/__init__.py index d467765a..cde1d7cd 100644 --- a/custom_components/tahoma/alarm_entities/__init__.py +++ b/custom_components/tahoma/alarm_entities/__init__.py @@ -1,8 +1,12 @@ """Alarm Control Panel entities.""" from pyoverkiz.enums.ui import UIWidget +from .alarm_panel_controller import AlarmPanelController +from .stateful_alarm_controller import StatefulAlarmController from .tsk_alarm_controller import TSKAlarmController WIDGET_TO_ALARM_ENTITY = { UIWidget.TSKALARM_CONTROLLER: TSKAlarmController, + UIWidget.STATEFUL_ALARM_CONTROLLER: StatefulAlarmController, + UIWidget.ALARM_PANEL_CONTROLLER: AlarmPanelController, } diff --git a/custom_components/tahoma/alarm_entities/alarm_panel_controller.py b/custom_components/tahoma/alarm_entities/alarm_panel_controller.py new file mode 100644 index 00000000..ebf0064a --- /dev/null +++ b/custom_components/tahoma/alarm_entities/alarm_panel_controller.py @@ -0,0 +1,72 @@ +"""Support for Overkiz AlarmPanelController.""" +from __future__ import annotations + +from pyoverkiz.enums import OverkizCommand, OverkizCommandParam, OverkizState + +from homeassistant.components.alarm_control_panel import AlarmControlPanelEntity +from homeassistant.components.alarm_control_panel.const import ( + SUPPORT_ALARM_ARM_AWAY, + SUPPORT_ALARM_ARM_HOME, + SUPPORT_ALARM_ARM_NIGHT, +) +from homeassistant.const import ( + STATE_ALARM_ARMED_AWAY, + STATE_ALARM_ARMED_HOME, + STATE_ALARM_ARMED_NIGHT, + STATE_ALARM_DISARMED, +) + +from ..entity import OverkizEntity + + +class AlarmPanelController(OverkizEntity, AlarmControlPanelEntity): + """Representation of a Overkiz Alarm Control Panel.""" + + _attr_supported_features = ( + SUPPORT_ALARM_ARM_AWAY | SUPPORT_ALARM_ARM_HOME | SUPPORT_ALARM_ARM_NIGHT + ) + + @property + def state(self): + """Return the state of the device.""" + state = self.executor.select_state(OverkizState.CORE_ACTIVE_ZONES) + + if [ + OverkizCommandParam.A, + OverkizCommandParam.B, + OverkizCommandParam.C, + ] in state: + return STATE_ALARM_ARMED_AWAY + + if [OverkizCommandParam.A, OverkizCommandParam.B] in state: + return STATE_ALARM_ARMED_NIGHT + + if [OverkizCommandParam.A] in state: + return STATE_ALARM_ARMED_HOME + + return STATE_ALARM_DISARMED + + async def async_alarm_disarm(self, code=None): + """Send disarm command.""" + await self.executor.async_execute_command(OverkizCommand.DISARM) + + async def async_alarm_arm_home(self, code=None): + """Send arm home command.""" + await self.executor.async_execute_command( + OverkizCommand.ALARM_ZONE_ON, + [OverkizCommandParam.A], + ) + + async def async_alarm_arm_night(self, code=None): + """Send arm night command.""" + await self.executor.async_execute_command( + OverkizCommand.ALARM_ZONE_ON, + [OverkizCommandParam.A, OverkizCommandParam.B], + ) + + async def async_alarm_arm_away(self, code=None): + """Send arm away command.""" + await self.executor.async_execute_command( + OverkizCommand.ALARM_ZONE_ON, + [OverkizCommandParam.A, OverkizCommandParam.B, OverkizCommandParam.C], + ) From 2e91275e569a9cb2eca461bc7031606a4514bab2 Mon Sep 17 00:00:00 2001 From: Mick Vleeshouwer Date: Sun, 20 Feb 2022 22:43:35 +0100 Subject: [PATCH 04/10] Add MyFox controller --- .../tahoma/alarm_entities/__init__.py | 2 + .../alarm_entities/alarm_panel_controller.py | 39 ++++--------- .../alarm_entities/my_fox_alarm_controller.py | 55 +++++++++++++++++++ .../alarm_entities/tsk_alarm_controller.py | 7 +++ 4 files changed, 76 insertions(+), 27 deletions(-) create mode 100644 custom_components/tahoma/alarm_entities/my_fox_alarm_controller.py diff --git a/custom_components/tahoma/alarm_entities/__init__.py b/custom_components/tahoma/alarm_entities/__init__.py index cde1d7cd..4d065aee 100644 --- a/custom_components/tahoma/alarm_entities/__init__.py +++ b/custom_components/tahoma/alarm_entities/__init__.py @@ -2,6 +2,7 @@ from pyoverkiz.enums.ui import UIWidget from .alarm_panel_controller import AlarmPanelController +from .my_fox_alarm_controller import MyFoxAlarmController from .stateful_alarm_controller import StatefulAlarmController from .tsk_alarm_controller import TSKAlarmController @@ -9,4 +10,5 @@ UIWidget.TSKALARM_CONTROLLER: TSKAlarmController, UIWidget.STATEFUL_ALARM_CONTROLLER: StatefulAlarmController, UIWidget.ALARM_PANEL_CONTROLLER: AlarmPanelController, + UIWidget.MY_FOX_ALARM_CONTROLLER: MyFoxAlarmController, } diff --git a/custom_components/tahoma/alarm_entities/alarm_panel_controller.py b/custom_components/tahoma/alarm_entities/alarm_panel_controller.py index ebf0064a..7c0c9895 100644 --- a/custom_components/tahoma/alarm_entities/alarm_panel_controller.py +++ b/custom_components/tahoma/alarm_entities/alarm_panel_controller.py @@ -29,22 +29,16 @@ class AlarmPanelController(OverkizEntity, AlarmControlPanelEntity): @property def state(self): """Return the state of the device.""" - state = self.executor.select_state(OverkizState.CORE_ACTIVE_ZONES) + MAP_ARM_TYPE = { + OverkizCommandParam.DISARMED: STATE_ALARM_DISARMED, + OverkizCommandParam.ARMED_DAY: STATE_ALARM_ARMED_HOME, + OverkizCommandParam.ARMED_NIGHT: STATE_ALARM_ARMED_NIGHT, + OverkizCommandParam.ARMED: STATE_ALARM_ARMED_AWAY, + } - if [ - OverkizCommandParam.A, - OverkizCommandParam.B, - OverkizCommandParam.C, - ] in state: - return STATE_ALARM_ARMED_AWAY - - if [OverkizCommandParam.A, OverkizCommandParam.B] in state: - return STATE_ALARM_ARMED_NIGHT - - if [OverkizCommandParam.A] in state: - return STATE_ALARM_ARMED_HOME - - return STATE_ALARM_DISARMED + return MAP_ARM_TYPE[ + self.executor.select_state(OverkizState.VERISURE_ALARM_PANEL_MAIN_ARM_TYPE) + ] async def async_alarm_disarm(self, code=None): """Send disarm command.""" @@ -52,21 +46,12 @@ async def async_alarm_disarm(self, code=None): async def async_alarm_arm_home(self, code=None): """Send arm home command.""" - await self.executor.async_execute_command( - OverkizCommand.ALARM_ZONE_ON, - [OverkizCommandParam.A], - ) + await self.executor.async_execute_command(OverkizCommand.ARM_PARTIAL_DAY) async def async_alarm_arm_night(self, code=None): """Send arm night command.""" - await self.executor.async_execute_command( - OverkizCommand.ALARM_ZONE_ON, - [OverkizCommandParam.A, OverkizCommandParam.B], - ) + await self.executor.async_execute_command(OverkizCommand.ARM_PARTIAL_NIGHT) async def async_alarm_arm_away(self, code=None): """Send arm away command.""" - await self.executor.async_execute_command( - OverkizCommand.ALARM_ZONE_ON, - [OverkizCommandParam.A, OverkizCommandParam.B, OverkizCommandParam.C], - ) + await self.executor.async_execute_command(OverkizCommand.ARM) diff --git a/custom_components/tahoma/alarm_entities/my_fox_alarm_controller.py b/custom_components/tahoma/alarm_entities/my_fox_alarm_controller.py new file mode 100644 index 00000000..69b5edee --- /dev/null +++ b/custom_components/tahoma/alarm_entities/my_fox_alarm_controller.py @@ -0,0 +1,55 @@ +"""Support for Overkiz MyFoxAlarmController.""" +from __future__ import annotations + +from pyoverkiz.enums import OverkizCommand, OverkizCommandParam, OverkizState + +from homeassistant.components.alarm_control_panel import AlarmControlPanelEntity +from homeassistant.components.alarm_control_panel.const import ( + SUPPORT_ALARM_ARM_AWAY, + SUPPORT_ALARM_ARM_NIGHT, +) +from homeassistant.const import ( + STATE_ALARM_ARMED_AWAY, + STATE_ALARM_ARMED_NIGHT, + STATE_ALARM_DISARMED, + STATE_ALARM_TRIGGERED, +) + +from ..entity import OverkizEntity + + +class MyFoxAlarmController(OverkizEntity, AlarmControlPanelEntity): + """Representation of a Overkiz Alarm Control Panel.""" + + _attr_supported_features = SUPPORT_ALARM_ARM_AWAY | SUPPORT_ALARM_ARM_NIGHT + + @property + def state(self): + """Return the state of the device.""" + if ( + self.executor.select_state(OverkizState.CORE_INTRUSION) + == OverkizCommandParam.DETECTED + ): + return STATE_ALARM_TRIGGERED + + MAP_MYFOX_STATUS_STATE = { + OverkizCommandParam.ARMED: STATE_ALARM_ARMED_AWAY, + OverkizCommandParam.DISARMED: STATE_ALARM_DISARMED, + OverkizCommandParam.PARTIAL: STATE_ALARM_ARMED_NIGHT, + } + + return MAP_MYFOX_STATUS_STATE[ + self.executor.select_state(OverkizState.MYFOX_ALARM_STATUS) + ] + + async def async_alarm_disarm(self, code=None): + """Send disarm command.""" + await self.executor.async_execute_command(OverkizCommand.DISARM) + + async def async_alarm_arm_night(self, code=None): + """Send arm night command.""" + await self.executor.async_execute_command(OverkizCommand.PARTIAL) + + async def async_alarm_arm_away(self, code=None): + """Send arm away command.""" + await self.executor.async_execute_command(OverkizCommand.ARM) diff --git a/custom_components/tahoma/alarm_entities/tsk_alarm_controller.py b/custom_components/tahoma/alarm_entities/tsk_alarm_controller.py index 93c273dd..5a3fbf09 100644 --- a/custom_components/tahoma/alarm_entities/tsk_alarm_controller.py +++ b/custom_components/tahoma/alarm_entities/tsk_alarm_controller.py @@ -15,6 +15,7 @@ STATE_ALARM_ARMED_NIGHT, STATE_ALARM_DISARMED, STATE_ALARM_PENDING, + STATE_ALARM_TRIGGERED, ) from ..entity import OverkizEntity @@ -31,6 +32,12 @@ class TSKAlarmController(OverkizEntity, AlarmControlPanelEntity): @property def state(self): """Return the state of the device.""" + if ( + self.executor.select_state(OverkizState.INTERNAL_INTRUSION_DETECTED) + == OverkizCommandParam.DETECTED + ): + return STATE_ALARM_TRIGGERED + if self.executor.select_state( OverkizState.INTERNAL_CURRENT_ALARM_MODE ) != self.executor.select_state(OverkizState.INTERNAL_TARGET_ALARM_MODE): From 841b8bee28a116a863ea4d8713c74cf768c77016 Mon Sep 17 00:00:00 2001 From: Mick Vleeshouwer Date: Sun, 20 Feb 2022 22:48:57 +0100 Subject: [PATCH 05/10] Update const --- custom_components/tahoma/const.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/custom_components/tahoma/const.py b/custom_components/tahoma/const.py index b1dcd8f0..0b61b6a9 100644 --- a/custom_components/tahoma/const.py +++ b/custom_components/tahoma/const.py @@ -40,7 +40,6 @@ # Used to map the Somfy widget and ui_class to the Home Assistant platform OVERKIZ_DEVICE_TO_PLATFORM = { UIClass.ADJUSTABLE_SLATS_ROLLER_SHUTTER: Platform.COVER, - UIClass.ALARM: Platform.ALARM_CONTROL_PANEL, UIClass.AWNING: Platform.COVER, UIClass.CURTAIN: Platform.COVER, UIClass.DOOR_LOCK: Platform.LOCK, @@ -59,6 +58,7 @@ UIClass.SWINGING_SHUTTER: Platform.COVER, UIClass.VENETIAN_BLIND: Platform.COVER, UIClass.WINDOW: Platform.COVER, + UIWidget.ALARM_PANEL_CONTROLLER: Platform.ALARM_CONTROL_PANEL, # widgetName, uiClass is Alarm (not supported) UIWidget.ATLANTIC_ELECTRICAL_HEATER: Platform.CLIMATE, # widgetName, uiClass is HeatingSystem (not supported) UIWidget.ATLANTIC_ELECTRICAL_HEATER_WITH_ADJUSTABLE_TEMPERATURE_SETPOINT: Platform.CLIMATE, # widgetName, uiClass is HeatingSystem (not supported) UIWidget.ATLANTIC_ELECTRICAL_TOWEL_DRYER: Platform.CLIMATE, # widgetName, uiClass is HeatingSystem (not supported) @@ -73,13 +73,13 @@ UIWidget.HITACHI_AIR_TO_AIR_HEAT_PUMP: Platform.CLIMATE, # widgetName, uiClass is HitachiHeatingSystem (not supported) UIWidget.HITACHI_AIR_TO_WATER_HEATING_ZONE: Platform.CLIMATE, # widgetName, uiClass is HitachiHeatingSystem (not supported) UIWidget.HITACHI_DHW: Platform.WATER_HEATER, # widgetName, uiClass is HitachiHeatingSystem (not supported) - UIWidget.MY_FOX_SECURITY_CAMERA: Platform.SWITCH, # widgetName, uiClass is Camera (not supported) - UIWidget.RTD_INDOOR_SIREN: Platform.SWITCH, # widgetName, uiClass is Siren (siren) - UIWidget.RTD_OUTDOOR_SIREN: Platform.SWITCH, # widgetName, uiClass is Siren (siren) + UIWidget.MY_FOX_ALARM_CONTROLLER: Platform.ALARM_CONTROL_PANEL, # widgetName, uiClass is Alarm (not supported) + UIWidget.MY_FOX_SECURITY_CAMERA: Platform.COVER, # widgetName, uiClass is Camera (not supported) UIWidget.RTS_GENERIC: Platform.COVER, # widgetName, uiClass is Generic (not supported) - UIWidget.SIREN_STATUS: None, # widgetName, uiClass is Siren (siren) + UIWidget.SIREN_STATUS: None, # widgetName, uiClass is Siren (switch) UIWidget.SOMFY_HEATING_TEMPERATURE_INTERFACE: Platform.CLIMATE, # widgetName, uiClass is HeatingSystem (not supported) UIWidget.SOMFY_THERMOSTAT: Platform.CLIMATE, # widgetName, uiClass is HeatingSystem (not supported) - UIWidget.STATELESS_ALARM_CONTROLLER: Platform.SWITCH, # widgetName, uiClass is Alarm (not supported) - UIWidget.STATELESS_EXTERIOR_HEATING: Platform.SWITCH, # widgetName, uiClass is ExteriorHeatingSystem (not supported) + UIWidget.STATEFUL_ALARM_CONTROLLER: Platform.ALARM_CONTROL_PANEL, # widgetName, uiClass is Alarm (not supported) + UIWidget.STATELESS_EXTERIOR_HEATING: Platform.CLIMATE, # widgetName, uiClass is ExteriorHeatingSystem. + UIWidget.TSKALARM_CONTROLLER: Platform.ALARM_CONTROL_PANEL, # widgetName, uiClass is Alarm (not supported) } From 186371dd7c9ddc60acd85f5a27359a1d4b36bac0 Mon Sep 17 00:00:00 2001 From: Mick Vleeshouwer Date: Mon, 21 Feb 2022 13:22:40 +0100 Subject: [PATCH 06/10] Update text --- custom_components/tahoma/alarm_control_panel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/tahoma/alarm_control_panel.py b/custom_components/tahoma/alarm_control_panel.py index 816c9e13..eaa06537 100644 --- a/custom_components/tahoma/alarm_control_panel.py +++ b/custom_components/tahoma/alarm_control_panel.py @@ -16,7 +16,7 @@ async def async_setup_entry( entry: ConfigEntry, async_add_entities: AddEntitiesCallback, ) -> None: - """Set up the Overkiz switch from a config entry.""" + """Set up the Overkiz alarm control panel from a config entry.""" data: HomeAssistantOverkizData = hass.data[DOMAIN][entry.entry_id] entities = [ From 6e7d65369a3ebc1eb20e52d1151e00971e6cea25 Mon Sep 17 00:00:00 2001 From: Mick Vleeshouwer Date: Mon, 21 Feb 2022 13:25:35 +0100 Subject: [PATCH 07/10] Bugfix --- custom_components/tahoma/const.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/custom_components/tahoma/const.py b/custom_components/tahoma/const.py index 0b61b6a9..35253ec7 100644 --- a/custom_components/tahoma/const.py +++ b/custom_components/tahoma/const.py @@ -40,6 +40,7 @@ # Used to map the Somfy widget and ui_class to the Home Assistant platform OVERKIZ_DEVICE_TO_PLATFORM = { UIClass.ADJUSTABLE_SLATS_ROLLER_SHUTTER: Platform.COVER, + UIClass.ALARM: Platform.ALARM_CONTROL_PANEL, UIClass.AWNING: Platform.COVER, UIClass.CURTAIN: Platform.COVER, UIClass.DOOR_LOCK: Platform.LOCK, @@ -74,12 +75,15 @@ UIWidget.HITACHI_AIR_TO_WATER_HEATING_ZONE: Platform.CLIMATE, # widgetName, uiClass is HitachiHeatingSystem (not supported) UIWidget.HITACHI_DHW: Platform.WATER_HEATER, # widgetName, uiClass is HitachiHeatingSystem (not supported) UIWidget.MY_FOX_ALARM_CONTROLLER: Platform.ALARM_CONTROL_PANEL, # widgetName, uiClass is Alarm (not supported) - UIWidget.MY_FOX_SECURITY_CAMERA: Platform.COVER, # widgetName, uiClass is Camera (not supported) + UIWidget.MY_FOX_SECURITY_CAMERA: Platform.SWITCH, # widgetName, uiClass is Camera (not supported) + UIWidget.RTD_INDOOR_SIREN: Platform.SWITCH, # widgetName, uiClass is Siren (siren) + UIWidget.RTD_OUTDOOR_SIREN: Platform.SWITCH, # widgetName, uiClass is Siren (siren) UIWidget.RTS_GENERIC: Platform.COVER, # widgetName, uiClass is Generic (not supported) - UIWidget.SIREN_STATUS: None, # widgetName, uiClass is Siren (switch) + UIWidget.SIREN_STATUS: None, # widgetName, uiClass is Siren (siren) UIWidget.SOMFY_HEATING_TEMPERATURE_INTERFACE: Platform.CLIMATE, # widgetName, uiClass is HeatingSystem (not supported) UIWidget.SOMFY_THERMOSTAT: Platform.CLIMATE, # widgetName, uiClass is HeatingSystem (not supported) + UIWidget.STATELESS_ALARM_CONTROLLER: Platform.SWITCH, # widgetName, uiClass is Alarm (not supported) UIWidget.STATEFUL_ALARM_CONTROLLER: Platform.ALARM_CONTROL_PANEL, # widgetName, uiClass is Alarm (not supported) - UIWidget.STATELESS_EXTERIOR_HEATING: Platform.CLIMATE, # widgetName, uiClass is ExteriorHeatingSystem. + UIWidget.STATELESS_EXTERIOR_HEATING: Platform.SWITCH, # widgetName, uiClass is ExteriorHeatingSystem (not supported) UIWidget.TSKALARM_CONTROLLER: Platform.ALARM_CONTROL_PANEL, # widgetName, uiClass is Alarm (not supported) -} +} \ No newline at end of file From 79c52f2e78ea8eea9a1428cf56c836adc704ee20 Mon Sep 17 00:00:00 2001 From: Mick Vleeshouwer Date: Mon, 21 Feb 2022 13:26:15 +0100 Subject: [PATCH 08/10] Bugfix --- custom_components/tahoma/const.py | 1 - 1 file changed, 1 deletion(-) diff --git a/custom_components/tahoma/const.py b/custom_components/tahoma/const.py index 35253ec7..a7ea875c 100644 --- a/custom_components/tahoma/const.py +++ b/custom_components/tahoma/const.py @@ -40,7 +40,6 @@ # Used to map the Somfy widget and ui_class to the Home Assistant platform OVERKIZ_DEVICE_TO_PLATFORM = { UIClass.ADJUSTABLE_SLATS_ROLLER_SHUTTER: Platform.COVER, - UIClass.ALARM: Platform.ALARM_CONTROL_PANEL, UIClass.AWNING: Platform.COVER, UIClass.CURTAIN: Platform.COVER, UIClass.DOOR_LOCK: Platform.LOCK, From bb0abf7e20c734760723913c81a371c9862d4a58 Mon Sep 17 00:00:00 2001 From: Mick Vleeshouwer Date: Mon, 21 Feb 2022 13:30:37 +0100 Subject: [PATCH 09/10] Bugfix --- custom_components/tahoma/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/tahoma/const.py b/custom_components/tahoma/const.py index a7ea875c..185f8df8 100644 --- a/custom_components/tahoma/const.py +++ b/custom_components/tahoma/const.py @@ -85,4 +85,4 @@ UIWidget.STATEFUL_ALARM_CONTROLLER: Platform.ALARM_CONTROL_PANEL, # widgetName, uiClass is Alarm (not supported) UIWidget.STATELESS_EXTERIOR_HEATING: Platform.SWITCH, # widgetName, uiClass is ExteriorHeatingSystem (not supported) UIWidget.TSKALARM_CONTROLLER: Platform.ALARM_CONTROL_PANEL, # widgetName, uiClass is Alarm (not supported) -} \ No newline at end of file +} From a66f27516603b9605fe94678518107c715e9823c Mon Sep 17 00:00:00 2001 From: Mick Vleeshouwer Date: Mon, 21 Feb 2022 23:35:00 +0100 Subject: [PATCH 10/10] Use constants from PyOverkiz --- .../tahoma/alarm_entities/tsk_alarm_controller.py | 14 +++++++++----- custom_components/tahoma/manifest.json | 2 +- requirements.txt | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/custom_components/tahoma/alarm_entities/tsk_alarm_controller.py b/custom_components/tahoma/alarm_entities/tsk_alarm_controller.py index 5a3fbf09..e7115b25 100644 --- a/custom_components/tahoma/alarm_entities/tsk_alarm_controller.py +++ b/custom_components/tahoma/alarm_entities/tsk_alarm_controller.py @@ -45,8 +45,8 @@ def state(self): MAP_INTERNAL_STATUS_STATE = { OverkizCommandParam.OFF: STATE_ALARM_DISARMED, - "zone1": STATE_ALARM_ARMED_HOME, - "zone2": STATE_ALARM_ARMED_NIGHT, + OverkizCommandParam.ZONE_1: STATE_ALARM_ARMED_HOME, + OverkizCommandParam.ZONE_2: STATE_ALARM_ARMED_NIGHT, OverkizCommandParam.TOTAL: STATE_ALARM_ARMED_AWAY, } @@ -60,16 +60,20 @@ async def async_alarm_disarm(self, code=None): async def async_alarm_arm_home(self, code=None): """Send arm home command.""" - await self.executor.async_execute_command("setTargetAlarmMode", "partial1") + await self.executor.async_execute_command( + OverkizCommand.SET_TARGET_ALARM_MODE, OverkizCommandParam.PARTIAL_1 + ) async def async_alarm_arm_night(self, code=None): """Send arm night command.""" - await self.executor.async_execute_command("setTargetAlarmMode", "partial2") + await self.executor.async_execute_command( + OverkizCommand.SET_TARGET_ALARM_MODE, OverkizCommandParam.PARTIAL_2 + ) async def async_alarm_arm_away(self, code=None): """Send arm away command.""" await self.executor.async_execute_command( - "setTargetAlarmMode", OverkizCommandParam.TOTAL + OverkizCommand.SET_TARGET_ALARM_MODE, OverkizCommandParam.TOTAL ) async def async_alarm_trigger(self, code=None) -> None: diff --git a/custom_components/tahoma/manifest.json b/custom_components/tahoma/manifest.json index b05f31ff..a737f2b0 100644 --- a/custom_components/tahoma/manifest.json +++ b/custom_components/tahoma/manifest.json @@ -5,7 +5,7 @@ "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/tahoma", "requirements": [ - "pyoverkiz==1.3.5" + "pyoverkiz==1.3.6" ], "codeowners": [ "@imicknl", diff --git a/requirements.txt b/requirements.txt index 13438c05..2d8b6af4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -pyoverkiz==1.3.5 \ No newline at end of file +pyoverkiz==1.3.6 \ No newline at end of file