pyg90alarm 2.3.1__py3-none-any.whl → 2.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyg90alarm/__init__.py +1 -1
- pyg90alarm/alarm.py +105 -17
- pyg90alarm/const.py +53 -1
- pyg90alarm/event_mapping.py +99 -0
- pyg90alarm/local/alarm_phones.py +77 -0
- pyg90alarm/local/alert_config.py +190 -0
- pyg90alarm/local/config.py +11 -136
- pyg90alarm/local/dataclass_load_save.py +131 -0
- pyg90alarm/local/history.py +55 -13
- pyg90alarm/local/host_config.py +167 -0
- pyg90alarm/local/net_config.py +127 -0
- pyg90alarm/notifications/base.py +18 -1
- pyg90alarm/notifications/protocol.py +12 -0
- {pyg90alarm-2.3.1.dist-info → pyg90alarm-2.4.0.dist-info}/METADATA +1 -1
- {pyg90alarm-2.3.1.dist-info → pyg90alarm-2.4.0.dist-info}/RECORD +18 -12
- {pyg90alarm-2.3.1.dist-info → pyg90alarm-2.4.0.dist-info}/WHEEL +0 -0
- {pyg90alarm-2.3.1.dist-info → pyg90alarm-2.4.0.dist-info}/licenses/LICENSE +0 -0
- {pyg90alarm-2.3.1.dist-info → pyg90alarm-2.4.0.dist-info}/top_level.txt +0 -0
pyg90alarm/__init__.py
CHANGED
|
@@ -44,7 +44,7 @@ from .definitions.devices import (
|
|
|
44
44
|
from .definitions.base import (
|
|
45
45
|
G90PeripheralTypes,
|
|
46
46
|
)
|
|
47
|
-
from .local.
|
|
47
|
+
from .local.alert_config import G90AlertConfigFlags
|
|
48
48
|
from .local.host_status import G90HostStatus
|
|
49
49
|
from .const import (
|
|
50
50
|
G90MessageTypes,
|
pyg90alarm/alarm.py
CHANGED
|
@@ -73,6 +73,7 @@ from .const import (
|
|
|
73
73
|
ROOM_ID,
|
|
74
74
|
G90ArmDisarmTypes,
|
|
75
75
|
G90RemoteButtonStates,
|
|
76
|
+
G90RFIDKeypadStates,
|
|
76
77
|
)
|
|
77
78
|
from .local.base_cmd import (G90BaseCommand, G90BaseCommandData)
|
|
78
79
|
from .local.paginated_result import G90PaginatedResult, G90PaginatedResponse
|
|
@@ -95,9 +96,12 @@ from .local.targeted_discovery import (
|
|
|
95
96
|
)
|
|
96
97
|
from .local.host_info import G90HostInfo
|
|
97
98
|
from .local.host_status import G90HostStatus
|
|
98
|
-
from .local.
|
|
99
|
+
from .local.alert_config import (G90AlertConfig, G90AlertConfigFlags)
|
|
99
100
|
from .local.history import G90History
|
|
100
101
|
from .local.user_data_crc import G90UserDataCRC
|
|
102
|
+
from .local.alarm_phones import G90AlarmPhones
|
|
103
|
+
from .local.host_config import G90HostConfig
|
|
104
|
+
from .local.net_config import G90NetConfig
|
|
101
105
|
from .callback import G90Callback, G90CallbackList
|
|
102
106
|
from .exceptions import G90Error, G90TimeoutError
|
|
103
107
|
from .cloud.notifications import G90CloudNotifications
|
|
@@ -146,6 +150,10 @@ if TYPE_CHECKING:
|
|
|
146
150
|
Callable[[int, str], None],
|
|
147
151
|
Callable[[int, str], Coroutine[None, None, None]]
|
|
148
152
|
]
|
|
153
|
+
RFIDKeypadCallback = Union[
|
|
154
|
+
Callable[[int, str, G90RFIDKeypadStates], None],
|
|
155
|
+
Callable[[int, str, G90RFIDKeypadStates], Coroutine[None, None, None]]
|
|
156
|
+
]
|
|
149
157
|
# Sensor-related callbacks for `G90Sensor` class - despite that class
|
|
150
158
|
# stores them, the invocation is done by the `G90Alarm` class hence these
|
|
151
159
|
# are defined here
|
|
@@ -217,6 +225,9 @@ class G90Alarm(G90NotificationProtocol):
|
|
|
217
225
|
self._remote_button_press_cb: G90CallbackList[
|
|
218
226
|
RemoteButtonPressCallback
|
|
219
227
|
] = G90CallbackList()
|
|
228
|
+
self._rfid_keypad_cb: G90CallbackList[
|
|
229
|
+
RFIDKeypadCallback
|
|
230
|
+
] = G90CallbackList()
|
|
220
231
|
self._door_open_when_arming_cb: G90CallbackList[
|
|
221
232
|
DoorOpenWhenArmingCallback
|
|
222
233
|
] = G90CallbackList()
|
|
@@ -484,6 +495,30 @@ class G90Alarm(G90NotificationProtocol):
|
|
|
484
495
|
"""
|
|
485
496
|
await self.alert_config.set(flags)
|
|
486
497
|
|
|
498
|
+
async def alarm_phones(self) -> G90AlarmPhones:
|
|
499
|
+
"""
|
|
500
|
+
Provides access to alarm panel phone numbers.
|
|
501
|
+
|
|
502
|
+
:return: Alarm panel phone numbers
|
|
503
|
+
"""
|
|
504
|
+
return await G90AlarmPhones.load(parent=self)
|
|
505
|
+
|
|
506
|
+
async def host_config(self) -> G90HostConfig:
|
|
507
|
+
"""
|
|
508
|
+
Provides access to alarm panel configuration.
|
|
509
|
+
|
|
510
|
+
:return: Alarm panel configuration
|
|
511
|
+
"""
|
|
512
|
+
return await G90HostConfig.load(parent=self)
|
|
513
|
+
|
|
514
|
+
async def net_config(self) -> G90NetConfig:
|
|
515
|
+
"""
|
|
516
|
+
Provides access to alarm panel network configuration.
|
|
517
|
+
|
|
518
|
+
:return: Alarm panel network configuration
|
|
519
|
+
"""
|
|
520
|
+
return await G90NetConfig.load(parent=self)
|
|
521
|
+
|
|
487
522
|
@property
|
|
488
523
|
async def user_data_crc(self) -> G90UserDataCRC:
|
|
489
524
|
"""
|
|
@@ -566,12 +601,18 @@ class G90Alarm(G90NotificationProtocol):
|
|
|
566
601
|
sensor._set_occupancy(False)
|
|
567
602
|
sensor.state_callback.invoke(sensor.occupancy)
|
|
568
603
|
|
|
569
|
-
|
|
570
|
-
#
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
604
|
+
# Determine if door close notifications are available for the
|
|
605
|
+
# given sensor
|
|
606
|
+
alert_config_flags = await self.alert_config.flags_with_fallback
|
|
607
|
+
if alert_config_flags is None:
|
|
608
|
+
# No alert configuration available, assume door close alerts
|
|
609
|
+
# are disabled
|
|
610
|
+
door_close_alert_enabled = False
|
|
611
|
+
else:
|
|
612
|
+
door_close_alert_enabled = (
|
|
613
|
+
G90AlertConfigFlags.DOOR_CLOSE in alert_config_flags
|
|
614
|
+
)
|
|
615
|
+
|
|
575
616
|
# The condition intentionally doesn't account for cord sensors of
|
|
576
617
|
# subtype door, since those won't send door open/close alerts, only
|
|
577
618
|
# notifications
|
|
@@ -588,7 +629,7 @@ class G90Alarm(G90NotificationProtocol):
|
|
|
588
629
|
' closing event will be emulated upon'
|
|
589
630
|
' %s seconds',
|
|
590
631
|
name, sensor.type,
|
|
591
|
-
alert_config_flags,
|
|
632
|
+
alert_config_flags or 'N/A',
|
|
592
633
|
self._reset_occupancy_interval)
|
|
593
634
|
G90Callback.invoke_delayed(
|
|
594
635
|
self._reset_occupancy_interval,
|
|
@@ -646,7 +687,7 @@ class G90Alarm(G90NotificationProtocol):
|
|
|
646
687
|
is opened or closed (if corresponding alert is configured on the
|
|
647
688
|
device).
|
|
648
689
|
|
|
649
|
-
.. seealso:: :attr:`.sensor_callback` for
|
|
690
|
+
.. seealso:: :attr:`.sensor_callback` for compatibility notes
|
|
650
691
|
"""
|
|
651
692
|
return self._door_open_close_cb
|
|
652
693
|
|
|
@@ -689,7 +730,7 @@ class G90Alarm(G90NotificationProtocol):
|
|
|
689
730
|
The device arm/disarm callback, which is invoked when device state
|
|
690
731
|
changes.
|
|
691
732
|
|
|
692
|
-
.. seealso:: :attr:`.sensor_callback` for
|
|
733
|
+
.. seealso:: :attr:`.sensor_callback` for compatibility notes
|
|
693
734
|
"""
|
|
694
735
|
return self._armdisarm_cb
|
|
695
736
|
|
|
@@ -743,7 +784,7 @@ class G90Alarm(G90NotificationProtocol):
|
|
|
743
784
|
"""
|
|
744
785
|
The device alarm callback, which is invoked when device alarm triggers.
|
|
745
786
|
|
|
746
|
-
.. seealso:: :attr:`.sensor_callback` for
|
|
787
|
+
.. seealso:: :attr:`.sensor_callback` for compatibility notes
|
|
747
788
|
"""
|
|
748
789
|
return self._alarm_cb
|
|
749
790
|
|
|
@@ -779,7 +820,7 @@ class G90Alarm(G90NotificationProtocol):
|
|
|
779
820
|
Low battery callback, which is invoked when sensor reports the
|
|
780
821
|
condition.
|
|
781
822
|
|
|
782
|
-
.. seealso:: :attr:`.sensor_callback` for
|
|
823
|
+
.. seealso:: :attr:`.sensor_callback` for compatibility notes
|
|
783
824
|
"""
|
|
784
825
|
return self._low_battery_cb
|
|
785
826
|
|
|
@@ -824,7 +865,7 @@ class G90Alarm(G90NotificationProtocol):
|
|
|
824
865
|
"""
|
|
825
866
|
SOS callback, which is invoked when SOS alert is triggered.
|
|
826
867
|
|
|
827
|
-
.. seealso:: :attr:`.sensor_callback` for
|
|
868
|
+
.. seealso:: :attr:`.sensor_callback` for compatibility notes
|
|
828
869
|
"""
|
|
829
870
|
return self._sos_cb
|
|
830
871
|
|
|
@@ -862,7 +903,7 @@ class G90Alarm(G90NotificationProtocol):
|
|
|
862
903
|
Remote button press callback, which is invoked when remote button is
|
|
863
904
|
pressed.
|
|
864
905
|
|
|
865
|
-
.. seealso:: :attr:`.sensor_callback` for
|
|
906
|
+
.. seealso:: :attr:`.sensor_callback` for compatibility notes
|
|
866
907
|
"""
|
|
867
908
|
return self._remote_button_press_cb
|
|
868
909
|
|
|
@@ -872,6 +913,53 @@ class G90Alarm(G90NotificationProtocol):
|
|
|
872
913
|
) -> None:
|
|
873
914
|
self._remote_button_press_cb.add(value)
|
|
874
915
|
|
|
916
|
+
async def on_rfid_keypad(
|
|
917
|
+
self, event_id: int, zone_name: str,
|
|
918
|
+
state: G90RFIDKeypadStates
|
|
919
|
+
) -> None:
|
|
920
|
+
"""
|
|
921
|
+
Invoked when RFID keypad event occurs. Fires corresponding callback if
|
|
922
|
+
set by the user with :attr:`.rfid_keypad_callback`.
|
|
923
|
+
|
|
924
|
+
Please note the method is for internal use by the class.
|
|
925
|
+
|
|
926
|
+
:param event_id: Index of the RFID keypad (sensor associated with the
|
|
927
|
+
RFID keypad)
|
|
928
|
+
:param zone_name: Sensor name
|
|
929
|
+
:param state: The RFID keypad state
|
|
930
|
+
"""
|
|
931
|
+
_LOGGER.debug(
|
|
932
|
+
'on_rfid_keypad: %s %s %s', event_id, zone_name, state
|
|
933
|
+
)
|
|
934
|
+
self._rfid_keypad_cb.invoke(event_id, zone_name, state)
|
|
935
|
+
|
|
936
|
+
# Invoke corresponding low battery callback for unification with
|
|
937
|
+
# regular sensors. Note that on_sensor_activity callback is not
|
|
938
|
+
# invoked, since it will reset the low battery flag
|
|
939
|
+
if state == G90RFIDKeypadStates.LOW_BATTERY:
|
|
940
|
+
await self.on_low_battery(event_id, zone_name)
|
|
941
|
+
else:
|
|
942
|
+
# Similar to remote button press, also report the event as sensor
|
|
943
|
+
# activity for unification
|
|
944
|
+
await self.on_sensor_activity(event_id, zone_name, True)
|
|
945
|
+
|
|
946
|
+
@property
|
|
947
|
+
def rfid_keypad_callback(
|
|
948
|
+
self
|
|
949
|
+
) -> G90CallbackList[RFIDKeypadCallback]:
|
|
950
|
+
"""
|
|
951
|
+
RFID keypad callback, which is invoked when RFID keypad event occurs.
|
|
952
|
+
|
|
953
|
+
.. seealso:: :attr:`.sensor_callback` for compatibility notes
|
|
954
|
+
"""
|
|
955
|
+
return self._rfid_keypad_cb
|
|
956
|
+
|
|
957
|
+
@rfid_keypad_callback.setter
|
|
958
|
+
def rfid_keypad_callback(
|
|
959
|
+
self, value: RFIDKeypadCallback
|
|
960
|
+
) -> None:
|
|
961
|
+
self._rfid_keypad_cb.add(value)
|
|
962
|
+
|
|
875
963
|
async def on_door_open_when_arming(
|
|
876
964
|
self, event_id: int, zone_name: str
|
|
877
965
|
) -> None:
|
|
@@ -905,7 +993,7 @@ class G90Alarm(G90NotificationProtocol):
|
|
|
905
993
|
Door open when arming callback, which is invoked when sensor reports
|
|
906
994
|
the condition.
|
|
907
995
|
|
|
908
|
-
.. seealso:: :attr:`.sensor_callback` for
|
|
996
|
+
.. seealso:: :attr:`.sensor_callback` for compatibility notes
|
|
909
997
|
"""
|
|
910
998
|
return self._door_open_when_arming_cb
|
|
911
999
|
|
|
@@ -961,7 +1049,7 @@ class G90Alarm(G90NotificationProtocol):
|
|
|
961
1049
|
Sensor list change callback, which is invoked when sensor list
|
|
962
1050
|
changes.
|
|
963
1051
|
|
|
964
|
-
.. seealso:: :attr:`.sensor_callback` for
|
|
1052
|
+
.. seealso:: :attr:`.sensor_callback` for compatibility notes
|
|
965
1053
|
"""
|
|
966
1054
|
return self._sensor_list_change_cb
|
|
967
1055
|
|
|
@@ -998,7 +1086,7 @@ class G90Alarm(G90NotificationProtocol):
|
|
|
998
1086
|
Device list change callback, which is invoked when device list
|
|
999
1087
|
changes.
|
|
1000
1088
|
|
|
1001
|
-
.. seealso:: :attr:`.sensor_callback` for
|
|
1089
|
+
.. seealso:: :attr:`.sensor_callback` for compatibility notes
|
|
1002
1090
|
"""
|
|
1003
1091
|
return self._device_list_change_cb
|
|
1004
1092
|
|
pyg90alarm/const.py
CHANGED
|
@@ -156,6 +156,7 @@ class G90Commands(IntEnum):
|
|
|
156
156
|
DELALLLOCK = 223
|
|
157
157
|
# Miscellaneous
|
|
158
158
|
GETAPINFO = 212
|
|
159
|
+
SETAPINFO = 213
|
|
159
160
|
PINGBYGPRS = 218
|
|
160
161
|
PING = 219
|
|
161
162
|
|
|
@@ -209,21 +210,48 @@ class G90AlertSources(IntEnum):
|
|
|
209
210
|
DEVICE = 0
|
|
210
211
|
SENSOR = 1
|
|
211
212
|
TAMPER = 3
|
|
213
|
+
INFRARED = 8
|
|
212
214
|
REMOTE = 10
|
|
213
215
|
RFID = 11
|
|
214
216
|
DOORBELL = 12
|
|
215
217
|
FINGERPRINT = 15
|
|
216
218
|
|
|
217
219
|
|
|
220
|
+
class G90CommonSensorAlertStates(IntEnum):
|
|
221
|
+
"""
|
|
222
|
+
Defines possible states of the alert sent by most sensors.
|
|
223
|
+
"""
|
|
224
|
+
DOOR_CLOSE = 0
|
|
225
|
+
DOOR_OPEN = 1
|
|
226
|
+
SOS = 2
|
|
227
|
+
TAMPER = 3
|
|
228
|
+
LOW_BATTERY = 4
|
|
229
|
+
ALARM = 254
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
class G90InfraredAlertStates(IntEnum):
|
|
233
|
+
"""
|
|
234
|
+
Defines possible states of the alerts sent by infrared sensors.
|
|
235
|
+
"""
|
|
236
|
+
MOTION_DETECTED = 0
|
|
237
|
+
TAMPER = 1
|
|
238
|
+
LOW_BATTERY = 2
|
|
239
|
+
|
|
240
|
+
|
|
218
241
|
class G90AlertStates(IntEnum):
|
|
219
242
|
"""
|
|
220
|
-
Defines
|
|
243
|
+
Defines consolidated states of the alert sent by infrared and other
|
|
244
|
+
sensors.
|
|
245
|
+
|
|
246
|
+
By a reason the infrared sensors use different codes for their alert
|
|
247
|
+
states, this enum consolidates them into a single set for unification.
|
|
221
248
|
"""
|
|
222
249
|
DOOR_CLOSE = 0
|
|
223
250
|
DOOR_OPEN = 1
|
|
224
251
|
SOS = 2
|
|
225
252
|
TAMPER = 3
|
|
226
253
|
LOW_BATTERY = 4
|
|
254
|
+
MOTION_DETECTED = 5
|
|
227
255
|
ALARM = 254
|
|
228
256
|
|
|
229
257
|
|
|
@@ -261,6 +289,15 @@ class G90HistoryStates(IntEnum):
|
|
|
261
289
|
REMOTE_BUTTON_ARM_HOME = 14
|
|
262
290
|
REMOTE_BUTTON_DISARM = 15
|
|
263
291
|
REMOTE_BUTTON_SOS = 16
|
|
292
|
+
RFID_KEY_ARM_AWAY = 17
|
|
293
|
+
RFID_KEY_ARM_HOME = 18
|
|
294
|
+
RFID_KEY_DISARM = 19
|
|
295
|
+
RFID_CARD_0 = 20
|
|
296
|
+
RFID_CARD_1 = 21
|
|
297
|
+
RFID_CARD_2 = 22
|
|
298
|
+
RFID_CARD_3 = 23
|
|
299
|
+
RFID_CARD_4 = 24
|
|
300
|
+
MOTION_DETECTED = 25
|
|
264
301
|
|
|
265
302
|
|
|
266
303
|
class G90RemoteButtonStates(IntEnum):
|
|
@@ -271,3 +308,18 @@ class G90RemoteButtonStates(IntEnum):
|
|
|
271
308
|
ARM_HOME = 1
|
|
272
309
|
DISARM = 2
|
|
273
310
|
SOS = 3
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
class G90RFIDKeypadStates(IntEnum):
|
|
314
|
+
"""
|
|
315
|
+
Defines possible states for RFID keypads.
|
|
316
|
+
"""
|
|
317
|
+
ARM_AWAY = 0
|
|
318
|
+
ARM_HOME = 1
|
|
319
|
+
DISARM = 2
|
|
320
|
+
LOW_BATTERY = 5
|
|
321
|
+
CARD_0 = 6
|
|
322
|
+
CARD_1 = 7
|
|
323
|
+
CARD_2 = 8
|
|
324
|
+
CARD_3 = 9
|
|
325
|
+
CARD_4 = 10
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Copyright (c) 2026 Ilia Sotnikov
|
|
2
|
+
#
|
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
# furnished to do so, subject to the following conditions:
|
|
9
|
+
#
|
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
|
11
|
+
# all copies or substantial portions of the Software.
|
|
12
|
+
#
|
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
|
+
# SOFTWARE.
|
|
20
|
+
|
|
21
|
+
"""
|
|
22
|
+
Defines mapping of various events.
|
|
23
|
+
"""
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
from typing import Dict, TYPE_CHECKING
|
|
26
|
+
import logging
|
|
27
|
+
from .const import (
|
|
28
|
+
G90AlertSources,
|
|
29
|
+
G90AlertStates,
|
|
30
|
+
G90CommonSensorAlertStates,
|
|
31
|
+
G90InfraredAlertStates,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
_LOGGER = logging.getLogger(__name__)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def map_alert_state(
|
|
38
|
+
source: G90AlertSources, state: int
|
|
39
|
+
) -> G90AlertStates:
|
|
40
|
+
"""
|
|
41
|
+
Converts alert state of infrared and other sensors to consolidated one.
|
|
42
|
+
|
|
43
|
+
:param source: Source of the alert
|
|
44
|
+
:param state: State code as received from the panel
|
|
45
|
+
:return: Consolidated alert state
|
|
46
|
+
"""
|
|
47
|
+
if TYPE_CHECKING:
|
|
48
|
+
# Forward declarations
|
|
49
|
+
key: G90CommonSensorAlertStates | G90InfraredAlertStates
|
|
50
|
+
mapping: Dict[
|
|
51
|
+
G90CommonSensorAlertStates | G90InfraredAlertStates,
|
|
52
|
+
G90AlertStates
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
# Mapping for common sensors
|
|
56
|
+
mapping = {
|
|
57
|
+
G90CommonSensorAlertStates.DOOR_CLOSE:
|
|
58
|
+
G90AlertStates.DOOR_CLOSE,
|
|
59
|
+
G90CommonSensorAlertStates.DOOR_OPEN:
|
|
60
|
+
G90AlertStates.DOOR_OPEN,
|
|
61
|
+
G90CommonSensorAlertStates.SOS:
|
|
62
|
+
G90AlertStates.SOS,
|
|
63
|
+
G90CommonSensorAlertStates.TAMPER:
|
|
64
|
+
G90AlertStates.TAMPER,
|
|
65
|
+
G90CommonSensorAlertStates.LOW_BATTERY:
|
|
66
|
+
G90AlertStates.LOW_BATTERY,
|
|
67
|
+
G90CommonSensorAlertStates.ALARM:
|
|
68
|
+
G90AlertStates.ALARM,
|
|
69
|
+
}
|
|
70
|
+
key = G90CommonSensorAlertStates(state)
|
|
71
|
+
mapping_kind = 'common'
|
|
72
|
+
|
|
73
|
+
# Mapping for infrared sensors
|
|
74
|
+
if source == G90AlertSources.INFRARED:
|
|
75
|
+
mapping = {
|
|
76
|
+
G90InfraredAlertStates.MOTION_DETECTED:
|
|
77
|
+
G90AlertStates.MOTION_DETECTED,
|
|
78
|
+
G90InfraredAlertStates.TAMPER:
|
|
79
|
+
G90AlertStates.TAMPER,
|
|
80
|
+
G90InfraredAlertStates.LOW_BATTERY:
|
|
81
|
+
G90AlertStates.LOW_BATTERY,
|
|
82
|
+
}
|
|
83
|
+
key = G90InfraredAlertStates(state)
|
|
84
|
+
mapping_kind = 'infrared'
|
|
85
|
+
|
|
86
|
+
try:
|
|
87
|
+
result = mapping[key]
|
|
88
|
+
except KeyError as exc:
|
|
89
|
+
# Raise the error similar to Enum if state is invalid
|
|
90
|
+
raise ValueError(
|
|
91
|
+
f'{state} is not valid for source {source}'
|
|
92
|
+
) from exc
|
|
93
|
+
|
|
94
|
+
_LOGGER.debug(
|
|
95
|
+
'Mapped %s sensor alert state %d to consolidated state %s'
|
|
96
|
+
' for source %s',
|
|
97
|
+
mapping_kind, state, repr(result), repr(source)
|
|
98
|
+
)
|
|
99
|
+
return result
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Copyright (c) 2026 Ilia Sotnikov
|
|
2
|
+
#
|
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
# furnished to do so, subject to the following conditions:
|
|
9
|
+
#
|
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
|
11
|
+
# all copies or substantial portions of the Software.
|
|
12
|
+
#
|
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
|
+
# SOFTWARE.
|
|
20
|
+
"""
|
|
21
|
+
Protocol entity for G90 alarm panel phone numbers.
|
|
22
|
+
"""
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
from typing import Dict, Any
|
|
25
|
+
from dataclasses import dataclass
|
|
26
|
+
from ..const import G90Commands
|
|
27
|
+
from .dataclass_load_save import DataclassLoadSave
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
class G90AlarmPhones(DataclassLoadSave):
|
|
32
|
+
"""
|
|
33
|
+
Interprets data fields of GETALMPHONE/SETALMPHONE commands.
|
|
34
|
+
"""
|
|
35
|
+
# pylint: disable=too-many-instance-attributes
|
|
36
|
+
LOAD_COMMAND = G90Commands.GETALMPHONE
|
|
37
|
+
SAVE_COMMAND = G90Commands.SETALMPHONE
|
|
38
|
+
|
|
39
|
+
# Password to operate the panel via SMS or incoming call.
|
|
40
|
+
panel_password: str
|
|
41
|
+
# Phone number of the alarm panel's SIM card.
|
|
42
|
+
panel_phone_number: str
|
|
43
|
+
# Alarm phone number to be called on alarm.
|
|
44
|
+
# Should be in country code + number format.
|
|
45
|
+
phone_number_1: str
|
|
46
|
+
# Same, but for second alarm phone number.
|
|
47
|
+
phone_number_2: str
|
|
48
|
+
# Same, but for third alarm phone number.
|
|
49
|
+
phone_number_3: str
|
|
50
|
+
# Same, but for fourth alarm phone number.
|
|
51
|
+
phone_number_4: str
|
|
52
|
+
# Same, but for fifth alarm phone number.
|
|
53
|
+
phone_number_5: str
|
|
54
|
+
# Same, but for sixth alarm phone number.
|
|
55
|
+
phone_number_6: str
|
|
56
|
+
# Phone number to send SMS notifications on alarm.
|
|
57
|
+
# Should be in country code + number format.
|
|
58
|
+
sms_push_number_1: str
|
|
59
|
+
# Same, but for second SMS notification phone number.
|
|
60
|
+
sms_push_number_2: str
|
|
61
|
+
|
|
62
|
+
def _asdict(self) -> Dict[str, Any]:
|
|
63
|
+
"""
|
|
64
|
+
Returns the dataclass fields as a dictionary, masking sensitive data.
|
|
65
|
+
"""
|
|
66
|
+
return {
|
|
67
|
+
'panel_password': '********',
|
|
68
|
+
'panel_phone_number': self.panel_phone_number,
|
|
69
|
+
'phone_number_1': self.phone_number_1,
|
|
70
|
+
'phone_number_2': self.phone_number_2,
|
|
71
|
+
'phone_number_3': self.phone_number_3,
|
|
72
|
+
'phone_number_4': self.phone_number_4,
|
|
73
|
+
'phone_number_5': self.phone_number_5,
|
|
74
|
+
'phone_number_6': self.phone_number_6,
|
|
75
|
+
'sms_push_number_1': self.sms_push_number_1,
|
|
76
|
+
'sms_push_number_2': self.sms_push_number_2,
|
|
77
|
+
}
|