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
@@ -4,28 +4,23 @@ import os
4
4
  import sys
5
5
  import time
6
6
  MYPATH = os.path.dirname(os.path.abspath(__file__))
7
- sys.path.append(os.path.dirname(MYPATH))
8
- import socketClient
9
7
  sys.path.append(os.path.join(MYPATH, '../lib/'))
10
8
  from TerminalColors import Colors
11
9
 
12
- # FILL OUT
13
- DEVICE = 'node01'
14
-
15
-
16
- def base_cmd():
17
- return ['--dev', DEVICE]
10
+ try:
11
+ from ._app_base import AppBase
12
+ except:
13
+ from _app_base import AppBase
18
14
 
15
+ CLIENT = None
19
16
 
20
17
  def light_demo(modules, smooth=True, sample=10):
21
18
  verdict = [True, []]
22
19
  smooth_str = '[smooth]' if smooth else '[simple]'
23
20
 
24
- if 'LM_rgb' in modules:
25
- args = base_cmd() + [f'rgb random {smooth}'] * sample + ['rgb toggle False']
26
- print(args)
21
+ if 'rgb' in modules:
27
22
  delta_t = time.time()
28
- status_rgb, answer_rgb = socketClient.run(args)
23
+ status_rgb, answer_rgb = CLIENT.run([f'rgb random {smooth}'] * sample + ['rgb toggle False'])
29
24
  delta_t = round((time.time() - delta_t) / sample, 2)
30
25
  if status_rgb:
31
26
  msg = f"{smooth_str} rgb module random color func: {Colors.OK}OK{Colors.NC} [{delta_t}sec]"
@@ -35,10 +30,9 @@ def light_demo(modules, smooth=True, sample=10):
35
30
  verdict[1].append(msg)
36
31
  verdict[0] &= False
37
32
 
38
- if 'LM_cct' in modules:
39
- args = base_cmd() + [f'cct random {smooth}'] * sample + ['cct toggle False']
33
+ if 'cct' in modules:
40
34
  delta_t = time.time()
41
- status_cct, answer_cct = socketClient.run(args)
35
+ status_cct, answer_cct = CLIENT.run([f'cct random {smooth}'] * sample + ['cct toggle False'])
42
36
  delta_t = round((time.time() - delta_t) / sample, 2)
43
37
  if status_cct:
44
38
  msg = f"{smooth_str} cct module random color func: {Colors.OK}OK{Colors.NC} [{delta_t}sec]"
@@ -48,10 +42,9 @@ def light_demo(modules, smooth=True, sample=10):
48
42
  verdict[1].append(msg)
49
43
  verdict[0] &= False
50
44
 
51
- if 'LM_neopixel' in modules:
52
- args = base_cmd() + [f'neopixel random {smooth}'] * sample + ['neopixel toggle False']
45
+ if 'neopixel' in modules:
53
46
  delta_t = time.time()
54
- status_neo, answer_neo = socketClient.run(args)
47
+ status_neo, answer_neo = CLIENT.run([f'neopixel random {smooth}'] * sample + ['neopixel toggle False'])
55
48
  delta_t = round((time.time() - delta_t) / sample, 2)
56
49
  if status_neo:
57
50
  msg = f"{smooth_str} neopixel module random color func: {Colors.OK}OK{Colors.NC} [{delta_t}sec]"
@@ -63,19 +56,17 @@ def light_demo(modules, smooth=True, sample=10):
63
56
  return verdict
64
57
 
65
58
 
66
- def app(devfid=None):
59
+ def app(devfid=None, pwd=None):
67
60
  """
68
61
  devfid: selected device input
69
62
  send command(s) over socket connection [socketClient.run(args)]
70
63
  list load module commands and send in single connection
71
64
  """
72
- global DEVICE
73
- if devfid is not None:
74
- DEVICE = devfid
65
+ global CLIENT
66
+ CLIENT = AppBase(device=devfid, password=pwd)
75
67
 
76
68
  # Get loaded modules
77
- args = base_cmd() + ['pacman module']
78
- status, modules = socketClient.run(args)
69
+ status, modules = CLIENT.run(['modules'])
79
70
  print("status: {}\nanswer: {}".format(status, modules))
80
71
 
81
72
  if not status:
