micrOSDevToolKit 2.9.8__py3-none-any.whl → 2.9.11__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.

Potentially problematic release.


This version of micrOSDevToolKit might be problematic. Click here for more details.

Files changed (59) hide show
  1. micrOS/release_info/micrOS_ReleaseInfo/system_analysis_sum.json +21 -21
  2. micrOS/source/LM_espnow.py +27 -1
  3. micrOS/source/LM_oled_ui.py +1 -1
  4. micrOS/source/LM_system.py +4 -4
  5. micrOS/source/Notify.py +4 -0
  6. micrOS/source/Server.py +1 -1
  7. micrOS/source/Shell.py +3 -3
  8. micrOS/source/Tasks.py +1 -1
  9. micrOS/source/Time.py +7 -8
  10. micrOS/source/__pycache__/Common.cpython-312.pyc +0 -0
  11. micrOS/source/__pycache__/Logger.cpython-312.pyc +0 -0
  12. micrOS/source/__pycache__/Server.cpython-312.pyc +0 -0
  13. micrOS/source/micrOSloader.py +0 -1
  14. micrOS/source/urequests.py +14 -7
  15. {micrOSDevToolKit-2.9.8.data → micrOSDevToolKit-2.9.11.data}/scripts/devToolKit.py +10 -0
  16. {micrOSDevToolKit-2.9.8.dist-info → micrOSDevToolKit-2.9.11.dist-info}/METADATA +66 -21
  17. {micrOSDevToolKit-2.9.8.dist-info → micrOSDevToolKit-2.9.11.dist-info}/RECORD +57 -50
  18. {micrOSDevToolKit-2.9.8.dist-info → micrOSDevToolKit-2.9.11.dist-info}/WHEEL +1 -1
  19. toolkit/DevEnvOTA.py +13 -9
  20. toolkit/DevEnvUSB.py +6 -5
  21. toolkit/MicrOSDevEnv.py +19 -5
  22. toolkit/WebRepl.py +73 -0
  23. toolkit/dashboard_apps/BackupRestore.py +20 -35
  24. toolkit/dashboard_apps/CCTDemo.py +12 -17
  25. toolkit/dashboard_apps/CCTTest.py +20 -24
  26. toolkit/dashboard_apps/CamStream.py +2 -6
  27. toolkit/dashboard_apps/CatGame.py +14 -16
  28. toolkit/dashboard_apps/Dimmer.py +11 -21
  29. toolkit/dashboard_apps/GetVersion.py +11 -19
  30. toolkit/dashboard_apps/MicrophoneTest.py +1 -6
  31. toolkit/dashboard_apps/NeoEffectsDemo.py +28 -34
  32. toolkit/dashboard_apps/NeopixelTest.py +20 -25
  33. toolkit/dashboard_apps/PresenceTest.py +2 -8
  34. toolkit/dashboard_apps/RGBTest.py +20 -24
  35. toolkit/dashboard_apps/RoboArm.py +24 -32
  36. toolkit/dashboard_apps/SED_test.py +10 -14
  37. toolkit/dashboard_apps/SensorsTest.py +61 -0
  38. toolkit/dashboard_apps/SystemTest.py +151 -77
  39. toolkit/dashboard_apps/Template_app.py +11 -23
  40. toolkit/dashboard_apps/_app_base.py +34 -0
  41. toolkit/dashboard_apps/uLightDemo.py +15 -24
  42. toolkit/lib/Repository.py +64 -0
  43. toolkit/lib/micrOSClient.py +16 -11
  44. toolkit/micrOSlint.py +3 -3
  45. toolkit/simulator_lib/__pycache__/aioespnow.cpython-312.pyc +0 -0
  46. toolkit/simulator_lib/aioespnow.py +28 -0
  47. toolkit/socketClient.py +0 -1
  48. toolkit/workspace/precompiled/LM_espnow.py +27 -1
  49. toolkit/workspace/precompiled/LM_oled_ui.mpy +0 -0
  50. toolkit/workspace/precompiled/LM_system.mpy +0 -0
  51. toolkit/workspace/precompiled/Notify.mpy +0 -0
  52. toolkit/workspace/precompiled/Shell.mpy +0 -0
  53. toolkit/workspace/precompiled/Time.mpy +0 -0
  54. toolkit/workspace/precompiled/micrOSloader.mpy +0 -0
  55. toolkit/workspace/precompiled/urequests.mpy +0 -0
  56. toolkit/dashboard_apps/AirQualityBME280.py +0 -36
  57. toolkit/dashboard_apps/AirQualityDHT22_CO2.py +0 -36
  58. {micrOSDevToolKit-2.9.8.dist-info → micrOSDevToolKit-2.9.11.dist-info}/LICENSE +0 -0
  59. {micrOSDevToolKit-2.9.8.dist-info → micrOSDevToolKit-2.9.11.dist-info}/top_level.txt +0 -0
