micrOSDevToolKit 2.8.5__py3-none-any.whl → 2.8.7__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 (88) hide show
  1. env/driver_cp210x/.DS_Store +0 -0
  2. env/driver_cp210x/macOS_VCP_Driver/SiLabsUSBDriverDisk.dmg +0 -0
  3. env/driver_cp210x/macOS_VCP_Driver/macOS_VCP_Driver_Release_Notes.txt +0 -0
  4. micrOS/micropython/esp32-20241129-v1.24.1.bin +0 -0
  5. micrOS/micropython/esp32s3-20241129-v1.24.1.bin +0 -0
  6. micrOS/micropython/esp32s3_spiram_oct-20241129-v1.24.1.bin +0 -0
  7. micrOS/micropython/rpi-pico-w-20241129-v1.24.1.uf2 +0 -0
  8. micrOS/micropython/tinypico-20241129-v1.24.1.bin +0 -0
  9. micrOS/release_info/micrOS_ReleaseInfo/system_analysis_sum.json +28 -28
  10. micrOS/source/Common.py +2 -2
  11. micrOS/source/Hooks.py +25 -15
  12. micrOS/source/LM_buzzer.py +1 -2
  13. micrOS/source/LM_cct.py +2 -3
  14. micrOS/source/LM_dimmer.py +1 -2
  15. micrOS/source/LM_distance.py +2 -4
  16. micrOS/source/LM_i2s_mic.py +4 -4
  17. micrOS/source/LM_keychain.py +2 -3
  18. micrOS/source/LM_light_sensor.py +1 -2
  19. micrOS/source/LM_neopixel.py +1 -2
  20. micrOS/source/LM_oledui.py +3 -4
  21. micrOS/source/LM_pet_feeder.py +3 -4
  22. micrOS/source/LM_presence.py +1 -2
  23. micrOS/source/LM_rest.py +52 -9
  24. micrOS/source/LM_rgb.py +1 -2
  25. micrOS/source/LM_roboarm.py +1 -2
  26. micrOS/source/LM_sound_event.py +2 -3
  27. micrOS/source/Notify.py +0 -1
  28. micrOS/source/Scheduler.py +7 -4
  29. micrOS/source/Shell.py +2 -2
  30. micrOS/source/Tasks.py +106 -98
  31. micrOS/source/Web.py +16 -5
  32. micrOS/source/dashboard.html +4 -4
  33. micrOS/source/micrOS.py +5 -10
  34. micrOS/source/micrOSloader.py +0 -5
  35. micrOS/source/uapi.js +5 -6
  36. micrOS/source/urequests.py +171 -85
  37. {micrOSDevToolKit-2.8.5.dist-info → micrOSDevToolKit-2.8.7.dist-info}/METADATA +1 -1
  38. {micrOSDevToolKit-2.8.5.dist-info → micrOSDevToolKit-2.8.7.dist-info}/RECORD +79 -81
  39. toolkit/DevEnvUSB.py +1 -6
  40. toolkit/lib/pip_package_installer.py +25 -7
  41. toolkit/simulator_lib/__pycache__/simulator.cpython-312.pyc +0 -0
  42. toolkit/simulator_lib/__pycache__/uasyncio.cpython-312.pyc +0 -0
  43. toolkit/simulator_lib/__pycache__/usocket.cpython-312.pyc +0 -0
  44. toolkit/simulator_lib/simulator.py +14 -0
  45. toolkit/simulator_lib/uasyncio.py +2 -2
  46. toolkit/simulator_lib/usocket.py +5 -1
  47. toolkit/workspace/precompiled/Common.mpy +0 -0
  48. toolkit/workspace/precompiled/Hooks.mpy +0 -0
  49. toolkit/workspace/precompiled/LM_buzzer.mpy +0 -0
  50. toolkit/workspace/precompiled/LM_cct.mpy +0 -0
  51. toolkit/workspace/precompiled/LM_dimmer.mpy +0 -0
  52. toolkit/workspace/precompiled/LM_distance.mpy +0 -0
  53. toolkit/workspace/precompiled/LM_i2s_mic.mpy +0 -0
  54. toolkit/workspace/precompiled/LM_keychain.mpy +0 -0
  55. toolkit/workspace/precompiled/LM_light_sensor.mpy +0 -0
  56. toolkit/workspace/precompiled/LM_neopixel.mpy +0 -0
  57. toolkit/workspace/precompiled/LM_oledui.mpy +0 -0
  58. toolkit/workspace/precompiled/LM_pet_feeder.py +3 -4
  59. toolkit/workspace/precompiled/LM_presence.mpy +0 -0
  60. toolkit/workspace/precompiled/LM_rest.mpy +0 -0
  61. toolkit/workspace/precompiled/LM_rgb.mpy +0 -0
  62. toolkit/workspace/precompiled/LM_roboarm.mpy +0 -0
  63. toolkit/workspace/precompiled/LM_sound_event.mpy +0 -0
  64. toolkit/workspace/precompiled/Notify.mpy +0 -0
  65. toolkit/workspace/precompiled/Scheduler.mpy +0 -0
  66. toolkit/workspace/precompiled/Shell.mpy +0 -0
  67. toolkit/workspace/precompiled/Tasks.mpy +0 -0
  68. toolkit/workspace/precompiled/Web.mpy +0 -0
  69. toolkit/workspace/precompiled/dashboard.html +4 -4
  70. toolkit/workspace/precompiled/micrOS.mpy +0 -0
  71. toolkit/workspace/precompiled/micrOSloader.mpy +0 -0
  72. toolkit/workspace/precompiled/node_config.json +1 -1
  73. toolkit/workspace/precompiled/uapi.js +5 -6
  74. toolkit/workspace/precompiled/urequests.mpy +0 -0
  75. env/driver_cp210x/CH34XSER_MAC/CH34X_DRV_INSTALL_INSTRUCTIONS.pdf +0 -0
  76. env/driver_cp210x/CH34XSER_MAC/CH34xVCPDriver.pkg +0 -0
  77. micrOS/micropython/esp32-20231005-v1.21.0.bin +0 -0
  78. micrOS/micropython/esp32-GENERIC-20240602-v1.23.0.bin +0 -0
  79. micrOS/micropython/rpi-pico-w-20240602-v1.23.0.uf2 +0 -0
  80. micrOS/micropython/tinypico-20231005-v1.21.0.bin +0 -0
  81. micrOS/micropython/tinypico_usbc-UM-20240105-v1.22.1.bin +0 -0
  82. /micrOS/micropython/{esp32c3-GENERIC-20240222-v1.22.2.bin → esp32c3-20240222-v1.22.2.bin} +0 -0
  83. /micrOS/micropython/{esp32s2-GENERIC-20240602-v1.23.0.bin → esp32s2-20240602-v1.23.0.bin} +0 -0
  84. /micrOS/micropython/{esp32s3-GENERIC-20240105-v1.22.1.bin → esp32s3-20240105-v1.22.1.bin} +0 -0
  85. {micrOSDevToolKit-2.8.5.data → micrOSDevToolKit-2.8.7.data}/scripts/devToolKit.py +0 -0
  86. {micrOSDevToolKit-2.8.5.dist-info → micrOSDevToolKit-2.8.7.dist-info}/LICENSE +0 -0
  87. {micrOSDevToolKit-2.8.5.dist-info → micrOSDevToolKit-2.8.7.dist-info}/WHEEL +0 -0
  88. {micrOSDevToolKit-2.8.5.dist-info → micrOSDevToolKit-2.8.7.dist-info}/top_level.txt +0 -0