@@ -0,0 +1,64 @@
1
+ import requests
2
+ import zipfile
3
+ import io
4
+ import os
5
+
6
+ try:
7
+ from .LocalMachine import CommandHandler
8
+ except:
9
+ from LocalMachine import CommandHandler
10
+
11
+
12
+ def git_clone_archive(url):
13
+ """
14
+ Clone git repo as archive (without git installed)
15
+ Note: No git history, it is just a snapshot
16
+ :param url: https://github.com/micropython/webrepl
17
+ """
18
+ print(f"CLONE ARCHIVE: {url}")
19
+ url = url.replace(".git", "") if url.endswith(".git") else url
20
+ # URL of the repository zip archive (adjust branch name if needed)
21
+ target_name = url.split("/")[-1].strip()
22
+ zip_url = f"{url}/archive/refs/heads/master.zip"
23
+ response = requests.get(zip_url)
24
+ if response.status_code == 200:
25
+ # Read the downloaded content as a binary stream
26
+ with zipfile.ZipFile(io.BytesIO(response.content)) as z:
27
+ for member in z.infolist():
28
+ # Each member's filename is something like 'webrepl-master/filename'
29
+ # Remove the first directory component
30
+ parts = member.filename.split('/', 1)
31
+ if len(parts) > 1:
32
+ relative_path = parts[1]
33
+ else:
34
+ relative_path = parts[0]
35
+
36
+ # Build the target path relative to the current directory
37
+ target_path = os.path.join(target_name, relative_path)
38
+
39
+ if member.is_dir():
40
+ os.makedirs(target_path, exist_ok=True)
41
+ else:
42
+ os.makedirs(os.path.dirname(target_path), exist_ok=True)
43
+ with z.open(member) as source, open(target_path, 'wb') as target_file:
44
+ target_file.write(source.read())
45
+ print(f"\tRepository extracted successfully: {target_name}")
46
+ return 0, zip_url, ""
47
+ print(f"\tFailed to download repository archive: {target_name}")
48
+ return 1, zip_url, ""
49
+
50
+
51
+ def git_clone(url):
52
+ """
53
+ Git clone - subshell call
54
+ - git is needed to be preinstalled
55
+ """
56
+ print(f"GIT CLONE: {url}")
57
+ target_name = url.split("/")[-1].strip().replace(".git", "")
58
+ command = 'git clone {url} {name}'.format(name=target_name, url=url)
59
+ exitcode, stdout, stderr = CommandHandler.run_command(command, shell=True)
60
+ if exitcode == 0:
61
+ print(f"\tRepository was cloned successfully: {target_name}")
62
+ else:
63
+ print(f"\tRepository clone failed: {target_name}")
64
+ return exitcode, stdout, stderr
@@ -280,7 +280,7 @@ class micrOSClient:
280
280
  f_delta_t = "{}[{:.2f}]{}".format(color.OKGREEN, delta_time, color.NC)
281
281
  self.dbg_print("{}[⏰] {} {}reply: {}{}".format(f_delta_t, cmd, color.BOLD, out, color.NC))
282
282
 
283
- # return output list
283
+ # return output list or None
284
284
  return out
285
285
 
286
286
  def send_cmd_retry(self, cmd, timeout=6, retry=5, stream=False):
@@ -317,10 +317,13 @@ class micrOSClient:
317
317
  cmd = input() # CANNOT contain prompt - it is coming back from response data
318
318
  # send command
319
319
  output = self.send_cmd(cmd, timeout=timeout, stream=True)
320
- if history is not None and "Shell: for hints type help." not in output: # History: Beta feature
320
+ if not (history is None or output is None) and "Shell: for hints type help." not in output: # History: Beta feature
321
321
  history.add_history(cmd)
322
322
  if 'Bye!' in str(output):
323
323
  break
324
+ if output is None:
325
+ print("Exiting... client disconnected")
326
+ break
324
327
  except KeyboardInterrupt:
325
328
  print("Exiting...")
326
329
  break
@@ -352,8 +355,9 @@ class micrOSClient:
352
355
  verdict.append(console_msg)
353
356
  print(f"===>\t\t{console_msg}")
354
357
  self.close()
355
- verdict.append(f"SINGLE CONNECTION LOAD TEST X{cnt}, AVERAGE REPLY TIME: {round(delta_t_all/cnt, 3)} sec\n")
356
- return verdict
358
+ delta_t_result = round(delta_t_all / cnt, 3)
359
+ verdict.append(f"SINGLE CONNECTION LOAD TEST X{cnt}, AVERAGE REPLY TIME: {delta_t_result} sec\n")
360
+ return verdict, delta_t_result
357
361
 
358
362
  def __del__(self):
359
363
  if self.dbg and self.avg_reply[1] > 0:
@@ -382,9 +386,10 @@ def micros_connection_metrics(address):
382
386
  print(f"\t\t{_console_msg}")
383
387
  all_reply.append(_console_msg)
384
388
  success_rate = int(round(_success / cnt, 2) * 100)
