benchlab-pytools 3.0.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 (184) hide show
  1. benchlab/__init__.py +14 -0
  2. benchlab/__main__.py +21 -0
  3. benchlab/config/README.md +325 -0
  4. benchlab/config/__init__.py +9 -0
  5. benchlab/config/config_client.py +631 -0
  6. benchlab/config/config_manager.py +495 -0
  7. benchlab/config/config_tool.py +358 -0
  8. benchlab/config/diff.py +163 -0
  9. benchlab/config/examples/complete_config.json +56 -0
  10. benchlab/config/examples/rgb_lighting.json +24 -0
  11. benchlab/config/examples/simple_fan.json +32 -0
  12. benchlab/config/schema.py +138 -0
  13. benchlab/core/README.md +154 -0
  14. benchlab/core/__init__.py +78 -0
  15. benchlab/core/config.py +145 -0
  16. benchlab/core/datasource.py +1209 -0
  17. benchlab/core/datasource_manager.py +418 -0
  18. benchlab/core/device_registry.py +206 -0
  19. benchlab/core/discovery.py +92 -0
  20. benchlab/core/infrastructure.py +309 -0
  21. benchlab/core/process_manager.py +356 -0
  22. benchlab/core/retry.py +85 -0
  23. benchlab/core/shared_serial.py +235 -0
  24. benchlab/core/statistics.py +224 -0
  25. benchlab/csv_log/README.md +206 -0
  26. benchlab/csv_log/__init__.py +5 -0
  27. benchlab/csv_log/csv_logger_enhanced.py +416 -0
  28. benchlab/csv_log/message_batcher.py +361 -0
  29. benchlab/csv_log/requirements.txt +3 -0
  30. benchlab/csv_log/smart_retry.py +466 -0
  31. benchlab/graph/README.md +117 -0
  32. benchlab/graph/__init__.py +5 -0
  33. benchlab/graph/app.py +353 -0
  34. benchlab/graph/requirements.txt +2 -0
  35. benchlab/graph/runner.py +42 -0
  36. benchlab/graph/ui.py +288 -0
  37. benchlab/hwinfo/README.md +135 -0
  38. benchlab/hwinfo/__init__.py +5 -0
  39. benchlab/hwinfo/hwinfo_export.py +386 -0
  40. benchlab/hwinfo/requirements.txt +1 -0
  41. benchlab/launcher.py +387 -0
  42. benchlab/link/.env.EXAMPLE +10 -0
  43. benchlab/link/README.md +172 -0
  44. benchlab/link/__init__.py +1 -0
  45. benchlab/link/link_main.py +479 -0
  46. benchlab/main.py +462 -0
  47. benchlab/menu.py +729 -0
  48. benchlab/menu_classic.py +410 -0
  49. benchlab/mqtt/README.md +201 -0
  50. benchlab/mqtt/__init__.py +5 -0
  51. benchlab/mqtt/mqtt.config_template +2 -0
  52. benchlab/mqtt/mqtt_publisher.py +540 -0
  53. benchlab/mqtt/requirements.txt +3 -0
  54. benchlab/prefs.py +67 -0
  55. benchlab/restapi/.env.example +17 -0
  56. benchlab/restapi/__init__.py +5 -0
  57. benchlab/restapi/favicon.ico +0 -0
  58. benchlab/restapi/readme.md +202 -0
  59. benchlab/restapi/requirements.txt +5 -0
  60. benchlab/restapi/telemetry_api.py +808 -0
  61. benchlab/sources.py +515 -0
  62. benchlab/tools.py +147 -0
  63. benchlab/tui/README.md +266 -0
  64. benchlab/tui/__init__.py +5 -0
  65. benchlab/tui/config.py +477 -0
  66. benchlab/tui/requirements.txt +2 -0
  67. benchlab/tui/tui_core.py +1298 -0
  68. benchlab/tui/tui_main.py +418 -0
  69. benchlab/vu/README.md +64 -0
  70. benchlab/vu/VU-Server/NOTICE.md +13 -0
  71. benchlab/vu/VU-Server/README.md +80 -0
  72. benchlab/vu/VU-Server/Running_from_source_on_linux.md +97 -0
  73. benchlab/vu/VU-Server/__init__.py +0 -0
  74. benchlab/vu/VU-Server/assets/vu1_hello_world.png +0 -0
  75. benchlab/vu/VU-Server/community_applications.md +13 -0
  76. benchlab/vu/VU-Server/config.yaml +9 -0
  77. benchlab/vu/VU-Server/database.py +256 -0
  78. benchlab/vu/VU-Server/dial_driver.py +534 -0
  79. benchlab/vu/VU-Server/dials/Comms_Hub_Gauge.py +78 -0
  80. benchlab/vu/VU-Server/dials/Comms_Hub_Server.py +100 -0
  81. benchlab/vu/VU-Server/dials/__init__.py +0 -0
  82. benchlab/vu/VU-Server/dials/base_logger.py +100 -0
  83. benchlab/vu/VU-Server/installer/inc/icon.ico +0 -0
  84. benchlab/vu/VU-Server/installer/install.nsi +148 -0
  85. benchlab/vu/VU-Server/make_version.py +40 -0
  86. benchlab/vu/VU-Server/pylintrc +628 -0
  87. benchlab/vu/VU-Server/requirements.txt +9 -0
  88. benchlab/vu/VU-Server/serial_driver.py +244 -0
  89. benchlab/vu/VU-Server/server.py +670 -0
  90. benchlab/vu/VU-Server/server_config.py +255 -0
  91. benchlab/vu/VU-Server/server_dial_handler.py +334 -0
  92. benchlab/vu/VU-Server/vu_notifications.py +24 -0
  93. benchlab/vu/VU-Server/www/android-chrome-192x192.png +0 -0
  94. benchlab/vu/VU-Server/www/android-chrome-512x512.png +0 -0
  95. benchlab/vu/VU-Server/www/apple-touch-icon.png +0 -0
  96. benchlab/vu/VU-Server/www/assets/css/demo.css +291 -0
  97. benchlab/vu/VU-Server/www/assets/css/demo.min.css +9 -0
  98. benchlab/vu/VU-Server/www/assets/css/demo.rtl.css +276 -0
  99. benchlab/vu/VU-Server/www/assets/css/demo.rtl.min.css +9 -0
  100. benchlab/vu/VU-Server/www/assets/css/tabler-flags.css +1084 -0
  101. benchlab/vu/VU-Server/www/assets/css/tabler-flags.min.css +9 -0
  102. benchlab/vu/VU-Server/www/assets/css/tabler-flags.rtl.css +1084 -0
  103. benchlab/vu/VU-Server/www/assets/css/tabler-flags.rtl.min.css +9 -0
  104. benchlab/vu/VU-Server/www/assets/css/tabler-payments.css +528 -0
  105. benchlab/vu/VU-Server/www/assets/css/tabler-payments.min.css +9 -0
  106. benchlab/vu/VU-Server/www/assets/css/tabler-payments.rtl.css +528 -0
  107. benchlab/vu/VU-Server/www/assets/css/tabler-payments.rtl.min.css +9 -0
  108. benchlab/vu/VU-Server/www/assets/css/tabler-social.css +10 -0
  109. benchlab/vu/VU-Server/www/assets/css/tabler-social.min.css +8 -0
  110. benchlab/vu/VU-Server/www/assets/css/tabler-social.rtl.css +10 -0
  111. benchlab/vu/VU-Server/www/assets/css/tabler-social.rtl.min.css +8 -0
  112. benchlab/vu/VU-Server/www/assets/css/tabler-vendors.css +1504 -0
  113. benchlab/vu/VU-Server/www/assets/css/tabler-vendors.min.css +9 -0
  114. benchlab/vu/VU-Server/www/assets/css/tabler-vendors.rtl.css +1504 -0
  115. benchlab/vu/VU-Server/www/assets/css/tabler-vendors.rtl.min.css +9 -0
  116. benchlab/vu/VU-Server/www/assets/css/tabler.css +25813 -0
  117. benchlab/vu/VU-Server/www/assets/css/tabler.min.css +13 -0
  118. benchlab/vu/VU-Server/www/assets/css/tabler.rtl.css +25777 -0
  119. benchlab/vu/VU-Server/www/assets/css/tabler.rtl.min.css +13 -0
  120. benchlab/vu/VU-Server/www/assets/css/theme.min.css +261 -0
  121. benchlab/vu/VU-Server/www/assets/img/header.png +0 -0
  122. benchlab/vu/VU-Server/www/assets/img/logo.png +0 -0
  123. benchlab/vu/VU-Server/www/assets/js/dark-theme.js +35 -0
  124. benchlab/vu/VU-Server/www/assets/js/dark-theme.min.js +9 -0
  125. benchlab/vu/VU-Server/www/assets/js/demo.js +132 -0
  126. benchlab/vu/VU-Server/www/assets/js/demo.min.js +9 -0
  127. benchlab/vu/VU-Server/www/assets/js/jquery.min.js +2 -0
  128. benchlab/vu/VU-Server/www/assets/js/tabler.esm.js +7482 -0
  129. benchlab/vu/VU-Server/www/assets/js/tabler.esm.min.js +15 -0
  130. benchlab/vu/VU-Server/www/assets/js/tabler.js +7543 -0
  131. benchlab/vu/VU-Server/www/assets/js/tabler.min.js +15 -0
  132. benchlab/vu/VU-Server/www/assets/js/vu1_api.js +68 -0
  133. benchlab/vu/VU-Server/www/assets/js/vu1_gui_api_key_settings.js +167 -0
  134. benchlab/vu/VU-Server/www/assets/js/vu1_gui_api_keys.js +138 -0
  135. benchlab/vu/VU-Server/www/assets/js/vu1_gui_dial.js +179 -0
  136. benchlab/vu/VU-Server/www/assets/js/vu1_gui_home.js +60 -0
  137. benchlab/vu/VU-Server/www/assets/js/vu1_gui_root.js +125 -0
  138. benchlab/vu/VU-Server/www/favicon-16x16.png +0 -0
  139. benchlab/vu/VU-Server/www/favicon-32x32.png +0 -0
  140. benchlab/vu/VU-Server/www/favicon.ico +0 -0
  141. benchlab/vu/VU-Server/www/favicon.png +0 -0
  142. benchlab/vu/VU-Server/www/index.html +47 -0
  143. benchlab/vu/VU-Server/www/views/api_keys.html +151 -0
  144. benchlab/vu/VU-Server/www/views/dial.html +286 -0
  145. benchlab/vu/VU-Server/www/views/footer.html +27 -0
  146. benchlab/vu/VU-Server/www/views/header.html +86 -0
  147. benchlab/vu/VU-Server/www/views/key_settings.html +132 -0
  148. benchlab/vu/VU-Server/www/views/start.html +124 -0
  149. benchlab/vu/__init__.py +5 -0
  150. benchlab/vu/assets/Barlow-Bold.ttf +0 -0
  151. benchlab/vu/assets/bl_dial_144x200.png +0 -0
  152. benchlab/vu/assets/bl_logo_144x200.png +0 -0
  153. benchlab/vu/devices.py +166 -0
  154. benchlab/vu/requirements.txt +24 -0
  155. benchlab/vu/sensors.py +18 -0
  156. benchlab/vu/vu_dial.config_template +90 -0
  157. benchlab/vu/vu_logo_gen.py +97 -0
  158. benchlab/vu/vu_server.config_template +5 -0
  159. benchlab/vu/vu_server_config.py +40 -0
  160. benchlab/vu/vu_server_manager.py +192 -0
  161. benchlab/vu/vu_tui.py +919 -0
  162. benchlab/vu/vu_updater.py +540 -0
  163. benchlab/wigidash/README.md +182 -0
  164. benchlab/wigidash/__init__.py +5 -0
  165. benchlab/wigidash/assets/Inter-Bold.ttf +0 -0
  166. benchlab/wigidash/assets/Inter.ttf +0 -0
  167. benchlab/wigidash/assets/benchlab.png +0 -0
  168. benchlab/wigidash/benchlab_fleet.py +150 -0
  169. benchlab/wigidash/benchlab_graph.py +517 -0
  170. benchlab/wigidash/benchlab_overview.py +426 -0
  171. benchlab/wigidash/benchlab_telemetry.py +105 -0
  172. benchlab/wigidash/benchlab_ui.py +190 -0
  173. benchlab/wigidash/benchlab_utils.py +182 -0
  174. benchlab/wigidash/requirements.txt +9 -0
  175. benchlab/wigidash/wigidash_device.py +541 -0
  176. benchlab/wigidash/wigidash_manager.py +342 -0
  177. benchlab/wigidash/wigidash_session.py +355 -0
  178. benchlab/wigidash/wigidash_usb.py +247 -0
  179. benchlab/wigidash/wigidash_widget.py +88 -0
  180. benchlab_pytools-3.0.0.dist-info/METADATA +239 -0
  181. benchlab_pytools-3.0.0.dist-info/RECORD +184 -0
  182. benchlab_pytools-3.0.0.dist-info/WHEEL +4 -0
  183. benchlab_pytools-3.0.0.dist-info/entry_points.txt +2 -0
  184. benchlab_pytools-3.0.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,244 @@
