pyvlx 0.2.27__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 (84) hide show
  1. pyvlx/__init__.py +21 -0
  2. pyvlx/api/__init__.py +23 -0
  3. pyvlx/api/activate_scene.py +63 -0
  4. pyvlx/api/api_event.py +73 -0
  5. pyvlx/api/command_send.py +85 -0
  6. pyvlx/api/factory_default.py +34 -0
  7. pyvlx/api/frame_creation.py +202 -0
  8. pyvlx/api/frames/__init__.py +76 -0
  9. pyvlx/api/frames/alias_array.py +45 -0
  10. pyvlx/api/frames/frame.py +56 -0
  11. pyvlx/api/frames/frame_activate_scene.py +92 -0
  12. pyvlx/api/frames/frame_activation_log_updated.py +14 -0
  13. pyvlx/api/frames/frame_command_send.py +280 -0
  14. pyvlx/api/frames/frame_discover_nodes.py +64 -0
  15. pyvlx/api/frames/frame_error_notification.py +42 -0
  16. pyvlx/api/frames/frame_facory_default.py +32 -0
  17. pyvlx/api/frames/frame_get_all_nodes_information.py +218 -0
  18. pyvlx/api/frames/frame_get_limitation.py +127 -0
  19. pyvlx/api/frames/frame_get_local_time.py +38 -0
  20. pyvlx/api/frames/frame_get_network_setup.py +64 -0
  21. pyvlx/api/frames/frame_get_node_information.py +223 -0
  22. pyvlx/api/frames/frame_get_protocol_version.py +53 -0
  23. pyvlx/api/frames/frame_get_scene_list.py +82 -0
  24. pyvlx/api/frames/frame_get_state.py +47 -0
  25. pyvlx/api/frames/frame_get_version.py +72 -0
  26. pyvlx/api/frames/frame_helper.py +40 -0
  27. pyvlx/api/frames/frame_house_status_monitor_disable_cfm.py +14 -0
  28. pyvlx/api/frames/frame_house_status_monitor_disable_req.py +14 -0
  29. pyvlx/api/frames/frame_house_status_monitor_enable_cfm.py +14 -0
  30. pyvlx/api/frames/frame_house_status_monitor_enable_req.py +14 -0
  31. pyvlx/api/frames/frame_leave_learn_state.py +41 -0
  32. pyvlx/api/frames/frame_node_information_changed.py +57 -0
  33. pyvlx/api/frames/frame_node_state_position_changed_notification.py +84 -0
  34. pyvlx/api/frames/frame_password_change.py +114 -0
  35. pyvlx/api/frames/frame_password_enter.py +70 -0
  36. pyvlx/api/frames/frame_reboot.py +32 -0
  37. pyvlx/api/frames/frame_set_node_name.py +73 -0
  38. pyvlx/api/frames/frame_set_utc.py +45 -0
  39. pyvlx/api/frames/frame_status_request.py +212 -0
  40. pyvlx/api/get_all_nodes_information.py +46 -0
  41. pyvlx/api/get_limitation.py +64 -0
  42. pyvlx/api/get_local_time.py +34 -0
  43. pyvlx/api/get_network_setup.py +34 -0
  44. pyvlx/api/get_node_information.py +42 -0
  45. pyvlx/api/get_protocol_version.py +40 -0
  46. pyvlx/api/get_scene_list.py +49 -0
  47. pyvlx/api/get_state.py +43 -0
  48. pyvlx/api/get_version.py +34 -0
  49. pyvlx/api/house_status_monitor.py +52 -0
  50. pyvlx/api/leave_learn_state.py +33 -0
  51. pyvlx/api/password_enter.py +39 -0
  52. pyvlx/api/reboot.py +33 -0
  53. pyvlx/api/session_id.py +20 -0
  54. pyvlx/api/set_node_name.py +32 -0
  55. pyvlx/api/set_utc.py +31 -0
  56. pyvlx/api/status_request.py +48 -0
  57. pyvlx/config.py +54 -0
  58. pyvlx/connection.py +182 -0
  59. pyvlx/const.py +685 -0
  60. pyvlx/dataobjects.py +161 -0
  61. pyvlx/discovery.py +100 -0
  62. pyvlx/exception.py +26 -0
  63. pyvlx/heartbeat.py +79 -0
  64. pyvlx/klf200gateway.py +167 -0
  65. pyvlx/lightening_device.py +102 -0
  66. pyvlx/log.py +4 -0
  67. pyvlx/node.py +74 -0
  68. pyvlx/node_helper.py +165 -0
  69. pyvlx/node_updater.py +162 -0
  70. pyvlx/nodes.py +99 -0
  71. pyvlx/on_off_switch.py +44 -0
  72. pyvlx/opening_device.py +644 -0
  73. pyvlx/parameter.py +357 -0
  74. pyvlx/py.typed +0 -0
  75. pyvlx/pyvlx.py +124 -0
  76. pyvlx/scene.py +53 -0
  77. pyvlx/scenes.py +60 -0
  78. pyvlx/slip.py +48 -0
  79. pyvlx/string_helper.py +20 -0
  80. pyvlx-0.2.27.dist-info/METADATA +122 -0
  81. pyvlx-0.2.27.dist-info/RECORD +84 -0
  82. pyvlx-0.2.27.dist-info/WHEEL +5 -0
  83. pyvlx-0.2.27.dist-info/licenses/LICENSE +165 -0
  84. pyvlx-0.2.27.dist-info/top_level.txt +1 -0