385
- all_reply.append(f"MULTI CONNECTION LOAD TEST X{cnt}, AVERAGE REPLY TIME: {round(_all_delta_t/cnt, 3)}s, "
386
- f"SERVER AVAILABILITY: {success_rate}% ({round(_all_delta_t/_success, 3)}s)")
387
- return all_reply
389
+ delta_t_result = round(_all_delta_t/cnt, 3)
390
+ all_reply.append(f"MULTI CONNECTION LOAD TEST X{cnt}, AVERAGE REPLY TIME: {delta_t_result}s, "
391
+ f"SERVER AVAILABILITY: {success_rate}% ({int((_all_delta_t/_success)*1000)} ms)")
392
+ return all_reply, delta_t_result
388
393
 
389
394
  # ---------------------------------------------------- #
390
395
  high_level_verdict = []
@@ -392,12 +397,12 @@ def micros_connection_metrics(address):
392
397
  # [1] Create micrOSClient object + Run LOAD tests
393
398
  com_obj = micrOSClient(host=address, port=9008, pwd="ADmin123", dbg=True)
394
399
  # [1.1] Run load test in one connection
395
- verdict_list = com_obj.load_test()
400
+ verdict_list, delta_t_single_session = com_obj.load_test()
396
401
  com_obj.close()
397
402
  high_level_verdict.append(verdict_list[-1])
398
403
 
399
404
  # [2] Run multi connection load test - reconnect - raw connection (without retry)
400
- verdict_multi = multi_conn_load(address)
405
+ verdict_multi, delta_t_multi_session = multi_conn_load(address)
401
406
  high_level_verdict.append((verdict_multi[-1]))
402
407
 
403
408
  ############################################################################
@@ -409,7 +414,7 @@ def micros_connection_metrics(address):
409
414
  for k in verdict_multi:
410
415
  print(f"\t{k}")
411
416
 
412
- return high_level_verdict
417
+ return high_level_verdict, delta_t_single_session, delta_t_multi_session
413
418
 
414
419
 
415
420
  if __name__ == "__main__":
@@ -443,7 +448,7 @@ if __name__ == "__main__":
443
448
  print(f"noconf out: {noconf_mode}")
444
449
  if force_close: com_obj.close()
445
450
 
446
- verdict = micros_connection_metrics(address=address)
451
+ verdict, delta_t_single, delta_t_multi = micros_connection_metrics(address=address)
447
452
  for k in verdict:
448
453
  print(f"+\t\t{k}")
449
454
 
toolkit/micrOSlint.py CHANGED
@@ -172,7 +172,7 @@ def core_dep_checker(categories, verbose=True):
172
172
  def load_module_checker(categories, verbose=True):
173
173
 
174
174
  def _is_allowed(_relation):
175
- _allowed_whitelist = ['Common', 'microIO', 'Types']
175
+ _allowed_whitelist = ['Common', 'microIO', 'Types', 'urequests']
176
176
  _allowed = []
177
177
  for _allow in _relation:
178
178
  if _allow in _allowed_whitelist:
@@ -239,7 +239,7 @@ def _run_pylint(file_name):
239
239
 
240
240
  def run_pylint(categories, verbose=True, dry_run=False):
241
241
  # ERROR CONFIG: drop error if this is in pylint output
242
- error_msg_core = ['syntax-error', 'undefined-variable', 'no-member']
242
+ error_msg_core = ['syntax-error', 'undefined-variable', 'bad-indentation'] # 'no-member' ?
243
243
  # BYPASS 'no-member' due to duty and sleep_ms micropython functions is drops false alarm, etc.
244
244
  error_msg_lm = ['syntax-error', 'undefined-variable']
245
245
 
@@ -467,7 +467,7 @@ def short_report(categories, states, verbose=True):
467
467
  print(f"load_module_checker: load module dependency check (no core): {c_OK if lm_dep[0] else c_NOK} {'' if lm_dep[1] == 0 else f'{lm_dep[1]}{_vis(lm_dep_diff)} warning(s)'}")
468
468
  print(f" core pylint score: {core_pylint}{_pyl_vis(core_score_diff)}")
469
469
  print(f"load module pylint score: {lm_pylint}{_pyl_vis(load_score_diff)}")
470
- print(f"pylint resource check (syntax): {c_OK if pylint_check[0] else f'{c_NOK}: {pylint_check[1]}' }")
470
+ print(f"pylint resource check (syntax?): {c_OK if pylint_check[0] else f'{c_NOK}: {pylint_check[1]}' }")
471
471
 
472
472
  exitcode = sum([1 for k, v in states.items() if not v[0]])
473
473
  print(f"micrOSlint verdict: {c_OK if exitcode == 0 else c_NOK}")
