pyg90alarm 1.16.1__py3-none-any.whl → 1.17.1__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/alarm.py +100 -2
- pyg90alarm/const.py +17 -0
- pyg90alarm/device_notifications.py +142 -37
- pyg90alarm/history.py +40 -16
- {pyg90alarm-1.16.1.dist-info → pyg90alarm-1.17.1.dist-info}/METADATA +1 -1
- {pyg90alarm-1.16.1.dist-info → pyg90alarm-1.17.1.dist-info}/RECORD +9 -9
- {pyg90alarm-1.16.1.dist-info → pyg90alarm-1.17.1.dist-info}/LICENSE +0 -0
- {pyg90alarm-1.16.1.dist-info → pyg90alarm-1.17.1.dist-info}/WHEEL +0 -0
- {pyg90alarm-1.16.1.dist-info → pyg90alarm-1.17.1.dist-info}/top_level.txt +0 -0
pyg90alarm/alarm.py
CHANGED
|
@@ -63,6 +63,7 @@ from .const import (
|
|
|
63
63
|
LOCAL_NOTIFICATIONS_HOST,
|
|
64
64
|
LOCAL_NOTIFICATIONS_PORT,
|
|
65
65
|
G90ArmDisarmTypes,
|
|
66
|
+
G90RemoteButtonStates,
|
|
66
67
|
)
|
|
67
68
|
from .base_cmd import (G90BaseCommand, G90BaseCommandData)
|
|
68
69
|
from .paginated_result import G90PaginatedResult, G90PaginatedResponse
|
|
@@ -109,8 +110,18 @@ if TYPE_CHECKING:
|
|
|
109
110
|
Callable[[G90ArmDisarmTypes], None],
|
|
110
111
|
Callable[[G90ArmDisarmTypes], Coroutine[None, None, None]]
|
|
111
112
|
]
|
|
113
|
+
SosCallback = Union[
|
|
114
|
+
Callable[[int, str, bool], None],
|
|
115
|
+
Callable[[int, str, bool], Coroutine[None, None, None]]
|
|
116
|
+
]
|
|
117
|
+
RemoteButtonPressCallback = Union[
|
|
118
|
+
Callable[[int, str, G90RemoteButtonStates], None],
|
|
119
|
+
Callable[
|
|
120
|
+
[int, str, G90RemoteButtonStates], Coroutine[None, None, None]
|
|
121
|
+
]
|
|
122
|
+
]
|
|
112
123
|
# Sensor-related callbacks for `G90Sensor` class - despite that class
|
|
113
|
-
# stores them, the
|
|
124
|
+
# stores them, the invocation is done by the `G90Alarm` class hence these
|
|
114
125
|
# are defined here
|
|
115
126
|
SensorStateCallback = Union[
|
|
116
127
|
Callable[[bool], None],
|
|
@@ -157,6 +168,10 @@ class G90Alarm(G90DeviceNotifications):
|
|
|
157
168
|
self._door_open_close_cb: Optional[DoorOpenCloseCallback] = None
|
|
158
169
|
self._alarm_cb: Optional[AlarmCallback] = None
|
|
159
170
|
self._low_battery_cb: Optional[LowBatteryCallback] = None
|
|
171
|
+
self._sos_cb: Optional[SosCallback] = None
|
|
172
|
+
self._remote_button_press_cb: Optional[
|
|
173
|
+
RemoteButtonPressCallback
|
|
174
|
+
] = None
|
|
160
175
|
self._reset_occupancy_interval = reset_occupancy_interval
|
|
161
176
|
self._alert_config: Optional[G90AlertConfigFlags] = None
|
|
162
177
|
self._sms_alert_when_armed = False
|
|
@@ -671,6 +686,86 @@ class G90Alarm(G90DeviceNotifications):
|
|
|
671
686
|
def low_battery_callback(self, value: LowBatteryCallback) -> None:
|
|
672
687
|
self._low_battery_cb = value
|
|
673
688
|
|
|
689
|
+
async def on_sos(
|
|
690
|
+
self, event_id: int, zone_name: str, is_host_sos: bool
|
|
691
|
+
) -> None:
|
|
692
|
+
"""
|
|
693
|
+
Invoked when SOS alert is triggered. Fires corresponding callback if
|
|
694
|
+
set by the user with :attr:`.sos_callback`.
|
|
695
|
+
|
|
696
|
+
Please note the method is for internal use by the class.
|
|
697
|
+
|
|
698
|
+
:param event_id: Index of the sensor triggered alarm
|
|
699
|
+
:param zone_name: Sensor name
|
|
700
|
+
:param is_host_sos:
|
|
701
|
+
Flag indicating if the SOS alert is triggered by the panel itself
|
|
702
|
+
(host)
|
|
703
|
+
"""
|
|
704
|
+
_LOGGER.debug('on_sos: %s %s %s', event_id, zone_name, is_host_sos)
|
|
705
|
+
G90Callback.invoke(self._sos_cb, event_id, zone_name, is_host_sos)
|
|
706
|
+
|
|
707
|
+
# Also report the event as alarm for unification, hard-coding the
|
|
708
|
+
# sensor name in case of host SOS
|
|
709
|
+
await self.on_alarm(event_id, 'Host SOS' if is_host_sos else zone_name)
|
|
710
|
+
|
|
711
|
+
if not is_host_sos:
|
|
712
|
+
# Also report the remote button press for SOS - the panel will not
|
|
713
|
+
# send corresponding alert
|
|
714
|
+
await self.on_remote_button_press(
|
|
715
|
+
event_id, zone_name, G90RemoteButtonStates.SOS
|
|
716
|
+
)
|
|
717
|
+
|
|
718
|
+
@property
|
|
719
|
+
def sos_callback(self) -> Optional[SosCallback]:
|
|
720
|
+
"""
|
|
721
|
+
SOS callback, which is invoked when SOS alert is triggered.
|
|
722
|
+
"""
|
|
723
|
+
return self._sos_cb
|
|
724
|
+
|
|
725
|
+
@sos_callback.setter
|
|
726
|
+
def sos_callback(self, value: SosCallback) -> None:
|
|
727
|
+
self._sos_cb = value
|
|
728
|
+
|
|
729
|
+
async def on_remote_button_press(
|
|
730
|
+
self, event_id: int, zone_name: str, button: G90RemoteButtonStates
|
|
731
|
+
) -> None:
|
|
732
|
+
"""
|
|
733
|
+
Invoked when remote button is pressed. Fires corresponding callback if
|
|
734
|
+
set by the user with :attr:`.remote_button_press_callback`.
|
|
735
|
+
|
|
736
|
+
Please note the method is for internal use by the class.
|
|
737
|
+
|
|
738
|
+
:param event_id: Index of the sensor triggered alarm
|
|
739
|
+
:param zone_name: Sensor name
|
|
740
|
+
:param button: The button pressed
|
|
741
|
+
"""
|
|
742
|
+
_LOGGER.debug(
|
|
743
|
+
'on_remote_button_press: %s %s %s', event_id, zone_name, button
|
|
744
|
+
)
|
|
745
|
+
G90Callback.invoke(
|
|
746
|
+
self._remote_button_press_cb, event_id, zone_name, button
|
|
747
|
+
)
|
|
748
|
+
|
|
749
|
+
# Also report the event as sensor activity for unification (remote is
|
|
750
|
+
# just a special type of the sensor)
|
|
751
|
+
await self.on_sensor_activity(event_id, zone_name, True)
|
|
752
|
+
|
|
753
|
+
@property
|
|
754
|
+
def remote_button_press_callback(
|
|
755
|
+
self
|
|
756
|
+
) -> Optional[RemoteButtonPressCallback]:
|
|
757
|
+
"""
|
|
758
|
+
Remote button press callback, which is invoked when remote button is
|
|
759
|
+
pressed.
|
|
760
|
+
"""
|
|
761
|
+
return self._remote_button_press_cb
|
|
762
|
+
|
|
763
|
+
@remote_button_press_callback.setter
|
|
764
|
+
def remote_button_press_callback(
|
|
765
|
+
self, value: RemoteButtonPressCallback
|
|
766
|
+
) -> None:
|
|
767
|
+
self._remote_button_press_cb = value
|
|
768
|
+
|
|
674
769
|
async def listen_device_notifications(self) -> None:
|
|
675
770
|
"""
|
|
676
771
|
Starts internal listener for device notifications/alerts.
|
|
@@ -820,7 +915,10 @@ class G90Alarm(G90DeviceNotifications):
|
|
|
820
915
|
# notifications port
|
|
821
916
|
self._handle_alert(
|
|
822
917
|
(self._host, self._notifications_local_port),
|
|
823
|
-
item.as_device_alert()
|
|
918
|
+
item.as_device_alert(),
|
|
919
|
+
# Skip verifying device GUID, since history entry
|
|
920
|
+
# don't have it
|
|
921
|
+
verify_device_id=False
|
|
824
922
|
)
|
|
825
923
|
|
|
826
924
|
# Record the entry as most recent one
|
pyg90alarm/const.py
CHANGED
|
@@ -187,8 +187,11 @@ class G90AlertTypes(IntEnum):
|
|
|
187
187
|
"""
|
|
188
188
|
Defines types of alerts sent by the alarm panel.
|
|
189
189
|
"""
|
|
190
|
+
HOST_SOS = 1
|
|
190
191
|
STATE_CHANGE = 2
|
|
191
192
|
ALARM = 3
|
|
193
|
+
SENSOR_ACTIVITY = 4
|
|
194
|
+
# Retained for compatibility, deprecated
|
|
192
195
|
DOOR_OPEN_CLOSE = 4
|
|
193
196
|
|
|
194
197
|
|
|
@@ -245,3 +248,17 @@ class G90HistoryStates(IntEnum):
|
|
|
245
248
|
LOW_BATTERY = 10
|
|
246
249
|
WIFI_CONNECTED = 11
|
|
247
250
|
WIFI_DISCONNECTED = 12
|
|
251
|
+
REMOTE_BUTTON_ARM_AWAY = 13
|
|
252
|
+
REMOTE_BUTTON_ARM_HOME = 14
|
|
253
|
+
REMOTE_BUTTON_DISARM = 15
|
|
254
|
+
REMOTE_BUTTON_SOS = 16
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
class G90RemoteButtonStates(IntEnum):
|
|
258
|
+
"""
|
|
259
|
+
Defines possible states for remote control buttons.
|
|
260
|
+
"""
|
|
261
|
+
ARM_AWAY = 0
|
|
262
|
+
ARM_HOME = 1
|
|
263
|
+
DISARM = 2
|
|
264
|
+
SOS = 3
|
|
@@ -39,6 +39,7 @@ from .const import (
|
|
|
39
39
|
G90ArmDisarmTypes,
|
|
40
40
|
G90AlertSources,
|
|
41
41
|
G90AlertStates,
|
|
42
|
+
G90RemoteButtonStates,
|
|
42
43
|
)
|
|
43
44
|
|
|
44
45
|
_LOGGER = logging.getLogger(__name__)
|
|
@@ -136,11 +137,13 @@ class G90DeviceNotifications(DatagramProtocol):
|
|
|
136
137
|
# Sensor activity notification
|
|
137
138
|
if notification.kind == G90NotificationTypes.SENSOR_ACTIVITY:
|
|
138
139
|
g90_zone_info = G90ZoneInfo(*notification.data)
|
|
140
|
+
|
|
139
141
|
_LOGGER.debug('Sensor notification: %s', g90_zone_info)
|
|
140
142
|
G90Callback.invoke(
|
|
141
143
|
self.on_sensor_activity,
|
|
142
144
|
g90_zone_info.idx, g90_zone_info.name
|
|
143
145
|
)
|
|
146
|
+
|
|
144
147
|
return
|
|
145
148
|
|
|
146
149
|
# Arm/disarm notification
|
|
@@ -149,52 +152,81 @@ class G90DeviceNotifications(DatagramProtocol):
|
|
|
149
152
|
*notification.data)
|
|
150
153
|
# Map the state received from the device to corresponding enum
|
|
151
154
|
state = G90ArmDisarmTypes(g90_armdisarm_info.state)
|
|
155
|
+
|
|
152
156
|
_LOGGER.debug('Arm/disarm notification: %s',
|
|
153
157
|
state)
|
|
154
158
|
G90Callback.invoke(self.on_armdisarm, state)
|
|
159
|
+
|
|
155
160
|
return
|
|
156
161
|
|
|
157
162
|
_LOGGER.warning('Unknown notification received from %s:%s:'
|
|
158
163
|
' kind %s, data %s',
|
|
159
164
|
addr[0], addr[1], notification.kind, notification.data)
|
|
160
165
|
|
|
166
|
+
def _handle_alert_sensor_activity(self, alert: G90DeviceAlert) -> bool:
|
|
167
|
+
"""
|
|
168
|
+
Handles sensor activity alert.
|
|
169
|
+
"""
|
|
170
|
+
if alert.source == G90AlertSources.REMOTE:
|
|
171
|
+
_LOGGER.debug('Remote button press alert: %s', alert)
|
|
172
|
+
G90Callback.invoke(
|
|
173
|
+
self.on_remote_button_press,
|
|
174
|
+
alert.event_id, alert.zone_name,
|
|
175
|
+
G90RemoteButtonStates(alert.state)
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
return True
|
|
179
|
+
|
|
180
|
+
if alert.state in (
|
|
181
|
+
G90AlertStates.DOOR_OPEN, G90AlertStates.DOOR_CLOSE
|
|
182
|
+
):
|
|
183
|
+
is_open = (
|
|
184
|
+
alert.source == G90AlertSources.SENSOR
|
|
185
|
+
and alert.state == G90AlertStates.DOOR_OPEN # noqa: W503
|
|
186
|
+
) or alert.source == G90AlertSources.DOORBELL
|
|
187
|
+
|
|
188
|
+
_LOGGER.debug('Door open_close alert: %s', alert)
|
|
189
|
+
G90Callback.invoke(
|
|
190
|
+
self.on_door_open_close,
|
|
191
|
+
alert.event_id, alert.zone_name, is_open
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
return True
|
|
195
|
+
|
|
196
|
+
if (
|
|
197
|
+
alert.source == G90AlertSources.SENSOR
|
|
198
|
+
and alert.state == G90AlertStates.LOW_BATTERY # noqa: W503
|
|
199
|
+
):
|
|
200
|
+
_LOGGER.debug('Low battery alert: %s', alert)
|
|
201
|
+
G90Callback.invoke(
|
|
202
|
+
self.on_low_battery,
|
|
203
|
+
alert.event_id, alert.zone_name
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
return True
|
|
207
|
+
|
|
208
|
+
return False
|
|
209
|
+
|
|
161
210
|
def _handle_alert(
|
|
162
|
-
self, addr: Tuple[str, int], alert: G90DeviceAlert
|
|
211
|
+
self, addr: Tuple[str, int], alert: G90DeviceAlert,
|
|
212
|
+
verify_device_id: bool = True
|
|
163
213
|
) -> None:
|
|
214
|
+
handled = False
|
|
215
|
+
|
|
164
216
|
# Stop processing when alert is received from the device with different
|
|
165
|
-
# GUID
|
|
166
|
-
if
|
|
217
|
+
# GUID (if enabled)
|
|
218
|
+
if (
|
|
219
|
+
verify_device_id and self.device_id
|
|
220
|
+
and alert.device_id != self.device_id
|
|
221
|
+
):
|
|
167
222
|
_LOGGER.error(
|
|
168
223
|
"Received alert from wrong device: expected '%s', got '%s'",
|
|
169
224
|
self.device_id, alert.device_id
|
|
170
225
|
)
|
|
171
226
|
return
|
|
172
227
|
|
|
173
|
-
if alert.type == G90AlertTypes.
|
|
174
|
-
|
|
175
|
-
G90AlertStates.DOOR_OPEN, G90AlertStates.DOOR_CLOSE
|
|
176
|
-
):
|
|
177
|
-
is_open = (
|
|
178
|
-
alert.source == G90AlertSources.SENSOR
|
|
179
|
-
and alert.state == G90AlertStates.DOOR_OPEN # noqa: W503
|
|
180
|
-
) or alert.source == G90AlertSources.DOORBELL
|
|
181
|
-
_LOGGER.debug('Door open_close alert: %s', alert)
|
|
182
|
-
G90Callback.invoke(
|
|
183
|
-
self.on_door_open_close,
|
|
184
|
-
alert.event_id, alert.zone_name, is_open
|
|
185
|
-
)
|
|
186
|
-
return
|
|
187
|
-
|
|
188
|
-
if (
|
|
189
|
-
alert.source == G90AlertSources.SENSOR
|
|
190
|
-
and alert.state == G90AlertStates.LOW_BATTERY # noqa: W503
|
|
191
|
-
):
|
|
192
|
-
_LOGGER.debug('Low battery alert: %s', alert)
|
|
193
|
-
G90Callback.invoke(
|
|
194
|
-
self.on_low_battery,
|
|
195
|
-
alert.event_id, alert.zone_name
|
|
196
|
-
)
|
|
197
|
-
return
|
|
228
|
+
if alert.type == G90AlertTypes.SENSOR_ACTIVITY:
|
|
229
|
+
handled = self._handle_alert_sensor_activity(alert)
|
|
198
230
|
|
|
199
231
|
if alert.type == G90AlertTypes.STATE_CHANGE:
|
|
200
232
|
# Define the mapping between device state received in the alert, to
|
|
@@ -209,25 +241,46 @@ class G90DeviceNotifications(DatagramProtocol):
|
|
|
209
241
|
G90AlertStateChangeTypes.DISARM: G90ArmDisarmTypes.DISARM
|
|
210
242
|
}
|
|
211
243
|
|
|
212
|
-
state = alarm_arm_disarm_state_map.get(alert.event_id)
|
|
244
|
+
state = alarm_arm_disarm_state_map.get(alert.event_id, None)
|
|
213
245
|
if state:
|
|
214
246
|
# We received the device state change related to arm/disarm,
|
|
215
247
|
# invoke the corresponding callback
|
|
216
248
|
_LOGGER.debug('Arm/disarm state change: %s', state)
|
|
217
249
|
G90Callback.invoke(self.on_armdisarm, state)
|
|
218
|
-
|
|
250
|
+
|
|
251
|
+
handled = True
|
|
219
252
|
|
|
220
253
|
if alert.type == G90AlertTypes.ALARM:
|
|
221
|
-
|
|
254
|
+
# Remote SOS
|
|
255
|
+
if alert.source == G90AlertSources.REMOTE:
|
|
256
|
+
_LOGGER.debug('SOS: %s', alert.zone_name)
|
|
257
|
+
G90Callback.invoke(
|
|
258
|
+
self.on_sos, alert.event_id, alert.zone_name, False
|
|
259
|
+
)
|
|
260
|
+
# Regular alarm
|
|
261
|
+
else:
|
|
262
|
+
_LOGGER.debug('Alarm: %s', alert.zone_name)
|
|
263
|
+
G90Callback.invoke(
|
|
264
|
+
self.on_alarm,
|
|
265
|
+
alert.event_id, alert.zone_name
|
|
266
|
+
)
|
|
267
|
+
handled = True
|
|
268
|
+
|
|
269
|
+
# Host SOS
|
|
270
|
+
if alert.type == G90AlertTypes.HOST_SOS:
|
|
271
|
+
zone_name = 'Host SOS'
|
|
272
|
+
|
|
273
|
+
_LOGGER.debug('SOS: Host')
|
|
222
274
|
G90Callback.invoke(
|
|
223
|
-
self.
|
|
224
|
-
alert.event_id, alert.zone_name
|
|
275
|
+
self.on_sos, alert.event_id, zone_name, True
|
|
225
276
|
)
|
|
226
|
-
return
|
|
227
277
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
278
|
+
handled = True
|
|
279
|
+
|
|
280
|
+
if not handled:
|
|
281
|
+
_LOGGER.warning('Unknown alert received from %s:%s:'
|
|
282
|
+
' type %s, data %s',
|
|
283
|
+
addr[0], addr[1], alert.type, alert)
|
|
231
284
|
|
|
232
285
|
# Implementation of datagram protocol,
|
|
233
286
|
# https://docs.python.org/3/library/asyncio-protocol.html#datagram-protocols
|
|
@@ -307,11 +360,16 @@ class G90DeviceNotifications(DatagramProtocol):
|
|
|
307
360
|
async def on_armdisarm(self, state: G90ArmDisarmTypes) -> None:
|
|
308
361
|
"""
|
|
309
362
|
Invoked when device is armed or disarmed.
|
|
363
|
+
|
|
364
|
+
:param state: State of the device
|
|
310
365
|
"""
|
|
311
366
|
|
|
312
367
|
async def on_sensor_activity(self, idx: int, name: str) -> None:
|
|
313
368
|
"""
|
|
314
369
|
Invoked on sensor activity.
|
|
370
|
+
|
|
371
|
+
:param idx: Index of the sensor.
|
|
372
|
+
:param name: Name of the sensor.
|
|
315
373
|
"""
|
|
316
374
|
|
|
317
375
|
async def on_door_open_close(
|
|
@@ -319,16 +377,55 @@ class G90DeviceNotifications(DatagramProtocol):
|
|
|
319
377
|
) -> None:
|
|
320
378
|
"""
|
|
321
379
|
Invoked when door sensor reports it opened or closed.
|
|
380
|
+
|
|
381
|
+
:param event_id: Index of the sensor reporting the event.
|
|
382
|
+
:param zone_name: Name of the sensor that reports door open/close.
|
|
383
|
+
:param is_open: Indicates if the door is open.
|
|
322
384
|
"""
|
|
323
385
|
|
|
324
386
|
async def on_low_battery(self, event_id: int, zone_name: str) -> None:
|
|
325
387
|
"""
|
|
326
388
|
Invoked when a sensor reports it is low on battery.
|
|
389
|
+
|
|
390
|
+
:param event_id: Index of the sensor.
|
|
391
|
+
:param zone_name: Name of the sensor that reports low battery.
|
|
327
392
|
"""
|
|
328
393
|
|
|
329
394
|
async def on_alarm(self, event_id: int, zone_name: str) -> None:
|
|
330
395
|
"""
|
|
331
396
|
Invoked when device triggers the alarm.
|
|
397
|
+
|
|
398
|
+
:param event_id: Index of the sensor.
|
|
399
|
+
:param zone_name: Name of the zone that triggered the alarm.
|
|
400
|
+
"""
|
|
401
|
+
|
|
402
|
+
async def on_remote_button_press(
|
|
403
|
+
self, event_id: int, zone_name: str, button: G90RemoteButtonStates
|
|
404
|
+
) -> None:
|
|
405
|
+
"""
|
|
406
|
+
Invoked when a remote button is pressed.
|
|
407
|
+
|
|
408
|
+
Please note there will only be call to the method w/o invoking
|
|
409
|
+
:meth:`G90DeviceNotifications.on_sensor_activity`.
|
|
410
|
+
|
|
411
|
+
:param event_id: Index of the sensor associated with the remote.
|
|
412
|
+
:param zone_name: Name of the sensor that reports remote button press.
|
|
413
|
+
:param button: The button pressed on the remote
|
|
414
|
+
"""
|
|
415
|
+
|
|
416
|
+
async def on_sos(
|
|
417
|
+
self, event_id: int, zone_name: str, is_host_sos: bool
|
|
418
|
+
) -> None:
|
|
419
|
+
"""
|
|
420
|
+
Invoked when SOS is triggered.
|
|
421
|
+
|
|
422
|
+
Please note that the panel might not set its status to alarm
|
|
423
|
+
internally, so that :meth:`G90DeviceNotifications` might need an
|
|
424
|
+
explicit call in the derived class to simulate that.
|
|
425
|
+
|
|
426
|
+
:param event_id: Index of the sensor.
|
|
427
|
+
:param zone_name: Name of the sensor that reports SOS.
|
|
428
|
+
:param is_host_sos: Indicates if the SOS is host-initiated.
|
|
332
429
|
"""
|
|
333
430
|
|
|
334
431
|
async def listen(self) -> None:
|
|
@@ -378,4 +475,12 @@ class G90DeviceNotifications(DatagramProtocol):
|
|
|
378
475
|
|
|
379
476
|
@device_id.setter
|
|
380
477
|
def device_id(self, device_id: str) -> None:
|
|
478
|
+
# Under not yet identified circumstances the device ID might be empty
|
|
479
|
+
# string provided by :meth:`G90Alarm.get_host_info` - disallow that
|
|
480
|
+
if not device_id or len(device_id.strip()) == 0:
|
|
481
|
+
_LOGGER.debug(
|
|
482
|
+
'Device ID is empty or contains whitespace only, not setting'
|
|
483
|
+
)
|
|
484
|
+
return
|
|
485
|
+
|
|
381
486
|
self._device_id = device_id
|
pyg90alarm/history.py
CHANGED
|
@@ -32,15 +32,17 @@ from .const import (
|
|
|
32
32
|
G90AlertStates,
|
|
33
33
|
G90AlertStateChangeTypes,
|
|
34
34
|
G90HistoryStates,
|
|
35
|
+
G90RemoteButtonStates,
|
|
35
36
|
)
|
|
36
37
|
from .device_notifications import G90DeviceAlert
|
|
37
38
|
|
|
38
39
|
_LOGGER = logging.getLogger(__name__)
|
|
39
40
|
|
|
40
41
|
|
|
41
|
-
# The state of the incoming history entries are mixed of `G90AlertStates
|
|
42
|
-
# `G90AlertStateChangeTypes`, depending on entry
|
|
43
|
-
# dictionaries, since enums used for keys have
|
|
42
|
+
# The state of the incoming history entries are mixed of `G90AlertStates`,
|
|
43
|
+
# `G90AlertStateChangeTypes` and `G90RemoteButtonStates`, depending on entry
|
|
44
|
+
# type - hence separate dictionaries, since enums used for keys have
|
|
45
|
+
# conflicting values
|
|
44
46
|
states_mapping_alerts = {
|
|
45
47
|
G90AlertStates.DOOR_CLOSE:
|
|
46
48
|
G90HistoryStates.DOOR_CLOSE,
|
|
@@ -71,6 +73,17 @@ states_mapping_state_changes = {
|
|
|
71
73
|
G90HistoryStates.WIFI_DISCONNECTED,
|
|
72
74
|
}
|
|
73
75
|
|
|
76
|
+
states_mapping_remote_buttons = {
|
|
77
|
+
G90RemoteButtonStates.ARM_AWAY:
|
|
78
|
+
G90HistoryStates.REMOTE_BUTTON_ARM_AWAY,
|
|
79
|
+
G90RemoteButtonStates.ARM_HOME:
|
|
80
|
+
G90HistoryStates.REMOTE_BUTTON_ARM_HOME,
|
|
81
|
+
G90RemoteButtonStates.DISARM:
|
|
82
|
+
G90HistoryStates.REMOTE_BUTTON_DISARM,
|
|
83
|
+
G90RemoteButtonStates.SOS:
|
|
84
|
+
G90HistoryStates.REMOTE_BUTTON_SOS,
|
|
85
|
+
}
|
|
86
|
+
|
|
74
87
|
|
|
75
88
|
@dataclass
|
|
76
89
|
class ProtocolData:
|
|
@@ -112,7 +125,7 @@ class G90History:
|
|
|
112
125
|
"""
|
|
113
126
|
try:
|
|
114
127
|
return G90AlertTypes(self._protocol_data.type)
|
|
115
|
-
except ValueError:
|
|
128
|
+
except (ValueError, KeyError):
|
|
116
129
|
_LOGGER.warning(
|
|
117
130
|
"Can't interpret '%s' as alert type (decoded protocol"
|
|
118
131
|
" data '%s', raw data '%s')",
|
|
@@ -125,18 +138,33 @@ class G90History:
|
|
|
125
138
|
"""
|
|
126
139
|
State for the history entry.
|
|
127
140
|
"""
|
|
141
|
+
# No meaningful state for SOS alerts initiated by the panel itself
|
|
142
|
+
# (host)
|
|
143
|
+
if self.type == G90AlertTypes.HOST_SOS:
|
|
144
|
+
return None
|
|
145
|
+
|
|
128
146
|
try:
|
|
147
|
+
# State of the remote indicate which button has been pressed
|
|
148
|
+
if (
|
|
149
|
+
self.type in [
|
|
150
|
+
G90AlertTypes.SENSOR_ACTIVITY, G90AlertTypes.ALARM
|
|
151
|
+
] and self.source == G90AlertSources.REMOTE
|
|
152
|
+
):
|
|
153
|
+
return states_mapping_remote_buttons[
|
|
154
|
+
G90RemoteButtonStates(self._protocol_data.state)
|
|
155
|
+
]
|
|
156
|
+
|
|
129
157
|
# Door open/close or alert types, mapped against `G90AlertStates`
|
|
130
158
|
# using `state` incoming field
|
|
131
159
|
if self.type in [
|
|
132
|
-
G90AlertTypes.
|
|
160
|
+
G90AlertTypes.SENSOR_ACTIVITY, G90AlertTypes.ALARM
|
|
133
161
|
]:
|
|
134
162
|
return G90HistoryStates(
|
|
135
163
|
states_mapping_alerts[
|
|
136
164
|
G90AlertStates(self._protocol_data.state)
|
|
137
165
|
]
|
|
138
166
|
)
|
|
139
|
-
except ValueError:
|
|
167
|
+
except (ValueError, KeyError):
|
|
140
168
|
_LOGGER.warning(
|
|
141
169
|
"Can't interpret '%s' as alert state (decoded protocol"
|
|
142
170
|
" data '%s', raw data '%s')",
|
|
@@ -151,7 +179,7 @@ class G90History:
|
|
|
151
179
|
G90AlertStateChangeTypes(self._protocol_data.event_id)
|
|
152
180
|
]
|
|
153
181
|
)
|
|
154
|
-
except ValueError:
|
|
182
|
+
except (ValueError, KeyError):
|
|
155
183
|
_LOGGER.warning(
|
|
156
184
|
"Can't interpret '%s' as state change (decoded protocol"
|
|
157
185
|
" data '%s', raw data '%s')",
|
|
@@ -166,13 +194,14 @@ class G90History:
|
|
|
166
194
|
Source of the history entry.
|
|
167
195
|
"""
|
|
168
196
|
try:
|
|
169
|
-
# Device state changes
|
|
170
|
-
# `G90AlertSources` using `source` incoming field
|
|
197
|
+
# Device state changes, open/close or alarm events are mapped
|
|
198
|
+
# against `G90AlertSources` using `source` incoming field
|
|
171
199
|
if self.type in [
|
|
172
|
-
G90AlertTypes.STATE_CHANGE, G90AlertTypes.
|
|
200
|
+
G90AlertTypes.STATE_CHANGE, G90AlertTypes.SENSOR_ACTIVITY,
|
|
201
|
+
G90AlertTypes.ALARM
|
|
173
202
|
]:
|
|
174
203
|
return G90AlertSources(self._protocol_data.source)
|
|
175
|
-
except ValueError:
|
|
204
|
+
except (ValueError, KeyError):
|
|
176
205
|
_LOGGER.warning(
|
|
177
206
|
"Can't interpret '%s' as alert source (decoded protocol"
|
|
178
207
|
" data '%s', raw data '%s')",
|
|
@@ -180,11 +209,6 @@ class G90History:
|
|
|
180
209
|
)
|
|
181
210
|
return None
|
|
182
211
|
|
|
183
|
-
# Alarm will have `SENSOR` as the source, since that is likely what
|
|
184
|
-
# triggered it
|
|
185
|
-
if self.type == G90AlertTypes.ALARM:
|
|
186
|
-
return G90AlertSources.SENSOR
|
|
187
|
-
|
|
188
212
|
# Other sources are assumed to be initiated by device itself
|
|
189
213
|
return G90AlertSources.DEVICE
|
|
190
214
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
pyg90alarm/__init__.py,sha256=5AITRm5jZSzuQaL7PS8fZZMZb4-IuGRhSqyAdfTt0Cs,2236
|
|
2
|
-
pyg90alarm/alarm.py,sha256=
|
|
2
|
+
pyg90alarm/alarm.py,sha256=GMft1R4Yp70VeWQLHApE8yVcfsDBbzhbHj1rc_gIj8k,35947
|
|
3
3
|
pyg90alarm/base_cmd.py,sha256=Bz7yoZ0RpkcjWARya664DKAPo3goD6BeaKtuW-hA804,9902
|
|
4
4
|
pyg90alarm/callback.py,sha256=3JsD_JChmZD24OyjaCP-PxxuBDBX7myGYhkM4RN7bk4,3742
|
|
5
5
|
pyg90alarm/config.py,sha256=2YtIgdT7clQXmYvkdn_fhIdS05CY8E1Yc90R8_tAmRI,1961
|
|
6
|
-
pyg90alarm/const.py,sha256=
|
|
7
|
-
pyg90alarm/device_notifications.py,sha256=
|
|
6
|
+
pyg90alarm/const.py,sha256=0EkfCtySEPi6W0TO-j-F1y7_MVFaMOuKDY1Bx6QGDDQ,6617
|
|
7
|
+
pyg90alarm/device_notifications.py,sha256=61oruR70snBRXNzOfj313TO7p2TmbEk-dH9AA1nkDkY,16687
|
|
8
8
|
pyg90alarm/discovery.py,sha256=fwyBHDCKGej06OwhpbVCHYTRU9WWkeYysAFgv3FiwqI,3575
|
|
9
9
|
pyg90alarm/exceptions.py,sha256=eiOcRe7D18EIPyPFDNU9DdFgbnkwPmkiLl8lGPOhBNw,1475
|
|
10
|
-
pyg90alarm/history.py,sha256=
|
|
10
|
+
pyg90alarm/history.py,sha256=5NfgB0V-7TZlMNHEjtRbOA0ZtJfQTgh2ysZIg5RM7ck,9080
|
|
11
11
|
pyg90alarm/host_info.py,sha256=4lFIaFEpYd3EvgNrDJmKijTrzX9i29nFISLLlXGnkmE,2759
|
|
12
12
|
pyg90alarm/host_status.py,sha256=4XhuilBzB8XsXkpeWj3PAVpmDPcTnBBOYunO21Flabo,1862
|
|
13
13
|
pyg90alarm/paginated_cmd.py,sha256=vJ8slMS7aNLpkAxnIe25EHstusYy1bYTl1j306ps-MQ,4439
|
|
@@ -20,8 +20,8 @@ pyg90alarm/definitions/sensors.py,sha256=rKOu21ZpI44xk6aMh_vBjniFqnsNTc1CKwAvnv4
|
|
|
20
20
|
pyg90alarm/entities/__init__.py,sha256=hHb6AOiC4Tz--rOWiiICMdLaZDs1Tf_xpWk_HeS_gO4,66
|
|
21
21
|
pyg90alarm/entities/device.py,sha256=f_LHvKCAqTEebZ4mrRh3CpPUI7o-OvpvOfyTRCbftJs,2818
|
|
22
22
|
pyg90alarm/entities/sensor.py,sha256=4r8ouAYTZB8ih8I4ncWdQOaifYsRxaC-ukY9jvnrRvk,16139
|
|
23
|
-
pyg90alarm-1.
|
|
24
|
-
pyg90alarm-1.
|
|
25
|
-
pyg90alarm-1.
|
|
26
|
-
pyg90alarm-1.
|
|
27
|
-
pyg90alarm-1.
|
|
23
|
+
pyg90alarm-1.17.1.dist-info/LICENSE,sha256=f884inRbeNv-O-hbwz62Ro_1J8xiHRTnJ2cCx6A0WvU,1070
|
|
24
|
+
pyg90alarm-1.17.1.dist-info/METADATA,sha256=7lYmor4_swZNNn3P2yF7FRse5Hz4X3xpgAeNE55t0LA,7714
|
|
25
|
+
pyg90alarm-1.17.1.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
26
|
+
pyg90alarm-1.17.1.dist-info/top_level.txt,sha256=czHiGxYMyTk5QEDTDb0EpPiKqUMRa8zI4zx58Ii409M,11
|
|
27
|
+
pyg90alarm-1.17.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|