@@ -5,34 +5,79 @@ import sys
5
5
  import time
6
6
  import socket
7
7
  import ast
8
+ from pprint import pprint
9
+ try:
10
+ from ._app_base import AppBase
11
+ except:
12
+ from _app_base import AppBase
13
+
8
14
  MYPATH = os.path.dirname(os.path.abspath(__file__))
9
- sys.path.append(os.path.dirname(MYPATH))
10
- import socketClient
15
+ REPORT_OUTPUT_PATH = os.path.join(MYPATH, '../../micrOS/release_info/micrOS_ReleaseInfo/devices_system_metrics.json')
11
16
  sys.path.append(os.path.join(MYPATH, '../lib/'))
12
17
  from TerminalColors import Colors
13
18
  import requests
14
19
 
15
- # FILL OUT
16
- DEVICE = '__simulator__'
17
- PASSWD = None
20
+ CLIENT = None
18
21
  TIMEOUT_SEC = 5
19
22
 
20
-
21
- def base_cmd():
22
- if PASSWD is None:
23
- return ['--dev', DEVICE]
24
- return ['--dev', DEVICE, '--password', PASSWD]
25
-
26
-
27
- def get_device():
28
- return DEVICE
29
-
23
+ # COLLECT AND SAVE SYSTEM TEST METRICS
24
+ ENABLE_DATA_COLLECTION = os.environ.get("ENABLE_DATA_COLLECTION", False)
25
+ REPORT_DICT = {}
26
+ METRICS = {}
27
+
28
+ #####################################
29
+ # METRICS #
30
+ #####################################
31
+ def load_reports():
32
+ global REPORT_DICT
33
+ previous_reports = {}
34
+ try:
35
+ with open(REPORT_OUTPUT_PATH, 'r') as f:
36
+ previous_reports = json.loads(f.read())
37
+ except FileNotFoundError:
38
+ pass
39
+ finally:
40
+ REPORT_DICT = previous_reports
41
+
42
+ def create_report(device_name:str, metrics:dict) -> None:
43
+ global REPORT_DICT
44
+
45
+ if not ENABLE_DATA_COLLECTION:
46
+ print(f"[SKIP] system test metrics export, ENABLE_DATA_COLLECTION={ENABLE_DATA_COLLECTION}")
47
+ pprint(metrics)
48
+ return
49
+ load_reports()
50
+ version = metrics.get('version')
51
+ device_type = metrics.get('board_type')
52
+ device_type = '???' if device_type is None else device_type.split()[-1]
53
+ if REPORT_DICT.get(version) is None:
54
+ REPORT_DICT[version] = {}
55
+ if REPORT_DICT.get(version).get(device_type) is None:
56
+ REPORT_DICT[version][device_type] = {}
57
+ REPORT_DICT[version][device_type][device_name] = metrics
58
+ # Cleanup - remove redundant elements
59
+ REPORT_DICT[version][device_type][device_name].pop("board_type", None)
60
+ REPORT_DICT[version][device_type][device_name].pop("version", None)
61
+ # Dump report
62
+ print(f"Save system test report: {REPORT_OUTPUT_PATH}")
63
+ pprint(metrics)
64
+ with open(REPORT_OUTPUT_PATH, 'w') as f:
65
+ f.write(json.dumps(REPORT_DICT, indent=4))
66
+
67
+
68
+ def _add_metrics(key:str, value):
69
+ global METRICS
70
+ METRICS[key] = value
71
+
72
+ #####################################
73
+ # TESTS #
74
+ #####################################
30
75
 
31
76
  def single_cmd_exec_check():
32
77
  info = "[ST] Run single command execution check [hello]"
33
78
  print(info)
34
79
  cmd_list = ['hello']
35
- output = execute(cmd_list)
80
+ output = CLIENT.execute(cmd_list)
36
81
  if output[0]:
37
82
  if output[1].startswith("hello:"):
38
83
  return True, info
@@ -42,17 +87,18 @@ def shell_cmds_check():
42
87
  info = "[ST] Run built-in shell commands [modules|version|help]"
43
88
  print(info)
44
89
  cmd_list = ['modules']
45
- output = execute(cmd_list)
90
+ output = CLIENT.execute(cmd_list)
46
91
  if output[0]:
92
+ _add_metrics("modules", ast.literal_eval(output[1]))
47
93
  if not (output[1].startswith("[") and output[1].endswith("]")):
48
94
  return False, f"{info}modules: {output[1]}"
49
95
  cmd_list = ['version']
50
- output = execute(cmd_list)
96
+ output = CLIENT.execute(cmd_list)
51
97
  if output[0]:
