pyg90alarm 2.3.0__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.
Files changed (42) hide show
  1. pyg90alarm/__init__.py +84 -0
  2. pyg90alarm/alarm.py +1274 -0
  3. pyg90alarm/callback.py +146 -0
  4. pyg90alarm/cloud/__init__.py +31 -0
  5. pyg90alarm/cloud/const.py +56 -0
  6. pyg90alarm/cloud/messages.py +593 -0
  7. pyg90alarm/cloud/notifications.py +410 -0
  8. pyg90alarm/cloud/protocol.py +518 -0
  9. pyg90alarm/const.py +273 -0
  10. pyg90alarm/definitions/__init__.py +3 -0
  11. pyg90alarm/definitions/base.py +247 -0
  12. pyg90alarm/definitions/devices.py +366 -0
  13. pyg90alarm/definitions/sensors.py +843 -0
  14. pyg90alarm/entities/__init__.py +3 -0
  15. pyg90alarm/entities/base_entity.py +93 -0
  16. pyg90alarm/entities/base_list.py +268 -0
  17. pyg90alarm/entities/device.py +97 -0
  18. pyg90alarm/entities/device_list.py +156 -0
  19. pyg90alarm/entities/sensor.py +891 -0
  20. pyg90alarm/entities/sensor_list.py +183 -0
  21. pyg90alarm/exceptions.py +63 -0
  22. pyg90alarm/local/__init__.py +0 -0
  23. pyg90alarm/local/base_cmd.py +293 -0
  24. pyg90alarm/local/config.py +157 -0
  25. pyg90alarm/local/discovery.py +103 -0
  26. pyg90alarm/local/history.py +272 -0
  27. pyg90alarm/local/host_info.py +89 -0
  28. pyg90alarm/local/host_status.py +52 -0
  29. pyg90alarm/local/notifications.py +117 -0
  30. pyg90alarm/local/paginated_cmd.py +132 -0
  31. pyg90alarm/local/paginated_result.py +135 -0
  32. pyg90alarm/local/targeted_discovery.py +162 -0
  33. pyg90alarm/local/user_data_crc.py +46 -0
  34. pyg90alarm/notifications/__init__.py +0 -0
  35. pyg90alarm/notifications/base.py +481 -0
  36. pyg90alarm/notifications/protocol.py +127 -0
  37. pyg90alarm/py.typed +0 -0
  38. pyg90alarm-2.3.0.dist-info/METADATA +277 -0
  39. pyg90alarm-2.3.0.dist-info/RECORD +42 -0
  40. pyg90alarm-2.3.0.dist-info/WHEEL +5 -0
  41. pyg90alarm-2.3.0.dist-info/licenses/LICENSE +21 -0
  42. pyg90alarm-2.3.0.dist-info/top_level.txt +1 -0
