micrOSDevToolKit 2.10.6__py3-none-any.whl → 2.13.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.
- env/driver_cp210x/macOS_VCP_Driver/SiLabsUSBDriverDisk.dmg +0 -0
- env/driver_cp210x/macOS_VCP_Driver/macOS_VCP_Driver_Release_Notes.txt +17 -1
- micrOS/micropython/esp32c6-GENERIC-20250415-v1.25.0.bin +0 -0
- micrOS/micropython/esp32s3-4MBflash-20241129-v1.24.1.bin +0 -0
- micrOS/release_info/micrOS_ReleaseInfo/system_analysis_sum.json +57 -61
- micrOS/source/Common.py +286 -91
- micrOS/source/Config.py +7 -7
- micrOS/source/Debug.py +50 -94
- micrOS/source/Espnow.py +7 -7
- micrOS/source/Files.py +23 -2
- micrOS/source/Hooks.py +62 -19
- micrOS/source/IO_esp32c6.py +16 -0
- micrOS/source/IO_esp32s3.py +37 -1
- micrOS/source/IO_m5stamp.py +35 -1
- micrOS/source/IO_qtpy.py +22 -17
- micrOS/source/IO_s3matrix.py +21 -0
- micrOS/source/IO_tinypico.py +38 -0
- micrOS/source/InterConnect.py +5 -5
- micrOS/source/Interrupts.py +2 -2
- micrOS/source/LM_VL53L0X.py +1 -1
- micrOS/source/LM_buzzer.py +6 -7
- micrOS/source/LM_cct.py +6 -5
- micrOS/source/LM_dashboard_be.py +2 -2
- micrOS/source/LM_dimmer.py +6 -5
- micrOS/source/LM_espnow.py +15 -10
- micrOS/source/LM_i2c.py +3 -2
- micrOS/source/LM_neoeffects.py +173 -230
- micrOS/source/LM_neomatrix.py +335 -0
- micrOS/source/LM_neopixel.py +10 -10
- micrOS/source/LM_pacman.py +40 -23
- micrOS/source/LM_qmi8658.py +204 -0
- micrOS/source/LM_rgb.py +6 -6
- micrOS/source/LM_roboarm.py +5 -4
- micrOS/source/LM_switch.py +6 -4
- micrOS/source/LM_tcs3472.py +75 -0
- micrOS/source/LM_telegram.py +5 -4
- micrOS/source/Logger.py +47 -33
- micrOS/source/Network.py +6 -6
- micrOS/source/Notify.py +2 -2
- micrOS/source/Scheduler.py +5 -5
- micrOS/source/Server.py +6 -6
- micrOS/source/Shell.py +4 -4
- micrOS/source/Tasks.py +20 -17
- micrOS/source/Time.py +12 -10
- micrOS/source/Types.py +2 -2
- micrOS/source/Web.py +20 -13
- micrOS/source/__pycache__/Common.cpython-312.pyc +0 -0
- micrOS/source/__pycache__/Debug.cpython-312.pyc +0 -0
- micrOS/source/__pycache__/Logger.cpython-312.pyc +0 -0
- micrOS/source/__pycache__/Server.cpython-312.pyc +0 -0
- micrOS/source/micrOS.py +10 -7
- micrOS/source/micrOSloader.py +6 -6
- micrOS/source/microIO.py +8 -6
- micrOS/source/urequests.py +4 -4
- {microsdevtoolkit-2.10.6.dist-info → microsdevtoolkit-2.13.0.dist-info}/METADATA +24 -22
- {microsdevtoolkit-2.10.6.dist-info → microsdevtoolkit-2.13.0.dist-info}/RECORD +142 -132
- toolkit/DevEnvCompile.py +20 -15
- toolkit/DevEnvOTA.py +29 -8
- toolkit/DevEnvUSB.py +52 -10
- toolkit/LM_to_compile.dat +1 -0
- toolkit/MicrOSDevEnv.py +10 -2
- toolkit/MicrosFiles.py +26 -0
- toolkit/dashboard_apps/NeoEffectsDemo.py +8 -15
- toolkit/dashboard_apps/QMI8685_GYRO.py +68 -0
- toolkit/dashboard_apps/_app_base.py +2 -2
- toolkit/dashboard_apps/_gyro_visualizer.py +78 -0
- toolkit/lib/LocalMachine.py +6 -1
- toolkit/lib/file_extensions.py +9 -3
- toolkit/micrOSlint.py +3 -1
- toolkit/simulator_lib/__pycache__/IO_darwin.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/machine.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/neopixel.cpython-312.pyc +0 -0
- toolkit/simulator_lib/machine.py +0 -1
- toolkit/simulator_lib/neopixel.py +3 -2
- toolkit/socketClient.py +3 -2
- toolkit/workspace/precompiled/Common.cpython-312.pyc +0 -0
- toolkit/workspace/precompiled/Common.mpy +0 -0
- toolkit/workspace/precompiled/Config.mpy +0 -0
- toolkit/workspace/precompiled/Debug.mpy +0 -0
- toolkit/workspace/precompiled/Espnow.mpy +0 -0
- toolkit/workspace/precompiled/Files.mpy +0 -0
- toolkit/workspace/precompiled/Hooks.mpy +0 -0
- toolkit/workspace/precompiled/IO_esp32c6.mpy +0 -0
- toolkit/workspace/precompiled/IO_esp32s3.mpy +0 -0
- toolkit/workspace/precompiled/IO_m5stamp.mpy +0 -0
- toolkit/workspace/precompiled/IO_qtpy.mpy +0 -0
- toolkit/workspace/precompiled/IO_s3matrix.mpy +0 -0
- toolkit/workspace/precompiled/IO_tinypico.mpy +0 -0
- toolkit/workspace/precompiled/InterConnect.mpy +0 -0
- toolkit/workspace/precompiled/Interrupts.mpy +0 -0
- toolkit/workspace/precompiled/LM_VL53L0X.py +1 -1
- toolkit/workspace/precompiled/LM_buzzer.mpy +0 -0
- toolkit/workspace/precompiled/LM_cct.mpy +0 -0
- toolkit/workspace/precompiled/LM_dashboard_be.py +2 -2
- toolkit/workspace/precompiled/LM_dimmer.mpy +0 -0
- toolkit/workspace/precompiled/LM_espnow.py +15 -10
- toolkit/workspace/precompiled/LM_i2c.py +3 -2
- toolkit/workspace/precompiled/LM_neoeffects.mpy +0 -0
- toolkit/workspace/precompiled/LM_neomatrix.mpy +0 -0
- toolkit/workspace/precompiled/LM_neopixel.mpy +0 -0
- toolkit/workspace/precompiled/LM_pacman.mpy +0 -0
- toolkit/workspace/precompiled/LM_qmi8658.py +204 -0
- toolkit/workspace/precompiled/LM_rgb.mpy +0 -0
- toolkit/workspace/precompiled/LM_roboarm.mpy +0 -0
- toolkit/workspace/precompiled/LM_switch.mpy +0 -0
- toolkit/workspace/precompiled/LM_tcs3472.py +75 -0
- toolkit/workspace/precompiled/LM_telegram.mpy +0 -0
- toolkit/workspace/precompiled/Logger.cpython-312.pyc +0 -0
- toolkit/workspace/precompiled/Logger.mpy +0 -0
- toolkit/workspace/precompiled/Network.mpy +0 -0
- toolkit/workspace/precompiled/Notify.mpy +0 -0
- toolkit/workspace/precompiled/Scheduler.mpy +0 -0
- toolkit/workspace/precompiled/Server.cpython-312.pyc +0 -0
- toolkit/workspace/precompiled/Server.mpy +0 -0
- toolkit/workspace/precompiled/Shell.mpy +0 -0
- toolkit/workspace/precompiled/Tasks.mpy +0 -0
- toolkit/workspace/precompiled/Time.mpy +0 -0
- toolkit/workspace/precompiled/Types.mpy +0 -0
- toolkit/workspace/precompiled/Web.mpy +0 -0
- toolkit/workspace/precompiled/micrOS.mpy +0 -0
- toolkit/workspace/precompiled/micrOSloader.mpy +0 -0
- toolkit/workspace/precompiled/microIO.mpy +0 -0
- toolkit/workspace/precompiled/urequests.mpy +0 -0
- micrOS/micropython/esp32s3-20240105-v1.22.1.bin +0 -0
- micrOS/source/LM_catgame.py +0 -75
- micrOS/source/LM_demo.py +0 -97
- micrOS/source/LM_intercon.py +0 -60
- micrOS/source/LM_ph_sensor.py +0 -51
- toolkit/workspace/precompiled/LM_catgame.py +0 -75
- toolkit/workspace/precompiled/LM_demo.py +0 -97
- toolkit/workspace/precompiled/LM_intercon.mpy +0 -0
- toolkit/workspace/precompiled/LM_ph_sensor.py +0 -51
- /micrOS/micropython/{esp32s3-20241129-v1.24.1.bin → esp32s3-8MBflash-20241129-v1.24.1.bin} +0 -0
- /micrOS/source/{dashboard.html → web/dashboard.html} +0 -0
- /micrOS/source/{index.html → web/index.html} +0 -0
- /micrOS/source/{uapi.js → web/uapi.js} +0 -0
- /micrOS/source/{udashboard.js → web/udashboard.js} +0 -0
- /micrOS/source/{ustyle.css → web/ustyle.css} +0 -0
- /micrOS/source/{uwidgets.js → web/uwidgets.js} +0 -0
- /micrOS/source/{uwidgets_pro.js → web/uwidgets_pro.js} +0 -0
- {microsdevtoolkit-2.10.6.data → microsdevtoolkit-2.13.0.data}/scripts/devToolKit.py +0 -0
- {microsdevtoolkit-2.10.6.dist-info → microsdevtoolkit-2.13.0.dist-info}/WHEEL +0 -0
- {microsdevtoolkit-2.10.6.dist-info → microsdevtoolkit-2.13.0.dist-info}/licenses/LICENSE +0 -0
- {microsdevtoolkit-2.10.6.dist-info → microsdevtoolkit-2.13.0.dist-info}/top_level.txt +0 -0
- /toolkit/workspace/precompiled/{dashboard.html → web/dashboard.html} +0 -0
- /toolkit/workspace/precompiled/{index.html → web/index.html} +0 -0
- /toolkit/workspace/precompiled/{uapi.js → web/uapi.js} +0 -0
- /toolkit/workspace/precompiled/{udashboard.js → web/udashboard.js} +0 -0
- /toolkit/workspace/precompiled/{ustyle.css → web/ustyle.css} +0 -0
- /toolkit/workspace/precompiled/{uwidgets.js → web/uwidgets.js} +0 -0
- /toolkit/workspace/precompiled/{uwidgets_pro.js → web/uwidgets_pro.js} +0 -0
toolkit/DevEnvCompile.py
CHANGED
|
@@ -133,12 +133,13 @@ class Compile:
|
|
|
133
133
|
|
|
134
134
|
def __cleanup_precompiled_dir(self):
|
|
135
135
|
self.console("Delete precompiled components: {}".format(self.precompiled_micrOS_dir_path))
|
|
136
|
-
for source in
|
|
137
|
-
if check_all_extensions(pysource)]:
|
|
136
|
+
for source in LocalMachine.FileHandler.list_dir(self.precompiled_micrOS_dir_path):
|
|
138
137
|
to_remove_path = os.path.join(self.precompiled_micrOS_dir_path, source)
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
138
|
+
if check_all_extensions(source) or LocalMachine.FileHandler.path_is_exists(to_remove_path)[1] == "d":
|
|
139
|
+
self.console("\t|-remove: {}".format(to_remove_path), state='imp')
|
|
140
|
+
if not self.dry_run:
|
|
141
|
+
if not LocalMachine.FileHandler.remove(to_remove_path):
|
|
142
|
+
self.console(f"\t\t|-ERROR: Failed to remove {to_remove_path}", state="err")
|
|
142
143
|
|
|
143
144
|
def get_micros_version_from_repo(self):
|
|
144
145
|
# Get repo version
|
|
@@ -235,17 +236,21 @@ class Compile:
|
|
|
235
236
|
workdir_handler = LocalMachine.SimplePopPushd()
|
|
236
237
|
workdir_handler.pushd(self.micrOS_dir_path)
|
|
237
238
|
|
|
238
|
-
self.console("COPY additional resources")
|
|
239
|
-
|
|
240
|
-
for source in [pysource for pysource in LocalMachine.FileHandler.list_dir(self.micrOS_dir_path) if
|
|
241
|
-
check_web_extensions(pysource)]:
|
|
239
|
+
self.console("COPY additional resources...", state="ok")
|
|
240
|
+
for source in LocalMachine.FileHandler.list_dir(self.micrOS_dir_path):
|
|
242
241
|
source_path = os.path.join(self.micrOS_dir_path, source)
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
242
|
+
# COPY DIRECTORY RESOURCES (/web)
|
|
243
|
+
if (LocalMachine.FileHandler.path_is_exists(source_path)[1] == 'd' and
|
|
244
|
+
not (source.startswith("_") or source.startswith("."))):
|
|
245
|
+
if self.dry_run:
|
|
246
|
+
state = True
|
|
247
|
+
else:
|
|
248
|
+
target_dir = os.path.join(self.precompiled_micrOS_dir_path, source)
|
|
249
|
+
self.console(f"|- COPY DIR: {source_path} -> {target_dir}", state="ok")
|
|
250
|
+
state = LocalMachine.FileHandler.copy(source_path, target_dir)
|
|
251
|
+
if not state:
|
|
252
|
+
self.console("Copy error", state='err')
|
|
253
|
+
|
|
249
254
|
workdir_handler.popd()
|
|
250
255
|
|
|
251
256
|
|
toolkit/DevEnvOTA.py
CHANGED
|
@@ -5,22 +5,26 @@ MYPATH = os.path.dirname(__file__)
|
|
|
5
5
|
print("Module [DevEnvOTA] path: {} __package__: {} __name__: {} __file__: {}".format(
|
|
6
6
|
sys.path[0], __package__, __name__, MYPATH))
|
|
7
7
|
|
|
8
|
+
from pprint import pprint
|
|
9
|
+
|
|
8
10
|
try:
|
|
9
11
|
from .DevEnvCompile import Compile
|
|
10
12
|
from . import socketClient
|
|
11
13
|
from .lib import LocalMachine
|
|
12
14
|
from .lib.TerminalColors import Colors
|
|
13
15
|
from .lib.SafeInput import input_with_timeout
|
|
14
|
-
from .lib.file_extensions import check_all_extensions
|
|
16
|
+
from .lib.file_extensions import check_all_extensions, check_web_extensions, check_python_extensions
|
|
15
17
|
from .lib.Repository import git_clone_archive, git_clone
|
|
18
|
+
from .MicrosFiles import micros_resource_list
|
|
16
19
|
except Exception as e:
|
|
17
20
|
print("Import warning __name__:{}: {}".format(__name__, e))
|
|
18
21
|
from DevEnvCompile import Compile
|
|
19
22
|
from lib import LocalMachine
|
|
20
23
|
from lib.TerminalColors import Colors
|
|
21
24
|
from lib.SafeInput import input_with_timeout
|
|
22
|
-
from lib.file_extensions import check_all_extensions
|
|
25
|
+
from lib.file_extensions import check_all_extensions, check_web_extensions, check_python_extensions
|
|
23
26
|
from lib.Repository import git_clone_archive, git_clone
|
|
27
|
+
from MicrosFiles import micros_resource_list
|
|
24
28
|
|
|
25
29
|
sys.path.append(MYPATH)
|
|
26
30
|
import socketClient
|
|
@@ -241,9 +245,9 @@ class OTA(Compile):
|
|
|
241
245
|
self.console(" loader update: {}".format(force_mode), state='OK')
|
|
242
246
|
|
|
243
247
|
# Parse files from precompiled dir
|
|
244
|
-
resource_list_to_upload =
|
|
245
|
-
|
|
246
|
-
|
|
248
|
+
resource_list_to_upload, dir_list_to_create = micros_resource_list(self.precompiled_micrOS_dir_path)
|
|
249
|
+
# LIMITATION: WEBREPL Cannot create directories with remote command...
|
|
250
|
+
|
|
247
251
|
# Apply upload settings on parsed resources
|
|
248
252
|
for index, source in enumerate(resource_list_to_upload):
|
|
249
253
|
source_name = os.path.basename(source)
|
|
@@ -268,7 +272,8 @@ class OTA(Compile):
|
|
|
268
272
|
# Add source to upload
|
|
269
273
|
upload_path_list.append(source)
|
|
270
274
|
# Upload files / sources
|
|
271
|
-
return self.ota_webrepl_update_core(device, upload_path_list=upload_path_list,
|
|
275
|
+
return self.ota_webrepl_update_core(device, upload_path_list=upload_path_list,
|
|
276
|
+
ota_password=webrepl_password, upload_root_dir=self.precompiled_micrOS_dir_path)
|
|
272
277
|
|
|
273
278
|
def _enable_micros_ota_update_via_webrepl(self, device=None, ota_password=None):
|
|
274
279
|
# Get specific device from device list
|
|
@@ -401,7 +406,8 @@ class OTA(Compile):
|
|
|
401
406
|
print(f"[SIM] 'OTA' COPY FILES... {source} -> {target}")
|
|
402
407
|
LocalMachine.FileHandler().copy(source, target)
|
|
403
408
|
|
|
404
|
-
def ota_webrepl_update_core(self, device=None, upload_path_list=
|
|
409
|
+
def ota_webrepl_update_core(self, device=None, upload_path_list=None, ota_password='ADmin123',
|
|
410
|
+
force_lm=False, upload_root_dir=None):
|
|
405
411
|
"""
|
|
406
412
|
Generic file uploader for micrOS - over webrepl
|
|
407
413
|
info: https://techoverflow.net/2020/02/22/how-to-upload-files-to-micropython-using-webrepl-using-webrepl_cli-py/
|
|
@@ -410,7 +416,11 @@ class OTA(Compile):
|
|
|
410
416
|
upload_path_list: file path list to upload
|
|
411
417
|
ota_password - accessing webrepl to upload files
|
|
412
418
|
force_lm - use prefix as 'LM_' for every file - for user file upload / GUI drag n drop
|
|
419
|
+
upload_root_dir - root directory to upload files (subdir support)
|
|
413
420
|
"""
|
|
421
|
+
if upload_path_list is None:
|
|
422
|
+
upload_path_list = []
|
|
423
|
+
|
|
414
424
|
if device[0] == "__simulator__":
|
|
415
425
|
OTA.sim_ota_update(upload_path_list, force_lm)
|
|
416
426
|
return
|
|
@@ -457,7 +467,18 @@ class OTA(Compile):
|
|
|
457
467
|
# Copy retry mechanism
|
|
458
468
|
exitcode = -1
|
|
459
469
|
source_name = os.path.basename(source)
|
|
460
|
-
|
|
470
|
+
if upload_root_dir is None:
|
|
471
|
+
# Drag-n-Drop file upload file type check and folder adjustment
|
|
472
|
+
if check_web_extensions(source_name):
|
|
473
|
+
source_name_target = os.path.join('web', source_name)
|
|
474
|
+
elif not check_python_extensions(source_name) and not source_name.endswith("node_config.json"):
|
|
475
|
+
source_name_target = os.path.join('data', source_name)
|
|
476
|
+
else:
|
|
477
|
+
# Copy file to micrOS root folder (.mpy and .py or node_config.json)
|
|
478
|
+
source_name_target = source_name
|
|
479
|
+
else:
|
|
480
|
+
# MAIN USE-CASE
|
|
481
|
+
source_name_target = source.replace(upload_root_dir, '')
|
|
461
482
|
|
|
462
483
|
# Force LM update - user load modules - drag n drop files
|
|
463
484
|
if force_lm and not source_name.startswith('LM_') and source_name.endswith('.py'):
|
toolkit/DevEnvUSB.py
CHANGED
|
@@ -13,12 +13,14 @@ try:
|
|
|
13
13
|
from .lib import LocalMachine
|
|
14
14
|
from .lib.TerminalColors import Colors
|
|
15
15
|
from .lib.SerialDriverHandler import install_usb_serial_driver
|
|
16
|
+
from .MicrosFiles import micros_resource_list
|
|
16
17
|
except Exception as e:
|
|
17
18
|
print("Import warning __name__:{}: {}".format(__name__, e))
|
|
18
19
|
from DevEnvCompile import Compile
|
|
19
20
|
from lib import LocalMachine
|
|
20
21
|
from lib.TerminalColors import Colors
|
|
21
22
|
from lib.SerialDriverHandler import install_usb_serial_driver
|
|
23
|
+
from MicrosFiles import micros_resource_list
|
|
22
24
|
|
|
23
25
|
|
|
24
26
|
class USB(Compile):
|
|
@@ -77,6 +79,11 @@ class USB(Compile):
|
|
|
77
79
|
'deploy': '{esptool_interface} --chip esp32c3 --port {dev} --baud 460800 write_flash -z 0x0 {micropython}',
|
|
78
80
|
'mpremote_cmd': 'mpremote',
|
|
79
81
|
'cmd_line_info': '[!HINT!] Fully automatic deployment...'},
|
|
82
|
+
'esp32c6':
|
|
83
|
+
{'erase': '{esptool_interface} --chip esp32c6 --port {dev} erase_flash',
|
|
84
|
+
'deploy': '{esptool_interface} --chip esp32c6 --port {dev} --baud 460800 write_flash -z 0x0 {micropython}',
|
|
85
|
+
'mpremote_cmd': 'mpremote',
|
|
86
|
+
'cmd_line_info': '[!HINT!] Fully automatic deployment...'},
|
|
80
87
|
}
|
|
81
88
|
if not USB.usb_driver_ok:
|
|
82
89
|
# Optimization - driver check
|
|
@@ -202,6 +209,38 @@ class USB(Compile):
|
|
|
202
209
|
self.console("Deployment failed.\n{} - {}".format(stdout, stderr), state='err')
|
|
203
210
|
return False
|
|
204
211
|
|
|
212
|
+
def _mkdir_on_dev(self, folders:list):
|
|
213
|
+
mpremote_cmd = self.dev_types_and_cmds[self.selected_device_type]['mpremote_cmd']
|
|
214
|
+
device = self.get_devices()[0]
|
|
215
|
+
if mpremote_cmd is None:
|
|
216
|
+
# Legacy ampy command (esp32 auto reboot tolerance...)
|
|
217
|
+
mkdir_cmd = self.dev_types_and_cmds[self.selected_device_type]['ampy_cmd'].format(dev=device, args=f'mkdir')
|
|
218
|
+
else:
|
|
219
|
+
mkdir_cmd = f'{mpremote_cmd} fs mkdir'
|
|
220
|
+
|
|
221
|
+
status = 0
|
|
222
|
+
for folder in folders:
|
|
223
|
+
_mkdir_cmd = f"{mkdir_cmd} {folder}"
|
|
224
|
+
self.console(f"Create directory on device: {_mkdir_cmd}")
|
|
225
|
+
if self.dry_run:
|
|
226
|
+
pass
|
|
227
|
+
else:
|
|
228
|
+
try:
|
|
229
|
+
exitcode, stdout, stderr = LocalMachine.CommandHandler.run_command(_mkdir_cmd, shell=True)
|
|
230
|
+
if exitcode != 0:
|
|
231
|
+
verdict = stdout + stderr
|
|
232
|
+
if "File exists" in verdict or "Directory already exists" in verdict:
|
|
233
|
+
exitcode = 0
|
|
234
|
+
else:
|
|
235
|
+
self.console(f"MKDIR ERROR:\n{stdout}\n{stderr}", state="err")
|
|
236
|
+
except Exception as e:
|
|
237
|
+
self.console(f"MKDIR ERROR {_mkdir_cmd}: {e}", state="err")
|
|
238
|
+
exitcode = 1
|
|
239
|
+
status += exitcode
|
|
240
|
+
|
|
241
|
+
return True if status == 0 else False
|
|
242
|
+
|
|
243
|
+
|
|
205
244
|
def put_micros_to_dev(self):
|
|
206
245
|
self.select_board_n_micropython()
|
|
207
246
|
status = True
|
|
@@ -218,17 +257,20 @@ class USB(Compile):
|
|
|
218
257
|
self.console(f"... wait for reset {10-k} sec", state='imp')
|
|
219
258
|
time.sleep(1)
|
|
220
259
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
260
|
+
# Parse micrOS resources with folders
|
|
261
|
+
_source_to_put_device, dir_list_to_create = micros_resource_list(self.precompiled_micrOS_dir_path)
|
|
262
|
+
self.console(f"CREATE FOLDERS: {dir_list_to_create}", state="ok")
|
|
263
|
+
# Create sub folders
|
|
264
|
+
if not self._mkdir_on_dev(dir_list_to_create):
|
|
265
|
+
self.console(f"Error creating directories on device: {dir_list_to_create}")
|
|
266
|
+
sys.exit(1)
|
|
267
|
+
# Generate resource list to be put on the device
|
|
268
|
+
source_to_put_device = list([s.replace(self.precompiled_micrOS_dir_path + "/", '') for s in _source_to_put_device])
|
|
224
269
|
# Set source order - main, boot
|
|
225
|
-
source_to_put_device.append(source_to_put_device.pop(source_to_put_device.index(
|
|
226
|
-
try:
|
|
227
|
-
# PIP deployment generates this ...
|
|
228
|
-
source_to_put_device.remove('__pycache__') # remove if accidentally left here
|
|
229
|
-
except:
|
|
230
|
-
pass
|
|
270
|
+
source_to_put_device.append(source_to_put_device.pop(source_to_put_device.index("main.py")))
|
|
231
271
|
|
|
272
|
+
mpremote_cmd = self.dev_types_and_cmds[self.selected_device_type]['mpremote_cmd']
|
|
273
|
+
device = self.get_devices()[0]
|
|
232
274
|
# Change workdir
|
|
233
275
|
workdir_handler = LocalMachine.SimplePopPushd()
|
|
234
276
|
workdir_handler.pushd(self.precompiled_micrOS_dir_path)
|
|
@@ -238,7 +280,7 @@ class USB(Compile):
|
|
|
238
280
|
self.console("[{}%] micrOS deploy via USB - {}".format(percent, device))
|
|
239
281
|
if mpremote_cmd is None:
|
|
240
282
|
# Legacy ampy command (esp32 auto reboot tolerance...)
|
|
241
|
-
command = self.dev_types_and_cmds[self.selected_device_type]['ampy_cmd'].format(dev=device, args=f'put {source}')
|
|
283
|
+
command = self.dev_types_and_cmds[self.selected_device_type]['ampy_cmd'].format(dev=device, args=f'put {source} /{source}')
|
|
242
284
|
else:
|
|
243
285
|
command = f'{mpremote_cmd} fs cp {source} :{source}' # new mpremote <1.24.1
|
|
244
286
|
if ' ' in source:
|
toolkit/LM_to_compile.dat
CHANGED
toolkit/MicrOSDevEnv.py
CHANGED
|
@@ -62,8 +62,16 @@ class MicrOSDevTool(OTA, USB):
|
|
|
62
62
|
if f.endswith('.json'):
|
|
63
63
|
continue
|
|
64
64
|
f_path = os.path.join(self.micrOS_dir_path, f)
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
if f.startswith("_") or f.startswith("."):
|
|
66
|
+
# SKIP files startswith `_` and `.`
|
|
67
|
+
continue
|
|
68
|
+
_, f_type = LocalMachine.FileHandler.path_is_exists(f_path)
|
|
69
|
+
target_dir = self.micros_sim_workspace
|
|
70
|
+
if f_type == "d":
|
|
71
|
+
target_dir = os.path.join(self.micros_sim_workspace, f)
|
|
72
|
+
self.console(f"[SIM] Copy micrOS resources: {f_path} -> {target_dir}")
|
|
73
|
+
if not LocalMachine.FileHandler().copy(f_path, target_dir):
|
|
74
|
+
self.console(f"[ERROR] Failed to copy: {f_path}")
|
|
67
75
|
|
|
68
76
|
if prepare_only:
|
|
69
77
|
# In case of automatic node_conf creation
|
toolkit/MicrosFiles.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
try:
|
|
4
|
+
from .lib import LocalMachine
|
|
5
|
+
from .lib.file_extensions import check_all_extensions, check_web_extensions
|
|
6
|
+
except Exception as e:
|
|
7
|
+
print("Import warning __name__:{}: {}".format(__name__, e))
|
|
8
|
+
from lib import LocalMachine
|
|
9
|
+
from lib.file_extensions import check_all_extensions, check_web_extensions
|
|
10
|
+
|
|
11
|
+
def micros_resource_list(root_folder):
|
|
12
|
+
resources_path = []
|
|
13
|
+
subfolders = []
|
|
14
|
+
for source in LocalMachine.FileHandler.list_dir(root_folder):
|
|
15
|
+
source_full_path = os.path.join(root_folder, source)
|
|
16
|
+
# [1] / Root directory source files and folders.
|
|
17
|
+
if check_all_extensions(source):
|
|
18
|
+
resources_path.append(source_full_path)
|
|
19
|
+
# [2] /dir Handle sub dictionary sources
|
|
20
|
+
elif LocalMachine.FileHandler.path_is_exists(source_full_path)[1] == 'd':
|
|
21
|
+
subfolders.append(source)
|
|
22
|
+
for sub_source in LocalMachine.FileHandler.list_dir(source_full_path):
|
|
23
|
+
sub_source_full_path = os.path.join(source_full_path, sub_source)
|
|
24
|
+
if check_all_extensions(sub_source):
|
|
25
|
+
resources_path.append(sub_source_full_path)
|
|
26
|
+
return resources_path, subfolders
|
|
@@ -25,40 +25,33 @@ def app(devfid=None, pwd=None):
|
|
|
25
25
|
status, answer = CLIENT.run(args)
|
|
26
26
|
time.sleep(2)
|
|
27
27
|
|
|
28
|
-
status, answer = CLIENT.run(['neoeffects rainbow
|
|
28
|
+
status, answer = CLIENT.run(['neoeffects rainbow'])
|
|
29
29
|
time.sleep(2)
|
|
30
|
-
status, answer = CLIENT.run(['task kill neoeffects.rainbow'])
|
|
31
30
|
|
|
32
31
|
status, answer = CLIENT.run(['neoeffects color 122 18 0'])
|
|
33
32
|
|
|
34
|
-
status, answer = CLIENT.run(['neoeffects cycle
|
|
33
|
+
status, answer = CLIENT.run(['neoeffects cycle'])
|
|
35
34
|
time.sleep(2)
|
|
36
|
-
status, answer = CLIENT.run(['task kill neoeffects.cycle'])
|
|
37
35
|
|
|
38
|
-
status, answer = CLIENT.run(['neoeffects meteor
|
|
36
|
+
status, answer = CLIENT.run(['neoeffects meteor'])
|
|
39
37
|
time.sleep(2)
|
|
40
|
-
status, answer = CLIENT.run(['task kill neoeffects.meteor'])
|
|
41
38
|
|
|
42
|
-
status, answer = CLIENT.run(['neoeffects fire
|
|
39
|
+
status, answer = CLIENT.run(['neoeffects fire'])
|
|
43
40
|
time.sleep(2)
|
|
44
|
-
status, answer = CLIENT.run(['task kill neoeffects.fire'])
|
|
45
41
|
|
|
46
|
-
time.sleep(1)
|
|
47
42
|
|
|
48
43
|
status, answer = CLIENT.run(['neoeffects random &&500'])
|
|
49
44
|
|
|
50
|
-
status, answer = CLIENT.run(['neoeffects cycle
|
|
45
|
+
status, answer = CLIENT.run(['neoeffects cycle'])
|
|
51
46
|
time.sleep(3)
|
|
52
|
-
status, answer = CLIENT.run(['task kill neoeffects.cycle'])
|
|
53
47
|
|
|
54
|
-
status, answer = CLIENT.run(['neoeffects meteor
|
|
48
|
+
status, answer = CLIENT.run(['neoeffects meteor'])
|
|
55
49
|
time.sleep(3)
|
|
56
|
-
status, answer = CLIENT.run(['task kill neoeffects.meteor'])
|
|
57
50
|
|
|
58
|
-
status, answer = CLIENT.run(['neoeffects fire
|
|
51
|
+
status, answer = CLIENT.run(['neoeffects fire'])
|
|
59
52
|
time.sleep(3)
|
|
60
|
-
status, answer = CLIENT.run(['task kill neoeffects.fire'])
|
|
61
53
|
|
|
54
|
+
status, answer = CLIENT.run(['task kill neoeffects.player'])
|
|
62
55
|
status, answer = CLIENT.run(['task kill neoeffects.random'])
|
|
63
56
|
status, answer = CLIENT.run(['neopixel color 122 18 0'])
|
|
64
57
|
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
import json
|
|
6
|
+
import time
|
|
7
|
+
import multiprocessing as mp
|
|
8
|
+
|
|
9
|
+
MYPATH = os.path.dirname(os.path.abspath(__file__))
|
|
10
|
+
sys.path.append(os.path.join(MYPATH, '../lib/'))
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
from ._app_base import AppBase
|
|
14
|
+
except ImportError:
|
|
15
|
+
from _app_base import AppBase
|
|
16
|
+
|
|
17
|
+
def print_table(data):
|
|
18
|
+
os.system('cls' if os.name == 'nt' else 'clear')
|
|
19
|
+
print(f"{'Sensor':<10} {'X':>10} {'Y':>10} {'Z':>10}")
|
|
20
|
+
for sensor in ['accel', 'gyro']:
|
|
21
|
+
x, y, z = data[sensor]
|
|
22
|
+
print(f"{sensor:<10} {x:10.2f} {y:10.2f} {z:10.2f}")
|
|
23
|
+
if 'temp' in data:
|
|
24
|
+
print(f"{'temp':<10} {data['temp']:>10.2f}")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def app(devfid=None, pwd=None):
|
|
28
|
+
CLIENT = AppBase(device=devfid, password=pwd)
|
|
29
|
+
measure_cmd = 'qmi8685 measure >json'
|
|
30
|
+
|
|
31
|
+
mp.set_start_method('spawn', force=True)
|
|
32
|
+
queue = mp.Queue()
|
|
33
|
+
|
|
34
|
+
# Start GUI process
|
|
35
|
+
from ._gyro_visualizer import visualizer_main
|
|
36
|
+
p = mp.Process(target=visualizer_main, args=(queue,))
|
|
37
|
+
p.start()
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
for _ in range(10000):
|
|
41
|
+
output = CLIENT.execute([measure_cmd])
|
|
42
|
+
status, result = output[0], output[1]
|
|
43
|
+
|
|
44
|
+
if status:
|
|
45
|
+
try:
|
|
46
|
+
parsed = json.loads(result)
|
|
47
|
+
print_table(parsed)
|
|
48
|
+
queue.put(parsed)
|
|
49
|
+
except Exception as e:
|
|
50
|
+
print(f"[Visualizer queue issue] {e}")
|
|
51
|
+
break
|
|
52
|
+
else:
|
|
53
|
+
print(f"[WARN] {result}")
|
|
54
|
+
|
|
55
|
+
time.sleep(0.05)
|
|
56
|
+
|
|
57
|
+
except KeyboardInterrupt:
|
|
58
|
+
print("Interrupted by user.")
|
|
59
|
+
|
|
60
|
+
finally:
|
|
61
|
+
if p.is_alive():
|
|
62
|
+
p.terminate()
|
|
63
|
+
p.join()
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
if __name__ == "__main__":
|
|
68
|
+
app()
|
|
@@ -20,10 +20,10 @@ class AppBase:
|
|
|
20
20
|
def get_device(self):
|
|
21
21
|
return self.device
|
|
22
22
|
|
|
23
|
-
def execute(self, cmd_list, tout=5):
|
|
23
|
+
def execute(self, cmd_list, tout=5, verbose=False):
|
|
24
24
|
cmd_args = self.base_cmd() + cmd_list
|
|
25
25
|
print(f"Execute: {cmd_args}")
|
|
26
|
-
return socketClient.run(cmd_args, timeout=tout)
|
|
26
|
+
return socketClient.run(cmd_args, timeout=tout, verbose=verbose)
|
|
27
27
|
|
|
28
28
|
def run(self, cmd_list):
|
|
29
29
|
"""Legacy"""
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import matplotlib.pyplot as plt
|
|
2
|
+
import matplotlib.animation as animation
|
|
3
|
+
import multiprocessing as mp
|
|
4
|
+
from collections import deque
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
import matplotlib.dates as mdates
|
|
7
|
+
|
|
8
|
+
def visualizer_main(queue):
|
|
9
|
+
# Make figure wider and a bit taller
|
|
10
|
+
fig, (ax_accel, ax_gyro) = plt.subplots(2, 1, figsize=(14, 8))
|
|
11
|
+
plt.subplots_adjust(top=0.88, bottom=0.12, hspace=0.3)
|
|
12
|
+
|
|
13
|
+
history = 100
|
|
14
|
+
accel_data = {'x': deque([0] * history, maxlen=history),
|
|
15
|
+
'y': deque([0] * history, maxlen=history),
|
|
16
|
+
'z': deque([0] * history, maxlen=history)}
|
|
17
|
+
gyro_data = {'x': deque([0] * history, maxlen=history),
|
|
18
|
+
'y': deque([0] * history, maxlen=history),
|
|
19
|
+
'z': deque([0] * history, maxlen=history)}
|
|
20
|
+
time_axis = deque([datetime.now()] * history, maxlen=history)
|
|
21
|
+
|
|
22
|
+
# Increase line width here
|
|
23
|
+
line_width = 2.5
|
|
24
|
+
|
|
25
|
+
accel_lines = {
|
|
26
|
+
axis: ax_accel.plot([], [], label=f'accel_{axis}', linewidth=line_width)[0]
|
|
27
|
+
for axis in 'xyz'
|
|
28
|
+
}
|
|
29
|
+
gyro_lines = {
|
|
30
|
+
axis: ax_gyro.plot([], [], label=f'gyro_{axis}', linewidth=line_width)[0]
|
|
31
|
+
for axis in 'xyz'
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
ax_accel.set_ylim(-2, 2)
|
|
35
|
+
ax_gyro.set_ylim(-300, 300)
|
|
36
|
+
|
|
37
|
+
for ax in [ax_accel, ax_gyro]:
|
|
38
|
+
ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M:%S'))
|
|
39
|
+
ax.legend()
|
|
40
|
+
ax.grid(True)
|
|
41
|
+
ax.set_xlabel("Time (H:M:S)")
|
|
42
|
+
|
|
43
|
+
ax_accel.set_title("Acceleration")
|
|
44
|
+
ax_gyro.set_title("Gyroscope")
|
|
45
|
+
|
|
46
|
+
def update(_):
|
|
47
|
+
try:
|
|
48
|
+
while not queue.empty():
|
|
49
|
+
data = queue.get_nowait()
|
|
50
|
+
current_time = datetime.now()
|
|
51
|
+
time_axis.append(current_time)
|
|
52
|
+
|
|
53
|
+
for axis, val in zip('xyz', data['accel']):
|
|
54
|
+
accel_data[axis].append(val)
|
|
55
|
+
for axis, val in zip('xyz', data['gyro']):
|
|
56
|
+
gyro_data[axis].append(val)
|
|
57
|
+
except Exception as e:
|
|
58
|
+
print(f"Visualizer error: {e}")
|
|
59
|
+
return
|
|
60
|
+
|
|
61
|
+
for axis in 'xyz':
|
|
62
|
+
accel_lines[axis].set_data(time_axis, accel_data[axis])
|
|
63
|
+
gyro_lines[axis].set_data(time_axis, gyro_data[axis])
|
|
64
|
+
|
|
65
|
+
for ax in [ax_accel, ax_gyro]:
|
|
66
|
+
ax.set_xlim(time_axis[0], time_axis[-1])
|
|
67
|
+
ax.figure.autofmt_xdate()
|
|
68
|
+
|
|
69
|
+
return list(accel_lines.values()) + list(gyro_lines.values())
|
|
70
|
+
|
|
71
|
+
ani = animation.FuncAnimation(fig, update, interval=50)
|
|
72
|
+
plt.show()
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
if __name__ == "__main__":
|
|
76
|
+
mp.set_start_method('spawn')
|
|
77
|
+
queue = mp.Queue()
|
|
78
|
+
visualizer_main(queue)
|
toolkit/lib/LocalMachine.py
CHANGED
|
@@ -186,11 +186,13 @@ class FileHandler:
|
|
|
186
186
|
os.remove(path)
|
|
187
187
|
elif type_ == 'd':
|
|
188
188
|
shutil.rmtree(path)
|
|
189
|
+
return True
|
|
189
190
|
except Exception as e:
|
|
190
191
|
if ignore:
|
|
191
192
|
debug_print("[DEBUG] Removing " + path + " is forced to ignore failure: " + str(e))
|
|
192
193
|
else:
|
|
193
194
|
raise Exception("Cannot remove " + path + ": " + str(e))
|
|
195
|
+
return False
|
|
194
196
|
|
|
195
197
|
@staticmethod
|
|
196
198
|
def extract_tar(targz, extract_path):
|
|
@@ -210,7 +212,10 @@ class FileHandler:
|
|
|
210
212
|
def copy(from_path, to_path):
|
|
211
213
|
debug_print("[DEBUG] Copy " + from_path + " to " + to_path)
|
|
212
214
|
try:
|
|
213
|
-
|
|
215
|
+
if os.path.isdir(from_path):
|
|
216
|
+
shutil.copytree(from_path, to_path, dirs_exist_ok=True)
|
|
217
|
+
else:
|
|
218
|
+
shutil.copy(from_path, to_path)
|
|
214
219
|
return True
|
|
215
220
|
except Exception as e:
|
|
216
221
|
debug_print("Copy error: {}".format(e))
|
toolkit/lib/file_extensions.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
PYTHON_EXTENSIONS = ('py', 'mpy')
|
|
3
|
+
WEB_ONLY = ('js', 'html', 'css', 'json', 'ico', 'jpeg', 'png')
|
|
4
|
+
ENABLED_EXTENSIONS = PYTHON_EXTENSIONS + WEB_ONLY
|
|
5
5
|
|
|
6
6
|
def check_all_extensions(path):
|
|
7
7
|
extension = path.split('.')[-1]
|
|
@@ -13,4 +13,10 @@ def check_web_extensions(path):
|
|
|
13
13
|
extension = path.split('.')[-1]
|
|
14
14
|
if extension in WEB_ONLY:
|
|
15
15
|
return True
|
|
16
|
+
return False
|
|
17
|
+
|
|
18
|
+
def check_python_extensions(path):
|
|
19
|
+
extension = path.split('.')[-1]
|
|
20
|
+
if extension in PYTHON_EXTENSIONS:
|
|
21
|
+
return True
|
|
16
22
|
return False
|
toolkit/micrOSlint.py
CHANGED
|
@@ -222,7 +222,9 @@ def _run_pylint(file_name):
|
|
|
222
222
|
'--disable=broad-exception-caught', # Disable BROAD exception
|
|
223
223
|
'--disable=broad-exception-raised', # Disable BROAD exception
|
|
224
224
|
'--disable=too-many-return-statements', # :D I don't think so :D
|
|
225
|
-
'--disable=too-many-branches'
|
|
225
|
+
'--disable=too-many-branches', # :D I don't think so :D
|
|
226
|
+
'--disable=too-many-positional-arguments', # :D I don't think so :D
|
|
227
|
+
'--disable=too-many-instance-attributes' # :D I don't think so :D
|
|
226
228
|
]
|
|
227
229
|
if file_name in ['Tasks.py', 'microIO.py', 'Types.py']:
|
|
228
230
|
pylint_opts.append('--disable=exec-used') # Disable micrOS execution core exec/eval warning
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
toolkit/simulator_lib/machine.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
from sim_console import console
|
|
2
2
|
|
|
3
3
|
class NeoPixel:
|
|
4
4
|
__instance = None
|
|
@@ -17,9 +17,10 @@ class NeoPixel:
|
|
|
17
17
|
return cls.__pix_list[key]
|
|
18
18
|
|
|
19
19
|
def __setitem__(cls, key, value):
|
|
20
|
+
console(f"Update NeoPixel at index {key} to {value}")
|
|
20
21
|
cls.__pix_list[key] = value
|
|
21
22
|
|
|
22
23
|
def write(cls):
|
|
23
|
-
|
|
24
|
+
console(f"Neopixel write: {cls.__pix_list}")
|
|
24
25
|
|
|
25
26
|
|
toolkit/socketClient.py
CHANGED
|
@@ -424,7 +424,7 @@ def socket_commandline_args(arg_list):
|
|
|
424
424
|
return ' <a> '.join(command_buffer), return_action_dict
|
|
425
425
|
|
|
426
426
|
|
|
427
|
-
def run(arg_list=[], timeout=10):
|
|
427
|
+
def run(arg_list=[], timeout=10, verbose=False):
|
|
428
428
|
""" Run from code
|
|
429
429
|
- Handles extra command line arguments
|
|
430
430
|
"""
|
|
@@ -434,7 +434,8 @@ def run(arg_list=[], timeout=10):
|
|
|
434
434
|
output = False, ''
|
|
435
435
|
try:
|
|
436
436
|
#print("Socket run (args): {}".format(args))
|
|
437
|
-
|
|
437
|
+
verbose = verbose or action['verbose']
|
|
438
|
+
output = main(args, host=host, port=port, timeout=timeout, pwd=action['password'], verbose=verbose)
|
|
438
439
|
except Exception as e:
|
|
439
440
|
if "TimeOut" in str(e):
|
|
440
441
|
print("Resolve device by host ... {}.local {}:{}:{}".format(fid, host, port, uid))
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|