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/Common.py
CHANGED
|
@@ -1,32 +1,225 @@
|
|
|
1
1
|
"""
|
|
2
|
-
micrOS Load Module programming API-s
|
|
2
|
+
micrOS Load Module programming Official API-s
|
|
3
3
|
Designed by Marcell Ban aka BxNxM
|
|
4
4
|
"""
|
|
5
|
-
|
|
6
|
-
from
|
|
5
|
+
from Server import Server, WebCli
|
|
6
|
+
from Debug import syslog as debug_syslog, console_write
|
|
7
|
+
from Logger import logger, log_get
|
|
8
|
+
from Files import OSPath, path_join
|
|
9
|
+
from microIO import resolve_pin
|
|
10
|
+
from Tasks import TaskBase, Manager, lm_exec, lm_is_loaded
|
|
7
11
|
from machine import Pin, ADC
|
|
8
|
-
from
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
from Notify import Notify
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
#####################################################################################
|
|
16
|
+
# SYSTEM #
|
|
17
|
+
#####################################################################################
|
|
18
|
+
def micro_task(tag:str, task=None, _wrap=False):
|
|
19
|
+
"""
|
|
20
|
+
[LM] Async task manager.
|
|
21
|
+
Modes:
|
|
22
|
+
A) GET:
|
|
23
|
+
micro_task("tag") -> existing task object or None
|
|
24
|
+
B) CREATE:
|
|
25
|
+
micro_task("tag", task=...) -> True | None | False
|
|
26
|
+
Creates a new async task with the given tag if not already running.
|
|
27
|
+
C) CREATE AS DECORATOR (shortcut):
|
|
28
|
+
@micro_task("main", _wrap=True)
|
|
29
|
+
async def mytask(tag, ...): ...
|
|
30
|
+
# Calling mytask(...) will create/start a new task under "main._mytask"
|
|
31
|
+
|
|
32
|
+
:param tag: Task tag string
|
|
33
|
+
:param task: Coroutine (or list of command arguments) to contract a task with
|
|
34
|
+
the given async task callback
|
|
35
|
+
:param _wrap: When True, return a decorator factory (for use as @micro_task(...))
|
|
36
|
+
:return: Task object (GET), bool|None|False (CREATE), or decorator (DECORATOR)
|
|
37
|
+
"""
|
|
38
|
+
# --- CREATE (original) ---
|
|
39
|
+
if task is not None:
|
|
40
|
+
return Manager().create_task(callback=task, tag=tag)
|
|
41
|
+
|
|
42
|
+
# --- CREATE WITH DECORATOR FACTORY (simplified) ---
|
|
43
|
+
if _wrap:
|
|
44
|
+
def _decorator(async_fn):
|
|
45
|
+
task_tag = f"{tag}._{async_fn.__name__}"
|
|
46
|
+
_launcher = (lambda *args, **kwargs: Manager().create_task(callback=async_fn(task_tag, *args, **kwargs),
|
|
47
|
+
tag=task_tag))
|
|
48
|
+
return _launcher
|
|
49
|
+
return _decorator
|
|
50
|
+
|
|
51
|
+
# --- GET (_wrap=False): return task object or None if not existing ---
|
|
52
|
+
return TaskBase.TASKS.get(tag, None)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def manage_task(tag:str, operation:str):
|
|
56
|
+
"""
|
|
57
|
+
[LM] Async task management
|
|
58
|
+
:param tag: task tag
|
|
59
|
+
:param operation: kill / show / isbusy
|
|
60
|
+
"""
|
|
61
|
+
if operation == "show":
|
|
62
|
+
return str(Manager().show(tag=tag))
|
|
63
|
+
if operation == "kill":
|
|
64
|
+
return Manager().kill(tag=tag)
|
|
65
|
+
if operation == "isbusy":
|
|
66
|
+
return TaskBase.is_busy(tag=tag)
|
|
67
|
+
raise Exception(f"Invalid operation: {operation}")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def exec_cmd(cmd:list, jsonify:bool=None, secure=False):
|
|
71
|
+
"""
|
|
72
|
+
[LM] Single (sync) LM execution
|
|
73
|
+
:param cmd: command string list, ex.: ['system', 'clock']
|
|
74
|
+
:param jsonify: request json output
|
|
75
|
+
:param secure: check LM is loaded, if NOT skip execution 'NotAllowed'
|
|
76
|
+
return state, output
|
|
77
|
+
"""
|
|
78
|
+
if secure and not lm_is_loaded(cmd[0]):
|
|
79
|
+
return False, f"NotAllowed {cmd[0]}"
|
|
80
|
+
return lm_exec(cmd, jsonify=jsonify)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def notify(*args, **kwargs) -> bool:
|
|
84
|
+
"""
|
|
85
|
+
[LM] micrOS common notification handler (Telegram, etc.)
|
|
86
|
+
text (0): notification text / None (return notification state)
|
|
87
|
+
:param channels (optional): select communication interface(s) by class name or an iterable of these.
|
|
88
|
+
If omitted or empty, sends over all available channels.
|
|
89
|
+
Examples (optional parameters):
|
|
90
|
+
Telegram params:
|
|
91
|
+
reply_to: message id to reply to (optional) - default: None
|
|
92
|
+
chat_id: chat identifier - default: None -> auto resolve in child class
|
|
93
|
+
MQTTClient params:
|
|
94
|
+
topic: mqtt topic to send the message - default: None -> auto resolve in child class
|
|
95
|
+
return: verdict: True/False
|
|
96
|
+
"""
|
|
97
|
+
# (1) Return notification state (if no text input given)
|
|
98
|
+
if kwargs.get("text", args[0] if args else None) is None:
|
|
99
|
+
return Notify.GLOBAL_NOTIFY
|
|
100
|
+
# (2) Send notification
|
|
101
|
+
try:
|
|
102
|
+
out = Notify.notify(*args, **kwargs)
|
|
103
|
+
except Exception as e:
|
|
104
|
+
debug_syslog(f"[ERR] Notify: {e}")
|
|
105
|
+
out = str(e)
|
|
106
|
+
if out is not None and (out.startswith('Sent') or out.endswith('disabled')):
|
|
107
|
+
return True
|
|
108
|
+
return False
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def web_endpoint(endpoint, function, method='GET') -> bool:
|
|
112
|
+
"""
|
|
113
|
+
[LM] Add test endpoint <localhost.local>/endpoint from Load Modules
|
|
114
|
+
:param endpoint: simple string, name of the endpoint
|
|
115
|
+
:param function:
|
|
116
|
+
[1] Normal function return tuple (html_type, data):
|
|
117
|
+
image/jpeg | text/html | text/plain, <data>
|
|
118
|
+
<data>: binary | string
|
|
119
|
+
[2] Stream function return tuple (multipart_type, data):
|
|
120
|
+
multipart/x-mixed-replace | multipart/form-data, <data>
|
|
121
|
+
<data>: {'callback':<func>, 'content-type': image/jpeg | audio/l16;*}
|
|
122
|
+
[3] String as file reference from /web
|
|
123
|
+
Example: 'filesui.html'
|
|
124
|
+
:param method: HTTP method name
|
|
125
|
+
"""
|
|
126
|
+
WebCli.register(endpoint=endpoint, callback=function, method=method)
|
|
127
|
+
return True
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def web_mounts(*args, **kwargs):
|
|
131
|
+
"""
|
|
132
|
+
Extend web engine shared root path list
|
|
133
|
+
:param modules: add /modules to web shared path
|
|
134
|
+
:param data: add /data to web shared path
|
|
135
|
+
"""
|
|
136
|
+
try:
|
|
137
|
+
return WebCli.web_mounts(*args, **kwargs)
|
|
138
|
+
except Exception as e:
|
|
139
|
+
syslog(f"[ERR] web_mounts error: {e}")
|
|
140
|
+
return {}
|
|
17
141
|
|
|
18
142
|
|
|
19
143
|
def socket_stream(func):
|
|
20
144
|
"""
|
|
21
|
-
[LM] Socket message
|
|
145
|
+
[LM] Decorator for Socket message stream - adds msgobj to the decorated function arg list.
|
|
22
146
|
Use msgobj as print function: msgobj("hello")
|
|
23
|
-
(
|
|
147
|
+
(Server singleton class - reply all bug/feature)
|
|
24
148
|
"""
|
|
25
149
|
def wrapper(*args, **kwargs):
|
|
26
|
-
return func(*args, **kwargs, msgobj=
|
|
150
|
+
return func(*args, **kwargs, msgobj=Server.reply_all)
|
|
27
151
|
return wrapper
|
|
28
152
|
|
|
29
153
|
|
|
154
|
+
@socket_stream
|
|
155
|
+
def data_logger(f_name, data=None, limit=12, msgobj=None):
|
|
156
|
+
"""
|
|
157
|
+
[LM] micrOS Common Data logger solution
|
|
158
|
+
- if data None => read mode
|
|
159
|
+
- if data value => write mode
|
|
160
|
+
:param f_name: log name (without extension, automatic: .dat, default folder: /data)
|
|
161
|
+
:param data: data to append
|
|
162
|
+
:param limit: line limit (max.: 12 with short lines: limited disk speed!)
|
|
163
|
+
:param msgobj: socket stream object (set automatically!)
|
|
164
|
+
"""
|
|
165
|
+
f_name = f_name if f_name.endswith('.dat') else f'{f_name}.dat'
|
|
166
|
+
# GET LOGGED DATA
|
|
167
|
+
if data is None:
|
|
168
|
+
# return log as msg stream
|
|
169
|
+
log_get(f_name, msgobj=msgobj)
|
|
170
|
+
return True
|
|
171
|
+
# ADD DATA TO LOG
|
|
172
|
+
return logger(data, f_name, limit)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def syslog(msg):
|
|
176
|
+
""" Wrapper of debug_syslog """
|
|
177
|
+
return debug_syslog(f"{msg}")
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def console(msg):
|
|
181
|
+
""" Wrapper of console_write """
|
|
182
|
+
return console_write(msg)
|
|
183
|
+
|
|
184
|
+
#####################################################################################
|
|
185
|
+
# SYSTEM DIRECTORY ACCESS #
|
|
186
|
+
#####################################################################################
|
|
187
|
+
|
|
188
|
+
def data_dir(f_name=None):
|
|
189
|
+
"""
|
|
190
|
+
Access for data dir path
|
|
191
|
+
:param f_name: if given, returns full path, otherwise returns data dir root path
|
|
192
|
+
"""
|
|
193
|
+
root_path = OSPath.DATA
|
|
194
|
+
if f_name is None:
|
|
195
|
+
return root_path
|
|
196
|
+
return path_join(root_path, f_name)
|
|
197
|
+
|
|
198
|
+
def web_dir(f_name=None):
|
|
199
|
+
"""
|
|
200
|
+
Access for web dir path
|
|
201
|
+
:param f_name: if given, returns full path, otherwise returns web dir root path
|
|
202
|
+
"""
|
|
203
|
+
root_path = OSPath.WEB
|
|
204
|
+
if f_name is None:
|
|
205
|
+
return root_path
|
|
206
|
+
return path_join(root_path, f_name)
|
|
207
|
+
|
|
208
|
+
def conf_dir(f_name):
|
|
209
|
+
"""
|
|
210
|
+
Create application configs under config directory
|
|
211
|
+
- node_config.json and config dir read restriction/protection (basic)
|
|
212
|
+
:param f_name: creates custom config path with f_name
|
|
213
|
+
"""
|
|
214
|
+
root_path = OSPath.CONFIG
|
|
215
|
+
if f_name.strip().lstrip("/") == "node_config.json":
|
|
216
|
+
raise Exception("Protected resource: config!")
|
|
217
|
+
return path_join(root_path, f_name)
|
|
218
|
+
|
|
219
|
+
#####################################################################################
|
|
220
|
+
# CHANNEL: SIGNAL GENERATORS #
|
|
221
|
+
#####################################################################################
|
|
222
|
+
|
|
30
223
|
def transition(from_val, to_val, step_ms, interval_sec):
|
|
31
224
|
"""
|
|
32
225
|
[LM] Single Generator for color/value transition:
|
|
@@ -49,20 +242,23 @@ def transition_gen(*args, interval_sec=1.0):
|
|
|
49
242
|
"""
|
|
50
243
|
[LM] Multiple Generator for color/value transitions:
|
|
51
244
|
- calculate minimum step count -> step_ms
|
|
52
|
-
- autofill and use
|
|
245
|
+
- autofill and use transition(from_val, to_val, step_ms, interval_sec)
|
|
53
246
|
:param args: ch1_from, ch1_to, ch2_from, ch2_to, etc...
|
|
54
247
|
:param interval_sec: interval in sec to calculate optimal fade/transition effect
|
|
55
248
|
return: gen, step_ms OR gen list, step_ms
|
|
56
249
|
"""
|
|
57
250
|
step_ms_min = 5 # min calculated step is 5 ms - good enough
|
|
58
|
-
delta = max(
|
|
251
|
+
delta = max((abs(args[ch_from_i] - args[ch_from_i+1]) for ch_from_i in range(0, len(args)-1, 2)))
|
|
59
252
|
step_ms = 0 if delta == 0 else int(interval_sec*1000 / delta)
|
|
60
253
|
step_ms = step_ms_min if step_ms < step_ms_min else step_ms
|
|
61
|
-
transitions = list(
|
|
254
|
+
transitions = list((transition(args[ch_from_i], args[ch_from_i+1], step_ms, interval_sec) for ch_from_i in range(0, len(args)-1, 2)))
|
|
62
255
|
if len(transitions) == 1:
|
|
63
256
|
return transitions[0], step_ms
|
|
64
257
|
return list(transitions), step_ms
|
|
65
258
|
|
|
259
|
+
#####################################################################################
|
|
260
|
+
# EXTRAS #
|
|
261
|
+
#####################################################################################
|
|
66
262
|
|
|
67
263
|
class SmartADC:
|
|
68
264
|
"""
|
|
@@ -80,7 +276,7 @@ class SmartADC:
|
|
|
80
276
|
self.adp_prop = (65535, 2450) # raw value, 2450mV (so 2,45V)
|
|
81
277
|
self.adc = None
|
|
82
278
|
if not isinstance(pin, int):
|
|
83
|
-
pin =
|
|
279
|
+
pin = resolve_pin(pin)
|
|
84
280
|
self.adc = ADC(Pin(pin))
|
|
85
281
|
self.adc.atten(ADC.ATTN_11DB) # 2450mV measure range
|
|
86
282
|
|
|
@@ -91,99 +287,177 @@ class SmartADC:
|
|
|
91
287
|
return {'raw': raw, 'percent': round(percent*100, 1), 'volt': volt}
|
|
92
288
|
|
|
93
289
|
@staticmethod
|
|
94
|
-
def
|
|
290
|
+
def get_instance(pin):
|
|
95
291
|
if pin in SmartADC.OBJS.keys():
|
|
96
292
|
return SmartADC.OBJS[pin]
|
|
97
293
|
SmartADC.OBJS[pin] = SmartADC(pin)
|
|
98
294
|
return SmartADC.OBJS[pin]
|
|
99
295
|
|
|
100
296
|
|
|
101
|
-
|
|
102
|
-
"""
|
|
103
|
-
[LM] Async task creation
|
|
104
|
-
- Indirect interface
|
|
105
|
-
tag:
|
|
106
|
-
[1] tag=None: return task generator object
|
|
107
|
-
[2] tag=taskID: return existing task object by tag
|
|
108
|
-
task: coroutine to execute (built in overload protection and lcm)
|
|
109
|
-
"""
|
|
110
|
-
# [0] Check dependencies
|
|
111
|
-
if TaskBase is None or Manager is None:
|
|
112
|
-
# RETURN: None - cannot utilize async task functionality
|
|
113
|
-
return None
|
|
114
|
-
if task is None:
|
|
115
|
-
# [1] Task is None -> Get task mode by tag
|
|
116
|
-
# RETURN task obj (access obj.out + obj.done (automatic - with keyword arg))
|
|
117
|
-
async_task = TaskBase.TASKS.get(tag, None)
|
|
118
|
-
return async_task
|
|
119
|
-
if TaskBase.is_busy(tag):
|
|
120
|
-
# [2] Shortcut: Check task state by tag
|
|
121
|
-
# RETURN: None - if task is already running
|
|
122
|
-
return None
|
|
123
|
-
# [3] Create task (not running) + task coroutine was provided
|
|
124
|
-
# RETURN task creation state - success (True) / fail (False)
|
|
125
|
-
state = Manager().create_task(callback=task, tag=tag)
|
|
126
|
-
return state
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
@socket_stream
|
|
130
|
-
def data_logger(f_name, data=None, limit=12, msgobj=None):
|
|
297
|
+
class AnimationPlayer:
|
|
131
298
|
"""
|
|
132
|
-
|
|
133
|
-
- if data None => read mode
|
|
134
|
-
- if data value => write mode
|
|
135
|
-
:param f_name: log name (without extension, automatic: .dat)
|
|
136
|
-
:param data: data to append
|
|
137
|
-
:param limit: line limit (max.: 12 with short lines: limited disk speed!)
|
|
138
|
-
:param msgobj: socket stream object (set automatically!)
|
|
299
|
+
Generic async animation (generator) player.
|
|
139
300
|
"""
|
|
140
|
-
f_name = f_name if f_name.endswith('.dat') else f'{f_name}.dat'
|
|
141
|
-
# GET LOGGED DATA
|
|
142
|
-
if data is None:
|
|
143
|
-
# return log as msg stream
|
|
144
|
-
log_get(f_name, msgobj=msgobj)
|
|
145
|
-
return True
|
|
146
|
-
# ADD DATA TO LOG
|
|
147
|
-
return logger(data, f_name, limit)
|
|
148
301
|
|
|
302
|
+
def __init__(self, animation:callable=None, tag:str=None, batch_draw:bool=False, batch_size:int=None, loop:bool=True):
|
|
303
|
+
"""
|
|
304
|
+
Initialize the AnimationPlayer with an optional animation.
|
|
305
|
+
:param animation: Function to GENERATE animation data
|
|
306
|
+
:param tag: Optional task tag for micro_task management.
|
|
307
|
+
:param batch_draw: If True - draw in batches
|
|
308
|
+
:param batch_size: Number of pixels per batch when drawing
|
|
309
|
+
:param loop: If True - loop the animation (default)
|
|
310
|
+
"""
|
|
311
|
+
self.animation:callable = None
|
|
312
|
+
self.batch_draw:bool = batch_draw
|
|
313
|
+
self.__max_batch_size:int = 256 # MAX BATCH SIZE - ASYNC PROTECTION
|
|
314
|
+
self.__batch_size:int = 8 # Default batch size: 8
|
|
315
|
+
self.__loop:bool = loop # Loop the animation (generator)
|
|
316
|
+
self._set_batch_size(batch_size) # Set batch size from parameter
|
|
317
|
+
self._player_speed_ms:int = 10 # Default speed in ms between frames
|
|
318
|
+
main_tag:str = tag if tag else "animation"
|
|
319
|
+
self._task_tag:str = f"{main_tag}.player"
|
|
320
|
+
if animation is not None and not self._set_animation(animation):
|
|
321
|
+
raise Exception("Invalid animation function provided.")
|
|
322
|
+
self.__running:bool = True
|
|
149
323
|
|
|
150
|
-
def
|
|
151
|
-
|
|
152
|
-
|
|
324
|
+
def _set_animation(self, animation:callable) -> bool:
|
|
325
|
+
"""
|
|
326
|
+
Setter to change/set current animation.
|
|
327
|
+
"""
|
|
328
|
+
if callable(animation):
|
|
329
|
+
self.animation = animation
|
|
330
|
+
return True
|
|
331
|
+
return False
|
|
153
332
|
|
|
333
|
+
def _set_batch_size(self, batch_size:int) -> None:
|
|
334
|
+
"""
|
|
335
|
+
Setter to change/set batch size.
|
|
336
|
+
- with max batch size check (due to async event loop feeding)
|
|
337
|
+
"""
|
|
338
|
+
if batch_size is None:
|
|
339
|
+
return
|
|
340
|
+
self.__batch_size = max(0, min(batch_size, self.__max_batch_size))
|
|
154
341
|
|
|
155
|
-
def
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
342
|
+
async def _render(self, my_task):
|
|
343
|
+
# Cache methods for speed
|
|
344
|
+
clear = self.clear
|
|
345
|
+
update = self.update
|
|
346
|
+
draw = self.draw
|
|
347
|
+
# Cache the current animation for comparison
|
|
348
|
+
current_animation = self.animation
|
|
349
|
+
frame_counter = 0
|
|
350
|
+
# Clear the display before each frame
|
|
351
|
+
if not self.batch_draw:
|
|
352
|
+
clear()
|
|
353
|
+
for data in self.animation():
|
|
354
|
+
# Check if animation has changed under the loop
|
|
355
|
+
if not self.__running or self.animation != current_animation:
|
|
356
|
+
# Animation changed — break — clean and restart animation loop.
|
|
357
|
+
clear()
|
|
358
|
+
break
|
|
359
|
+
# Update data cache
|
|
360
|
+
update(*data)
|
|
361
|
+
if self.batch_draw:
|
|
362
|
+
# Batched draw mode
|
|
363
|
+
frame_counter += 1
|
|
364
|
+
if frame_counter >= self.__batch_size:
|
|
365
|
+
draw()
|
|
366
|
+
frame_counter = 0
|
|
367
|
+
await my_task.feed(sleep_ms=self._player_speed_ms)
|
|
368
|
+
else:
|
|
369
|
+
# Real-time draw mode
|
|
370
|
+
draw()
|
|
371
|
+
await my_task.feed(sleep_ms=self._player_speed_ms)
|
|
177
372
|
|
|
178
|
-
def
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
373
|
+
async def _player(self):
|
|
374
|
+
"""
|
|
375
|
+
Async task to play the current animation.
|
|
376
|
+
"""
|
|
377
|
+
with micro_task(tag=self._task_tag) as my_task:
|
|
378
|
+
while self.__running:
|
|
379
|
+
my_task.out = f"Play {self.animation.__name__} ({self._player_speed_ms}ms/frame)"
|
|
380
|
+
try:
|
|
381
|
+
await self._render(my_task)
|
|
382
|
+
except IndexError:
|
|
383
|
+
# Draw after generator exhausted and Restart animation if IndexError occurs
|
|
384
|
+
self.draw()
|
|
385
|
+
if not self.__loop:
|
|
386
|
+
break
|
|
387
|
+
await my_task.feed(sleep_ms=self._player_speed_ms)
|
|
388
|
+
my_task.out = "Restart animation"
|
|
389
|
+
except Exception as e:
|
|
390
|
+
my_task.out = f"Error: {e}"
|
|
391
|
+
break
|
|
392
|
+
my_task.out = f"Animation stopped...{my_task.out}"
|
|
393
|
+
|
|
394
|
+
def control(self, play_speed_ms:int, bt_draw:bool=None, bt_size:int=None, loop:bool=None):
|
|
395
|
+
"""
|
|
396
|
+
Set/Get current play speed of the animation.
|
|
397
|
+
:param play_speed_ms: player loop speed in milliseconds.
|
|
398
|
+
:param bt_draw: batch drawing flag.
|
|
399
|
+
:param bt_size: batch drawing size.
|
|
400
|
+
:param loop: loop flag.
|
|
401
|
+
"""
|
|
402
|
+
if isinstance(play_speed_ms, int):
|
|
403
|
+
self._player_speed_ms = max(0, min(10000, int(play_speed_ms)))
|
|
404
|
+
if isinstance(bt_draw, bool):
|
|
405
|
+
self.batch_draw = bt_draw
|
|
406
|
+
if isinstance(bt_size, int):
|
|
407
|
+
self._set_batch_size(bt_size)
|
|
408
|
+
if isinstance(loop, bool):
|
|
409
|
+
self.__loop = loop
|
|
410
|
+
return {"realtime": not self.batch_draw, "batched": self.batch_draw,
|
|
411
|
+
"size": self.__batch_size, "speed_ms": self._player_speed_ms,
|
|
412
|
+
"loop": self.__loop}
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
def play(self, animation=None, speed_ms=None, bt_draw=False, bt_size=None, loop=True):
|
|
416
|
+
"""
|
|
417
|
+
Play animation via generator function.
|
|
418
|
+
:param animation: Animation generator function.
|
|
419
|
+
:param speed_ms: Speed of the animation in milliseconds. (min.: 3ms)
|
|
420
|
+
:param bt_draw: batch drawing flag.
|
|
421
|
+
:param bt_size: batch drawing size.
|
|
422
|
+
:param loop: Loop the animation.
|
|
423
|
+
:return: Player settings.
|
|
424
|
+
"""
|
|
425
|
+
|
|
426
|
+
if animation is not None:
|
|
427
|
+
if not self._set_animation(animation):
|
|
428
|
+
return "Invalid animation"
|
|
429
|
+
if self.animation is None:
|
|
430
|
+
return "No animation to play"
|
|
431
|
+
# Handle player settings
|
|
432
|
+
settings = self.control(play_speed_ms=speed_ms, bt_draw=bt_draw, bt_size=bt_size, loop=loop)
|
|
433
|
+
# Ensure async loop set up correctly. (After stop operation, it is needed)
|
|
434
|
+
self.__running = True
|
|
435
|
+
# [!] ASYNC TASK CREATION
|
|
436
|
+
state:dict = micro_task(tag=self._task_tag, task=self._player())
|
|
437
|
+
settings["state"] = list(state.values())[0]
|
|
438
|
+
return settings
|
|
439
|
+
|
|
440
|
+
def stop(self):
|
|
441
|
+
"""
|
|
442
|
+
Stop the animation.
|
|
443
|
+
"""
|
|
444
|
+
self.__running = False
|
|
445
|
+
return "Stop animation player"
|
|
446
|
+
|
|
447
|
+
def update(self, *arg, **kwargs):
|
|
448
|
+
"""
|
|
449
|
+
Child class must implement this method to handle drawing logic.
|
|
450
|
+
"""
|
|
451
|
+
raise NotImplementedError("Child class must implement update method.")
|
|
452
|
+
|
|
453
|
+
def draw(self):
|
|
454
|
+
"""
|
|
455
|
+
Draw the current frame.
|
|
456
|
+
"""
|
|
457
|
+
raise NotImplementedError("Child class must implement draw method.")
|
|
458
|
+
|
|
459
|
+
def clear(self):
|
|
460
|
+
"""
|
|
461
|
+
Clear the display.
|
|
462
|
+
"""
|
|
463
|
+
raise NotImplementedError("Child class must implement clear method.")
|