52
98
  if not ('.' in output[1] and '-' in output[1]):
53
99
  return False, f"{info}version: {output[1]}"
54
100
  cmd_list = ['help']
55
- output = execute(cmd_list)
101
+ output = CLIENT.execute(cmd_list)
56
102
  if output[0]:
57
103
  if not ('[MICROS]' in output[1] and '[CONF]' in output[1] and '[TASK]' in output[1] and '[EXEC]' in output[1]):
58
104
  return False, f"{info}help: {output[1]}"
@@ -63,7 +109,7 @@ def lm_cmd_exec_check():
63
109
  info = "[ST] Run Load Module command execution check [system heartbeat]"
64
110
  print(info)
65
111
  cmd_list = ['system heartbeat']
66
- output = execute(cmd_list)
112
+ output = CLIENT.execute(cmd_list)
67
113
  if output[0]:
68
114
  if output[1].strip() == '<3 heartbeat <3':
69
115
  return True, info
@@ -74,7 +120,7 @@ def micrOS_config_get():
74
120
  info = "[ST] Run micrOS config get [conf -> socport]"
75
121
  print(info)
76
122
  cmd_list = ['config <a> socport']
77
- output = execute(cmd_list)
123
+ output = CLIENT.execute(cmd_list)
78
124
  if output[0]:
79
125
  if output[1].strip() == '9008':
80
126
  return True, info
@@ -88,7 +134,7 @@ def micrOS_config_set():
88
134
 
89
135
  # [1] Get actual utc value
90
136
  cmd_list = ['config <a> utc']
91
- output = execute(cmd_list)
137
+ output = CLIENT.execute(cmd_list)
92
138
  if output[0]:
93
139
  try:
94
140
  utc_bak = int(output[1].strip())
@@ -98,21 +144,21 @@ def micrOS_config_set():
98
144
  # [2] Set x+1 value as expected
99
145
  utc_expected = utc_bak+1
100
146
  cmd_list = ['config <a> utc {}'.format(utc_expected)]
101
- output = execute(cmd_list)
147
+ output = CLIENT.execute(cmd_list)
102
148
  if output[0]:
103
149
  if output[1].strip() != 'Saved':
104
150
  return False, f"{info} + utc overwrite issue: {output[1]}"
105
151
 
106
152
  # [3] Get modified utc value - veridy [2] step
107
153
  cmd_list = ['config <a> utc']
108
- output = execute(cmd_list)
154
+ output = CLIENT.execute(cmd_list)
109
155
  if output[0]:
110
156
  if int(output[1].strip()) != utc_expected:
111
157
  return False, f"{info} + utc modified value error: {output[1]} != {utc_expected}"
112
158
 
113
159
  # Restore original value
114
160
  cmd_list = ['config <a> utc {}'.format(utc_bak)]
115
- output = execute(cmd_list)
161
+ output = CLIENT.execute(cmd_list)
116
162
  if output[0]:
117
163
  if output[1].strip() != 'Saved':
118
164
  return False, f"{info} + utc overwrite issue: {output[1]}"
@@ -126,11 +172,11 @@ def micrOS_bgjob_one_shot_check():
126
172
  print(info)
127
173
 
128
174
  # Initial task cleanup...
129
- execute(['task kill system.clock'])
175
+ CLIENT.execute(['task kill system.clock'])
130
176
 
131
177
  for _ in range(0, 2):
132
178
  cmd_list = ['system clock &']
133
- output = execute(cmd_list)
179
+ output = CLIENT.execute(cmd_list)
134
180
  time.sleep(1)
135
181
  if output[0]:
136
182
  if 'Start system.clock' not in output[1].strip():
@@ -144,14 +190,14 @@ def micrOS_bgjob_loop_check():
144
190
 
145
191
  # Start background task loop
146
192
  cmd_list = ['system clock &&']
147
- output = execute(cmd_list)
193
+ output = CLIENT.execute(cmd_list)
148
194
  if output[0]:
149
195
  if 'Start system.clock' not in output[1].strip():
150
196
  return False, f'[Start Task error] {info} + not expected return: {output[1]}'
151
197
 
152
198
  # Attempt to overload background thread
153
199
  cmd_list = ['system clock &&']
154
- output = execute(cmd_list)
200
+ output = CLIENT.execute(cmd_list)
155
201
  if output[0]:
156
202
  if 'system.clock is Busy' not in output[1].strip():
157
203
  return False, f'[Overload task - run same] {info} + not expected return: {output[1]}'
@@ -159,14 +205,14 @@ def micrOS_bgjob_loop_check():
159
205
  # Show task output by task tag
160
206
  time.sleep(0.1) # Give time for the task to start and update buffer... (sim)
