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/Server.py
CHANGED
|
@@ -13,21 +13,34 @@ Designed by Marcell Ban aka BxNxM GitHub
|
|
|
13
13
|
import uasyncio as asyncio
|
|
14
14
|
from utime import ticks_ms, ticks_diff
|
|
15
15
|
from Config import cfgget
|
|
16
|
-
from Debug import console_write,
|
|
16
|
+
from Debug import console_write, syslog
|
|
17
17
|
from Network import ifconfig
|
|
18
18
|
from Tasks import Manager
|
|
19
19
|
from Shell import Shell
|
|
20
20
|
try:
|
|
21
|
-
from gc import collect
|
|
21
|
+
from gc import collect
|
|
22
22
|
except:
|
|
23
23
|
console_write("[SIMULATOR MODE GC IMPORT]")
|
|
24
|
-
from simgc import collect
|
|
24
|
+
from simgc import collect
|
|
25
25
|
|
|
26
26
|
# Module load optimization, needed only for webui
|
|
27
27
|
if cfgget('webui'):
|
|
28
|
-
from
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
from Web import WebEngine
|
|
29
|
+
else:
|
|
30
|
+
# Create dummy web engine - Lazy loading
|
|
31
|
+
class WebEngine:
|
|
32
|
+
__slots__ = []
|
|
33
|
+
def __init__(self, *args, **kwargs):
|
|
34
|
+
pass
|
|
35
|
+
@staticmethod
|
|
36
|
+
def register(*args, **kwargs) -> None:
|
|
37
|
+
"""Child class can implement"""
|
|
38
|
+
syslog(f"[WARN] webui disabled, skip register: {kwargs.get('endpoint')}")
|
|
39
|
+
@staticmethod
|
|
40
|
+
def web_mounts(*args, **kwargs) -> dict:
|
|
41
|
+
"""Child class can implement"""
|
|
42
|
+
syslog(f"[WARN] webui disabled, skip web_mounts: {kwargs.get('endpoint')}")
|
|
43
|
+
return {}
|
|
31
44
|
|
|
32
45
|
#########################################################
|
|
33
46
|
# SOCKET SERVER-CLIENT HANDLER CLASSES #
|
|
@@ -59,19 +72,25 @@ class Client:
|
|
|
59
72
|
console_write("|" + "-" * Client.INDENT + msg)
|
|
60
73
|
Client.INDENT += 1 if Client.INDENT < 50 else 0 # Auto indent
|
|
61
74
|
|
|
62
|
-
async def read(self):
|
|
75
|
+
async def read(self, decoding='utf8', timeout_seconds=0):
|
|
63
76
|
"""
|
|
64
77
|
[Base] Implements client read function, reader size: 2048
|
|
65
|
-
|
|
66
|
-
-
|
|
67
|
-
-
|
|
68
|
-
- exit command handling (stop: return True)
|
|
78
|
+
:return tuple: read_error, data
|
|
79
|
+
- read_error is set to true upon timeout or other exception
|
|
80
|
+
- data holds bytes or decoded string read from the socket
|
|
69
81
|
"""
|
|
70
82
|
Client.console(f"[Client] read {self.client_id}")
|
|
71
83
|
self.last_msg_t = ticks_ms()
|
|
72
84
|
try:
|
|
73
|
-
|
|
74
|
-
|
|
85
|
+
if timeout_seconds:
|
|
86
|
+
request = await asyncio.wait_for(self.reader.read(self.read_bytes), timeout_seconds)
|
|
87
|
+
else:
|
|
88
|
+
request = await self.reader.read(self.read_bytes)
|
|
89
|
+
if decoding:
|
|
90
|
+
request = request.decode(decoding)
|
|
91
|
+
except asyncio.TimeoutError:
|
|
92
|
+
Client.console(f"[Client] Stream read timeout ({self.client_id}), timeout={timeout_seconds}s")
|
|
93
|
+
return True, ''
|
|
75
94
|
except Exception as e:
|
|
76
95
|
Client.console(f"[Client] Stream read error ({self.client_id}): {e}")
|
|
77
96
|
collect() # gc collection: "fix" for memory allocation failed, allocating 2049 bytes
|
|
@@ -79,8 +98,6 @@ class Client:
|
|
|
79
98
|
|
|
80
99
|
# Input handling
|
|
81
100
|
Client.console(f"[Client] raw request ({self.client_id}): |{request}|")
|
|
82
|
-
if request in ('exit', ''):
|
|
83
|
-
return True, request
|
|
84
101
|
return False, request
|
|
85
102
|
|
|
86
103
|
async def a_send(self, response, encode='utf8'):
|
|
@@ -95,7 +112,7 @@ class Client:
|
|
|
95
112
|
except Exception as e:
|
|
96
113
|
# Maintain ACTIVE_CLIS - remove closed connection by peer.
|
|
97
114
|
await self.close()
|
|
98
|
-
|
|
115
|
+
syslog(f"[WARN] Client.a_send (auto-drop) {self.client_id}: {e}")
|
|
99
116
|
return # Abort async send (no drain)
|
|
100
117
|
# Send buffered data with async task - hacky
|
|
101
118
|
try:
|
|
@@ -107,10 +124,10 @@ class Client:
|
|
|
107
124
|
Client.console(f"[Client] Drain error -> close conn: {e}")
|
|
108
125
|
await self.close()
|
|
109
126
|
else:
|
|
110
|
-
console_write(
|
|
127
|
+
console_write("[Client] NoCon: response>dev/nul")
|
|
111
128
|
|
|
112
129
|
def send(self, response):
|
|
113
|
-
# Implement in child class - synchronous send method
|
|
130
|
+
# Optional - Implement in child class - synchronous send (all) method
|
|
114
131
|
pass
|
|
115
132
|
|
|
116
133
|
async def close(self):
|
|
@@ -138,7 +155,7 @@ class Client:
|
|
|
138
155
|
if Client.ACTIVE_CLIS.get(client_id, None) is not None:
|
|
139
156
|
Client.ACTIVE_CLIS.pop(client_id)
|
|
140
157
|
# Update server task output (? test ?)
|
|
141
|
-
Manager().
|
|
158
|
+
Manager().task_msg('server', ','.join(list(Client.ACTIVE_CLIS)))
|
|
142
159
|
|
|
143
160
|
def __del__(self):
|
|
144
161
|
"""Client GC collect"""
|
|
@@ -146,176 +163,31 @@ class Client:
|
|
|
146
163
|
Client.console(f"[Client] del: {self.client_id}")
|
|
147
164
|
|
|
148
165
|
|
|
149
|
-
class WebCli(Client):
|
|
150
|
-
REST_ENDPOINTS = {}
|
|
151
|
-
AUTH = cfgget('auth')
|
|
152
|
-
REQ200 = "HTTP/1.1 200 OK\r\nContent-Type: {dtype}\r\nContent-Length:{len}\r\n\r\n{data}"
|
|
153
|
-
REQ400 = "HTTP/1.1 400 Bad Request\r\nContent-Type: text/plain\r\nContent-Length: {len}\r\n\r\n{data}"
|
|
154
|
-
REQ404 = "HTTP/1.1 404 Not Found\r\nContent-Type: text/plain\r\nContent-Length: {len}\r\n\r\n{data}"
|
|
166
|
+
class WebCli(Client, WebEngine):
|
|
155
167
|
|
|
156
168
|
def __init__(self, reader, writer):
|
|
157
169
|
Client.__init__(self, reader, writer, r_size=512)
|
|
158
|
-
|
|
159
|
-
@staticmethod
|
|
160
|
-
def rest_setter(endpoint, callback):
|
|
161
|
-
# AUTO ENABLE webui when rest_setter called and webui is False
|
|
162
|
-
if not cfgget('webui'):
|
|
163
|
-
from Config import cfgput
|
|
164
|
-
if cfgput('webui', True): # SET webui to True
|
|
165
|
-
from machine import reset
|
|
166
|
-
reset() # HARD RESET (REBOOT)
|
|
167
|
-
WebCli.REST_ENDPOINTS[endpoint] = callback
|
|
170
|
+
WebEngine.__init__(self, client=self, version=Shell.MICROS_VERSION)
|
|
168
171
|
|
|
169
172
|
async def run_web(self):
|
|
170
173
|
# Update server task output
|
|
171
|
-
Manager().
|
|
174
|
+
Manager().task_msg('server', ','.join(list(Client.ACTIVE_CLIS)))
|
|
172
175
|
|
|
173
176
|
# Run async connection handling
|
|
174
177
|
while self.connected:
|
|
175
178
|
try:
|
|
176
179
|
# Read request msg from client
|
|
177
|
-
state, request = await self.read()
|
|
178
|
-
if state:
|
|
180
|
+
state, request = await self.read(decoding=None)
|
|
181
|
+
if state or not request:
|
|
182
|
+
break
|
|
183
|
+
if not await self.response(request):
|
|
179
184
|
break
|
|
180
|
-
await self.response(request)
|
|
181
185
|
except Exception as e:
|
|
182
|
-
|
|
186
|
+
syslog(f"[ERR] Client.run_web: {e}")
|
|
183
187
|
break
|
|
184
188
|
# Close connection
|
|
185
189
|
await self.close()
|
|
186
190
|
|
|
187
|
-
@staticmethod
|
|
188
|
-
def file_type(path):
|
|
189
|
-
"""File dynamic Content-Type handling"""
|
|
190
|
-
if path.endswith(".html"):
|
|
191
|
-
return "text/html"
|
|
192
|
-
elif path.endswith(".css"):
|
|
193
|
-
return "text/css"
|
|
194
|
-
elif path.endswith(".js"):
|
|
195
|
-
return "application/javascript"
|
|
196
|
-
else:
|
|
197
|
-
return "text/plain"
|
|
198
|
-
|
|
199
|
-
async def response(self, request):
|
|
200
|
-
"""HTTP GET REQUEST - WEB INTERFACE"""
|
|
201
|
-
# Parse request line (first line)
|
|
202
|
-
_method, url, _version = request.split('\n')[0].split()
|
|
203
|
-
# Protocol validation
|
|
204
|
-
if _method != "GET" and _version.startswith('HTTP'):
|
|
205
|
-
_err = f"Bad Request: not GET HTTP/1.1"
|
|
206
|
-
await self.a_send(self.REQ400.format(len=len(_err), data=_err))
|
|
207
|
-
return
|
|
208
|
-
|
|
209
|
-
# [1] REST API GET ENDPOINT [/rest]
|
|
210
|
-
if url.startswith('/rest'):
|
|
211
|
-
Client.console("[WebCli] --- /rest ACCEPT")
|
|
212
|
-
try:
|
|
213
|
-
await self.a_send(WebCli.rest(url))
|
|
214
|
-
except Exception as e:
|
|
215
|
-
await self.a_send(self.REQ404.format(len=len(str(e)), data=e))
|
|
216
|
-
return
|
|
217
|
-
# [2] DYNAMIC/USER ENDPOINTS (from Load Modules)
|
|
218
|
-
if await self.endpoints(url):
|
|
219
|
-
return
|
|
220
|
-
# [3] HOME/PAGE ENDPOINT(s) [default: / -> /index.html]
|
|
221
|
-
if url.startswith('/'):
|
|
222
|
-
resource = 'index.html' if url == '/' else url.replace('/', '')
|
|
223
|
-
Client.console(f"[WebCli] --- {url} ACCEPT")
|
|
224
|
-
if resource.split('.')[-1] not in ('html', 'js', 'css'):
|
|
225
|
-
await self.a_send(self.REQ404.format(len=27, data='404 Not supported file type'))
|
|
226
|
-
return
|
|
227
|
-
try:
|
|
228
|
-
# SEND RESOURCE CONTENT: HTML, JS, CSS
|
|
229
|
-
with open(resource, 'r') as file:
|
|
230
|
-
html = file.read()
|
|
231
|
-
await self.a_send(self.REQ200.format(dtype=WebCli.file_type(resource), len=len(html), data=html))
|
|
232
|
-
except OSError:
|
|
233
|
-
await self.a_send(self.REQ404.format(len=13, data='404 Not Found'))
|
|
234
|
-
return
|
|
235
|
-
# INVALID/BAD REQUEST
|
|
236
|
-
await self.a_send(self.REQ400.format(len=15, data='400 Bad Request'))
|
|
237
|
-
|
|
238
|
-
async def endpoints(self, url):
|
|
239
|
-
url = url[1:] # Cut first / char
|
|
240
|
-
if url in WebCli.REST_ENDPOINTS:
|
|
241
|
-
console_write(f"[WebCli] endpoint: {url}")
|
|
242
|
-
# Registered endpoint was found - exec callback
|
|
243
|
-
try:
|
|
244
|
-
# RESOLVE ENDPOINT CALLBACK
|
|
245
|
-
# dtype:
|
|
246
|
-
# one-shot: image/jpeg | text/html | text/plain - data: raw
|
|
247
|
-
# task: multipart/x-mixed-replace | multipart/form-data - data: dict=callback,content-type
|
|
248
|
-
# content-type: image/jpeg | audio/l16;*
|
|
249
|
-
dtype, data = WebCli.REST_ENDPOINTS[url]()
|
|
250
|
-
if dtype == 'image/jpeg':
|
|
251
|
-
resp = f"HTTP/1.1 200 OK\r\nContent-Type: {dtype}\r\nContent-Length:{len(data)}\r\n\r\n".encode('utf8') + data
|
|
252
|
-
await self.a_send(resp, encode=None)
|
|
253
|
-
elif dtype in ('multipart/x-mixed-replace', 'multipart/form-data'):
|
|
254
|
-
headers = (f"HTTP/1.1 200 OK\r\nContent-Type: {dtype}; boundary=\"micrOS_boundary\"\r\n\r\n").encode('utf-8')
|
|
255
|
-
await self.a_send(headers, encode=None)
|
|
256
|
-
# Start Native stream async task
|
|
257
|
-
task = NativeTask()
|
|
258
|
-
task.create(callback=self.stream(data['callback'], task, data['content-type']),
|
|
259
|
-
tag=f"web.stream_{self.client_id.replace('W', '')}")
|
|
260
|
-
else: # dtype: text/html or text/plain
|
|
261
|
-
await self.a_send(f"HTTP/1.1 200 OK\r\nContent-Type: {dtype}\r\nContent-Length:{len(data)}\r\n\r\n{data}")
|
|
262
|
-
except Exception as e:
|
|
263
|
-
await self.a_send(self.REQ404.format(len=len(str(e)), data=e))
|
|
264
|
-
errlog_add(f"[ERR] WebCli endpoints {url}: {e}")
|
|
265
|
-
return True # Registered endpoint was found and executed
|
|
266
|
-
return False # Not registered endpoint
|
|
267
|
-
|
|
268
|
-
async def stream(self, callback, task, content_type):
|
|
269
|
-
"""
|
|
270
|
-
Async stream method
|
|
271
|
-
:param callback: sync or async function callback (auto-detect) WARNING: works for functions only (not methods!)
|
|
272
|
-
"""
|
|
273
|
-
is_coroutine = 'generator' in str(type(callback)) # async function callback auto-detect
|
|
274
|
-
with task:
|
|
275
|
-
task.out = 'Stream started'
|
|
276
|
-
data_to_send = b''
|
|
277
|
-
|
|
278
|
-
while self.connected and data_to_send is not None:
|
|
279
|
-
data_to_send = await callback() if is_coroutine else callback()
|
|
280
|
-
part = (f"\r\n--micrOS_boundary\r\nContent-Type: {content_type}\r\n\r\n").encode('utf-8') + data_to_send
|
|
281
|
-
task.out = 'Data sent'
|
|
282
|
-
await self.a_send(part, encode=None)
|
|
283
|
-
await asyncio.sleep_ms(10)
|
|
284
|
-
|
|
285
|
-
# Gracefully terminate the stream
|
|
286
|
-
if self.connected:
|
|
287
|
-
closing_boundary = '\r\n--micrOS_boundary--\r\n'
|
|
288
|
-
await self.a_send(closing_boundary, encode=None)
|
|
289
|
-
await self.close()
|
|
290
|
-
task.out = 'Finished stream'
|
|
291
|
-
|
|
292
|
-
@staticmethod
|
|
293
|
-
def rest(url):
|
|
294
|
-
resp_schema = {'result': None, 'state': False}
|
|
295
|
-
cmd = url.replace('/rest', '')
|
|
296
|
-
if len(cmd) > 1:
|
|
297
|
-
# REST sub-parameter handling (rest commands)
|
|
298
|
-
cmd = (cmd.replace('/', ' ').replace('%22', '"').replace('%E2%80%9C', '"')
|
|
299
|
-
.replace('%E2%80%9D', '"').replace('-', ' ').strip().split())
|
|
300
|
-
# request json format instead of default string output (+ handle & tasks syntax)
|
|
301
|
-
cmd.insert(-1, '>json') if cmd[-1].startswith('&') else cmd.append('>json')
|
|
302
|
-
# EXECUTE COMMAND - LoadModule
|
|
303
|
-
if WebCli.AUTH:
|
|
304
|
-
state, out = lm_exec(cmd) if lm_is_loaded(cmd[0]) else (True, 'Auth:Protected')
|
|
305
|
-
else:
|
|
306
|
-
state, out = lm_exec(cmd)
|
|
307
|
-
try:
|
|
308
|
-
resp_schema['result'] = loads(out) # Load again ... hack for embedded shell json converter...
|
|
309
|
-
except:
|
|
310
|
-
resp_schema['result'] = out
|
|
311
|
-
resp_schema['state'] = state
|
|
312
|
-
else:
|
|
313
|
-
resp_schema['result'] = {"micrOS": Shell.MICROS_VERSION, 'node': cfgget('devfid'), 'auth': WebCli.AUTH}
|
|
314
|
-
if len(tuple(WebCli.REST_ENDPOINTS.keys())) > 0:
|
|
315
|
-
resp_schema['result']['usr_endpoints'] = tuple(WebCli.REST_ENDPOINTS)
|
|
316
|
-
resp_schema['state'] = True
|
|
317
|
-
response = dumps(resp_schema)
|
|
318
|
-
return WebCli.REQ200.format(dtype='text/html', len=len(response), data=response)
|
|
319
191
|
|
|
320
192
|
class ShellCli(Client, Shell):
|
|
321
193
|
|
|
@@ -328,7 +200,9 @@ class ShellCli(Client, Shell):
|
|
|
328
200
|
|
|
329
201
|
def send(self, response):
|
|
330
202
|
"""
|
|
331
|
-
|
|
203
|
+
Synchronous send function (with drain task)
|
|
204
|
+
- not used in Shell or ShellCli
|
|
205
|
+
- Note: it is a support function for synchronous scenarios: Server.reply_all
|
|
332
206
|
"""
|
|
333
207
|
if self.connected:
|
|
334
208
|
if self.prompt() != response:
|
|
@@ -338,21 +212,20 @@ class ShellCli(Client, Shell):
|
|
|
338
212
|
# Store data in stream buffer
|
|
339
213
|
try:
|
|
340
214
|
self.writer.write(response.encode('utf8'))
|
|
341
|
-
except
|
|
215
|
+
except:
|
|
342
216
|
# Maintain ACTIVE_CLIS - remove closed connection by peer.
|
|
343
217
|
Client.drop_client(self.client_id)
|
|
344
|
-
|
|
218
|
+
syslog(f"[WARN] ShellCli.send (auto-drop) {self.client_id}")
|
|
345
219
|
# Send buffered data with async task - hacky
|
|
346
220
|
if self.drain_event.is_set():
|
|
347
221
|
self.drain_event.clear() # set drain busy (False)
|
|
348
222
|
asyncio.get_event_loop().create_task(self.__wait_for_drain())
|
|
349
223
|
else:
|
|
350
|
-
console_write(
|
|
224
|
+
console_write("[ShellCli] NoCon: response>/dev/nul")
|
|
351
225
|
|
|
352
226
|
async def __wait_for_drain(self):
|
|
353
227
|
"""
|
|
354
|
-
Handle drain serialization
|
|
355
|
-
- solve output data duplicate
|
|
228
|
+
Handle drain serialization - for synchronous send function
|
|
356
229
|
"""
|
|
357
230
|
try:
|
|
358
231
|
# send write buffer
|
|
@@ -365,55 +238,45 @@ class ShellCli(Client, Shell):
|
|
|
365
238
|
# set drain free
|
|
366
239
|
self.drain_event.set() # set drain free (True)
|
|
367
240
|
|
|
368
|
-
async def
|
|
369
|
-
Client.console(f"[ShellCli] Close connection {self.client_id}")
|
|
370
|
-
self.send("Bye!\n")
|
|
371
|
-
# Reset shell state machine
|
|
372
|
-
self.reset()
|
|
373
|
-
await asyncio.sleep_ms(50)
|
|
374
|
-
# Used from Client parent class
|
|
375
|
-
await super().close()
|
|
376
|
-
|
|
377
|
-
async def __shell_cmd(self, request):
|
|
241
|
+
async def a_send(self, response, encode='utf8'):
|
|
378
242
|
"""
|
|
379
|
-
|
|
243
|
+
Async send for Shell (new line + prompt$)
|
|
380
244
|
"""
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
state = self.shell(request)
|
|
386
|
-
if state:
|
|
387
|
-
return False # exit_loop
|
|
388
|
-
return True # exit_loop : Close session when shell returns False (auth Failed, etc.)
|
|
389
|
-
except Exception as e:
|
|
390
|
-
Client.console(f"[ShellCli] Shell exception: {e}")
|
|
391
|
-
if "ECONNRESET" in str(e):
|
|
392
|
-
return True # exit_loop
|
|
393
|
-
self.send("[HA] Critical error - disconnect & hard reset")
|
|
394
|
-
errlog_add("[ERR] Socket critical error - reboot")
|
|
395
|
-
self.reboot()
|
|
245
|
+
if self.prompt() != response:
|
|
246
|
+
# [format] Add new line if not prompt
|
|
247
|
+
response = f"{response}\n"
|
|
248
|
+
await super().a_send(response, encode)
|
|
396
249
|
|
|
397
250
|
async def run_shell(self):
|
|
398
251
|
# Update server task output
|
|
399
|
-
Manager().
|
|
252
|
+
Manager().task_msg('server', ','.join(list(Client.ACTIVE_CLIS)))
|
|
400
253
|
# Init prompt
|
|
401
|
-
self.
|
|
254
|
+
await self.a_send(self.prompt())
|
|
402
255
|
# Run async connection handling
|
|
256
|
+
_exit = False
|
|
403
257
|
while self.connected:
|
|
404
258
|
try:
|
|
405
259
|
# Read request msg from client
|
|
406
260
|
state, request = await self.read()
|
|
407
|
-
if state:
|
|
408
|
-
break
|
|
409
|
-
_exit = await self.__shell_cmd(request)
|
|
410
|
-
if _exit:
|
|
411
|
-
collect()
|
|
261
|
+
if state or request in ('exit', ''):
|
|
412
262
|
break
|
|
263
|
+
# Run micrOS shell with request string
|
|
264
|
+
Client.console("[ShellCli] --- #Run shell")
|
|
265
|
+
# Shell -> True (OK) or False (NOK) -> NOK->Close session (auth Failed, etc.)
|
|
266
|
+
_exit = not await self.shell(request)
|
|
413
267
|
except Exception as e:
|
|
414
|
-
|
|
268
|
+
syslog(f"[ERR] Shell client: {e}")
|
|
269
|
+
if "ECONNRESET" in str(e):
|
|
270
|
+
_exit = True # exit_loop
|
|
271
|
+
else:
|
|
272
|
+
await self.a_send("[HA] Critical error - disconnect & hard reset")
|
|
273
|
+
syslog("[ERR] Socket critical error - reboot")
|
|
274
|
+
await self.reboot()
|
|
275
|
+
if _exit:
|
|
276
|
+
collect()
|
|
415
277
|
break
|
|
416
278
|
# Close connection
|
|
279
|
+
await self.a_send("Bye!")
|
|
417
280
|
await self.close()
|
|
418
281
|
|
|
419
282
|
|
|
@@ -421,13 +284,14 @@ class ShellCli(Client, Shell):
|
|
|
421
284
|
# SOCKET SERVER CLASS #
|
|
422
285
|
#########################################################
|
|
423
286
|
|
|
424
|
-
class
|
|
287
|
+
class Server:
|
|
425
288
|
"""
|
|
426
289
|
Socket message data packet layer - send and receive
|
|
427
290
|
Embedded command interpretation:
|
|
428
291
|
- exit
|
|
429
292
|
Handle user requests/commands with Shell (bash like experience)
|
|
430
293
|
"""
|
|
294
|
+
__slots__ = ['server', 'web', '_host', '_socqueue', '_port', '_timeout', '_initialized']
|
|
431
295
|
__instance = None
|
|
432
296
|
|
|
433
297
|
def __new__(cls):
|
|
@@ -437,8 +301,8 @@ class SocketServer:
|
|
|
437
301
|
cls - class
|
|
438
302
|
"""
|
|
439
303
|
if not cls.__instance:
|
|
440
|
-
#
|
|
441
|
-
cls.__instance = super(
|
|
304
|
+
# Server singleton properties
|
|
305
|
+
cls.__instance = super(Server, cls).__new__(cls)
|
|
442
306
|
cls.__instance._initialized = False
|
|
443
307
|
return cls.__instance
|
|
444
308
|
|
|
@@ -549,8 +413,11 @@ class SocketServer:
|
|
|
549
413
|
"""
|
|
550
414
|
for _, cli in Client.ACTIVE_CLIS.items():
|
|
551
415
|
if cli.connected:
|
|
552
|
-
cli.send(msg)
|
|
416
|
+
cli.send(f"~~~ {msg}")
|
|
553
417
|
|
|
554
418
|
def __del__(self):
|
|
555
419
|
Client.console("[ socket server ] <<destructor>>")
|
|
556
|
-
self.server
|
|
420
|
+
if self.server:
|
|
421
|
+
self.server.close()
|
|
422
|
+
if self.web:
|
|
423
|
+
self.web.close()
|