micrOSDevToolKit 2.19.0__py3-none-any.whl → 2.21.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.
Potentially problematic release.
This version of micrOSDevToolKit might be problematic. Click here for more details.
- micrOS/release_info/micrOS_ReleaseInfo/system_analysis_sum.json +35 -35
- micrOS/source/Common.py +5 -13
- micrOS/source/Config.py +5 -2
- micrOS/source/Espnow.py +101 -45
- micrOS/source/Files.py +50 -23
- micrOS/source/InterConnect.py +10 -5
- micrOS/source/Pacman.py +141 -0
- micrOS/source/Shell.py +1 -1
- micrOS/source/Tasks.py +59 -54
- micrOS/source/modules/LM_buzzer.py +1 -4
- micrOS/source/modules/LM_cct.py +2 -4
- micrOS/source/modules/LM_dimmer.py +1 -2
- micrOS/source/modules/LM_distance.py +1 -3
- micrOS/source/modules/LM_i2s_mic.py +1 -2
- micrOS/source/modules/LM_keychain.py +1 -2
- micrOS/source/modules/LM_light_sensor.py +1 -4
- micrOS/source/modules/LM_mqtt_client.py +13 -10
- micrOS/source/modules/LM_neopixel.py +1 -2
- micrOS/source/modules/LM_oled_ui.py +39 -41
- micrOS/source/modules/LM_oledui.py +58 -89
- micrOS/source/modules/LM_pacman.py +36 -44
- micrOS/source/modules/LM_presence.py +1 -2
- micrOS/source/modules/LM_rest.py +1 -2
- micrOS/source/modules/LM_rgb.py +1 -2
- micrOS/source/modules/LM_roboarm.py +3 -4
- micrOS/source/modules/LM_robustness.py +1 -2
- micrOS/source/modules/LM_telegram.py +1 -2
- micrOS/source/urequests.py +1 -1
- {microsdevtoolkit-2.19.0.dist-info → microsdevtoolkit-2.21.0.dist-info}/METADATA +153 -214
- {microsdevtoolkit-2.19.0.dist-info → microsdevtoolkit-2.21.0.dist-info}/RECORD +67 -67
- toolkit/DevEnvOTA.py +2 -2
- toolkit/DevEnvUSB.py +1 -1
- toolkit/dashboard_apps/SystemTest.py +17 -14
- toolkit/lib/micrOSClient.py +37 -15
- toolkit/lib/micrOSClientHistory.py +35 -1
- toolkit/simulator_lib/__pycache__/uos.cpython-312.pyc +0 -0
- toolkit/simulator_lib/uos.py +1 -0
- toolkit/workspace/precompiled/Common.mpy +0 -0
- toolkit/workspace/precompiled/Config.mpy +0 -0
- toolkit/workspace/precompiled/Espnow.mpy +0 -0
- toolkit/workspace/precompiled/Files.mpy +0 -0
- toolkit/workspace/precompiled/InterConnect.mpy +0 -0
- toolkit/workspace/precompiled/Pacman.mpy +0 -0
- toolkit/workspace/precompiled/Shell.mpy +0 -0
- toolkit/workspace/precompiled/Tasks.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_buzzer.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_cct.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_dimmer.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_distance.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_i2s_mic.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_keychain.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_light_sensor.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_mqtt_client.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_neopixel.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_oled_ui.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_oledui.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_pacman.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_presence.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_rest.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_rgb.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_roboarm.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_robustness.py +1 -2
- toolkit/workspace/precompiled/modules/LM_telegram.mpy +0 -0
- micrOS/source/modules/LM_pet_feeder.py +0 -78
- toolkit/workspace/precompiled/modules/LM_pet_feeder.py +0 -78
- {microsdevtoolkit-2.19.0.data → microsdevtoolkit-2.21.0.data}/scripts/devToolKit.py +0 -0
- {microsdevtoolkit-2.19.0.dist-info → microsdevtoolkit-2.21.0.dist-info}/WHEEL +0 -0
- {microsdevtoolkit-2.19.0.dist-info → microsdevtoolkit-2.21.0.dist-info}/licenses/LICENSE +0 -0
- {microsdevtoolkit-2.19.0.dist-info → microsdevtoolkit-2.21.0.dist-info}/top_level.txt +0 -0
|
@@ -123,8 +123,8 @@ def publish(topic: str, message: str, retain: bool = False):
|
|
|
123
123
|
:return: Status message string.
|
|
124
124
|
"""
|
|
125
125
|
unique_tag = f'mqtt.publish.{topic}.{time.ticks_ms()}'
|
|
126
|
-
state = micro_task(tag=unique_tag, task=_publish(unique_tag, message, topic, retain))
|
|
127
|
-
return f"Message was sent {state}"
|
|
126
|
+
state:dict = micro_task(tag=unique_tag, task=_publish(unique_tag, message, topic, retain))
|
|
127
|
+
return f"Message was sent ({list(state.values())[0]})"
|
|
128
128
|
|
|
129
129
|
|
|
130
130
|
####################
|
|
@@ -142,8 +142,8 @@ async def _up():
|
|
|
142
142
|
my_task.out = "Wait"
|
|
143
143
|
await MQTT.CLIENT.up.wait()
|
|
144
144
|
MQTT.CLIENT.up.clear()
|
|
145
|
-
state = micro_task(tag=MQTT.SUB_TASK, task=_subscribe(MQTT.DEFAULT_TOPIC))
|
|
146
|
-
my_task.out = f"Re-Subscription {state}"
|
|
145
|
+
state:dict = micro_task(tag=MQTT.SUB_TASK, task=_subscribe(MQTT.DEFAULT_TOPIC))
|
|
146
|
+
my_task.out = f"Re-Subscription ({list(state.values())[0]})"
|
|
147
147
|
my_task.feed()
|
|
148
148
|
|
|
149
149
|
|
|
@@ -165,10 +165,14 @@ async def _init_client():
|
|
|
165
165
|
MQTT.CLIENT.up.clear()
|
|
166
166
|
|
|
167
167
|
# Initialize mqtt topics
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
syslog(f"Failed start mqtt
|
|
168
|
+
try:
|
|
169
|
+
micro_task(tag=MQTT.SUB_TASK, task=_subscribe(MQTT.DEFAULT_TOPIC))
|
|
170
|
+
except Exception as err:
|
|
171
|
+
syslog(f"Failed start mqtt subscribe: {err}")
|
|
172
|
+
try:
|
|
173
|
+
micro_task(tag=MQTT.UP_TASK, task=_up())
|
|
174
|
+
except Exception as err:
|
|
175
|
+
syslog(f"Failed start mqtt up: {err}")
|
|
172
176
|
# Async listener loop
|
|
173
177
|
await _receiver()
|
|
174
178
|
my_task.out = "Receiver closed"
|
|
@@ -230,8 +234,7 @@ def load(username: str, password: str, server_ip: str, server_port: str='1883',
|
|
|
230
234
|
MQTT.CLIENT = MQTTClient(_configure(username, password, server_ip, server_port))
|
|
231
235
|
MQTT.QOS = qos
|
|
232
236
|
|
|
233
|
-
|
|
234
|
-
return {MQTT.CLIENT_TASK: "Starting"} if state else {MQTT.CLIENT_TASK: "Already running"}
|
|
237
|
+
return micro_task(tag=MQTT.CLIENT_TASK, task=_init_client())
|
|
235
238
|
|
|
236
239
|
|
|
237
240
|
def help(widgets=False):
|
|
@@ -278,8 +278,7 @@ def transition(r=None, g=None, b=None, sec=1.0, wake=False):
|
|
|
278
278
|
# Create transition generator and calculate step_ms
|
|
279
279
|
rgb_gen, step_ms = transition_gen(r_from, r_to, g_from, g_to, b_from, b_to, interval_sec=sec)
|
|
280
280
|
# [!] ASYNC TASK CREATION [1*] with async task callback + taskID (TAG) handling
|
|
281
|
-
|
|
282
|
-
return "Starting transition" if state else "Transition already running"
|
|
281
|
+
return micro_task(tag=Data.RGB_TASK_TAG, task=_task(ms_period=step_ms, iterable=rgb_gen))
|
|
283
282
|
|
|
284
283
|
|
|
285
284
|
def random(smooth=True, max_val=255):
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
"""
|
|
2
|
+
micrOS simple OLED UI (irq or single task based refresh)
|
|
3
|
+
- with page generation
|
|
4
|
+
Designed by Marcell Ban aka BxNxM
|
|
5
|
+
"""
|
|
6
|
+
|
|
1
7
|
from Config import cfgget
|
|
2
8
|
from utime import localtime
|
|
3
9
|
from network import WLAN, STA_IF
|
|
@@ -236,8 +242,8 @@ class PageUI:
|
|
|
236
242
|
else:
|
|
237
243
|
self.page_callback_list[self.active_page]() # <== Execute page functions
|
|
238
244
|
except Exception as e:
|
|
239
|
-
PageUI.PAGE_UI_OBJ.show_msg = f"Err: {e}" # Show page error in msgbox
|
|
240
245
|
syslog(f"oled_ui render error: {e}")
|
|
246
|
+
PageUI.PAGE_UI_OBJ.show_msg = f"Err: {e}" # Show page error in msgbox
|
|
241
247
|
PageUI.DISPLAY.show()
|
|
242
248
|
self.__power_save()
|
|
243
249
|
else:
|
|
@@ -332,16 +338,17 @@ class PageUI:
|
|
|
332
338
|
#####################################
|
|
333
339
|
# PAGE GENERATORS #
|
|
334
340
|
#####################################
|
|
335
|
-
def intercon_page(self,
|
|
341
|
+
def intercon_page(self, cmd:str, run=False):
|
|
336
342
|
"""Generic interconnect page core - create multiple page with it"""
|
|
337
343
|
posx, posy = 5, 12
|
|
338
344
|
|
|
339
345
|
def _button():
|
|
346
|
+
nonlocal host, _cmd
|
|
340
347
|
# BUTTON CALLBACK - INTERCONNECT execution
|
|
341
348
|
self.open_intercons.append(host)
|
|
342
349
|
try:
|
|
343
350
|
# Send CMD to other device & show result
|
|
344
|
-
state, data_meta = exec_cmd(
|
|
351
|
+
state, data_meta = exec_cmd(_cmd, jsonify=True)
|
|
345
352
|
if state:
|
|
346
353
|
self.cmd_task_tag = list(data_meta.keys())[0]
|
|
347
354
|
verdict = list(data_meta.values())[0]
|
|
@@ -354,21 +361,24 @@ class PageUI:
|
|
|
354
361
|
self.open_intercons.remove(host)
|
|
355
362
|
|
|
356
363
|
# Check open host connection
|
|
357
|
-
|
|
358
|
-
|
|
364
|
+
_cmd = cmd.strip().split()
|
|
365
|
+
host = _cmd[-1].replace(">", "").replace("&", "")
|
|
359
366
|
# Draw host + cmd details
|
|
360
|
-
PageUI.DISPLAY.text(
|
|
361
|
-
PageUI.DISPLAY.text(
|
|
367
|
+
PageUI.DISPLAY.text(' '.join(_cmd[0:-1]), 0, posy)
|
|
368
|
+
PageUI.DISPLAY.text(_cmd[-1], posx, posy+10)
|
|
369
|
+
self._cmd_text(posx, posy + 10)
|
|
370
|
+
|
|
362
371
|
# Update display output with retrieved task result (by TaskID)
|
|
363
372
|
if self.cmd_task_tag is not None:
|
|
364
373
|
task_buffer = manage_task(self.cmd_task_tag, 'show').replace(' ', '')
|
|
365
374
|
if task_buffer is not None and len(task_buffer) > 0:
|
|
366
375
|
# Set display out to task buffered data
|
|
367
376
|
self.cmd_out = task_buffer
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
377
|
+
if not manage_task(self.cmd_task_tag, 'isbusy'):
|
|
378
|
+
# Kill task - clean
|
|
379
|
+
manage_task(self.cmd_task_tag, 'kill')
|
|
380
|
+
# data gathered - remove tag - skip re-read
|
|
381
|
+
self.cmd_task_tag = None
|
|
372
382
|
# Show self.cmd_out value on display
|
|
373
383
|
self._cmd_text(posx, posy+10)
|
|
374
384
|
# Run button event at page init
|
|
@@ -378,7 +388,7 @@ class PageUI:
|
|
|
378
388
|
# Set button press callback (+draw button)
|
|
379
389
|
self.set_press_callback(_button)
|
|
380
390
|
|
|
381
|
-
def cmd_call_page(self, cmd, run=False):
|
|
391
|
+
def cmd_call_page(self, cmd:str, run=False):
|
|
382
392
|
"""Generic LoadModule execution page core - create multiple page with it"""
|
|
383
393
|
posx, posy = 5, 12
|
|
384
394
|
|
|
@@ -429,8 +439,14 @@ def _intercon_cache(line_limit=3):
|
|
|
429
439
|
cache = hosts()["intercon"]
|
|
430
440
|
if sum([1 for _ in cache]) > 0:
|
|
431
441
|
for key, val in cache.items():
|
|
432
|
-
|
|
433
|
-
|
|
442
|
+
if '.' in key:
|
|
443
|
+
# IP splitting
|
|
444
|
+
key = key.split('.')[0]
|
|
445
|
+
val = '.'.join(val.split('.')[-2:])
|
|
446
|
+
else:
|
|
447
|
+
# MAC splitting
|
|
448
|
+
key = key.split(':')[0]
|
|
449
|
+
val = ':'.join(val.split(':')[-2:])
|
|
434
450
|
PageUI.DISPLAY.text(f" {val} {key}", 0, line_start+(line_cnt*10))
|
|
435
451
|
line_cnt += 1
|
|
436
452
|
if line_cnt > line_limit:
|
|
@@ -514,8 +530,7 @@ def msgbox(msg='micrOS msg'):
|
|
|
514
530
|
PageUI.PAGE_UI_OBJ.render_page()
|
|
515
531
|
return 'Show msg'
|
|
516
532
|
|
|
517
|
-
|
|
518
|
-
def intercon_genpage(cmd:str=None, run=False):
|
|
533
|
+
def genpage(cmd:str=None, run=False):
|
|
519
534
|
"""
|
|
520
535
|
Create intercon pages dynamically :)
|
|
521
536
|
- based on cmd value.
|
|
@@ -523,31 +538,15 @@ def intercon_genpage(cmd:str=None, run=False):
|
|
|
523
538
|
:param run: run button event at page init: True/False
|
|
524
539
|
:return: page creation verdict
|
|
525
540
|
"""
|
|
526
|
-
raw = cmd.split()
|
|
527
|
-
host = raw[0]
|
|
528
|
-
cmd = raw[1:]
|
|
529
|
-
try:
|
|
530
|
-
# Create page for intercon command
|
|
531
|
-
PageUI.PAGE_UI_OBJ.add_page(lambda: PageUI.PAGE_UI_OBJ.intercon_page(host, cmd, run=run))
|
|
532
|
-
except Exception as e:
|
|
533
|
-
syslog(f'[ERR] intercon_genpage: {e}')
|
|
534
|
-
return str(e)
|
|
535
|
-
return True
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
def cmd_genpage(cmd:str=None, run=False):
|
|
539
|
-
"""
|
|
540
|
-
Create load module execution pages dynamically :)
|
|
541
|
-
- based on cmd value: load_module function (args)
|
|
542
|
-
:param cmd: 'load_module function (args)' string
|
|
543
|
-
:param run: run button event at page init: True/False
|
|
544
|
-
:return: page creation verdict
|
|
545
|
-
"""
|
|
546
541
|
try:
|
|
547
|
-
|
|
548
|
-
|
|
542
|
+
if ">>" in cmd or "&" in cmd:
|
|
543
|
+
# Create page for intercon/task background command
|
|
544
|
+
PageUI.PAGE_UI_OBJ.add_page(lambda: PageUI.PAGE_UI_OBJ.intercon_page(cmd, run=run))
|
|
545
|
+
else:
|
|
546
|
+
# Create page for realtime command
|
|
547
|
+
PageUI.PAGE_UI_OBJ.add_page(lambda: PageUI.PAGE_UI_OBJ.cmd_call_page(cmd, run=run))
|
|
549
548
|
except Exception as e:
|
|
550
|
-
syslog(f'[ERR]
|
|
549
|
+
syslog(f'[ERR] genpage: {e}')
|
|
551
550
|
return str(e)
|
|
552
551
|
return True
|
|
553
552
|
|
|
@@ -598,6 +597,5 @@ def help(widgets=False):
|
|
|
598
597
|
'draw',
|
|
599
598
|
'BUTTON control cmd=<prev,press,next,on,off>',
|
|
600
599
|
'msgbox "msg"',
|
|
601
|
-
'
|
|
602
|
-
'cmd_genpage "cmd" run=False',
|
|
600
|
+
'genpage "cmd" run=False',
|
|
603
601
|
'pinmap'), widgets=widgets)
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
"""
|
|
2
|
+
micrOS multitask OLED UI
|
|
3
|
+
- with page generation
|
|
4
|
+
Designed by Marcell Ban aka BxNxM
|
|
5
|
+
"""
|
|
1
6
|
from utime import localtime, ticks_ms, ticks_diff, sleep_ms
|
|
2
7
|
from Common import syslog, micro_task, manage_task, exec_cmd
|
|
3
8
|
from Types import resolve
|
|
@@ -121,8 +126,7 @@ class Frame(BaseFrame):
|
|
|
121
126
|
"""
|
|
122
127
|
# [!] ASYNC TASK CREATION [1*] with async task callback + taskID (TAG) handling
|
|
123
128
|
self._taskid = f"oledui.{tid}"
|
|
124
|
-
|
|
125
|
-
return "Starting" if state else "Already running"
|
|
129
|
+
return micro_task(tag=self._taskid, task=self._task(period_ms=period_ms))
|
|
126
130
|
|
|
127
131
|
def hover(self):
|
|
128
132
|
"""
|
|
@@ -486,8 +490,7 @@ class ScreenSaver(BaseFrame):
|
|
|
486
490
|
def run(self, fps=10):
|
|
487
491
|
# [!] ASYNC TASK CREATION [1*] with async task callback + taskID (TAG) handling
|
|
488
492
|
period_ms = int(1000/fps)
|
|
489
|
-
|
|
490
|
-
return "Starting" if state else "Already running"
|
|
493
|
+
return micro_task(tag="oledui.anim", task=self._task(period_ms))
|
|
491
494
|
|
|
492
495
|
def cancel(self):
|
|
493
496
|
if self.running:
|
|
@@ -740,79 +743,59 @@ class PageUI:
|
|
|
740
743
|
:param y: frame y
|
|
741
744
|
"""
|
|
742
745
|
x, y = x+2, y+4
|
|
743
|
-
def _execute(display, w, h, x, y):
|
|
744
|
-
nonlocal cmd
|
|
745
|
-
try:
|
|
746
|
-
cmd_list = cmd.strip().split()
|
|
747
|
-
# Send CMD to other device & show result
|
|
748
|
-
state, out = exec_cmd(cmd_list)
|
|
749
|
-
cmd_out = out.strip()
|
|
750
|
-
except Exception as e:
|
|
751
|
-
cmd_out = str(e)
|
|
752
|
-
self.app_frame.press_output = cmd_out
|
|
753
|
-
PageUI.write_lines(cmd_out, display, x, y + 15)
|
|
754
|
-
|
|
755
|
-
display.text(cmd, x, y)
|
|
756
|
-
if run:
|
|
757
|
-
_execute(display, w, h, x, y)
|
|
758
|
-
else:
|
|
759
|
-
self._press_indicator(display, w, h, x, y)
|
|
760
|
-
PageUI.write_lines(self.app_frame.press_output, display, x, y + 15)
|
|
761
|
-
# Return "press" callback, mandatory input parameters: display, w, h, x, y
|
|
762
|
-
return {"press": _execute}
|
|
763
|
-
return
|
|
764
746
|
|
|
747
|
+
def _display_output():
|
|
748
|
+
nonlocal x, y, display
|
|
749
|
+
if self._cmd_task_tag is None:
|
|
750
|
+
# Display cached data
|
|
751
|
+
PageUI.write_lines(self.app_frame.press_output, display, x, y + 20)
|
|
752
|
+
return
|
|
753
|
+
task_buffer = manage_task(self._cmd_task_tag, 'show').replace(' ', '')
|
|
754
|
+
if task_buffer is not None and len(task_buffer) > 0:
|
|
755
|
+
# Update display out to task buffered data
|
|
756
|
+
self.app_frame.press_output = task_buffer
|
|
757
|
+
if not manage_task(self._cmd_task_tag, 'isbusy'):
|
|
758
|
+
# data gathered - remove tag - skip re-read
|
|
759
|
+
self._cmd_task_tag = None
|
|
760
|
+
# Display task cached data
|
|
761
|
+
PageUI.write_lines(self.app_frame.press_output, display, x, y + 20)
|
|
765
762
|
|
|
766
|
-
def intercon_exec_page(self, host, cmd, run, display, w, h, x, y):
|
|
767
|
-
"""
|
|
768
|
-
:param host: hostname or IP address of a device
|
|
769
|
-
:param cmd: load module string command
|
|
770
|
-
:param run: auto-run command (every page refresh)
|
|
771
|
-
:param display: display instance
|
|
772
|
-
:param h: frame h
|
|
773
|
-
:param w: frame w
|
|
774
|
-
:param x: frame x
|
|
775
|
-
:param y: frame y
|
|
776
|
-
"""
|
|
777
|
-
x, y = x+2, y+4
|
|
778
763
|
def _execute(display, w, h, x, y):
|
|
779
|
-
nonlocal
|
|
780
|
-
# Check open host connection
|
|
764
|
+
nonlocal cmd, run
|
|
781
765
|
try:
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
if
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
if
|
|
788
|
-
self.
|
|
766
|
+
cmd_list = cmd.strip().split()
|
|
767
|
+
# TASK mode: background execution, intercon: >> OR task: &
|
|
768
|
+
if '>>' in cmd_list[-1] or '&' in cmd_list[-1]:
|
|
769
|
+
# BACKGROUND: EXECUTE COMMAND
|
|
770
|
+
state, out = exec_cmd(cmd_list, jsonify=True) if self._cmd_task_tag is None else (False, "skip...")
|
|
771
|
+
if state:
|
|
772
|
+
self._cmd_task_tag = list(out.keys())[0]
|
|
773
|
+
buffer = manage_task(self._cmd_task_tag, 'show').replace(' ', '')
|
|
774
|
+
if buffer is not None and len(buffer) > 0:
|
|
775
|
+
self.app_frame.press_output = buffer
|
|
789
776
|
else:
|
|
790
|
-
|
|
777
|
+
# REALTIME mode: get command execution result
|
|
778
|
+
state, out = exec_cmd(cmd_list, jsonify=True)
|
|
779
|
+
self.app_frame.press_output = str(out)
|
|
791
780
|
except Exception as e:
|
|
792
781
|
self.app_frame.press_output = str(e)
|
|
782
|
+
# Print and cache output to display
|
|
783
|
+
PageUI.write_lines(self.app_frame.press_output, display, x, y+20)
|
|
793
784
|
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
if task_buffer is not None and len(task_buffer) > 0:
|
|
799
|
-
# Set display out to task buffered data
|
|
800
|
-
self.app_frame.press_output = task_buffer
|
|
801
|
-
# data gathered - remove tag - skip re-read
|
|
802
|
-
self._cmd_task_tag = None
|
|
803
|
-
PageUI.write_lines(self.app_frame.press_output, display, x, y + 20, line_limit=2)
|
|
804
|
-
|
|
805
|
-
PageUI.write_lines(f"{host.split(".")[0]}:{' '.join(cmd)}", display, x, y, line_limit=2)
|
|
785
|
+
# Write command header line and buffered output
|
|
786
|
+
PageUI.write_lines(cmd, display, x, y, line_limit=2)
|
|
787
|
+
_display_output()
|
|
788
|
+
# RUN command
|
|
806
789
|
if run:
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
_read_buffer()
|
|
790
|
+
# Automatic Execution Mode (in page refresh time)
|
|
791
|
+
_execute(display, w, h, x, y)
|
|
792
|
+
return None
|
|
793
|
+
# Button Press Execution Mode (callback)
|
|
812
794
|
self._press_indicator(display, w, h, x, y)
|
|
813
795
|
# Return "press" callback, mandatory input parameters: display, w, h, x, y
|
|
814
796
|
return {"press": _execute}
|
|
815
797
|
|
|
798
|
+
|
|
816
799
|
#################################################################################
|
|
817
800
|
# Page function #
|
|
818
801
|
#################################################################################
|
|
@@ -835,8 +818,14 @@ def _intercon_nodes_page(display, w, h, x, y):
|
|
|
835
818
|
cache = hosts()["intercon"]
|
|
836
819
|
if sum([1 for _ in cache]) > 0:
|
|
837
820
|
for key, val in cache.items():
|
|
838
|
-
|
|
839
|
-
|
|
821
|
+
if '.' in key:
|
|
822
|
+
# IP splitting
|
|
823
|
+
key = key.split('.')[0]
|
|
824
|
+
val = '.'.join(val.split('.')[-2:])
|
|
825
|
+
else:
|
|
826
|
+
# MAC splitting
|
|
827
|
+
key = key.split(':')[0]
|
|
828
|
+
val = ':'.join(val.split(':')[-2:])
|
|
840
829
|
display.text(f" {val} {key}", x, line_start + (line_cnt * 10))
|
|
841
830
|
line_cnt += 1
|
|
842
831
|
if line_cnt > line_limit:
|
|
@@ -902,7 +891,7 @@ def cursor(x, y):
|
|
|
902
891
|
return "Set cursor position"
|
|
903
892
|
|
|
904
893
|
|
|
905
|
-
def
|
|
894
|
+
def genpage(cmd=None, run=False):
|
|
906
895
|
"""
|
|
907
896
|
Create load module execution pages dynamically :)
|
|
908
897
|
- based on cmd value: load_module function (args)
|
|
@@ -917,30 +906,11 @@ def cmd_genpage(cmd=None, run=False):
|
|
|
917
906
|
# Create page for intercon command
|
|
918
907
|
PageUI.INSTANCE.add_page(lambda display, w, h, x, y: PageUI.INSTANCE.lm_exec_page(cmd, run, display, w, h, x, y))
|
|
919
908
|
except Exception as e:
|
|
920
|
-
syslog(f'[ERR]
|
|
909
|
+
syslog(f'[ERR] genpage: {e}')
|
|
921
910
|
return str(e)
|
|
922
911
|
return True
|
|
923
912
|
|
|
924
913
|
|
|
925
|
-
def intercon_genpage(cmd=None, run=False):
|
|
926
|
-
"""
|
|
927
|
-
Create intercon pages dynamically :)
|
|
928
|
-
- based on cmd value.
|
|
929
|
-
:param cmd: 'host hello' or 'host system clock'
|
|
930
|
-
:param run: run button event at page init: True/False
|
|
931
|
-
:return: page creation verdict
|
|
932
|
-
"""
|
|
933
|
-
raw = cmd.split()
|
|
934
|
-
host = raw[0]
|
|
935
|
-
cmd = raw[1:]
|
|
936
|
-
try:
|
|
937
|
-
# Create page for intercon command
|
|
938
|
-
PageUI.INSTANCE.add_page(lambda display, w, h, x, y: PageUI.INSTANCE.intercon_exec_page(host, cmd, run, display, w, h, x, y))
|
|
939
|
-
except Exception as e:
|
|
940
|
-
syslog(f'[ERR] intercon_genpage: {e}')
|
|
941
|
-
return str(e)
|
|
942
|
-
return True
|
|
943
|
-
|
|
944
914
|
def add_page(page_callback):
|
|
945
915
|
"""
|
|
946
916
|
[LM] Create page from load module with callback function
|
|
@@ -965,6 +935,5 @@ def help(widgets=False):
|
|
|
965
935
|
"BUTTON control cmd=<prev,press,next,on,off>",
|
|
966
936
|
"BUTTON debug", "cursor x y",
|
|
967
937
|
"popup msg='text'", "cancel_popup",
|
|
968
|
-
"
|
|
969
|
-
"intercon_genpage 'host cmd' run=False"),
|
|
938
|
+
"genpage cmd='system clock'"),
|
|
970
939
|
widgets=widgets)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from sys import modules
|
|
2
2
|
from Common import socket_stream
|
|
3
|
-
from Files import is_protected, list_fs, ilist_fs,
|
|
3
|
+
from Files import is_protected, list_fs, ilist_fs, remove_file, remove_dir, OSPath, path_join
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
#############################################
|
|
@@ -31,13 +31,22 @@ def ls(path="/", content='*', raw=False, select='*', core=False):
|
|
|
31
31
|
return lines
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
def rm(path,
|
|
34
|
+
def rm(path, force=False):
|
|
35
35
|
"""
|
|
36
36
|
Linux like rm command - delete app resources and folders
|
|
37
37
|
:param path: app resource name/path, ex.: LM_robustness.py
|
|
38
|
-
:param
|
|
38
|
+
:param force: bypasses protection check - sudo mode
|
|
39
39
|
"""
|
|
40
|
-
return
|
|
40
|
+
return remove_file(path, force)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def rmdir(path, force=False):
|
|
44
|
+
"""
|
|
45
|
+
Linux like rmdir command for directory deletion
|
|
46
|
+
:param path: app resource folder path, ex.: /lib/myapp
|
|
47
|
+
:param force: bypasses protection check - sudo mode
|
|
48
|
+
"""
|
|
49
|
+
return remove_dir(path, force)
|
|
41
50
|
|
|
42
51
|
|
|
43
52
|
def dirtree(path="/", raw=False, core=False):
|
|
@@ -64,44 +73,26 @@ def cat(path):
|
|
|
64
73
|
return content
|
|
65
74
|
|
|
66
75
|
|
|
67
|
-
def download(
|
|
76
|
+
def download(ref=None):
|
|
68
77
|
"""
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
78
|
+
Unified mip-based downloader for micrOS.
|
|
79
|
+
Automatically detects:
|
|
80
|
+
1. Official MicroPython packages (from https://micropython.org/pi/v2)
|
|
81
|
+
Example: pacman download "umqtt.simple"
|
|
82
|
+
2. Single-file load modules (LM_/IO_ names or URLs)
|
|
83
|
+
Example: pacman download "https://github.com/BxNxM/micrOS/blob/master/toolkit/workspace/precompiled/modules/LM_rgb.mpy"
|
|
84
|
+
pacman download "github.com/BxNxM/micrOS/blob/master/toolkit/workspace/precompiled/modules/LM_rgb.mpy"
|
|
85
|
+
3. GitHub packages (folders via tree/blob URLs or github: form)
|
|
86
|
+
Example: pacman download "github:peterhinch/micropython-mqtt"
|
|
87
|
+
pacman download "https://github.com/peterhinch/micropython-mqtt/tree/master"
|
|
88
|
+
pacman download "https://github.com/peterhinch/micropython-mqtt/blob/master/package.json"
|
|
89
|
+
pacman download "https://github.com/peterhinch/micropython-mqtt"
|
|
90
|
+
[NOK] pacman download "https://github.com/basanovase/sim7600/tree/main/sim7600" -> Package not found: github:basanovase/sim7600/package.json
|
|
91
|
+
4. Install from local /config/requirements.txt file
|
|
92
|
+
Example: pacman download "requirements.txt"
|
|
72
93
|
"""
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
try:
|
|
76
|
-
verdict += f"Install {url}\n"
|
|
77
|
-
if target is None:
|
|
78
|
-
install(url) # Default download: /lib
|
|
79
|
-
else:
|
|
80
|
-
install(url, target=target) # Custom target
|
|
81
|
-
verdict += "\n|- Done"
|
|
82
|
-
except Exception as e:
|
|
83
|
-
verdict += f"|- Cannot install: {url}\n{e}"
|
|
84
|
-
return verdict
|
|
85
|
-
|
|
86
|
-
from mip import install
|
|
87
|
-
verdict = ""
|
|
88
|
-
if url is None and package is None:
|
|
89
|
-
return "Nothing to download, url=None package=None"
|
|
90
|
-
if package is None:
|
|
91
|
-
verdict += "Install from GitHub URL"
|
|
92
|
-
base_url = "https://raw.githubusercontent.com/"
|
|
93
|
-
file_name = url.split("/")[-1]
|
|
94
|
-
if not(file_name.endswith("py") and file_name.startswith("LM_")):
|
|
95
|
-
return "Invalid file name in url ending, hint: /LM_*.mpy or /LM_*.py"
|
|
96
|
-
# Convert GitHub URL to raw content URL
|
|
97
|
-
if "github.com" in url and "blob" in url:
|
|
98
|
-
url = url.replace("https://github.com/", base_url).replace("/blob", "")
|
|
99
|
-
else:
|
|
100
|
-
url = f"{base_url}{url}"
|
|
101
|
-
return _install(target=OSPath.MODULES) # Install module from Github URL
|
|
102
|
-
url = package
|
|
103
|
-
return _install() # Install official package
|
|
104
|
-
|
|
94
|
+
from Pacman import download as pm_download
|
|
95
|
+
return pm_download(ref)
|
|
105
96
|
|
|
106
97
|
def del_duplicates(migrate=True):
|
|
107
98
|
"""
|
|
@@ -119,7 +110,7 @@ def del_duplicates(migrate=True):
|
|
|
119
110
|
if m in py and m != 'main':
|
|
120
111
|
to_delete = f'{m}.py'
|
|
121
112
|
try:
|
|
122
|
-
verdict =
|
|
113
|
+
verdict = remove_file(path_join(modules_path, to_delete))
|
|
123
114
|
except:
|
|
124
115
|
verdict = "n/a"
|
|
125
116
|
state = False
|
|
@@ -130,7 +121,7 @@ def del_duplicates(migrate=True):
|
|
|
130
121
|
def _migrate_from_root(_rf):
|
|
131
122
|
nonlocal _deleted, files
|
|
132
123
|
if _rf in files:
|
|
133
|
-
|
|
124
|
+
remove_file(path_join(OSPath._ROOT, _rf))
|
|
134
125
|
if _rf in ("LM_pacman.mpy", "LM_system.mpy"):
|
|
135
126
|
# Delete protected LMs from root
|
|
136
127
|
remove(path_join(OSPath._ROOT, _rf))
|
|
@@ -188,7 +179,7 @@ def cachedump(delete=None, msgobj=None):
|
|
|
188
179
|
# Remove given cache file
|
|
189
180
|
try:
|
|
190
181
|
delete_cache = path_join(data_dir, f"{delete}.cache")
|
|
191
|
-
verdict =
|
|
182
|
+
verdict = remove_file(delete_cache)
|
|
192
183
|
return f'{delete_cache} delete done.: {verdict}'
|
|
193
184
|
except:
|
|
194
185
|
return f'{delete}.cache not exists'
|
|
@@ -252,7 +243,7 @@ def delmod(mod):
|
|
|
252
243
|
else:
|
|
253
244
|
return f'Invalid {mod}, must ends with .py or .mpy'
|
|
254
245
|
try:
|
|
255
|
-
return
|
|
246
|
+
return remove_file(path_join(OSPath.MODULES, to_remove))
|
|
256
247
|
except Exception as e:
|
|
257
248
|
return f'Cannot delete: {mod}: {e}'
|
|
258
249
|
|
|
@@ -286,5 +277,6 @@ def help(widgets=False):
|
|
|
286
277
|
'micros_checksum',
|
|
287
278
|
'ls path="/" content="*/f/d" select="*/LM/IO"',
|
|
288
279
|
'rm <path>',
|
|
280
|
+
'rmdir <path>',
|
|
289
281
|
'dirtree path="/"',
|
|
290
282
|
'makedir <path>')
|
|
@@ -213,8 +213,7 @@ def motion_trig(sample_ms=15, buff_size=10):
|
|
|
213
213
|
|
|
214
214
|
# [3] Start mic sampling in async task
|
|
215
215
|
# [!] ASYNC TASK CREATION [1*] with async task callback + taskID (TAG) handling
|
|
216
|
-
|
|
217
|
-
return "Starting" if state else "Already running"
|
|
216
|
+
return micro_task(tag=Data.TASK_TAG, task=__task(ms_period=sample_ms, buff_size=buff_size))
|
|
218
217
|
|
|
219
218
|
|
|
220
219
|
def subscribe_intercon(on, off):
|
micrOS/source/modules/LM_rest.py
CHANGED
|
@@ -66,8 +66,7 @@ def aurl(subdomain):
|
|
|
66
66
|
tag = "rest." + subdomain.replace("http://", '').replace("https://", '')
|
|
67
67
|
if len(tag) > 50:
|
|
68
68
|
tag = tag[0:50]
|
|
69
|
-
|
|
70
|
-
return f"Starting" if state else f"Already running"
|
|
69
|
+
return micro_task(tag=tag, task=__task(subdomain, tag))
|
|
71
70
|
|
|
72
71
|
|
|
73
72
|
def help(widgets=False):
|
micrOS/source/modules/LM_rgb.py
CHANGED
|
@@ -246,8 +246,7 @@ def transition(r=None, g=None, b=None, sec=1.0, wake=False):
|
|
|
246
246
|
# Create transition generator and calculate step_ms
|
|
247
247
|
rgb_gen, step_ms = transition_gen(r_from, r, g_from, g, b_from, b, interval_sec=sec)
|
|
248
248
|
# [!] ASYNC TASK CREATION [1*] with async task callback + taskID (TAG) handling
|
|
249
|
-
|
|
250
|
-
return "Starting transition" if state else "Transition already running"
|
|
249
|
+
return micro_task(tag=Data.RGB_TASK_TAG, task=_task(ms_period=step_ms, iterable=rgb_gen))
|
|
251
250
|
|
|
252
251
|
|
|
253
252
|
def random(smooth=True, max_val=1000):
|
|
@@ -204,11 +204,10 @@ def play(*args, s=None, delay=None, deinit=True):
|
|
|
204
204
|
|
|
205
205
|
# Start play - servo XY in async task
|
|
206
206
|
# [!] ASYNC TASK CREATION [1*] with async task callback + taskID (TAG) handling
|
|
207
|
-
state = micro_task(tag=RoboArm.PLAY_TAG, task=_play(args, deinit, delay))
|
|
208
|
-
if state:
|
|
209
|
-
return 'Play: {} steps'.format(int(len(args)/2))
|
|
210
|
-
return 'Play - already running'
|
|
211
207
|
|
|
208
|
+
state:dict = micro_task(tag=RoboArm.PLAY_TAG, task=_play(args, deinit, delay))
|
|
209
|
+
state.update({"Play steps": int(len(args)/2)})
|
|
210
|
+
return state
|
|
212
211
|
|
|
213
212
|
def record(clean=False, rec_limit=8):
|
|
214
213
|
"""
|
|
@@ -83,8 +83,7 @@ def create_task():
|
|
|
83
83
|
"""
|
|
84
84
|
# [!] ASYNC TASK CREATION [1*] with async task callback + taskID (TAG) handling
|
|
85
85
|
task_tag = "microtask.run"
|
|
86
|
-
|
|
87
|
-
return "Starting" if state else "Already running"
|
|
86
|
+
return micro_task(tag=task_tag, task=__task(tag=task_tag, period_ms=5))
|
|
88
87
|
|
|
89
88
|
|
|
90
89
|
@micro_task("microtask", _wrap=True)
|
|
@@ -362,8 +362,7 @@ def receiver_loop(period=3):
|
|
|
362
362
|
if Telegram.INSTANCE is None:
|
|
363
363
|
return "Network unavailable."
|
|
364
364
|
tag = 'telegram.server_bot'
|
|
365
|
-
|
|
366
|
-
return {tag: "Starting"} if state else {tag: "Already running"}
|
|
365
|
+
return micro_task(tag=tag, task=Telegram.server_bot(tag=tag, period=period))
|
|
367
366
|
|
|
368
367
|
|
|
369
368
|
def help(widgets=False):
|
micrOS/source/urequests.py
CHANGED
|
@@ -282,7 +282,7 @@ async def apost(url, data=None, json=None, headers:dict=None, sock_size=256, jso
|
|
|
282
282
|
return await arequest('POST', url, data=data, json=json, headers=headers, sock_size=sock_size, jsonify=jsonify)
|
|
283
283
|
|
|
284
284
|
|
|
285
|
-
def host_cache():
|
|
285
|
+
def host_cache() -> dict:
|
|
286
286
|
"""
|
|
287
287
|
Return address cache
|
|
288
288
|
"""
|