161
207
  cmd_list = ['task show system.clock']
162
- output = execute(cmd_list)
208
+ output = CLIENT.execute(cmd_list)
163
209
  if output[0]:
164
210
  if "No task found" in output[1].strip() or len(output[1].strip()) == 0:
165
211
  return False, f'[No task output] {info} + not expected return: {output[1]}'
166
212
 
167
213
  # Stop BgJob
168
214
  cmd_list = ['task kill system.clock']
169
- output = execute(cmd_list)
215
+ output = CLIENT.execute(cmd_list)
170
216
  if output[0]:
171
217
  if 'Kill:' in output[1].strip() or 'system.clock' in output[1].strip():
172
218
  return True, f'[Stop task] {info}'
@@ -179,7 +225,7 @@ def micrOS_task_list_check():
179
225
  print(info)
180
226
 
181
227
  async_available_cmd_list = ['task list']
182
- output = execute(async_available_cmd_list)
228
+ output = CLIENT.execute(async_available_cmd_list)
183
229
  if output[0]:
184
230
  if "---- micrOS top ----" not in output[1]:
185
231
  return False, f"{info} - ERROR: missing response prefix {output[1]}"
@@ -187,7 +233,7 @@ def micrOS_task_list_check():
187
233
  return False, f"{info} - task list error: {output[1]}"
188
234
 
189
235
  async_available_cmd_list = ['task list >json']
190
- output = execute(async_available_cmd_list)
236
+ output = CLIENT.execute(async_available_cmd_list)
191
237
  if output[0]:
192
238
  starts = '{'
193
239
  ends = '}'
@@ -201,10 +247,11 @@ def micrOS_get_version():
201
247
  info = "[ST] Run micrOS get version [version]"
202
248
  print(info)
203
249
  cmd_list = ['version']
204
- output = execute(cmd_list)
250
+ output = CLIENT.execute(cmd_list)
205
251
  if output[0]:
206
252
  if '.' in output[1].strip() and '-' in output[1].strip():
207
253
  return True, f"{info} v:{output[1].strip()}"
254
+ _add_metrics('version', output[1])
208
255
  return False, f"{info} out: {output[1]}"
209
256
 
210
257
 
@@ -212,7 +259,7 @@ def json_format_check():
212
259
  info = "[ST] Run micrOS raw output check aka >json [system rssi >json]"
213
260
  print(info)
214
261
  cmd_list = ['system rssi >json']
215
- output = execute(cmd_list)
262
+ output = CLIENT.execute(cmd_list)
216
263
  if output[0] and output[1].startswith("{") and output[1].endswith("}"):
217
264
  return True, info + f" out: {output[1]}"
218
265
  return False, info + f" out: {output[1]}"
@@ -223,25 +270,25 @@ def negative_interface_check():
223
270
  print(info)
224
271
 
225
272
  cmd_list = ['Apple']
226
- output = execute(cmd_list)
273
+ output = CLIENT.execute(cmd_list)
227
274
  if output[0]:
228
275
  if 'Shell: for hints type help.' not in output[1].strip():
229
276
  return False, f'[Wrong single command] {info} + not expected return: {output[1]}'
230
277
 
231
278
  cmd_list = ['Apple test']
232
- output = execute(cmd_list)
279
+ output = CLIENT.execute(cmd_list)
233
280
  if output[0]:
234
281
  if 'no module named' not in output[1].strip().lower():
235
282
  return False, f'[Missing module] {info} + not expected return: {output[1]}'
236
283
 
237
284
  cmd_list = ['conf', 'gmttimaaaa']
238
- output = execute(cmd_list)
285
+ output = CLIENT.execute(cmd_list)
239
286
  if output[0]:
240
287
  if output[1].strip() != 'None':
241
288
  return False, f'[Config invalid key] {info} + not expected return: {output[1]}'
242
289
 
243
290
  cmd_list = ['conf', 'utc "type"']
244
- output = execute(cmd_list)
291
+ output = CLIENT.execute(cmd_list)
245
292
  if output[0]:
246
293
  if output[1].strip() != 'Failed to save':
247
294
  return False, f'[Config invalid key type] {info} + not expected return: {output[1]}'
@@ -265,11 +312,12 @@ def measure_package_response_time():
265
312
  # Start time
266
313
  start = time.time()
267
314
  # Command exec
268
- output = execute(cmd_list)
315
+ output = CLIENT.execute(cmd_list)
269
316
  # Stop time
270
317
  end = time.time() - start
271
318
  # Get average response time
272
319
  delta_cmd_rep_time = round(end/10, 4)
320
+ _add_metrics('shell_heartbeatX10_response_ms', int(delta_cmd_rep_time*1000))
273
321
  # Create verdict
