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
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>Files</title>
|
|
6
|
+
<!-- Mobile viewport -->
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
|
8
|
+
<!-- Base micrOS style -->
|
|
9
|
+
<link rel="stylesheet" href="../ustyle.css">
|
|
10
|
+
|
|
11
|
+
<!-- Files UI layout-only CSS -->
|
|
12
|
+
<style>
|
|
13
|
+
/* Main layout */
|
|
14
|
+
#ui {
|
|
15
|
+
display: flex;
|
|
16
|
+
gap: 40px;
|
|
17
|
+
height: 100%;
|
|
18
|
+
max-width: 95%;
|
|
19
|
+
}
|
|
20
|
+
#folders {
|
|
21
|
+
width: clamp(120px, 20vw, 200px);
|
|
22
|
+
flex-shrink: 0;
|
|
23
|
+
display: flex;
|
|
24
|
+
flex-direction: column;
|
|
25
|
+
}
|
|
26
|
+
/* Disk bar on top of sidebar */
|
|
27
|
+
#diskbar {
|
|
28
|
+
position: sticky;
|
|
29
|
+
top: 0;
|
|
30
|
+
margin-bottom: 12px;
|
|
31
|
+
padding: 6px 10px;
|
|
32
|
+
font-size: 12px;
|
|
33
|
+
background: rgba(255,255,255,.1);
|
|
34
|
+
border-radius: 6px;
|
|
35
|
+
backdrop-filter: blur(2px);
|
|
36
|
+
z-index: 5;
|
|
37
|
+
}
|
|
38
|
+
/* Disk Usage Widget */
|
|
39
|
+
#diskmeter {
|
|
40
|
+
height: 6px;
|
|
41
|
+
background: rgba(255,255,255,.2);
|
|
42
|
+
border-radius: 3px;
|
|
43
|
+
overflow: hidden;
|
|
44
|
+
}
|
|
45
|
+
#diskused {
|
|
46
|
+
height: 100%;
|
|
47
|
+
width: 0%;
|
|
48
|
+
background: #4caf50;
|
|
49
|
+
}
|
|
50
|
+
/* Files column */
|
|
51
|
+
#files {
|
|
52
|
+
flex: 1;
|
|
53
|
+
min-width: 0;
|
|
54
|
+
display: flex;
|
|
55
|
+
flex-direction: column;
|
|
56
|
+
}
|
|
57
|
+
/* Always-visible header in Files */
|
|
58
|
+
#files-header {
|
|
59
|
+
position: sticky;
|
|
60
|
+
top: 0;
|
|
61
|
+
z-index: 5;
|
|
62
|
+
padding-bottom: 8px;
|
|
63
|
+
background: rgba(255,255,255,.1);
|
|
64
|
+
border-radius: 6px;
|
|
65
|
+
backdrop-filter: blur(2px);
|
|
66
|
+
}
|
|
67
|
+
/* Toolbar */
|
|
68
|
+
#top {
|
|
69
|
+
display: flex;
|
|
70
|
+
align-items: center;
|
|
71
|
+
gap: 8px;
|
|
72
|
+
min-height: 44px;
|
|
73
|
+
flex-wrap: wrap;
|
|
74
|
+
}
|
|
75
|
+
#top input[type="file"] {
|
|
76
|
+
max-width: 100%;
|
|
77
|
+
}
|
|
78
|
+
/* Scrollable file list ONLY */
|
|
79
|
+
#list {
|
|
80
|
+
flex: 1;
|
|
81
|
+
overflow-y: auto;
|
|
82
|
+
}
|
|
83
|
+
#list div {
|
|
84
|
+
padding: 6px 8px;
|
|
85
|
+
border-radius: 4px;
|
|
86
|
+
cursor: pointer;
|
|
87
|
+
word-break: break-word;
|
|
88
|
+
}
|
|
89
|
+
#list div:hover {
|
|
90
|
+
background: rgba(255,255,255,.1);
|
|
91
|
+
}
|
|
92
|
+
/* Default selection style (files, editor, etc) */
|
|
93
|
+
.sel {
|
|
94
|
+
background: color-mix(in srgb, white 40%, transparent);
|
|
95
|
+
box-shadow: inset 0 0 0 2px color-mix(in srgb, white 60%, transparent);
|
|
96
|
+
}
|
|
97
|
+
/* Softer selection for folders only */
|
|
98
|
+
#folder-path .sel {
|
|
99
|
+
background: color-mix(in srgb, white 15%, transparent);
|
|
100
|
+
box-shadow: none;
|
|
101
|
+
}
|
|
102
|
+
/* Folder list spacing */
|
|
103
|
+
#folder-path {
|
|
104
|
+
display: flex;
|
|
105
|
+
flex-direction: column;
|
|
106
|
+
gap: 5px;
|
|
107
|
+
}
|
|
108
|
+
/* Folder item padding + touch-friendly */
|
|
109
|
+
#folder-path .dir-item {
|
|
110
|
+
padding: 5px 6px; /*makes them easier to tap*/
|
|
111
|
+
border-radius: 3px;
|
|
112
|
+
cursor: pointer;
|
|
113
|
+
}
|
|
114
|
+
/* Hover effect for folders */
|
|
115
|
+
#folder-path .dir-item:hover {
|
|
116
|
+
background: rgba(255,255,255,.08);
|
|
117
|
+
}
|
|
118
|
+
.folders {
|
|
119
|
+
margin-bottom: 8px;
|
|
120
|
+
}
|
|
121
|
+
/* Keep Folders title + list sticky as ONE block under disk bar */
|
|
122
|
+
#folders-sticky {
|
|
123
|
+
position: sticky;
|
|
124
|
+
top: 60px; /* sits just below diskbar */
|
|
125
|
+
z-index: 4;
|
|
126
|
+
}
|
|
127
|
+
/* directory file listing effect */
|
|
128
|
+
#list.loading {
|
|
129
|
+
filter: blur(3px);
|
|
130
|
+
opacity: 0.5;
|
|
131
|
+
pointer-events: none; /* prevents clicking while loading */
|
|
132
|
+
transition: filter 0.15s ease, opacity 0.15s ease;
|
|
133
|
+
}
|
|
134
|
+
</style>
|
|
135
|
+
</head>
|
|
136
|
+
|
|
137
|
+
<body>
|
|
138
|
+
<h1> micrOS Files </h1>
|
|
139
|
+
|
|
140
|
+
<div id="ui">
|
|
141
|
+
<!-- Left sidebar (fixed, no scroll) -->
|
|
142
|
+
<aside id="folders">
|
|
143
|
+
<header id="diskbar">
|
|
144
|
+
<div id="disktext">Disk: — MB used / — MB free</div>
|
|
145
|
+
<div id="diskmeter">
|
|
146
|
+
<div id="diskused"></div>
|
|
147
|
+
</div>
|
|
148
|
+
</header>
|
|
149
|
+
|
|
150
|
+
<!-- Sticky folder block -->
|
|
151
|
+
<div id="folders-sticky">
|
|
152
|
+
<div class="folders">📂 Folders</div>
|
|
153
|
+
<div id="folder-path">/user_data</div>
|
|
154
|
+
</div>
|
|
155
|
+
</aside>
|
|
156
|
+
|
|
157
|
+
<!-- Files column -->
|
|
158
|
+
<main id="files">
|
|
159
|
+
<!-- Sticky files header -->
|
|
160
|
+
<div id="files-header">
|
|
161
|
+
<div id="top">
|
|
162
|
+
<input type="file" id="file">
|
|
163
|
+
<button onclick="uploadFile()">🔼 Upload</button>
|
|
164
|
+
<button onclick="openFile()">📖 Open</button>
|
|
165
|
+
<button onclick="download()">🔽 Download</button>
|
|
166
|
+
<button onclick="deleteFile()"> 🗑️ Delete</button>
|
|
167
|
+
<button onclick="editor()">📄 Edit</button>
|
|
168
|
+
</div>
|
|
169
|
+
</div>
|
|
170
|
+
|
|
171
|
+
<!-- Only this scrolls -->
|
|
172
|
+
<div id="list"></div>
|
|
173
|
+
</main>
|
|
174
|
+
</div>
|
|
175
|
+
|
|
176
|
+
<script src="../filesui.js"></script>
|
|
177
|
+
</body>
|
|
178
|
+
</html>
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
let selected = null;
|
|
2
|
+
let selectedEl = null; // DOM element of selected file row
|
|
3
|
+
let selectedDir = 'user_data'; // fallback
|
|
4
|
+
let _editorScriptLoaded = false;
|
|
5
|
+
let editorFile = null; // 🔹 track what's currently opened in editor
|
|
6
|
+
|
|
7
|
+
// 🔹 Simple root message output
|
|
8
|
+
let _msgTimer, _fadeTimer;
|
|
9
|
+
function popUpMsg(msg) {
|
|
10
|
+
let el = document.getElementById('root-message');
|
|
11
|
+
if (!el) {
|
|
12
|
+
el = document.createElement('div');
|
|
13
|
+
el.id = 'root-message';
|
|
14
|
+
Object.assign(el.style, {
|
|
15
|
+
position: 'fixed',
|
|
16
|
+
top: '8px',
|
|
17
|
+
left: '50%',
|
|
18
|
+
transform: 'translateX(-50%)',
|
|
19
|
+
background: 'rgba(220, 60, 60, 0.9)', // warm UI red
|
|
20
|
+
color: '#fff',
|
|
21
|
+
padding: '6px 12px',
|
|
22
|
+
borderRadius: '4px',
|
|
23
|
+
fontSize: '12px',
|
|
24
|
+
zIndex: '99999',
|
|
25
|
+
transition: 'opacity 0.4s ease',
|
|
26
|
+
opacity: '0'
|
|
27
|
+
});
|
|
28
|
+
document.body.appendChild(el);
|
|
29
|
+
}
|
|
30
|
+
el.textContent = msg;
|
|
31
|
+
el.style.display = 'block';
|
|
32
|
+
requestAnimationFrame(() => el.style.opacity = '1');
|
|
33
|
+
// Clean timers
|
|
34
|
+
clearTimeout(_msgTimer);
|
|
35
|
+
clearTimeout(_fadeTimer);
|
|
36
|
+
// Start timer
|
|
37
|
+
_msgTimer = setTimeout(() => {
|
|
38
|
+
el.style.opacity = '0';
|
|
39
|
+
_fadeTimer = setTimeout(() => el.style.display = 'none', 400);
|
|
40
|
+
}, 5000);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// 🔹 centralized selection clear
|
|
44
|
+
function clearSelection() {
|
|
45
|
+
document
|
|
46
|
+
.querySelectorAll('#list .file-item')
|
|
47
|
+
.forEach(x => x.className = 'file-item');
|
|
48
|
+
|
|
49
|
+
selected = null;
|
|
50
|
+
selectedEl = null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function load() {
|
|
54
|
+
console.info('load.loadDirs');
|
|
55
|
+
|
|
56
|
+
loadDirs().then(() => {
|
|
57
|
+
console.info('load.loadFiles:', selectedDir);
|
|
58
|
+
loadFiles();
|
|
59
|
+
});
|
|
60
|
+
console.info('load.loadDiskUsage');
|
|
61
|
+
updateDiskUsage();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function loadFiles() {
|
|
65
|
+
const contentList = document.getElementById('list');
|
|
66
|
+
|
|
67
|
+
// 🔹 Enter loading state
|
|
68
|
+
contentList.classList.add('loading');
|
|
69
|
+
|
|
70
|
+
fetch('/fs/list', {
|
|
71
|
+
method: 'POST',
|
|
72
|
+
headers: {
|
|
73
|
+
'Content-Type': 'text/plain'
|
|
74
|
+
},
|
|
75
|
+
body: selectedDir || '/'
|
|
76
|
+
})
|
|
77
|
+
.then(r => r.json())
|
|
78
|
+
.then(files => {
|
|
79
|
+
list.innerHTML = '';
|
|
80
|
+
clearSelection();
|
|
81
|
+
// 🔹 Empty folder placeholder
|
|
82
|
+
if (!Array.isArray(files) || files.length === 0) {
|
|
83
|
+
const d = document.createElement('div');
|
|
84
|
+
d.className = 'file-item placeholder';
|
|
85
|
+
d.textContent = '.empty';
|
|
86
|
+
d.style.opacity = '0.5';
|
|
87
|
+
d.style.pointerEvents = 'none'; // 🔹 non-clickable
|
|
88
|
+
list.appendChild(d);
|
|
89
|
+
|
|
90
|
+
console.info("Files loaded (empty folder)");
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
// 🔹 Files listing
|
|
94
|
+
files.forEach(f => {
|
|
95
|
+
const name = f.path.split('/').pop();
|
|
96
|
+
const d = document.createElement('div');
|
|
97
|
+
d.className = 'file-item';
|
|
98
|
+
d.textContent = `${name} ${f.size}B`;
|
|
99
|
+
|
|
100
|
+
d.onclick = (e) => {
|
|
101
|
+
e.stopPropagation();
|
|
102
|
+
|
|
103
|
+
if (selectedEl === d) {
|
|
104
|
+
clearSelection();
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
clearSelection();
|
|
109
|
+
d.className = 'file-item sel';
|
|
110
|
+
selected = name;
|
|
111
|
+
selectedEl = d;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
list.appendChild(d);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
console.info("Files loaded");
|
|
118
|
+
})
|
|
119
|
+
.catch(err => {
|
|
120
|
+
console.error("load failed:", err);
|
|
121
|
+
popUpMsg("Failed to load files: " + err.message);
|
|
122
|
+
})
|
|
123
|
+
.finally(() => {
|
|
124
|
+
// 🔹 Exit loading state (success or error)
|
|
125
|
+
contentList.classList.remove('loading');
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function loadDirs() {
|
|
130
|
+
return fetch('/fs/dirs')
|
|
131
|
+
.then(r => r.json())
|
|
132
|
+
.then(dirs => {
|
|
133
|
+
const container = document.getElementById('folder-path');
|
|
134
|
+
container.innerHTML = '';
|
|
135
|
+
|
|
136
|
+
if (!Array.isArray(dirs) || !dirs.length) return;
|
|
137
|
+
|
|
138
|
+
dirs.forEach(dir => {
|
|
139
|
+
const normalized = dir.replace(/^\/+/, '');
|
|
140
|
+
const d = document.createElement('div');
|
|
141
|
+
d.className = 'dir-item';
|
|
142
|
+
d.textContent = normalized;
|
|
143
|
+
|
|
144
|
+
d.onclick = () => {
|
|
145
|
+
document
|
|
146
|
+
.querySelectorAll('#folder-path .dir-item')
|
|
147
|
+
.forEach(x => x.className = 'dir-item');
|
|
148
|
+
|
|
149
|
+
d.className = 'dir-item sel';
|
|
150
|
+
selectedDir = normalized;
|
|
151
|
+
console.info('dirChange.loadFiles:', selectedDir);
|
|
152
|
+
loadFiles();
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
// 🔹 Selection logic
|
|
156
|
+
if (!selectedDir) {
|
|
157
|
+
selectedDir = normalized;
|
|
158
|
+
d.className = 'dir-item sel';
|
|
159
|
+
}
|
|
160
|
+
else if (normalized === selectedDir) {
|
|
161
|
+
d.className = 'dir-item sel';
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
container.appendChild(d);
|
|
165
|
+
console.info("Folders loaded");
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// 🔹 Fallback if folder vanished
|
|
169
|
+
if (
|
|
170
|
+
!container.querySelector('.dir-item.sel') &&
|
|
171
|
+
container.firstChild
|
|
172
|
+
) {
|
|
173
|
+
selectedDir = container.firstChild.textContent;
|
|
174
|
+
container.firstChild.classList.add('sel');
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
.catch(err => {
|
|
178
|
+
console.error("dirs load failed:", err);
|
|
179
|
+
popUpMsg("Failed to load folders: " + err.message);
|
|
180
|
+
})
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function uploadFile() {
|
|
184
|
+
const f = file.files[0];
|
|
185
|
+
if (!f) return;
|
|
186
|
+
|
|
187
|
+
const fd = new FormData();
|
|
188
|
+
const targetPath = `${selectedDir}/${f.name}`;
|
|
189
|
+
// This sets filename="selectedDir/file.txt" in multipart
|
|
190
|
+
fd.append('file', f, targetPath);
|
|
191
|
+
|
|
192
|
+
console.info("uploadFile:", targetPath);
|
|
193
|
+
fetch('/fs/files', { method: 'POST', body: fd })
|
|
194
|
+
.then(async r => {
|
|
195
|
+
if (!r.ok) {
|
|
196
|
+
const resp = (await r.text()) || r.statusText;
|
|
197
|
+
throw new Error(`${r.status} - ${resp}`);
|
|
198
|
+
}
|
|
199
|
+
return r;
|
|
200
|
+
})
|
|
201
|
+
.then(load)
|
|
202
|
+
.catch(err => {
|
|
203
|
+
console.error("uploadFile error:", err);
|
|
204
|
+
popUpMsg("Upload failed: " + err.message);
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function openFile() {
|
|
209
|
+
if (!selected) return;
|
|
210
|
+
const resource = `/${selectedDir}/${selected}`;
|
|
211
|
+
console.info('openFile:', resource);
|
|
212
|
+
window.open(resource);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function download() {
|
|
216
|
+
if (!selected) return;
|
|
217
|
+
|
|
218
|
+
const resource = `/${selectedDir}/${selected}`;
|
|
219
|
+
console.info('download:', resource);
|
|
220
|
+
|
|
221
|
+
const a = document.createElement('a');
|
|
222
|
+
a.href = resource;
|
|
223
|
+
a.download = selected;
|
|
224
|
+
a.click();
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function deleteFile() {
|
|
228
|
+
if (!selected) return;
|
|
229
|
+
|
|
230
|
+
const toDelete = `/${selectedDir}/${selected}`;
|
|
231
|
+
console.info("deleteFile:", toDelete);
|
|
232
|
+
|
|
233
|
+
fetch('/fs/files', { method: 'DELETE', body: toDelete })
|
|
234
|
+
.then(async r => {
|
|
235
|
+
if (!r.ok) {
|
|
236
|
+
const resp = (await r.text()) || r.statusText;
|
|
237
|
+
throw new Error(`${r.status} - ${resp}`);
|
|
238
|
+
}
|
|
239
|
+
return r;
|
|
240
|
+
})
|
|
241
|
+
.then(() => {
|
|
242
|
+
// 🔹 If the deleted file is open in editor → DESTROY editor
|
|
243
|
+
if (_editorScriptLoaded && editorFile === toDelete) {
|
|
244
|
+
window.destroyEditor?.();
|
|
245
|
+
editorFile = null;
|
|
246
|
+
console.info("deleteFile: editor destroyed");
|
|
247
|
+
}
|
|
248
|
+
})
|
|
249
|
+
.then(load)
|
|
250
|
+
.catch(err => {
|
|
251
|
+
console.error("deleteFile failed:", err);
|
|
252
|
+
popUpMsg("Delete failed: " + err.message);
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function loadEditorScript() {
|
|
257
|
+
if (_editorScriptLoaded) return Promise.resolve();
|
|
258
|
+
|
|
259
|
+
return new Promise((resolve, reject) => {
|
|
260
|
+
const s = document.createElement('script');
|
|
261
|
+
s.src = '../editor.js';
|
|
262
|
+
s.onload = () => {
|
|
263
|
+
_editorScriptLoaded = true;
|
|
264
|
+
resolve();
|
|
265
|
+
};
|
|
266
|
+
s.onerror = reject;
|
|
267
|
+
document.head.appendChild(s);
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
async function editor() {
|
|
272
|
+
const filename = selected ?? `LM_blinky.py`;
|
|
273
|
+
const resource = `/${selectedDir}/${filename}`;
|
|
274
|
+
console.info('editor:', resource);
|
|
275
|
+
|
|
276
|
+
await loadEditorScript();
|
|
277
|
+
|
|
278
|
+
let container = document.getElementById('editor');
|
|
279
|
+
if (!container) {
|
|
280
|
+
container = document.createElement('div');
|
|
281
|
+
container.id = 'editor';
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
window.createEditor(container);
|
|
285
|
+
|
|
286
|
+
// 🔹 placement delegated to editor.js
|
|
287
|
+
window.openEditor(resource, {
|
|
288
|
+
anchor: selectedEl,
|
|
289
|
+
list: document.getElementById('list')
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
editorFile = resource; // 🔹 track currently opened file
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
function updateDiskUsage() {
|
|
296
|
+
fetch('/fs/usage')
|
|
297
|
+
.then(r => r.json())
|
|
298
|
+
.then(data => {
|
|
299
|
+
const usedMB = (data.used / (1024 * 1024)).toFixed(1);
|
|
300
|
+
const freeMB = (data.free / (1024 * 1024)).toFixed(1);
|
|
301
|
+
const total = data.used + data.free;
|
|
302
|
+
const percent = total ? (data.used / total) * 100 : 0;
|
|
303
|
+
|
|
304
|
+
document.getElementById('disktext').textContent =
|
|
305
|
+
`Disk: ${usedMB} MB used / ${freeMB} MB free`;
|
|
306
|
+
|
|
307
|
+
document.getElementById('diskused').style.width =
|
|
308
|
+
`${percent.toFixed(1)}%`;
|
|
309
|
+
|
|
310
|
+
console.info("DiskUsage: update");
|
|
311
|
+
})
|
|
312
|
+
.catch(err => {
|
|
313
|
+
console.error("disk usage failed:", err);
|
|
314
|
+
popUpMsg("Disk usage unavailable: " + err.message);
|
|
315
|
+
})
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// 🔹 Global outside-click handler
|
|
319
|
+
document.addEventListener('click', (e) => {
|
|
320
|
+
// Ignore toolbar / editor buttons
|
|
321
|
+
if (e.target.closest('button')) return;
|
|
322
|
+
|
|
323
|
+
// If editor is open, keep selection locked
|
|
324
|
+
if (_editorScriptLoaded && editorFile) return;
|
|
325
|
+
|
|
326
|
+
const list = document.getElementById('list');
|
|
327
|
+
const editor = document.getElementById('editor');
|
|
328
|
+
|
|
329
|
+
if (
|
|
330
|
+
list &&
|
|
331
|
+
!list.contains(e.target) &&
|
|
332
|
+
(!editor || !editor.contains(e.target))
|
|
333
|
+
) {
|
|
334
|
+
clearSelection();
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
load();
|
|
@@ -6,14 +6,56 @@
|
|
|
6
6
|
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="black" />
|
|
7
7
|
<title>microWeb</title>
|
|
8
8
|
<link rel="stylesheet" href="ustyle.css">
|
|
9
|
+
<style>
|
|
10
|
+
hr {
|
|
11
|
+
border: none;
|
|
12
|
+
height: 2px;
|
|
13
|
+
background: rgba(255, 255, 255, 0.25);
|
|
14
|
+
margin: 16px 0;
|
|
15
|
+
}
|
|
16
|
+
#restInfoHeader {
|
|
17
|
+
margin-bottom: 12px;
|
|
18
|
+
}
|
|
19
|
+
/* Container */
|
|
20
|
+
.endpoint-groups {
|
|
21
|
+
display: flex;
|
|
22
|
+
flex-wrap: wrap;
|
|
23
|
+
gap: 12px;
|
|
24
|
+
margin-bottom: 12px;
|
|
25
|
+
width: 100%;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* Group cards */
|
|
29
|
+
.endpoint-group {
|
|
30
|
+
display: flex;
|
|
31
|
+
flex-wrap: wrap;
|
|
32
|
+
align-items: center;
|
|
33
|
+
gap: 6px;
|
|
34
|
+
padding: 8px;
|
|
35
|
+
border-radius: 6px;
|
|
36
|
+
background: rgba(255, 255, 255, 0.12);
|
|
37
|
+
backdrop-filter: blur(2px);
|
|
38
|
+
max-width: 100%;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* Prevent buttons from getting tiny */
|
|
42
|
+
.endpoint-group button {
|
|
43
|
+
white-space: nowrap;
|
|
44
|
+
}
|
|
45
|
+
</style>
|
|
9
46
|
<script src="uapi.js" defer></script>
|
|
10
47
|
</head>
|
|
11
48
|
<body>
|
|
12
49
|
<img src="https://github.com/BxNxM/micrOS/blob/master/media/logo_mini.png?raw=true" alt="micrOS Logo" width="60" height="60">
|
|
13
50
|
<h1> microWeb server </h1>
|
|
14
|
-
<
|
|
51
|
+
<div id="restInfo">
|
|
52
|
+
<div id="restInfoHeader"></div>
|
|
53
|
+
<div id="endpointHint">🔗 Endpoints:</div>
|
|
54
|
+
<div id="endpointGroups" class="endpoint-groups"></div>
|
|
55
|
+
</div>
|
|
56
|
+
<hr>
|
|
15
57
|
<h2>🚀 REST API</h2>
|
|
16
|
-
<p>
|
|
58
|
+
<p>Shortcuts:</p>
|
|
17
59
|
<button onclick="restAPI('system/info')">SysInfo</button>
|
|
18
60
|
<button onclick="restAPI('system/alarms')">Alarms</button>
|
|
19
61
|
<button onclick="restAPI('system/clock')">Clock</button>
|
|
@@ -41,19 +41,60 @@ function restConsole(apiUrl, data, delta) {
|
|
|
41
41
|
document.getElementById('restConsoleTime').innerHTML = `⏱ Response time: ${delta} ms`;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
function
|
|
44
|
+
function renderEndpointGroups(endpoints) {
|
|
45
|
+
const container = document.getElementById('endpointGroups');
|
|
46
|
+
if (!container) {return;}
|
|
47
|
+
container.innerHTML = '';
|
|
48
|
+
if (!Array.isArray(endpoints) || endpoints.length === 0) {return;}
|
|
49
|
+
const groups = endpoints.reduce((acc, endpoint) => {
|
|
50
|
+
const trimmed = endpoint.replace(/^\/+/, '');
|
|
51
|
+
if (!trimmed) {return acc;}
|
|
52
|
+
const root = trimmed.split('/')[0];
|
|
53
|
+
acc[root] = acc[root] || [];
|
|
54
|
+
acc[root].push(trimmed);
|
|
55
|
+
return acc;
|
|
56
|
+
}, {});
|
|
57
|
+
Object.keys(groups).sort().forEach(group => {
|
|
58
|
+
const entries = groups[group].sort();
|
|
59
|
+
const isSingle = entries.length === 1 && entries[0] === group;
|
|
60
|
+
if (isSingle) {
|
|
61
|
+
const button = document.createElement('button');
|
|
62
|
+
button.textContent = group;
|
|
63
|
+
button.onclick = () => window.open(`/${group}`, '_blank');
|
|
64
|
+
container.appendChild(button);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const groupEl = document.createElement('div');
|
|
68
|
+
groupEl.className = 'endpoint-group';
|
|
69
|
+
const title = document.createElement('span');
|
|
70
|
+
title.className = 'endpoint-group-title';
|
|
71
|
+
title.textContent = group;
|
|
72
|
+
groupEl.appendChild(title);
|
|
73
|
+
entries.forEach(entry => {
|
|
74
|
+
const label = entry === group ? group : entry.replace(`${group}/`, '');
|
|
75
|
+
const button = document.createElement('button');
|
|
76
|
+
button.textContent = label;
|
|
77
|
+
button.onclick = () => window.open(`/${entry}`, '_blank');
|
|
78
|
+
groupEl.appendChild(button);
|
|
79
|
+
});
|
|
80
|
+
container.appendChild(groupEl);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function restInfo(showPages=true) {
|
|
45
85
|
// UPDATES: 'restInfo' and restConsole(...)
|
|
46
|
-
restAPICore(cmd='').then(({ response, delta, query }) => {
|
|
86
|
+
restAPICore(cmd = '').then(({ response, delta, query }) => {
|
|
47
87
|
// Update API Console
|
|
48
88
|
restConsole(query, response, delta)
|
|
49
|
-
// Update '
|
|
89
|
+
// Update 'restInfo' tag
|
|
50
90
|
const result = response['result'];
|
|
51
91
|
const auth = result.auth ? "🔑" : "";
|
|
52
92
|
let infoHeader = `micrOS: ${result.micrOS} ❖ node: ${result.node}${auth}`;
|
|
53
|
-
|
|
54
|
-
.
|
|
55
|
-
|
|
56
|
-
|
|
93
|
+
if (showPages) {
|
|
94
|
+
const endpoints = result['usr_endpoints'] ? Array.from(result['usr_endpoints']) : [];
|
|
95
|
+
renderEndpointGroups(endpoints);
|
|
96
|
+
}
|
|
97
|
+
document.getElementById('restInfoHeader').innerHTML = infoHeader;
|
|
57
98
|
}).catch(error => {
|
|
58
99
|
console.error('Error in restAPI:', error);
|
|
59
100
|
});
|
|
@@ -4,10 +4,13 @@
|
|
|
4
4
|
100% {background-position: 0% 50%;}
|
|
5
5
|
}
|
|
6
6
|
body {
|
|
7
|
-
height:
|
|
8
|
-
width:
|
|
9
|
-
padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
|
|
7
|
+
min-height: 100vh;
|
|
8
|
+
min-width: 100vw;
|
|
10
9
|
margin: 3%;
|
|
10
|
+
padding: env(safe-area-inset-top)
|
|
11
|
+
env(safe-area-inset-right)
|
|
12
|
+
env(safe-area-inset-bottom)
|
|
13
|
+
env(safe-area-inset-left);
|
|
11
14
|
background: linear-gradient(110deg, #4b3c66, #21184f, #712336);
|
|
12
15
|
background-size: 200% 200%;
|
|
13
16
|
animation: backgroundAnimation 15s infinite;
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|