pyg90alarm 1.10.0__py3-none-any.whl → 1.12.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 +192 -35
- pyg90alarm/base_cmd.py +49 -83
- pyg90alarm/const.py +30 -0
- pyg90alarm/definitions/sensors.py +241 -1
- pyg90alarm/device_notifications.py +103 -82
- pyg90alarm/discovery.py +11 -43
- pyg90alarm/entities/sensor.py +20 -0
- pyg90alarm/history.py +174 -12
- pyg90alarm/targeted_discovery.py +9 -44
- {pyg90alarm-1.10.0.dist-info → pyg90alarm-1.12.1.dist-info}/METADATA +13 -6
- pyg90alarm-1.12.1.dist-info/RECORD +26 -0
- {pyg90alarm-1.10.0.dist-info → pyg90alarm-1.12.1.dist-info}/WHEEL +1 -1
- pyg90alarm-1.10.0.dist-info/RECORD +0 -26
- {pyg90alarm-1.10.0.dist-info → pyg90alarm-1.12.1.dist-info}/LICENSE +0 -0
- {pyg90alarm-1.10.0.dist-info → pyg90alarm-1.12.1.dist-info}/top_level.txt +0 -0
|
@@ -475,6 +475,16 @@ SENSOR_DEFINITIONS = [
|
|
|
475
475
|
rwMode=SensorRwMode.READ,
|
|
476
476
|
matchMode=SensorMatchMode.ONLY20BITS
|
|
477
477
|
),
|
|
478
|
+
# Door Sensor WRDS01
|
|
479
|
+
SensorDefinition(
|
|
480
|
+
type=1,
|
|
481
|
+
subtype=3,
|
|
482
|
+
rx=0,
|
|
483
|
+
tx=0,
|
|
484
|
+
private_data='00',
|
|
485
|
+
rwMode=SensorRwMode.READ,
|
|
486
|
+
matchMode=SensorMatchMode.ALL
|
|
487
|
+
),
|
|
478
488
|
# Door Sensor
|
|
479
489
|
SensorDefinition(
|
|
480
490
|
type=1,
|
|
@@ -485,6 +495,96 @@ SENSOR_DEFINITIONS = [
|
|
|
485
495
|
rwMode=SensorRwMode.READ,
|
|
486
496
|
matchMode=SensorMatchMode.ONLY16BITS
|
|
487
497
|
),
|
|
498
|
+
# Glass Break Sensor BLPS
|
|
499
|
+
SensorDefinition(
|
|
500
|
+
type=2,
|
|
501
|
+
subtype=0,
|
|
502
|
+
rx=0,
|
|
503
|
+
tx=0,
|
|
504
|
+
private_data='00',
|
|
505
|
+
rwMode=SensorRwMode.READ,
|
|
506
|
+
matchMode=SensorMatchMode.ALL
|
|
507
|
+
),
|
|
508
|
+
# Gas Detector WGD01
|
|
509
|
+
SensorDefinition(
|
|
510
|
+
type=3,
|
|
511
|
+
subtype=0,
|
|
512
|
+
rx=0,
|
|
513
|
+
tx=0,
|
|
514
|
+
private_data='00',
|
|
515
|
+
rwMode=SensorRwMode.READ,
|
|
516
|
+
matchMode=SensorMatchMode.ALL
|
|
517
|
+
),
|
|
518
|
+
# Smoke Detector WSD02
|
|
519
|
+
SensorDefinition(
|
|
520
|
+
type=4,
|
|
521
|
+
subtype=0,
|
|
522
|
+
rx=0,
|
|
523
|
+
tx=0,
|
|
524
|
+
private_data='00',
|
|
525
|
+
rwMode=SensorRwMode.READ,
|
|
526
|
+
matchMode=SensorMatchMode.ALL
|
|
527
|
+
),
|
|
528
|
+
# Smoke Detector WSD04
|
|
529
|
+
SensorDefinition(
|
|
530
|
+
type=4,
|
|
531
|
+
subtype=1,
|
|
532
|
+
rx=0,
|
|
533
|
+
tx=0,
|
|
534
|
+
private_data='00',
|
|
535
|
+
rwMode=SensorRwMode.READ,
|
|
536
|
+
matchMode=SensorMatchMode.ALL
|
|
537
|
+
),
|
|
538
|
+
# Panic Button WEB01
|
|
539
|
+
SensorDefinition(
|
|
540
|
+
type=5,
|
|
541
|
+
subtype=1,
|
|
542
|
+
rx=0,
|
|
543
|
+
tx=0,
|
|
544
|
+
private_data='00',
|
|
545
|
+
rwMode=SensorRwMode.READ,
|
|
546
|
+
matchMode=SensorMatchMode.ALL
|
|
547
|
+
),
|
|
548
|
+
# Panic Button WEB03
|
|
549
|
+
SensorDefinition(
|
|
550
|
+
type=5,
|
|
551
|
+
subtype=0,
|
|
552
|
+
rx=0,
|
|
553
|
+
tx=0,
|
|
554
|
+
private_data='00',
|
|
555
|
+
rwMode=SensorRwMode.READ,
|
|
556
|
+
matchMode=SensorMatchMode.ALL
|
|
557
|
+
),
|
|
558
|
+
# Shock Sensor WSS01
|
|
559
|
+
SensorDefinition(
|
|
560
|
+
type=6,
|
|
561
|
+
subtype=0,
|
|
562
|
+
rx=0,
|
|
563
|
+
tx=0,
|
|
564
|
+
private_data='00',
|
|
565
|
+
rwMode=SensorRwMode.READ,
|
|
566
|
+
matchMode=SensorMatchMode.ALL
|
|
567
|
+
),
|
|
568
|
+
# Water Detector LSTC02
|
|
569
|
+
SensorDefinition(
|
|
570
|
+
type=7,
|
|
571
|
+
subtype=1,
|
|
572
|
+
rx=0,
|
|
573
|
+
tx=0,
|
|
574
|
+
private_data='',
|
|
575
|
+
rwMode=SensorRwMode.READ,
|
|
576
|
+
matchMode=SensorMatchMode.ALL
|
|
577
|
+
),
|
|
578
|
+
# Water Detector LSTC01
|
|
579
|
+
SensorDefinition(
|
|
580
|
+
type=7,
|
|
581
|
+
subtype=0,
|
|
582
|
+
rx=0,
|
|
583
|
+
tx=0,
|
|
584
|
+
private_data='00',
|
|
585
|
+
rwMode=SensorRwMode.READ,
|
|
586
|
+
matchMode=SensorMatchMode.ALL
|
|
587
|
+
),
|
|
488
588
|
# PIR motion sensor WMS08
|
|
489
589
|
SensorDefinition(
|
|
490
590
|
type=8,
|
|
@@ -505,6 +605,66 @@ SENSOR_DEFINITIONS = [
|
|
|
505
605
|
rwMode=SensorRwMode.READ,
|
|
506
606
|
matchMode=SensorMatchMode.ONLY20BITS
|
|
507
607
|
),
|
|
608
|
+
# PIR motion sensor ODPIR
|
|
609
|
+
SensorDefinition(
|
|
610
|
+
type=8,
|
|
611
|
+
subtype=0,
|
|
612
|
+
rx=0,
|
|
613
|
+
tx=0,
|
|
614
|
+
private_data='00',
|
|
615
|
+
rwMode=SensorRwMode.READ,
|
|
616
|
+
matchMode=SensorMatchMode.ALL
|
|
617
|
+
),
|
|
618
|
+
# PIR motion sensor N650
|
|
619
|
+
SensorDefinition(
|
|
620
|
+
type=8,
|
|
621
|
+
subtype=5,
|
|
622
|
+
rx=0,
|
|
623
|
+
tx=0,
|
|
624
|
+
private_data='00',
|
|
625
|
+
rwMode=SensorRwMode.READ,
|
|
626
|
+
matchMode=SensorMatchMode.ALL
|
|
627
|
+
),
|
|
628
|
+
# PIR motion sensor WPD02
|
|
629
|
+
SensorDefinition(
|
|
630
|
+
type=8,
|
|
631
|
+
subtype=6,
|
|
632
|
+
rx=0,
|
|
633
|
+
tx=0,
|
|
634
|
+
private_data='00',
|
|
635
|
+
rwMode=SensorRwMode.READ,
|
|
636
|
+
matchMode=SensorMatchMode.ALL
|
|
637
|
+
),
|
|
638
|
+
# PIR motion sensor WCMS02
|
|
639
|
+
SensorDefinition(
|
|
640
|
+
type=8,
|
|
641
|
+
subtype=8,
|
|
642
|
+
rx=0,
|
|
643
|
+
tx=0,
|
|
644
|
+
private_data='00',
|
|
645
|
+
rwMode=SensorRwMode.READ,
|
|
646
|
+
matchMode=SensorMatchMode.ALL
|
|
647
|
+
),
|
|
648
|
+
# PIR motion sensor CWMS01
|
|
649
|
+
SensorDefinition(
|
|
650
|
+
type=8,
|
|
651
|
+
subtype=9,
|
|
652
|
+
rx=0,
|
|
653
|
+
tx=0,
|
|
654
|
+
private_data='00',
|
|
655
|
+
rwMode=SensorRwMode.READ,
|
|
656
|
+
matchMode=SensorMatchMode.ALL
|
|
657
|
+
),
|
|
658
|
+
# PIR motion sensor WMS04
|
|
659
|
+
SensorDefinition(
|
|
660
|
+
type=8,
|
|
661
|
+
subtype=11,
|
|
662
|
+
rx=0,
|
|
663
|
+
tx=0,
|
|
664
|
+
private_data='00',
|
|
665
|
+
rwMode=SensorRwMode.READ,
|
|
666
|
+
matchMode=SensorMatchMode.ALL
|
|
667
|
+
),
|
|
508
668
|
# PIR motion sensor WMS07
|
|
509
669
|
SensorDefinition(
|
|
510
670
|
type=8,
|
|
@@ -515,6 +675,66 @@ SENSOR_DEFINITIONS = [
|
|
|
515
675
|
rwMode=SensorRwMode.READ,
|
|
516
676
|
matchMode=SensorMatchMode.ONLY20BITS
|
|
517
677
|
),
|
|
678
|
+
# PIR motion sensor ODPIR03
|
|
679
|
+
SensorDefinition(
|
|
680
|
+
type=8,
|
|
681
|
+
subtype=4,
|
|
682
|
+
rx=0,
|
|
683
|
+
tx=0,
|
|
684
|
+
private_data='00',
|
|
685
|
+
rwMode=SensorRwMode.READ,
|
|
686
|
+
matchMode=SensorMatchMode.ALL
|
|
687
|
+
),
|
|
688
|
+
# PIR motion sensor WPD01
|
|
689
|
+
SensorDefinition(
|
|
690
|
+
type=8,
|
|
691
|
+
subtype=7,
|
|
692
|
+
rx=0,
|
|
693
|
+
tx=0,
|
|
694
|
+
private_data='00',
|
|
695
|
+
rwMode=SensorRwMode.READ,
|
|
696
|
+
matchMode=SensorMatchMode.ALL
|
|
697
|
+
),
|
|
698
|
+
# PIR motion sensor PIR Ceiling
|
|
699
|
+
SensorDefinition(
|
|
700
|
+
type=8,
|
|
701
|
+
subtype=1,
|
|
702
|
+
rx=0,
|
|
703
|
+
tx=0,
|
|
704
|
+
private_data='00',
|
|
705
|
+
rwMode=SensorRwMode.READ,
|
|
706
|
+
matchMode=SensorMatchMode.ALL
|
|
707
|
+
),
|
|
708
|
+
# Beams ABT
|
|
709
|
+
SensorDefinition(
|
|
710
|
+
type=9,
|
|
711
|
+
subtype=0,
|
|
712
|
+
rx=0,
|
|
713
|
+
tx=0,
|
|
714
|
+
private_data='00',
|
|
715
|
+
rwMode=SensorRwMode.READ,
|
|
716
|
+
matchMode=SensorMatchMode.ALL
|
|
717
|
+
),
|
|
718
|
+
# Beams ABE
|
|
719
|
+
SensorDefinition(
|
|
720
|
+
type=9,
|
|
721
|
+
subtype=1,
|
|
722
|
+
rx=0,
|
|
723
|
+
tx=0,
|
|
724
|
+
private_data='00',
|
|
725
|
+
rwMode=SensorRwMode.READ,
|
|
726
|
+
matchMode=SensorMatchMode.ALL
|
|
727
|
+
),
|
|
728
|
+
# Beams ABH
|
|
729
|
+
SensorDefinition(
|
|
730
|
+
type=9,
|
|
731
|
+
subtype=2,
|
|
732
|
+
rx=0,
|
|
733
|
+
tx=0,
|
|
734
|
+
private_data='00',
|
|
735
|
+
rwMode=SensorRwMode.READ,
|
|
736
|
+
matchMode=SensorMatchMode.ALL
|
|
737
|
+
),
|
|
518
738
|
# Remote RMC08
|
|
519
739
|
SensorDefinition(
|
|
520
740
|
type=10,
|
|
@@ -565,6 +785,16 @@ SENSOR_DEFINITIONS = [
|
|
|
565
785
|
rwMode=SensorRwMode.READ,
|
|
566
786
|
matchMode=SensorMatchMode.ONLY20BITS
|
|
567
787
|
),
|
|
788
|
+
# Door Bell WDB
|
|
789
|
+
SensorDefinition(
|
|
790
|
+
type=12,
|
|
791
|
+
subtype=1,
|
|
792
|
+
rx=0,
|
|
793
|
+
tx=0,
|
|
794
|
+
private_data='00',
|
|
795
|
+
rwMode=SensorRwMode.READ,
|
|
796
|
+
matchMode=SensorMatchMode.ALL
|
|
797
|
+
),
|
|
568
798
|
# TouchID Detector
|
|
569
799
|
SensorDefinition(
|
|
570
800
|
type=13,
|
|
@@ -595,7 +825,17 @@ SENSOR_DEFINITIONS = [
|
|
|
595
825
|
rwMode=SensorRwMode.READ,
|
|
596
826
|
matchMode=SensorMatchMode.ONLY16BITS
|
|
597
827
|
),
|
|
598
|
-
#
|
|
828
|
+
# Sub Host SS08S
|
|
829
|
+
SensorDefinition(
|
|
830
|
+
type=16,
|
|
831
|
+
subtype=0,
|
|
832
|
+
rx=0,
|
|
833
|
+
tx=0,
|
|
834
|
+
private_data='00',
|
|
835
|
+
rwMode=SensorRwMode.READ,
|
|
836
|
+
matchMode=SensorMatchMode.ALL
|
|
837
|
+
),
|
|
838
|
+
# Gas Valve Detector WGD02
|
|
599
839
|
SensorDefinition(
|
|
600
840
|
type=18,
|
|
601
841
|
subtype=0,
|
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
"""
|
|
22
22
|
Implements support for notifications/alerts sent by G90 alarm panel.
|
|
23
23
|
"""
|
|
24
|
-
|
|
25
24
|
import json
|
|
26
25
|
import logging
|
|
27
26
|
from collections import namedtuple
|
|
@@ -34,15 +33,17 @@ from .const import (
|
|
|
34
33
|
G90AlertStateChangeTypes,
|
|
35
34
|
G90ArmDisarmTypes,
|
|
36
35
|
G90AlertSources,
|
|
36
|
+
G90AlertStates,
|
|
37
37
|
)
|
|
38
38
|
|
|
39
|
+
|
|
39
40
|
_LOGGER = logging.getLogger(__name__)
|
|
40
41
|
|
|
41
42
|
|
|
42
43
|
class G90Message(namedtuple('G90Message',
|
|
43
44
|
['code', 'data'])):
|
|
44
45
|
"""
|
|
45
|
-
|
|
46
|
+
Represents the message received from the device.
|
|
46
47
|
|
|
47
48
|
:meta private:
|
|
48
49
|
"""
|
|
@@ -51,7 +52,7 @@ class G90Message(namedtuple('G90Message',
|
|
|
51
52
|
class G90Notification(namedtuple('G90Notification',
|
|
52
53
|
['kind', 'data'])):
|
|
53
54
|
"""
|
|
54
|
-
|
|
55
|
+
Represents the notification received from the device.
|
|
55
56
|
|
|
56
57
|
:meta private:
|
|
57
58
|
"""
|
|
@@ -60,7 +61,7 @@ class G90Notification(namedtuple('G90Notification',
|
|
|
60
61
|
class G90ZoneInfo(namedtuple('G90ZoneInfo',
|
|
61
62
|
['idx', 'name'])):
|
|
62
63
|
"""
|
|
63
|
-
|
|
64
|
+
Represents zone details received from the device.
|
|
64
65
|
|
|
65
66
|
:meta private:
|
|
66
67
|
"""
|
|
@@ -69,7 +70,7 @@ class G90ZoneInfo(namedtuple('G90ZoneInfo',
|
|
|
69
70
|
class G90ArmDisarmInfo(namedtuple('G90ArmDisarmInfo',
|
|
70
71
|
['state'])):
|
|
71
72
|
"""
|
|
72
|
-
|
|
73
|
+
Represents the arm/disarm state received from the device.
|
|
73
74
|
|
|
74
75
|
:meta private:
|
|
75
76
|
"""
|
|
@@ -80,46 +81,31 @@ class G90DeviceAlert(namedtuple('G90DeviceAlert',
|
|
|
80
81
|
'zone_name', 'device_id', 'unix_time',
|
|
81
82
|
'resv4', 'other'])):
|
|
82
83
|
"""
|
|
83
|
-
|
|
84
|
+
Represents alert received from the device.
|
|
84
85
|
|
|
85
86
|
:meta private:
|
|
86
87
|
"""
|
|
87
88
|
|
|
88
89
|
|
|
89
|
-
class
|
|
90
|
+
class G90DeviceNotifications:
|
|
90
91
|
"""
|
|
91
92
|
tbd
|
|
92
|
-
|
|
93
|
-
:meta private:
|
|
94
93
|
"""
|
|
95
|
-
def __init__(self,
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
self._armdisarm_cb = armdisarm_cb
|
|
101
|
-
self._sensor_cb = sensor_cb
|
|
102
|
-
self._door_open_close_cb = door_open_close_cb
|
|
103
|
-
self._alarm_cb = alarm_cb
|
|
104
|
-
|
|
105
|
-
def connection_made(self, transport):
|
|
106
|
-
"""
|
|
107
|
-
tbd
|
|
108
|
-
"""
|
|
109
|
-
|
|
110
|
-
def connection_lost(self, exc):
|
|
111
|
-
"""
|
|
112
|
-
tbd
|
|
113
|
-
"""
|
|
94
|
+
def __init__(self, port, host):
|
|
95
|
+
# pylint: disable=too-many-arguments
|
|
96
|
+
self._notification_transport = None
|
|
97
|
+
self._notifications_host = host
|
|
98
|
+
self._notifications_port = port
|
|
114
99
|
|
|
115
100
|
def _handle_notification(self, addr, notification):
|
|
116
101
|
# Sensor activity notification
|
|
117
102
|
if notification.kind == G90NotificationTypes.SENSOR_ACTIVITY:
|
|
118
103
|
g90_zone_info = G90ZoneInfo(*notification.data)
|
|
119
104
|
_LOGGER.debug('Sensor notification: %s', g90_zone_info)
|
|
120
|
-
G90Callback.invoke(
|
|
121
|
-
|
|
122
|
-
|
|
105
|
+
G90Callback.invoke(
|
|
106
|
+
self.on_sensor_activity,
|
|
107
|
+
g90_zone_info.idx, g90_zone_info.name
|
|
108
|
+
)
|
|
123
109
|
return
|
|
124
110
|
|
|
125
111
|
# Arm/disarm notification
|
|
@@ -130,8 +116,7 @@ class G90DeviceNotificationProtocol:
|
|
|
130
116
|
state = G90ArmDisarmTypes(g90_armdisarm_info.state)
|
|
131
117
|
_LOGGER.debug('Arm/disarm notification: %s',
|
|
132
118
|
state)
|
|
133
|
-
G90Callback.invoke(self.
|
|
134
|
-
state)
|
|
119
|
+
G90Callback.invoke(self.on_armdisarm, state)
|
|
135
120
|
return
|
|
136
121
|
|
|
137
122
|
_LOGGER.warning('Unknown notification received from %s:%s:'
|
|
@@ -140,14 +125,30 @@ class G90DeviceNotificationProtocol:
|
|
|
140
125
|
|
|
141
126
|
def _handle_alert(self, addr, alert):
|
|
142
127
|
if alert.type == G90AlertTypes.DOOR_OPEN_CLOSE:
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
)
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
128
|
+
if alert.state in (
|
|
129
|
+
G90AlertStates.DOOR_OPEN, G90AlertStates.DOOR_CLOSE
|
|
130
|
+
):
|
|
131
|
+
is_open = (
|
|
132
|
+
alert.source == G90AlertSources.SENSOR
|
|
133
|
+
and alert.state == G90AlertStates.DOOR_OPEN # noqa: W503
|
|
134
|
+
) or alert.source == G90AlertSources.DOORBELL
|
|
135
|
+
_LOGGER.debug('Door open_close alert: %s', alert)
|
|
136
|
+
G90Callback.invoke(
|
|
137
|
+
self.on_door_open_close,
|
|
138
|
+
alert.event_id, alert.zone_name, is_open
|
|
139
|
+
)
|
|
140
|
+
return
|
|
141
|
+
|
|
142
|
+
if (
|
|
143
|
+
alert.source == G90AlertSources.SENSOR
|
|
144
|
+
and alert.state == G90AlertStates.LOW_BATTERY # noqa: W503
|
|
145
|
+
):
|
|
146
|
+
_LOGGER.debug('Low battery alert: %s', alert)
|
|
147
|
+
G90Callback.invoke(
|
|
148
|
+
self.on_low_battery,
|
|
149
|
+
alert.event_id, alert.zone_name
|
|
150
|
+
)
|
|
151
|
+
return
|
|
151
152
|
|
|
152
153
|
if alert.type == G90AlertTypes.STATE_CHANGE:
|
|
153
154
|
# Define the mapping between device state received in the alert, to
|
|
@@ -167,21 +168,36 @@ class G90DeviceNotificationProtocol:
|
|
|
167
168
|
# We received the device state change related to arm/disarm,
|
|
168
169
|
# invoke the corresponding callback
|
|
169
170
|
_LOGGER.debug('Arm/disarm state change: %s', state)
|
|
170
|
-
G90Callback.invoke(self.
|
|
171
|
+
G90Callback.invoke(self.on_armdisarm, state)
|
|
171
172
|
return
|
|
172
173
|
|
|
173
174
|
if alert.type == G90AlertTypes.ALARM:
|
|
174
175
|
_LOGGER.debug('Alarm: %s', alert.zone_name)
|
|
175
|
-
G90Callback.invoke(
|
|
176
|
+
G90Callback.invoke(
|
|
177
|
+
self.on_alarm,
|
|
178
|
+
alert.event_id, alert.zone_name
|
|
179
|
+
)
|
|
176
180
|
return
|
|
177
181
|
|
|
178
182
|
_LOGGER.warning('Unknown alert received from %s:%s:'
|
|
179
183
|
' type %s, data %s',
|
|
180
184
|
addr[0], addr[1], alert.type, alert)
|
|
181
185
|
|
|
186
|
+
# Implementation of datagram protocol,
|
|
187
|
+
# https://docs.python.org/3/library/asyncio-protocol.html#datagram-protocols
|
|
188
|
+
def connection_made(self, transport):
|
|
189
|
+
"""
|
|
190
|
+
Invoked when connection from the device is made.
|
|
191
|
+
"""
|
|
192
|
+
|
|
193
|
+
def connection_lost(self, exc):
|
|
194
|
+
"""
|
|
195
|
+
Same but when the connection is lost.
|
|
196
|
+
"""
|
|
197
|
+
|
|
182
198
|
def datagram_received(self, data, addr): # pylint:disable=R0911
|
|
183
199
|
"""
|
|
184
|
-
|
|
200
|
+
Invoked from datagram is received from the device.
|
|
185
201
|
"""
|
|
186
202
|
s_data = data.decode('utf-8')
|
|
187
203
|
if not s_data.endswith('\0'):
|
|
@@ -227,59 +243,64 @@ class G90DeviceNotificationProtocol:
|
|
|
227
243
|
_LOGGER.warning('Unknown message received from %s:%s: %s',
|
|
228
244
|
addr[0], addr[1], message)
|
|
229
245
|
|
|
246
|
+
async def on_armdisarm(self, state):
|
|
247
|
+
"""
|
|
248
|
+
Invoked when device is armed or disarmed.
|
|
249
|
+
"""
|
|
230
250
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
self._door_open_close_cb = door_open_close_cb
|
|
243
|
-
self._alarm_cb = alarm_cb
|
|
244
|
-
self._sock = sock
|
|
245
|
-
|
|
246
|
-
def proto_factory(self):
|
|
251
|
+
async def on_sensor_activity(self, idx, name):
|
|
252
|
+
"""
|
|
253
|
+
Invoked on sensor activity.
|
|
254
|
+
"""
|
|
255
|
+
|
|
256
|
+
async def on_door_open_close(self, event_id, zone_name, is_open):
|
|
257
|
+
"""
|
|
258
|
+
Invoked when door sensor reports it opened or closed.
|
|
259
|
+
"""
|
|
260
|
+
|
|
261
|
+
async def on_low_battery(self, event_id, zone_name):
|
|
247
262
|
"""
|
|
248
|
-
|
|
263
|
+
Invoked when a sensor reports it is low on battery.
|
|
264
|
+
"""
|
|
265
|
+
|
|
266
|
+
async def on_alarm(self, event_id, zone_name):
|
|
267
|
+
"""
|
|
268
|
+
Invoked when device triggers the alarm.
|
|
249
269
|
"""
|
|
250
|
-
return G90DeviceNotificationProtocol(
|
|
251
|
-
armdisarm_cb=self._armdisarm_cb,
|
|
252
|
-
sensor_cb=self._sensor_cb,
|
|
253
|
-
door_open_close_cb=self._door_open_close_cb,
|
|
254
|
-
alarm_cb=self._alarm_cb
|
|
255
|
-
)
|
|
256
270
|
|
|
257
271
|
async def listen(self):
|
|
258
272
|
"""
|
|
259
|
-
|
|
273
|
+
Listens for notifications/alers from the device.
|
|
260
274
|
"""
|
|
261
275
|
try:
|
|
262
276
|
loop = asyncio.get_running_loop()
|
|
263
277
|
except AttributeError:
|
|
264
278
|
loop = asyncio.get_event_loop()
|
|
265
279
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
280
|
+
_LOGGER.debug('Creating UDP endpoint for %s:%s',
|
|
281
|
+
self._notifications_host,
|
|
282
|
+
self._notifications_port)
|
|
283
|
+
(self._notification_transport,
|
|
284
|
+
_protocol) = await loop.create_datagram_endpoint(
|
|
285
|
+
lambda: self,
|
|
286
|
+
local_addr=(
|
|
287
|
+
self._notifications_host, self._notifications_port
|
|
288
|
+
))
|
|
289
|
+
|
|
290
|
+
@property
|
|
291
|
+
def listener_started(self):
|
|
292
|
+
"""
|
|
293
|
+
Indicates if the listener of the device notifications has been started.
|
|
294
|
+
|
|
295
|
+
:rtype: bool
|
|
296
|
+
"""
|
|
297
|
+
return self._notification_transport is not None
|
|
279
298
|
|
|
280
299
|
def close(self):
|
|
281
300
|
"""
|
|
282
|
-
|
|
301
|
+
Closes the listener.
|
|
283
302
|
"""
|
|
284
303
|
if self._notification_transport:
|
|
304
|
+
_LOGGER.debug('No longer listening for device notifications')
|
|
285
305
|
self._notification_transport.close()
|
|
306
|
+
self._notification_transport = None
|
pyg90alarm/discovery.py
CHANGED
|
@@ -32,34 +32,28 @@ from .const import G90Commands
|
|
|
32
32
|
_LOGGER = logging.getLogger(__name__)
|
|
33
33
|
|
|
34
34
|
|
|
35
|
-
class
|
|
35
|
+
class G90Discovery(G90BaseCommand):
|
|
36
36
|
"""
|
|
37
37
|
tbd
|
|
38
|
-
|
|
39
|
-
:meta private:
|
|
40
38
|
"""
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
tbd
|
|
44
|
-
"""
|
|
45
|
-
self._parent = parent
|
|
46
|
-
|
|
47
|
-
def connection_made(self, transport):
|
|
48
|
-
"""
|
|
49
|
-
tbd
|
|
50
|
-
"""
|
|
51
|
-
|
|
52
|
-
def connection_lost(self, exc):
|
|
39
|
+
# pylint: disable=too-few-public-methods
|
|
40
|
+
def __init__(self, timeout=10, **kwargs):
|
|
53
41
|
"""
|
|
54
42
|
tbd
|
|
55
43
|
"""
|
|
44
|
+
# pylint: disable=too-many-arguments
|
|
45
|
+
super().__init__(code=G90Commands.GETHOSTINFO, timeout=timeout,
|
|
46
|
+
**kwargs)
|
|
47
|
+
self._discovered_devices = []
|
|
56
48
|
|
|
49
|
+
# Implementation of datagram protocol,
|
|
50
|
+
# https://docs.python.org/3/library/asyncio-protocol.html#datagram-protocols
|
|
57
51
|
def datagram_received(self, data, addr):
|
|
58
52
|
"""
|
|
59
53
|
tbd
|
|
60
54
|
"""
|
|
61
55
|
try:
|
|
62
|
-
ret = self.
|
|
56
|
+
ret = self.from_wire(data)
|
|
63
57
|
host_info = G90HostInfo(*ret)
|
|
64
58
|
_LOGGER.debug('Received from %s:%s: %s', addr[0], addr[1], ret)
|
|
65
59
|
res = {
|
|
@@ -69,31 +63,11 @@ class G90DiscoveryProtocol:
|
|
|
69
63
|
}
|
|
70
64
|
res.update(host_info._asdict())
|
|
71
65
|
_LOGGER.debug('Discovered device: %s', res)
|
|
72
|
-
self.
|
|
66
|
+
self.add_device(res)
|
|
73
67
|
|
|
74
68
|
except Exception as exc: # pylint: disable=broad-except
|
|
75
69
|
_LOGGER.warning('Got exception, ignoring: %s', exc)
|
|
76
70
|
|
|
77
|
-
def error_received(self, exc):
|
|
78
|
-
"""
|
|
79
|
-
tbd
|
|
80
|
-
"""
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
class G90Discovery(G90BaseCommand):
|
|
84
|
-
"""
|
|
85
|
-
tbd
|
|
86
|
-
"""
|
|
87
|
-
# pylint: disable=too-few-public-methods
|
|
88
|
-
def __init__(self, timeout=10, **kwargs):
|
|
89
|
-
"""
|
|
90
|
-
tbd
|
|
91
|
-
"""
|
|
92
|
-
# pylint: disable=too-many-arguments
|
|
93
|
-
super().__init__(code=G90Commands.GETHOSTINFO, timeout=timeout,
|
|
94
|
-
**kwargs)
|
|
95
|
-
self._discovered_devices = []
|
|
96
|
-
|
|
97
71
|
async def process(self):
|
|
98
72
|
"""
|
|
99
73
|
tbd
|
|
@@ -118,9 +92,3 @@ class G90Discovery(G90BaseCommand):
|
|
|
118
92
|
tbd
|
|
119
93
|
"""
|
|
120
94
|
self._discovered_devices.append(value)
|
|
121
|
-
|
|
122
|
-
def _proto_factory(self):
|
|
123
|
-
"""
|
|
124
|
-
tbd
|
|
125
|
-
"""
|
|
126
|
-
return G90DiscoveryProtocol(self)
|
pyg90alarm/entities/sensor.py
CHANGED
|
@@ -172,6 +172,7 @@ class G90Sensor: # pylint:disable=too-many-instance-attributes
|
|
|
172
172
|
self._subindex = subindex
|
|
173
173
|
self._occupancy = False
|
|
174
174
|
self._state_callback = None
|
|
175
|
+
self._low_battery_callback = None
|
|
175
176
|
self._proto_idx = proto_idx
|
|
176
177
|
self._extra_data = None
|
|
177
178
|
|
|
@@ -217,6 +218,25 @@ class G90Sensor: # pylint:disable=too-many-instance-attributes
|
|
|
217
218
|
"""
|
|
218
219
|
self._state_callback = value
|
|
219
220
|
|
|
221
|
+
@property
|
|
222
|
+
def low_battery_callback(self):
|
|
223
|
+
"""
|
|
224
|
+
Returns callback the sensor might have set for low battery condition.
|
|
225
|
+
|
|
226
|
+
:return: Sensor's low battery callback
|
|
227
|
+
:rtype: object
|
|
228
|
+
"""
|
|
229
|
+
return self._low_battery_callback
|
|
230
|
+
|
|
231
|
+
@low_battery_callback.setter
|
|
232
|
+
def low_battery_callback(self, value):
|
|
233
|
+
"""
|
|
234
|
+
Sets callback for the low battery condition reported by the sensor.
|
|
235
|
+
|
|
236
|
+
:param object value: Sensor's low battery callback
|
|
237
|
+
"""
|
|
238
|
+
self._low_battery_callback = value
|
|
239
|
+
|
|
220
240
|
@property
|
|
221
241
|
def occupancy(self):
|
|
222
242
|
"""
|