274
322
  print(output)
275
323
  if output[0] and "<3 heartbeat <3" in output[1]:
@@ -281,7 +329,7 @@ def micros_alarm_check():
281
329
  info = "[ST] Test alarm state - system alarms should be null"
282
330
  print(info)
283
331
  cmd_list = ['system alarms']
284
- output = execute(cmd_list)
332
+ output = CLIENT.execute(cmd_list)
285
333
  alarm_cnt = 0
286
334
  if output[0]:
287
335
  try:
@@ -292,7 +340,7 @@ def micros_alarm_check():
292
340
  print(e)
293
341
  # Clean alarms
294
342
  cmd_list = ['system alarms True']
295
- execute(cmd_list)
343
+ CLIENT.execute(cmd_list)
296
344
  # Evaluation
297
345
  if alarm_cnt > 0:
298
346
  return True, info + f" -1 !!!WARN!!! [{alarm_cnt}] out: {output[1]}"
@@ -301,10 +349,10 @@ def micros_alarm_check():
301
349
 
302
350
  def oled_msg_end_result(result):
303
351
  cmd_list = ['pacman moduls >json']
304
- output = execute(cmd_list)
352
+ output = CLIENT.execute(cmd_list)
305
353
  if output[0] and 'LM_oled_ui' in output[1]:
306
354
  cmd_list = [f'oled_ui msgbox "{result} %"']
307
- print(execute(cmd_list))
355
+ print(CLIENT.execute(cmd_list))
308
356
 
309
357
 
310
358
  def check_device_by_hostname(dev):
@@ -325,7 +373,7 @@ def check_robustness_exception():
325
373
  info_msg = '[ST] Check robustness - exception [robustness raise_error]'
326
374
  print(info_msg)
327
375
  cmd_list = ['robustness raise_error']
328
- output = execute(cmd_list)
376
+ output = CLIENT.execute(cmd_list)
329
377
  if output[0] and "Core error: LM_robustness->raise_error: Test exception" in output[1]:
330
378
  return True, f'{info_msg}: Valid error msg: exec_lm_core *->raise_error: *'
331
379
  else:
@@ -336,7 +384,7 @@ def check_robustness_memory():
336
384
  info_msg = '[ST] Check robustness - memory_leak [robustness memory_leak 12]'
337
385
  print(info_msg)
338
386
  cmd_list = ['robustness memory_leak 12']
339
- output = execute(cmd_list)
387
+ output = CLIENT.execute(cmd_list)
340
388
  if output[0] and "[12] RAM Alloc" in output[1]:
341
389
  end_result = output[1].split("\n")[-1]
342
390
  return True, f'{info_msg}: Mem alloc: {end_result}'
@@ -348,7 +396,7 @@ def check_robustness_recursion():
348
396
  info_msg = '[ST] Check robustness - recursion [robustness recursion_limit 8]'
349
397
  print(info_msg)
350
398
  cmd_list = ['robustness recursion_limit 8']
351
- output = execute(cmd_list, tout=10)
399
+ output = CLIENT.execute(cmd_list, tout=10)
352
400
  if output[0]:
353
401
  last_line = output[1].split("\n")[-1]
354
402
  if "Recursion limit:" in last_line:
@@ -372,7 +420,7 @@ def check_intercon(host=None):
372
420
  _output = None
373
421
  for _ in range(0, 2):
374
422
  time.sleep(1)
375
- _output = execute(_cmd_list, tout=8)
423
+ _output = CLIENT.execute(_cmd_list, tout=8)
376
424
  if _output[0] and 'No task found:' not in _output[1]:
377
425
  _state = True
378
426
  break
@@ -382,7 +430,7 @@ def check_intercon(host=None):
382
430
  print(info_msg)
383
431
  host = 'test.local' if host is None else host
384
432
  cmd_list = ['intercon sendcmd "{}" "hello" >json'.format(host)]
385
- output = execute(cmd_list, tout=8)
433
+ output = CLIENT.execute(cmd_list, tout=8)
386
434
  output = _convert_return_to_dict(output)
387
435
  device_was_found = False
388
436
  if output[0] is False or output[1] is None:
@@ -404,7 +452,7 @@ def check_intercon(host=None):
404
452
  if device_was_found:
405
453
  # DO Negative testing as well
406
454
  cmd_list = ['intercon sendcmd "notavailable.local" "hello" >json']
407
- output_neg = execute(cmd_list, tout=15)
455
+ output_neg = CLIENT.execute(cmd_list, tout=15)
408
456
  output_neg = _convert_return_to_dict(output_neg)
409
457
  state_neg = False, output_neg
410
458
  if len(output_neg[1]) > 1 and "hello" in output_neg[1]['verdict']:
