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,187 @@
|
|
|
1
|
+
"""
|
|
2
|
+
A MicroPython library for the TCS3472 light sensing chip
|
|
3
|
+
https://github.com/tti0/tcs3472-micropython
|
|
4
|
+
|
|
5
|
+
Copyright (c) 2021 tti0
|
|
6
|
+
Licensed under the MIT License
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from struct import unpack
|
|
10
|
+
from time import sleep
|
|
11
|
+
from machine import I2C, Pin, PWM
|
|
12
|
+
from microIO import bind_pin, pinmap_search
|
|
13
|
+
from Types import resolve
|
|
14
|
+
|
|
15
|
+
from LM_neopixel import load as neo_load, color as neo_color, toggle as neo_toggle # local neopixel light indicator
|
|
16
|
+
from LM_cluster import run as cluster_run # DEMO: neomatrix cluster
|
|
17
|
+
|
|
18
|
+
CURRENT_ANIMATION_INDEX = 0 # DEMO: neomatrix cluster animation
|
|
19
|
+
|
|
20
|
+
class TCS3472:
|
|
21
|
+
INSTANCE = None
|
|
22
|
+
|
|
23
|
+
def __init__(self, address=0x29, led_pin=None):
|
|
24
|
+
self._bus = I2C(sda=Pin(bind_pin('i2c_sda')), scl=Pin(bind_pin('i2c_scl')))
|
|
25
|
+
self._i2c_address = address
|
|
26
|
+
self._bus.writeto(self._i2c_address, b'\x80\x03')
|
|
27
|
+
self._bus.writeto(self._i2c_address, b'\x81\x2b')
|
|
28
|
+
self.led = PWM(Pin(bind_pin('led', led_pin), Pin.OUT), freq=20480)
|
|
29
|
+
self.led_brightness = 20
|
|
30
|
+
TCS3472.INSTANCE = self
|
|
31
|
+
|
|
32
|
+
def scaled(self, saturation=1.5):
|
|
33
|
+
"""
|
|
34
|
+
Normalize by strongest color, then adjust saturation.
|
|
35
|
+
saturation = 1.0 -> normal
|
|
36
|
+
saturation > 1.0 -> more vibrant
|
|
37
|
+
saturation < 1.0 -> more pastel
|
|
38
|
+
"""
|
|
39
|
+
_, r, g, b = self.raw()
|
|
40
|
+
m = max(r, g, b)
|
|
41
|
+
if m == 0:
|
|
42
|
+
return 0.0, 0.0, 0.0
|
|
43
|
+
|
|
44
|
+
# Normalize by strongest channel
|
|
45
|
+
r, g, b = r / m, g / m, b / m
|
|
46
|
+
|
|
47
|
+
# Grayscale = average of channels
|
|
48
|
+
gray = (r + g + b) / 3
|
|
49
|
+
|
|
50
|
+
# Interpolate between gray and color
|
|
51
|
+
r = gray + (r - gray) * saturation
|
|
52
|
+
g = gray + (g - gray) * saturation
|
|
53
|
+
b = gray + (b - gray) * saturation
|
|
54
|
+
|
|
55
|
+
# Clamp to 0..1
|
|
56
|
+
return max(0, min(1, r)), max(0, min(1, g)), max(0, min(1, b))
|
|
57
|
+
|
|
58
|
+
def rgb(self):
|
|
59
|
+
return tuple(int(x * 255) for x in self.scaled())
|
|
60
|
+
|
|
61
|
+
def light(self):
|
|
62
|
+
return self.raw()[0]
|
|
63
|
+
|
|
64
|
+
def brightness(self, level=65.535):
|
|
65
|
+
return int((self.light() / level))
|
|
66
|
+
|
|
67
|
+
def valid(self):
|
|
68
|
+
self._bus.writeto(self._i2c_address, b'\x93')
|
|
69
|
+
return self._bus.readfrom(self._i2c_address, 1)[0] & 1
|
|
70
|
+
|
|
71
|
+
def raw(self):
|
|
72
|
+
self._bus.writeto(self._i2c_address, b'\xb4')
|
|
73
|
+
return unpack("<HHHH", self._bus.readfrom(self._i2c_address, 8))
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
############################ Exposed functions ############################
|
|
77
|
+
|
|
78
|
+
def load(led_pin=20):
|
|
79
|
+
"""
|
|
80
|
+
Load the TCS3472 Color sensor instance.
|
|
81
|
+
"""
|
|
82
|
+
if TCS3472.INSTANCE is None:
|
|
83
|
+
TCS3472(led_pin=led_pin)
|
|
84
|
+
neo_load(ledcnt=1)
|
|
85
|
+
led(False)
|
|
86
|
+
return TCS3472.INSTANCE
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def pinmap():
|
|
90
|
+
"""
|
|
91
|
+
Show used pin mapping for this module.
|
|
92
|
+
"""
|
|
93
|
+
return pinmap_search(['i2c_scl', 'i2c_sda', 'led'])
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def measure():
|
|
97
|
+
"""
|
|
98
|
+
MEASURE sensor
|
|
99
|
+
"""
|
|
100
|
+
sensor = load()
|
|
101
|
+
measurement = {"rgb": sensor.rgb(), "light": sensor.light(), "brightness": sensor.brightness()}
|
|
102
|
+
return measurement
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def led(state:bool=None, br:int=None):
|
|
106
|
+
"""
|
|
107
|
+
SENSOR LED toggle
|
|
108
|
+
:param state: None-automatic, True-ON, False-OFF
|
|
109
|
+
:param br: brightness 0-100
|
|
110
|
+
"""
|
|
111
|
+
def _set_duty(_br):
|
|
112
|
+
_br = sensor.led_brightness if _br is None else _br
|
|
113
|
+
sensor.led.duty(int(_br * 10))
|
|
114
|
+
if _br != 0:
|
|
115
|
+
sensor.led_brightness = _br
|
|
116
|
+
|
|
117
|
+
sensor = load()
|
|
118
|
+
if state is None:
|
|
119
|
+
# INVERT STATE
|
|
120
|
+
led_current_state = sensor.led.duty() > 0
|
|
121
|
+
if led_current_state:
|
|
122
|
+
_set_duty(br)
|
|
123
|
+
_set_duty(0)
|
|
124
|
+
neo_toggle(False)
|
|
125
|
+
else:
|
|
126
|
+
_set_duty(br)
|
|
127
|
+
neo_toggle(True)
|
|
128
|
+
else:
|
|
129
|
+
# SET STATE: ON/OFF
|
|
130
|
+
if state:
|
|
131
|
+
_set_duty(br)
|
|
132
|
+
neo_toggle(True)
|
|
133
|
+
else:
|
|
134
|
+
_set_duty(br)
|
|
135
|
+
_set_duty(0)
|
|
136
|
+
neo_toggle(False)
|
|
137
|
+
return f"LED on, {sensor.led_brightness}%" if sensor.led.duty()>0 else f"LED off"
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def indicator(br=5):
|
|
141
|
+
"""
|
|
142
|
+
Color indicator Neopixel LED update
|
|
143
|
+
:param br: brightness 0-100
|
|
144
|
+
"""
|
|
145
|
+
r, g, b = measure()['rgb']
|
|
146
|
+
br = float(br / 100)
|
|
147
|
+
_r, _g, _b = int(r*br), int(g*br), int(b*br)
|
|
148
|
+
neo_color(_r, _g, _b, smooth=False)
|
|
149
|
+
return r, g, b
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def neomatrix_update():
|
|
153
|
+
"""
|
|
154
|
+
DEMO - Send color codes for all neomatrix devices over espnow cluster
|
|
155
|
+
"""
|
|
156
|
+
r, g, b = indicator()
|
|
157
|
+
command = f"neomatrix color_fill {r} {g} {b}"
|
|
158
|
+
cluster_run(command)
|
|
159
|
+
return {"cmd": command, "cluster": "task show con.espnow.*"}
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def neomatrix_animation():
|
|
163
|
+
"""
|
|
164
|
+
DEMO - Set random animation on neomatrix espnow cluster
|
|
165
|
+
"""
|
|
166
|
+
global CURRENT_ANIMATION_INDEX
|
|
167
|
+
animations = ('spiral', 'snake', 'noise')
|
|
168
|
+
|
|
169
|
+
next_animation = CURRENT_ANIMATION_INDEX + 1
|
|
170
|
+
CURRENT_ANIMATION_INDEX = 0 if next_animation >= len(animations) else next_animation
|
|
171
|
+
command = f"neomatrix {animations[CURRENT_ANIMATION_INDEX]}"
|
|
172
|
+
cluster_run(command)
|
|
173
|
+
return {"cmd": command, "cluster": "task show con.espnow.*"}
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def help(widgets=False):
|
|
177
|
+
"""
|
|
178
|
+
TCS3472 Color sensor
|
|
179
|
+
"""
|
|
180
|
+
return resolve(('load led_pin=20',
|
|
181
|
+
'TEXTBOX measure',
|
|
182
|
+
'BUTTON led state=<True,False>',
|
|
183
|
+
'SLIDER led state=True br=<0-100-5>',
|
|
184
|
+
'indicator br=<0-100>',
|
|
185
|
+
'BUTTON neomatrix_update',
|
|
186
|
+
'BUTTON neomatrix_animation',
|
|
187
|
+
'pinmap'), widgets=widgets)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -38,6 +38,9 @@
|
|
|
38
38
|
</head>
|
|
39
39
|
<body>
|
|
40
40
|
<h1> micrOS dashboard </h1>
|
|
41
|
+
<div id="restInfo">
|
|
42
|
+
<div id="restInfoHeader"></div>
|
|
43
|
+
</div>
|
|
41
44
|
<!-- Container for the dynamically generated list -->
|
|
42
45
|
<section id="widgets-section"></section>
|
|
43
46
|
<br><br><br>
|
|
@@ -54,6 +57,7 @@
|
|
|
54
57
|
<script>
|
|
55
58
|
document.addEventListener("DOMContentLoaded", function() {
|
|
56
59
|
// Init basic info from board after DOM is fully loaded
|
|
60
|
+
restInfo(showPages=false);
|
|
57
61
|
|
|
58
62
|
// INIT DASHBOARD (load active modules -> build page)
|
|
59
63
|
DynamicWidgetLoad();
|
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
/* ============================================================
|
|
2
|
+
* Embedded MicroPython Editor
|
|
3
|
+
* Self-contained, embeddable, dependency-free
|
|
4
|
+
*
|
|
5
|
+
* Public API:
|
|
6
|
+
* createEditor(container)
|
|
7
|
+
* openEditor(url, { anchor, list })
|
|
8
|
+
* destroyEditor()
|
|
9
|
+
* ============================================================ */
|
|
10
|
+
|
|
11
|
+
let _editor = null;
|
|
12
|
+
|
|
13
|
+
// 🔹 track original DOM position of editor container
|
|
14
|
+
let _host = {
|
|
15
|
+
container: null,
|
|
16
|
+
parent: null,
|
|
17
|
+
next: null
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/* ---------- Public API ---------- */
|
|
21
|
+
|
|
22
|
+
window.createEditor = function (container) {
|
|
23
|
+
console.info("editor.js: createEditor");
|
|
24
|
+
injectCSS();
|
|
25
|
+
|
|
26
|
+
if (!_editor) {
|
|
27
|
+
_host.container = container;
|
|
28
|
+
_host.parent = container.parentNode;
|
|
29
|
+
_host.next = container.nextSibling;
|
|
30
|
+
|
|
31
|
+
_editor = new EmbeddedEditor(container);
|
|
32
|
+
}
|
|
33
|
+
return _editor;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
window.openEditor = function (url, opts = {}) {
|
|
37
|
+
if (!_editor) {
|
|
38
|
+
console.warn("Editor not active");
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
console.info("editor.js: openEditor");
|
|
42
|
+
const { anchor, list } = opts;
|
|
43
|
+
const c = _host.container;
|
|
44
|
+
// 🔹 editor owns placement logic
|
|
45
|
+
if (anchor) {
|
|
46
|
+
anchor.insertAdjacentElement("afterend", c);
|
|
47
|
+
console.info("editor.js: openEditor.placed after selected element");
|
|
48
|
+
} else if (list) {
|
|
49
|
+
list.insertAdjacentElement("beforebegin", c);
|
|
50
|
+
console.info("editor.js: openEditor.placed before selected element");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
_editor.open(url);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
window.destroyEditor = function () {
|
|
57
|
+
if (_editor) {
|
|
58
|
+
_editor.close();
|
|
59
|
+
if (_host.container) {
|
|
60
|
+
_host.container.remove();
|
|
61
|
+
console.info("editor.js: destroyEditor - container removed");
|
|
62
|
+
}
|
|
63
|
+
_editor = null;
|
|
64
|
+
_host.container = null;
|
|
65
|
+
_host.parent = null;
|
|
66
|
+
_host.next = null;
|
|
67
|
+
console.info("editor.js: destroyEditor - editor destroyed");
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/* ---------- CSS (scoped + injected) ---------- */
|
|
72
|
+
|
|
73
|
+
function injectCSS() {
|
|
74
|
+
if (document.getElementById("mp-editor-css")) return;
|
|
75
|
+
|
|
76
|
+
const css = document.createElement("style");
|
|
77
|
+
css.id = "mp-editor-css";
|
|
78
|
+
css.textContent = `
|
|
79
|
+
.mp-editor {
|
|
80
|
+
font-family: monospace;
|
|
81
|
+
background: #1e1e1e;
|
|
82
|
+
color: #d4d4d4;
|
|
83
|
+
}
|
|
84
|
+
.mp-editor .toolbar {
|
|
85
|
+
background: #252526;
|
|
86
|
+
padding: 6px;
|
|
87
|
+
display: flex;
|
|
88
|
+
gap: 6px;
|
|
89
|
+
align-items: center;
|
|
90
|
+
}
|
|
91
|
+
.mp-editor input {
|
|
92
|
+
background: #1e1e1e;
|
|
93
|
+
color: #d4d4d4;
|
|
94
|
+
border: 1px solid #555;
|
|
95
|
+
padding: 4px 6px;
|
|
96
|
+
}
|
|
97
|
+
.mp-editor button {
|
|
98
|
+
background: #0e639c;
|
|
99
|
+
border: none;
|
|
100
|
+
color: #fff;
|
|
101
|
+
padding: 6px 10px;
|
|
102
|
+
cursor: pointer;
|
|
103
|
+
}
|
|
104
|
+
.mp-editor button:hover { background: #1177bb; }
|
|
105
|
+
.mp-editor .close {
|
|
106
|
+
margin-left: auto;
|
|
107
|
+
background: transparent;
|
|
108
|
+
color: #ccc;
|
|
109
|
+
font-size: 16px;
|
|
110
|
+
padding: 4px 8px;
|
|
111
|
+
}
|
|
112
|
+
.mp-editor .close:hover { background: #333; color: #fff; }
|
|
113
|
+
.mp-editor .status { font-size: 13px; }
|
|
114
|
+
.mp-editor .status.ok { color: #6a9955; }
|
|
115
|
+
.mp-editor .status.err { color: #f44747; }
|
|
116
|
+
.mp-editor .status.info { color: #cccccc; }
|
|
117
|
+
.mp-editor .editor {
|
|
118
|
+
display: flex;
|
|
119
|
+
height: 500px;
|
|
120
|
+
overflow: hidden;
|
|
121
|
+
}
|
|
122
|
+
.mp-editor .lines {
|
|
123
|
+
background: #252526;
|
|
124
|
+
color: #858585;
|
|
125
|
+
padding: 8px;
|
|
126
|
+
text-align: right;
|
|
127
|
+
user-select: none;
|
|
128
|
+
line-height: 20px;
|
|
129
|
+
flex-shrink: 0;
|
|
130
|
+
overflow: hidden;
|
|
131
|
+
white-space: pre;
|
|
132
|
+
}
|
|
133
|
+
.mp-editor textarea {
|
|
134
|
+
flex: 1;
|
|
135
|
+
background: #1e1e1e;
|
|
136
|
+
color: #d4d4d4;
|
|
137
|
+
border: none;
|
|
138
|
+
padding: 8px;
|
|
139
|
+
resize: none;
|
|
140
|
+
outline: none;
|
|
141
|
+
font-family: monospace;
|
|
142
|
+
line-height: 20px;
|
|
143
|
+
overflow: auto;
|
|
144
|
+
}
|
|
145
|
+
.mp-editor .lines,
|
|
146
|
+
.mp-editor input,
|
|
147
|
+
.mp-editor textarea {
|
|
148
|
+
font-size: 14px;
|
|
149
|
+
}
|
|
150
|
+
`;
|
|
151
|
+
document.head.appendChild(css);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/* ---------- Syntax registry ---------- */
|
|
155
|
+
|
|
156
|
+
// 🔹 NEW
|
|
157
|
+
const SYNTAX_CHECKERS = {
|
|
158
|
+
".py": checkPythonSyntax,
|
|
159
|
+
// ".js": checkJSSyntax,
|
|
160
|
+
// ".html": checkHTMLSyntax,
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// 🔹 NEW
|
|
164
|
+
function getCheckerFor(name) {
|
|
165
|
+
const ext = "." + name.split(".").pop().toLowerCase();
|
|
166
|
+
return SYNTAX_CHECKERS[ext] || null;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/* ---------- Editor Implementation ---------- */
|
|
170
|
+
|
|
171
|
+
class EmbeddedEditor {
|
|
172
|
+
constructor(container) {
|
|
173
|
+
this.container = container;
|
|
174
|
+
this.buildUI();
|
|
175
|
+
this.bindEvents();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
buildUI() {
|
|
179
|
+
console.info("editor.js: EmbeddedEditor.buildUI");
|
|
180
|
+
this.container.innerHTML = `
|
|
181
|
+
<div class="mp-editor">
|
|
182
|
+
<div class="toolbar">
|
|
183
|
+
<input class="filename" value="">
|
|
184
|
+
<button class="load">Load</button>
|
|
185
|
+
<button class="save">Save</button>
|
|
186
|
+
<button class="syntax">Syntax</button>
|
|
187
|
+
<span class="status info">ready</span>
|
|
188
|
+
<button class="close" title="Close">✕</button>
|
|
189
|
+
</div>
|
|
190
|
+
<div class="editor">
|
|
191
|
+
<div class="lines"></div>
|
|
192
|
+
<textarea class="code" wrap="off"></textarea>
|
|
193
|
+
</div>
|
|
194
|
+
</div>`;
|
|
195
|
+
this.codeEl = this.container.querySelector(".code");
|
|
196
|
+
this.linesEl = this.container.querySelector(".lines");
|
|
197
|
+
this.fileEl = this.container.querySelector(".filename");
|
|
198
|
+
this.statusEl = this.container.querySelector(".status");
|
|
199
|
+
this.syntaxBtn = this.container.querySelector(".syntax"); // 🔹 NEW
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
bindEvents() {
|
|
203
|
+
this.codeEl.addEventListener("input", () => {
|
|
204
|
+
this.updateLines();
|
|
205
|
+
this.setStatus("edited");
|
|
206
|
+
});
|
|
207
|
+
this.codeEl.addEventListener("scroll", () =>
|
|
208
|
+
this.linesEl.scrollTop = this.codeEl.scrollTop
|
|
209
|
+
);
|
|
210
|
+
this.codeEl.addEventListener("keydown", e => {
|
|
211
|
+
if (e.key === "Tab") {
|
|
212
|
+
e.preventDefault();
|
|
213
|
+
const s = this.codeEl.selectionStart;
|
|
214
|
+
const ePos = this.codeEl.selectionEnd;
|
|
215
|
+
this.codeEl.value =
|
|
216
|
+
this.codeEl.value.slice(0, s) +
|
|
217
|
+
" " +
|
|
218
|
+
this.codeEl.value.slice(ePos);
|
|
219
|
+
this.codeEl.selectionStart = this.codeEl.selectionEnd = s + 4;
|
|
220
|
+
this.updateLines();
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
this.fileEl.addEventListener("input", () => // 🔹 NEW
|
|
224
|
+
this.updateSyntaxAvailability()
|
|
225
|
+
);
|
|
226
|
+
this.container.querySelector(".load")
|
|
227
|
+
.addEventListener("click", () => this.loadFile());
|
|
228
|
+
this.container.querySelector(".save")
|
|
229
|
+
.addEventListener("click", () => this.save());
|
|
230
|
+
this.container.querySelector(".syntax")
|
|
231
|
+
.addEventListener("click", () => this.syntaxCheck());
|
|
232
|
+
this.container.querySelector(".close")
|
|
233
|
+
.addEventListener("click", () => window.destroyEditor());
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/* ---------- UI helpers ---------- */
|
|
237
|
+
|
|
238
|
+
setStatus(text, type = "info") {
|
|
239
|
+
this.statusEl.textContent = text;
|
|
240
|
+
this.statusEl.className = "status " + type;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
updateSyntaxAvailability() { // 🔹 NEW
|
|
244
|
+
this.syntaxBtn.style.display =
|
|
245
|
+
getCheckerFor(this.fileEl.value) ? "" : "none";
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
updateLines() {
|
|
249
|
+
const scroll = this.codeEl.scrollTop;
|
|
250
|
+
const count = this.codeEl.value.split("\n").length;
|
|
251
|
+
this.linesEl.textContent =
|
|
252
|
+
Array.from({ length: count }, (_, i) => i + 1).join("\n");
|
|
253
|
+
this.linesEl.scrollTop = scroll;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/* ---------- File ops ---------- */
|
|
257
|
+
open(url) {
|
|
258
|
+
const name = url?.split("/").pop();
|
|
259
|
+
this.setStatus("loading...");
|
|
260
|
+
fetch(url)
|
|
261
|
+
.then(r => r.ok ? r.text() : Promise.reject())
|
|
262
|
+
.then(t => {
|
|
263
|
+
// 🔹 Success → show file content + path
|
|
264
|
+
this.codeEl.value = t;
|
|
265
|
+
this.fileEl.value = url;
|
|
266
|
+
this.updateLines();
|
|
267
|
+
this.updateSyntaxAvailability();
|
|
268
|
+
this.setStatus("loaded", "ok");
|
|
269
|
+
})
|
|
270
|
+
.catch(() => {
|
|
271
|
+
// 🔹 Failure → special case for LM_blinky.py
|
|
272
|
+
if (name === "LM_blinky.py") {
|
|
273
|
+
this.fileEl.value = url || ""; // 🔹 show path in input
|
|
274
|
+
this.loadExample();
|
|
275
|
+
} else {
|
|
276
|
+
// 🔹 Empty editor, but still show file path
|
|
277
|
+
this.codeEl.value = "";
|
|
278
|
+
this.fileEl.value = url || "";
|
|
279
|
+
this.updateLines();
|
|
280
|
+
this.updateSyntaxAvailability();
|
|
281
|
+
this.setStatus("file not found or unreadable", "err");
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
loadFile() {
|
|
287
|
+
if (!this.fileEl.value)
|
|
288
|
+
return this.setStatus("no filename", "err");
|
|
289
|
+
console.info("editor.js: EmbeddedEditor.loadFile: ", this.fileEl.value);
|
|
290
|
+
this.open(this.fileEl.value);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
save() {
|
|
294
|
+
const name = this.fileEl.value;
|
|
295
|
+
if (!name) {
|
|
296
|
+
this.setStatus("no filename", "err");
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
console.info("editor.js: EmbeddedEditor.save (upload): ", name);
|
|
301
|
+
const blob = new Blob([this.codeEl.value], { type: "text/plain" });
|
|
302
|
+
const file = new File([blob], name);
|
|
303
|
+
const fd = new FormData();
|
|
304
|
+
fd.append("file", file);
|
|
305
|
+
|
|
306
|
+
fetch("/fs/files", { method: "POST", body: fd })
|
|
307
|
+
.then(async r => {
|
|
308
|
+
if (!r.ok) {
|
|
309
|
+
const t = (await r.text()) || r.statusText;
|
|
310
|
+
console.error("editor.js: upload failed:", r.status, r.statusText, t);
|
|
311
|
+
throw new Error(`${r.status} - ${t}`);
|
|
312
|
+
}
|
|
313
|
+
this.setStatus("saved", "ok");
|
|
314
|
+
})
|
|
315
|
+
.catch(err => {
|
|
316
|
+
console.error("editor.js: upload error:", err);
|
|
317
|
+
this.setStatus("Save failed: " + err.message, "err");
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/* ---------- Syntax ---------- */
|
|
322
|
+
syntaxCheck() { // 🔹 MODIFIED
|
|
323
|
+
const checker = getCheckerFor(this.fileEl.value);
|
|
324
|
+
if (!checker) return;
|
|
325
|
+
|
|
326
|
+
const r = checker(this.codeEl.value);
|
|
327
|
+
this.setStatus(
|
|
328
|
+
r.ok ? "syntax OK" : Object.entries(r.errors[0]).map(([k, v]) => `${k}=${JSON.stringify(v)}`).join(" "),
|
|
329
|
+
r.ok ? "ok" : "err"
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/* ---------- Close ---------- */
|
|
334
|
+
close() {
|
|
335
|
+
this.container.innerHTML = "";
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/* ---------- Example ---------- */
|
|
339
|
+
|
|
340
|
+
loadExample() {
|
|
341
|
+
console.info("editor.js: EmbeddedEditor.loadExample");
|
|
342
|
+
this.codeEl.value =
|
|
343
|
+
`# LM_blinky.py – MicroPython example
|
|
344
|
+
# Guide: https://github.com/BxNxM/micrOS/blob/master/APPLICATION_GUIDE.md
|
|
345
|
+
import machine
|
|
346
|
+
from microIO import bind_pin, pinmap_search
|
|
347
|
+
from Common import micro_task
|
|
348
|
+
|
|
349
|
+
global LED = None
|
|
350
|
+
|
|
351
|
+
def load(pin=2):
|
|
352
|
+
global LED
|
|
353
|
+
if LED is None:
|
|
354
|
+
LED = machine.Pin(bind_pin("led", pin), machine.Pin.OUT)
|
|
355
|
+
return LED
|
|
356
|
+
|
|
357
|
+
@micro_task("blinky", _wrap=True)
|
|
358
|
+
def blink(tag):
|
|
359
|
+
with micro_task(tag=tag) as my_task:
|
|
360
|
+
if LED is None:
|
|
361
|
+
my_task.out = "LED uninitialized"
|
|
362
|
+
return
|
|
363
|
+
my_task.out = "BlinkyBlink task"
|
|
364
|
+
while True:
|
|
365
|
+
LED.value(not LED.value())
|
|
366
|
+
await my_task.feed(sleep_ms=500)
|
|
367
|
+
|
|
368
|
+
def pinmap():
|
|
369
|
+
return pinmap_search(['led'])
|
|
370
|
+
|
|
371
|
+
def help(widgets=False):
|
|
372
|
+
return "load pin=2", "blink", "pinmap"
|
|
373
|
+
`;
|
|
374
|
+
this.updateLines();
|
|
375
|
+
this.updateSyntaxAvailability();
|
|
376
|
+
this.setStatus("example loaded", "info");
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/* ---------- Syntax checker(s) ---------- */
|
|
382
|
+
|
|
383
|
+
function checkPythonSyntax(text) {
|
|
384
|
+
const lines = text
|
|
385
|
+
.replace(/\t/g, " ")
|
|
386
|
+
.replace(/\s+$/, "")
|
|
387
|
+
.split("\n");
|
|
388
|
+
const stack = [0];
|
|
389
|
+
const errors = [];
|
|
390
|
+
const colonRE = /^(async\s+)?(def|with|class)\s+/;
|
|
391
|
+
let depth = 0;
|
|
392
|
+
function lastCodeLine(i) {
|
|
393
|
+
while (i >= 0) {
|
|
394
|
+
const t = lines[i].trim();
|
|
395
|
+
if (t && !t.startsWith("#")) return t;
|
|
396
|
+
i--;
|
|
397
|
+
}
|
|
398
|
+
return "";
|
|
399
|
+
}
|
|
400
|
+
function updateDepth(d, line) {
|
|
401
|
+
for (const c of line.replace(/#.*$/, "")) {
|
|
402
|
+
if ("([{".includes(c)) d++;
|
|
403
|
+
else if (")]}".includes(c)) d = Math.max(0, d - 1);
|
|
404
|
+
}
|
|
405
|
+
return d;
|
|
406
|
+
}
|
|
407
|
+
lines.forEach((line, i) => {
|
|
408
|
+
const n = i + 1;
|
|
409
|
+
const t = line.trim();
|
|
410
|
+
const depthBefore = depth;
|
|
411
|
+
depth = updateDepth(depth, line);
|
|
412
|
+
const topLevel = depthBefore === 0 && depth === 0;
|
|
413
|
+
if (!t || t.startsWith("#")) return;
|
|
414
|
+
const ind = line.match(/^ */)[0].length;
|
|
415
|
+
const cur = stack[stack.length - 1];
|
|
416
|
+
// Indentation check (only at top level)
|
|
417
|
+
if (topLevel) {
|
|
418
|
+
if (ind > cur) {
|
|
419
|
+
const prev = lastCodeLine(i - 1);
|
|
420
|
+
if (!prev.endsWith(":")) {
|
|
421
|
+
errors.push({ line: n, error: "indent", prev, got: ind, expected: cur });
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
stack.push(ind);
|
|
425
|
+
}
|
|
426
|
+
while (stack.length > 1 && ind < stack[stack.length - 1]) {
|
|
427
|
+
stack.pop();
|
|
428
|
+
}
|
|
429
|
+
if (ind !== stack[stack.length - 1]) {
|
|
430
|
+
errors.push({ line: n, error: "dedent", got: ind, expected: stack[stack.length - 1] });
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
// Colon check
|
|
435
|
+
if (colonRE.test(t) && !t.endsWith(":")) {
|
|
436
|
+
errors.push({ line: n, error: "colon", lineText: t });
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
return { ok: errors.length === 0, errors };
|
|
440
|
+
}
|