pyg90alarm/callback.py ADDED
@@ -0,0 +1,146 @@
1
+ # Copyright (c) 2021 Ilia Sotnikov
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+
21
+ """
22
+ Implements callbacks.
23
+ """
24
+ from __future__ import annotations
25
+ import asyncio
26
+ from functools import (partial, wraps)
27
+ from asyncio import Task
28
+ from typing import (
29
+ Any, Callable, Coroutine, cast, Optional, Union, TypeVar, Generic
30
+ )
31
+ import logging
32
+
33
+ Callback = Optional[
34
+ Union[
35
+ Callable[..., None],
36
+ Callable[..., Coroutine[None, None, None]],
37
+ ]
38
+ ]
39
+ T = TypeVar('T', bound=Callback)
40
+
41
+ _LOGGER = logging.getLogger(__name__)
42
+
43
+
44
+ class G90Callback:
45
+ """
46
+ Implements callbacks.
47
+ """
48
+ @staticmethod
49
+ def invoke(
50
+ callback: Callback, *args: Any, **kwargs: Any
51
+ ) -> None:
52
+ """
53
+ Invokes the callback.
54
+ """
55
+ if not callback:
56
+ return
57
+
58
+ _LOGGER.debug('Attempting to invoke callback %s'
59
+ ' (args: %s, kwargs: %s)',
60
+ callback, args, kwargs)
61
+
62
+ if not asyncio.iscoroutinefunction(callback):
63
+ def async_wrapper(
64
+ func: Callable[..., None]
65
+ ) -> Callable[..., Coroutine[Any, Any, None]]:
66
+ """
67
+ Wraps the regular callback function into coroutine, so it could
68
+ later be created as async task.
69
+ """
70
+ @wraps(func)
71
+ async def wrapper(
72
+ *args: Any, **kwds: Any
73
+ ) -> None:
74
+ return func(*args, **kwds)
75
+
76
+ return cast(Callable[..., Coroutine[Any, Any, None]], wrapper)
77
+
78
+ task = asyncio.create_task(
79
+ async_wrapper(
80
+ cast(Callable[..., None], callback)
81
+ )(*args, **kwargs)
82
+ )
83
+ else:
84
+ task = asyncio.create_task(callback(*args, **kwargs))
85
+
86
+ def reap_callback_exception(task: Task[Any]) -> None:
87
+ """
88
+ Reaps an exception (if any) from the task logging it, to prevent
89
+ `asyncio` reporting that task exception was never retrieved.
90
+ """
91
+ exc = task.exception()
92
+ if exc:
93
+ _LOGGER.error(
94
+ "Got exception when invoking callback '%s(...)':",
95
+ cast(
96
+ Coroutine[Any, Any, None], task.get_coro()
97
+ ).__qualname__,
98
+ exc_info=exc, stack_info=False
99
+ )
100
+
101
+ task.add_done_callback(reap_callback_exception)
102
+
103
+ @staticmethod
104
+ def invoke_delayed(
105
+ delay: float, callback: Callable[..., None], *args: Any, **kwargs: Any
106
+ ) -> None:
107
+ """
108
+ Invokes the callback after a delay.
109
+ """
110
+ loop = asyncio.get_running_loop()
111
+ loop.call_later(delay, partial(callback, *args, **kwargs))
112
+
113
+
114
+ class G90CallbackList(Generic[T]):
115
+ """
116
+ Implements a list of callbacks.
117
+ """
118
+ def __init__(self) -> None:
119
+ self._callbacks: list[T] = []
120
+
121
+ def add(self, callback: T) -> None:
122
+ """
123
+ Adds a callback to the list.
124
+ """
125
+ if callback and callback not in self._callbacks:
126
+ self._callbacks.append(callback)
127
+
128
+ def remove(self, callback: T) -> None:
129
+ """
130
+ Removes a callback from the list.
131
+ """
132
+ if callback in self._callbacks:
133
+ self._callbacks.remove(callback)
134
+
135
+ def clear(self) -> None:
136
+ """
137
+ Clears the list of callbacks.
138
+ """
139
+ self._callbacks.clear()
140
+
141
+ def invoke(self, *args: Any, **kwargs: Any) -> None:
142
+ """
143
+ Invokes all callbacks in the list.
144
+ """
145
+ for callback in self._callbacks:
146
+ G90Callback.invoke(callback, *args, **kwargs)
@@ -0,0 +1,31 @@
1
+ # Copyright (c) 2025 Ilia Sotnikov
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+
21
+ """
22
+ Cloud communication implementation for G90 alarm systems.
23
+
24
+ This module provides the necessary components to interact with G90 alarm
25
+ systems through their cloud protocol (referred to as version 1.1).
26
+ """
27
+ from .notifications import G90CloudNotifications # noqa: F401
28
+
29
+ __all__ = [
30
+ 'G90CloudNotifications',
31
+ ]
@@ -0,0 +1,56 @@
1
+ # Copyright (c) 2025 Ilia Sotnikov
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+
21
+ """
22
+ Constants used in the G90 cloud protocol implementation.
23
+
24
+ This module defines the main enumerations for direction and command types
25
+ used in the cloud protocol communication with G90 alarm systems.
26
+ """
27
+ from enum import IntEnum
28
+
29
+
30
+ class G90CloudDirection(IntEnum):
31
+ """
32
+ Defines the direction of G90 cloud protocol messages.
33
+
34
+ These values indicate whether messages are flowing from the cloud to the
35
+ device, from the device to the cloud, or are part of discovery processes.
36
+ """
37
+ UNSPECIFIED = 0
38
+ CLOUD = 32 # 0x20
39
+ DEVICE = 16 # 0x10
40
+ DEVICE_DISCOVERY = 48 # 0x30
41
+ CLOUD_DISCOVERY = 208 # 0xD0
42
+
43
+
44
+ class G90CloudCommand(IntEnum):
45
+ """
46
+ Defines the command types used in G90 cloud protocol messages.
47
+
48
+ These values identify the purpose of each cloud protocol message,
49
+ such as hello messages, notifications, commands, and status updates.
50
+ """
51
+ HELLO = 0x01
52
+ HELLO_ACK = 0x41
53
+ NOTIFICATION = 0x22
54
+ STATUS_CHANGE = 0x21
55
+ HELLO_INFO = 0x63
56
+ COMMAND = 0x29