@@ -417,9 +465,11 @@ def check_intercon(host=None):
417
465
 
418
466
  def measure_conn_metrics():
419
467
  try:
420
- verdict = socketClient.connection_metrics(f"{get_device().strip()}.local")
468
+ verdict, delta_t_single, delta_t_multi = CLIENT.connection_metrics()
469
+ _add_metrics("shell_single_session_dt_ms", int(delta_t_single*1000))
470
+ _add_metrics("shell_multi_session_dt_ms", int(delta_t_multi*1000))
421
471
  for k in verdict:
422
- print("\t\t{}".format(k))
472
+ print(f"\t\t{k}")
423
473
  state = True if len(verdict) > 0 else False
424
474
  except Exception as e:
425
475
  state = False
@@ -429,7 +479,7 @@ def measure_conn_metrics():
429
479
 
430
480
  def memory_usage():
431
481
  cmd = ['system memory_usage >json']
432
- out = execute(cmd, tout=TIMEOUT_SEC)
482
+ out = CLIENT.execute(cmd, tout=TIMEOUT_SEC)
433
483
  state, raw_output = out[0], out[1]
434
484
  try:
435
485
  json_out = json.loads(raw_output)
@@ -437,6 +487,8 @@ def memory_usage():
437
487
  return False, '[ST] {}ERR{}: {}: {}'.format(Colors.ERR, Colors.NC, raw_output, e)
438
488
 
439
489
  # {"percent": 93.11, "mem_used": 103504}
490
+ _add_metrics('mem_percent', json_out.get('percent'))
491
+ _add_metrics('mem_used_byte', json_out.get('mem_used'))
440
492
  if json_out.get('percent') > 70: # MEM USAGE WARNING INDICATOR: 80%
