pyg90alarm 1.20.0__tar.gz → 2.0.0__tar.gz
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-1.20.0 → pyg90alarm-2.0.0}/.github/workflows/main.yml +0 -3
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/MANIFEST.in +1 -1
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/PKG-INFO +101 -18
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/README.rst +97 -14
- pyg90alarm-2.0.0/docs/cloud-protocol.rst +85 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/docs/index.rst +2 -1
- pyg90alarm-1.20.0/docs/protocol.rst → pyg90alarm-2.0.0/docs/local-protocol.rst +10 -12
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/setup.py +1 -2
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/sonar-project.properties +1 -1
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/src/pyg90alarm/__init__.py +5 -5
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/src/pyg90alarm/alarm.py +130 -34
- pyg90alarm-2.0.0/src/pyg90alarm/cloud/__init__.py +31 -0
- pyg90alarm-2.0.0/src/pyg90alarm/cloud/const.py +56 -0
- pyg90alarm-2.0.0/src/pyg90alarm/cloud/messages.py +593 -0
- pyg90alarm-2.0.0/src/pyg90alarm/cloud/notifications.py +409 -0
- pyg90alarm-2.0.0/src/pyg90alarm/cloud/protocol.py +518 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/src/pyg90alarm/const.py +5 -0
- {pyg90alarm-1.20.0/src/pyg90alarm → pyg90alarm-2.0.0/src/pyg90alarm/local}/base_cmd.py +3 -6
- {pyg90alarm-1.20.0/src/pyg90alarm → pyg90alarm-2.0.0/src/pyg90alarm/local}/discovery.py +1 -1
- {pyg90alarm-1.20.0/src/pyg90alarm → pyg90alarm-2.0.0/src/pyg90alarm/local}/history.py +4 -2
- {pyg90alarm-1.20.0/src/pyg90alarm → pyg90alarm-2.0.0/src/pyg90alarm/local}/host_status.py +1 -1
- pyg90alarm-2.0.0/src/pyg90alarm/local/notifications.py +116 -0
- {pyg90alarm-1.20.0/src/pyg90alarm → pyg90alarm-2.0.0/src/pyg90alarm/local}/paginated_cmd.py +2 -2
- {pyg90alarm-1.20.0/src/pyg90alarm → pyg90alarm-2.0.0/src/pyg90alarm/local}/paginated_result.py +1 -1
- {pyg90alarm-1.20.0/src/pyg90alarm → pyg90alarm-2.0.0/src/pyg90alarm/local}/targeted_discovery.py +2 -2
- pyg90alarm-1.20.0/src/pyg90alarm/device_notifications.py → pyg90alarm-2.0.0/src/pyg90alarm/notifications/base.py +115 -173
- pyg90alarm-2.0.0/src/pyg90alarm/notifications/protocol.py +116 -0
- pyg90alarm-2.0.0/src/pyg90alarm/py.typed +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/src/pyg90alarm.egg-info/PKG-INFO +101 -18
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/src/pyg90alarm.egg-info/SOURCES.txt +24 -13
- pyg90alarm-2.0.0/tests/__init__.py +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/tests/conftest.py +60 -4
- pyg90alarm-2.0.0/tests/device_mock.py +705 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/tests/test_alarm.py +106 -82
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/tests/test_base_commands.py +10 -10
- pyg90alarm-2.0.0/tests/test_cloud_notifications.py +502 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/tests/test_discovery.py +4 -4
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/tests/test_history.py +3 -3
- pyg90alarm-1.20.0/tests/test_notifications.py → pyg90alarm-2.0.0/tests/test_local_notifications.py +209 -125
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/tests/test_paginated_commands.py +5 -5
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/tox.ini +1 -1
- pyg90alarm-1.20.0/tests/device_mock.py +0 -277
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/.github/CODEOWNERS +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/.gitignore +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/.pylintrc +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/.readthedocs.yaml +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/LICENSE +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/docs/.DS_Store +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/docs/.gitignore +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/docs/api-docs.rst +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/docs/conf.py +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/docs/requirements.txt +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/pyproject.toml +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/setup.cfg +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/src/pyg90alarm/callback.py +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/src/pyg90alarm/definitions/__init__.py +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/src/pyg90alarm/definitions/sensors.py +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/src/pyg90alarm/entities/__init__.py +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/src/pyg90alarm/entities/base_entity.py +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/src/pyg90alarm/entities/base_list.py +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/src/pyg90alarm/entities/device.py +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/src/pyg90alarm/entities/device_list.py +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/src/pyg90alarm/entities/sensor.py +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/src/pyg90alarm/entities/sensor_list.py +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/src/pyg90alarm/exceptions.py +0 -0
- {pyg90alarm-1.20.0/tests → pyg90alarm-2.0.0/src/pyg90alarm/local}/__init__.py +0 -0
- {pyg90alarm-1.20.0/src/pyg90alarm → pyg90alarm-2.0.0/src/pyg90alarm/local}/config.py +0 -0
- {pyg90alarm-1.20.0/src/pyg90alarm → pyg90alarm-2.0.0/src/pyg90alarm/local}/host_info.py +0 -0
- {pyg90alarm-1.20.0/src/pyg90alarm → pyg90alarm-2.0.0/src/pyg90alarm/local}/user_data_crc.py +0 -0
- /pyg90alarm-1.20.0/src/pyg90alarm/py.typed → /pyg90alarm-2.0.0/src/pyg90alarm/notifications/__init__.py +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/src/pyg90alarm.egg-info/dependency_links.txt +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/src/pyg90alarm.egg-info/requires.txt +0 -0
- {pyg90alarm-1.20.0 → pyg90alarm-2.0.0}/src/pyg90alarm.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: pyg90alarm
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: G90 Alarm system protocol
|
|
5
5
|
Home-page: https://github.com/hostcc/pyg90alarm
|
|
6
6
|
Author: Ilia Sotnikov
|
|
@@ -15,14 +15,13 @@ Classifier: Topic :: Home Automation
|
|
|
15
15
|
Classifier: Topic :: System :: Hardware
|
|
16
16
|
Classifier: License :: OSI Approved :: MIT License
|
|
17
17
|
Classifier: Programming Language :: Python :: 3
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
19
18
|
Classifier: Programming Language :: Python :: 3.9
|
|
20
19
|
Classifier: Programming Language :: Python :: 3.10
|
|
21
20
|
Classifier: Programming Language :: Python :: 3.11
|
|
22
21
|
Classifier: Programming Language :: Python :: 3.12
|
|
23
22
|
Classifier: Programming Language :: Python :: 3.13
|
|
24
23
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
25
|
-
Requires-Python: >=3.
|
|
24
|
+
Requires-Python: >=3.9, <4
|
|
26
25
|
Description-Content-Type: text/x-rst
|
|
27
26
|
License-File: LICENSE
|
|
28
27
|
Provides-Extra: dev
|
|
@@ -40,6 +39,7 @@ Dynamic: description
|
|
|
40
39
|
Dynamic: description-content-type
|
|
41
40
|
Dynamic: home-page
|
|
42
41
|
Dynamic: keywords
|
|
42
|
+
Dynamic: license-file
|
|
43
43
|
Dynamic: project-url
|
|
44
44
|
Dynamic: provides-extra
|
|
45
45
|
Dynamic: requires-python
|
|
@@ -136,22 +136,14 @@ Known caveats
|
|
|
136
136
|
contact sensors though, since an intruder cutting the line will trigger the
|
|
137
137
|
alarm.
|
|
138
138
|
|
|
139
|
-
|
|
140
|
-
|
|
139
|
+
Device notifications
|
|
140
|
+
====================
|
|
141
141
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
source/destination ports being ``45000:12901`` (non-configurable), and sent when
|
|
145
|
-
the device has IP address of its WiFi interface set to ``10.10.10.250``. That is
|
|
146
|
-
the same IP the device will allocate to the WiFi interface when AP (access
|
|
147
|
-
point is enabled). Please note enabling the AP *is not* required for the
|
|
148
|
-
notifications to be sent, only the IP address matters. Likely the firmware does
|
|
149
|
-
a check internally and enables those when corresponding IP address is found on
|
|
150
|
-
the WiFi interface.
|
|
142
|
+
Local notifications
|
|
143
|
+
-------------------
|
|
151
144
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
for further details on the device notifications.
|
|
145
|
+
There is a hidden device capability to send protocol notifications over the
|
|
146
|
+
WiFi interface, thus called local. The notifications are done using broadcast UDP packets with source/destination ports being ``45000:12901`` (non-configurable), and sent when the device has IP address of its WiFi interface set to ``10.10.10.250``. That is the same IP the device will allocate to the WiFi interface when AP (access point is enabled). Please note enabling the AP *is not* required for the notifications to be sent, only the IP address matters. Likely the firmware does a check internally and enables those when corresponding IP address is found on the WiFi interface.
|
|
155
147
|
|
|
156
148
|
Depending on your network setup, ensuring the `10.10.10.250` IP address is
|
|
157
149
|
allocated to the WiFi interface of the device might be as simple as DHCP
|
|
@@ -178,6 +170,97 @@ set the IP address allocation up.
|
|
|
178
170
|
alert to be enabled in the mobile application, otherwise it won't be
|
|
179
171
|
recorded in the history.
|
|
180
172
|
|
|
173
|
+
For the local notifications to be enabled the ```G90Alarm.use_local_notifications()``` needs to be called upon contstucting an instance of ``G90Alarm`` class, then ```G90Alarm.listen_notifications()`z to start processing those coming from the panel - the code fragment below demonstrate that though being incomplete since callbacks (e.g. ``G90Alarm.on_armdisarm()``) should be set for the actual processing of the notifications.
|
|
174
|
+
|
|
175
|
+
.. code:: python
|
|
176
|
+
|
|
177
|
+
from pyg90alarm import G90Alarm
|
|
178
|
+
|
|
179
|
+
# Create an instance of the alarm panel
|
|
180
|
+
alarm = G90Alarm(host='10.10.10.250')
|
|
181
|
+
# Enable local notifications
|
|
182
|
+
await alarm.use_local_notifications()
|
|
183
|
+
# Start listening for notifications
|
|
184
|
+
await alarm.listen_notifications()
|
|
185
|
+
|
|
186
|
+
Cloud notifications
|
|
187
|
+
-------------------
|
|
188
|
+
|
|
189
|
+
The cloud protocol is native to the panel and is used to interact with mobile application. The package can mimic the cloud server and interpret the messages the panel sends to the cloud, allowing to receive the notifications and alerts.
|
|
190
|
+
While the protocol also allows to send commands to the panel, it is not implemented and local protocol is used for that - i.e. when cloud notifications are in use the local protocol still utilized for sending commands to the panel.
|
|
191
|
+
|
|
192
|
+
The cloud protocol is TCP based and typically interacts with cloud service at known IP address and port (not customizeable at panel side). To process the cloud notifications all the traffic from panel towards the cloud (IP address ``47.88.7.61`` and TCP port ``5678`` as of writing) needs to be diverted to the node where the package is running - depending on your network equipment it could be port forwarding, DNAT or other means. It is unclear whether the panel utilizes DNS to resolve the cloud service IP address, hence the documentation only mentions IP-based traffic redirection.
|
|
193
|
+
|
|
194
|
+
Please see
|
|
195
|
+
`cloud-protocol.rst <docs/cloud-protocol.rst>`_ for further details on the protocol.
|
|
196
|
+
|
|
197
|
+
The benefit of the cloud notifications is that the panel no longer required to have ``10.10.10.250`` IP address.
|
|
198
|
+
|
|
199
|
+
The package could act as:
|
|
200
|
+
|
|
201
|
+
- Standalone cloud server with no Internet connectivity or cloud service
|
|
202
|
+
required at all - good if you'd like to avoid having a vendor service involved. Please note the mobile application will show panel as offline in this mode
|
|
203
|
+
- Chained cloud server, where in addition to intepreting the notifications it
|
|
204
|
+
will also forward all packets received from the panel to the cloud server, and pass its responses back to the panel. This allows to have notificaitons processed by the package and the mobile application working as well.
|
|
205
|
+
|
|
206
|
+
.. note:: Sending packets upstream to the known IP address and port of the cloud server might result in those looped back (since traffic from panel to cloud service has to be redirected to the host where package runs), if your network equipment can't account for source address in redirection rules (i.e. limiting the port redirection to the panel's IP address). In that case you'll need another redirection, from the host where the package runs to the cloud service using an IP from your network. That way those two redirection rules will coexist correctly. To illustate:
|
|
207
|
+
|
|
208
|
+
Port forwarding rule 1:
|
|
209
|
+
|
|
210
|
+
- Source: panel IP address
|
|
211
|
+
- Destination: 47.88.7.61
|
|
212
|
+
- Port: 5678
|
|
213
|
+
- Redirect to host: host where package runs
|
|
214
|
+
- Redirect to port: 5678 (or other port if you want to use it)
|
|
215
|
+
|
|
216
|
+
Port forwarding rule 2 (optional):
|
|
217
|
+
|
|
218
|
+
- Source: host where package runs
|
|
219
|
+
- Destination: an IP address from your network
|
|
220
|
+
- Port: 5678 (or other port if you want to use it)
|
|
221
|
+
- Redirect to : 47.88.7.61
|
|
222
|
+
- Redirect to port: 5678
|
|
223
|
+
|
|
224
|
+
The code fragments below demonstrate how to utilize both modes - please note those are incomplete, since no callbacks are set to process the notifications.
|
|
225
|
+
|
|
226
|
+
**Standalone mode**
|
|
227
|
+
|
|
228
|
+
.. code:: python
|
|
229
|
+
|
|
230
|
+
from pyg90alarm import G90Alarm
|
|
231
|
+
|
|
232
|
+
# Create an instance of the alarm panel
|
|
233
|
+
alarm = G90Alarm(host='<panel IP address>')
|
|
234
|
+
# Enable cloud notifications
|
|
235
|
+
await alarm.use_cloud_notifications(
|
|
236
|
+
# Optional, see note above redirecting cloud traffic from panel
|
|
237
|
+
local_port=5678,
|
|
238
|
+
upstream_host=None
|
|
239
|
+
)
|
|
240
|
+
# Start listening for notifications
|
|
241
|
+
await alarm.listen_notifications()
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
**Chained mode**
|
|
245
|
+
|
|
246
|
+
.. code:: python
|
|
247
|
+
|
|
248
|
+
from pyg90alarm import G90Alarm
|
|
249
|
+
|
|
250
|
+
# Create an instance of the alarm panel
|
|
251
|
+
alarm = G90Alarm(host='<panel IP address>')
|
|
252
|
+
# Enable cloud notifications
|
|
253
|
+
await alarm.use_cloud_notifications(
|
|
254
|
+
# Optional, see note above redirecting cloud traffic from panel
|
|
255
|
+
local_port=5678,
|
|
256
|
+
# See note above re: cloud service and sending packets to it
|
|
257
|
+
upstream_host='47.88.7.61',
|
|
258
|
+
upstream_port=5678
|
|
259
|
+
)
|
|
260
|
+
# Start listening for notifications
|
|
261
|
+
await alarm.listen_notifications()
|
|
262
|
+
|
|
263
|
+
|
|
181
264
|
Quick start
|
|
182
265
|
===========
|
|
183
266
|
|
|
@@ -89,22 +89,14 @@ Known caveats
|
|
|
89
89
|
contact sensors though, since an intruder cutting the line will trigger the
|
|
90
90
|
alarm.
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
Device notifications
|
|
93
|
+
====================
|
|
94
94
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
source/destination ports being ``45000:12901`` (non-configurable), and sent when
|
|
98
|
-
the device has IP address of its WiFi interface set to ``10.10.10.250``. That is
|
|
99
|
-
the same IP the device will allocate to the WiFi interface when AP (access
|
|
100
|
-
point is enabled). Please note enabling the AP *is not* required for the
|
|
101
|
-
notifications to be sent, only the IP address matters. Likely the firmware does
|
|
102
|
-
a check internally and enables those when corresponding IP address is found on
|
|
103
|
-
the WiFi interface.
|
|
95
|
+
Local notifications
|
|
96
|
+
-------------------
|
|
104
97
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
for further details on the device notifications.
|
|
98
|
+
There is a hidden device capability to send protocol notifications over the
|
|
99
|
+
WiFi interface, thus called local. The notifications are done using broadcast UDP packets with source/destination ports being ``45000:12901`` (non-configurable), and sent when the device has IP address of its WiFi interface set to ``10.10.10.250``. That is the same IP the device will allocate to the WiFi interface when AP (access point is enabled). Please note enabling the AP *is not* required for the notifications to be sent, only the IP address matters. Likely the firmware does a check internally and enables those when corresponding IP address is found on the WiFi interface.
|
|
108
100
|
|
|
109
101
|
Depending on your network setup, ensuring the `10.10.10.250` IP address is
|
|
110
102
|
allocated to the WiFi interface of the device might be as simple as DHCP
|
|
@@ -131,6 +123,97 @@ set the IP address allocation up.
|
|
|
131
123
|
alert to be enabled in the mobile application, otherwise it won't be
|
|
132
124
|
recorded in the history.
|
|
133
125
|
|
|
126
|
+
For the local notifications to be enabled the ```G90Alarm.use_local_notifications()``` needs to be called upon contstucting an instance of ``G90Alarm`` class, then ```G90Alarm.listen_notifications()`z to start processing those coming from the panel - the code fragment below demonstrate that though being incomplete since callbacks (e.g. ``G90Alarm.on_armdisarm()``) should be set for the actual processing of the notifications.
|
|
127
|
+
|
|
128
|
+
.. code:: python
|
|
129
|
+
|
|
130
|
+
from pyg90alarm import G90Alarm
|
|
131
|
+
|
|
132
|
+
# Create an instance of the alarm panel
|
|
133
|
+
alarm = G90Alarm(host='10.10.10.250')
|
|
134
|
+
# Enable local notifications
|
|
135
|
+
await alarm.use_local_notifications()
|
|
136
|
+
# Start listening for notifications
|
|
137
|
+
await alarm.listen_notifications()
|
|
138
|
+
|
|
139
|
+
Cloud notifications
|
|
140
|
+
-------------------
|
|
141
|
+
|
|
142
|
+
The cloud protocol is native to the panel and is used to interact with mobile application. The package can mimic the cloud server and interpret the messages the panel sends to the cloud, allowing to receive the notifications and alerts.
|
|
143
|
+
While the protocol also allows to send commands to the panel, it is not implemented and local protocol is used for that - i.e. when cloud notifications are in use the local protocol still utilized for sending commands to the panel.
|
|
144
|
+
|
|
145
|
+
The cloud protocol is TCP based and typically interacts with cloud service at known IP address and port (not customizeable at panel side). To process the cloud notifications all the traffic from panel towards the cloud (IP address ``47.88.7.61`` and TCP port ``5678`` as of writing) needs to be diverted to the node where the package is running - depending on your network equipment it could be port forwarding, DNAT or other means. It is unclear whether the panel utilizes DNS to resolve the cloud service IP address, hence the documentation only mentions IP-based traffic redirection.
|
|
146
|
+
|
|
147
|
+
Please see
|
|
148
|
+
`cloud-protocol.rst <docs/cloud-protocol.rst>`_ for further details on the protocol.
|
|
149
|
+
|
|
150
|
+
The benefit of the cloud notifications is that the panel no longer required to have ``10.10.10.250`` IP address.
|
|
151
|
+
|
|
152
|
+
The package could act as:
|
|
153
|
+
|
|
154
|
+
- Standalone cloud server with no Internet connectivity or cloud service
|
|
155
|
+
required at all - good if you'd like to avoid having a vendor service involved. Please note the mobile application will show panel as offline in this mode
|
|
156
|
+
- Chained cloud server, where in addition to intepreting the notifications it
|
|
157
|
+
will also forward all packets received from the panel to the cloud server, and pass its responses back to the panel. This allows to have notificaitons processed by the package and the mobile application working as well.
|
|
158
|
+
|
|
159
|
+
.. note:: Sending packets upstream to the known IP address and port of the cloud server might result in those looped back (since traffic from panel to cloud service has to be redirected to the host where package runs), if your network equipment can't account for source address in redirection rules (i.e. limiting the port redirection to the panel's IP address). In that case you'll need another redirection, from the host where the package runs to the cloud service using an IP from your network. That way those two redirection rules will coexist correctly. To illustate:
|
|
160
|
+
|
|
161
|
+
Port forwarding rule 1:
|
|
162
|
+
|
|
163
|
+
- Source: panel IP address
|
|
164
|
+
- Destination: 47.88.7.61
|
|
165
|
+
- Port: 5678
|
|
166
|
+
- Redirect to host: host where package runs
|
|
167
|
+
- Redirect to port: 5678 (or other port if you want to use it)
|
|
168
|
+
|
|
169
|
+
Port forwarding rule 2 (optional):
|
|
170
|
+
|
|
171
|
+
- Source: host where package runs
|
|
172
|
+
- Destination: an IP address from your network
|
|
173
|
+
- Port: 5678 (or other port if you want to use it)
|
|
174
|
+
- Redirect to : 47.88.7.61
|
|
175
|
+
- Redirect to port: 5678
|
|
176
|
+
|
|
177
|
+
The code fragments below demonstrate how to utilize both modes - please note those are incomplete, since no callbacks are set to process the notifications.
|
|
178
|
+
|
|
179
|
+
**Standalone mode**
|
|
180
|
+
|
|
181
|
+
.. code:: python
|
|
182
|
+
|
|
183
|
+
from pyg90alarm import G90Alarm
|
|
184
|
+
|
|
185
|
+
# Create an instance of the alarm panel
|
|
186
|
+
alarm = G90Alarm(host='<panel IP address>')
|
|
187
|
+
# Enable cloud notifications
|
|
188
|
+
await alarm.use_cloud_notifications(
|
|
189
|
+
# Optional, see note above redirecting cloud traffic from panel
|
|
190
|
+
local_port=5678,
|
|
191
|
+
upstream_host=None
|
|
192
|
+
)
|
|
193
|
+
# Start listening for notifications
|
|
194
|
+
await alarm.listen_notifications()
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
**Chained mode**
|
|
198
|
+
|
|
199
|
+
.. code:: python
|
|
200
|
+
|
|
201
|
+
from pyg90alarm import G90Alarm
|
|
202
|
+
|
|
203
|
+
# Create an instance of the alarm panel
|
|
204
|
+
alarm = G90Alarm(host='<panel IP address>')
|
|
205
|
+
# Enable cloud notifications
|
|
206
|
+
await alarm.use_cloud_notifications(
|
|
207
|
+
# Optional, see note above redirecting cloud traffic from panel
|
|
208
|
+
local_port=5678,
|
|
209
|
+
# See note above re: cloud service and sending packets to it
|
|
210
|
+
upstream_host='47.88.7.61',
|
|
211
|
+
upstream_port=5678
|
|
212
|
+
)
|
|
213
|
+
# Start listening for notifications
|
|
214
|
+
await alarm.listen_notifications()
|
|
215
|
+
|
|
216
|
+
|
|
134
217
|
Quick start
|
|
135
218
|
===========
|
|
136
219
|
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
Cloud protocol
|
|
2
|
+
=============================================
|
|
3
|
+
|
|
4
|
+
.. contents::
|
|
5
|
+
|
|
6
|
+
Version
|
|
7
|
+
-------
|
|
8
|
+
|
|
9
|
+
The cloud protocol version: 1.1 (presumably, as seen in response to ``GETHOSTINFO`` local command).
|
|
10
|
+
|
|
11
|
+
Description
|
|
12
|
+
-----------
|
|
13
|
+
|
|
14
|
+
The cloud protocol is TCP based, using ``47.88.7.61`` as destination IP address and port ``5678`` (both as seen towards cloud service side). The connection is always initiated by the alarm panel.
|
|
15
|
+
|
|
16
|
+
The protocol is binary with header (basic or versioned) and command-specific payload. All data is sent in host order (little-endian, LSB first). See below for their wire format.
|
|
17
|
+
|
|
18
|
+
Security
|
|
19
|
+
--------
|
|
20
|
+
|
|
21
|
+
.. warning:: The cloud protocol *does not* provide any authorization or encryption. Presumably, the device ID (GUID) is what identifies the panel to the cloud service.
|
|
22
|
+
|
|
23
|
+
Packet format
|
|
24
|
+
-------------
|
|
25
|
+
|
|
26
|
+
The G90 cloud protocol packets consist of a header followed by command-specific payload:
|
|
27
|
+
|
|
28
|
+
::
|
|
29
|
+
|
|
30
|
+
+----------------+------------------------+
|
|
31
|
+
| Header | Payload |
|
|
32
|
+
| (8 or 12 bytes)| (variable length) |
|
|
33
|
+
+----------------+------------------------+
|
|
34
|
+
|
|
35
|
+
Header format
|
|
36
|
+
-------------
|
|
37
|
+
|
|
38
|
+
The protocol uses two types of headers:
|
|
39
|
+
|
|
40
|
+
1. Basic Header (8 bytes):
|
|
41
|
+
|
|
42
|
+
::
|
|
43
|
+
|
|
44
|
+
0 1 2 3
|
|
45
|
+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
|
46
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
47
|
+
| Command | Source | Flag1 | Destination |
|
|
48
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
49
|
+
| Message Length |
|
|
50
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
51
|
+
|
|
52
|
+
2. Versioned Header (12 bytes):
|
|
53
|
+
|
|
54
|
+
::
|
|
55
|
+
|
|
56
|
+
0 1 2 3
|
|
57
|
+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
|
58
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
59
|
+
| Command | Source | Flag1 | Destination |
|
|
60
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
61
|
+
| Message Length |
|
|
62
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
63
|
+
| Version | Sequence |
|
|
64
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
65
|
+
|
|
66
|
+
Where:
|
|
67
|
+
|
|
68
|
+
- **Command**: The command type (see :py:class:`.G90CloudCommand`)
|
|
69
|
+
- **Source**: The source direction of the message (see :py:class:`.G90CloudDirection`)
|
|
70
|
+
- **Flag1**: A flag of unknown purpose (typically 0x00)
|
|
71
|
+
- **Destination**: The destination direction of the message (see :py:class:`.G90CloudDirection`)
|
|
72
|
+
- **Message Length**: Total length of the message including header and payload
|
|
73
|
+
- **Version**: Protocol version (0x01 for protocol version 1.1)
|
|
74
|
+
- **Sequence**: Sequence number, either 0 for single message in the packet or starting from 1 for multiple ones
|
|
75
|
+
|
|
76
|
+
Payload format
|
|
77
|
+
--------------
|
|
78
|
+
|
|
79
|
+
The payload format is command-specific and follows the header. The payload length can be calculated as:
|
|
80
|
+
|
|
81
|
+
::
|
|
82
|
+
|
|
83
|
+
Payload Length = Message Length - Header Size
|
|
84
|
+
|
|
85
|
+
All messages are defined in the :py:mod:`.cloud.messages` module for the headeres and the command-specific payload.
|
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
Local protocol
|
|
2
|
+
=============================================
|
|
3
3
|
|
|
4
4
|
.. contents::
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
By the time of writing the following protocol versions are in use:
|
|
6
|
+
Version
|
|
7
|
+
-------
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
* Local: version 1.2
|
|
9
|
+
The local protocol version: 1.2 (presumably, as seen in response to ``GETHOSTINFO`` local command).
|
|
13
10
|
|
|
14
|
-
|
|
11
|
+
Description
|
|
12
|
+
-----------
|
|
15
13
|
|
|
16
14
|
The local protocol is UDP based, using destination port (alarm panel side) of
|
|
17
15
|
``12368``. It has been noticed the vendor provided applications (at least, on iOS)
|
|
@@ -37,7 +35,7 @@ That translates to:
|
|
|
37
35
|
You should consider implementing network controls to, at least, limit on what
|
|
38
36
|
clients could interact with the alarm control panel. The implementation might
|
|
39
37
|
consider firewall rules, VLANs and other measures available in the network
|
|
40
|
-
equipment you
|
|
38
|
+
equipment you use.
|
|
41
39
|
|
|
42
40
|
Request
|
|
43
41
|
-------
|
|
@@ -148,7 +146,7 @@ notifications are send unconditionally, that is you cannot disable them, while
|
|
|
148
146
|
alerts are only sent if enabled in the device.
|
|
149
147
|
|
|
150
148
|
To receive the notifications from the device you need to follow the steps
|
|
151
|
-
outlined in :ref:`
|
|
149
|
+
outlined in :ref:`Local notifications`.
|
|
152
150
|
|
|
153
151
|
The device uses UDP protocol and ``12901`` target port, each notification is
|
|
154
152
|
sent in separate packets having the following structure:
|
|
@@ -159,4 +157,4 @@ All messages are terminated with binary zero (shown below as ``\0``), and text
|
|
|
159
157
|
uses ``utf-8`` encoding.
|
|
160
158
|
|
|
161
159
|
Data varies across different notification and alert types, see
|
|
162
|
-
`pyg90alarm/
|
|
160
|
+
`src/pyg90alarm/local/notifications.py <../../src/pyg90alarm/local/notifications.py>`_.
|
|
@@ -36,7 +36,6 @@ setup(
|
|
|
36
36
|
'Topic :: System :: Hardware',
|
|
37
37
|
'License :: OSI Approved :: MIT License',
|
|
38
38
|
'Programming Language :: Python :: 3',
|
|
39
|
-
'Programming Language :: Python :: 3.8',
|
|
40
39
|
'Programming Language :: Python :: 3.9',
|
|
41
40
|
'Programming Language :: Python :: 3.10',
|
|
42
41
|
'Programming Language :: Python :: 3.11',
|
|
@@ -48,7 +47,7 @@ setup(
|
|
|
48
47
|
keywords='g90, alarm, protocol',
|
|
49
48
|
package_dir={'': 'src'},
|
|
50
49
|
packages=find_packages(where='src'),
|
|
51
|
-
python_requires='>=3.
|
|
50
|
+
python_requires='>=3.9, <4',
|
|
52
51
|
install_requires=[],
|
|
53
52
|
|
|
54
53
|
extras_require={
|
|
@@ -23,17 +23,17 @@ Python package to control G90-based alarm systems.
|
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
25
|
from .alarm import G90Alarm
|
|
26
|
-
from .base_cmd import G90BaseCommand
|
|
27
|
-
from .paginated_result import G90PaginatedResult
|
|
28
|
-
from .
|
|
26
|
+
from .local.base_cmd import G90BaseCommand
|
|
27
|
+
from .local.paginated_result import G90PaginatedResult
|
|
28
|
+
from .notifications.base import (
|
|
29
29
|
G90DeviceAlert,
|
|
30
30
|
)
|
|
31
31
|
from .entities.sensor import G90Sensor, G90SensorTypes
|
|
32
32
|
from .entities.device import G90Device
|
|
33
|
-
from .host_info import (
|
|
33
|
+
from .local.host_info import (
|
|
34
34
|
G90HostInfo, G90HostInfoWifiStatus, G90HostInfoGsmStatus
|
|
35
35
|
)
|
|
36
|
-
from .host_status import G90HostStatus
|
|
36
|
+
from .local.host_status import G90HostStatus
|
|
37
37
|
from .const import (
|
|
38
38
|
G90MessageTypes,
|
|
39
39
|
G90NotificationTypes,
|