pyvlx/connection.py ADDED
@@ -0,0 +1,182 @@
1
+ """Module for handling the TCP connection with Gateway."""
2
+ import asyncio
3
+ import ssl
4
+ import sys
5
+ from typing import Callable, Coroutine, List, Optional, Set
6
+
7
+ from .api.frame_creation import frame_from_raw
8
+ from .api.frames import FrameBase
9
+ from .config import Config
10
+ from .exception import PyVLXException
11
+ from .log import PYVLXLOG
12
+ from .slip import get_next_slip, is_slip, slip_pack
13
+
14
+
15
+ class SlipTokenizer:
16
+ """Helper class for splitting up binary stream to slip packets."""
17
+
18
+ def __init__(self) -> None:
19
+ """Init Tokenizer."""
20
+ self.data = bytes()
21
+
22
+ def feed(self, chunk: bytes) -> None:
23
+ """Feed chunk to tokenizer."""
24
+ if not chunk:
25
+ return
26
+ self.data += chunk
27
+
28
+ def has_tokens(self) -> bool:
29
+ """Return True if Tokenizer has tokens."""
30
+ return is_slip(self.data)
31
+
32
+ def get_next_token(self) -> Optional[bytes]:
33
+ """Get next token from Tokenizer."""
34
+ slip, self.data = get_next_slip(self.data)
35
+ return slip
36
+
37
+
38
+ class TCPTransport(asyncio.Protocol):
39
+ """Class for handling asyncio connection transport."""
40
+
41
+ def __init__(
42
+ self,
43
+ frame_received_cb: Callable[[FrameBase], None],
44
+ connection_lost_cb: Callable[[], None],
45
+ ):
46
+ """Init TCPTransport."""
47
+ self.frame_received_cb = frame_received_cb
48
+ self.connection_lost_cb = connection_lost_cb
49
+ self.tokenizer = SlipTokenizer()
50
+
51
+ def connection_made(self, transport: object) -> None:
52
+ """Handle sucessful connection."""
53
+ PYVLXLOG.debug("Socket connection to KLF 200 opened")
54
+
55
+ def data_received(self, data: bytes) -> None:
56
+ """Handle data received."""
57
+ self.tokenizer.feed(data)
58
+ while self.tokenizer.has_tokens():
59
+ raw = self.tokenizer.get_next_token()
60
+ assert raw is not None
61
+
62
+ try:
63
+ frame = frame_from_raw(raw)
64
+ if frame is not None:
65
+ self.frame_received_cb(frame)
66
+ except PyVLXException:
67
+ PYVLXLOG.error("Error in data_received", exc_info=sys.exc_info())
68
+
69
+ def connection_lost(self, exc: object) -> None:
70
+ """Handle lost connection."""
71
+ PYVLXLOG.debug("Socket connection to KLF 200 has been lost")
72
+ self.connection_lost_cb()
73
+
74
+
75
+ CallbackType = Callable[[FrameBase], Coroutine]
76
+
77
+
78
+ class Connection:
79
+ """Class for handling TCP connection."""
80
+
81
+ def __init__(self, loop: asyncio.AbstractEventLoop, config: Config):
82
+ """Init TCP connection."""
83
+ self.loop = loop
84
+ self.config = config
85
+ self.transport: Optional[asyncio.Transport] = None
86
+ self.frame_received_cbs: List[CallbackType] = []
87
+ self.connection_closed_cbs: List[Callable[[], Coroutine]] = []
88
+ self.connection_opened_cbs: List[Callable[[], Coroutine]] = []
89
+ self.connected = False
90
+ self.connection_counter = 0
91
+ self.tasks: Set[asyncio.Task] = set()
92
+
93
+ def __del__(self) -> None:
94
+ """Destruct connection."""
95
+ self.disconnect()
96
+
97
+ def disconnect(self) -> None:
98
+ """Disconnect connection."""
99
+ if self.transport is not None:
100
+ self.transport.close()
101
+ self.transport = None
102
+ self.connected = False
103
+ PYVLXLOG.debug("TCP transport closed.")
104
+ for connection_closed_cb in self.connection_closed_cbs:
105
+ if asyncio.iscoroutine(connection_closed_cb()):
106
+ task = self.loop.create_task(connection_closed_cb())
107
+ self.tasks.add(task)
108
+ task.add_done_callback(self.tasks.remove)
109
+
110
+ async def connect(self) -> None:
111
+ """Connect to gateway via SSL."""
112
+ tcp_client = TCPTransport(self.frame_received_cb, connection_lost_cb=self.on_connection_lost)
113
+ assert self.config.host is not None
114
+ self.transport, _ = await self.loop.create_connection(
115
+ lambda: tcp_client,
116
+ host=self.config.host,
117
+ port=self.config.port,
118
+ ssl=self.create_ssl_context(),
119
+ )
120
+ self.connected = True
121
+ self.connection_counter += 1
122
+ PYVLXLOG.debug(
123
+ "Amount of connections since last HA start: %s", self.connection_counter
124
+ )
125
+ for connection_opened_cb in self.connection_opened_cbs:
126
+ if asyncio.iscoroutine(connection_opened_cb()):
127
+ task = self.loop.create_task(connection_opened_cb())
128
+ self.tasks.add(task)
129
+ task.add_done_callback(self.tasks.remove)
130
+
131
+ def register_frame_received_cb(self, callback: CallbackType) -> None:
132
+ """Register frame received callback."""
133
+ self.frame_received_cbs.append(callback)
134
+
135
+ def unregister_frame_received_cb(self, callback: CallbackType) -> None:
136
+ """Unregister frame received callback."""
137
+ self.frame_received_cbs.remove(callback)
138
+
139
+ def register_connection_closed_cb(self, callback: Callable[[], Coroutine]) -> None:
140
+ """Register connection closed callback."""
141
+ self.connection_closed_cbs.append(callback)
142
+
143
+ def unregister_connection_closed_cb(self, callback: Callable[[], Coroutine]) -> None:
144
+ """Unregister connection closed callback."""
145
+ self.connection_closed_cbs.remove(callback)
146
+
147
+ def register_connection_opened_cb(self, callback: Callable[[], Coroutine]) -> None:
148
+ """Register connection opened callback."""
149
+ self.connection_opened_cbs.append(callback)
150
+
151
+ def unregister_connection_opened_cb(self, callback: Callable[[], Coroutine]) -> None:
152
+ """Unregister connection opened callback."""
153
+ self.connection_opened_cbs.remove(callback)
154
+
155
+ def write(self, frame: FrameBase) -> None:
156
+ """Write frame to Bus."""
157
+ if not isinstance(frame, FrameBase):
158
+ raise PyVLXException("Frame not of type FrameBase", *type(frame))
159
+ PYVLXLOG.debug("SEND: %s", frame)
160
+ assert self.transport is not None
161
+ self.transport.write(slip_pack(bytes(frame)))
162
+
163
+ @staticmethod
164
+ def create_ssl_context() -> ssl.SSLContext:
165
+ """Create and return SSL Context."""
166
+ ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
167
+ ssl_context.check_hostname = False
168
+ ssl_context.verify_mode = ssl.CERT_NONE
169
+ return ssl_context
170
+
171
+ def frame_received_cb(self, frame: FrameBase) -> None:
172
+ """Received message."""
173
+ PYVLXLOG.debug("REC: %s", frame)
174
+ for frame_received_cb in self.frame_received_cbs:
175
+ # pylint: disable=not-callable
176
+ task = self.loop.create_task(frame_received_cb(frame))
177
+ self.tasks.add(task)
178
+ task.add_done_callback(self.tasks.remove)
179
+
180
+ def on_connection_lost(self) -> None:
181
+ """Server closed connection."""
182
+ self.disconnect()