micrOSDevToolKit 2.9.1__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/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-20241129-v1.24.1.bin → 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 +167 -163
- micrOS/source/Auth.py +37 -0
- micrOS/source/Common.py +361 -116
- micrOS/source/Config.py +32 -22
- micrOS/source/Debug.py +50 -94
- micrOS/source/Espnow.py +377 -100
- micrOS/source/Files.py +207 -0
- micrOS/source/Hooks.py +48 -20
- micrOS/source/InterConnect.py +126 -42
- micrOS/source/Interrupts.py +6 -6
- micrOS/source/Logger.py +63 -26
- micrOS/source/Network.py +41 -21
- micrOS/source/Notify.py +48 -22
- micrOS/source/Pacman.py +326 -0
- micrOS/source/Scheduler.py +14 -54
- micrOS/source/Server.py +67 -69
- micrOS/source/Shell.py +99 -91
- micrOS/source/Tasks.py +141 -95
- micrOS/source/Time.py +19 -18
- micrOS/source/Types.py +53 -9
- micrOS/source/Web.py +381 -76
- 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/config/_git.keep +0 -0
- micrOS/source/helpers.py +132 -0
- micrOS/source/micrOS.py +17 -7
- micrOS/source/micrOSloader.py +5 -12
- micrOS/source/microIO.py +44 -20
- micrOS/source/modules/IO_esp32c6.py +38 -0
- micrOS/source/{IO_esp32s3.py → modules/IO_esp32s3.py} +37 -1
- micrOS/source/{IO_m5stamp.py → modules/IO_m5stamp.py} +35 -1
- micrOS/source/{IO_qtpy.py → modules/IO_qtpy.py} +22 -17
- micrOS/source/{IO_tinypico.py → modules/IO_tinypico.py} +38 -0
- micrOS/source/modules/LM_L298N.py +161 -0
- {toolkit/workspace/precompiled → micrOS/source/modules}/LM_L9110_DCmotor.py +3 -3
- micrOS/source/{LM_OV2640.py → modules/LM_OV2640.py} +45 -27
- micrOS/source/{LM_VL53L0X.py → modules/LM_VL53L0X.py} +3 -3
- micrOS/source/{LM_aht10.py → modules/LM_aht10.py} +2 -2
- micrOS/source/{LM_bme280.py → modules/LM_bme280.py} +3 -3
- micrOS/source/{LM_buzzer.py → modules/LM_buzzer.py} +18 -25
- micrOS/source/{LM_cct.py → modules/LM_cct.py} +17 -21
- micrOS/source/modules/LM_cluster.py +255 -0
- micrOS/source/{LM_co2.py → modules/LM_co2.py} +3 -3
- micrOS/source/{LM_dht11.py → modules/LM_dht11.py} +2 -2
- micrOS/source/{LM_dht22.py → modules/LM_dht22.py} +2 -2
- micrOS/source/{LM_dimmer.py → modules/LM_dimmer.py} +9 -9
- micrOS/source/{LM_distance.py → modules/LM_distance.py} +4 -6
- micrOS/source/{LM_ds18.py → modules/LM_ds18.py} +2 -2
- micrOS/source/{LM_esp32.py → modules/LM_esp32.py} +5 -0
- micrOS/source/modules/LM_espnow.py +53 -0
- micrOS/source/modules/LM_fileserver.py +265 -0
- micrOS/source/{LM_genIO.py → modules/LM_genIO.py} +52 -37
- micrOS/source/{LM_haptic.py → modules/LM_haptic.py} +2 -2
- {toolkit/workspace/precompiled → micrOS/source/modules}/LM_i2c.py +5 -4
- micrOS/source/{LM_i2s_mic.py → modules/LM_i2s_mic.py} +6 -7
- micrOS/source/{LM_ld2410.py → modules/LM_ld2410.py} +2 -2
- micrOS/source/{LM_light_sensor.py → modules/LM_light_sensor.py} +10 -21
- 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} +19 -23
- micrOS/source/{LM_oled.py → modules/LM_oled.py} +2 -2
- micrOS/source/{LM_oled_sh1106.py → modules/LM_oled_sh1106.py} +3 -3
- micrOS/source/{LM_oled_ui.py → modules/LM_oled_ui.py} +72 -64
- micrOS/source/modules/LM_pacman.py +320 -0
- micrOS/source/{LM_presence.py → modules/LM_presence.py} +11 -15
- micrOS/source/modules/LM_qmi8658.py +204 -0
- micrOS/source/{LM_rencoder.py → modules/LM_rencoder.py} +2 -2
- micrOS/source/{LM_rest.py → modules/LM_rest.py} +4 -6
- micrOS/source/{LM_rgb.py → modules/LM_rgb.py} +21 -29
- micrOS/source/{LM_roboarm.py → modules/LM_roboarm.py} +8 -8
- micrOS/source/modules/LM_robustness.py +137 -0
- micrOS/source/{LM_servo.py → modules/LM_servo.py} +3 -3
- micrOS/source/{LM_stepper.py → modules/LM_stepper.py} +5 -5
- micrOS/source/{LM_switch.py → modules/LM_switch.py} +11 -9
- micrOS/source/{LM_system.py → modules/LM_system.py} +38 -32
- micrOS/source/modules/LM_tcs3472.py +187 -0
- micrOS/source/{LM_telegram.py → modules/LM_telegram.py} +164 -116
- micrOS/source/{LM_trackball.py → modules/LM_trackball.py} +3 -3
- micrOS/source/{LM_veml7700.py → modules/LM_veml7700.py} +2 -2
- micrOS/source/modules/LM_web.py +38 -0
- micrOS/source/urequests.py +39 -15
- {toolkit/workspace/precompiled → micrOS/source/web}/dashboard.html +4 -0
- micrOS/source/web/editor.js +440 -0
- micrOS/source/web/filesui.html +178 -0
- micrOS/source/web/filesui.js +338 -0
- {toolkit/workspace/precompiled → micrOS/source/web}/index.html +44 -2
- micrOS/source/{uapi.js → web/uapi.js} +48 -7
- micrOS/source/{ustyle.css → web/ustyle.css} +6 -3
- micrOS/utests/__init__.py +0 -0
- micrOS/utests/test_scheduler.py +435 -0
- {micrOSDevToolKit-2.9.1.data → microsdevtoolkit-2.26.1.data}/scripts/devToolKit.py +33 -3
- {micrOSDevToolKit-2.9.1.dist-info → microsdevtoolkit-2.26.1.dist-info}/METADATA +327 -268
- microsdevtoolkit-2.26.1.dist-info/RECORD +396 -0
- {micrOSDevToolKit-2.9.1.dist-info → microsdevtoolkit-2.26.1.dist-info}/WHEEL +1 -1
- toolkit/DevEnvCompile.py +63 -33
- toolkit/DevEnvOTA.py +58 -22
- toolkit/DevEnvUSB.py +110 -55
- toolkit/Gateway.py +6 -6
- toolkit/LM_to_compile.dat +6 -4
- toolkit/MicrOSDevEnv.py +127 -57
- toolkit/WebRepl.py +73 -0
- toolkit/dashboard_apps/BackupRestore.py +20 -35
- 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 +1 -6
- 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 +202 -105
- toolkit/dashboard_apps/Template_app.py +11 -23
- 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 +4 -4
- 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 +6 -0
- toolkit/lib/micrOSClient.py +123 -50
- toolkit/lib/micrOSClientHistory.py +156 -0
- toolkit/lib/pip_package_installer.py +5 -2
- toolkit/micrOSdashboard.py +12 -17
- toolkit/micrOSlint.py +20 -8
- 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__/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/dht.py +1 -1
- toolkit/simulator_lib/framebuf.py +49 -1
- toolkit/simulator_lib/machine.py +17 -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 +137 -59
- toolkit/simulator_lib/uasyncio.py +33 -2
- toolkit/simulator_lib/uos.py +147 -0
- toolkit/simulator_lib/urandom.py +4 -0
- toolkit/socketClient.py +43 -23
- toolkit/user_data/webhooks/generic.py +1 -1
- toolkit/user_data/webhooks/macro.py +1 -1
- 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/{IO_esp32.mpy → modules/IO_esp32.mpy} +0 -0
- toolkit/workspace/precompiled/{IO_esp32c3.mpy → modules/IO_esp32c3.mpy} +0 -0
- toolkit/workspace/precompiled/modules/IO_esp32c6.mpy +0 -0
- toolkit/workspace/precompiled/{IO_esp32s2.mpy → 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 +3 -3
- toolkit/workspace/precompiled/modules/LM_OV2640.mpy +0 -0
- toolkit/workspace/precompiled/{LM_VL53L0X.py → modules/LM_VL53L0X.py} +3 -3
- toolkit/workspace/precompiled/{LM_aht10.mpy → modules/LM_aht10.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_bme280.mpy → 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/{LM_co2.mpy → modules/LM_co2.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_dht11.mpy → modules/LM_dht11.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_dht22.mpy → 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/{LM_ds18.mpy → modules/LM_ds18.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_esp32.py → modules/LM_esp32.py} +5 -0
- 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/{LM_haptic.mpy → modules/LM_haptic.mpy} +0 -0
- {micrOS/source → toolkit/workspace/precompiled/modules}/LM_i2c.py +5 -4
- 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/{LM_oled.mpy → modules/LM_oled.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_oled_sh1106.mpy → 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} +2 -2
- 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_servo.mpy → modules/LM_servo.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_sound_event.mpy → 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/{LM_trackball.mpy → modules/LM_trackball.mpy} +0 -0
- toolkit/workspace/precompiled/{LM_veml7700.mpy → 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 +4 -0
- toolkit/workspace/precompiled/web/editor.js +440 -0
- toolkit/workspace/precompiled/web/filesui.html +178 -0
- toolkit/workspace/precompiled/web/filesui.js +338 -0
- {micrOS/source → toolkit/workspace/precompiled/web}/index.html +44 -2
- toolkit/workspace/precompiled/{uapi.js → web/uapi.js} +48 -7
- toolkit/workspace/precompiled/{ustyle.css → web/ustyle.css} +6 -3
- micrOS/micropython/esp32-20241129-v1.24.1.bin +0 -0
- micrOS/micropython/esp32c3-20240222-v1.22.2.bin +0 -0
- micrOS/micropython/esp32s2-20240602-v1.23.0.bin +0 -0
- micrOS/micropython/esp32s2-LOLIN_MINI-20220618-v1.19.1.bin +0 -0
- micrOS/micropython/esp32s2-LOLIN_MINI-20240602-v1.23.0.bin +0 -0
- micrOS/micropython/esp32s3-20240105-v1.22.1.bin +0 -0
- micrOS/micropython/esp32s3_spiram_oct-20231005-v1.21.0.bin +0 -0
- micrOS/micropython/esp32s3_spiram_oct-20241129-v1.24.1.bin +0 -0
- micrOS/micropython/rpi-pico-w-20241129-v1.24.1.uf2 +0 -0
- micrOS/micropython/tinypico-20241129-v1.24.1.bin +0 -0
- micrOS/source/LM_L298N_DCmotor.py +0 -86
- micrOS/source/LM_catgame.py +0 -75
- micrOS/source/LM_dashboard_be.py +0 -37
- micrOS/source/LM_demo.py +0 -97
- micrOS/source/LM_espnow.py +0 -23
- micrOS/source/LM_intercon.py +0 -57
- micrOS/source/LM_keychain.py +0 -322
- micrOS/source/LM_lmpacman.py +0 -126
- micrOS/source/LM_neoeffects.py +0 -331
- micrOS/source/LM_oledui.py +0 -972
- micrOS/source/LM_pet_feeder.py +0 -78
- micrOS/source/LM_ph_sensor.py +0 -51
- micrOS/source/LM_robustness.py +0 -74
- micrOS/source/reset.py +0 -11
- micrOSDevToolKit-2.9.1.dist-info/RECORD +0 -365
- 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__/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_esp32s3.mpy +0 -0
- toolkit/workspace/precompiled/IO_m5stamp.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_catgame.py +0 -75
- toolkit/workspace/precompiled/LM_cct.mpy +0 -0
- toolkit/workspace/precompiled/LM_dashboard_be.py +0 -37
- toolkit/workspace/precompiled/LM_demo.py +0 -97
- toolkit/workspace/precompiled/LM_dimmer.mpy +0 -0
- toolkit/workspace/precompiled/LM_distance.mpy +0 -0
- toolkit/workspace/precompiled/LM_espnow.py +0 -23
- toolkit/workspace/precompiled/LM_genIO.mpy +0 -0
- 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_ui.mpy +0 -0
- toolkit/workspace/precompiled/LM_oledui.mpy +0 -0
- toolkit/workspace/precompiled/LM_pet_feeder.py +0 -78
- 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 -74
- 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/node_config.json +0 -1
- toolkit/workspace/precompiled/reset.mpy +0 -0
- /micrOS/source/{IO_esp32.py → modules/IO_esp32.py} +0 -0
- /micrOS/source/{IO_esp32c3.py → modules/IO_esp32c3.py} +0 -0
- /micrOS/source/{IO_esp32s2.py → modules/IO_esp32s2.py} +0 -0
- /micrOS/source/{IO_rp2.py → modules/IO_rp2.py} +0 -0
- /micrOS/source/{LM_gameOfLife.py → modules/LM_gameOfLife.py} +0 -0
- /micrOS/source/{LM_rgbcct.py → modules/LM_rgbcct.py} +0 -0
- /micrOS/source/{LM_rp2w.py → modules/LM_rp2w.py} +0 -0
- /micrOS/source/{LM_sdcard.py → modules/LM_sdcard.py} +0 -0
- /micrOS/source/{LM_sound_event.py → modules/LM_sound_event.py} +0 -0
- /micrOS/source/{LM_tinyrgb.py → modules/LM_tinyrgb.py} +0 -0
- /micrOS/source/{udashboard.js → web/udashboard.js} +0 -0
- /micrOS/source/{uwidgets.js → web/uwidgets.js} +0 -0
- /micrOS/source/{uwidgets_pro.js → web/uwidgets_pro.js} +0 -0
- {micrOSDevToolKit-2.9.1.dist-info → microsdevtoolkit-2.26.1.dist-info/licenses}/LICENSE +0 -0
- {micrOSDevToolKit-2.9.1.dist-info → microsdevtoolkit-2.26.1.dist-info}/top_level.txt +0 -0
- /toolkit/workspace/precompiled/{LM_rp2w.py → modules/LM_rp2w.py} +0 -0
- /toolkit/workspace/precompiled/{LM_sdcard.py → modules/LM_sdcard.py} +0 -0
- /toolkit/workspace/precompiled/{udashboard.js → web/udashboard.js} +0 -0
- /toolkit/workspace/precompiled/{uwidgets.js → web/uwidgets.js} +0 -0
- /toolkit/workspace/precompiled/{uwidgets_pro.js → web/uwidgets_pro.js} +0 -0
micrOS/source/Common.py
CHANGED
|
@@ -2,121 +2,62 @@
|
|
|
2
2
|
micrOS Load Module programming Official API-s
|
|
3
3
|
Designed by Marcell Ban aka BxNxM
|
|
4
4
|
"""
|
|
5
|
-
|
|
6
5
|
from Server import Server, WebCli
|
|
7
|
-
from Debug import
|
|
6
|
+
from Debug import syslog as debug_syslog, console_write
|
|
8
7
|
from Logger import logger, log_get
|
|
8
|
+
from Files import OSPath, path_join
|
|
9
9
|
from microIO import resolve_pin
|
|
10
|
-
from Tasks import TaskBase, Manager, lm_exec
|
|
10
|
+
from Tasks import TaskBase, Manager, lm_exec, lm_is_loaded
|
|
11
11
|
from machine import Pin, ADC
|
|
12
12
|
from Notify import Notify
|
|
13
13
|
|
|
14
|
-
################## Common LM features ##################
|
|
15
14
|
|
|
16
|
-
|
|
15
|
+
#####################################################################################
|
|
16
|
+
# SYSTEM #
|
|
17
|
+
#####################################################################################
|
|
18
|
+
def micro_task(tag:str, task=None, _wrap=False):
|
|
17
19
|
"""
|
|
18
|
-
[LM]
|
|
19
|
-
:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
yield round(from_val + (cnt * delta) * direc)
|
|
30
|
-
else:
|
|
31
|
-
yield round(to_val)
|
|
32
|
-
|
|
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"
|
|
33
31
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
:param args: ch1_from, ch1_to, ch2_from, ch2_to, etc...
|
|
40
|
-
:param interval_sec: interval in sec to calculate optimal fade/transition effect
|
|
41
|
-
return: gen, step_ms OR gen list, step_ms
|
|
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)
|
|
42
37
|
"""
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
step_ms = step_ms_min if step_ms < step_ms_min else step_ms
|
|
47
|
-
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)))
|
|
48
|
-
if len(transitions) == 1:
|
|
49
|
-
return transitions[0], step_ms
|
|
50
|
-
return list(transitions), step_ms
|
|
38
|
+
# --- CREATE (original) ---
|
|
39
|
+
if task is not None:
|
|
40
|
+
return Manager().create_task(callback=task, tag=tag)
|
|
51
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
|
|
52
50
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
[LM] General ADC implementation for auto scaled output: raw, percent, volt
|
|
56
|
-
https://docs.micropython.org/en/latest/esp32/quickref.html#adc-analog-to-digital-conversion
|
|
57
|
-
ADC.ATTN_0DB: 0 dB attenuation, resulting in a full-scale voltage range of 0-1.1V
|
|
58
|
-
ADC.ATTN_2_5DB: 2.5 dB ... of 0-1.5V
|
|
59
|
-
ADC.ATTN_6DB: 6 dB ... of 0-2.2V
|
|
60
|
-
ADC.ATTN_11DB: 11 dB ... of 0-2450mV/
|
|
61
|
-
Note that the absolute maximum voltage rating for input pins is 3.6V. Going near to this boundary risks damage to the IC!
|
|
62
|
-
"""
|
|
63
|
-
OBJS = {}
|
|
51
|
+
# --- GET (_wrap=False): return task object or None if not existing ---
|
|
52
|
+
return TaskBase.TASKS.get(tag, None)
|
|
64
53
|
|
|
65
|
-
def __init__(self, pin):
|
|
66
|
-
self.adp_prop = (65535, 2450) # raw value, 2450mV (so 2,45V)
|
|
67
|
-
self.adc = None
|
|
68
|
-
if not isinstance(pin, int):
|
|
69
|
-
pin = resolve_pin(pin)
|
|
70
|
-
self.adc = ADC(Pin(pin))
|
|
71
|
-
self.adc.atten(ADC.ATTN_11DB) # 2450mV measure range
|
|
72
|
-
|
|
73
|
-
def get(self):
|
|
74
|
-
raw = int((self.adc.read_u16() + self.adc.read_u16())/2) # 16-bit ADC value (0-65535)
|
|
75
|
-
percent = raw / self.adp_prop[0]
|
|
76
|
-
volt = round(percent * self.adp_prop[1] / 1000, 2) # devide with 1000 to get V from mV
|
|
77
|
-
return {'raw': raw, 'percent': round(percent*100, 1), 'volt': volt}
|
|
78
54
|
|
|
79
|
-
|
|
80
|
-
def get_instance(pin):
|
|
81
|
-
if pin in SmartADC.OBJS.keys():
|
|
82
|
-
return SmartADC.OBJS[pin]
|
|
83
|
-
SmartADC.OBJS[pin] = SmartADC(pin)
|
|
84
|
-
return SmartADC.OBJS[pin]
|
|
85
|
-
|
|
86
|
-
################# micrOS feature interfaces #################
|
|
87
|
-
|
|
88
|
-
def micro_task(tag, task=None):
|
|
89
|
-
"""
|
|
90
|
-
[LM] Async task creation
|
|
91
|
-
:param tag:
|
|
92
|
-
[1] tag=None: return task generator object
|
|
93
|
-
[2] tag=taskID: return existing task object by tag
|
|
94
|
-
:param task: coroutine to execute (with built-in overload protection and lcm)
|
|
95
|
-
"""
|
|
96
|
-
if task is None:
|
|
97
|
-
# [1] Task is None -> Get task mode by tag
|
|
98
|
-
# RETURN task obj (access obj.out + obj.done (automatic - with keyword arg))
|
|
99
|
-
async_task = TaskBase.TASKS.get(tag, None)
|
|
100
|
-
return async_task
|
|
101
|
-
if TaskBase.is_busy(tag):
|
|
102
|
-
# [2] Shortcut: Check task state by tag
|
|
103
|
-
# RETURN: None - if task is already running
|
|
104
|
-
return None
|
|
105
|
-
# [3] Create task (not running) + task coroutine was provided
|
|
106
|
-
# RETURN task creation state - success (True) / fail (False)
|
|
107
|
-
state = Manager().create_task(callback=task, tag=tag)
|
|
108
|
-
return state
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
def manage_task(tag, operation):
|
|
55
|
+
def manage_task(tag:str, operation:str):
|
|
112
56
|
"""
|
|
113
57
|
[LM] Async task management
|
|
114
58
|
:param tag: task tag
|
|
115
59
|
:param operation: kill / show / isbusy
|
|
116
60
|
"""
|
|
117
|
-
if Manager is None:
|
|
118
|
-
# RETURN: None - cannot utilize async task functionality
|
|
119
|
-
return None
|
|
120
61
|
if operation == "show":
|
|
121
62
|
return str(Manager().show(tag=tag))
|
|
122
63
|
if operation == "kill":
|
|
@@ -126,41 +67,48 @@ def manage_task(tag, operation):
|
|
|
126
67
|
raise Exception(f"Invalid operation: {operation}")
|
|
127
68
|
|
|
128
69
|
|
|
129
|
-
def exec_cmd(cmd,
|
|
70
|
+
def exec_cmd(cmd:list, jsonify:bool=None, secure=False):
|
|
130
71
|
"""
|
|
131
72
|
[LM] Single (sync) LM execution
|
|
132
|
-
:param cmd: command string list
|
|
133
|
-
:param
|
|
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'
|
|
134
76
|
return state, output
|
|
135
77
|
"""
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
return lm_exec(cmd)
|
|
140
|
-
return lm_exec(cmd) if isinstance(cmd, list) else False, f"Invalid type, must be list: {type(cmd)}"
|
|
78
|
+
if secure and not lm_is_loaded(cmd[0]):
|
|
79
|
+
return False, f"NotAllowed {cmd[0]}"
|
|
80
|
+
return lm_exec(cmd, jsonify=jsonify)
|
|
141
81
|
|
|
142
82
|
|
|
143
|
-
def notify(
|
|
83
|
+
def notify(*args, **kwargs) -> bool:
|
|
144
84
|
"""
|
|
145
|
-
[LM] micrOS common notification handler (Telegram)
|
|
146
|
-
|
|
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
|
|
147
95
|
return: verdict: True/False
|
|
148
96
|
"""
|
|
149
|
-
# (1) Return notification state
|
|
150
|
-
if text is None:
|
|
97
|
+
# (1) Return notification state (if no text input given)
|
|
98
|
+
if kwargs.get("text", args[0] if args else None) is None:
|
|
151
99
|
return Notify.GLOBAL_NOTIFY
|
|
152
100
|
# (2) Send notification
|
|
153
101
|
try:
|
|
154
|
-
out = Notify.notify(
|
|
102
|
+
out = Notify.notify(*args, **kwargs)
|
|
155
103
|
except Exception as e:
|
|
156
|
-
|
|
104
|
+
debug_syslog(f"[ERR] Notify: {e}")
|
|
157
105
|
out = str(e)
|
|
158
106
|
if out is not None and (out.startswith('Sent') or out.endswith('disabled')):
|
|
159
107
|
return True
|
|
160
108
|
return False
|
|
161
109
|
|
|
162
110
|
|
|
163
|
-
def web_endpoint(endpoint, function) -> bool:
|
|
111
|
+
def web_endpoint(endpoint, function, method='GET') -> bool:
|
|
164
112
|
"""
|
|
165
113
|
[LM] Add test endpoint <localhost.local>/endpoint from Load Modules
|
|
166
114
|
:param endpoint: simple string, name of the endpoint
|
|
@@ -171,11 +119,27 @@ def web_endpoint(endpoint, function) -> bool:
|
|
|
171
119
|
[2] Stream function return tuple (multipart_type, data):
|
|
172
120
|
multipart/x-mixed-replace | multipart/form-data, <data>
|
|
173
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
|
|
174
125
|
"""
|
|
175
|
-
WebCli.register(endpoint=endpoint, callback=function)
|
|
126
|
+
WebCli.register(endpoint=endpoint, callback=function, method=method)
|
|
176
127
|
return True
|
|
177
128
|
|
|
178
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 {}
|
|
141
|
+
|
|
142
|
+
|
|
179
143
|
def socket_stream(func):
|
|
180
144
|
"""
|
|
181
145
|
[LM] Decorator for Socket message stream - adds msgobj to the decorated function arg list.
|
|
@@ -193,7 +157,7 @@ def data_logger(f_name, data=None, limit=12, msgobj=None):
|
|
|
193
157
|
[LM] micrOS Common Data logger solution
|
|
194
158
|
- if data None => read mode
|
|
195
159
|
- if data value => write mode
|
|
196
|
-
:param f_name: log name (without extension, automatic: .dat)
|
|
160
|
+
:param f_name: log name (without extension, automatic: .dat, default folder: /data)
|
|
197
161
|
:param data: data to append
|
|
198
162
|
:param limit: line limit (max.: 12 with short lines: limited disk speed!)
|
|
199
163
|
:param msgobj: socket stream object (set automatically!)
|
|
@@ -209,10 +173,291 @@ def data_logger(f_name, data=None, limit=12, msgobj=None):
|
|
|
209
173
|
|
|
210
174
|
|
|
211
175
|
def syslog(msg):
|
|
212
|
-
""" Wrapper of
|
|
213
|
-
return
|
|
176
|
+
""" Wrapper of debug_syslog """
|
|
177
|
+
return debug_syslog(f"{msg}")
|
|
214
178
|
|
|
215
179
|
|
|
216
180
|
def console(msg):
|
|
217
181
|
""" Wrapper of console_write """
|
|
218
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
|
+
|
|
223
|
+
def transition(from_val, to_val, step_ms, interval_sec):
|
|
224
|
+
"""
|
|
225
|
+
[LM] Single Generator for color/value transition:
|
|
226
|
+
:param from_val: from value - start from
|
|
227
|
+
:param to_val: to value - target value
|
|
228
|
+
:param step_ms: step to reach to_val - timirq_seq
|
|
229
|
+
:param interval_sec: time of full interval
|
|
230
|
+
"""
|
|
231
|
+
if interval_sec > 0:
|
|
232
|
+
step_cnt = round((interval_sec*1000)/step_ms)
|
|
233
|
+
delta = abs((from_val-to_val)/step_cnt)
|
|
234
|
+
direc = -1 if from_val > to_val else 1
|
|
235
|
+
for cnt in range(0, step_cnt+1):
|
|
236
|
+
yield round(from_val + (cnt * delta) * direc)
|
|
237
|
+
else:
|
|
238
|
+
yield round(to_val)
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def transition_gen(*args, interval_sec=1.0):
|
|
242
|
+
"""
|
|
243
|
+
[LM] Multiple Generator for color/value transitions:
|
|
244
|
+
- calculate minimum step count -> step_ms
|
|
245
|
+
- autofill and use transition(from_val, to_val, step_ms, interval_sec)
|
|
246
|
+
:param args: ch1_from, ch1_to, ch2_from, ch2_to, etc...
|
|
247
|
+
:param interval_sec: interval in sec to calculate optimal fade/transition effect
|
|
248
|
+
return: gen, step_ms OR gen list, step_ms
|
|
249
|
+
"""
|
|
250
|
+
step_ms_min = 5 # min calculated step is 5 ms - good enough
|
|
251
|
+
delta = max((abs(args[ch_from_i] - args[ch_from_i+1]) for ch_from_i in range(0, len(args)-1, 2)))
|
|
252
|
+
step_ms = 0 if delta == 0 else int(interval_sec*1000 / delta)
|
|
253
|
+
step_ms = step_ms_min if step_ms < step_ms_min else step_ms
|
|
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)))
|
|
255
|
+
if len(transitions) == 1:
|
|
256
|
+
return transitions[0], step_ms
|
|
257
|
+
return list(transitions), step_ms
|
|
258
|
+
|
|
259
|
+
#####################################################################################
|
|
260
|
+
# EXTRAS #
|
|
261
|
+
#####################################################################################
|
|
262
|
+
|
|
263
|
+
class SmartADC:
|
|
264
|
+
"""
|
|
265
|
+
[LM] General ADC implementation for auto scaled output: raw, percent, volt
|
|
266
|
+
https://docs.micropython.org/en/latest/esp32/quickref.html#adc-analog-to-digital-conversion
|
|
267
|
+
ADC.ATTN_0DB: 0 dB attenuation, resulting in a full-scale voltage range of 0-1.1V
|
|
268
|
+
ADC.ATTN_2_5DB: 2.5 dB ... of 0-1.5V
|
|
269
|
+
ADC.ATTN_6DB: 6 dB ... of 0-2.2V
|
|
270
|
+
ADC.ATTN_11DB: 11 dB ... of 0-2450mV/
|
|
271
|
+
Note that the absolute maximum voltage rating for input pins is 3.6V. Going near to this boundary risks damage to the IC!
|
|
272
|
+
"""
|
|
273
|
+
OBJS = {}
|
|
274
|
+
|
|
275
|
+
def __init__(self, pin):
|
|
276
|
+
self.adp_prop = (65535, 2450) # raw value, 2450mV (so 2,45V)
|
|
277
|
+
self.adc = None
|
|
278
|
+
if not isinstance(pin, int):
|
|
279
|
+
pin = resolve_pin(pin)
|
|
280
|
+
self.adc = ADC(Pin(pin))
|
|
281
|
+
self.adc.atten(ADC.ATTN_11DB) # 2450mV measure range
|
|
282
|
+
|
|
283
|
+
def get(self):
|
|
284
|
+
raw = int((self.adc.read_u16() + self.adc.read_u16())/2) # 16-bit ADC value (0-65535)
|
|
285
|
+
percent = raw / self.adp_prop[0]
|
|
286
|
+
volt = round(percent * self.adp_prop[1] / 1000, 2) # devide with 1000 to get V from mV
|
|
287
|
+
return {'raw': raw, 'percent': round(percent*100, 1), 'volt': volt}
|
|
288
|
+
|
|
289
|
+
@staticmethod
|
|
290
|
+
def get_instance(pin):
|
|
291
|
+
if pin in SmartADC.OBJS.keys():
|
|
292
|
+
return SmartADC.OBJS[pin]
|
|
293
|
+
SmartADC.OBJS[pin] = SmartADC(pin)
|
|
294
|
+
return SmartADC.OBJS[pin]
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
class AnimationPlayer:
|
|
298
|
+
"""
|
|
299
|
+
Generic async animation (generator) player.
|
|
300
|
+
"""
|
|
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
|
|
323
|
+
|
|
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
|
|
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))
|
|
341
|
+
|
|
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)
|
|
372
|
+
|
|
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.")
|