1
+ import re
2
+ import time
3
+ from threading import Lock
4
+ import serial as _serial
5
+ import serial.tools.list_ports as _lp
6
+ import serial.tools.list_ports_common as _lpc
7
+ from serial.tools.list_ports import comports
8
+ from dials.base_logger import logger
9
+
10
+
11
+ class SerialHardware(object):
12
+ def __init__( self,
13
+ port_info,
14
+ flush_on_write=True,
15
+ serialPrefix = '',
16
+ serialSuffix = '\r\n',
17
+ timeout=0.2,
18
+ debug_uart=False):
19
+
20
+ self.lock = Lock()
21
+
22
+ self.flush_on_write = flush_on_write
23
+ self.serialPrefix = serialPrefix
24
+ self.serialSuffix = serialSuffix
25
+ self.debug_uart = debug_uart
26
+
27
+ # If port is string, find port by name
28
+ if isinstance(port_info, str):
29
+ self.port_info = self._find_port_by_name(port_info)
30
+ else:
31
+ self.port_info = port_info
32
+
33
+ if not isinstance(self.port_info, _lpc.ListPortInfo):
34
+ raise TypeError("The port_info for {} must be of type {}".format(self.__class__, _lpc.ListPortInfo))
35
+
36
+ self.port = _serial.Serial(
37
+ port=self.port_info.device,
38
+ baudrate=115200,
39
+ bytesize=_serial.EIGHTBITS,
40
+ parity=_serial.PARITY_NONE,
41
+ stopbits=_serial.STOPBITS_ONE,
42
+ timeout=timeout, # seconds
43
+ write_timeout=timeout, # seconds
44
+ )
45
+
46
+
47
+ if debug_uart:
48
+ logger.info("Debug UART is set. UART RX/TX will be printed to debug log")
49
+
50
+ logger.debug("Serial driver initialized with")
51
+ logger.debug("-- flush_on_write: '{}'".format(self.flush_on_write))
52
+ logger.debug("-- timeout: '{}'".format(timeout))
53
+
54
+ def __enter__(self):
55
+ self.open()
56
+ return self
57
+
58
+ def __exit__(self, exc_type, exc_value, traceback):
59
+ self.close()
60
+
61
+ def open(self):
62
+ if self.is_open():
63
+ if self.debug_uart:
64
+ logger.debug("Port is already open")
65
+ return
66
+ self.port.open()
67
+ self.port.reset_input_buffer()
68
+ self.port.reset_output_buffer()
69
+ if self.debug_uart:
70
+ logger.debug("Port open and buffers flushed")
71
+
72
+ def close(self):
73
+ if not self.is_open():
74
+ return
75
+ self.port.reset_input_buffer()
76
+ self.port.reset_output_buffer()
77
+ self.port.close()
78
+
79
+ def is_open(self):
80
+ return self.port.is_open
81
+
82
+ def assert_open(self):
83
+ if not self.is_open():
84
+ raise _serial.SerialException("Serial port must be open. port: \"{}\" description \"{}\"".format(self.port_info.name, self.description()))
85
+
86
+ def get_port_info(self):
87
+ return self.port_info
88
+
89
+ def description(self):
90
+ return self.port_info.description
91
+
92
+ def _find_port_by_name(self, port_info):
93
+ availablePorts = comports()
94
+ logger.debug(f"Searching for COM port `{port_info}`")
95
+ for port in availablePorts:
96
+ logger.debug(f"{port.device}")
97
+ logger.debug(f"\tProduct: {port.product}")
98
+ logger.debug(f"\tDesc: {port.description}")
99
+ logger.debug(f"\tSN: {port.serial_number}")
100
+ logger.debug(f"\tVID:{port.vid} PID:{port.pid}")
101
+ logger.debug(f"\tLocation: {port.location}")
102
+ logger.debug(f"\tInterface: {port.interface}")
103
+ if port.device == port_info:
104
+ logger.debug("Using '{}' as GaugeHub COM port".format(port.device))
105
+ return port
106
+ return None
107
+
108
+ def _read_until_re_match(self, status_re=None, timeout=2):
109
+ """
110
+ Read lines from serial until either a line containing status_re is found or timeout
111
+
112
+ @param status_re regex, the status message you're waiting for
113
+ @param timeout time to wait for respone
114
+ @return tuple with True|False success|failure and the all the lines receiverd up
115
+ to the line containing the status_re match. Never returns lines if no match is found
116
+ """
117
+ rx_lines = []
118
+
119
+ compiled_re = re.compile(status_re, flags=re.IGNORECASE)
120
+
121
+ timeout_timestmap = time.time() + timeout
122
+ while time.time() <= timeout_timestmap:
123
+ # Wait for new line
124
+ line = self.handle_serial_read()
125
+ if line:
126
+ if self.debug_uart:
127
+ logger.debug(f"_read_until_re_match:{line}")
128
+ rx_lines.append(line)
129
+ if compiled_re.match(line):
130
+ return True, rx_lines
131
+ return False, []
132
+
133
+ def wait_for_re_string(self, regexstr=r'', timeout=30, return_all=False):
134
+ status, lines = self._read_until_re_match(status_re=regexstr, timeout=timeout)
135
+ if status:
136
+ if return_all:
137
+ return lines
138
+ return True
139
+
140
+ if return_all:
141
+ return []
142
+ return False
143
+
144
+ def read_until_response(self, timeout=5):
145
+ rx_lines = []
146
+
147
+ timeout_timestmap = time.time() + timeout
148
+ while time.time() <= timeout_timestmap:
149
+ # Wait for new line
150
+ line = self.handle_serial_read()
151
+ if line:
152
+ if self.debug_uart:
153
+ logger.debug(line)
154
+ rx_lines.append(line)
155
+ if line.startswith('<'):
156
+ break
157
+ if time.time() > timeout_timestmap:
158
+ logger.error(f"Timeout occured ({time.time()} > {timeout_timestmap})")
159
+ break
160
+
161
+ return rx_lines
162
+
163
+ def handle_serial_send(self, command):
164
+ """
165
+ Basic implementations of serial write for the serial_transaction.
166
+ Sends the passed string, depending on the object settings, adds
167
+ a newline and/or flushes the in port before sending
168
+
169
+ @param command the command str
170
+ @return True if the command sent successfully
171
+ """
172
+ self.assert_open()
173
+ command = self.serialPrefix + command + self.serialSuffix
174
+
175
+ if self.flush_on_write and self.port.in_waiting > 0:
176
+ logger.error("Warning: In bytes waiting. Discarded. Port: \"{}\" description \"{}\"".format(self.port_info.name, self.description()))
177
+
178
+ if self.flush_on_write:
179
+ self.port.reset_input_buffer()
180
+
181
+ try:
182
+ if self.debug_uart:
183
+ logger.debug(f"Writting: '{command.encode()}'")
184
+ self.port.write(command.encode())
185
+ return True
186
+ except _serial.SerialTimeoutException:
187
+ logger.error("Warning: writing timed out. port: \"{}\" description \"{}\"".format(self.port_info.name, self.description()))
188
+ return False
189
+
190
+ def handle_serial_read(self):
191
+ """
192
+ Basic read implementation. Reads 1 line and decodes as utf-8
193
+
194
+ @return the response str, None if the read fails or times out
195
+ """
196
+ try:
197
+ response = self.port.readline()
198
+ try:
199
+ ret = response.decode("utf-8").strip()
200
+ except Exception as e:
201
+ logger.error(e)
202
+ ret = ""
203
+ return ret
204
+ except _serial.SerialTimeoutException:
205
+ logger.error("Warning: reading response timed out. port: \"{}\" description \"{}\"".format(self.port_info.name, self.description()))
206
+ return None
207
+
208
+ return None
209
+
210
+ def serial_transaction(self, payload, ignore_response=False):
211
+ """
212
+ Wrapper to send a str payload to the serial port and get a response.
213
+ Acquires the lock and asserts that the port is open and then calls the handle_serial_send
214
+ If verify_response is set it reads until the response_re or default status_re is hit and return all lines up to that point or timeout
215
+ Otherwise returns a single line from handle_serial_read
216
+ handle_serial_read and handle_serial_send have default implementations that can be overridden
217
+
218
+ @param payload the string serial payload passed to handle_serial_send
219
+ @ignore_response don't read any response
220
+ @return the result from the handle_serial_read sub payload
221
+ """
222
+ lines = []
223
+ try:
224
+ self.lock.acquire()
225
+ self.assert_open()
226
+
227
+ if not isinstance(payload, str) and not isinstance(payload, bytes) and not isinstance(payload, bytearray):
228
+ raise TypeError("Serial_transaction expects str/bytes/bytearray")
229
+
230
+ # Check if any messages were received
231
+ while self.port.in_waiting:
232
+ lines.append(self.handle_serial_read())
233
+
234
+ if not self.handle_serial_send(payload):
235
+ raise _serial.SerialException("Failed to send {}".format(payload))
236
+
237
+ if not ignore_response:
238
+ rx_lines = self.read_until_response()
239
+
240
+ lines = rx_lines + lines
241
+
242
+ return lines
243
+ finally:
244
+ self.lock.release()