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
toolkit/lib/micrOSClient.py
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import socket
|
|
2
|
-
import sys
|
|
3
|
-
|
|
4
2
|
import select
|
|
5
3
|
import re
|
|
6
4
|
import time
|
|
@@ -10,6 +8,25 @@ except:
|
|
|
10
8
|
from TerminalColors import Colors as color
|
|
11
9
|
|
|
12
10
|
|
|
11
|
+
ANSI_ESCAPE_RE = re.compile(r"\x1B\[[0-?]*[ -/]*[@-~]")
|
|
12
|
+
|
|
13
|
+
def load_command_history(prompt_getter):
|
|
14
|
+
"""Optional command history feature"""
|
|
15
|
+
try:
|
|
16
|
+
try:
|
|
17
|
+
from .micrOSClientHistory import CommandInterface
|
|
18
|
+
except:
|
|
19
|
+
from micrOSClientHistory import CommandInterface
|
|
20
|
+
except Exception as e:
|
|
21
|
+
print(f"Command history - disabled (readline module error): {e}")
|
|
22
|
+
return None
|
|
23
|
+
try:
|
|
24
|
+
return CommandInterface(prompt=prompt_getter)
|
|
25
|
+
except Exception as e:
|
|
26
|
+
print(f"Command history error: {e}")
|
|
27
|
+
return None
|
|
28
|
+
|
|
29
|
+
|
|
13
30
|
class micrOSClient:
|
|
14
31
|
CONN_MAP = {}
|
|
15
32
|
|
|
@@ -35,6 +52,10 @@ class micrOSClient:
|
|
|
35
52
|
# Validate and resolve host (IP/Hostname)
|
|
36
53
|
self.__address_manager()
|
|
37
54
|
|
|
55
|
+
@property
|
|
56
|
+
def telnet_prompt(self):
|
|
57
|
+
return f"{color.BOLD}{self.preprompt}{self.prompt}{color.NC} "
|
|
58
|
+
|
|
38
59
|
def __address_manager(self):
|
|
39
60
|
self.dbg_print("[INIT] micrOSClient")
|
|
40
61
|
# Host is valid IP address - self.host is ip address OK
|
|
@@ -67,10 +88,22 @@ class micrOSClient:
|
|
|
67
88
|
|
|
68
89
|
@staticmethod
|
|
69
90
|
def validate_ipv4(str_in):
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
91
|
+
parts = str_in.split(".")
|
|
92
|
+
# An IPv4 address must have exactly 4 parts
|
|
93
|
+
if len(parts) != 4:
|
|
94
|
+
return False
|
|
95
|
+
for part in parts:
|
|
96
|
+
# Each part must be a number and not empty
|
|
97
|
+
if not part.isdigit():
|
|
98
|
+
return False
|
|
99
|
+
num = int(part)
|
|
100
|
+
# Each number must be in the valid range (0-255)
|
|
101
|
+
if num < 0 or num > 255:
|
|
102
|
+
return False
|
|
103
|
+
# Prevents leading zeros (e.g., "01" is invalid)
|
|
104
|
+
if part != str(num):
|
|
105
|
+
return False
|
|
106
|
+
return True
|
|
74
107
|
|
|
75
108
|
def __connect(self, timeout):
|
|
76
109
|
# Server connection - create socket
|
|
@@ -143,24 +176,35 @@ class micrOSClient:
|
|
|
143
176
|
|
|
144
177
|
def __filter_preprompt(self, _data):
|
|
145
178
|
if len(_data) == 0:
|
|
146
|
-
return
|
|
147
|
-
|
|
148
|
-
|
|
179
|
+
return _data
|
|
180
|
+
|
|
181
|
+
has_trailing_newline = _data.endswith('\n')
|
|
182
|
+
working = _data.rstrip('\n')
|
|
183
|
+
lines = working.split('\n') if working else ['']
|
|
184
|
+
last_line = lines[-1]
|
|
185
|
+
|
|
149
186
|
if self.prompt is not None:
|
|
150
|
-
|
|
151
|
-
if
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
187
|
+
prompt_index = last_line.find(self.prompt)
|
|
188
|
+
if prompt_index != -1:
|
|
189
|
+
raw_prefix = last_line[:prompt_index]
|
|
190
|
+
plain_prefix = ANSI_ESCAPE_RE.sub('', raw_prefix)
|
|
191
|
+
|
|
192
|
+
plain_prefix = plain_prefix.rstrip()
|
|
193
|
+
if plain_prefix:
|
|
194
|
+
if not plain_prefix.endswith(' '):
|
|
195
|
+
plain_prefix += ' '
|
|
196
|
+
self.preprompt = plain_prefix
|
|
197
|
+
else:
|
|
198
|
+
self.preprompt = ""
|
|
199
|
+
|
|
200
|
+
lines[-1] = last_line[prompt_index:]
|
|
162
201
|
|
|
163
|
-
|
|
202
|
+
rebuilt = '\n'.join(lines)
|
|
203
|
+
if has_trailing_newline:
|
|
204
|
+
rebuilt += '\n'
|
|
205
|
+
return rebuilt
|
|
206
|
+
|
|
207
|
+
def __receive_data(self, read_timeout=20, stream=False):
|
|
164
208
|
"""
|
|
165
209
|
Client Receiver Loop
|
|
166
210
|
- read_timeout - wait for server to reply (should be <15, avoid msg queue-ing)
|
|
@@ -173,7 +217,11 @@ class micrOSClient:
|
|
|
173
217
|
# Collect answer data
|
|
174
218
|
if select.select([self.conn], [], [], read_timeout)[0]:
|
|
175
219
|
while True:
|
|
176
|
-
|
|
220
|
+
incoming_data = self.conn.recv(4096).decode('utf-8')
|
|
221
|
+
if stream:
|
|
222
|
+
incoming_data = incoming_data.replace(self.prompt, f"{color.NC}{color.BOLD}{self.prompt}{color.NC}")
|
|
223
|
+
print(f"\r{color.LIGHT_GRAY}{incoming_data}{color.NC}", end="")
|
|
224
|
+
data_buffer += incoming_data
|
|
177
225
|
# Last line from data_buffer (handle fragmented messages - prompt detection)
|
|
178
226
|
last_line = data_buffer.strip().split("\n")[-1]
|
|
179
227
|
# Wait for prompt or special cases (exit/prompt)
|
|
@@ -200,7 +248,7 @@ class micrOSClient:
|
|
|
200
248
|
self.isconn = False
|
|
201
249
|
self.spacer = 0
|
|
202
250
|
|
|
203
|
-
def __run_command(self, cmd):
|
|
251
|
+
def __run_command(self, cmd, stream=False):
|
|
204
252
|
"""
|
|
205
253
|
Run command on server tcp/ip connection
|
|
206
254
|
- prompt check - validate device ("hostname $" = "prompt")
|
|
@@ -218,14 +266,14 @@ class micrOSClient:
|
|
|
218
266
|
# Workaround for reboot command - micrOS async server cannot send Bye! msg before reboot.
|
|
219
267
|
if reboot_request:
|
|
220
268
|
return 'Bye!'
|
|
221
|
-
data = self.__receive_data()
|
|
269
|
+
data = self.__receive_data(stream=stream)
|
|
222
270
|
return data
|
|
223
271
|
# Skip command run: prompt and host not the same!
|
|
224
272
|
print(f"[micrOSClient] {color.ERR}prompt mismatch{color.NC}, hostname: {check_hostname} prompt: {check_prompt} ")
|
|
225
273
|
# Check UID?
|
|
226
274
|
return None
|
|
227
275
|
|
|
228
|
-
def send_cmd(self, cmd, timeout=3, retry=5):
|
|
276
|
+
def send_cmd(self, cmd, timeout=3, retry=5, stream=False):
|
|
229
277
|
"""
|
|
230
278
|
Send command function - main usage for non interactive mode
|
|
231
279
|
"""
|
|
@@ -244,7 +292,7 @@ class micrOSClient:
|
|
|
244
292
|
|
|
245
293
|
# @ Run command
|
|
246
294
|
try:
|
|
247
|
-
out = self.__run_command(cmd)
|
|
295
|
+
out = self.__run_command(cmd, stream=stream)
|
|
248
296
|
except Exception as e:
|
|
249
297
|
self.dbg_print("{}[ERR]{} send_cmd error: {}".format(color.ERR, color.NC, e))
|
|
250
298
|
self.dbg_print("Auto deinit connection")
|
|
@@ -258,14 +306,14 @@ class micrOSClient:
|
|
|
258
306
|
f_delta_t = "{}[{:.2f}]{}".format(color.OKGREEN, delta_time, color.NC)
|
|
259
307
|
self.dbg_print("{}[⏰] {} {}reply: {}{}".format(f_delta_t, cmd, color.BOLD, out, color.NC))
|
|
260
308
|
|
|
261
|
-
# return output list
|
|
309
|
+
# return output list or None
|
|
262
310
|
return out
|
|
263
311
|
|
|
264
|
-
def send_cmd_retry(self, cmd, timeout=6, retry=5):
|
|
312
|
+
def send_cmd_retry(self, cmd, timeout=6, retry=5, stream=False):
|
|
265
313
|
out = None
|
|
266
314
|
for cnt in range(0, retry):
|
|
267
315
|
try:
|
|
268
|
-
out = self.send_cmd(cmd, timeout)
|
|
316
|
+
out = self.send_cmd(cmd, timeout, stream=stream)
|
|
269
317
|
if out is None or isinstance(out, list):
|
|
270
318
|
break
|
|
271
319
|
except OSError as e:
|
|
@@ -277,7 +325,7 @@ class micrOSClient:
|
|
|
277
325
|
time.sleep(0.2)
|
|
278
326
|
return out
|
|
279
327
|
|
|
280
|
-
def telnet(self, timeout=
|
|
328
|
+
def telnet(self, timeout=5):
|
|
281
329
|
"""
|
|
282
330
|
Implements interactive mode for socket communication.
|
|
283
331
|
"""
|
|
@@ -287,18 +335,41 @@ class micrOSClient:
|
|
|
287
335
|
print("Telnet connect: {}".format(e))
|
|
288
336
|
if "busy" in str(e) or "timed out" in str(e) or "No route to host" in str(e) or "Host is down" in str(e):
|
|
289
337
|
return
|
|
338
|
+
|
|
339
|
+
history = load_command_history(self.telnet_prompt) # History: Beta feature
|
|
340
|
+
if history is not None:
|
|
341
|
+
history.prompt = self.telnet_prompt
|
|
342
|
+
print(self.telnet_prompt, end="")
|
|
343
|
+
is_empty = False # Empty input support
|
|
290
344
|
while True:
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
345
|
+
try:
|
|
346
|
+
# INPUT HANDLING
|
|
347
|
+
if history is not None:
|
|
348
|
+
history.prompt = self.telnet_prompt
|
|
349
|
+
cmd = input(self.telnet_prompt if is_empty else '') # CANNOT contain prompt - it is coming back from response data
|
|
350
|
+
if len(cmd.strip()) == 0:
|
|
351
|
+
is_empty = True
|
|
352
|
+
if history is not None:
|
|
353
|
+
history.prompt = self.telnet_prompt
|
|
354
|
+
continue
|
|
355
|
+
is_empty = False
|
|
356
|
+
# SEND COMMAND
|
|
357
|
+
output = self.send_cmd(cmd, timeout=timeout, stream=True)
|
|
358
|
+
if history is not None:
|
|
359
|
+
history.prompt = self.telnet_prompt
|
|
360
|
+
if not (history is None or output is None) and "Shell: for hints type help." not in output: # History: Beta feature
|
|
361
|
+
history.add_history(cmd)
|
|
362
|
+
# OUTPUT HANDLING
|
|
363
|
+
if 'Bye!' in str(output):
|
|
364
|
+
break
|
|
365
|
+
if output is None:
|
|
366
|
+
print("Exiting... client disconnected")
|
|
367
|
+
break
|
|
368
|
+
except KeyboardInterrupt:
|
|
369
|
+
print("Exiting...")
|
|
301
370
|
break
|
|
371
|
+
if history is not None: # History: Beta feature
|
|
372
|
+
history.save_history()
|
|
302
373
|
self.close()
|
|
303
374
|
|
|
304
375
|
def dbg_print(self, msg, end='\n'):
|
|
@@ -325,8 +396,9 @@ class micrOSClient:
|
|
|
325
396
|
verdict.append(console_msg)
|
|
326
397
|
print(f"===>\t\t{console_msg}")
|
|
327
398
|
self.close()
|
|
328
|
-
|
|
329
|
-
|
|
399
|
+
delta_t_result = round(delta_t_all / cnt, 3)
|
|
400
|
+
verdict.append(f"SINGLE CONNECTION LOAD TEST X{cnt}, AVERAGE REPLY TIME: {delta_t_result} sec\n")
|
|
401
|
+
return verdict, delta_t_result
|
|
330
402
|
|
|
331
403
|
def __del__(self):
|
|
332
404
|
if self.dbg and self.avg_reply[1] > 0:
|
|
@@ -355,9 +427,10 @@ def micros_connection_metrics(address):
|
|
|
355
427
|
print(f"\t\t{_console_msg}")
|
|
356
428
|
all_reply.append(_console_msg)
|
|
357
429
|
success_rate = int(round(_success / cnt, 2) * 100)
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
430
|
+
delta_t_result = round(_all_delta_t/cnt, 3)
|
|
431
|
+
all_reply.append(f"MULTI CONNECTION LOAD TEST X{cnt}, AVERAGE REPLY TIME: {delta_t_result}s, "
|
|
432
|
+
f"SERVER AVAILABILITY: {success_rate}% ({int((_all_delta_t/_success)*1000)} ms)")
|
|
433
|
+
return all_reply, delta_t_result
|
|
361
434
|
|
|
362
435
|
# ---------------------------------------------------- #
|
|
363
436
|
high_level_verdict = []
|
|
@@ -365,12 +438,12 @@ def micros_connection_metrics(address):
|
|
|
365
438
|
# [1] Create micrOSClient object + Run LOAD tests
|
|
366
439
|
com_obj = micrOSClient(host=address, port=9008, pwd="ADmin123", dbg=True)
|
|
367
440
|
# [1.1] Run load test in one connection
|
|
368
|
-
verdict_list = com_obj.load_test()
|
|
441
|
+
verdict_list, delta_t_single_session = com_obj.load_test()
|
|
369
442
|
com_obj.close()
|
|
370
443
|
high_level_verdict.append(verdict_list[-1])
|
|
371
444
|
|
|
372
445
|
# [2] Run multi connection load test - reconnect - raw connection (without retry)
|
|
373
|
-
verdict_multi = multi_conn_load(address)
|
|
446
|
+
verdict_multi, delta_t_multi_session = multi_conn_load(address)
|
|
374
447
|
high_level_verdict.append((verdict_multi[-1]))
|
|
375
448
|
|
|
376
449
|
############################################################################
|
|
@@ -382,7 +455,7 @@ def micros_connection_metrics(address):
|
|
|
382
455
|
for k in verdict_multi:
|
|
383
456
|
print(f"\t{k}")
|
|
384
457
|
|
|
385
|
-
return high_level_verdict
|
|
458
|
+
return high_level_verdict, delta_t_single_session, delta_t_multi_session
|
|
386
459
|
|
|
387
460
|
|
|
388
461
|
if __name__ == "__main__":
|
|
@@ -416,7 +489,7 @@ if __name__ == "__main__":
|
|
|
416
489
|
print(f"noconf out: {noconf_mode}")
|
|
417
490
|
if force_close: com_obj.close()
|
|
418
491
|
|
|
419
|
-
verdict = micros_connection_metrics(address=address)
|
|
492
|
+
verdict, delta_t_single, delta_t_multi = micros_connection_metrics(address=address)
|
|
420
493
|
for k in verdict:
|
|
421
494
|
print(f"+\t\t{k}")
|
|
422
495
|
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import os
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
import readline # Linux/macOS
|
|
7
|
+
except ImportError:
|
|
8
|
+
import pyreadline3 as readline # Windows (PowerShell, CMD)
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
from .TerminalColors import Colors as color
|
|
12
|
+
except:
|
|
13
|
+
from TerminalColors import Colors as color
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
ANSI_ESCAPE_RE = re.compile(r"\x1B\[[0-?]*[ -/]*[@-~]")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class CommandInterface:
|
|
20
|
+
def __init__(self, prompt):
|
|
21
|
+
self._prompt = ""
|
|
22
|
+
self._prompt_plain = ""
|
|
23
|
+
self._last_rendered_length = 0
|
|
24
|
+
self.prompt = prompt
|
|
25
|
+
self.command_history = ["help"]
|
|
26
|
+
self.history_file = os.path.expanduser("~/.micrOS_cmd_history") # History file (Linux/macOS)
|
|
27
|
+
|
|
28
|
+
# Configure readline
|
|
29
|
+
self.load_history()
|
|
30
|
+
readline.set_completer_delims("") # Ensure entire command is considered
|
|
31
|
+
readline.set_completer(self.autocomplete)
|
|
32
|
+
# Check if we're running on macOS using libedit
|
|
33
|
+
if "libedit" in readline.__doc__:
|
|
34
|
+
readline.parse_and_bind("bind ^I rl_complete") # macOS alternative
|
|
35
|
+
else:
|
|
36
|
+
readline.parse_and_bind("tab: complete") # Linux/GNU readline
|
|
37
|
+
readline.set_pre_input_hook(self.pre_input_hook)
|
|
38
|
+
readline.set_completion_display_matches_hook(self.completion_display)
|
|
39
|
+
|
|
40
|
+
def __auto_clear_history(self):
|
|
41
|
+
cmd_history = []
|
|
42
|
+
# Load file history in order - skip duplicates
|
|
43
|
+
if os.path.exists(self.history_file):
|
|
44
|
+
with open(self.history_file, "r") as f:
|
|
45
|
+
for line in reversed(f.readlines()):
|
|
46
|
+
if line in cmd_history:
|
|
47
|
+
continue
|
|
48
|
+
cmd_history.append(line)
|
|
49
|
+
# Save cleaned history to file
|
|
50
|
+
with open(self.history_file, "w") as f:
|
|
51
|
+
f.writelines(f"{item}\n" for item in reversed(cmd_history))
|
|
52
|
+
|
|
53
|
+
def load_history(self):
|
|
54
|
+
"""Loads command history from a file if available."""
|
|
55
|
+
print(f"Command history: {self.history_file}")
|
|
56
|
+
try:
|
|
57
|
+
self.__auto_clear_history()
|
|
58
|
+
except Exception as e:
|
|
59
|
+
print(f"Auto clean history error: {e}")
|
|
60
|
+
if os.path.exists(self.history_file):
|
|
61
|
+
with open(self.history_file, "r") as f:
|
|
62
|
+
for line in f:
|
|
63
|
+
clean_line = line.strip()
|
|
64
|
+
if clean_line: # Avoid empty lines
|
|
65
|
+
self.command_history.append(clean_line)
|
|
66
|
+
readline.add_history(clean_line)
|
|
67
|
+
|
|
68
|
+
def save_history(self):
|
|
69
|
+
"""Saves command history to a file."""
|
|
70
|
+
with open(self.history_file, "w") as f:
|
|
71
|
+
for cmd in self.command_history:
|
|
72
|
+
f.write(cmd + "\n")
|
|
73
|
+
|
|
74
|
+
def add_history(self, cmd):
|
|
75
|
+
"""Updates readline history and command_history."""
|
|
76
|
+
cmd = cmd.strip()
|
|
77
|
+
if cmd and cmd != self.command_history[-1]: # Avoid duplicate last command
|
|
78
|
+
self.command_history.append(cmd)
|
|
79
|
+
readline.add_history(cmd)
|
|
80
|
+
|
|
81
|
+
def autocomplete(self, text, state):
|
|
82
|
+
"""Autocomplete function: suggests previous commands."""
|
|
83
|
+
matches = list(dict.fromkeys(cmd for cmd in self.command_history if cmd.startswith(text)))
|
|
84
|
+
return matches[state] if state < len(matches) else None
|
|
85
|
+
|
|
86
|
+
@staticmethod
|
|
87
|
+
def _strip_ansi(value):
|
|
88
|
+
if not value:
|
|
89
|
+
return ""
|
|
90
|
+
return ANSI_ESCAPE_RE.sub("", value)
|
|
91
|
+
|
|
92
|
+
@property
|
|
93
|
+
def prompt(self):
|
|
94
|
+
return self._prompt
|
|
95
|
+
|
|
96
|
+
@prompt.setter
|
|
97
|
+
def prompt(self, value):
|
|
98
|
+
self._prompt = value
|
|
99
|
+
self._prompt_plain = self._strip_ansi(value)
|
|
100
|
+
|
|
101
|
+
def pre_input_hook(self):
|
|
102
|
+
"""Ensures prompt visibility when scrolling through history."""
|
|
103
|
+
buffer = readline.get_line_buffer()
|
|
104
|
+
sys.stdout.write("\r")
|
|
105
|
+
rendered = f"{self.prompt}{buffer}"
|
|
106
|
+
sys.stdout.write(rendered)
|
|
107
|
+
|
|
108
|
+
visible_length = len(self._prompt_plain) + len(buffer)
|
|
109
|
+
if visible_length < self._last_rendered_length:
|
|
110
|
+
padding = " " * (self._last_rendered_length - visible_length)
|
|
111
|
+
sys.stdout.write(padding)
|
|
112
|
+
sys.stdout.write("\r")
|
|
113
|
+
sys.stdout.write(rendered)
|
|
114
|
+
|
|
115
|
+
sys.stdout.flush()
|
|
116
|
+
self._last_rendered_length = visible_length
|
|
117
|
+
readline.redisplay() # Ensures history navigation does not erase prompt
|
|
118
|
+
|
|
119
|
+
def completion_display(self, substitutions, matches, longest_match_length):
|
|
120
|
+
print("\nSuggestions:", ", ".join(matches))
|
|
121
|
+
|
|
122
|
+
#####################################
|
|
123
|
+
# STANDALONE TEST METHODS #
|
|
124
|
+
#####################################
|
|
125
|
+
|
|
126
|
+
def dummy_send_cmd(self, cmd, stream):
|
|
127
|
+
"""TEST FUNCTION - OUTPUT STRUCTURE SIMULATION (Must remain unchanged)."""
|
|
128
|
+
dummy_reply = "Bye!" if cmd.strip() in ["exit", "reboot"] else f"Dummy reply for {cmd}"
|
|
129
|
+
if stream:
|
|
130
|
+
print(dummy_reply) # micrOS protocol: return response data
|
|
131
|
+
print(self.prompt, end="") # micrOS protocol: return prompt -> indicating ready state
|
|
132
|
+
else:
|
|
133
|
+
dummy_reply = f"{dummy_reply}\n{self.prompt}"
|
|
134
|
+
return dummy_reply
|
|
135
|
+
|
|
136
|
+
def dummy_run(self):
|
|
137
|
+
"""TEST FUNCTION - Simulated interactive terminal."""
|
|
138
|
+
print(f"{self.prompt}", end="", flush=True)
|
|
139
|
+
while True:
|
|
140
|
+
try:
|
|
141
|
+
cmd = input()
|
|
142
|
+
output = self.dummy_send_cmd(cmd, stream=True)
|
|
143
|
+
self.add_history(cmd)
|
|
144
|
+
if 'Bye!' in str(output):
|
|
145
|
+
break
|
|
146
|
+
except KeyboardInterrupt:
|
|
147
|
+
print("\nExiting...")
|
|
148
|
+
break
|
|
149
|
+
|
|
150
|
+
self.save_history()
|
|
151
|
+
print("Session closed.")
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
if __name__ == "__main__":
|
|
155
|
+
shell = CommandInterface(prompt="<prompt_placeholder>$ ")
|
|
156
|
+
shell.dummy_run()
|
|
@@ -66,8 +66,11 @@ def install_package(name, additional_pip_param=None):
|
|
|
66
66
|
print(f"{TerminalColors.Colors.OK}[PIP] install {name} OK{TerminalColors.Colors.NC}")
|
|
67
67
|
else:
|
|
68
68
|
print(f"{TerminalColors.Colors.WARN}[PIP] install {name} NOK{TerminalColors.Colors.NC}")
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
if "--break-system-packages" in out:
|
|
70
|
+
# (Retry) Support system wide package install
|
|
71
|
+
install_package(name, additional_pip_param="--break-system-packages")
|
|
72
|
+
elif "This environment is externally managed" in out:
|
|
73
|
+
# (Retry-Fallback) Support brew installed python
|
|
71
74
|
if "brew install" in out:
|
|
72
75
|
print(f"Install optional dependency (brew): {name}")
|
|
73
76
|
state, out = run_subprocess(["brew", "install", name])
|
toolkit/micrOSdashboard.py
CHANGED
|
@@ -6,17 +6,12 @@ import os
|
|
|
6
6
|
import threading
|
|
7
7
|
import subprocess
|
|
8
8
|
import time
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
from PyQt5.
|
|
13
|
-
from PyQt5.QtGui import QIcon
|
|
14
|
-
|
|
15
|
-
from PyQt5.QtWidgets import QApplication, QPlainTextEdit
|
|
16
|
-
from PyQt5.QtCore import QThread, pyqtSignal
|
|
17
|
-
from PyQt5.QtGui import QFont
|
|
18
|
-
from PyQt5 import QtGui
|
|
19
|
-
from PyQt5.QtGui import QPixmap
|
|
9
|
+
|
|
10
|
+
from PyQt5.QtWidgets import (QApplication, QPlainTextEdit, QPushButton, QProgressBar, QComboBox, QLabel, QCheckBox,
|
|
11
|
+
QLineEdit, QMessageBox, QWidget, QToolTip)
|
|
12
|
+
from PyQt5.QtCore import pyqtSlot, QThread, QSize, pyqtSignal
|
|
13
|
+
from PyQt5.QtGui import QIcon, QTextCursor, QFont, QPixmap
|
|
14
|
+
|
|
20
15
|
import concurrent.futures
|
|
21
16
|
|
|
22
17
|
MYPATH = os.path.dirname(__file__)
|
|
@@ -29,14 +24,14 @@ try:
|
|
|
29
24
|
from . import socketClient
|
|
30
25
|
from . import dashboard_apps
|
|
31
26
|
from .lib import LocalMachine
|
|
32
|
-
from .lib.
|
|
27
|
+
from .lib.MicrosFiles import check_all_extensions
|
|
33
28
|
except Exception as e:
|
|
34
29
|
print("Import warning: {}".format(e))
|
|
35
30
|
import MicrOSDevEnv
|
|
36
31
|
import socketClient
|
|
37
32
|
import dashboard_apps
|
|
38
33
|
from lib import LocalMachine
|
|
39
|
-
from lib.
|
|
34
|
+
from lib.MicrosFiles import check_all_extensions
|
|
40
35
|
|
|
41
36
|
APP_DIR = os.path.join(MYPATH, 'dashboard_apps')
|
|
42
37
|
|
|
@@ -454,7 +449,7 @@ class HeaderInfo:
|
|
|
454
449
|
logo_path = os.path.join(MYPATH, '../media/logo_mini.png')
|
|
455
450
|
button = QPushButton('', self.parent_obj)
|
|
456
451
|
button.setIcon(QIcon(logo_path))
|
|
457
|
-
button.setIconSize(
|
|
452
|
+
button.setIconSize(QSize(50, 50))
|
|
458
453
|
button.setGeometry(20, 5, 50, 50)
|
|
459
454
|
button.setToolTip(f"Open micrOS repo documentation\n{self.url}")
|
|
460
455
|
button.setStyleSheet('border: 0px solid black;')
|
|
@@ -581,7 +576,7 @@ class ClusterStatus:
|
|
|
581
576
|
except:
|
|
582
577
|
hwuid = hello
|
|
583
578
|
status = '🟢' if status else '🔴'
|
|
584
|
-
msg = f"{status}{hwuid}|{devip}🏷{fuid} v
|
|
579
|
+
msg = f"{status}{hwuid} | {devip}🏷{fuid} v:{version}"
|
|
585
580
|
return msg
|
|
586
581
|
|
|
587
582
|
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
@@ -954,7 +949,7 @@ class micrOSGUI(QWidget):
|
|
|
954
949
|
self.devenv_usb_deployment_is_active = True
|
|
955
950
|
# Create a Thread with a function without any arguments
|
|
956
951
|
self.console.append_output('[usb_deploy] |- start usb_deploy job')
|
|
957
|
-
th = threading.Thread(target=self.devtool_obj.deploy_micros, kwargs={'
|
|
952
|
+
th = threading.Thread(target=self.devtool_obj.deploy_micros, kwargs={'restore_config': False, "cleanup_workdir": True},
|
|
958
953
|
daemon=DAEMON)
|
|
959
954
|
th.start()
|
|
960
955
|
self.bgjob_thread_obj_dict['usb_deploy'] = th
|
|
@@ -1219,7 +1214,7 @@ class micrOSGUI(QWidget):
|
|
|
1219
1214
|
|
|
1220
1215
|
def main():
|
|
1221
1216
|
app = QApplication(sys.argv)
|
|
1222
|
-
app.setWindowIcon(
|
|
1217
|
+
app.setWindowIcon(QIcon(os.path.join(MYPATH, '../media/logo.png')))
|
|
1223
1218
|
ex = micrOSGUI()
|
|
1224
1219
|
ex.draw()
|
|
1225
1220
|
sys.exit(app.exec_())
|
toolkit/micrOSlint.py
CHANGED
|
@@ -18,7 +18,7 @@ MICROS_SOURCE_DIR = os.path.join(MYPATH, '../micrOS/source')
|
|
|
18
18
|
RELEASE_INFO_PATH = os.path.join(MYPATH, '../micrOS/release_info/micrOS_ReleaseInfo')
|
|
19
19
|
|
|
20
20
|
# MICROS LINTER CONFIG
|
|
21
|
-
ALLOWED_LM_DEP_WARNS =
|
|
21
|
+
ALLOWED_LM_DEP_WARNS = 3 # ALLOWED NUMBER OF LM CORE DEPENDENCY (less is better)
|
|
22
22
|
|
|
23
23
|
def parse_micros_file_categories(verbose=True):
|
|
24
24
|
"""
|
|
@@ -27,11 +27,17 @@ def parse_micros_file_categories(verbose=True):
|
|
|
27
27
|
file_ignore_list = ['.DS_Store']
|
|
28
28
|
# micrOS file categories
|
|
29
29
|
categories = {'core': [], 'load_module': [], 'pin_maps': [], 'other': []}
|
|
30
|
-
|
|
30
|
+
modules_path = os.path.join(MICROS_SOURCE_DIR, "modules")
|
|
31
|
+
web_path = os.path.join(MICROS_SOURCE_DIR, "web")
|
|
32
|
+
check_file = lambda _b, _f: os.path.isfile(os.path.join(_b, _f)) and _f not in file_ignore_list
|
|
33
|
+
root_files = [f for f in LocalMachine.FileHandler.list_dir(MICROS_SOURCE_DIR) if check_file(MICROS_SOURCE_DIR, f)]
|
|
34
|
+
module_files = [f"modules/{f}" for f in LocalMachine.FileHandler.list_dir(modules_path) if check_file(modules_path, f)]
|
|
35
|
+
web_files = [f"web/{f}" for f in LocalMachine.FileHandler.list_dir(web_path) if check_file(web_path, f)]
|
|
36
|
+
files = root_files + module_files + web_files
|
|
31
37
|
for f in files:
|
|
32
|
-
if f.
|
|
38
|
+
if f.endswith('.py') and "LM_" in f:
|
|
33
39
|
categories['load_module'].append(f)
|
|
34
|
-
elif f.
|
|
40
|
+
elif f.endswith('.py') and "IO_" in f:
|
|
35
41
|
categories['pin_maps'].append(f)
|
|
36
42
|
elif f.endswith('.py'):
|
|
37
43
|
categories['core'].append(f)
|
|
@@ -172,14 +178,15 @@ def core_dep_checker(categories, verbose=True):
|
|
|
172
178
|
def load_module_checker(categories, verbose=True):
|
|
173
179
|
|
|
174
180
|
def _is_allowed(_relation):
|
|
175
|
-
_allowed_whitelist = ['Common', 'microIO', 'Types']
|
|
181
|
+
_allowed_whitelist = ['Common', 'microIO', 'Types', 'urequests', 'Auth']
|
|
176
182
|
_allowed = []
|
|
177
183
|
for _allow in _relation:
|
|
178
184
|
if _allow in _allowed_whitelist:
|
|
179
185
|
_allowed.append(_allow)
|
|
180
186
|
return _relation, _allowed
|
|
181
187
|
|
|
182
|
-
lm_god_mode = ['LM_system.py', '
|
|
188
|
+
lm_god_mode = ['modules/LM_system.py', 'modules/LM_pacman.py',
|
|
189
|
+
'modules/LM_espnow.py', 'modules/LM_cluster.py']
|
|
183
190
|
state_lm_dep = True
|
|
184
191
|
verdict = []
|
|
185
192
|
lm_resources = categories['load_module']
|
|
@@ -222,7 +229,12 @@ def _run_pylint(file_name):
|
|
|
222
229
|
'--disable=broad-exception-caught', # Disable BROAD exception
|
|
223
230
|
'--disable=broad-exception-raised', # Disable BROAD exception
|
|
224
231
|
'--disable=too-many-return-statements', # :D I don't think so :D
|
|
225
|
-
'--disable=too-many-branches'
|
|
232
|
+
'--disable=too-many-branches', # :D I don't think so :D
|
|
233
|
+
'--disable=too-many-positional-arguments', # :D I don't think so :D
|
|
234
|
+
'--disable=too-many-instance-attributes', # :D I don't think so :D
|
|
235
|
+
'--disable=wrong-import-position', # :D I don't think so :D !!! It is needed due to optimizations
|
|
236
|
+
'--disable=too-many-arguments', # :D I know what I am doing...
|
|
237
|
+
'--disable=multiple-statements', # :D I line oneliners
|
|
226
238
|
]
|
|
227
239
|
if file_name in ['Tasks.py', 'microIO.py', 'Types.py']:
|
|
228
240
|
pylint_opts.append('--disable=exec-used') # Disable micrOS execution core exec/eval warning
|
|
@@ -239,7 +251,7 @@ def _run_pylint(file_name):
|
|
|
239
251
|
|
|
240
252
|
def run_pylint(categories, verbose=True, dry_run=False):
|
|
241
253
|
# ERROR CONFIG: drop error if this is in pylint output
|
|
242
|
-
error_msg_core = ['syntax-error', 'undefined-variable', 'no-member'
|
|
254
|
+
error_msg_core = ['syntax-error', 'undefined-variable', 'bad-indentation'] # 'no-member' ?
|
|
243
255
|
# BYPASS 'no-member' due to duty and sleep_ms micropython functions is drops false alarm, etc.
|
|
244
256
|
error_msg_lm = ['syntax-error', 'undefined-variable']
|
|
245
257
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|