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
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
from machine import Pin, time_pulse_us
|
|
2
|
+
from utime import sleep_us
|
|
3
|
+
from microIO import bind_pin, pinmap_search
|
|
4
|
+
from Common import micro_task
|
|
5
|
+
from Types import resolve
|
|
6
|
+
|
|
7
|
+
__TRIGGER_OBJ = None
|
|
8
|
+
__ECHO_OBJ = None
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def __init_HCSR04():
|
|
12
|
+
"""
|
|
13
|
+
HCSR04 Ultrasonic distance sensor
|
|
14
|
+
"""
|
|
15
|
+
global __TRIGGER_OBJ, __ECHO_OBJ
|
|
16
|
+
if __TRIGGER_OBJ is None or __ECHO_OBJ is None:
|
|
17
|
+
trigger_pin = bind_pin('hcsrtrig')
|
|
18
|
+
echo_pin = bind_pin('hcsrecho')
|
|
19
|
+
# Init trigger pin (out)
|
|
20
|
+
__TRIGGER_OBJ = Pin(trigger_pin, mode=Pin.OUT, pull=None)
|
|
21
|
+
__TRIGGER_OBJ.value(0)
|
|
22
|
+
# Init echo pin (in)
|
|
23
|
+
__ECHO_OBJ = Pin(echo_pin, mode=Pin.IN, pull=None)
|
|
24
|
+
return __TRIGGER_OBJ, __ECHO_OBJ
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def __send_pulse_and_wait(echo_timeout_us=1000000):
|
|
28
|
+
trigger_pin, echo_pin = __init_HCSR04()
|
|
29
|
+
trigger_pin.value(0) # Stabilize the sensor
|
|
30
|
+
sleep_us(5)
|
|
31
|
+
trigger_pin.value(1)
|
|
32
|
+
# Send a 10us pulse.
|
|
33
|
+
sleep_us(10)
|
|
34
|
+
trigger_pin.value(0)
|
|
35
|
+
try:
|
|
36
|
+
pulse_time = time_pulse_us(echo_pin, 1, echo_timeout_us)
|
|
37
|
+
return pulse_time
|
|
38
|
+
except OSError as ex:
|
|
39
|
+
if ex.args[0] == 110: # 110 = ETIMEDOUT
|
|
40
|
+
raise OSError('Out of range')
|
|
41
|
+
raise ex
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
async def __task(period_ms, dimmer, idle_cm):
|
|
45
|
+
average = None
|
|
46
|
+
with micro_task(tag="distance.visual") as my_task:
|
|
47
|
+
while True:
|
|
48
|
+
brightness_max_cm = 200
|
|
49
|
+
brightness_min_cm = 5
|
|
50
|
+
dist = int(measure_cm()["cm"])
|
|
51
|
+
if dist > idle_cm+100:
|
|
52
|
+
await my_task.feed(sleep_ms=50)
|
|
53
|
+
continue
|
|
54
|
+
dist = brightness_max_cm if dist > brightness_max_cm else dist # Limit max
|
|
55
|
+
dist = 0 if dist < brightness_min_cm else dist # Limit min
|
|
56
|
+
average = dist if average is None else (average + dist) / 2
|
|
57
|
+
brightness = int(600 * (average/(brightness_max_cm)))
|
|
58
|
+
if dist >= idle_cm:
|
|
59
|
+
dimmer(5)
|
|
60
|
+
else:
|
|
61
|
+
dimmer(brightness)
|
|
62
|
+
|
|
63
|
+
# Store data in task cache (task show mytask)
|
|
64
|
+
my_task.out = f'Dist: {dist} br: {brightness}'
|
|
65
|
+
# Async sleep - feed event loop
|
|
66
|
+
await my_task.feed(sleep_ms=period_ms)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def start_dimmer_indicator(idle_distance=180):
|
|
70
|
+
"""Distance visualization on LED brightness (LM_dimmer)"""
|
|
71
|
+
from LM_dimmer import set_value
|
|
72
|
+
# [!] ASYNC TASK CREATION [1*] with async task callback + taskID (TAG) handling
|
|
73
|
+
return micro_task(tag="distance.visual", task=__task(period_ms=200, dimmer=set_value, idle_cm=idle_distance))
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
#########################
|
|
77
|
+
# Application functions #
|
|
78
|
+
#########################
|
|
79
|
+
|
|
80
|
+
def load():
|
|
81
|
+
"""
|
|
82
|
+
Initialize HCSR04 ultrasonic distance sensor module
|
|
83
|
+
"""
|
|
84
|
+
__init_HCSR04()
|
|
85
|
+
return "HCSR04 Ultrasonic distance sensor - loaded"
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def measure_mm():
|
|
89
|
+
"""
|
|
90
|
+
To calculate the distance we get the pulse_time and divide it by 2
|
|
91
|
+
(the pulse walk the distance twice) and by 29.1 becasue
|
|
92
|
+
the sound speed on air (343.2 m/s), that It's equivalent to
|
|
93
|
+
0.34320 mm/us that is 1mm each 2.91us
|
|
94
|
+
pulse_time // 2 // 2.91 -> pulse_time // 5.82 -> pulse_time * 100 // 582
|
|
95
|
+
"""
|
|
96
|
+
return {'mm': __send_pulse_and_wait() * 100 // 582}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def measure_cm():
|
|
100
|
+
return {'cm': (__send_pulse_and_wait() / 2) / 29.1}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def deinit():
|
|
104
|
+
global __TRIGGER_OBJ, __ECHO_OBJ
|
|
105
|
+
trigger_pin, echo_pin = __init_HCSR04()
|
|
106
|
+
trigger_pin.deinit()
|
|
107
|
+
echo_pin.deinit()
|
|
108
|
+
__TRIGGER_OBJ = None
|
|
109
|
+
__ECHO_OBJ = None
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
#######################
|
|
113
|
+
# LM helper functions #
|
|
114
|
+
#######################
|
|
115
|
+
|
|
116
|
+
def pinmap():
|
|
117
|
+
"""
|
|
118
|
+
[i] micrOS LM naming convention
|
|
119
|
+
Shows logical pins - pin number(s) used by this Load module
|
|
120
|
+
- info which pins to use for this application
|
|
121
|
+
:return dict: pin name (str) - pin value (int) pairs
|
|
122
|
+
"""
|
|
123
|
+
return pinmap_search(['hcsrtrig', 'hcsrecho', 'dimmer'])
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def help(widgets=False):
|
|
127
|
+
"""
|
|
128
|
+
[i] micrOS LM naming convention - built-in help message
|
|
129
|
+
:return tuple:
|
|
130
|
+
(widgets=False) list of functions implemented by this application
|
|
131
|
+
(widgets=True) list of widget json for UI generation
|
|
132
|
+
"""
|
|
133
|
+
return resolve(('measure_mm', 'TEXTBOX measure_cm', 'deinit', 'pinmap',
|
|
134
|
+
'load', 'start_dimmer_indicator idle_distance=180',
|
|
135
|
+
'[info] HCSR04 Ultrasonic distance sensor'), widgets=widgets)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import machine, onewire, ds18x20, time
|
|
2
|
-
from microIO import
|
|
2
|
+
from microIO import bind_pin, pinmap_search
|
|
3
|
+
from Types import resolve
|
|
3
4
|
|
|
4
5
|
DS_OBJ = None
|
|
5
6
|
|
|
@@ -7,7 +8,7 @@ DS_OBJ = None
|
|
|
7
8
|
def __init_DS18():
|
|
8
9
|
global DS_OBJ
|
|
9
10
|
if DS_OBJ is None:
|
|
10
|
-
ds_pin = machine.Pin(
|
|
11
|
+
ds_pin = machine.Pin(bind_pin('ds18'))
|
|
11
12
|
DS_OBJ = ds18x20.DS18X20(onewire.OneWire(ds_pin))
|
|
12
13
|
return DS_OBJ
|
|
13
14
|
|
|
@@ -16,6 +17,13 @@ def __init_DS18():
|
|
|
16
17
|
# Application functions #
|
|
17
18
|
#########################
|
|
18
19
|
|
|
20
|
+
def load():
|
|
21
|
+
"""
|
|
22
|
+
Initialize DS18 temp sensor module
|
|
23
|
+
"""
|
|
24
|
+
__init_DS18()
|
|
25
|
+
return "DS18 temp sensor module - loaded"
|
|
26
|
+
|
|
19
27
|
def measure():
|
|
20
28
|
"""
|
|
21
29
|
Measure with digital onewire temperature sensor
|
|
@@ -53,7 +61,7 @@ def pinmap():
|
|
|
53
61
|
- info which pins to use for this application
|
|
54
62
|
:return dict: pin name (str) - pin value (int) pairs
|
|
55
63
|
"""
|
|
56
|
-
return
|
|
64
|
+
return pinmap_search('ds18')
|
|
57
65
|
|
|
58
66
|
|
|
59
67
|
def help(widgets=False):
|
|
@@ -63,4 +71,4 @@ def help(widgets=False):
|
|
|
63
71
|
(widgets=False) list of functions implemented by this application
|
|
64
72
|
(widgets=True) list of widget json for UI generation
|
|
65
73
|
"""
|
|
66
|
-
return 'measure', 'pinmap'
|
|
74
|
+
return resolve(('TEXTBOX measure', 'load', 'pinmap'), widgets=widgets)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import esp32
|
|
2
|
+
from Common import syslog
|
|
2
3
|
|
|
3
4
|
#########################
|
|
4
5
|
# Application functions #
|
|
@@ -17,8 +18,19 @@ def temp():
|
|
|
17
18
|
"""
|
|
18
19
|
Measure CPU temperature
|
|
19
20
|
"""
|
|
21
|
+
try:
|
|
22
|
+
cpu_temp = esp32.mcu_temperature()
|
|
23
|
+
return {'MCU temp [C]': int(cpu_temp)}
|
|
24
|
+
except:
|
|
25
|
+
pass
|
|
26
|
+
try:
|
|
27
|
+
raw_temp = esp32.raw_temperature()
|
|
28
|
+
except Exception as e:
|
|
29
|
+
syslog(f"[WARN] cpu temp: {e}")
|
|
30
|
+
return {'CPU temp [C]': -1.0}
|
|
20
31
|
# read the internal temperature of the MCU, in Farenheit
|
|
21
|
-
|
|
32
|
+
cpu_temp = round((raw_temp - 32) / 1.8, 1)
|
|
33
|
+
return {'CPU temp [C]': cpu_temp}
|
|
22
34
|
|
|
23
35
|
|
|
24
36
|
def touch(triglvl=300):
|
|
@@ -28,8 +40,8 @@ def touch(triglvl=300):
|
|
|
28
40
|
:return dict: verdict isTouched and value
|
|
29
41
|
"""
|
|
30
42
|
from machine import TouchPad, Pin
|
|
31
|
-
from microIO import
|
|
32
|
-
t = TouchPad(Pin(
|
|
43
|
+
from microIO import resolve_pin
|
|
44
|
+
t = TouchPad(Pin(resolve_pin('touch_0')))
|
|
33
45
|
value = t.read() # Returns a smaller number when touched
|
|
34
46
|
return {'isTouched': True if value < triglvl else False, 'value': value}
|
|
35
47
|
|
|
@@ -49,7 +61,7 @@ def battery():
|
|
|
49
61
|
|
|
50
62
|
def help(widgets=False):
|
|
51
63
|
"""
|
|
52
|
-
[i] micrOS LM naming convention - built-in help message
|
|
64
|
+
[BETA][i] micrOS LM naming convention - built-in help message
|
|
53
65
|
:return tuple:
|
|
54
66
|
(widgets=False) list of functions implemented by this application
|
|
55
67
|
(widgets=True) list of widget json for UI generation
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from Espnow import ESPNowSS
|
|
2
|
+
ESPNOW = ESPNowSS()
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def send(peer:bytes|str, cmd:str='modules'):
|
|
6
|
+
"""
|
|
7
|
+
Send message to peer (by mac address)
|
|
8
|
+
:param peer: mac address of espnow device
|
|
9
|
+
:param cmd: message string/load module call
|
|
10
|
+
"""
|
|
11
|
+
return ESPNOW.send(peer, cmd)
|
|
12
|
+
|
|
13
|
+
def stats():
|
|
14
|
+
"""
|
|
15
|
+
Get ESPNOW stats
|
|
16
|
+
"""
|
|
17
|
+
return ESPNOW.stats()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def members():
|
|
21
|
+
"""
|
|
22
|
+
Get ESPNow devices
|
|
23
|
+
"""
|
|
24
|
+
return ESPNOW.members()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def handshake(peer:bytes|str):
|
|
28
|
+
"""
|
|
29
|
+
Handshake with ESPNow Peer
|
|
30
|
+
:param peer: mac address of espnow device
|
|
31
|
+
- device name detection
|
|
32
|
+
- address:name caching
|
|
33
|
+
"""
|
|
34
|
+
return ESPNOW.handshake(peer)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def remove(peer:bytes):
|
|
38
|
+
"""
|
|
39
|
+
Remove peer by binary mac address
|
|
40
|
+
:param peer: binary mac address of espnow device
|
|
41
|
+
"""
|
|
42
|
+
return ESPNOW.remove_peer(peer)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def help():
|
|
46
|
+
"""
|
|
47
|
+
ESPNOW sender/receiver with LM execution
|
|
48
|
+
"""
|
|
49
|
+
return ('handshake peer=<mac-address>',
|
|
50
|
+
'send peer=<peer-name> cmd="hello"',
|
|
51
|
+
'remove peer=<binary-mac-address>',
|
|
52
|
+
'stats',
|
|
53
|
+
'members')
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
"""
|
|
2
|
+
micrOS Fileserver addon for WebEngine
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from json import dumps
|
|
6
|
+
from re import compile as recompile
|
|
7
|
+
from uos import stat, rename, mkdir, statvfs
|
|
8
|
+
|
|
9
|
+
from Common import web_endpoint, web_mounts, web_dir, syslog
|
|
10
|
+
from Files import path_join, is_dir, remove_dir, remove_file, OSPath, abs_path, ilist_fs
|
|
11
|
+
from Web import url_path_resolve
|
|
12
|
+
from Auth import sudo
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Shared:
|
|
16
|
+
ROOT_DIR = web_dir("user_data") # Default Public WEB dir
|
|
17
|
+
TMP_DIR = path_join(ROOT_DIR, "tmp") # Temporary directory for partial uploads
|
|
18
|
+
UPLOAD_COUNTER = 0 # Counter for handling partial uploads
|
|
19
|
+
MOUNTS_WRITE_ACCESS = {"$modules": False, "$data": False, "$logs": False}
|
|
20
|
+
# mpy: code bytestream
|
|
21
|
+
HIDE_FEXT = ("mpy",) # Hide / Protect (delete/upload) files with the listed extensions
|
|
22
|
+
|
|
23
|
+
@staticmethod
|
|
24
|
+
def check_write_access(path):
|
|
25
|
+
"""
|
|
26
|
+
Raw input path mount write access checker
|
|
27
|
+
"""
|
|
28
|
+
if "$" in path:
|
|
29
|
+
# Mount alias in path
|
|
30
|
+
for access in Shared.MOUNTS_WRITE_ACCESS:
|
|
31
|
+
if access in path:
|
|
32
|
+
if Shared.MOUNTS_WRITE_ACCESS[access]:
|
|
33
|
+
return # Writeable
|
|
34
|
+
raise ValueError(f'ReadOnly path: {path}')
|
|
35
|
+
else:
|
|
36
|
+
# No mount alias in path
|
|
37
|
+
return # Writeable
|
|
38
|
+
raise ValueError(f'ReadOnly path: {path}')
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
#############################################
|
|
42
|
+
# Web Endpoint Callbacks #
|
|
43
|
+
#############################################
|
|
44
|
+
|
|
45
|
+
def _list_file_paths_clb(root_dir=None):
|
|
46
|
+
"""
|
|
47
|
+
List files shared path
|
|
48
|
+
"""
|
|
49
|
+
if isinstance(root_dir, bytes)and len(root_dir.strip()) > 0:
|
|
50
|
+
# Decode input path from request body
|
|
51
|
+
root_dir = root_dir.decode("ascii")
|
|
52
|
+
else:
|
|
53
|
+
root_dir = Shared.ROOT_DIR
|
|
54
|
+
|
|
55
|
+
# Resolve and Validate path (mount aliases)
|
|
56
|
+
try:
|
|
57
|
+
root_dir = resolve_path(root_dir.replace(web_dir(), ""))
|
|
58
|
+
except Exception as e:
|
|
59
|
+
return "text/plain", str(e)
|
|
60
|
+
|
|
61
|
+
user_data = []
|
|
62
|
+
# Show file content on selected root_dir
|
|
63
|
+
# Hide: .mpy files (non-readable/non-editable)
|
|
64
|
+
for name in (f for f in ilist_fs(path=root_dir, type_filter='f') if f.split(".")[-1] not in Shared.HIDE_FEXT):
|
|
65
|
+
file_path = path_join(root_dir, name)
|
|
66
|
+
user_data.append(file_path)
|
|
67
|
+
|
|
68
|
+
response = [
|
|
69
|
+
{
|
|
70
|
+
'path': file_path.replace(web_dir(),""),
|
|
71
|
+
'size': stat(file_path)[6],
|
|
72
|
+
'created': stat(file_path)[9]
|
|
73
|
+
}
|
|
74
|
+
for file_path in user_data
|
|
75
|
+
]
|
|
76
|
+
return 'application/json', dumps(response)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _delete_file_clb(file_to_delete: bytes):
|
|
80
|
+
file_to_delete = file_to_delete.decode('ascii')
|
|
81
|
+
Shared.check_write_access(file_to_delete)
|
|
82
|
+
filepath = resolve_path(file_to_delete)
|
|
83
|
+
if is_dir(filepath):
|
|
84
|
+
raise ValueError(f'File does not exist: {filepath}')
|
|
85
|
+
# File name extension based delete protection
|
|
86
|
+
if filepath.split(".")[-1] in Shared.HIDE_FEXT:
|
|
87
|
+
raise ValueError(f'Delete access denied: {filepath}')
|
|
88
|
+
verdict = remove_file(filepath)
|
|
89
|
+
return 'text/plain', verdict
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _upload_file_clb(part_headers: dict, part_body: bytes, first=False, last=False):
|
|
93
|
+
"""
|
|
94
|
+
Callback function for handling file uploads (Content-Type: multipart/form-data)
|
|
95
|
+
This callback is invoked on every part.
|
|
96
|
+
"""
|
|
97
|
+
cd = part_headers.get('content-disposition', '')
|
|
98
|
+
target_filepath = None
|
|
99
|
+
filename = ""
|
|
100
|
+
cd_pattern = recompile(r'filename\*?=(?:"([^"]+)"|([^;]+))')
|
|
101
|
+
|
|
102
|
+
if match := cd_pattern.search(cd):
|
|
103
|
+
filepath = match.group(1) or match.group(2)
|
|
104
|
+
filepath = filepath.strip()
|
|
105
|
+
# Reject UTF-8 and percent-encoded UTF-8 filenames (RFC 8187)
|
|
106
|
+
if filepath.lower().startswith("utf-8'"):
|
|
107
|
+
raise ValueError("Percent encoded filenames are not supported")
|
|
108
|
+
Shared.check_write_access(filepath)
|
|
109
|
+
target_filepath = resolve_path(filepath)
|
|
110
|
+
filename = target_filepath.split("/")[-1]
|
|
111
|
+
|
|
112
|
+
# File name extension based upload protection
|
|
113
|
+
if not filename or filename.split(".")[-1] in Shared.HIDE_FEXT:
|
|
114
|
+
raise ValueError(f"Invalid filename in part headers: {filename}")
|
|
115
|
+
target_parts = target_filepath.strip("/").split("/")
|
|
116
|
+
if len(target_parts) == 2 and target_parts[-2] == "web":
|
|
117
|
+
# Write protected /web root -> redirect to user shared dir
|
|
118
|
+
target_filepath = path_join(Shared.ROOT_DIR, filename)
|
|
119
|
+
|
|
120
|
+
if first:
|
|
121
|
+
Shared.UPLOAD_COUNTER += 1
|
|
122
|
+
|
|
123
|
+
if first and last:
|
|
124
|
+
with open(target_filepath, 'wb') as f:
|
|
125
|
+
f.write(part_body)
|
|
126
|
+
elif first and not last:
|
|
127
|
+
tmp_file_path = path_join(Shared.TMP_DIR, f"{filename}.{Shared.UPLOAD_COUNTER}")
|
|
128
|
+
with open(tmp_file_path, 'wb') as f:
|
|
129
|
+
f.write(part_body)
|
|
130
|
+
else:
|
|
131
|
+
tmp_file_path = path_join(Shared.TMP_DIR, f"{filename}.{Shared.UPLOAD_COUNTER}")
|
|
132
|
+
with open(tmp_file_path, 'ab') as f:
|
|
133
|
+
f.write(part_body)
|
|
134
|
+
if last:
|
|
135
|
+
rename(tmp_file_path, target_filepath)
|
|
136
|
+
|
|
137
|
+
return 'text/plain', 'ok'
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def _disk_usage_clb():
|
|
141
|
+
"""
|
|
142
|
+
Calculate disk usage
|
|
143
|
+
return {'used': <bytes used>, 'free': <bytes free>}
|
|
144
|
+
"""
|
|
145
|
+
# Check root dir usage
|
|
146
|
+
fs_stat = statvfs(OSPath._ROOT)
|
|
147
|
+
fs_free = fs_stat[0] * fs_stat[3]
|
|
148
|
+
fs_size = fs_stat[0] * fs_stat[2]
|
|
149
|
+
used = fs_size - fs_free
|
|
150
|
+
return 'application/json', dumps({'used': used, 'free': fs_free})
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
#############################################
|
|
154
|
+
# Public functions #
|
|
155
|
+
#############################################
|
|
156
|
+
|
|
157
|
+
def load(web_data_dir:str=None):
|
|
158
|
+
"""
|
|
159
|
+
Initialize fileserver.
|
|
160
|
+
:param web_data_dir: web data public directory (default: /web/<user_data>)
|
|
161
|
+
"""
|
|
162
|
+
if isinstance(web_data_dir, str):
|
|
163
|
+
# Customize public web dir name
|
|
164
|
+
Shared.ROOT_DIR = web_dir(web_data_dir)
|
|
165
|
+
Shared.TMP_DIR = path_join(Shared.ROOT_DIR, 'tmp')
|
|
166
|
+
if is_dir(Shared.TMP_DIR):
|
|
167
|
+
remove_dir(Shared.TMP_DIR, force=True) # Clean existing partial uploads, is force needed?
|
|
168
|
+
if not is_dir(Shared.ROOT_DIR):
|
|
169
|
+
root_dir = web_dir()
|
|
170
|
+
base_dir = root_dir
|
|
171
|
+
for subdir in Shared.TMP_DIR.replace(root_dir, "").split('/'):
|
|
172
|
+
current_dir = path_join(base_dir, subdir)
|
|
173
|
+
if not is_dir(current_dir):
|
|
174
|
+
mkdir(current_dir)
|
|
175
|
+
base_dir = current_dir
|
|
176
|
+
|
|
177
|
+
# Register endpoints
|
|
178
|
+
# [GET] List shared directories
|
|
179
|
+
web_endpoint('fs/dirs', lambda: ('application/json', dumps(get_shared_dirs())))
|
|
180
|
+
# [GET] List help message
|
|
181
|
+
web_endpoint('fs/list', lambda: ('text/plain', 'USE THIS AS POST Endpoint, select dir in http body'))
|
|
182
|
+
# [POST] List selected directory content
|
|
183
|
+
web_endpoint('fs/list', _list_file_paths_clb, 'POST')
|
|
184
|
+
# [GET] Files - list user files
|
|
185
|
+
web_endpoint('fs/files', _list_file_paths_clb)
|
|
186
|
+
# [DELETE] Files - delete selected file
|
|
187
|
+
web_endpoint('fs/files', _delete_file_clb, 'DELETE')
|
|
188
|
+
# [POST] Upload file to the selected path (in filename)
|
|
189
|
+
web_endpoint('fs/files', _upload_file_clb, 'POST')
|
|
190
|
+
# [GET] Show internal flash storage usage
|
|
191
|
+
web_endpoint('fs/usage', _disk_usage_clb)
|
|
192
|
+
# [GET] Fileserver homepage UI
|
|
193
|
+
web_endpoint('fs', 'filesui.html')
|
|
194
|
+
|
|
195
|
+
return "Fileserver was initialized, endpoints: /fs, /fs/files, /fs/dirs, /fs/usage"
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def resolve_path(path):
|
|
199
|
+
"""
|
|
200
|
+
Resolve and Validate input path
|
|
201
|
+
:param path: URL resource path or mount path string
|
|
202
|
+
"""
|
|
203
|
+
# Path resolve and validation
|
|
204
|
+
path = abs_path(path)
|
|
205
|
+
err, path = url_path_resolve(path)
|
|
206
|
+
if err:
|
|
207
|
+
raise ValueError(f"Invalid path: {path}")
|
|
208
|
+
filename = path.split("/")[-1]
|
|
209
|
+
# Filename validation
|
|
210
|
+
filename_pattern = recompile(r"^[a-zA-Z0-9._-]+$")
|
|
211
|
+
if not filename_pattern.match(filename):
|
|
212
|
+
raise ValueError(f"Filename contains invalid characters: {path}")
|
|
213
|
+
return path
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def get_shared_dirs() -> list:
|
|
217
|
+
"""
|
|
218
|
+
Getter for web shared dirs
|
|
219
|
+
- default: /web/Shared.ROOT_DIR
|
|
220
|
+
- extended: web_mounts()
|
|
221
|
+
"""
|
|
222
|
+
web_dirs = list([a for a, p in web_mounts().items() if p is not None])
|
|
223
|
+
web_dirs.insert(0, Shared.ROOT_DIR.replace(web_dir(), ""))
|
|
224
|
+
return web_dirs
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def get_user_dir():
|
|
228
|
+
"""
|
|
229
|
+
Getter for user configured shared dir
|
|
230
|
+
- used by other load modules
|
|
231
|
+
"""
|
|
232
|
+
return Shared.ROOT_DIR
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def extend_mounts(modules:bool=None, data:bool=None, logs:bool=None):
|
|
236
|
+
"""
|
|
237
|
+
Extend web engine shared root path list
|
|
238
|
+
:param modules: add/remove /modules to web shared path
|
|
239
|
+
:param data: add/remove /data to web shared path
|
|
240
|
+
:param logs: add/remove /logs web shared path
|
|
241
|
+
"""
|
|
242
|
+
return web_mounts(modules, data, logs)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
@sudo
|
|
246
|
+
def mounts_write_access(modules:bool=None, data:bool=None, logs:bool=None):
|
|
247
|
+
if modules is not None:
|
|
248
|
+
Shared.MOUNTS_WRITE_ACCESS["$modules"] = modules
|
|
249
|
+
if data is not None:
|
|
250
|
+
Shared.MOUNTS_WRITE_ACCESS["$data"] = data
|
|
251
|
+
if logs is not None:
|
|
252
|
+
Shared.MOUNTS_WRITE_ACCESS["$logs"] = logs
|
|
253
|
+
return Shared.MOUNTS_WRITE_ACCESS
|
|
254
|
+
|
|
255
|
+
#######################
|
|
256
|
+
# Helper LM functions #
|
|
257
|
+
#######################
|
|
258
|
+
|
|
259
|
+
def help(widgets=False):
|
|
260
|
+
return (f'load web_data_dir=<shared directory under {web_dir()}>',
|
|
261
|
+
'resolve_path "<str>"',
|
|
262
|
+
'get_shared_dirs',
|
|
263
|
+
'get_user_dir',
|
|
264
|
+
'extend_mounts modules:bool=None data:bool=None logs:bool=None',
|
|
265
|
+
'mounts_write_access modules:bool=None data:bool=None logs:bool=None')
|
|
@@ -145,7 +145,7 @@ Custom config usage:
|
|
|
145
145
|
def my_config(add_cells):
|
|
146
146
|
# custom cells
|
|
147
147
|
cells = ((10,10),(1,0,0),(0,1,1),(0,0,1))
|
|
148
|
-
|
|
148
|
+
load(w=32, h=16, custom=cells)
|
|
149
149
|
|
|
150
150
|
matrix = []
|
|
151
151
|
while matrix is not None:
|
|
@@ -153,7 +153,7 @@ def my_config(add_cells):
|
|
|
153
153
|
print(matrix)
|
|
154
154
|
"""
|
|
155
155
|
|
|
156
|
-
def
|
|
156
|
+
def load(w=32, h=16, custom=None):
|
|
157
157
|
"""
|
|
158
158
|
Init Conway's Game of Life
|
|
159
159
|
:param w: width of display (pixel)
|
|
@@ -171,14 +171,14 @@ def load_n_init(w=32, h=16, custom=None):
|
|
|
171
171
|
def next_gen(raw=False, w=32, h=16):
|
|
172
172
|
"""
|
|
173
173
|
Main Game of Life function
|
|
174
|
-
Get Next Generation of cells (with auto
|
|
174
|
+
Get Next Generation of cells (with auto load and GoL reinit)
|
|
175
175
|
:param raw: Output type (raw:True -> matrix), (raw:False formatted output)
|
|
176
176
|
:param w: width of display (pixel) - auto init
|
|
177
177
|
:param h: height of display (pixel) - auto init
|
|
178
178
|
return change of life matrix or None if there is no change (on None, restart feature: call reset())
|
|
179
179
|
"""
|
|
180
180
|
if GoL.GOL is None:
|
|
181
|
-
|
|
181
|
+
load(w=w, h=h)
|
|
182
182
|
matrix = GoL.GOL.next_gen()
|
|
183
183
|
if raw:
|
|
184
184
|
return matrix # Matrix / None (no change)
|
|
@@ -205,4 +205,4 @@ def help(widgets=False):
|
|
|
205
205
|
(widgets=False) list of functions implemented by this application
|
|
206
206
|
(widgets=True) list of widget json for UI generation
|
|
207
207
|
"""
|
|
208
|
-
return '
|
|
208
|
+
return 'load w=32 h=16 custom=None', 'next_gen w=32 h=16 raw=False', 'reset'
|