@@ -37,7 +37,6 @@ Terminal ready
37
37
  """
38
38
 
39
39
  import LM_i2s_mic
40
- import uasyncio as asyncio
41
40
  import json
42
41
 
43
42
  from microIO import pinmap_search
@@ -647,7 +646,7 @@ async def __control_task(capture_duration_ms,
647
646
  :param pause_duration_ms: int - duration of pause frames to distinguish events
648
647
  :param event_buffer_length: int - number of events to store at once
649
648
  """
650
- with micro_task(tag=Data.CONTROL_TASK_TAG):
649
+ with micro_task(tag=Data.CONTROL_TASK_TAG) as my_task:
651
650
  samples = []
652
651
  frame_size = int((frame_size_ms/1000)*LM_i2s_mic.Data.SAMPLING_RATE)
653
652
  pause_duration = int(pause_duration_ms/frame_size_ms)
@@ -674,7 +673,7 @@ async def __control_task(capture_duration_ms,
674
673
 
675
674
  # Wait for new samples to be taken
676
675
  ms_period = int(len(new_samples)/LM_i2s_mic.Data.SAMPLING_RATE)
677
- await asyncio.sleep_ms(ms_period)
676
+ await my_task.feed(sleep_ms=ms_period)
678
677
  Data.EVENTS = Data.EVENTS[-event_buffer_length:]
679
678
  except Exception as e:
680
679
  console(f'[ERR] sound_event: {e}')
micrOS/source/Notify.py CHANGED
@@ -9,7 +9,6 @@ from Debug import console_write
9
9
  # with Telegram Class #
10
10
  #########################################
11
11
 
12
-
13
12
  class Telegram:
14
13
  # Telegram bot token and chat ID
15
14
  # https://core.telegram.org/bots/api
@@ -1,6 +1,6 @@
1
1
  from time import localtime
2
2
  from re import compile
3
- from Tasks import exec_lm_core_schedule
3
+ from Tasks import exec_lm_pipe_schedule
4
4
  from Debug import console_write, errlog_add
5
5
  from Time import Sun, suntime, ntp_time
6
6
 
@@ -179,7 +179,7 @@ def __scheduler_trigger(cron_time_now, crontask, deltasec=2):
179
179
  lm_state = False
180
180
  if isinstance(crontask[1], str):
181
181
  # [1] Execute Load Module as a string (user LMs)
182
- lm_state = exec_lm_core_schedule(crontask[1].split())
182
+ lm_state = exec_lm_pipe_schedule(crontask[1])
183
183
  else:
184
184
  try:
185
185
  # [2] Execute function reference (built-in functions)
@@ -207,6 +207,7 @@ def deserialize_raw_input(cron_data):
207
207
  Scheduler/Cron input string format
208
208
  :param cron_data: raw cron tasks, time based task execution input (bytearray)
209
209
  example: WD:H:M:S!LM func;WD:H:M:S!LM func; ...
210
+ multi command example: WD:H:M:S!LM func;LM func2;; WD:H:M:S!LM func;; ...
210
211
 
211
212
  time_tag: timestamp / time-tag aka suntime
212
213
  timestamp: WD:H:M:S
@@ -218,8 +219,10 @@ def deserialize_raw_input(cron_data):
218
219
  Returns tuple: (("WD:H:M:S", 'LM FUNC'), ("WD:H:M:S", 'LM FUNC'), ...)
219
220
  """
220
221
  try:
221
- # Parse and create return - convert cron_data (bytearray) to string
222
- return (tuple(cron.split('!')) for cron in str(cron_data, 'utf-8').split(';'))
222
+ # Parse and create return
223
+ cd = str(cron_data, 'utf-8') # convert cron_data (bytearray) to string
224
+ sep = ';;' if ';;' in cd else ';' # support multi command with ;;
225
+ return (tuple(cron.split('!')) for cron in cd.split(sep))
223
226
  except Exception as e:
224
227
  errlog_add(f"[ERR] cron deserialize - syntax error: {e}")
225
228
  return ()
micrOS/source/Shell.py CHANGED
@@ -2,7 +2,7 @@
2
2
  Module is responsible for shell like environment
3
3
  dedicated to micrOS framework.
4
4
  Built-in-function:
5
- - Shell wrapper for safe InterpreterCore interface
5
+ - Shell wrapper for lm_exec interface
6
6
  - Configuration handling interface - state machine handling
7
7
  - Help (runtime) message generation
8
8
 
@@ -25,7 +25,7 @@ from Debug import errlog_add
25
25
 
26
26
  class Shell:
27
27
  __slots__ = ['__devfid', '__auth_mode', '__hwuid', '__auth_ok', '__conf_mode']
28
- MICROS_VERSION = '2.8.1-0'
28
+ MICROS_VERSION = '2.8.4-0'
29
29
 
30
30
  def __init__(self):
31
31
  """
micrOS/source/Tasks.py CHANGED
@@ -19,7 +19,7 @@ from Network import sta_high_avail
19
19
 
20
20
  try:
21
21
  from gc import collect
22
- except:
22
+ except ImportError:
23
23
  console_write("[SIMULATOR MODE GC IMPORT]")
24
24
  from simgc import collect
25
25
 
@@ -38,22 +38,34 @@ class TaskBase:
38
38
  TASKS = {} # TASK OBJ list
39
39
 
40
40
  def __init__(self):
41
- self.task = None # [TASK] Store created async task object
42
- self.done = asyncio.Event() # [TASK] Store done state
43
- self.out = "" # [TASK] Store output
44
- self.tag = None # [TASK] Task tag (identification)
41
+ self.task = None # Store created async task object
42
+ self.tag = None # Task tag (identification)
43
+ self.done = asyncio.Event() # Store task done state
44
+ self.out = "" # Store task output
45
45
 
46
46
  @staticmethod
47
- def is_busy(tag):
47
+ def is_busy(tag) -> bool:
48
48
  """
49
- Check task is busy by tag in TASKS
50
- - exists + running = busy
49
+ Check task is busy by tag
50
+ :param tag: for task selection
51
51
  """
52
52
  task = TaskBase.TASKS.get(tag, None)
53
53
  # return True: busy OR False: not busy (inactive)
54
54
  return bool(task is not None and not task.done.is_set())
55
55
 
56
- def cancel(self):
56
+ @staticmethod
57
+ def task_gc():
58
+ """
59
+ Automatic passive task deletion over QUEUE_SIZE
60
+ """
61
+ keep = TaskBase.QUEUE_SIZE
62
+ passive = tuple((task_tag for task_tag in list(TaskBase.TASKS) if not TaskBase.is_busy(task_tag)))
63
+ if len(passive) >= keep:
64
+ for i in range(0, len(passive)-keep+1):
65
+ del TaskBase.TASKS[passive[i]]
66
+ collect() # GC collect
67
+
68
+ def cancel(self) -> bool:
57
69
  """
58
70
  Cancel task (+cleanup)
59
71
  """
@@ -83,13 +95,13 @@ class TaskBase:
83
95
  collect() # GC collect
84
96
 
85
97
  @staticmethod
86
- def task_gc():
87
- keep = TaskBase.QUEUE_SIZE
88
- passive = tuple((task_tag for task_tag in list(TaskBase.TASKS) if not TaskBase.is_busy(task_tag)))
89
- if len(passive) >= keep:
90
- for i in range(0, len(passive)-keep+1):
91
- del TaskBase.TASKS[passive[i]]
92
- collect() # GC collect
98
+ async def feed(sleep_ms=1):
99
+ """
100
+ Feed event loop
101
+ :param sleep_ms: in millisecond (min: 1)
102
+ """
103
+ # TODO: feed WDT - preemptive cooperative multitasking aka reboot if no feed until X time period
104
+ return await asyncio.sleep_ms(sleep_ms)
93
105
 
94
106
  def __del__(self):
95
107
  try:
@@ -187,9 +199,12 @@ class MagicTask(TaskBase):
187
199
  - self.__inloop: lm call type - one-shot (False) / looped (True)
188
200
  - self.__msg_buf: lm msg object redirect to variable - store lm output
189
201
  """
202
+ jsonify = self.__callback[-1] == '>json'
203
+ if jsonify:
204
+ self.__callback = self.__callback[:-1]
190
205
  while True:
191
- await asyncio.sleep_ms(self.__sleep)
192
- state, self.out = _exec_lm_core(self.__callback)
206
+ await self.feed(self.__sleep)
207
+ state, self.out = _exec_lm_core(self.__callback, jsonify)
193
208
  if not state or not self.__inloop:
194
209
  break
195
210
  self.task_gc() # Task pool cleanup
@@ -265,10 +280,10 @@ class Manager:
265
280
  try:
266
281
  while True:
267
282
  # [0] Just chill
268
- await asyncio.sleep_ms(300)
283
+ await my_task.feed(300)
269
284
  # [1] PROBE SYSTEM LOAD + 300ms
270
285
  t = ticks_ms()
271
- await asyncio.sleep_ms(300)
286
+ await my_task.feed(300)
272
287
  delta_rate = int(((ticks_diff(ticks_ms(), t) / 300) - 1) * 100)
273
288
  Manager.LOAD = int((Manager.LOAD + delta_rate) / 2) # Average - smooth
274
289
  # [2] NETWORK AUTO REPAIR
@@ -353,7 +368,6 @@ class Manager:
353
368
  - by tag: module.function
354
369
  - by tag module.*, kill all for selected module
355
370
  """
356
-
357
371
  def terminate(_tag):
358
372
  to_kill = TaskBase.TASKS.get(_tag, None)
359
373
  try:
@@ -399,85 +413,94 @@ class Manager:
399
413
  #################################################################
400
414
  # LM EXEC CORE functions #
401
415
  #################################################################
402
-
403
- def lm_exec(arg_list):
416
+ def exec_builtins(func):
417
+ """
418
+ Module execution built-in commands and modifiers
419
+ - modules - show active modules list
420
+ - task kill ... - task termination
421
+ show ... - task output dump
422
+ - ... >json - postfix to "jsonize" the output
423
+ """
424
+ def wrapper(arg_list, jsonify=None):
425
+ # Ensure the parameter is a list of strings
426
+ if isinstance(arg_list, list) and arg_list:
427
+ # JSONIFY: [1] >json in arg_list or [2] jsonify True/False
428
+ json_flag = arg_list[-1] == '>json'
429
+ if json_flag:
430
+ arg_list = arg_list[:-1]
431
+ json_flag = jsonify if isinstance(jsonify, bool) else json_flag
432
+ # MODULES
433
+ if arg_list[0] == 'modules':
434
+ return True, list((m.strip().replace('LM_', '') for m in modules if m.startswith('LM_'))) + ['task']
435
+ # Handle task manipulation commands: list, kill, show - return True -> Command handled
436
+ if 'task' == arg_list[0]:
437
+ arg_len = len(arg_list)
438
+ # task list
439
+ if arg_len > 1 and 'list' == arg_list[1]:
440
+ on, off = Manager.list_tasks(json=json_flag)
441
+ # RETURN: JSON mode Human readable mode with cpu & queue info
442
+ return (True, {'active': on[3:], 'inactive': off}) if json_flag else (True, '\n'.join(on) + '\n' + '\n'.join(off) + '\n')
443
+ # task kill <taskID> / task show <taskID>
444
+ if arg_len > 2:
445
+ if 'kill' == arg_list[1]:
446
+ state, msg = Manager.kill(tag=arg_list[2])
447
+ return True, msg
448
+ if 'show' == arg_list[1]:
449
+ return True, Manager.show(tag=arg_list[2])
450
+ return True, "Invalid task cmd! Help: task list / kill <taskID> / show <taskID>"
451
+ # Call the decorated function with the additional flag
452
+ return func(arg_list, json_flag)
453
+ return wrapper
454
+
455
+
456
+ @exec_builtins
457
+ def lm_exec(arg_list, jsonify):
404
458
  """
405
459
  Main LM executor function with
406
460
  - async (background)
407
461
  - sync
408
462
  (single) task execution (_exec_lm_core)
409
463
  :param arg_list: command parameters
410
- Return Bool(OK/NOK), STR(Command output)
464
+ :param jsonify: request json output (controlled by the decorator)
465
+ Return Bool(OK/NOK), "Command output"
411
466
  """
412
467
 
413
- def _exec_task():
414
- nonlocal arg_list, arg_len
415
- # [1] Handle task manipulation commands: list, kill, show - return True -> Command handled
416
- if 'task' == arg_list[0]:
417
- # task list
418
- if arg_len > 1 and 'list' == arg_list[1]:
419
- if arg_len > 2 and arg_list[2].strip() == '>json':
420
- # JSON mode
421
- on, off = Manager.list_tasks(json=True)
422
- return True, {'active': on[3:], 'inactive': off}
423
- on, off = Manager.list_tasks(json=False)
424
- # Human readable mode with cpu & queue info
425
- return True, '\n'.join(on) + '\n' + '\n'.join(off) + '\n' # Show active tasks and passive tasks
426
- # task kill <taskID> / task show <taskID>
427
- if arg_len > 2:
428
- if 'kill' == arg_list[1]:
429
- state, msg = Manager.kill(tag=arg_list[2])
430
- return True, msg
431
- if 'show' == arg_list[1]:
432
- return True, Manager.show(tag=arg_list[2])
433
- return True, "Invalid task cmd! Help: task list / kill <taskID> / show <taskID>"
434
- # [2] Start async task, postfix: &, &&
435
- if arg_len > 2 and '&' in arg_list[-1]:
436
- # Evaluate task mode: loop + delay
437
- mode = arg_list.pop(-1)
438
- loop = mode.count('&') == 2
439
- delay = mode.replace('&', '').strip()
440
- delay = int(delay) if delay.isdigit() else None
441
- # Create and start async lm task
442
- try:
443
- state = Manager.create_task(arg_list, loop=loop, delay=delay)
444
- except Exception as e:
445
- # Valid & handled task command
446
- return True, str(e)
447
- tag = '.'.join(arg_list[0:2])
468
+ # [1] Async "background" task execution, postfix: &, &&
469
+ if len(arg_list) > 2 and '&' in arg_list[-1]:
470
+ # Evaluate task mode: loop + delay
471
+ mode = arg_list.pop(-1)
472
+ loop = mode.count('&') == 2
473
+ delay = mode.replace('&', '').strip()
474
+ delay = int(delay) if delay.isdigit() else None
475
+ # Create and start async lm task
476
+ try:
477
+ state = Manager.create_task(arg_list, loop=loop, delay=delay)
478
+ except Exception as e:
448
479
  # Valid & handled task command
449
- if state:
450
- return True, f"Start {tag}"
451
- return True, f"{tag} is Busy"
452
- # Not valid task command
453
- return False, ''
454
-
455
- # ================ main function ================
456
- # modules built-in function: show loaded LoadModules
457
- arg_len = len(arg_list)
458
- if arg_len > 0 and arg_list[0] == 'modules':
459
- return True, list((m.strip().replace('LM_', '') for m in modules if m.startswith('LM_'))) + ['task']
460
- # [1] Run task command: start (&), list, kill, show
461
- is_task, out = _exec_task()
462
- if is_task:
463
- return True, out
480
+ return True, str(e)
481
+ tag = '.'.join(arg_list[0:2])
482
+ # Valid & handled task command
483
+ if state:
484
+ return True, f"Start {tag}"
485
+ return True, f"{tag} is Busy"
486
+
464
487
  # [2] Sync "realtime" task execution
465
- state, out = _exec_lm_core(arg_list)
488
+ state, out = _exec_lm_core(arg_list, jsonify)
466
489
  return state, out
467
490
 
468
491
 
469
- def _exec_lm_core(cmd_list):
492
+ def _exec_lm_core(cmd_list, jsonify):
470
493
  """
471
494
  [CORE] Single command executor: MODULE.FUNCTION...
472
495
  :param cmd_list: list of string parameters
473
496
  [1] module name (LM)
474
497
  [2] function
475
498
  [3...] parameters (separator: space)
476
- [-1] Built-in json output handler: >json
499
+ :param jsonify: request json output
477
500
  Return Bool(OK/NOK), STR(Command output)
478
501
  """
479
502
 
480
- def __func_params(param):
503
+ def _func_params(param):
481
504
  buf = None
482
505
  if "'" in param or '"' in param:
483
506
  str_index = [i for i, c in enumerate(param) if c in ('"', "'")]
@@ -489,12 +512,9 @@ def _exec_lm_core(cmd_list):
489
512
  param = param.format(*buf)
490
513
  return param
491
514
 
492
- # Check json mode for LM execution
493
- json_mode = cmd_list[-1] == '>json'
494
- cmd_list = cmd_list[0:-1] if json_mode else cmd_list
495
515
  # LoadModule execution
496
516
  if len(cmd_list) >= 2:
497
- lm_mod, lm_func, lm_params = f"LM_{cmd_list[0]}", cmd_list[1], __func_params(' '.join(cmd_list[2:]))
517
+ lm_mod, lm_func, lm_params = f"LM_{cmd_list[0]}", cmd_list[1], _func_params(' '.join(cmd_list[2:]))
498
518
  try:
499
519
  # ------------- LM LOAD & EXECUTE ------------- #
500
520
  # [1] LOAD MODULE - OPTIMIZED by sys.modules
@@ -516,11 +536,11 @@ def _exec_lm_core(cmd_list):
516
536
  # Handle LM output data
517
537
  if isinstance(lm_output, dict):
518
538
  # json True: output->json else Format dict output "human readable"
519
- lm_output = dumps(lm_output) if json_mode else '\n'.join(
539
+ lm_output = dumps(lm_output) if jsonify else '\n'.join(
520
540
  [f" {key}: {value}" for key, value in lm_output.items()])
521
541
  if lm_func == 'help':
522
542
  # Special case for help command: json True: output->json else Format dict output "human readable"
523
- lm_output = dumps(lm_output) if json_mode else '\n'.join([f" {out}," for out in lm_output])
543
+ lm_output = dumps(lm_output) if jsonify else '\n'.join([f" {out}," for out in lm_output])
524
544
  # Return LM exec result
525
545
  return True, str(lm_output)
526
546
  # ---------------------------------------------------------------------- #
@@ -540,7 +560,7 @@ def lm_is_loaded(lm_name):
540
560
  [Auth mode]
541
561
  Check lm_name in enabled modules
542
562
  """
543
- static_keywords = tuple('task')
563
+ static_keywords = ('task', 'modules')
544
564
  loaded_mods = [lm.replace('LM_', '') for lm in modules if lm.startswith('LM_')]
545
565
  return lm_name in static_keywords or lm_name in loaded_mods
546
566
 
@@ -573,7 +593,7 @@ def exec_lm_pipe(taskstr):
573
593
 
574
594
  def exec_lm_pipe_schedule(taskstr):
575
595
  """
576
- Scheduled Wrapper for exec_lm_pipe for IRQs (extIRQ, timIRQ)
596
+ Scheduled Wrapper for exec_lm_pipe for IRQs (extIRQ, timIRQ, cronIRQ)
577
597
  """
578
598
  try:
579
599
  schedule(exec_lm_pipe, taskstr)
@@ -581,15 +601,3 @@ def exec_lm_pipe_schedule(taskstr):
581
601
  except Exception as e:
582
602
  errlog_add(f"[ERR] exec_lm_pipe_schedule: {e}")
583
603
  return False
584
-
585
-
586
- def exec_lm_core_schedule(arg_list):
587
- """
588
- Scheduled Wrapper for lm_exec for cron IRQ
589
- """
590
- try:
591
- schedule(lm_exec, arg_list)
592
- return True
593
- except Exception as e:
594
- errlog_add(f"[ERR] schedule_lm_exec {arg_list}: {e}")
595
- return False
micrOS/source/Web.py CHANGED
@@ -1,3 +1,17 @@
1
+ """
2
+ Module is responsible for webserver environment
3
+ dedicated to micrOS framework.
4
+ Built-in-function:
5
+ - response
6
+ - landing page: index.html
7
+ - rest/ - call load modules, e.x.: system/top
8
+ - file response (.html, .css, .js, .jped) - generic file server feature
9
+ - "virtual" endpoints - to reply from script on a defined endpoint
10
+ - stream - stream data (jpeg) function
11
+
12
+ Designed by Marcell Ban aka BxNxM
13
+ """
14
+
1
15
  from json import dumps, loads
2
16
  import uasyncio as asyncio
3
17
  from Tasks import lm_exec, NativeTask, lm_is_loaded
@@ -76,14 +90,11 @@ class WebEngine:
76
90
  # REST sub-parameter handling (rest commands)
77
91
  cmd = (cmd.replace('/', ' ').replace('%22', '"').replace('%E2%80%9C', '"')
78
92
  .replace('%E2%80%9D', '"').replace('-', ' ').strip().split())
79
- # request json format instead of default string output (+ handle & tasks syntax)
80
- cmd.insert(-1, '>json') if cmd[-1].startswith('&') else cmd.append('>json')
81
93
  # EXECUTE COMMAND - LoadModule
82
94
  if WebEngine.AUTH:
83
- state, out = lm_exec(cmd) if lm_is_loaded(cmd[0]) or cmd[0].startswith('modules') else (
84
- True, 'Auth:Protected')
95
+ state, out = lm_exec(cmd, jsonify=True) if lm_is_loaded(cmd[0]) else (True, 'Auth:Protected')
85
96
  else:
86
- state, out = lm_exec(cmd)
97
+ state, out = lm_exec(cmd, jsonify=True)
87
98
  try:
88
99
  resp_schema['result'] = loads(out) # Load again ... hack for embedded shell json converter...
89
100
  except:
@@ -31,10 +31,10 @@
31
31
  transition: border-color 0.3s ease; /* Smooth transition for border color */
32
32
  }
33
33
  </style>
34
- <script src="uapi.js" defer></script>
35
- <script src="uwidgets.js" defer></script>
36
- <script src="uwidgets_pro.js" defer></script>
37
- <script src="udashboard.js" defer></script>
34
+ <script src="uapi.js" ></script>
35
+ <script src="uwidgets.js" ></script>
36
+ <script src="uwidgets_pro.js" ></script>
37
+ <script src="udashboard.js" ></script>
38
38
  </head>
39
39
  <body>
40
40
  <h1> micrOS dashboard </h1>
micrOS/source/micrOS.py CHANGED
@@ -20,15 +20,6 @@ from Debug import errlog_add
20
20
  # INTERRUPT HANDLER INTERFACES / WRAPPERS #
21
21
  #################################################################
22
22
 
23
-
24
- def safe_boot():
25
- try:
26
- bootup()
27
- except Exception as e:
28
- print(f"[micrOS main] Hooks.boot() error: {e}")
29
- errlog_add(f"[ERR] safe_boot: {e}")
30
-
31
-
32
23
  def irq_handler():
33
24
  try:
34
25
  enableInterrupt()
@@ -58,7 +49,11 @@ def micrOS():
58
49
  aio = Manager()
59
50
 
60
51
  # BOOT TASKS: Initial LM executions
61
- safe_boot()
52
+ try:
53
+ bootup()
54
+ except Exception as e:
55
+ print(f"[micrOS main] Hooks.boot() error: {e}")
56
+ errlog_add(f"[ERR] safe_boot: {e}")
62
57
 
63
58
  # NETWORK setup
64
59
  nwmd = auto_nw_config()
@@ -34,7 +34,6 @@ def __is_micrOS():
34
34
  False -> webrepl
35
35
  * EOE (EndOfExecution) -> off
36
36
  """
37
- mode = 'micros'
38
37
  try:
39
38
  with open('.if_mode', 'r') as f:
40
39
  mode = f.read().strip().lower()
@@ -82,10 +81,6 @@ def __auto_restart_event():
82
81
  - value: micros [update was successful - reboot is necessary]
83
82
  :return:
84
83
  """
85
- from sys import platform
86
- if platform == 'rp2':
87
- print("[loader][ota-rebooter] SKIP on platform: rp2 (webrepl block)")
88
- return
89
84
 
90
85
  from utime import sleep
91
86
  trigger_is_active = False
micrOS/source/uapi.js CHANGED
@@ -1,9 +1,9 @@
1
- // Get the current hostname and create the REST API URL
2
- const currentHostname = window.location.hostname;
3
- const port = window.location.port ? `:${window.location.port}` : "";
1
+ // CORE MICROS BACKEND INTERFACE
2
+
3
+ const BASE_URL = `http://${window.location.hostname}${window.location.port ? `:${window.location.port}` : ""}`;
4
4
 
5
5
  function restAPICore(cmd, timeout=5000) {
6
- const query = `http://${currentHostname}${port}/rest/${cmd.trim().replace(/\s+/g, '/')}`;
6
+ const query = `${BASE_URL}/rest/${cmd.trim().replace(/\s+/g, '/')}`;
7
7
  const controller = new AbortController();
8
8
  const timeoutId = setTimeout(() => controller.abort(), timeout);
9
9
  const startTime = performance.now();
@@ -59,5 +59,4 @@ function restInfo() {
59
59
  });
60
60
  }
61
61
 
62
- // Init basic info from board
63
- // restInfo();
62
+ // Designed by BxNxM |/|/|/|/