pyg90alarm 1.10.1__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 +188 -27
- pyg90alarm/base_cmd.py +38 -65
- pyg90alarm/const.py +29 -0
- pyg90alarm/definitions/sensors.py +241 -1
- pyg90alarm/device_notifications.py +99 -73
- pyg90alarm/discovery.py +11 -43
- pyg90alarm/entities/sensor.py +20 -0
- pyg90alarm/history.py +174 -12
- pyg90alarm/targeted_discovery.py +8 -43
- {pyg90alarm-1.10.1.dist-info → pyg90alarm-1.12.1.dist-info}/METADATA +13 -6
- pyg90alarm-1.12.1.dist-info/RECORD +26 -0
- {pyg90alarm-1.10.1.dist-info → pyg90alarm-1.12.1.dist-info}/WHEEL +1 -1
- pyg90alarm-1.10.1.dist-info/RECORD +0 -26
- {pyg90alarm-1.10.1.dist-info → pyg90alarm-1.12.1.dist-info}/LICENSE +0 -0
- {pyg90alarm-1.10.1.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,6 +33,7 @@ from .const import (
|
|
|
34
33
|
G90AlertStateChangeTypes,
|
|
35
34
|
G90ArmDisarmTypes,
|
|
36
35
|
G90AlertSources,
|
|
36
|
+
G90AlertStates,
|
|
37
37
|
)
|
|
38
38
|
|
|
39
39
|
|
|
@@ -43,7 +43,7 @@ _LOGGER = logging.getLogger(__name__)
|
|
|
43
43
|
class G90Message(namedtuple('G90Message',
|
|
44
44
|
['code', 'data'])):
|
|
45
45
|
"""
|
|
46
|
-
|
|
46
|
+
Represents the message received from the device.
|
|
47
47
|
|
|
48
48
|
:meta private:
|
|
49
49
|
"""
|
|
@@ -52,7 +52,7 @@ class G90Message(namedtuple('G90Message',
|
|
|
52
52
|
class G90Notification(namedtuple('G90Notification',
|
|
53
53
|
['kind', 'data'])):
|
|
54
54
|
"""
|
|
55
|
-
|
|
55
|
+
Represents the notification received from the device.
|
|
56
56
|
|
|
57
57
|
:meta private:
|
|
58
58
|
"""
|
|
@@ -61,7 +61,7 @@ class G90Notification(namedtuple('G90Notification',
|
|
|
61
61
|
class G90ZoneInfo(namedtuple('G90ZoneInfo',
|
|
62
62
|
['idx', 'name'])):
|
|
63
63
|
"""
|
|
64
|
-
|
|
64
|
+
Represents zone details received from the device.
|
|
65
65
|
|
|
66
66
|
:meta private:
|
|
67
67
|
"""
|
|
@@ -70,7 +70,7 @@ class G90ZoneInfo(namedtuple('G90ZoneInfo',
|
|
|
70
70
|
class G90ArmDisarmInfo(namedtuple('G90ArmDisarmInfo',
|
|
71
71
|
['state'])):
|
|
72
72
|
"""
|
|
73
|
-
|
|
73
|
+
Represents the arm/disarm state received from the device.
|
|
74
74
|
|
|
75
75
|
:meta private:
|
|
76
76
|
"""
|
|
@@ -81,46 +81,31 @@ class G90DeviceAlert(namedtuple('G90DeviceAlert',
|
|
|
81
81
|
'zone_name', 'device_id', 'unix_time',
|
|
82
82
|
'resv4', 'other'])):
|
|
83
83
|
"""
|
|
84
|
-
|
|
84
|
+
Represents alert received from the device.
|
|
85
85
|
|
|
86
86
|
:meta private:
|
|
87
87
|
"""
|
|
88
88
|
|
|
89
89
|
|
|
90
|
-
class
|
|
90
|
+
class G90DeviceNotifications:
|
|
91
91
|
"""
|
|
92
92
|
tbd
|
|
93
|
-
|
|
94
|
-
:meta private:
|
|
95
93
|
"""
|
|
96
|
-
def __init__(self,
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
self._armdisarm_cb = armdisarm_cb
|
|
102
|
-
self._sensor_cb = sensor_cb
|
|
103
|
-
self._door_open_close_cb = door_open_close_cb
|
|
104
|
-
self._alarm_cb = alarm_cb
|
|
105
|
-
|
|
106
|
-
def connection_made(self, transport):
|
|
107
|
-
"""
|
|
108
|
-
tbd
|
|
109
|
-
"""
|
|
110
|
-
|
|
111
|
-
def connection_lost(self, exc):
|
|
112
|
-
"""
|
|
113
|
-
tbd
|
|
114
|
-
"""
|
|
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
|
|
115
99
|
|
|
116
100
|
def _handle_notification(self, addr, notification):
|
|
117
101
|
# Sensor activity notification
|
|
118
102
|
if notification.kind == G90NotificationTypes.SENSOR_ACTIVITY:
|
|
119
103
|
g90_zone_info = G90ZoneInfo(*notification.data)
|
|
120
104
|
_LOGGER.debug('Sensor notification: %s', g90_zone_info)
|
|
121
|
-
G90Callback.invoke(
|
|
122
|
-
|
|
123
|
-
|
|
105
|
+
G90Callback.invoke(
|
|
106
|
+
self.on_sensor_activity,
|
|
107
|
+
g90_zone_info.idx, g90_zone_info.name
|
|
108
|
+
)
|
|
124
109
|
return
|
|
125
110
|
|
|
126
111
|
# Arm/disarm notification
|
|
@@ -131,8 +116,7 @@ class G90DeviceNotificationProtocol:
|
|
|
131
116
|
state = G90ArmDisarmTypes(g90_armdisarm_info.state)
|
|
132
117
|
_LOGGER.debug('Arm/disarm notification: %s',
|
|
133
118
|
state)
|
|
134
|
-
G90Callback.invoke(self.
|
|
135
|
-
state)
|
|
119
|
+
G90Callback.invoke(self.on_armdisarm, state)
|
|
136
120
|
return
|
|
137
121
|
|
|
138
122
|
_LOGGER.warning('Unknown notification received from %s:%s:'
|
|
@@ -141,14 +125,30 @@ class G90DeviceNotificationProtocol:
|
|
|
141
125
|
|
|
142
126
|
def _handle_alert(self, addr, alert):
|
|
143
127
|
if alert.type == G90AlertTypes.DOOR_OPEN_CLOSE:
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
)
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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
|
|
152
152
|
|
|
153
153
|
if alert.type == G90AlertTypes.STATE_CHANGE:
|
|
154
154
|
# Define the mapping between device state received in the alert, to
|
|
@@ -168,21 +168,36 @@ class G90DeviceNotificationProtocol:
|
|
|
168
168
|
# We received the device state change related to arm/disarm,
|
|
169
169
|
# invoke the corresponding callback
|
|
170
170
|
_LOGGER.debug('Arm/disarm state change: %s', state)
|
|
171
|
-
G90Callback.invoke(self.
|
|
171
|
+
G90Callback.invoke(self.on_armdisarm, state)
|
|
172
172
|
return
|
|
173
173
|
|
|
174
174
|
if alert.type == G90AlertTypes.ALARM:
|
|
175
175
|
_LOGGER.debug('Alarm: %s', alert.zone_name)
|
|
176
|
-
G90Callback.invoke(
|
|
176
|
+
G90Callback.invoke(
|
|
177
|
+
self.on_alarm,
|
|
178
|
+
alert.event_id, alert.zone_name
|
|
179
|
+
)
|
|
177
180
|
return
|
|
178
181
|
|
|
179
182
|
_LOGGER.warning('Unknown alert received from %s:%s:'
|
|
180
183
|
' type %s, data %s',
|
|
181
184
|
addr[0], addr[1], alert.type, alert)
|
|
182
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
|
+
|
|
183
198
|
def datagram_received(self, data, addr): # pylint:disable=R0911
|
|
184
199
|
"""
|
|
185
|
-
|
|
200
|
+
Invoked from datagram is received from the device.
|
|
186
201
|
"""
|
|
187
202
|
s_data = data.decode('utf-8')
|
|
188
203
|
if not s_data.endswith('\0'):
|
|
@@ -228,37 +243,34 @@ class G90DeviceNotificationProtocol:
|
|
|
228
243
|
_LOGGER.warning('Unknown message received from %s:%s: %s',
|
|
229
244
|
addr[0], addr[1], message)
|
|
230
245
|
|
|
246
|
+
async def on_armdisarm(self, state):
|
|
247
|
+
"""
|
|
248
|
+
Invoked when device is armed or disarmed.
|
|
249
|
+
"""
|
|
231
250
|
|
|
232
|
-
|
|
233
|
-
"""
|
|
234
|
-
tbd
|
|
235
|
-
"""
|
|
236
|
-
def __init__(self, port, host,
|
|
237
|
-
armdisarm_cb=None, sensor_cb=None,
|
|
238
|
-
door_open_close_cb=None, alarm_cb=None):
|
|
239
|
-
# pylint: disable=too-many-arguments
|
|
240
|
-
self._notification_transport = None
|
|
241
|
-
self._host = host
|
|
242
|
-
self._port = port
|
|
243
|
-
self._armdisarm_cb = armdisarm_cb
|
|
244
|
-
self._sensor_cb = sensor_cb
|
|
245
|
-
self._door_open_close_cb = door_open_close_cb
|
|
246
|
-
self._alarm_cb = alarm_cb
|
|
247
|
-
|
|
248
|
-
def proto_factory(self):
|
|
251
|
+
async def on_sensor_activity(self, idx, name):
|
|
249
252
|
"""
|
|
250
|
-
|
|
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):
|
|
262
|
+
"""
|
|
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.
|
|
251
269
|
"""
|
|
252
|
-
return G90DeviceNotificationProtocol(
|
|
253
|
-
armdisarm_cb=self._armdisarm_cb,
|
|
254
|
-
sensor_cb=self._sensor_cb,
|
|
255
|
-
door_open_close_cb=self._door_open_close_cb,
|
|
256
|
-
alarm_cb=self._alarm_cb
|
|
257
|
-
)
|
|
258
270
|
|
|
259
271
|
async def listen(self):
|
|
260
272
|
"""
|
|
261
|
-
|
|
273
|
+
Listens for notifications/alers from the device.
|
|
262
274
|
"""
|
|
263
275
|
try:
|
|
264
276
|
loop = asyncio.get_running_loop()
|
|
@@ -266,15 +278,29 @@ class G90DeviceNotifications:
|
|
|
266
278
|
loop = asyncio.get_event_loop()
|
|
267
279
|
|
|
268
280
|
_LOGGER.debug('Creating UDP endpoint for %s:%s',
|
|
269
|
-
self.
|
|
281
|
+
self._notifications_host,
|
|
282
|
+
self._notifications_port)
|
|
270
283
|
(self._notification_transport,
|
|
271
284
|
_protocol) = await loop.create_datagram_endpoint(
|
|
272
|
-
self
|
|
273
|
-
local_addr=(
|
|
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
|
|
274
298
|
|
|
275
299
|
def close(self):
|
|
276
300
|
"""
|
|
277
|
-
|
|
301
|
+
Closes the listener.
|
|
278
302
|
"""
|
|
279
303
|
if self._notification_transport:
|
|
304
|
+
_LOGGER.debug('No longer listening for device notifications')
|
|
280
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
|
"""
|