micrOSDevToolKit 2.1.5__py3-none-any.whl → 2.26.1__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.
- env/driver_cp210x/.DS_Store +0 -0
- 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/esp32-20251209-v1.27.0.bin +0 -0
- micrOS/micropython/esp32c3-20251209-v1.27.0.bin +0 -0
- micrOS/micropython/esp32c6-20251209-v1.27.0.bin +0 -0
- micrOS/micropython/esp32s2-20251209-v1.27.0.bin +0 -0
- micrOS/micropython/esp32s2-LOLIN_MINI-20251209-v1.27.0.bin +0 -0
- micrOS/micropython/esp32s3-4MBflash-20241129-v1.24.1.bin +0 -0
- micrOS/micropython/esp32s3-8MBflash-20251209-v1.27.0.bin +0 -0
- micrOS/micropython/esp32s3_spiram_oct-20251209-v1.27.0.bin +0 -0
- micrOS/micropython/rpi-pico-w-20251209-v1.27.0.uf2 +0 -0
- micrOS/micropython/tinypico-20251209-v1.27.0.bin +0 -0
- micrOS/release_info/micrOS_ReleaseInfo/system_analysis_sum.json +191 -151
- micrOS/source/Auth.py +37 -0
- micrOS/source/Common.py +376 -102
- micrOS/source/Config.py +55 -25
- micrOS/source/Debug.py +54 -193
- micrOS/source/Espnow.py +404 -0
- micrOS/source/Files.py +207 -0
- micrOS/source/Hooks.py +88 -16
- micrOS/source/InterConnect.py +130 -46
- micrOS/source/Interrupts.py +8 -8
- micrOS/source/Logger.py +131 -0
- micrOS/source/Network.py +41 -21
- micrOS/source/Notify.py +74 -198
- micrOS/source/Pacman.py +326 -0
- micrOS/source/Scheduler.py +18 -55
- micrOS/source/Server.py +84 -217
- micrOS/source/Shell.py +103 -93
- micrOS/source/Tasks.py +239 -173
- micrOS/source/Time.py +21 -22
- micrOS/source/Types.py +89 -54
- micrOS/source/Web.py +485 -0
- micrOS/source/__pycache__/Common.cpython-312.pyc +0 -0
- micrOS/source/__pycache__/Debug.cpython-312.pyc +0 -0
- micrOS/source/__pycache__/Files.cpython-312.pyc +0 -0
- micrOS/source/__pycache__/Logger.cpython-312.pyc +0 -0
- micrOS/source/__pycache__/Scheduler.cpython-312.pyc +0 -0
- micrOS/source/__pycache__/Server.cpython-312.pyc +0 -0
- micrOS/source/__pycache__/Shell.cpython-312.pyc +0 -0
- micrOS/source/__pycache__/replhelper.cpython-312.pyc +0 -0
- micrOS/source/helpers.py +132 -0
- micrOS/source/micrOS.py +25 -21
- micrOS/source/micrOSloader.py +14 -23
- micrOS/source/microIO.py +94 -57
- toolkit/simulator_lib/LP_darwin.py → micrOS/source/modules/IO_esp32.py +22 -11
- micrOS/source/{IO_esp32c3.py → modules/IO_esp32c3.py} +6 -1
- micrOS/source/modules/IO_esp32c6.py +38 -0
- micrOS/source/{IO_esp32s2.py → modules/IO_esp32s2.py} +6 -1
- micrOS/source/{IO_esp32s3.py → modules/IO_esp32s3.py} +43 -2
- micrOS/source/modules/IO_m5stamp.py +86 -0
- micrOS/source/{IO_qtpy.py → modules/IO_qtpy.py} +28 -18
- micrOS/source/{IO_tinypico.py → modules/IO_tinypico.py} +48 -3
- micrOS/source/modules/LM_L298N.py +161 -0
- {toolkit/workspace/precompiled → micrOS/source/modules}/LM_L9110_DCmotor.py +4 -4
- micrOS/source/{LM_OV2640.py → modules/LM_OV2640.py} +53 -42
- micrOS/source/{LM_VL53L0X.py → modules/LM_VL53L0X.py} +5 -5
- micrOS/source/{LM_aht10.py → modules/LM_aht10.py} +12 -4
- micrOS/source/{LM_bme280.py → modules/LM_bme280.py} +13 -25
- micrOS/source/{LM_buzzer.py → modules/LM_buzzer.py} +42 -40
- micrOS/source/{LM_cct.py → modules/LM_cct.py} +22 -27
- micrOS/source/modules/LM_cluster.py +255 -0
- micrOS/source/{LM_co2.py → modules/LM_co2.py} +13 -6
- micrOS/source/{LM_dht11.py → modules/LM_dht11.py} +13 -29
- micrOS/source/{LM_dht22.py → modules/LM_dht22.py} +13 -28
- micrOS/source/{LM_dimmer.py → modules/LM_dimmer.py} +19 -16
- micrOS/source/modules/LM_distance.py +135 -0
- micrOS/source/{LM_ds18.py → modules/LM_ds18.py} +12 -4
- micrOS/source/{LM_esp32.py → modules/LM_esp32.py} +16 -4
- micrOS/source/modules/LM_espnow.py +53 -0
- micrOS/source/modules/LM_fileserver.py +265 -0
- micrOS/source/{LM_gameOfLife.py → modules/LM_gameOfLife.py} +5 -5
- micrOS/source/{LM_genIO.py → modules/LM_genIO.py} +49 -35
- micrOS/source/modules/LM_haptic.py +111 -0
- micrOS/source/modules/LM_i2c.py +61 -0
- micrOS/source/{LM_i2s_mic.py → modules/LM_i2s_mic.py} +20 -23
- micrOS/source/{LM_ld2410.py → modules/LM_ld2410.py} +3 -3
- micrOS/source/{LM_light_sensor.py → modules/LM_light_sensor.py} +22 -26
- micrOS/source/modules/LM_mh_z19c.py +198 -0
- micrOS/source/modules/LM_neoeffects.py +284 -0
- micrOS/source/{LM_neopixel.py → modules/LM_neopixel.py} +26 -31
- micrOS/source/{LM_oled.py → modules/LM_oled.py} +28 -20
- micrOS/source/{LM_oled_sh1106.py → modules/LM_oled_sh1106.py} +28 -24
- micrOS/source/{LM_oled_ui.py → modules/LM_oled_ui.py} +132 -174
- micrOS/source/modules/LM_pacman.py +320 -0
- micrOS/source/{LM_presence.py → modules/LM_presence.py} +24 -36
- micrOS/source/modules/LM_qmi8658.py +204 -0
- micrOS/source/{LM_rencoder.py → modules/LM_rencoder.py} +40 -11
- micrOS/source/modules/LM_rest.py +81 -0
- micrOS/source/{LM_rgb.py → modules/LM_rgb.py} +25 -34
- micrOS/source/{LM_rgbcct.py → modules/LM_rgbcct.py} +5 -5
- micrOS/source/{LM_roboarm.py → modules/LM_roboarm.py} +37 -45
- micrOS/source/modules/LM_robustness.py +137 -0
- micrOS/source/{LM_rp2w.py → modules/LM_rp2w.py} +3 -0
- micrOS/source/{LM_sdcard.py → modules/LM_sdcard.py} +3 -0
- micrOS/source/{LM_servo.py → modules/LM_servo.py} +4 -4
- micrOS/source/modules/LM_sound_event.py +751 -0
- micrOS/source/{LM_stepper.py → modules/LM_stepper.py} +8 -8
- micrOS/source/{LM_switch.py → modules/LM_switch.py} +21 -18
- micrOS/source/{LM_system.py → modules/LM_system.py} +96 -59
- micrOS/source/modules/LM_tcs3472.py +187 -0
- micrOS/source/modules/LM_telegram.py +388 -0
- micrOS/source/modules/LM_trackball.py +287 -0
- micrOS/source/modules/LM_veml7700.py +159 -0
- micrOS/source/modules/LM_web.py +38 -0
- micrOS/source/urequests.py +204 -91
- {toolkit/workspace/precompiled → micrOS/source/web}/dashboard.html +9 -4
- micrOS/source/web/editor.js +440 -0
- micrOS/source/web/filesui.html +178 -0
- micrOS/source/web/filesui.js +338 -0
- micrOS/source/{index.html → web/index.html} +44 -2
- micrOS/source/web/uapi.js +103 -0
- micrOS/source/web/udashboard.js +129 -0
- micrOS/source/web/ustyle.css +55 -0
- micrOS/source/web/uwidgets.js +172 -0
- micrOS/source/web/uwidgets_pro.js +99 -0
- micrOS/utests/__init__.py +0 -0
- micrOS/utests/test_scheduler.py +435 -0
- {micrOSDevToolKit-2.1.5.data → microsdevtoolkit-2.26.1.data}/scripts/devToolKit.py +47 -4
- {micrOSDevToolKit-2.1.5.dist-info → microsdevtoolkit-2.26.1.dist-info}/METADATA +392 -279
- microsdevtoolkit-2.26.1.dist-info/RECORD +396 -0
- {micrOSDevToolKit-2.1.5.dist-info → microsdevtoolkit-2.26.1.dist-info}/WHEEL +1 -1
- toolkit/DevEnvCompile.py +63 -33
- toolkit/DevEnvOTA.py +72 -22
- toolkit/DevEnvUSB.py +147 -77
- toolkit/Gateway.py +9 -9
- toolkit/LM_to_compile.dat +12 -4
- toolkit/MicrOSDevEnv.py +129 -51
- toolkit/WebRepl.py +73 -0
- toolkit/dashboard_apps/BackupRestore.py +171 -0
- toolkit/dashboard_apps/CCTDemo.py +12 -17
- toolkit/dashboard_apps/CCTTest.py +20 -24
- toolkit/dashboard_apps/CamStream.py +2 -6
- toolkit/dashboard_apps/CatGame.py +14 -16
- toolkit/dashboard_apps/Dimmer.py +11 -21
- toolkit/dashboard_apps/GetVersion.py +11 -19
- toolkit/dashboard_apps/MicrophoneTest.py +2 -7
- toolkit/dashboard_apps/NeoEffectsDemo.py +22 -35
- toolkit/dashboard_apps/NeopixelTest.py +20 -25
- toolkit/dashboard_apps/PresenceTest.py +2 -8
- toolkit/dashboard_apps/QMI8685_GYRO.py +68 -0
- toolkit/dashboard_apps/RGBTest.py +20 -24
- toolkit/dashboard_apps/RoboArm.py +24 -32
- toolkit/dashboard_apps/SED_test.py +10 -14
- toolkit/dashboard_apps/SensorsTest.py +61 -0
- toolkit/dashboard_apps/SystemTest.py +219 -117
- toolkit/dashboard_apps/Template_app.py +12 -19
- toolkit/dashboard_apps/_app_base.py +34 -0
- toolkit/dashboard_apps/_gyro_visualizer.py +78 -0
- toolkit/dashboard_apps/uLightDemo.py +15 -24
- toolkit/index.html +6 -5
- toolkit/lib/LocalMachine.py +6 -1
- toolkit/lib/MicrosFiles.py +46 -0
- toolkit/lib/Repository.py +64 -0
- toolkit/lib/TerminalColors.py +4 -0
- toolkit/lib/macroScript.py +371 -0
- toolkit/lib/micrOSClient.py +124 -51
- toolkit/lib/micrOSClientHistory.py +156 -0
- toolkit/lib/pip_package_installer.py +31 -4
- toolkit/micrOSdashboard.py +16 -21
- toolkit/micrOSlint.py +28 -10
- toolkit/simulator_lib/.DS_Store +0 -0
- micrOS/source/IO_esp32.py → toolkit/simulator_lib/IO_darwin.py +3 -0
- toolkit/simulator_lib/__pycache__/IO_darwin.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/aioespnow.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/camera.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/framebuf.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/machine.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/micropython.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/mip.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/neopixel.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/network.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/sim_common.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/simgc.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/simulator.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/uasyncio.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/uos.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/urandom.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/usocket.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/ussl.cpython-312.pyc +0 -0
- toolkit/simulator_lib/aioespnow.py +28 -0
- toolkit/simulator_lib/camera.py +84 -0
- toolkit/simulator_lib/dht.py +1 -1
- toolkit/simulator_lib/framebuf.py +49 -1
- toolkit/simulator_lib/machine.py +32 -2
- toolkit/simulator_lib/micropython.py +3 -3
- toolkit/simulator_lib/mip.py +165 -0
- toolkit/simulator_lib/neopixel.py +3 -2
- toolkit/simulator_lib/network.py +2 -1
- toolkit/simulator_lib/node_config.json +2 -3
- toolkit/simulator_lib/ntptime.py +1 -1
- toolkit/simulator_lib/{sim_console.py → sim_common.py} +2 -3
- toolkit/simulator_lib/simgc.py +6 -2
- toolkit/simulator_lib/simulator.py +138 -46
- toolkit/simulator_lib/uasyncio.py +34 -3
- toolkit/simulator_lib/uos.py +147 -0
- toolkit/simulator_lib/urandom.py +4 -0
- toolkit/simulator_lib/usocket.py +5 -1
- toolkit/simulator_lib/view01.jpg +0 -0
- toolkit/simulator_lib/view02.jpg +0 -0
- toolkit/socketClient.py +43 -23
- toolkit/user_data/webhooks/generic.py +1 -1
- toolkit/user_data/webhooks/macro.py +44 -0
- toolkit/user_data/webhooks/template.macro +20 -0
- toolkit/user_data/webhooks/template.py +1 -1
- toolkit/workspace/precompiled/Auth.mpy +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/InterConnect.mpy +0 -0
- toolkit/workspace/precompiled/Interrupts.mpy +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/Pacman.mpy +0 -0
- toolkit/workspace/precompiled/Scheduler.mpy +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/_mpy.version +1 -1
- toolkit/workspace/precompiled/config/_git.keep +0 -0
- toolkit/workspace/precompiled/helpers.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/modules/IO_esp32.mpy +0 -0
- toolkit/workspace/precompiled/modules/IO_esp32c3.mpy +0 -0
- toolkit/workspace/precompiled/modules/IO_esp32c6.mpy +0 -0
- toolkit/workspace/precompiled/modules/IO_esp32s2.mpy +0 -0
- toolkit/workspace/precompiled/modules/IO_esp32s3.mpy +0 -0
- toolkit/workspace/precompiled/modules/IO_m5stamp.mpy +0 -0
- toolkit/workspace/precompiled/modules/IO_qtpy.mpy +0 -0
- toolkit/workspace/precompiled/modules/IO_rp2.mpy +0 -0
- toolkit/workspace/precompiled/modules/IO_tinypico.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_L298N.mpy +0 -0
- {micrOS/source → toolkit/workspace/precompiled/modules}/LM_L9110_DCmotor.py +4 -4
- toolkit/workspace/precompiled/modules/LM_OV2640.mpy +0 -0
- toolkit/workspace/precompiled/{LM_VL53L0X.py → modules/LM_VL53L0X.py} +5 -5
- toolkit/workspace/precompiled/modules/LM_aht10.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_bme280.mpy +0 -0
- toolkit/workspace/precompiled/{LM_buzzer.mpy → modules/LM_buzzer.mpy} +0 -0
- toolkit/workspace/precompiled/modules/LM_cct.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_cluster.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_co2.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_dht11.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_dht22.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_ds18.mpy +0 -0
- toolkit/workspace/precompiled/{LM_esp32.py → modules/LM_esp32.py} +16 -4
- toolkit/workspace/precompiled/modules/LM_espnow.py +53 -0
- toolkit/workspace/precompiled/modules/LM_fileserver.mpy +0 -0
- toolkit/workspace/precompiled/{LM_gameOfLife.mpy → modules/LM_gameOfLife.mpy} +0 -0
- toolkit/workspace/precompiled/modules/LM_genIO.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_haptic.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_i2c.py +61 -0
- toolkit/workspace/precompiled/modules/LM_i2s_mic.mpy +0 -0
- toolkit/workspace/precompiled/{LM_ld2410.mpy → modules/LM_ld2410.mpy} +0 -0
- toolkit/workspace/precompiled/modules/LM_light_sensor.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_mh_z19c.py +198 -0
- toolkit/workspace/precompiled/modules/LM_neoeffects.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_neopixel.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_oled.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_oled_sh1106.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_oled_ui.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_qmi8658.py +204 -0
- toolkit/workspace/precompiled/{LM_rencoder.py → modules/LM_rencoder.py} +40 -11
- toolkit/workspace/precompiled/modules/LM_rest.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_rgb.mpy +0 -0
- toolkit/workspace/precompiled/{LM_rgbcct.mpy → modules/LM_rgbcct.mpy} +0 -0
- toolkit/workspace/precompiled/modules/LM_roboarm.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_robustness.py +137 -0
- toolkit/workspace/precompiled/{LM_rp2w.py → modules/LM_rp2w.py} +3 -0
- toolkit/workspace/precompiled/{LM_sdcard.py → modules/LM_sdcard.py} +3 -0
- toolkit/workspace/precompiled/{LM_servo.mpy → modules/LM_servo.mpy} +0 -0
- toolkit/workspace/precompiled/modules/LM_sound_event.mpy +0 -0
- toolkit/workspace/precompiled/{LM_stepper.mpy → modules/LM_stepper.mpy} +0 -0
- toolkit/workspace/precompiled/modules/LM_switch.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_system.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_tcs3472.py +187 -0
- toolkit/workspace/precompiled/modules/LM_telegram.mpy +0 -0
- toolkit/workspace/precompiled/{LM_tinyrgb.mpy → modules/LM_tinyrgb.mpy} +0 -0
- toolkit/workspace/precompiled/modules/LM_trackball.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_veml7700.mpy +0 -0
- toolkit/workspace/precompiled/modules/LM_web.mpy +0 -0
- toolkit/workspace/precompiled/urequests.mpy +0 -0
- {micrOS/source → toolkit/workspace/precompiled/web}/dashboard.html +9 -4
- toolkit/workspace/precompiled/web/editor.js +440 -0
- toolkit/workspace/precompiled/web/filesui.html +178 -0
- toolkit/workspace/precompiled/web/filesui.js +338 -0
- toolkit/workspace/precompiled/{index.html → web/index.html} +44 -2
- toolkit/workspace/precompiled/web/uapi.js +103 -0
- toolkit/workspace/precompiled/web/udashboard.js +129 -0
- toolkit/workspace/precompiled/web/ustyle.css +55 -0
- toolkit/workspace/precompiled/web/uwidgets.js +172 -0
- toolkit/workspace/precompiled/web/uwidgets_pro.js +99 -0
- env/driver_cp210x/CH34XSER_MAC/CH34X_DRV_INSTALL_INSTRUCTIONS.pdf +0 -0
- env/driver_cp210x/CH34XSER_MAC/CH34xVCPDriver.pkg +0 -0
- micrOS/micropython/esp32-20231005-v1.21.0.bin +0 -0
- micrOS/micropython/esp32c3-GENERIC-20240105-v1.22.1.bin +0 -0
- micrOS/micropython/esp32c3-GENERIC-20240222-v1.22.2.bin +0 -0
- micrOS/micropython/esp32s2-GENERIC-20240105-v1.22.1.bin +0 -0
- micrOS/micropython/esp32s2-LOLIN_MINI-20220618-v1.19.1.bin +0 -0
- micrOS/micropython/esp32s3-GENERIC-20240105-v1.22.1.bin +0 -0
- micrOS/micropython/esp32s3_spiram_oct-20231005-v1.21.0.bin +0 -0
- micrOS/micropython/rpi-pico-w-20231005-v1.21.0.uf2 +0 -0
- micrOS/micropython/tinypico-20231005-v1.21.0.bin +0 -0
- micrOS/micropython/tinypico-usbc-UM-20240105-v1.22.1.bin +0 -0
- micrOS/source/LM_L298N_DCmotor.py +0 -86
- micrOS/source/LM_catgame.py +0 -74
- micrOS/source/LM_dashboard_be.py +0 -37
- micrOS/source/LM_demo.py +0 -85
- micrOS/source/LM_distance.py +0 -88
- micrOS/source/LM_i2c.py +0 -44
- micrOS/source/LM_intercon.py +0 -57
- micrOS/source/LM_keychain.py +0 -318
- micrOS/source/LM_lmpacman.py +0 -126
- micrOS/source/LM_neoeffects.py +0 -327
- micrOS/source/LM_pet_feeder.py +0 -76
- micrOS/source/LM_ph_sensor.py +0 -51
- micrOS/source/LM_rest.py +0 -40
- micrOS/source/LM_robustness.py +0 -73
- micrOS/source/LM_telegram.py +0 -96
- micrOS/source/reset.py +0 -11
- micrOS/source/uapi.js +0 -76
- micrOS/source/udashboard.js +0 -137
- micrOS/source/ustyle.css +0 -28
- micrOS/source/uwidgets.js +0 -179
- micrOSDevToolKit-2.1.5.dist-info/RECORD +0 -337
- toolkit/dashboard_apps/AirQualityBME280.py +0 -36
- toolkit/dashboard_apps/AirQualityDHT22_CO2.py +0 -36
- toolkit/lib/file_extensions.py +0 -16
- toolkit/simulator_lib/__pycache__/LP_darwin.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/LP_darwin.cpython-38.pyc +0 -0
- toolkit/simulator_lib/__pycache__/LP_darwin.cpython-39.pyc +0 -0
- toolkit/simulator_lib/__pycache__/sim_console.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/sim_console.cpython-38.pyc +0 -0
- toolkit/simulator_lib/__pycache__/sim_console.cpython-39.pyc +0 -0
- toolkit/workspace/precompiled/IO_esp32.mpy +0 -0
- toolkit/workspace/precompiled/IO_esp32c3.mpy +0 -0
- toolkit/workspace/precompiled/IO_esp32s2.mpy +0 -0
- toolkit/workspace/precompiled/IO_esp32s3.mpy +0 -0
- toolkit/workspace/precompiled/IO_qtpy.mpy +0 -0
- toolkit/workspace/precompiled/IO_rp2.mpy +0 -0
- toolkit/workspace/precompiled/IO_tinypico.mpy +0 -0
- toolkit/workspace/precompiled/LM_L298N_DCmotor.mpy +0 -0
- toolkit/workspace/precompiled/LM_OV2640.mpy +0 -0
- toolkit/workspace/precompiled/LM_aht10.mpy +0 -0
- toolkit/workspace/precompiled/LM_bme280.mpy +0 -0
- toolkit/workspace/precompiled/LM_catgame.py +0 -74
- toolkit/workspace/precompiled/LM_cct.mpy +0 -0
- toolkit/workspace/precompiled/LM_co2.mpy +0 -0
- toolkit/workspace/precompiled/LM_dashboard_be.py +0 -37
- toolkit/workspace/precompiled/LM_demo.py +0 -85
- toolkit/workspace/precompiled/LM_dht11.mpy +0 -0
- toolkit/workspace/precompiled/LM_dht22.mpy +0 -0
- toolkit/workspace/precompiled/LM_dimmer.mpy +0 -0
- toolkit/workspace/precompiled/LM_distance.py +0 -88
- toolkit/workspace/precompiled/LM_ds18.mpy +0 -0
- toolkit/workspace/precompiled/LM_genIO.mpy +0 -0
- toolkit/workspace/precompiled/LM_i2c.py +0 -44
- toolkit/workspace/precompiled/LM_i2s_mic.mpy +0 -0
- toolkit/workspace/precompiled/LM_intercon.mpy +0 -0
- toolkit/workspace/precompiled/LM_keychain.mpy +0 -0
- toolkit/workspace/precompiled/LM_light_sensor.mpy +0 -0
- toolkit/workspace/precompiled/LM_lmpacman.mpy +0 -0
- toolkit/workspace/precompiled/LM_neoeffects.mpy +0 -0
- toolkit/workspace/precompiled/LM_neopixel.mpy +0 -0
- toolkit/workspace/precompiled/LM_oled.mpy +0 -0
- toolkit/workspace/precompiled/LM_oled_sh1106.mpy +0 -0
- toolkit/workspace/precompiled/LM_oled_ui.mpy +0 -0
- toolkit/workspace/precompiled/LM_pet_feeder.py +0 -76
- toolkit/workspace/precompiled/LM_ph_sensor.py +0 -51
- toolkit/workspace/precompiled/LM_presence.mpy +0 -0
- toolkit/workspace/precompiled/LM_rest.mpy +0 -0
- toolkit/workspace/precompiled/LM_rgb.mpy +0 -0
- toolkit/workspace/precompiled/LM_roboarm.mpy +0 -0
- toolkit/workspace/precompiled/LM_robustness.py +0 -73
- toolkit/workspace/precompiled/LM_switch.mpy +0 -0
- toolkit/workspace/precompiled/LM_system.mpy +0 -0
- toolkit/workspace/precompiled/LM_telegram.mpy +0 -0
- toolkit/workspace/precompiled/reset.mpy +0 -0
- toolkit/workspace/precompiled/uapi.js +0 -76
- toolkit/workspace/precompiled/udashboard.js +0 -137
- toolkit/workspace/precompiled/ustyle.css +0 -28
- toolkit/workspace/precompiled/uwidgets.js +0 -179
- /toolkit/user_data/node_config_archive/.include → /micrOS/source/config/_git.keep +0 -0
- /micrOS/source/{IO_rp2.py → modules/IO_rp2.py} +0 -0
- /micrOS/source/{LM_tinyrgb.py → modules/LM_tinyrgb.py} +0 -0
- {micrOSDevToolKit-2.1.5.dist-info → microsdevtoolkit-2.26.1.dist-info/licenses}/LICENSE +0 -0
- {micrOSDevToolKit-2.1.5.dist-info → microsdevtoolkit-2.26.1.dist-info}/top_level.txt +0 -0
micrOS/source/Tasks.py
CHANGED
|
@@ -10,18 +10,19 @@ Designed by Marcell Ban aka BxNxM
|
|
|
10
10
|
#################################################################
|
|
11
11
|
from sys import modules
|
|
12
12
|
from json import dumps
|
|
13
|
+
from re import match
|
|
13
14
|
import uasyncio as asyncio
|
|
14
15
|
from micropython import schedule
|
|
15
16
|
from utime import ticks_ms, ticks_diff
|
|
16
|
-
from Debug import console_write,
|
|
17
|
+
from Debug import console_write, syslog
|
|
17
18
|
from Config import cfgget
|
|
18
19
|
from Network import sta_high_avail
|
|
19
20
|
|
|
20
21
|
try:
|
|
21
|
-
from gc import collect
|
|
22
|
-
except:
|
|
22
|
+
from gc import collect as gcollect
|
|
23
|
+
except ImportError:
|
|
23
24
|
console_write("[SIMULATOR MODE GC IMPORT]")
|
|
24
|
-
from simgc import collect
|
|
25
|
+
from simgc import collect as gcollect
|
|
25
26
|
|
|
26
27
|
#################################################################
|
|
27
28
|
# Implement custom task class #
|
|
@@ -33,26 +34,52 @@ class TaskBase:
|
|
|
33
34
|
"""
|
|
34
35
|
Async task base definition for common features
|
|
35
36
|
"""
|
|
37
|
+
__slots__ = ['task', 'done', 'out', 'tag', '__callback', '__inloop', '__sleep']
|
|
36
38
|
QUEUE_SIZE = cfgget('aioqueue') # QUEUE size from config
|
|
37
39
|
TASKS = {} # TASK OBJ list
|
|
38
40
|
|
|
39
41
|
def __init__(self):
|
|
40
|
-
self.task = None #
|
|
41
|
-
self.
|
|
42
|
-
self.
|
|
43
|
-
self.
|
|
42
|
+
self.task = None # Store created async task object
|
|
43
|
+
self.tag = None # Task tag (identification)
|
|
44
|
+
self.done = asyncio.Event() # Store task done state
|
|
45
|
+
self.out = "" # Store task output
|
|
44
46
|
|
|
47
|
+
###### BASE METHODS FOR CHILD CLASSES ####
|
|
48
|
+
def _create(self, callback:callable) -> dict:
|
|
49
|
+
"""
|
|
50
|
+
Create async task and register it to TASKS dict by tag
|
|
51
|
+
:param callback: coroutine function
|
|
52
|
+
"""
|
|
53
|
+
# Create async task from coroutine function
|
|
54
|
+
self.task = asyncio.get_event_loop().create_task(callback)
|
|
55
|
+
# Store Task object by key - for task control
|
|
56
|
+
TaskBase.TASKS[self.tag] = self
|
|
57
|
+
return {self.tag: "Starting"}
|
|
58
|
+
|
|
59
|
+
@staticmethod
|
|
60
|
+
def _task_gc():
|
|
61
|
+
"""
|
|
62
|
+
Automatic passive task deletion over QUEUE_SIZE
|
|
63
|
+
"""
|
|
64
|
+
keep = TaskBase.QUEUE_SIZE
|
|
65
|
+
passive = tuple((task_tag for task_tag in list(TaskBase.TASKS) if not TaskBase.is_busy(task_tag)))
|
|
66
|
+
if len(passive) >= keep:
|
|
67
|
+
for i in range(0, len(passive)-keep+1):
|
|
68
|
+
del TaskBase.TASKS[passive[i]]
|
|
69
|
+
gcollect()
|
|
70
|
+
|
|
71
|
+
###### PUBLIC TASK METHODS #####
|
|
45
72
|
@staticmethod
|
|
46
|
-
def is_busy(tag):
|
|
73
|
+
def is_busy(tag:str) -> bool:
|
|
47
74
|
"""
|
|
48
|
-
Check task is busy by tag
|
|
49
|
-
|
|
75
|
+
Check task is busy by tag
|
|
76
|
+
:param tag: for task selection
|
|
50
77
|
"""
|
|
51
78
|
task = TaskBase.TASKS.get(tag, None)
|
|
52
|
-
# return True: busy OR False: not busy (inactive)
|
|
79
|
+
# return True: busy OR False: not busy (inactive) OR None: not exists
|
|
53
80
|
return bool(task is not None and not task.done.is_set())
|
|
54
81
|
|
|
55
|
-
def cancel(self):
|
|
82
|
+
def cancel(self) -> bool:
|
|
56
83
|
"""
|
|
57
84
|
Cancel task (+cleanup)
|
|
58
85
|
"""
|
|
@@ -62,15 +89,38 @@ class TaskBase:
|
|
|
62
89
|
self.task.cancel() # Try to cancel task by asyncio
|
|
63
90
|
except Exception as e:
|
|
64
91
|
if "can't cancel self" != str(e):
|
|
65
|
-
|
|
92
|
+
syslog(f"[WARN] IRQ Task cancel: {e}")
|
|
66
93
|
self.__task_del()
|
|
67
94
|
else:
|
|
68
95
|
return False
|
|
69
96
|
except Exception as e:
|
|
70
|
-
|
|
97
|
+
syslog(f"[ERR] Task kill: {e}")
|
|
71
98
|
return False
|
|
72
99
|
return True
|
|
73
100
|
|
|
101
|
+
@staticmethod
|
|
102
|
+
async def feed(sleep_ms=1):
|
|
103
|
+
"""
|
|
104
|
+
Feed event loop
|
|
105
|
+
:param sleep_ms: in millisecond
|
|
106
|
+
"""
|
|
107
|
+
# TODO?: feed WDT - auto restart when system is frozen
|
|
108
|
+
if sleep_ms <= 0:
|
|
109
|
+
return await asyncio.sleep(0.000_000_1) # 0 means: 100ns (Absolute minimum)
|
|
110
|
+
return await asyncio.sleep_ms(sleep_ms)
|
|
111
|
+
|
|
112
|
+
async def await_result(self, timeout:int=5):
|
|
113
|
+
"""
|
|
114
|
+
Wait for task completion with timeout
|
|
115
|
+
:param timeout: in seconds
|
|
116
|
+
"""
|
|
117
|
+
try:
|
|
118
|
+
await asyncio.wait_for(self.done.wait(), timeout)
|
|
119
|
+
except asyncio.TimeoutError:
|
|
120
|
+
return "Timeout has beed exceeded"
|
|
121
|
+
return self.out
|
|
122
|
+
|
|
123
|
+
###### PRIVATE LCM METHODS #####
|
|
74
124
|
def __task_del(self, keep_cache=False):
|
|
75
125
|
"""
|
|
76
126
|
Delete task from TASKS
|
|
@@ -79,22 +129,13 @@ class TaskBase:
|
|
|
79
129
|
if self.tag in TaskBase.TASKS:
|
|
80
130
|
if not keep_cache: # True - In case of destructor
|
|
81
131
|
del TaskBase.TASKS[self.tag]
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
@staticmethod
|
|
85
|
-
def task_gc():
|
|
86
|
-
keep = TaskBase.QUEUE_SIZE
|
|
87
|
-
passive = tuple([task_tag for task_tag in list(TaskBase.TASKS) if not TaskBase.is_busy(task_tag)])
|
|
88
|
-
if len(passive) >= keep:
|
|
89
|
-
for i in range(0, len(passive)-keep+1):
|
|
90
|
-
del TaskBase.TASKS[passive[i]]
|
|
91
|
-
collect() # GC collect
|
|
132
|
+
gcollect()
|
|
92
133
|
|
|
93
134
|
def __del__(self):
|
|
94
135
|
try:
|
|
95
136
|
self.__task_del(keep_cache=True)
|
|
96
137
|
except Exception as e:
|
|
97
|
-
|
|
138
|
+
syslog(f"[ERR] TaskBase.__del__: {e}")
|
|
98
139
|
|
|
99
140
|
|
|
100
141
|
class NativeTask(TaskBase):
|
|
@@ -103,7 +144,7 @@ class NativeTask(TaskBase):
|
|
|
103
144
|
- could be built in function or custom code from load modules
|
|
104
145
|
"""
|
|
105
146
|
|
|
106
|
-
def create(self, callback=None, tag=None):
|
|
147
|
+
def create(self, callback:callable=None, tag:str=None) -> dict:
|
|
107
148
|
"""
|
|
108
149
|
Create async task with coroutine callback (no queue limit check!)
|
|
109
150
|
+ async socket server task
|
|
@@ -112,15 +153,11 @@ class NativeTask(TaskBase):
|
|
|
112
153
|
"""
|
|
113
154
|
# Create task tag
|
|
114
155
|
self.tag = f"aio.{ticks_ms()}" if tag is None else tag
|
|
115
|
-
if
|
|
156
|
+
if self.is_busy(self.tag):
|
|
116
157
|
# Skip task if already running
|
|
117
|
-
return
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
self.task = asyncio.get_event_loop().create_task(callback)
|
|
121
|
-
# Store Task object by key - for task control
|
|
122
|
-
TaskBase.TASKS[self.tag] = self
|
|
123
|
-
return True
|
|
158
|
+
return {self.tag: "Already running"}
|
|
159
|
+
# Create task with coroutine callback
|
|
160
|
+
return super()._create(callback)
|
|
124
161
|
|
|
125
162
|
def __enter__(self):
|
|
126
163
|
"""
|
|
@@ -137,7 +174,7 @@ class NativeTask(TaskBase):
|
|
|
137
174
|
Helper function for Task creation in Load Modules
|
|
138
175
|
[HINT] Use python with feature to utilize this feature
|
|
139
176
|
"""
|
|
140
|
-
self.
|
|
177
|
+
self._task_gc() # Task pool cleanup
|
|
141
178
|
self.done.set()
|
|
142
179
|
|
|
143
180
|
|
|
@@ -153,7 +190,7 @@ class MagicTask(TaskBase):
|
|
|
153
190
|
self.__inloop = False # [LM] Task while loop for LM callback
|
|
154
191
|
self.__sleep = 20 # [LM] Task while loop - async wait (proc feed) [ms]
|
|
155
192
|
|
|
156
|
-
def create(self, callback=None, loop=None, sleep=None):
|
|
193
|
+
def create(self, callback:list=None, loop:bool=None, sleep:int=None) -> dict:
|
|
157
194
|
"""
|
|
158
195
|
Create async task with function callback (with queue limit check)
|
|
159
196
|
- wrap (sync) function into async task (task_wrapper)
|
|
@@ -163,20 +200,16 @@ class MagicTask(TaskBase):
|
|
|
163
200
|
"""
|
|
164
201
|
# Create task tag
|
|
165
202
|
self.tag = '.'.join(callback[0:2])
|
|
166
|
-
if
|
|
203
|
+
if self.is_busy(self.tag):
|
|
167
204
|
# Skip task if already running
|
|
168
|
-
return
|
|
169
|
-
|
|
205
|
+
return {self.tag: "Already running"}
|
|
170
206
|
# Set parameters for async wrapper
|
|
171
207
|
self.__callback = callback
|
|
172
208
|
self.__inloop = self.__inloop if loop is None else loop
|
|
173
209
|
# Set sleep value for async loop - optional parameter with min sleep limit check (20ms)
|
|
174
210
|
self.__sleep = self.__sleep if sleep is None else sleep if sleep > 19 else self.__sleep
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
# Store Task object by key - for task control
|
|
178
|
-
TaskBase.TASKS[self.tag] = self
|
|
179
|
-
return True
|
|
211
|
+
# Create task with coroutine callback
|
|
212
|
+
return super()._create(self.__task_wrapper())
|
|
180
213
|
|
|
181
214
|
async def __task_wrapper(self):
|
|
182
215
|
"""
|
|
@@ -187,11 +220,11 @@ class MagicTask(TaskBase):
|
|
|
187
220
|
- self.__msg_buf: lm msg object redirect to variable - store lm output
|
|
188
221
|
"""
|
|
189
222
|
while True:
|
|
190
|
-
await
|
|
223
|
+
await self.feed(self.__sleep)
|
|
191
224
|
state, self.out = _exec_lm_core(self.__callback)
|
|
192
225
|
if not state or not self.__inloop:
|
|
193
226
|
break
|
|
194
|
-
self.
|
|
227
|
+
self._task_gc() # Task pool cleanup
|
|
195
228
|
self.done.set()
|
|
196
229
|
|
|
197
230
|
def cancel(self):
|
|
@@ -208,8 +241,10 @@ class Manager:
|
|
|
208
241
|
"""
|
|
209
242
|
micrOS async task handler
|
|
210
243
|
"""
|
|
244
|
+
__slots__ = ['_initialized', 'idle_counter']
|
|
211
245
|
INSTANCE = None # Manager object
|
|
212
246
|
LOAD = 0 # CPU overload measure
|
|
247
|
+
INTERCON = None # Dynamic ref. for interconnect calls
|
|
213
248
|
|
|
214
249
|
def __new__(cls):
|
|
215
250
|
"""
|
|
@@ -223,7 +258,7 @@ class Manager:
|
|
|
223
258
|
cls.INSTANCE._initialized = False
|
|
224
259
|
# Set async event loop exception handler
|
|
225
260
|
asyncio.get_event_loop().set_exception_handler(lambda loop=None, context=None:
|
|
226
|
-
|
|
261
|
+
syslog(f"[aio] exception: {loop}:{context}"))
|
|
227
262
|
return cls.INSTANCE
|
|
228
263
|
|
|
229
264
|
def __init__(self):
|
|
@@ -248,7 +283,7 @@ class Manager:
|
|
|
248
283
|
"""
|
|
249
284
|
if Manager._queue_len() >= TaskBase.QUEUE_SIZE:
|
|
250
285
|
msg = f"[aio] Task queue full: {TaskBase.QUEUE_SIZE}"
|
|
251
|
-
|
|
286
|
+
syslog(msg)
|
|
252
287
|
raise Exception(msg)
|
|
253
288
|
|
|
254
289
|
async def idle_task(self):
|
|
@@ -263,28 +298,33 @@ class Manager:
|
|
|
263
298
|
try:
|
|
264
299
|
while True:
|
|
265
300
|
# [0] Just chill
|
|
266
|
-
await
|
|
301
|
+
await my_task.feed(300)
|
|
267
302
|
# [1] PROBE SYSTEM LOAD + 300ms
|
|
268
303
|
t = ticks_ms()
|
|
269
|
-
await
|
|
304
|
+
await my_task.feed(300)
|
|
270
305
|
delta_rate = int(((ticks_diff(ticks_ms(), t) / 300) - 1) * 100)
|
|
271
306
|
Manager.LOAD = int((Manager.LOAD + delta_rate) / 2) # Average - smooth
|
|
272
307
|
# [2] NETWORK AUTO REPAIR
|
|
273
|
-
if self.idle_counter >
|
|
308
|
+
if self.idle_counter > 300: # ~ 3 min
|
|
274
309
|
self.idle_counter = 0 # Reset counter
|
|
275
|
-
# Check and fix STA network (
|
|
310
|
+
# Check and fix STA network (reboot if target ssid is available not yet connected)
|
|
276
311
|
sta_high_avail()
|
|
277
312
|
self.idle_counter += 1 # Increase counter
|
|
278
313
|
except Exception as e:
|
|
279
|
-
|
|
314
|
+
syslog(f"[ERR] Idle task exists: {e}")
|
|
280
315
|
my_task.done.set()
|
|
281
316
|
|
|
282
317
|
@staticmethod
|
|
283
|
-
def create_task(callback, tag=None, loop=False, delay=None):
|
|
318
|
+
def create_task(callback, tag:str=None, loop:bool=False, delay:int=None) -> dict:
|
|
284
319
|
"""
|
|
285
|
-
Primary interface
|
|
286
|
-
|
|
287
|
-
|
|
320
|
+
Primary interface of micrOS Generic task creator method
|
|
321
|
+
:param tag: task unique identifier
|
|
322
|
+
NativeTask:
|
|
323
|
+
:param callback: callable, coroutine to start a task
|
|
324
|
+
MagicTask with queue limiter:
|
|
325
|
+
:param callback: list of staring (command)
|
|
326
|
+
:param loop: MagicTask looping parameter
|
|
327
|
+
:param delay: MagicTask delay parameter
|
|
288
328
|
"""
|
|
289
329
|
if isinstance(callback, list):
|
|
290
330
|
# Check queue if task is Load Module
|
|
@@ -320,7 +360,7 @@ class Manager:
|
|
|
320
360
|
_tasks = []
|
|
321
361
|
tag_parts = tag.split('.')
|
|
322
362
|
for t in TaskBase.TASKS:
|
|
323
|
-
if t.startswith(tag_parts[0])
|
|
363
|
+
if len(tag_parts) > 1 and t.startswith('.'.join(tag_parts[0:-1])) and tag_parts[-1] == '*':
|
|
324
364
|
_tasks.append(t)
|
|
325
365
|
if len(_tasks) == 0:
|
|
326
366
|
return []
|
|
@@ -344,20 +384,19 @@ class Manager:
|
|
|
344
384
|
return '\n'.join(output)
|
|
345
385
|
|
|
346
386
|
@staticmethod
|
|
347
|
-
def kill(tag):
|
|
387
|
+
def kill(tag:str) -> (bool, str):
|
|
348
388
|
"""
|
|
349
389
|
Primary interface
|
|
350
390
|
Kill/terminate async task
|
|
351
391
|
- by tag: module.function
|
|
352
392
|
- by tag module.*, kill all for selected module
|
|
353
393
|
"""
|
|
354
|
-
|
|
355
394
|
def terminate(_tag):
|
|
356
395
|
to_kill = TaskBase.TASKS.get(_tag, None)
|
|
357
396
|
try:
|
|
358
397
|
return False if to_kill is None else to_kill.cancel()
|
|
359
398
|
except Exception as e:
|
|
360
|
-
|
|
399
|
+
syslog(f"[ERR] Task kill: {e}")
|
|
361
400
|
return False
|
|
362
401
|
|
|
363
402
|
# Handle task group kill (module.*)
|
|
@@ -383,126 +422,130 @@ class Manager:
|
|
|
383
422
|
try:
|
|
384
423
|
asyncio.get_event_loop().run_forever()
|
|
385
424
|
except Exception as e:
|
|
386
|
-
|
|
425
|
+
syslog(f"[aio] loop stopped: {e}")
|
|
387
426
|
asyncio.get_event_loop().close()
|
|
388
427
|
|
|
389
428
|
@staticmethod
|
|
390
|
-
def
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
429
|
+
def task_msg(tag:str, msg:str=None) -> bool|str:
|
|
430
|
+
"""
|
|
431
|
+
Set/Get task message (for server virtual task, etc.)
|
|
432
|
+
"""
|
|
433
|
+
_task = TaskBase.TASKS.get(tag, None)
|
|
434
|
+
if _task is None:
|
|
435
|
+
return False
|
|
436
|
+
# Get task output
|
|
437
|
+
if tag is None:
|
|
438
|
+
return _task.out
|
|
439
|
+
# Set task output
|
|
440
|
+
_task.out = msg
|
|
441
|
+
return True
|
|
395
442
|
|
|
396
443
|
|
|
397
444
|
#################################################################
|
|
398
445
|
# LM EXEC CORE functions #
|
|
399
446
|
#################################################################
|
|
400
|
-
|
|
401
|
-
def exec_lm_pipe(taskstr):
|
|
447
|
+
def exec_builtins(func):
|
|
402
448
|
"""
|
|
403
|
-
|
|
404
|
-
|
|
449
|
+
[Decorator] Module execution built-in commands and modifiers
|
|
450
|
+
- modules - show active modules list
|
|
451
|
+
- task kill ... - task termination
|
|
452
|
+
show ... - task output dump
|
|
453
|
+
- ... >json - postfix to jsonify the output
|
|
405
454
|
"""
|
|
406
|
-
|
|
407
|
-
#
|
|
408
|
-
if
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
455
|
+
def wrapper(arg_list:list, jsonify=None):
|
|
456
|
+
# Ensure the parameter is a list of strings
|
|
457
|
+
if isinstance(arg_list, list) and arg_list:
|
|
458
|
+
# Postfix operator handling
|
|
459
|
+
# ... >json - command output format option
|
|
460
|
+
# ... >>node01.local - intercon: command execution on remote device by hostname/IP address
|
|
461
|
+
arg_list, json_flag = (arg_list[:-1], True) if arg_list[-1] == '>json' else (arg_list, False)
|
|
462
|
+
json_flag = jsonify if isinstance(jsonify, bool) else json_flag
|
|
463
|
+
arg_list, intercon_target = ((arg_list[:-1], arg_list[-1].replace(">>", ""))
|
|
464
|
+
if match(r'^>>[A-Za-z0-9._-]+$', arg_list[-1])
|
|
465
|
+
else (arg_list, None))
|
|
466
|
+
|
|
467
|
+
# INTERCONNECT
|
|
468
|
+
if intercon_target:
|
|
469
|
+
if Manager.INTERCON is None:
|
|
470
|
+
from InterConnect import send_cmd
|
|
471
|
+
Manager.INTERCON = send_cmd
|
|
472
|
+
try:
|
|
473
|
+
out = Manager.INTERCON(host=intercon_target, cmd=arg_list)
|
|
474
|
+
except Exception as e:
|
|
475
|
+
out = {}
|
|
476
|
+
syslog(f"[ERR] Intercon: {e}")
|
|
477
|
+
return True, out
|
|
478
|
+
|
|
479
|
+
# MODULES
|
|
480
|
+
if arg_list[0] == 'modules':
|
|
481
|
+
return True, list((m.strip().replace('LM_', '') for m in modules if m.startswith('LM_'))) + ['task']
|
|
482
|
+
|
|
483
|
+
# Handle task manipulation commands: list, kill, show - return True -> Command handled
|
|
484
|
+
if 'task' == arg_list[0]:
|
|
485
|
+
arg_len = len(arg_list)
|
|
486
|
+
# task list
|
|
487
|
+
if arg_len > 1 and 'list' == arg_list[1]:
|
|
488
|
+
on, off = Manager.list_tasks(json=json_flag)
|
|
489
|
+
# RETURN: JSON mode Human readable mode with cpu & queue info
|
|
490
|
+
return (True, dumps({'active': on[3:], 'inactive': off})) if json_flag else (True, '\n'.join(on) + '\n' + '\n'.join(off) + '\n')
|
|
491
|
+
# task kill <taskID> / task show <taskID>
|
|
492
|
+
if arg_len > 2:
|
|
493
|
+
if 'kill' == arg_list[1]:
|
|
494
|
+
_, msg = Manager.kill(tag=arg_list[2])
|
|
495
|
+
return True, msg
|
|
496
|
+
if 'show' == arg_list[1]:
|
|
497
|
+
return True, Manager.show(tag=arg_list[2])
|
|
498
|
+
return True, "Invalid task cmd! Help: task list / kill <taskID> / show <taskID>"
|
|
499
|
+
|
|
500
|
+
# Call the decorated function with the additional flag
|
|
501
|
+
return func(arg_list, json_flag)
|
|
502
|
+
return False, None
|
|
503
|
+
|
|
504
|
+
return wrapper
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
def lm_exec(arg_list:list, jsonify:bool=None):
|
|
421
508
|
"""
|
|
422
|
-
|
|
423
|
-
-
|
|
509
|
+
Main LM executor function with
|
|
510
|
+
- async (background)
|
|
511
|
+
- sync
|
|
512
|
+
(single) task execution (_exec_lm_core)
|
|
513
|
+
:param arg_list: command parameters
|
|
514
|
+
:param jsonify: request json output (controlled by the decorator)
|
|
515
|
+
Return Bool(OK/NOK), "Command output"
|
|
424
516
|
"""
|
|
425
|
-
try:
|
|
426
|
-
schedule(exec_lm_pipe, taskstr)
|
|
427
|
-
return True
|
|
428
|
-
except Exception as e:
|
|
429
|
-
errlog_add(f"[ERR] exec_lm_pipe_schedule: {e}")
|
|
430
|
-
return False
|
|
431
517
|
|
|
518
|
+
# [1] Async "background" task execution, postfix: &, &&
|
|
519
|
+
if len(arg_list) > 2 and '&' in arg_list[-1]:
|
|
520
|
+
# Evaluate task mode: loop + delay
|
|
521
|
+
mode = arg_list.pop(-1)
|
|
522
|
+
loop = mode.count('&') == 2
|
|
523
|
+
delay = mode.replace('&', '').strip()
|
|
524
|
+
delay = int(delay) if delay.isdigit() else None
|
|
525
|
+
# Create and start async lm task
|
|
526
|
+
try:
|
|
527
|
+
return True, Manager.create_task(arg_list, loop=loop, delay=delay)
|
|
528
|
+
except Exception as e:
|
|
529
|
+
return False, {".".join(arg_list[0:2]): str(e)}
|
|
432
530
|
|
|
433
|
-
def lm_exec(arg_list):
|
|
434
|
-
"""
|
|
435
|
-
Main LM executor function wrapper
|
|
436
|
-
- handle async (background) task execution
|
|
437
|
-
- handle sync task execution (_exec_lm_core)
|
|
438
|
-
"""
|
|
439
|
-
|
|
440
|
-
def task_manager(msg_list):
|
|
441
|
-
msg_len = len(msg_list)
|
|
442
|
-
# [1] Handle task manipulation commands: list, kill, show - return True -> Command handled
|
|
443
|
-
if 'task' == msg_list[0]:
|
|
444
|
-
# task list
|
|
445
|
-
if msg_len > 1 and 'list' == msg_list[1]:
|
|
446
|
-
if msg_len > 2 and msg_list[2].strip() == '>json':
|
|
447
|
-
# JSON mode
|
|
448
|
-
on, off = Manager.list_tasks(json=True)
|
|
449
|
-
return True, {'active': on[3:], 'inactive': off}
|
|
450
|
-
on, off = Manager.list_tasks(json=False)
|
|
451
|
-
# Human readable mode with cpu & queue info
|
|
452
|
-
return True, '\n'.join(on) + '\n' + '\n'.join(off) + '\n' # Show active tasks and passive tasks
|
|
453
|
-
# task kill <taskID> / task show <taskID>
|
|
454
|
-
if msg_len > 2:
|
|
455
|
-
if 'kill' == msg_list[1]:
|
|
456
|
-
state, msg = Manager.kill(tag=msg_list[2])
|
|
457
|
-
return True, msg
|
|
458
|
-
if 'show' == msg_list[1]:
|
|
459
|
-
return True, Manager.show(tag=msg_list[2])
|
|
460
|
-
return True, "Invalid task cmd! Help: task list / kill <taskID> / show <taskID>"
|
|
461
|
-
# [2] Start async task, postfix: &, &&
|
|
462
|
-
if msg_len > 2 and '&' in arg_list[-1]:
|
|
463
|
-
# Evaluate task mode: loop + delay
|
|
464
|
-
mode = arg_list.pop(-1)
|
|
465
|
-
loop = mode.count('&') == 2
|
|
466
|
-
delay = mode.replace('&', '').strip()
|
|
467
|
-
delay = int(delay) if delay.isdigit() else None
|
|
468
|
-
# Create and start async lm task
|
|
469
|
-
try:
|
|
470
|
-
state = Manager.create_task(arg_list, loop=loop, delay=delay)
|
|
471
|
-
except Exception as e:
|
|
472
|
-
# Valid & handled task command
|
|
473
|
-
return True, str(e)
|
|
474
|
-
tag = '.'.join(arg_list[0:2])
|
|
475
|
-
# Valid & handled task command
|
|
476
|
-
if state:
|
|
477
|
-
return True, f"Start {tag}"
|
|
478
|
-
return True, f"{tag} is Busy"
|
|
479
|
-
# Not valid task command
|
|
480
|
-
return False, ''
|
|
481
|
-
|
|
482
|
-
# ================ main function ================
|
|
483
|
-
# modules built-in function: show loaded LoadModules
|
|
484
|
-
if len(arg_list) > 0 and arg_list[0] == 'modules':
|
|
485
|
-
return True, list([m.strip().replace('LM_', '') for m in modules if m.startswith('LM_')])
|
|
486
|
-
# [1] Run task command: start (&), list, kill, show
|
|
487
|
-
is_task, out = task_manager(arg_list)
|
|
488
|
-
if is_task:
|
|
489
|
-
return True, out
|
|
490
531
|
# [2] Sync "realtime" task execution
|
|
491
|
-
state, out = _exec_lm_core(arg_list)
|
|
532
|
+
state, out = _exec_lm_core(arg_list, jsonify)
|
|
492
533
|
return state, out
|
|
493
534
|
|
|
494
535
|
|
|
495
|
-
|
|
536
|
+
@exec_builtins
|
|
537
|
+
def _exec_lm_core(cmd_list, jsonify):
|
|
496
538
|
"""
|
|
497
|
-
CORE
|
|
539
|
+
[CORE] Single command executor: MODULE.FUNCTION...
|
|
498
540
|
:param cmd_list: list of string parameters
|
|
499
541
|
[1] module name (LM)
|
|
500
542
|
[2] function
|
|
501
543
|
[3...] parameters (separator: space)
|
|
502
|
-
|
|
544
|
+
:param jsonify: request json output
|
|
545
|
+
Return Bool(OK/NOK), Str(Command output)
|
|
503
546
|
"""
|
|
504
547
|
|
|
505
|
-
def
|
|
548
|
+
def _func_params(param):
|
|
506
549
|
buf = None
|
|
507
550
|
if "'" in param or '"' in param:
|
|
508
551
|
str_index = [i for i, c in enumerate(param) if c in ('"', "'")]
|
|
@@ -514,12 +557,9 @@ def _exec_lm_core(cmd_list):
|
|
|
514
557
|
param = param.format(*buf)
|
|
515
558
|
return param
|
|
516
559
|
|
|
517
|
-
# Check json mode for LM execution
|
|
518
|
-
json_mode = cmd_list[-1] == '>json'
|
|
519
|
-
cmd_list = cmd_list[0:-1] if json_mode else cmd_list
|
|
520
560
|
# LoadModule execution
|
|
521
561
|
if len(cmd_list) >= 2:
|
|
522
|
-
lm_mod, lm_func, lm_params = f"LM_{cmd_list[0]}", cmd_list[1],
|
|
562
|
+
lm_mod, lm_func, lm_params = f"LM_{cmd_list[0]}", cmd_list[1], _func_params(' '.join(cmd_list[2:]))
|
|
523
563
|
try:
|
|
524
564
|
# ------------- LM LOAD & EXECUTE ------------- #
|
|
525
565
|
# [1] LOAD MODULE - OPTIMIZED by sys.modules
|
|
@@ -540,12 +580,13 @@ def _exec_lm_core(cmd_list):
|
|
|
540
580
|
# ------------ LM output format: dict(jsonify) / str(raw) ------------- #
|
|
541
581
|
# Handle LM output data
|
|
542
582
|
if isinstance(lm_output, dict):
|
|
543
|
-
#
|
|
544
|
-
lm_output = dumps(lm_output) if
|
|
583
|
+
# jsonify (True) json output, (False) default, "human readable" output)
|
|
584
|
+
lm_output = dumps(lm_output) if jsonify else '\n'.join(
|
|
545
585
|
[f" {key}: {value}" for key, value in lm_output.items()])
|
|
546
586
|
if lm_func == 'help':
|
|
547
|
-
# Special case
|
|
548
|
-
|
|
587
|
+
# Special case:
|
|
588
|
+
# jsonify (True) json output, (False) default, "human readable" formatted output)
|
|
589
|
+
lm_output = dumps(lm_output) if jsonify else '\n'.join([f" {out}," for out in lm_output])
|
|
549
590
|
# Return LM exec result
|
|
550
591
|
return True, str(lm_output)
|
|
551
592
|
# ---------------------------------------------------------------------- #
|
|
@@ -554,30 +595,55 @@ def _exec_lm_core(cmd_list):
|
|
|
554
595
|
# UNLOAD MODULE IF MEMORY ERROR HAPPENED + gc.collect
|
|
555
596
|
if lm_mod in modules:
|
|
556
597
|
del modules[lm_mod]
|
|
557
|
-
|
|
598
|
+
gcollect()
|
|
558
599
|
# LM EXECUTION ERROR
|
|
559
600
|
return False, f"Core error: {lm_mod}->{lm_func}: {e}"
|
|
560
601
|
return False, "Shell: for hints type help.\nShell: for LM exec: [1](LM)module [2]function [3...]optional params"
|
|
561
602
|
|
|
603
|
+
|
|
562
604
|
def lm_is_loaded(lm_name):
|
|
563
605
|
"""
|
|
564
606
|
[Auth mode]
|
|
565
607
|
Check lm_name in enabled modules
|
|
566
608
|
"""
|
|
567
|
-
static_keywords =
|
|
609
|
+
static_keywords = ('task', 'modules')
|
|
568
610
|
loaded_mods = [lm.replace('LM_', '') for lm in modules if lm.startswith('LM_')]
|
|
569
611
|
return lm_name in static_keywords or lm_name in loaded_mods
|
|
570
612
|
|
|
571
613
|
|
|
572
|
-
|
|
614
|
+
##################### LM EXEC CORE WRAPPERS #####################
|
|
615
|
+
|
|
616
|
+
def exec_lm_pipe(taskstr):
|
|
573
617
|
"""
|
|
574
|
-
|
|
575
|
-
-
|
|
576
|
-
|
|
618
|
+
Real-time multi command executor
|
|
619
|
+
- with #comment annotation feature
|
|
620
|
+
:param taskstr: contains LM calls separated by ;
|
|
621
|
+
Used for execute config callback parameters (BootHook, IRQs, ...)
|
|
577
622
|
"""
|
|
578
623
|
try:
|
|
579
|
-
|
|
624
|
+
# Handle config default empty value (do nothing)
|
|
625
|
+
if taskstr.startswith('n/a'):
|
|
626
|
+
return True
|
|
627
|
+
# Execute individual commands - msgobj->"/dev/null"
|
|
628
|
+
for cmd in (cmd.strip().split() for cmd in taskstr.split(';') if len(cmd) > 0):
|
|
629
|
+
if cmd[0].startswith("#"):
|
|
630
|
+
console_write(f"[SKIP] exec_lm_pipe: {' '.join(cmd)}")
|
|
631
|
+
continue
|
|
632
|
+
if not lm_exec(cmd)[0]:
|
|
633
|
+
syslog(f"[WARN] exec_lm_pipe: {' '.join(cmd)}")
|
|
634
|
+
except Exception as e:
|
|
635
|
+
syslog(f"[ERR] exec_lm_pipe {taskstr}: {e}")
|
|
636
|
+
return False
|
|
637
|
+
return True
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
def exec_lm_pipe_schedule(taskstr):
|
|
641
|
+
"""
|
|
642
|
+
Scheduled Wrapper for exec_lm_pipe for IRQs (extIRQ, timIRQ, cronIRQ)
|
|
643
|
+
"""
|
|
644
|
+
try:
|
|
645
|
+
schedule(exec_lm_pipe, taskstr)
|
|
580
646
|
return True
|
|
581
647
|
except Exception as e:
|
|
582
|
-
|
|
648
|
+
syslog(f"[ERR] exec_lm_pipe_schedule: {e}")
|
|
583
649
|
return False
|