441
493
  return state, '[ST] {}WARNING{}: memory usage {}% ({} bytes)'.format(Colors.WARN, Colors.NC,
442
494
  json_out.get('percent'),
@@ -450,7 +502,7 @@ def disk_usage():
450
502
  Check disk usage - manually defined 16% (336_000 byte) - check degradations...
451
503
  """
452
504
  cmd = ['system disk_usage >json']
453
- out = execute(cmd, tout=TIMEOUT_SEC)
505
+ out = CLIENT.execute(cmd, tout=TIMEOUT_SEC)
454
506
  state, raw_output = out[0], out[1]
455
507
  try:
456
508
  json_out = json.loads(raw_output)
@@ -458,6 +510,8 @@ def disk_usage():
458
510
  return False, '[ST] {}ERR{}: {}: {}'.format(Colors.ERR, Colors.NC, raw_output, e)
459
511
 
460
512
  # {"percent": 15.4, "fs_used": 323_584}
513
+ _add_metrics('fs_percent', json_out.get('percent'))
514
+ _add_metrics('fs_used_byte', json_out.get('fs_used'))
461
515
  if json_out.get('fs_used') > 700_000: # MEM USAGE WARNING INDICATOR: 700_000 bytes (700kb)
462
516
  return state, '[ST] {}WARNING{}: disk usage {}% ({} bytes)'.format(Colors.WARN, Colors.NC,
463
517
  json_out.get('percent'),
@@ -468,7 +522,7 @@ def disk_usage():
468
522
 
469
523
  def task_list():
470
524
  cmd = ['task list']
471
- out = execute(cmd, tout=TIMEOUT_SEC)
525
+ out = CLIENT.execute(cmd, tout=TIMEOUT_SEC)
472
526
  state, output = out[0], out[1]
473
527
  if state:
474
528
  return state, output.replace('\n', f'\n{" "*51}') # TODO format output
@@ -478,12 +532,12 @@ def task_list():
478
532
  def webcli_test():
479
533
  endpoints = []
480
534
  cmd = ['conf', 'webui']
481
- out = execute(cmd, tout=TIMEOUT_SEC)
535
+ out = CLIENT.execute(cmd, tout=TIMEOUT_SEC)
482
536
  state, output = out[0], out[1]
483
537
  if state:
484
538
  verdict = f"[ST] WEBUI IS ENABLED ({output})" if output.strip() == 'True' else f"[ST] WEBUI IS DISABLED ({output})"
485
539
  if output.strip() == 'True':
486
- out = execute(['conf', 'devip'], tout=TIMEOUT_SEC)
540
+ out = CLIENT.execute(['conf', 'devip'], tout=TIMEOUT_SEC)
487
541
  if out[0] and out[1] is not None:
488
542
  devip = out[1]
489
543
  endpoints.append(f'http://{devip}')
@@ -491,27 +545,35 @@ def webcli_test():
491
545
 
492
546
  for endpoint in endpoints:
493
547
  _start_t = time.time()
548
+ delta_t = -1
494
549
  try:
495
550
  response = requests.get(endpoint, timeout=5)
551
+ delta_t = round(time.time() - _start_t, 2)
496
552
  # Check if the request was successful
497
553
  if not (response.status_code == 200 and ('<!DOCTYPE html>' in str(response.content) or '"micrOS"' in str(response.content))):
498
- verdict += f" Endpoint: {endpoint} [{Colors.ERR}NOK{Colors.NC}]({round(time.time()-_start_t, 2)}s)"
554
+ verdict += f" Endpoint: {endpoint} [{Colors.ERR}NOK{Colors.NC}]({delta_t}s)"
499
555
  print(response.content)
500
556
  state = False
501
557
  else:
502
- verdict += f" Endpoint: {endpoint} [{Colors.OK}OK{Colors.NC}]({round(time.time()-_start_t, 2)}s)"
558
+ verdict += f" Endpoint: {endpoint} [{Colors.OK}OK{Colors.NC}]({delta_t}s)"
559
+
560
+ metrics_name = 'landingpage' if "." in endpoint.split('/')[-1] else endpoint.split('/')[-1]
561
+ _add_metrics(f"web_{metrics_name}_response_ms", int(delta_t*1000))
503
562
  except Exception as e:
504
- verdict += f" Endpoint: {endpoint} [{Colors.ERR}NOK{Colors.NC}]({round(time.time()-_start_t, 2)}s)"
563
+ verdict += f" Endpoint: {endpoint} [{Colors.ERR}NOK{Colors.NC}]({delta_t}s)"
505
564
  print(f"webcli_test error: {e}")
506
565
  state = False
507
566
  return state, verdict
508
567
  return state, output
509
568
 
569
+ #####################################
570
+ # HELPERS #
571
+ #####################################
510
572
 
511
573
  def after_st_reboot():
512
574
  verdict = False, 'reboot -h failed'
513
575
  cmd = ['reboot -h']
514
- out = execute(cmd, tout=TIMEOUT_SEC)
576
+ out = CLIENT.execute(cmd, tout=TIMEOUT_SEC)
515
577
  state, output = out[0], out[1]
516
578
  if state:
517
579
  verdict = state, f'[reboot-h] commad out: {output}'
@@ -519,7 +581,7 @@ def after_st_reboot():
519
581
  print(f"[reboot-h] Wait for node up again ({retry}/{retry*2}sec)")
520
582
  time.sleep(2)
521
583
  try:
522
- up, o = execute(['hello'], tout=TIMEOUT_SEC)
584
+ up, o = CLIENT.execute(['hello'], tout=TIMEOUT_SEC)
523
585
  if up:
524
586
  verdict = True, f"[reboot-h][OK] successfully rebooted: {o} (boot time: ~{retry * 2}sec)"
525
587
  print(verdict[1])
@@ -532,19 +594,37 @@ def after_st_reboot():
532
594
 
533
595
  def get_dev_version():
534
596
  cmd = ['version']
535
- out = execute(cmd, tout=TIMEOUT_SEC)
597
+ out = CLIENT.execute(cmd, tout=TIMEOUT_SEC)
536
598
  state, output = out[0], out[1]
599
+ _add_metrics("version", output)
537
600
  if state:
538
601
  return output
539
602
  return '0.0.0-0'
540
603
 
604
+ def get_dev_board_type():
605
+ cmd = ['system info >json']
606
+ out = CLIENT.execute(cmd, tout=TIMEOUT_SEC)
607
+ state, output = out[0], out[1]
608
+ output = ast.literal_eval(output)
609
+ board = output.get("board")
610
+ upython = output.get("upython")
611
+ _add_metrics("board_type", board)
612
+ _add_metrics("micropython_version", str(upython))
613
+ if state:
614
+ return board, upython
615
+ return None, None
616
+
617
+ #####################################
618
+ # MAIN APP #
619
+ #####################################
620
+
541
621
  def app(devfid=None, pwd=None):
542
- global DEVICE, PASSWD
543
- if devfid is not None:
544
- DEVICE = devfid
545
- if pwd is not None:
546
- PASSWD = pwd
622
+ global CLIENT
623
+ CLIENT = AppBase(device=devfid, password=pwd)
547
624
 
625
+ # Get device info
626
+ version = get_dev_version()
627
+ get_dev_board_type() # update metrics
548
628
  # Get test verdict
549
629
  verdict = {'single_cmds': single_cmd_exec_check(),
550
630
  'shell_cmds': shell_cmds_check(),
@@ -558,7 +638,7 @@ def app(devfid=None, pwd=None):
558
638
  'json_check': json_format_check(),
559
639
  'response_time': measure_package_response_time(),
560
640
  'negative_api': negative_interface_check(),
561
- 'dhcp_hostname': check_device_by_hostname(DEVICE),
641
+ 'dhcp_hostname': check_device_by_hostname(CLIENT.get_device()),
562
642
  'lm_exception': check_robustness_exception(),
563
643
  'mem_usage': memory_usage(),
564
644
  'disk_usage': disk_usage(),
@@ -575,8 +655,8 @@ def app(devfid=None, pwd=None):
575
655
  # Test Evaluation
576
656
  final_state = True
577
657
  ok_cnt = 0
578
- version = get_dev_version()
579
- print(f"\n----------------------------------- micrOS System Test results on {DEVICE}:{version} device -----------------------------------")
658
+ create_report(CLIENT.get_device(), METRICS)
659
+ print(f"\n----------------------------------- micrOS System Test results on {CLIENT.get_device()}:{version} device -----------------------------------")
580
660
  print("\tTEST NAME\t\tSTATE\t\tDescription\n")
581
661
  for test, state_data in verdict.items():
582
662
  state = Colors.ERR + 'NOK' + Colors.NC
@@ -596,11 +676,5 @@ def app(devfid=None, pwd=None):
596
676
  oled_msg_end_result(f"System[{state}] {pass_rate}")
597
677
 
598
678
 
599
- def execute(cmd_list, tout=5):
600
- cmd_args = base_cmd() + cmd_list
601
- print("[ST] test cmd: {}".format(cmd_args))
602
- return socketClient.run(cmd_args, timeout=tout)
603
-
604
-
605
679
  if __name__ == "__main__":
606
680
  app()
@@ -2,28 +2,16 @@
2
2
 
3
3
  import os
4
4
  import sys
5
- import time
6
5
  MYPATH = os.path.dirname(os.path.abspath(__file__))
7
- sys.path.append(os.path.dirname(MYPATH))
8
- import socketClient
9
6
  sys.path.append(os.path.join(MYPATH, '../lib/'))
10
7
  from TerminalColors import Colors
11
8
 
12
- # FILL OUT
13
- DEVICE = 'node01'
14
- PASSWD = None
15
-
16
- def base_cmd():
17
- if PASSWD is None:
18
- return ['--dev', DEVICE]
19
- return ['--dev', DEVICE, '--password', PASSWD]
20
-
21
- def run_command(cmd):
22
- # EDIT YOUR COMMAND
23
- args = base_cmd() + cmd
24
- status, answer = socketClient.run(args)
25
- return status, answer
9
+ try:
10
+ from ._app_base import AppBase
11
+ except:
12
+ from _app_base import AppBase
26
13
 
14
+ CLIENT = None
27
15
 
28
16
  def app(devfid=None, pwd=None):
29
17
  """
@@ -31,13 +19,13 @@ def app(devfid=None, pwd=None):
31
19
  send command(s) over socket connection [socketClient.run(args)]
32
20
  list load module commands and send in single connection
33
21
  """
34
- global DEVICE, PASSWD
35
- if devfid is not None:
36
- DEVICE = devfid
37
- if pwd is not None:
38
- PASSWD = pwd
22
+ global CLIENT
23
+ CLIENT = AppBase(device=devfid, password=pwd)
39
24
 
40
- status, answer = run_command(['help', 'version'])
25
+ output = CLIENT.execute(['help', 'version'])
26
+ status = output[0]
27
+ result = output[1]
28
+ print(f"{Colors.WARN}[{status}]{Colors.NC} {result}")
41
29
 
42
30
 
43
31
  if __name__ == "__main__":
@@ -0,0 +1,34 @@
1
+ #####################################
2
+ # APP CONFIG #
3
+ #####################################
4
+ import os, sys
5
+ MYPATH = os.path.dirname(os.path.abspath(__file__))
6
+ sys.path.append(os.path.dirname(MYPATH))
7
+ import socketClient
8
+
9
+ class AppBase:
10
+
11
+ def __init__(self, device:str, password:str):
12
+ self.device = device
13
+ self.password = password
14
+
15
+ def base_cmd(self) -> list:
16
+ if self.password is None:
17
+ return ['--dev', self.device]
18
+ return ['--dev', self.device, '--password', self.password]
19
+
20
+ def get_device(self):
21
+ return self.device
22
+
23
+ def execute(self, cmd_list, tout=5):
24
+ cmd_args = self.base_cmd() + cmd_list
25
+ print(f"Execute: {cmd_args}")
26
+ return socketClient.run(cmd_args, timeout=tout)
27
+
28
+ def run(self, cmd_list):
29
+ """Legacy"""
30
+ out = self.execute(cmd_list)
31
+ return out[0], out[1]
32
+
33
+ def connection_metrics(self):
34
+ return socketClient.connection_metrics(f"{self.device}.local")