1 """Each ElkM1 area will be created as a separate alarm_control_panel."""
3 from __future__
import annotations
7 from elkm1_lib.areas
import Area
8 from elkm1_lib.const
import AlarmState, ArmedStatus, ArmLevel, ArmUpState
9 from elkm1_lib.elements
import Element
10 from elkm1_lib.elk
import Elk
11 from elkm1_lib.keypads
import Keypad
12 import voluptuous
as vol
16 AlarmControlPanelEntity,
17 AlarmControlPanelEntityFeature,
18 AlarmControlPanelState,
28 from .
import ElkM1ConfigEntry
31 ATTR_CHANGED_BY_KEYPAD,
33 ELK_USER_CODE_SERVICE_SCHEMA,
35 from .entity
import ElkAttachedEntity, ElkEntity, create_elk_entities
36 from .models
import ELKM1Data
38 DISPLAY_MESSAGE_SERVICE_SCHEMA: VolDictType = {
39 vol.Optional(
"clear", default=2): vol.All(vol.Coerce(int), vol.In([0, 1, 2])),
40 vol.Optional(
"beep", default=
False): cv.boolean,
41 vol.Optional(
"timeout", default=0): vol.All(
42 vol.Coerce(int), vol.Range(min=0, max=65535)
44 vol.Optional(
"line1", default=
""): cv.string,
45 vol.Optional(
"line2", default=
""): cv.string,
48 SERVICE_ALARM_DISPLAY_MESSAGE =
"alarm_display_message"
49 SERVICE_ALARM_ARM_VACATION =
"alarm_arm_vacation"
50 SERVICE_ALARM_ARM_HOME_INSTANT =
"alarm_arm_home_instant"
51 SERVICE_ALARM_ARM_NIGHT_INSTANT =
"alarm_arm_night_instant"
52 SERVICE_ALARM_BYPASS =
"alarm_bypass"
53 SERVICE_ALARM_CLEAR_BYPASS =
"alarm_clear_bypass"
58 config_entry: ElkM1ConfigEntry,
59 async_add_entities: AddEntitiesCallback,
61 """Set up the ElkM1 alarm platform."""
62 elk_data = config_entry.runtime_data
64 entities: list[ElkEntity] = []
68 platform = entity_platform.async_get_current_platform()
70 platform.async_register_entity_service(
71 SERVICE_ALARM_ARM_VACATION,
72 ELK_USER_CODE_SERVICE_SCHEMA,
73 "async_alarm_arm_vacation",
75 platform.async_register_entity_service(
76 SERVICE_ALARM_ARM_HOME_INSTANT,
77 ELK_USER_CODE_SERVICE_SCHEMA,
78 "async_alarm_arm_home_instant",
80 platform.async_register_entity_service(
81 SERVICE_ALARM_ARM_NIGHT_INSTANT,
82 ELK_USER_CODE_SERVICE_SCHEMA,
83 "async_alarm_arm_night_instant",
85 platform.async_register_entity_service(
86 SERVICE_ALARM_DISPLAY_MESSAGE,
87 DISPLAY_MESSAGE_SERVICE_SCHEMA,
88 "async_display_message",
90 platform.async_register_entity_service(
92 ELK_USER_CODE_SERVICE_SCHEMA,
95 platform.async_register_entity_service(
96 SERVICE_ALARM_CLEAR_BYPASS,
97 ELK_USER_CODE_SERVICE_SCHEMA,
103 """Representation of an Area / Partition within the ElkM1 alarm panel."""
105 _attr_supported_features = (
106 AlarmControlPanelEntityFeature.ARM_HOME
107 | AlarmControlPanelEntityFeature.ARM_AWAY
108 | AlarmControlPanelEntityFeature.ARM_NIGHT
112 def __init__(self, element: Element, elk: Elk, elk_data: ELKM1Data) ->
None:
113 """Initialize Area as Alarm Control Panel."""
114 super().
__init__(element, elk, elk_data)
120 self.
_state_state: AlarmControlPanelState |
None =
None
123 """Register callback for ElkM1 changes."""
125 if len(self.
_elk_elk_elk.areas.elements) == 1:
126 for keypad
in self.
_elk_elk_elk.keypads:
134 if ATTR_CHANGED_BY_KEYPAD
in last_state.attributes:
136 if ATTR_CHANGED_BY_TIME
in last_state.attributes:
138 if ATTR_CHANGED_BY_ID
in last_state.attributes:
140 if ATTR_CHANGED_BY
in last_state.attributes:
141 self.
_changed_by_changed_by = last_state.attributes[ATTR_CHANGED_BY]
143 def _watch_keypad(self, keypad: Element, changeset: dict[str, Any]) ->
None:
144 assert isinstance(keypad, Keypad)
145 if keypad.area != self.
_element_element.index:
147 if changeset.get(
"last_user")
is not None:
154 def _watch_area(self, area: Element, changeset: dict[str, Any]) ->
None:
155 if not (last_log := changeset.get(
"last_log")):
158 if (user_number := last_log.get(
"user_number"))
is None:
168 """Return the alarm code format."""
169 return CodeFormat.NUMBER
173 """Return the state of the element."""
178 """Attributes of the area."""
181 attrs[
"is_exit"] = elmt.is_exit
182 attrs[
"timer1"] = elmt.timer1
183 attrs[
"timer2"] = elmt.timer2
184 if elmt.armed_status
is not None:
185 attrs[
"armed_status"] = ArmedStatus(elmt.armed_status).name.lower()
186 if elmt.arm_up_state
is not None:
187 attrs[
"arm_up_state"] = ArmUpState(elmt.arm_up_state).name.lower()
188 if elmt.alarm_state
is not None:
189 attrs[
"alarm_state"] = AlarmState(elmt.alarm_state).name.lower()
197 """Last change triggered by."""
201 elk_state_to_hass_state = {
202 ArmedStatus.DISARMED: AlarmControlPanelState.DISARMED,
203 ArmedStatus.ARMED_AWAY: AlarmControlPanelState.ARMED_AWAY,
204 ArmedStatus.ARMED_STAY: AlarmControlPanelState.ARMED_HOME,
205 ArmedStatus.ARMED_STAY_INSTANT: AlarmControlPanelState.ARMED_HOME,
206 ArmedStatus.ARMED_TO_NIGHT: AlarmControlPanelState.ARMED_NIGHT,
207 ArmedStatus.ARMED_TO_NIGHT_INSTANT: AlarmControlPanelState.ARMED_NIGHT,
208 ArmedStatus.ARMED_TO_VACATION: AlarmControlPanelState.ARMED_AWAY,
211 if self.
_element_element.alarm_state
is None:
213 elif self.
_element_element.in_alarm_state():
215 self.
_state_state = AlarmControlPanelState.TRIGGERED
218 AlarmControlPanelState.ARMING
220 else AlarmControlPanelState.PENDING
222 elif self.
_element_element.armed_status
is not None:
223 self.
_state_state = elk_state_to_hass_state[self.
_element_element.armed_status]
231 """Send disarm command."""
236 """Send arm home command."""
238 self.
_element_element.arm(ArmLevel.ARMED_STAY,
int(code))
241 """Send arm away command."""
243 self.
_element_element.arm(ArmLevel.ARMED_AWAY,
int(code))
246 """Send arm night command."""
248 self.
_element_element.arm(ArmLevel.ARMED_NIGHT,
int(code))
251 """Send arm stay instant command."""
253 self.
_element_element.arm(ArmLevel.ARMED_STAY_INSTANT,
int(code))
256 """Send arm night instant command."""
258 self.
_element_element.arm(ArmLevel.ARMED_NIGHT_INSTANT,
int(code))
261 """Send arm vacation command."""
263 self.
_element_element.arm(ArmLevel.ARMED_VACATION,
int(code))
266 self, clear: int, beep: bool, timeout: int, line1: str, line2: str
268 """Display a message on all keypads for the area."""
269 self.
_element_element.display_message(clear, beep, timeout, line1, line2)
272 """Bypass all zones in area."""
277 """Clear bypass for all zones in area."""
None _watch_keypad(self, Element keypad, dict[str, Any] changeset)
bool _entry_exit_timer_is_running(self)
None async_display_message(self, int clear, bool beep, int timeout, str line1, str line2)
None async_bypass(self, str|None code=None)
None __init__(self, Element element, Elk elk, ELKM1Data elk_data)
None _element_changed(self, Element element, dict[str, Any] changeset)
None async_alarm_arm_away(self, str|None code=None)
None async_added_to_hass(self)
None async_alarm_disarm(self, str|None code=None)
None async_alarm_arm_night_instant(self, str|None code=None)
None async_alarm_arm_vacation(self, str|None code=None)
None async_clear_bypass(self, str|None code=None)
None async_alarm_arm_home(self, str|None code=None)
str|None changed_by(self)
dict[str, Any] extra_state_attributes(self)
None _watch_area(self, Element area, dict[str, Any] changeset)
None async_alarm_arm_home_instant(self, str|None code=None)
None async_alarm_arm_night(self, str|None code=None)
CodeFormat|None code_format(self)
AlarmControlPanelState|None alarm_state(self)
dict[str, Any] initial_attrs(self)
None async_write_ha_state(self)
State|None async_get_last_state(self)
None async_setup_entry(HomeAssistant hass, ElkM1ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
list[ElkEntity]|None create_elk_entities(ELKM1Data elk_data, Iterable[Element] elk_elements, str element_type, Any class_, list[ElkEntity] entities)