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
micrOS/source/LM_oledui.py
DELETED
|
@@ -1,972 +0,0 @@
|
|
|
1
|
-
from utime import localtime, ticks_ms, ticks_diff, sleep_ms
|
|
2
|
-
from Common import syslog, micro_task, manage_task, exec_cmd
|
|
3
|
-
from Types import resolve
|
|
4
|
-
# Core modules
|
|
5
|
-
from Config import cfgget
|
|
6
|
-
from Time import uptime
|
|
7
|
-
|
|
8
|
-
# Load Modules
|
|
9
|
-
from LM_system import top, memory_usage, ifconfig, rssi as sta_rssi, list_stations
|
|
10
|
-
try:
|
|
11
|
-
import LM_intercon as InterCon
|
|
12
|
-
except:
|
|
13
|
-
InterCon = None # Optional function handling
|
|
14
|
-
try:
|
|
15
|
-
from LM_esp32 import temp as cpu_temp
|
|
16
|
-
except Exception as e:
|
|
17
|
-
cpu_temp = None # Optional function handling
|
|
18
|
-
try:
|
|
19
|
-
from LM_gameOfLife import next_gen as gol_nextgen, reset as gol_reset
|
|
20
|
-
except:
|
|
21
|
-
gol_nextgen = None # Optional function handling
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
DEBUG = False
|
|
25
|
-
|
|
26
|
-
#################################
|
|
27
|
-
# Frame classes #
|
|
28
|
-
#################################
|
|
29
|
-
|
|
30
|
-
class BaseFrame:
|
|
31
|
-
|
|
32
|
-
def __init__(self, display, width, height, x=0, y=0):
|
|
33
|
-
"""Basic pixel frame properties"""
|
|
34
|
-
self.display = display # Display object
|
|
35
|
-
self.w = width # Frame width
|
|
36
|
-
self.h = height # Frame height
|
|
37
|
-
self.x = x # Frame start X
|
|
38
|
-
self.y = y # Frame start Y
|
|
39
|
-
self.selected = False # Store frame instance selection - updated by Cursor
|
|
40
|
-
self.paused = False # Async task pause feature (Frame class)
|
|
41
|
-
|
|
42
|
-
def clean(self):
|
|
43
|
-
"""Clean pixel frame area"""
|
|
44
|
-
self.display.rect(x=self.x, y=self.y, w=self.w, h=self.h, state=0, fill=True)
|
|
45
|
-
if self.selected or DEBUG:
|
|
46
|
-
self.display.rect(x=self.x, y=self.y, w=self.w, h=self.h, state=1, fill=False)
|
|
47
|
-
|
|
48
|
-
def select(self, x, y):
|
|
49
|
-
"""Select frame based on x,x aka cursor"""
|
|
50
|
-
if self.x <= x <= self.x + self.w+1 and self.y <= y <= self.y + self.h:
|
|
51
|
-
if not self.selected:
|
|
52
|
-
self.selected = True
|
|
53
|
-
self.display.rect(x=self.x, y=self.y, w=self.w, h=self.h, state=1, fill=False)
|
|
54
|
-
else:
|
|
55
|
-
self.selected = False
|
|
56
|
-
return self.selected
|
|
57
|
-
|
|
58
|
-
def pause(self, state=None):
|
|
59
|
-
"""Used by child classes to control internal execution loop state"""
|
|
60
|
-
if state is None:
|
|
61
|
-
return self.paused
|
|
62
|
-
self.paused = state
|
|
63
|
-
return self.paused
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
class Frame(BaseFrame):
|
|
67
|
-
# Collect all created Frame objects
|
|
68
|
-
FRAMES = set()
|
|
69
|
-
HIBERNATE = False
|
|
70
|
-
|
|
71
|
-
def __init__(self, display, callback, width, height, x=0, y=0, tag="", hover_clb=None, press_clb=None):
|
|
72
|
-
super().__init__(display, width, height, x, y)
|
|
73
|
-
# Store callbacks
|
|
74
|
-
self.callback = callback # Main callback - draw or run
|
|
75
|
-
self.hover_clb = hover_clb # Hover callback - optional
|
|
76
|
-
self.press_clb = press_clb # Press callback - optional
|
|
77
|
-
self.tag = tag # used for frame identification
|
|
78
|
-
self._taskid = None # used for task identification
|
|
79
|
-
self._fast_refresh = False # Interrupt app frame task sleep - for callback reload
|
|
80
|
-
Frame.FRAMES.add(self) # Store - managed frames
|
|
81
|
-
|
|
82
|
-
def draw(self):
|
|
83
|
-
"""
|
|
84
|
-
Redraw frame
|
|
85
|
-
"""
|
|
86
|
-
self.clean()
|
|
87
|
-
# Pass adjusted useful area
|
|
88
|
-
try:
|
|
89
|
-
self.callback(self.display, self.w - 2, self.h - 2, self.x + 1, self.y + 1)
|
|
90
|
-
except Exception as e:
|
|
91
|
-
syslog(f"[ERR] Frame clb: {e}")
|
|
92
|
-
self.display.show()
|
|
93
|
-
return f"Draw {self._taskid} frame"
|
|
94
|
-
|
|
95
|
-
async def _task(self, period_ms):
|
|
96
|
-
"""
|
|
97
|
-
Frame task - draw executor
|
|
98
|
-
"""
|
|
99
|
-
with micro_task(tag=self._taskid) as my_task:
|
|
100
|
-
s = None
|
|
101
|
-
micro_sleep_ms = 50
|
|
102
|
-
period_ms = micro_sleep_ms if period_ms < micro_sleep_ms else period_ms
|
|
103
|
-
while True:
|
|
104
|
-
if s != self.paused:
|
|
105
|
-
my_task.out = 'paused' if self.paused else f'refresh: {period_ms} ms'
|
|
106
|
-
s = self.paused
|
|
107
|
-
if self.paused:
|
|
108
|
-
await my_task.feed(sleep_ms=period_ms) # extra wait in paused mode
|
|
109
|
-
else:
|
|
110
|
-
# Draw/Refresh frame
|
|
111
|
-
self.draw()
|
|
112
|
-
# Async sleep - feed event loop
|
|
113
|
-
for micro_sleep in range(0, period_ms, micro_sleep_ms):
|
|
114
|
-
if self._fast_refresh:
|
|
115
|
-
self._fast_refresh = False
|
|
116
|
-
break
|
|
117
|
-
await my_task.feed(sleep_ms=micro_sleep_ms)
|
|
118
|
-
|
|
119
|
-
def clb_refresh(self):
|
|
120
|
-
"""Fast reload app loop callbacks"""
|
|
121
|
-
self._fast_refresh = True
|
|
122
|
-
|
|
123
|
-
def run(self, tid, period_ms=500):
|
|
124
|
-
"""
|
|
125
|
-
Start registered callback frame task
|
|
126
|
-
"""
|
|
127
|
-
# [!] ASYNC TASK CREATION [1*] with async task callback + taskID (TAG) handling
|
|
128
|
-
self._taskid = f"oledui.{tid}"
|
|
129
|
-
state = micro_task(tag=self._taskid, task=self._task(period_ms=period_ms))
|
|
130
|
-
return "Starting" if state else "Already running"
|
|
131
|
-
|
|
132
|
-
def hover(self):
|
|
133
|
-
"""
|
|
134
|
-
Called by Cursor
|
|
135
|
-
"""
|
|
136
|
-
if PopUpFrame.INSTANCE is None:
|
|
137
|
-
return False
|
|
138
|
-
if callable(self.hover_clb):
|
|
139
|
-
PopUpFrame.INSTANCE.run(self.hover_clb)
|
|
140
|
-
return True
|
|
141
|
-
return False
|
|
142
|
-
|
|
143
|
-
def press(self):
|
|
144
|
-
"""
|
|
145
|
-
Redraw frame on press
|
|
146
|
-
- PageUI control
|
|
147
|
-
"""
|
|
148
|
-
if self.press_clb is None:
|
|
149
|
-
return
|
|
150
|
-
self.clean()
|
|
151
|
-
# Pass adjusted useful area
|
|
152
|
-
try:
|
|
153
|
-
self.press_clb(self.display, self.w - 2, self.h - 2, self.x + 1, self.y + 1)
|
|
154
|
-
except Exception as e:
|
|
155
|
-
syslog(f"[ERR] Frame press clb: {e}")
|
|
156
|
-
self.display.show()
|
|
157
|
-
|
|
158
|
-
@staticmethod
|
|
159
|
-
def pause_all():
|
|
160
|
-
"""
|
|
161
|
-
Pause all managed frames
|
|
162
|
-
"""
|
|
163
|
-
Frame.HIBERNATE = True
|
|
164
|
-
for frame in Frame.FRAMES:
|
|
165
|
-
frame.pause(True)
|
|
166
|
-
|
|
167
|
-
@staticmethod
|
|
168
|
-
def resume_all():
|
|
169
|
-
"""
|
|
170
|
-
Resume all managed frames
|
|
171
|
-
"""
|
|
172
|
-
Frame.HIBERNATE = False
|
|
173
|
-
for frame in Frame.FRAMES:
|
|
174
|
-
frame.pause(False)
|
|
175
|
-
frame.draw()
|
|
176
|
-
|
|
177
|
-
@staticmethod
|
|
178
|
-
def get_frame(tag):
|
|
179
|
-
"""
|
|
180
|
-
Get frame by tag
|
|
181
|
-
"""
|
|
182
|
-
for frame in Frame.FRAMES:
|
|
183
|
-
if frame.tag == tag:
|
|
184
|
-
return frame
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
class Cursor(BaseFrame):
|
|
188
|
-
TAG = "" # Selected/Active frame tag
|
|
189
|
-
|
|
190
|
-
def __init__(self, display, width, height, x=0, y=0):
|
|
191
|
-
super().__init__(display, width, height, x, y)
|
|
192
|
-
self.pos_xy = (x, y)
|
|
193
|
-
|
|
194
|
-
def draw(self):
|
|
195
|
-
x, y = self.pos_xy
|
|
196
|
-
new_x = x if x-1 < 0 else x-1
|
|
197
|
-
new_y = y+1
|
|
198
|
-
self.display.rect(new_x, new_y, 2, 2, 1) # draw new cursor
|
|
199
|
-
self.display.show()
|
|
200
|
-
|
|
201
|
-
def update(self, x, y):
|
|
202
|
-
"""
|
|
203
|
-
Update cursor with
|
|
204
|
-
- cursor position
|
|
205
|
-
- frame selection
|
|
206
|
-
"""
|
|
207
|
-
self.clean()
|
|
208
|
-
self.pos_xy = (x, y)
|
|
209
|
-
for frame in Frame.FRAMES:
|
|
210
|
-
if frame.select(x, y): # select/deselect frame based on coordinates
|
|
211
|
-
# Frame was found
|
|
212
|
-
if frame.tag != Cursor.TAG:
|
|
213
|
-
# Change event
|
|
214
|
-
if Cursor.TAG == "footer" and PageBarFrame.INSTANCE:
|
|
215
|
-
# Leave footer event - clean selection
|
|
216
|
-
PageBarFrame.INSTANCE.selected = False
|
|
217
|
-
PageBarFrame.INSTANCE.draw()
|
|
218
|
-
# Update TAG
|
|
219
|
-
Cursor.TAG = frame.tag
|
|
220
|
-
# Handle hover action
|
|
221
|
-
has_hover = frame.hover()
|
|
222
|
-
if not has_hover:
|
|
223
|
-
PopUpFrame.INSTANCE.cancel()
|
|
224
|
-
self.draw()
|
|
225
|
-
|
|
226
|
-
def clean(self):
|
|
227
|
-
"""
|
|
228
|
-
Clean previous cursor
|
|
229
|
-
"""
|
|
230
|
-
x, y = self.pos_xy
|
|
231
|
-
self.display.rect(x - 1, y + 1, 2, 2, 0)
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
class HeaderBarFrames:
|
|
235
|
-
|
|
236
|
-
def __init__(self, display, cursor_draw, timer=30):
|
|
237
|
-
self.display = display
|
|
238
|
-
self.cursor_draw = cursor_draw
|
|
239
|
-
self.timer = [timer, timer] #[0] default value, [1] timer cnt
|
|
240
|
-
# Create header: time frame
|
|
241
|
-
time_frame = Frame(self.display, self._time, width=66, height=10, x=32, y=0, tag="time",
|
|
242
|
-
hover_clb=self._time_hover)
|
|
243
|
-
time_frame.run("time", period_ms=1000)
|
|
244
|
-
# Create header: cpu,mem metrics
|
|
245
|
-
cpu_mem_frame = Frame(self.display, self._cpu_mem, width=12, height=10, x=116, y=0, tag="cpu_mem",
|
|
246
|
-
hover_clb=self._cpu_mem_hover)
|
|
247
|
-
cpu_mem_frame.run('cpu_mem', period_ms=2100)
|
|
248
|
-
# Create header: wifi rssi
|
|
249
|
-
rssi_frame = Frame(self.display, self._rssi, width=10, height=10, x=0, y=0, tag="rssi",
|
|
250
|
-
hover_clb=self._rssi_hover)
|
|
251
|
-
rssi_frame.run('rssi', period_ms=4200)
|
|
252
|
-
# Create header: timer frame (auto sleep)
|
|
253
|
-
if isinstance(timer, int):
|
|
254
|
-
timer_frame = Frame(self.display, self._timer, width=8, height=10, x=14, y=0, tag="timer",
|
|
255
|
-
hover_clb=self._timer_hover)
|
|
256
|
-
timer_frame.run("timer", period_ms=int((timer*1000)/24))
|
|
257
|
-
|
|
258
|
-
def _time(self, display, w, h, x, y):
|
|
259
|
-
# Built-in: time widget frame
|
|
260
|
-
ltime = localtime()
|
|
261
|
-
try:
|
|
262
|
-
h = f"0{ltime[-5]}" if len(str(ltime[-5])) < 2 else ltime[-5]
|
|
263
|
-
m = f"0{ltime[-4]}" if len(str(ltime[-4])) < 2 else ltime[-4]
|
|
264
|
-
s = f"0{ltime[-3]}" if len(str(ltime[-3])) < 2 else ltime[-3]
|
|
265
|
-
except:
|
|
266
|
-
h, m, s = 0, 0, 0
|
|
267
|
-
display.text(f"{h}:{m}:{s}", x, y)
|
|
268
|
-
self.cursor_draw()
|
|
269
|
-
|
|
270
|
-
def _time_hover(self, display, w, h, x, y):
|
|
271
|
-
display.text(f"Uptime:", x, y)
|
|
272
|
-
display.text(uptime(), x+10, y+10)
|
|
273
|
-
self.cursor_draw()
|
|
274
|
-
|
|
275
|
-
def _timer(self, display, w=5, h=5, x=0, y=0):
|
|
276
|
-
# Built-in: timer widget frame
|
|
277
|
-
_view = int(w * h * (self.timer[1] / self.timer[0]))
|
|
278
|
-
_complete_lines_cnt = int(_view / w) # complete lines number
|
|
279
|
-
_sub_line_x = _view - (_complete_lines_cnt * w) # incomplete line width
|
|
280
|
-
for _l in range(0, h):
|
|
281
|
-
if _l < _complete_lines_cnt:
|
|
282
|
-
display.line(x, y+_l, x+w, y+_l)
|
|
283
|
-
else:
|
|
284
|
-
display.line(x, y+_l, x+_sub_line_x, y+_l)
|
|
285
|
-
break
|
|
286
|
-
self.timer[1] -= 1
|
|
287
|
-
if self.timer[1] <= 0:
|
|
288
|
-
# Pause All Frame tasks
|
|
289
|
-
self.hibernate(display, w, h, x, y)
|
|
290
|
-
|
|
291
|
-
def _timer_hover(self, display, w, h, x, y):
|
|
292
|
-
display.text("Power off in", x, y)
|
|
293
|
-
display.text(f"{self.timer[1]} sec", x+10, y+10)
|
|
294
|
-
self.cursor_draw()
|
|
295
|
-
|
|
296
|
-
def hibernate(self, display, w, h, x, y):
|
|
297
|
-
Frame.pause_all()
|
|
298
|
-
if ScreenSaver.INSTANCE is None:
|
|
299
|
-
self.display.poweroff()
|
|
300
|
-
else:
|
|
301
|
-
ScreenSaver.INSTANCE.run()
|
|
302
|
-
self.reset_timer()
|
|
303
|
-
|
|
304
|
-
def reset_timer(self):
|
|
305
|
-
self.timer[1] = self.timer[0]
|
|
306
|
-
|
|
307
|
-
def _cpu_mem(self, display, w, h, x, y):
|
|
308
|
-
# Built-in: cpu_mem widget frame
|
|
309
|
-
sys_usage = top()
|
|
310
|
-
cpu = sys_usage.get('CPU load [%]', 100)
|
|
311
|
-
cpu = 100 if cpu > 100 else cpu # limit cpu overload in visualization
|
|
312
|
-
mem = sys_usage.get('Mem usage [%]', 100)
|
|
313
|
-
_cpu_limit, _mem_limit = cpu > 90, mem > 70 # fill indicator (limit)
|
|
314
|
-
_cpu, _mem = int(h * (cpu / 100))+1, int(h * (mem / 100))+1
|
|
315
|
-
width = int((w-2)/2)
|
|
316
|
-
y_base = y+h
|
|
317
|
-
spacer = 3
|
|
318
|
-
display.rect(x, y_base-_cpu, w=width, h=_cpu, fill=_cpu_limit) # cpu usage indicator
|
|
319
|
-
display.rect(x+width+spacer, y_base-_mem, w=width, h=_mem, fill=_mem_limit) # memory usage indicator
|
|
320
|
-
self.cursor_draw()
|
|
321
|
-
|
|
322
|
-
def _cpu_mem_hover(self, display, w, h, x, y):
|
|
323
|
-
sys_usage = top() # Get CPU and MEM usage percentage
|
|
324
|
-
mem_kb = int(memory_usage().get("mem_used", 0) / 1000) # Get MEM usage in kb
|
|
325
|
-
cpu = sys_usage.get('CPU load [%]', 100)
|
|
326
|
-
mem = sys_usage.get('Mem usage [%]', 100)
|
|
327
|
-
cpu_t = ""
|
|
328
|
-
if callable(cpu_temp):
|
|
329
|
-
_cpu_t = int(list(cpu_temp().values())[0])
|
|
330
|
-
cpu_t = f"{_cpu_t}C" if _cpu_t > 0 else ""
|
|
331
|
-
display.text(f"CPU {cpu}% {cpu_t}", x, y)
|
|
332
|
-
display.text(f"MEM {mem}%", x, y+10)
|
|
333
|
-
display.text(f"{mem_kb}kb", x+32, y+20)
|
|
334
|
-
self.cursor_draw()
|
|
335
|
-
|
|
336
|
-
@staticmethod
|
|
337
|
-
def __rssi_into():
|
|
338
|
-
value = list(sta_rssi().values())[0]
|
|
339
|
-
min_rssi, max_rssi = -90, -40
|
|
340
|
-
rssi = max(min_rssi, min(max_rssi, value))
|
|
341
|
-
rssi_ratio = ((rssi - min_rssi) / (max_rssi - min_rssi))
|
|
342
|
-
return round(rssi_ratio, 1), value
|
|
343
|
-
|
|
344
|
-
def _rssi(self, display, w, h, x, y):
|
|
345
|
-
# Built-in: _rssi widget frame
|
|
346
|
-
x = min(x-1, 0) # visual offset in start_x
|
|
347
|
-
rssi_ratio, _ = self.__rssi_into()
|
|
348
|
-
# Top level line indicator
|
|
349
|
-
display.line(x, y, x+w, y)
|
|
350
|
-
# Calculate lines
|
|
351
|
-
start_line_y = y+h-1
|
|
352
|
-
end_line_y = y + int(h*(1-rssi_ratio))
|
|
353
|
-
for y_index in range(start_line_y, end_line_y, -1):
|
|
354
|
-
end_x = x + min(w, w-int(w*(y_index/start_line_y))+1)
|
|
355
|
-
display.line(x, y_index, end_x, y_index)
|
|
356
|
-
# Button level line indicator
|
|
357
|
-
display.line(x, y+h-1, x+1, y+h-1)
|
|
358
|
-
self.cursor_draw()
|
|
359
|
-
|
|
360
|
-
def _rssi_hover(self, display, w, h, x, y):
|
|
361
|
-
nw_mode = ifconfig()[0]
|
|
362
|
-
if nw_mode == "STA":
|
|
363
|
-
rssi_ratio, strength = self.__rssi_into()
|
|
364
|
-
display.text(f"{nw_mode} mode", x, y)
|
|
365
|
-
display.text(f"rssi: {rssi_ratio*100}%", x+10, y+10)
|
|
366
|
-
display.text(f"{strength}dBm", x+50, y + 20)
|
|
367
|
-
elif nw_mode == "AP":
|
|
368
|
-
display.text(f"{nw_mode} mode", x, y)
|
|
369
|
-
devs_mac = [d[0] for d in list_stations()]
|
|
370
|
-
for i, mac in enumerate(devs_mac):
|
|
371
|
-
display.text(f"{mac}", x, y + 9 + (i*9))
|
|
372
|
-
if i > 2:
|
|
373
|
-
break
|
|
374
|
-
else:
|
|
375
|
-
display.text(f"{nw_mode} mode", x, y)
|
|
376
|
-
self.cursor_draw()
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
class AppFrame(Frame):
|
|
380
|
-
PAGES = []
|
|
381
|
-
|
|
382
|
-
def __init__(self, display, cursor_draw, width, height, x=0, y=0, tag="app", page=0):
|
|
383
|
-
super().__init__(display, self._application, width, height, x=x, y=y, tag=tag)
|
|
384
|
-
self.active_page_index = page
|
|
385
|
-
self.cursor_draw = cursor_draw
|
|
386
|
-
self.press_output = ""
|
|
387
|
-
|
|
388
|
-
def _application(self, display, width, height, x=0, y=0):
|
|
389
|
-
if len(AppFrame.PAGES) > 0:
|
|
390
|
-
page = AppFrame.PAGES[self.active_page_index]
|
|
391
|
-
# Pass adjusted useful area
|
|
392
|
-
try:
|
|
393
|
-
output = page(display, width, height, x, y)
|
|
394
|
-
# Add user press callback from page output
|
|
395
|
-
self.press_clb = output.get("press", None) if isinstance(output, dict) else None
|
|
396
|
-
except Exception as e:
|
|
397
|
-
display.text(e, x, y)
|
|
398
|
-
self.cursor_draw()
|
|
399
|
-
|
|
400
|
-
@staticmethod
|
|
401
|
-
def add_page(page):
|
|
402
|
-
if callable(page):
|
|
403
|
-
AppFrame.PAGES.append(page) # add single page
|
|
404
|
-
return True
|
|
405
|
-
if isinstance(page, list):
|
|
406
|
-
AppFrame.PAGES += page # add list of pages
|
|
407
|
-
return True
|
|
408
|
-
return False
|
|
409
|
-
|
|
410
|
-
def next(self):
|
|
411
|
-
pages_cnt = len(AppFrame.PAGES) - 1
|
|
412
|
-
self.active_page_index += 1
|
|
413
|
-
if self.active_page_index > pages_cnt:
|
|
414
|
-
self.active_page_index = 0
|
|
415
|
-
self.clb_refresh()
|
|
416
|
-
self.press_output = ""
|
|
417
|
-
|
|
418
|
-
def previous(self):
|
|
419
|
-
pages_cnt = len(AppFrame.PAGES) - 1
|
|
420
|
-
self.active_page_index -= 1
|
|
421
|
-
if self.active_page_index < 0:
|
|
422
|
-
self.active_page_index = pages_cnt
|
|
423
|
-
self.clb_refresh()
|
|
424
|
-
self.press_output = ""
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
class PageBarFrame(Frame):
|
|
428
|
-
INSTANCE = None
|
|
429
|
-
|
|
430
|
-
def __init__(self, display, cursor_draw, app_frame, width, height=5, x=0, y=0, tag="footer"):
|
|
431
|
-
super().__init__(display, self._page_indicator, width, height, x=x, y=y, tag=tag)
|
|
432
|
-
self.cursor_draw = cursor_draw
|
|
433
|
-
self.app_frame = app_frame
|
|
434
|
-
self._trigger_limit_ms = 100
|
|
435
|
-
PageBarFrame.INSTANCE = self
|
|
436
|
-
|
|
437
|
-
def _page_indicator(self, display, w, h, x, y):
|
|
438
|
-
if callable(PageUI.HAPTIC):
|
|
439
|
-
PageUI.HAPTIC()
|
|
440
|
-
page_cnt = len(AppFrame.PAGES)
|
|
441
|
-
plen = int(round(w / page_cnt))
|
|
442
|
-
# Draw active page indicator
|
|
443
|
-
display.rect(x+self.app_frame.active_page_index*plen+1, y+1, plen-2, h-2, fill=True)
|
|
444
|
-
self.cursor_draw()
|
|
445
|
-
|
|
446
|
-
class ScreenSaver(BaseFrame):
|
|
447
|
-
INSTANCE = None
|
|
448
|
-
|
|
449
|
-
def __init__(self, display, width, height, x=0, y=0):
|
|
450
|
-
super().__init__(display, width+1, height+1, x=x, y=y)
|
|
451
|
-
self.running = False
|
|
452
|
-
ScreenSaver.INSTANCE = self
|
|
453
|
-
|
|
454
|
-
def screen_saver(self):
|
|
455
|
-
# Default mode
|
|
456
|
-
if gol_nextgen is None:
|
|
457
|
-
self.cancel()
|
|
458
|
-
self.display.poweroff()
|
|
459
|
-
return # __power_save / no game of life screen saver
|
|
460
|
-
# Screen saver mode
|
|
461
|
-
matrix = gol_nextgen(raw=True)
|
|
462
|
-
if matrix is None:
|
|
463
|
-
self.cancel()
|
|
464
|
-
self.display.poweroff()
|
|
465
|
-
else:
|
|
466
|
-
# Update display with Conway's Game of Life
|
|
467
|
-
self.clean()
|
|
468
|
-
matrix_height = len(matrix)
|
|
469
|
-
for line_idx, line in enumerate(matrix):
|
|
470
|
-
for x_idx, v in enumerate(line):
|
|
471
|
-
scale = int(self.h / matrix_height)
|
|
472
|
-
if scale == 1:
|
|
473
|
-
self.display.pixel(x_idx, line_idx, color=v)
|
|
474
|
-
else:
|
|
475
|
-
self.display.rect(x_idx*scale, line_idx*scale, w=scale, h=scale, state=v, fill=True)
|
|
476
|
-
self.display.show()
|
|
477
|
-
|
|
478
|
-
async def _task(self, period_ms):
|
|
479
|
-
self.running = True
|
|
480
|
-
with micro_task(tag="oledui.anim") as my_task:
|
|
481
|
-
counter = 0
|
|
482
|
-
while self.running:
|
|
483
|
-
counter += 1
|
|
484
|
-
self.screen_saver()
|
|
485
|
-
# Store data in task cache (task show mytask)
|
|
486
|
-
my_task.out = f'GameOfLife: {counter}'
|
|
487
|
-
# Async sleep - feed event loop
|
|
488
|
-
await my_task.feed(sleep_ms=period_ms)
|
|
489
|
-
my_task.out = f'GameOfLife stopped: {counter}'
|
|
490
|
-
|
|
491
|
-
def run(self, fps=10):
|
|
492
|
-
# [!] ASYNC TASK CREATION [1*] with async task callback + taskID (TAG) handling
|
|
493
|
-
period_ms = int(1000/fps)
|
|
494
|
-
state = micro_task(tag="oledui.anim", task=self._task(period_ms))
|
|
495
|
-
return "Starting" if state else "Already running"
|
|
496
|
-
|
|
497
|
-
def cancel(self):
|
|
498
|
-
if self.running:
|
|
499
|
-
self.running = False
|
|
500
|
-
gol_reset()
|
|
501
|
-
self.clean()
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
class PopUpFrame(BaseFrame):
|
|
505
|
-
INSTANCE = None
|
|
506
|
-
|
|
507
|
-
def __init__(self, display, cursor_draw, app_frame, width, height=5, x=0, y=0):
|
|
508
|
-
super().__init__(display, width, height, x=x, y=y)
|
|
509
|
-
self.cursor_draw = cursor_draw
|
|
510
|
-
self.app_frame = app_frame
|
|
511
|
-
self.callback = None
|
|
512
|
-
self._taskid = None
|
|
513
|
-
offset = 6
|
|
514
|
-
self._inner_x = self.x + offset
|
|
515
|
-
self._inner_y = self.y + offset
|
|
516
|
-
self._inner_w = self.w - (offset * 2)
|
|
517
|
-
self._inner_h = self.h - (offset * 2)
|
|
518
|
-
PopUpFrame.INSTANCE = self
|
|
519
|
-
|
|
520
|
-
def _draw_icon(self):
|
|
521
|
-
# Frame
|
|
522
|
-
if DEBUG:
|
|
523
|
-
self.display.rect(self._inner_x, self._inner_y, self._inner_w, self._inner_h)
|
|
524
|
-
# Info sign
|
|
525
|
-
x = self._inner_x+2
|
|
526
|
-
y_dot = self._inner_y+4
|
|
527
|
-
y_base = y_dot+8
|
|
528
|
-
width = 6
|
|
529
|
-
self.display.rect(x, y_dot, width, 6, fill=1) # .
|
|
530
|
-
self.display.rect(x, y_base, width, 14, fill=1) # i
|
|
531
|
-
|
|
532
|
-
def draw(self):
|
|
533
|
-
"""Draw callback"""
|
|
534
|
-
self.clean()
|
|
535
|
-
self._draw_icon()
|
|
536
|
-
if callable(self.callback):
|
|
537
|
-
text_x_offset = 15
|
|
538
|
-
self.callback(self.display, self._inner_w, self._inner_h, self._inner_x+text_x_offset, self._inner_y+4)
|
|
539
|
-
self.display.show()
|
|
540
|
-
self.cursor_draw()
|
|
541
|
-
return f"Draw {self._taskid} frame"
|
|
542
|
-
|
|
543
|
-
def run(self, callback):
|
|
544
|
-
"""Start draw task with callback"""
|
|
545
|
-
# [!] ASYNC TASK CREATION [1*] with async task callback + taskID (TAG) handling
|
|
546
|
-
self.app_frame.pause(True)
|
|
547
|
-
self.selected = True
|
|
548
|
-
self.callback = callback
|
|
549
|
-
self.draw()
|
|
550
|
-
|
|
551
|
-
def textbox(self, msg):
|
|
552
|
-
"""
|
|
553
|
-
Draw PopUp Textbox
|
|
554
|
-
"""
|
|
555
|
-
# Prepare
|
|
556
|
-
self.app_frame.pause(True)
|
|
557
|
-
self.selected = True
|
|
558
|
-
self.clean()
|
|
559
|
-
self._draw_icon()
|
|
560
|
-
# Format message: fitting and \n parsing
|
|
561
|
-
text_x_offset = 12
|
|
562
|
-
PageUI.write_lines(msg, self.display, self._inner_x + text_x_offset, self._inner_y+4, line_limit=3)
|
|
563
|
-
self.display.show()
|
|
564
|
-
return f"Draw textbox frame"
|
|
565
|
-
|
|
566
|
-
def cancel(self):
|
|
567
|
-
if self.selected:
|
|
568
|
-
self.selected = False
|
|
569
|
-
self.clean()
|
|
570
|
-
self.app_frame.pause(False)
|
|
571
|
-
if self._taskid is not None:
|
|
572
|
-
self._taskid = None
|
|
573
|
-
return manage_task(self._taskid, "kill")
|
|
574
|
-
return True
|
|
575
|
-
|
|
576
|
-
#################################################################################
|
|
577
|
-
# PageUI manager #
|
|
578
|
-
# (Frame manager) #
|
|
579
|
-
#################################################################################
|
|
580
|
-
|
|
581
|
-
class PageUI:
|
|
582
|
-
INSTANCE = None
|
|
583
|
-
DISPLAY = None
|
|
584
|
-
HAPTIC = None
|
|
585
|
-
|
|
586
|
-
def __init__(self, w=128, h=64, page=0, poweroff=None, oled_type='ssd1306', control=None, haptic=False):
|
|
587
|
-
"""
|
|
588
|
-
:param w: screen width
|
|
589
|
-
:param h: screen height
|
|
590
|
-
:param page: start page index
|
|
591
|
-
:param poweroff: power off after given seconds
|
|
592
|
-
:param oled_type: ssd1306 or sh1106
|
|
593
|
-
:param control: trackball / None
|
|
594
|
-
"""
|
|
595
|
-
# OLED setup
|
|
596
|
-
if oled_type.strip() in ('ssd1306', 'sh1106'):
|
|
597
|
-
if oled_type.strip() == 'ssd1306':
|
|
598
|
-
import LM_oled as oled
|
|
599
|
-
else:
|
|
600
|
-
import LM_oled_sh1106 as oled
|
|
601
|
-
PageUI.DISPLAY = oled
|
|
602
|
-
oled.load(width=w, height=h, brightness=50)
|
|
603
|
-
else:
|
|
604
|
-
syslog(f"Oled UI unknown oled_type: {oled_type}")
|
|
605
|
-
Exception(f"Oled UI unknown oled_type: {oled_type}")
|
|
606
|
-
# Trackball & Haptic setup
|
|
607
|
-
self._setup(control, haptic)
|
|
608
|
-
self.width = w-1 # 128 -> 0-127: Good for xy calculation, but absolut width+1 needed!
|
|
609
|
-
self.height = h-1 # 64 -> 0-63: Good for xy calculation, but absolut width+1 needed!
|
|
610
|
-
self.page = page
|
|
611
|
-
self.timer = poweroff
|
|
612
|
-
self._last_page_switch = ticks_ms()
|
|
613
|
-
self._cmd_task_tag = None
|
|
614
|
-
# Store persistent frame objects
|
|
615
|
-
self.cursor = None
|
|
616
|
-
self.header_bar = None
|
|
617
|
-
self.app_frame = None
|
|
618
|
-
self.page_bar = None
|
|
619
|
-
self.popup = None
|
|
620
|
-
self.screen_saver = None
|
|
621
|
-
# Save
|
|
622
|
-
PageUI.INSTANCE = self
|
|
623
|
-
self.DISPLAY.clean()
|
|
624
|
-
|
|
625
|
-
def _setup(self, control, haptic):
|
|
626
|
-
# Trackball setup
|
|
627
|
-
if control is not None and control.strip() == "trackball":
|
|
628
|
-
from LM_trackball import subscribe_event
|
|
629
|
-
subscribe_event(self._control_clb)
|
|
630
|
-
# Haptic setup
|
|
631
|
-
if haptic:
|
|
632
|
-
try:
|
|
633
|
-
from LM_haptic import tap
|
|
634
|
-
PageUI.HAPTIC = tap
|
|
635
|
-
except Exception as e:
|
|
636
|
-
syslog(f"[ERR] oledui haptic: {e}")
|
|
637
|
-
|
|
638
|
-
def _boot_msg(self):
|
|
639
|
-
start_x = 24
|
|
640
|
-
start_y = 28
|
|
641
|
-
msg = "Loading..."
|
|
642
|
-
for i in range(0, len(msg)):
|
|
643
|
-
self.DISPLAY.text(msg[0:i+1], start_x, start_y)
|
|
644
|
-
self.DISPLAY.show()
|
|
645
|
-
sleep_ms(100)
|
|
646
|
-
|
|
647
|
-
def create(self):
|
|
648
|
-
self._boot_msg()
|
|
649
|
-
# Create managed frames
|
|
650
|
-
self.cursor = Cursor(PageUI.DISPLAY, width=2, height=2, x=0, y=self.height)
|
|
651
|
-
self.header_bar = HeaderBarFrames(PageUI.DISPLAY, timer=self.timer, cursor_draw=self.cursor.draw)
|
|
652
|
-
self.app_frame = AppFrame(PageUI.DISPLAY, self.cursor.draw, width=self.width+1,
|
|
653
|
-
height=self.height-15, x=0, y=self.height-53, page=self.page)
|
|
654
|
-
self.app_frame.run("page", period_ms=900)
|
|
655
|
-
self.page_bar = PageBarFrame(PageUI.DISPLAY, self.cursor.draw, self.app_frame,
|
|
656
|
-
width=self.width+1, height=6, x=0, y=self.height-5)
|
|
657
|
-
self.page_bar.draw()
|
|
658
|
-
self.popup = PopUpFrame(PageUI.DISPLAY, self.cursor.draw, self.app_frame, width=self.width+1,
|
|
659
|
-
height=self.height-15, x=0, y=self.height-53)
|
|
660
|
-
self.screen_saver = ScreenSaver(PageUI.DISPLAY, width=self.width, height=self.height, x=0, y=0)
|
|
661
|
-
|
|
662
|
-
def _control_clb(self, params):
|
|
663
|
-
"""
|
|
664
|
-
{"X": trackball.posx, "Y": trackball.posy,
|
|
665
|
-
"S": trackball.toggle, "action": trackball.action}
|
|
666
|
-
"""
|
|
667
|
-
action = params.get('action', None)
|
|
668
|
-
if action is not None:
|
|
669
|
-
x, y = params['X'], self.height - params['Y'] # invert Y axes
|
|
670
|
-
self.cursor.update(x, y)
|
|
671
|
-
lut = {"right": "next", "left": "prev"} # Convert trackball output to control command
|
|
672
|
-
self.control(lut.get(action, action))
|
|
673
|
-
self.DISPLAY.show()
|
|
674
|
-
|
|
675
|
-
def control(self, action, force=False):
|
|
676
|
-
# Wake on action
|
|
677
|
-
self.wake()
|
|
678
|
-
# Initial actions:
|
|
679
|
-
self.header_bar.reset_timer()
|
|
680
|
-
self.cursor.draw()
|
|
681
|
-
|
|
682
|
-
# Enable page lift-right scroll when footer is selected
|
|
683
|
-
if Cursor.TAG == 'footer' or force:
|
|
684
|
-
delta_t = ticks_diff(ticks_ms(), self._last_page_switch)
|
|
685
|
-
if delta_t > 200: # Check page switch frequency - max 200ms
|
|
686
|
-
self._last_page_switch = ticks_ms()
|
|
687
|
-
if action == "next":
|
|
688
|
-
self.app_frame.next()
|
|
689
|
-
if action == "prev":
|
|
690
|
-
self.app_frame.previous()
|
|
691
|
-
self.page_bar.draw()
|
|
692
|
-
if action == "off":
|
|
693
|
-
Frame.pause_all()
|
|
694
|
-
self.screen_saver.run()
|
|
695
|
-
#self.DISPLAY.poweroff()
|
|
696
|
-
if action == "on":
|
|
697
|
-
self.screen_saver.cancel()
|
|
698
|
-
Frame.resume_all()
|
|
699
|
-
self.DISPLAY.poweron()
|
|
700
|
-
if action == "press":
|
|
701
|
-
if self.popup.selected:
|
|
702
|
-
self.popup.cancel()
|
|
703
|
-
self.app_frame.press()
|
|
704
|
-
|
|
705
|
-
def wake(self):
|
|
706
|
-
"""Wake up UI from hibernation"""
|
|
707
|
-
if Frame.HIBERNATE:
|
|
708
|
-
self.screen_saver.cancel()
|
|
709
|
-
if callable(PageUI.HAPTIC):
|
|
710
|
-
PageUI.HAPTIC()
|
|
711
|
-
Frame.resume_all()
|
|
712
|
-
self.DISPLAY.poweron()
|
|
713
|
-
|
|
714
|
-
@staticmethod
|
|
715
|
-
def add_page(page):
|
|
716
|
-
return AppFrame.add_page(page)
|
|
717
|
-
|
|
718
|
-
@staticmethod
|
|
719
|
-
def write_lines(msg, display, x, y, line_limit=3):
|
|
720
|
-
chunk_size = 15
|
|
721
|
-
char_height = 10
|
|
722
|
-
text_x_offset = 3
|
|
723
|
-
# Format message: fitting and \n parsing
|
|
724
|
-
msg = msg.split('\n')
|
|
725
|
-
chunks = [line[i:i + chunk_size] for line in msg for i in range(0, len(line), chunk_size)]
|
|
726
|
-
for i, line in enumerate(chunks):
|
|
727
|
-
if i > line_limit-1: # max line_limit lines of 13 char
|
|
728
|
-
break
|
|
729
|
-
line_start_y = char_height * i
|
|
730
|
-
display.text(line, x + text_x_offset, y + line_start_y)
|
|
731
|
-
|
|
732
|
-
def _press_indicator(self, display, w, h, x, y):
|
|
733
|
-
"""Dynamic page - draw press callback indicator"""
|
|
734
|
-
if self.app_frame.press_output == "":
|
|
735
|
-
display.text("press", int(x + (w / 2) - 20), y + 30)
|
|
736
|
-
|
|
737
|
-
def lm_exec_page(self, cmd, run, display, w, h, x, y):
|
|
738
|
-
"""
|
|
739
|
-
:param cmd: load module string command
|
|
740
|
-
:param run: auto-run command (every page refresh)
|
|
741
|
-
:param display: display instance
|
|
742
|
-
:param h: frame h
|
|
743
|
-
:param w: frame w
|
|
744
|
-
:param x: frame x
|
|
745
|
-
:param y: frame y
|
|
746
|
-
"""
|
|
747
|
-
x, y = x+2, y+4
|
|
748
|
-
def _execute(display, w, h, x, y):
|
|
749
|
-
nonlocal cmd
|
|
750
|
-
try:
|
|
751
|
-
cmd_list = cmd.strip().split()
|
|
752
|
-
# Send CMD to other device & show result
|
|
753
|
-
state, out = exec_cmd(cmd_list, skip_check=True)
|
|
754
|
-
cmd_out = out.strip()
|
|
755
|
-
except Exception as e:
|
|
756
|
-
cmd_out = str(e)
|
|
757
|
-
self.app_frame.press_output = cmd_out
|
|
758
|
-
PageUI.write_lines(cmd_out, display, x, y + 15)
|
|
759
|
-
|
|
760
|
-
display.text(cmd, x, y)
|
|
761
|
-
if run:
|
|
762
|
-
_execute(display, w, h, x, y)
|
|
763
|
-
else:
|
|
764
|
-
self._press_indicator(display, w, h, x, y)
|
|
765
|
-
PageUI.write_lines(self.app_frame.press_output, display, x, y + 15)
|
|
766
|
-
# Return "press" callback, mandatory input parameters: display, w, h, x, y
|
|
767
|
-
return {"press": _execute}
|
|
768
|
-
return
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
def intercon_exec_page(self, host, cmd, run, display, w, h, x, y):
|
|
772
|
-
"""
|
|
773
|
-
:param host: hostname or IP address of a device
|
|
774
|
-
:param cmd: load module string command
|
|
775
|
-
:param run: auto-run command (every page refresh)
|
|
776
|
-
:param display: display instance
|
|
777
|
-
:param h: frame h
|
|
778
|
-
:param w: frame w
|
|
779
|
-
:param x: frame x
|
|
780
|
-
:param y: frame y
|
|
781
|
-
"""
|
|
782
|
-
x, y = x+2, y+4
|
|
783
|
-
def _execute(display, w, h, x, y):
|
|
784
|
-
nonlocal host, cmd, run
|
|
785
|
-
# Check open host connection
|
|
786
|
-
try:
|
|
787
|
-
# Send CMD to other device & show result
|
|
788
|
-
data_meta = InterCon.send_cmd(host, cmd)
|
|
789
|
-
self._cmd_task_tag = data_meta['tag']
|
|
790
|
-
if "Task is Busy" in data_meta['verdict'] and not run:
|
|
791
|
-
self.app_frame.press_output = data_meta['verdict'] # Otherwise the task start output not relevant on UI
|
|
792
|
-
except Exception as e:
|
|
793
|
-
self.app_frame.press_output = str(e)
|
|
794
|
-
|
|
795
|
-
def _read_buffer():
|
|
796
|
-
# Read command output from async buffer
|
|
797
|
-
if self._cmd_task_tag is not None:
|
|
798
|
-
task_buffer = manage_task(self._cmd_task_tag, 'show').replace(' ', '')
|
|
799
|
-
if task_buffer is not None and len(task_buffer) > 0:
|
|
800
|
-
# Set display out to task buffered data
|
|
801
|
-
self.app_frame.press_output = task_buffer
|
|
802
|
-
# data gathered - remove tag - skip re-read
|
|
803
|
-
self._cmd_task_tag = None
|
|
804
|
-
PageUI.write_lines(self.app_frame.press_output, display, x, y + 20, line_limit=2)
|
|
805
|
-
|
|
806
|
-
PageUI.write_lines(f"{host.split(".")[0]}:{cmd}", display, x, y, line_limit=2)
|
|
807
|
-
if run:
|
|
808
|
-
if self._cmd_task_tag is None:
|
|
809
|
-
_execute(display, w, h, x, y)
|
|
810
|
-
_read_buffer()
|
|
811
|
-
return
|
|
812
|
-
_read_buffer()
|
|
813
|
-
self._press_indicator(display, w, h, x, y)
|
|
814
|
-
# Return "press" callback, mandatory input parameters: display, w, h, x, y
|
|
815
|
-
return {"press": _execute}
|
|
816
|
-
|
|
817
|
-
#################################################################################
|
|
818
|
-
# Page function #
|
|
819
|
-
#################################################################################
|
|
820
|
-
|
|
821
|
-
def _system_page(display, w, h, x, y):
|
|
822
|
-
"""
|
|
823
|
-
System basic information page
|
|
824
|
-
"""
|
|
825
|
-
devip = ifconfig()[1][0]
|
|
826
|
-
display.text(cfgget("devfid"), x, y+5)
|
|
827
|
-
display.text(f" {devip}", x, y+15)
|
|
828
|
-
display.text(f" V: {cfgget('version')}", x, y+25)
|
|
829
|
-
return True
|
|
830
|
-
|
|
831
|
-
def _intercon_nodes_page(display, w, h, x, y):
|
|
832
|
-
if InterCon is None:
|
|
833
|
-
return False
|
|
834
|
-
line_limit = 3
|
|
835
|
-
line_start = y+5
|
|
836
|
-
line_cnt = 1
|
|
837
|
-
display.text("InterCon cache", x, line_start)
|
|
838
|
-
if sum([1 for _ in InterCon.host_cache()]) > 0:
|
|
839
|
-
for key, val in InterCon.host_cache().items():
|
|
840
|
-
key = key.split('.')[0]
|
|
841
|
-
val = '.'.join(val.split('.')[-2:])
|
|
842
|
-
display.text(f" {val} {key}", x, line_start + (line_cnt * 10))
|
|
843
|
-
line_cnt += 1
|
|
844
|
-
if line_cnt > line_limit:
|
|
845
|
-
break
|
|
846
|
-
return True
|
|
847
|
-
display.text("Empty", x+40, line_start + 20)
|
|
848
|
-
return True
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
def _empty_page(display, w, h, x, y):
|
|
852
|
-
pass
|
|
853
|
-
|
|
854
|
-
#################################################################################
|
|
855
|
-
# Public functions #
|
|
856
|
-
#################################################################################
|
|
857
|
-
|
|
858
|
-
def load(width=128, height=64, oled_type="sh1106", control='trackball', poweroff=None, haptic=False):
|
|
859
|
-
"""
|
|
860
|
-
Create async oled UI
|
|
861
|
-
:param width: screen width in pixels
|
|
862
|
-
:param height: screen height in pixels
|
|
863
|
-
:param oled_type: sh1106 / ssd1306
|
|
864
|
-
:param control: trackball / None
|
|
865
|
-
:param poweroff: power off after given seconds
|
|
866
|
-
:param haptic: enable (True) / disable (False) haptic feedbacks (vibration)
|
|
867
|
-
"""
|
|
868
|
-
if PageUI.INSTANCE is None:
|
|
869
|
-
ui = PageUI(width, height, poweroff=poweroff, oled_type=oled_type, control=control, haptic=haptic)
|
|
870
|
-
# Add default pages...
|
|
871
|
-
ui.add_page([_system_page, _intercon_nodes_page, _empty_page])
|
|
872
|
-
ui.create() # Header(4), AppPage(1), PagerIndicator
|
|
873
|
-
return "PageUI was created"
|
|
874
|
-
return "PageUI was already created"
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
def control(cmd="next"):
|
|
878
|
-
if cmd in ("next", "prev", "on", "off", "press"):
|
|
879
|
-
PageUI.INSTANCE.control(cmd, force=True)
|
|
880
|
-
return cmd
|
|
881
|
-
return f"Unknown action: {cmd}"
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
def popup(msg='micrOS msg'):
|
|
885
|
-
"""
|
|
886
|
-
POP-UP message function
|
|
887
|
-
:param msg: message string
|
|
888
|
-
"""
|
|
889
|
-
PageUI.INSTANCE.wake()
|
|
890
|
-
return PageUI.INSTANCE.popup.textbox(msg)
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
def cancel_popup():
|
|
894
|
-
return PageUI.INSTANCE.popup.cancel()
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
def cursor(x, y):
|
|
898
|
-
"""
|
|
899
|
-
Virtual cursor
|
|
900
|
-
:param x: x coordinate
|
|
901
|
-
:param y: y coordinate
|
|
902
|
-
"""
|
|
903
|
-
PageUI.INSTANCE.cursor.update(x, y)
|
|
904
|
-
return "Set cursor position"
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
def cmd_genpage(cmd=None, run=False):
|
|
908
|
-
"""
|
|
909
|
-
Create load module execution pages dynamically :)
|
|
910
|
-
- based on cmd value: load_module function (args)
|
|
911
|
-
:param cmd: 'load_module function (args)' string
|
|
912
|
-
:param run: run button event at page init: True/False
|
|
913
|
-
:return: page creation verdict
|
|
914
|
-
"""
|
|
915
|
-
if not isinstance(cmd, str):
|
|
916
|
-
return False
|
|
917
|
-
|
|
918
|
-
try:
|
|
919
|
-
# Create page for intercon command
|
|
920
|
-
PageUI.INSTANCE.add_page(lambda display, w, h, x, y: PageUI.INSTANCE.lm_exec_page(cmd, run, display, w, h, x, y))
|
|
921
|
-
except Exception as e:
|
|
922
|
-
syslog(f'[ERR] cmd_genpage: {e}')
|
|
923
|
-
return str(e)
|
|
924
|
-
return True
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
def intercon_genpage(cmd=None, run=False):
|
|
928
|
-
"""
|
|
929
|
-
Create intercon pages dynamically :)
|
|
930
|
-
- based on cmd value.
|
|
931
|
-
:param cmd: 'host hello' or 'host system clock'
|
|
932
|
-
:param run: run button event at page init: True/False
|
|
933
|
-
:return: page creation verdict
|
|
934
|
-
"""
|
|
935
|
-
raw = cmd.split()
|
|
936
|
-
host = raw[0]
|
|
937
|
-
cmd = ' '.join(raw[1:])
|
|
938
|
-
try:
|
|
939
|
-
# Create page for intercon command
|
|
940
|
-
PageUI.INSTANCE.add_page(lambda display, w, h, x, y: PageUI.INSTANCE.intercon_exec_page(host, cmd, run, display, w, h, x, y))
|
|
941
|
-
except Exception as e:
|
|
942
|
-
syslog(f'[ERR] intercon_genpage: {e}')
|
|
943
|
-
return str(e)
|
|
944
|
-
return True
|
|
945
|
-
|
|
946
|
-
def add_page(page_callback):
|
|
947
|
-
"""
|
|
948
|
-
[LM] Create page from load module with callback function
|
|
949
|
-
:param page_callback: callback func(display, w, h, x, y)
|
|
950
|
-
"""
|
|
951
|
-
return AppFrame.add_page(page_callback)
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
def debug():
|
|
955
|
-
global DEBUG
|
|
956
|
-
DEBUG = not DEBUG
|
|
957
|
-
return DEBUG
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
def help(widgets=False):
|
|
961
|
-
"""
|
|
962
|
-
New generation of oled_ui
|
|
963
|
-
- with async frames
|
|
964
|
-
"""
|
|
965
|
-
return resolve(
|
|
966
|
-
("load width=128 height=64 oled_type='sh1106/ssd1306' control='trackball' poweroff=None/sec haptic=False",
|
|
967
|
-
"BUTTON control cmd=<prev,press,next,on,off>",
|
|
968
|
-
"BUTTON debug", "cursor x y",
|
|
969
|
-
"popup msg='text'", "cancel_popup",
|
|
970
|
-
"cmd_genpage cmd='system clock'",
|
|
971
|
-
"intercon_genpage 'host cmd' run=False"),
|
|
972
|
-
widgets=widgets)
|