@@ -0,0 +1,28 @@
1
+
2
+
3
+ class AIOESPNow:
4
+
5
+ def __init__(self):
6
+ self._active = False
7
+ self.peers_table = None
8
+
9
+ def active(self, state=None):
10
+ if state is not None:
11
+ self._active = state
12
+ return self._active
13
+
14
+ def stats(self):
15
+ pass
16
+
17
+ def add_peer(self, mac):
18
+ pass
19
+
20
+ async def asend(self, mac, full_msg):
21
+ pass
22
+
23
+ def send(self, mac, full_msg):
24
+ pass
25
+
26
+ def __iter__(self):
27
+ return (i for i in range(0, 3))
28
+
toolkit/socketClient.py CHANGED
@@ -4,7 +4,6 @@
4
4
  import sys
5
5
  import socket
6
6
  import os
7
- import select
8
7
  import time
9
8
  import json
10
9
  import threading
@@ -1,23 +1,49 @@
1
1
  import Espnow
2
2
 
3
3
  def load():
4
+ """
5
+ Initialize ESPNOW protocal
6
+ """
4
7
  return Espnow.initialize()
5
8
 
6
- def send(peer, msg='ping'):
9
+ def send(peer, msg='modules'):
10
+ """
11
+ Send message to peer (by mac address)
12
+ :param peer: mac address of espnow device
13
+ :param msg: message string/load module call
14
+ """
7
15
  return Espnow.espnow_send(peer, msg)
8
16
 
9
17
  def start_server():
18
+ """
19
+ Start ESPNOW server/listener
20
+ - this can receive espnow messages
21
+ - it includes Load Module execution logic (beta)
22
+ """
10
23
  return Espnow.espnow_server()
11
24
 
12
25
  def stats():
26
+ """
27
+ Get ESPNOW stats
28
+ """
13
29
  return Espnow.stats()
14
30
 
15
31
  def add_peer(peer):
32
+ """
33
+ Add ESPNOW peer to known hosts
34
+ - It is needed before first send(...)
35
+ """
16
36
  now = Espnow.initialize()
17
37
  return Espnow.add_peer(now, peer)
18
38
 
19
39
  def mac_address():
40
+ """
41
+ Get ESPNOW compatible mac address
42
+ """
20
43
  return Espnow.mac_address()
21
44
 
22
45
  def help():
46
+ """
47
+ [beta] ESPNOW sender/receiver with LM execution
48
+ """
23
49
  return 'load', 'send <peer> "ping"', 'start_server', 'add_peer <peer>', 'stats', 'mac_address'
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -1,36 +0,0 @@
1
- #!/usr/bin/env python3
2
-
3
- import os
4
- import sys
5
- import time
6
- MYPATH = os.path.dirname(os.path.abspath(__file__))
7
- sys.path.append(os.path.dirname(MYPATH))
8
- import socketClient
9
-
10
- # FILL OUT
11
- DEVICE = 'AirQualityPro'
12
-
13
-
14
- def base_cmd():
15
- return ['--dev', DEVICE]
16
-
17
-
18
- def app(devfid=None):
19
- global DEVICE
20
- if devfid is not None:
21
- DEVICE = devfid
22
- for k in range(0, 20):
23
- args = base_cmd() + ['bme280 measure']
24
- try:
25
- status, answer = socketClient.run(args)
26
- if status:
27
- print("|- [{}/20] OK".format(k+1))
28
- else:
29
- print("|- [{}/20] ERR".format(k+1))
30
- time.sleep(3)
31
- except KeyboardInterrupt:
32
- break
33
-
34
-
35
- if __name__ == "__main__":
36
- app()
@@ -1,36 +0,0 @@
1
- #!/usr/bin/env python3
2
-
3
- import os
4
- import sys
5
- import time
6
- MYPATH = os.path.dirname(os.path.abspath(__file__))
7
- sys.path.append(os.path.dirname(MYPATH))
8
- import socketClient
9
-
10
- # FILL OUT
11
- DEVICE = 'airquality'
12
-
13
-
14
- def base_cmd():
15
- return ['--dev', DEVICE]
16
-
17
-
18
- def app(devfid=None):
19
- global DEVICE
20
- if devfid is not None:
21
- DEVICE = devfid
22
- for k in range(0, 20):
23
- args = base_cmd() + ['dht22 measure_w_co2']
24
- try:
25
- status, answer = socketClient.run(args)
26
- if status:
27
- print("|- [{}/20] OK".format(k+1))
28
- else:
29
- print("|- [{}/20] ERR".format(k+1))
30
- time.sleep(3)
31
- except KeyboardInterrupt:
32
- break
33
-
34
-
35
- if __name__ == "__main__":
36
- app()