pyg90alarm 1.20.0__tar.gz → 2.0.1__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.
Files changed (73) hide show
  1. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/.github/workflows/main.yml +0 -3
  2. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/MANIFEST.in +1 -1
  3. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/PKG-INFO +101 -18
  4. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/README.rst +97 -14
  5. pyg90alarm-2.0.1/docs/cloud-protocol.rst +85 -0
  6. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/docs/index.rst +2 -1
  7. pyg90alarm-1.20.0/docs/protocol.rst → pyg90alarm-2.0.1/docs/local-protocol.rst +10 -12
  8. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/setup.py +1 -2
  9. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/sonar-project.properties +1 -1
  10. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/src/pyg90alarm/__init__.py +5 -5
  11. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/src/pyg90alarm/alarm.py +130 -34
  12. pyg90alarm-2.0.1/src/pyg90alarm/cloud/__init__.py +31 -0
  13. pyg90alarm-2.0.1/src/pyg90alarm/cloud/const.py +56 -0
  14. pyg90alarm-2.0.1/src/pyg90alarm/cloud/messages.py +593 -0
  15. pyg90alarm-2.0.1/src/pyg90alarm/cloud/notifications.py +409 -0
  16. pyg90alarm-2.0.1/src/pyg90alarm/cloud/protocol.py +518 -0
  17. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/src/pyg90alarm/const.py +5 -0
  18. {pyg90alarm-1.20.0/src/pyg90alarm → pyg90alarm-2.0.1/src/pyg90alarm/local}/base_cmd.py +3 -6
  19. {pyg90alarm-1.20.0/src/pyg90alarm → pyg90alarm-2.0.1/src/pyg90alarm/local}/discovery.py +1 -1
  20. {pyg90alarm-1.20.0/src/pyg90alarm → pyg90alarm-2.0.1/src/pyg90alarm/local}/history.py +4 -2
  21. {pyg90alarm-1.20.0/src/pyg90alarm → pyg90alarm-2.0.1/src/pyg90alarm/local}/host_status.py +1 -1
  22. pyg90alarm-2.0.1/src/pyg90alarm/local/notifications.py +116 -0
  23. {pyg90alarm-1.20.0/src/pyg90alarm → pyg90alarm-2.0.1/src/pyg90alarm/local}/paginated_cmd.py +2 -2
  24. {pyg90alarm-1.20.0/src/pyg90alarm → pyg90alarm-2.0.1/src/pyg90alarm/local}/paginated_result.py +1 -1
  25. {pyg90alarm-1.20.0/src/pyg90alarm → pyg90alarm-2.0.1/src/pyg90alarm/local}/targeted_discovery.py +2 -2
  26. pyg90alarm-1.20.0/src/pyg90alarm/device_notifications.py → pyg90alarm-2.0.1/src/pyg90alarm/notifications/base.py +115 -173
  27. pyg90alarm-2.0.1/src/pyg90alarm/notifications/protocol.py +116 -0
  28. pyg90alarm-2.0.1/src/pyg90alarm/py.typed +0 -0
  29. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/src/pyg90alarm.egg-info/PKG-INFO +101 -18
  30. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/src/pyg90alarm.egg-info/SOURCES.txt +24 -13
  31. pyg90alarm-2.0.1/tests/__init__.py +0 -0
  32. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/tests/conftest.py +60 -4
  33. pyg90alarm-2.0.1/tests/device_mock.py +705 -0
  34. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/tests/test_alarm.py +106 -82
  35. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/tests/test_base_commands.py +10 -10
  36. pyg90alarm-2.0.1/tests/test_cloud_notifications.py +502 -0
  37. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/tests/test_discovery.py +4 -4
  38. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/tests/test_history.py +3 -3
  39. pyg90alarm-1.20.0/tests/test_notifications.py → pyg90alarm-2.0.1/tests/test_local_notifications.py +209 -125
  40. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/tests/test_paginated_commands.py +5 -5
  41. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/tox.ini +1 -1
  42. pyg90alarm-1.20.0/tests/device_mock.py +0 -277
  43. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/.github/CODEOWNERS +0 -0
  44. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/.gitignore +0 -0
  45. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/.pylintrc +0 -0
  46. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/.readthedocs.yaml +0 -0
  47. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/LICENSE +0 -0
  48. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/docs/.DS_Store +0 -0
  49. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/docs/.gitignore +0 -0
  50. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/docs/api-docs.rst +0 -0
  51. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/docs/conf.py +0 -0
  52. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/docs/requirements.txt +0 -0
  53. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/pyproject.toml +0 -0
  54. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/setup.cfg +0 -0
  55. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/src/pyg90alarm/callback.py +0 -0
  56. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/src/pyg90alarm/definitions/__init__.py +0 -0
  57. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/src/pyg90alarm/definitions/sensors.py +0 -0
  58. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/src/pyg90alarm/entities/__init__.py +0 -0
  59. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/src/pyg90alarm/entities/base_entity.py +0 -0
  60. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/src/pyg90alarm/entities/base_list.py +0 -0
  61. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/src/pyg90alarm/entities/device.py +0 -0
  62. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/src/pyg90alarm/entities/device_list.py +0 -0
  63. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/src/pyg90alarm/entities/sensor.py +0 -0
  64. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/src/pyg90alarm/entities/sensor_list.py +0 -0
  65. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/src/pyg90alarm/exceptions.py +0 -0
  66. {pyg90alarm-1.20.0/tests → pyg90alarm-2.0.1/src/pyg90alarm/local}/__init__.py +0 -0
  67. {pyg90alarm-1.20.0/src/pyg90alarm → pyg90alarm-2.0.1/src/pyg90alarm/local}/config.py +0 -0
  68. {pyg90alarm-1.20.0/src/pyg90alarm → pyg90alarm-2.0.1/src/pyg90alarm/local}/host_info.py +0 -0
  69. {pyg90alarm-1.20.0/src/pyg90alarm → pyg90alarm-2.0.1/src/pyg90alarm/local}/user_data_crc.py +0 -0
  70. /pyg90alarm-1.20.0/src/pyg90alarm/py.typed → /pyg90alarm-2.0.1/src/pyg90alarm/notifications/__init__.py +0 -0
  71. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/src/pyg90alarm.egg-info/dependency_links.txt +0 -0
  72. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/src/pyg90alarm.egg-info/requires.txt +0 -0
  73. {pyg90alarm-1.20.0 → pyg90alarm-2.0.1}/src/pyg90alarm.egg-info/top_level.txt +0 -0
@@ -16,9 +16,6 @@ jobs:
16
16
  strategy:
17
17
  matrix:
18
18
  include:
19
- - os: ubuntu-latest
20
- python: '3.8'
21
- toxenv: py
22
19
  - os: ubuntu-latest
23
20
  python: '3.9'
24
21
  toxenv: py
@@ -9,6 +9,6 @@ include LICENSE
9
9
  # Include setup.py
10
10
  include setup.py
11
11
 
12
- recursive-include src py.typed
12
+ recursive-include src *.py py.typed
13
13
 
14
14
  exclude requirements_dev.txt
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: pyg90alarm
3
- Version: 1.20.0
3
+ Version: 2.0.1
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.8, <4
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
- Enabling device notifications
140
- =============================
139
+ Device notifications
140
+ ====================
141
141
 
142
- There is a hidden device capability to send protocol notifications over the
143
- WiFi interface. The notifications are done using broadcast UDP packets with
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
- Please see
153
- `protocol documentation <https://pyg90alarm.readthedocs.io/en/stable/protocol.html>`_
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
- Enabling device notifications
93
- =============================
92
+ Device notifications
93
+ ====================
94
94
 
95
- There is a hidden device capability to send protocol notifications over the
96
- WiFi interface. The notifications are done using broadcast UDP packets with
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
- Please see
106
- `protocol documentation <https://pyg90alarm.readthedocs.io/en/stable/protocol.html>`_
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.
@@ -3,7 +3,8 @@
3
3
  :hidden:
4
4
 
5
5
  Introduction <self>
6
- protocol
6
+ local-protocol
7
+ cloud-protocol
7
8
  api-docs
8
9
 
9
10
  .. contents::
@@ -1,17 +1,15 @@
1
- G90 alarm panel protocol
2
- ========================
1
+ Local protocol
2
+ =============================================
3
3
 
4
4
  .. contents::
5
5
 
6
- There are two protocols a G90 alarm system uses: one towards its own cloud and
7
- another for the clients on local network over WiFi connection.
8
-
9
- By the time of writing the following protocol versions are in use:
6
+ Version
7
+ -------
10
8
 
11
- * Cloud: version 1.1
12
- * Local: version 1.2
9
+ The local protocol version: 1.2 (presumably, as seen in response to ``GETHOSTINFO`` local command).
13
10
 
14
- .. note:: The rest of the document describes only the local protocol, version 1.2
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 user
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:`Enabling device notifications`.
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/device_notifications.py <../../src/pyg90alarm/device_notifications.py>`_.
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.8, <4',
50
+ python_requires='>=3.9, <4',
52
51
  install_requires=[],
53
52
 
54
53
  extras_require={
@@ -1,4 +1,4 @@
1
- sonar.python.version=3.7, 3.8, 3.9, 3.10
1
+ sonar.python.version=3.9, 3.10, 3.11, 3.12, 3.13
2
2
  sonar.python.coverage.reportPaths=coverage.xml
3
3
  sonar.python.pylint.reportPaths=pylint.txt
4
4
  sonar.python.flake8.reportPaths=flake8.txt
@@ -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 .device_notifications import (
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,