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.
Files changed (368) hide show
  1. env/driver_cp210x/macOS_VCP_Driver/SiLabsUSBDriverDisk.dmg +0 -0
  2. env/driver_cp210x/macOS_VCP_Driver/macOS_VCP_Driver_Release_Notes.txt +17 -1
  3. micrOS/micropython/esp32-20251209-v1.27.0.bin +0 -0
  4. micrOS/micropython/esp32c3-20251209-v1.27.0.bin +0 -0
  5. micrOS/micropython/esp32c6-20251209-v1.27.0.bin +0 -0
  6. micrOS/micropython/esp32s2-20251209-v1.27.0.bin +0 -0
  7. micrOS/micropython/esp32s2-LOLIN_MINI-20251209-v1.27.0.bin +0 -0
  8. micrOS/micropython/{esp32s3-20241129-v1.24.1.bin → esp32s3-4MBflash-20241129-v1.24.1.bin} +0 -0
  9. micrOS/micropython/esp32s3-8MBflash-20251209-v1.27.0.bin +0 -0
  10. micrOS/micropython/esp32s3_spiram_oct-20251209-v1.27.0.bin +0 -0
  11. micrOS/micropython/rpi-pico-w-20251209-v1.27.0.uf2 +0 -0
  12. micrOS/micropython/tinypico-20251209-v1.27.0.bin +0 -0
  13. micrOS/release_info/micrOS_ReleaseInfo/system_analysis_sum.json +167 -163
  14. micrOS/source/Auth.py +37 -0
  15. micrOS/source/Common.py +361 -116
  16. micrOS/source/Config.py +32 -22
  17. micrOS/source/Debug.py +50 -94
  18. micrOS/source/Espnow.py +377 -100
  19. micrOS/source/Files.py +207 -0
  20. micrOS/source/Hooks.py +48 -20
  21. micrOS/source/InterConnect.py +126 -42
  22. micrOS/source/Interrupts.py +6 -6
  23. micrOS/source/Logger.py +63 -26
  24. micrOS/source/Network.py +41 -21
  25. micrOS/source/Notify.py +48 -22
  26. micrOS/source/Pacman.py +326 -0
  27. micrOS/source/Scheduler.py +14 -54
  28. micrOS/source/Server.py +67 -69
  29. micrOS/source/Shell.py +99 -91
  30. micrOS/source/Tasks.py +141 -95
  31. micrOS/source/Time.py +19 -18
  32. micrOS/source/Types.py +53 -9
  33. micrOS/source/Web.py +381 -76
  34. micrOS/source/__pycache__/Common.cpython-312.pyc +0 -0
  35. micrOS/source/__pycache__/Debug.cpython-312.pyc +0 -0
  36. micrOS/source/__pycache__/Files.cpython-312.pyc +0 -0
  37. micrOS/source/__pycache__/Logger.cpython-312.pyc +0 -0
  38. micrOS/source/__pycache__/Scheduler.cpython-312.pyc +0 -0
  39. micrOS/source/__pycache__/Server.cpython-312.pyc +0 -0
  40. micrOS/source/__pycache__/Shell.cpython-312.pyc +0 -0
  41. micrOS/source/__pycache__/replhelper.cpython-312.pyc +0 -0
  42. micrOS/source/config/_git.keep +0 -0
  43. micrOS/source/helpers.py +132 -0
  44. micrOS/source/micrOS.py +17 -7
  45. micrOS/source/micrOSloader.py +5 -12
  46. micrOS/source/microIO.py +44 -20
  47. micrOS/source/modules/IO_esp32c6.py +38 -0
  48. micrOS/source/{IO_esp32s3.py → modules/IO_esp32s3.py} +37 -1
  49. micrOS/source/{IO_m5stamp.py → modules/IO_m5stamp.py} +35 -1
  50. micrOS/source/{IO_qtpy.py → modules/IO_qtpy.py} +22 -17
  51. micrOS/source/{IO_tinypico.py → modules/IO_tinypico.py} +38 -0
  52. micrOS/source/modules/LM_L298N.py +161 -0
  53. {toolkit/workspace/precompiled → micrOS/source/modules}/LM_L9110_DCmotor.py +3 -3
  54. micrOS/source/{LM_OV2640.py → modules/LM_OV2640.py} +45 -27
  55. micrOS/source/{LM_VL53L0X.py → modules/LM_VL53L0X.py} +3 -3
  56. micrOS/source/{LM_aht10.py → modules/LM_aht10.py} +2 -2
  57. micrOS/source/{LM_bme280.py → modules/LM_bme280.py} +3 -3
  58. micrOS/source/{LM_buzzer.py → modules/LM_buzzer.py} +18 -25
  59. micrOS/source/{LM_cct.py → modules/LM_cct.py} +17 -21
  60. micrOS/source/modules/LM_cluster.py +255 -0
  61. micrOS/source/{LM_co2.py → modules/LM_co2.py} +3 -3
  62. micrOS/source/{LM_dht11.py → modules/LM_dht11.py} +2 -2
  63. micrOS/source/{LM_dht22.py → modules/LM_dht22.py} +2 -2
  64. micrOS/source/{LM_dimmer.py → modules/LM_dimmer.py} +9 -9
  65. micrOS/source/{LM_distance.py → modules/LM_distance.py} +4 -6
  66. micrOS/source/{LM_ds18.py → modules/LM_ds18.py} +2 -2
  67. micrOS/source/{LM_esp32.py → modules/LM_esp32.py} +5 -0
  68. micrOS/source/modules/LM_espnow.py +53 -0
  69. micrOS/source/modules/LM_fileserver.py +265 -0
  70. micrOS/source/{LM_genIO.py → modules/LM_genIO.py} +52 -37
  71. micrOS/source/{LM_haptic.py → modules/LM_haptic.py} +2 -2
  72. {toolkit/workspace/precompiled → micrOS/source/modules}/LM_i2c.py +5 -4
  73. micrOS/source/{LM_i2s_mic.py → modules/LM_i2s_mic.py} +6 -7
  74. micrOS/source/{LM_ld2410.py → modules/LM_ld2410.py} +2 -2
  75. micrOS/source/{LM_light_sensor.py → modules/LM_light_sensor.py} +10 -21
  76. micrOS/source/modules/LM_mh_z19c.py +198 -0
  77. micrOS/source/modules/LM_neoeffects.py +284 -0
  78. micrOS/source/{LM_neopixel.py → modules/LM_neopixel.py} +19 -23
  79. micrOS/source/{LM_oled.py → modules/LM_oled.py} +2 -2
  80. micrOS/source/{LM_oled_sh1106.py → modules/LM_oled_sh1106.py} +3 -3
  81. micrOS/source/{LM_oled_ui.py → modules/LM_oled_ui.py} +72 -64
  82. micrOS/source/modules/LM_pacman.py +320 -0
  83. micrOS/source/{LM_presence.py → modules/LM_presence.py} +11 -15
  84. micrOS/source/modules/LM_qmi8658.py +204 -0
  85. micrOS/source/{LM_rencoder.py → modules/LM_rencoder.py} +2 -2
  86. micrOS/source/{LM_rest.py → modules/LM_rest.py} +4 -6
  87. micrOS/source/{LM_rgb.py → modules/LM_rgb.py} +21 -29
  88. micrOS/source/{LM_roboarm.py → modules/LM_roboarm.py} +8 -8
  89. micrOS/source/modules/LM_robustness.py +137 -0
  90. micrOS/source/{LM_servo.py → modules/LM_servo.py} +3 -3
  91. micrOS/source/{LM_stepper.py → modules/LM_stepper.py} +5 -5
  92. micrOS/source/{LM_switch.py → modules/LM_switch.py} +11 -9
  93. micrOS/source/{LM_system.py → modules/LM_system.py} +38 -32
  94. micrOS/source/modules/LM_tcs3472.py +187 -0
  95. micrOS/source/{LM_telegram.py → modules/LM_telegram.py} +164 -116
  96. micrOS/source/{LM_trackball.py → modules/LM_trackball.py} +3 -3
  97. micrOS/source/{LM_veml7700.py → modules/LM_veml7700.py} +2 -2
  98. micrOS/source/modules/LM_web.py +38 -0
  99. micrOS/source/urequests.py +39 -15
  100. {toolkit/workspace/precompiled → micrOS/source/web}/dashboard.html +4 -0
  101. micrOS/source/web/editor.js +440 -0
  102. micrOS/source/web/filesui.html +178 -0
  103. micrOS/source/web/filesui.js +338 -0
  104. {toolkit/workspace/precompiled → micrOS/source/web}/index.html +44 -2
  105. micrOS/source/{uapi.js → web/uapi.js} +48 -7
  106. micrOS/source/{ustyle.css → web/ustyle.css} +6 -3
  107. micrOS/utests/__init__.py +0 -0
  108. micrOS/utests/test_scheduler.py +435 -0
  109. {micrOSDevToolKit-2.9.1.data → microsdevtoolkit-2.26.1.data}/scripts/devToolKit.py +33 -3
  110. {micrOSDevToolKit-2.9.1.dist-info → microsdevtoolkit-2.26.1.dist-info}/METADATA +327 -268
  111. microsdevtoolkit-2.26.1.dist-info/RECORD +396 -0
  112. {micrOSDevToolKit-2.9.1.dist-info → microsdevtoolkit-2.26.1.dist-info}/WHEEL +1 -1
  113. toolkit/DevEnvCompile.py +63 -33
  114. toolkit/DevEnvOTA.py +58 -22
  115. toolkit/DevEnvUSB.py +110 -55
  116. toolkit/Gateway.py +6 -6
  117. toolkit/LM_to_compile.dat +6 -4
  118. toolkit/MicrOSDevEnv.py +127 -57
  119. toolkit/WebRepl.py +73 -0
  120. toolkit/dashboard_apps/BackupRestore.py +20 -35
  121. toolkit/dashboard_apps/CCTDemo.py +12 -17
  122. toolkit/dashboard_apps/CCTTest.py +20 -24
  123. toolkit/dashboard_apps/CamStream.py +2 -6
  124. toolkit/dashboard_apps/CatGame.py +14 -16
  125. toolkit/dashboard_apps/Dimmer.py +11 -21
  126. toolkit/dashboard_apps/GetVersion.py +11 -19
  127. toolkit/dashboard_apps/MicrophoneTest.py +1 -6
  128. toolkit/dashboard_apps/NeoEffectsDemo.py +22 -35
  129. toolkit/dashboard_apps/NeopixelTest.py +20 -25
  130. toolkit/dashboard_apps/PresenceTest.py +2 -8
  131. toolkit/dashboard_apps/QMI8685_GYRO.py +68 -0
  132. toolkit/dashboard_apps/RGBTest.py +20 -24
  133. toolkit/dashboard_apps/RoboArm.py +24 -32
  134. toolkit/dashboard_apps/SED_test.py +10 -14
  135. toolkit/dashboard_apps/SensorsTest.py +61 -0
  136. toolkit/dashboard_apps/SystemTest.py +202 -105
  137. toolkit/dashboard_apps/Template_app.py +11 -23
  138. toolkit/dashboard_apps/_app_base.py +34 -0
  139. toolkit/dashboard_apps/_gyro_visualizer.py +78 -0
  140. toolkit/dashboard_apps/uLightDemo.py +15 -24
  141. toolkit/index.html +4 -4
  142. toolkit/lib/LocalMachine.py +6 -1
  143. toolkit/lib/MicrosFiles.py +46 -0
  144. toolkit/lib/Repository.py +64 -0
  145. toolkit/lib/TerminalColors.py +4 -0
  146. toolkit/lib/macroScript.py +6 -0
  147. toolkit/lib/micrOSClient.py +123 -50
  148. toolkit/lib/micrOSClientHistory.py +156 -0
  149. toolkit/lib/pip_package_installer.py +5 -2
  150. toolkit/micrOSdashboard.py +12 -17
  151. toolkit/micrOSlint.py +20 -8
  152. toolkit/simulator_lib/__pycache__/IO_darwin.cpython-312.pyc +0 -0
  153. toolkit/simulator_lib/__pycache__/aioespnow.cpython-312.pyc +0 -0
  154. toolkit/simulator_lib/__pycache__/framebuf.cpython-312.pyc +0 -0
  155. toolkit/simulator_lib/__pycache__/machine.cpython-312.pyc +0 -0
  156. toolkit/simulator_lib/__pycache__/micropython.cpython-312.pyc +0 -0
  157. toolkit/simulator_lib/__pycache__/mip.cpython-312.pyc +0 -0
  158. toolkit/simulator_lib/__pycache__/neopixel.cpython-312.pyc +0 -0
  159. toolkit/simulator_lib/__pycache__/network.cpython-312.pyc +0 -0
  160. toolkit/simulator_lib/__pycache__/sim_common.cpython-312.pyc +0 -0
  161. toolkit/simulator_lib/__pycache__/simgc.cpython-312.pyc +0 -0
  162. toolkit/simulator_lib/__pycache__/simulator.cpython-312.pyc +0 -0
  163. toolkit/simulator_lib/__pycache__/uasyncio.cpython-312.pyc +0 -0
  164. toolkit/simulator_lib/__pycache__/uos.cpython-312.pyc +0 -0
  165. toolkit/simulator_lib/__pycache__/urandom.cpython-312.pyc +0 -0
  166. toolkit/simulator_lib/__pycache__/usocket.cpython-312.pyc +0 -0
  167. toolkit/simulator_lib/__pycache__/ussl.cpython-312.pyc +0 -0
  168. toolkit/simulator_lib/aioespnow.py +28 -0
  169. toolkit/simulator_lib/dht.py +1 -1
  170. toolkit/simulator_lib/framebuf.py +49 -1
  171. toolkit/simulator_lib/machine.py +17 -2
  172. toolkit/simulator_lib/micropython.py +3 -3
  173. toolkit/simulator_lib/mip.py +165 -0
  174. toolkit/simulator_lib/neopixel.py +3 -2
  175. toolkit/simulator_lib/network.py +2 -1
  176. toolkit/simulator_lib/node_config.json +2 -3
  177. toolkit/simulator_lib/ntptime.py +1 -1
  178. toolkit/simulator_lib/{sim_console.py → sim_common.py} +2 -3
  179. toolkit/simulator_lib/simgc.py +6 -2
  180. toolkit/simulator_lib/simulator.py +137 -59
  181. toolkit/simulator_lib/uasyncio.py +33 -2
  182. toolkit/simulator_lib/uos.py +147 -0
  183. toolkit/simulator_lib/urandom.py +4 -0
  184. toolkit/socketClient.py +43 -23
  185. toolkit/user_data/webhooks/generic.py +1 -1
  186. toolkit/user_data/webhooks/macro.py +1 -1
  187. toolkit/user_data/webhooks/template.py +1 -1
  188. toolkit/workspace/precompiled/Auth.mpy +0 -0
  189. toolkit/workspace/precompiled/Common.mpy +0 -0
  190. toolkit/workspace/precompiled/Config.mpy +0 -0
  191. toolkit/workspace/precompiled/Debug.mpy +0 -0
  192. toolkit/workspace/precompiled/Espnow.mpy +0 -0
  193. toolkit/workspace/precompiled/Files.mpy +0 -0
  194. toolkit/workspace/precompiled/Hooks.mpy +0 -0
  195. toolkit/workspace/precompiled/InterConnect.mpy +0 -0
  196. toolkit/workspace/precompiled/Interrupts.mpy +0 -0
  197. toolkit/workspace/precompiled/Logger.mpy +0 -0
  198. toolkit/workspace/precompiled/Network.mpy +0 -0
  199. toolkit/workspace/precompiled/Notify.mpy +0 -0
  200. toolkit/workspace/precompiled/Pacman.mpy +0 -0
  201. toolkit/workspace/precompiled/Scheduler.mpy +0 -0
  202. toolkit/workspace/precompiled/Server.mpy +0 -0
  203. toolkit/workspace/precompiled/Shell.mpy +0 -0
  204. toolkit/workspace/precompiled/Tasks.mpy +0 -0
  205. toolkit/workspace/precompiled/Time.mpy +0 -0
  206. toolkit/workspace/precompiled/Types.mpy +0 -0
  207. toolkit/workspace/precompiled/Web.mpy +0 -0
  208. toolkit/workspace/precompiled/_mpy.version +1 -1
  209. toolkit/workspace/precompiled/config/_git.keep +0 -0
  210. toolkit/workspace/precompiled/helpers.mpy +0 -0
  211. toolkit/workspace/precompiled/micrOS.mpy +0 -0
  212. toolkit/workspace/precompiled/micrOSloader.mpy +0 -0
  213. toolkit/workspace/precompiled/microIO.mpy +0 -0
  214. toolkit/workspace/precompiled/{IO_esp32.mpy → modules/IO_esp32.mpy} +0 -0
  215. toolkit/workspace/precompiled/{IO_esp32c3.mpy → modules/IO_esp32c3.mpy} +0 -0
  216. toolkit/workspace/precompiled/modules/IO_esp32c6.mpy +0 -0
  217. toolkit/workspace/precompiled/{IO_esp32s2.mpy → modules/IO_esp32s2.mpy} +0 -0
  218. toolkit/workspace/precompiled/modules/IO_esp32s3.mpy +0 -0
  219. toolkit/workspace/precompiled/modules/IO_m5stamp.mpy +0 -0
  220. toolkit/workspace/precompiled/modules/IO_qtpy.mpy +0 -0
  221. toolkit/workspace/precompiled/modules/IO_rp2.mpy +0 -0
  222. toolkit/workspace/precompiled/modules/IO_tinypico.mpy +0 -0
  223. toolkit/workspace/precompiled/modules/LM_L298N.mpy +0 -0
  224. {micrOS/source → toolkit/workspace/precompiled/modules}/LM_L9110_DCmotor.py +3 -3
  225. toolkit/workspace/precompiled/modules/LM_OV2640.mpy +0 -0
  226. toolkit/workspace/precompiled/{LM_VL53L0X.py → modules/LM_VL53L0X.py} +3 -3
  227. toolkit/workspace/precompiled/{LM_aht10.mpy → modules/LM_aht10.mpy} +0 -0
  228. toolkit/workspace/precompiled/{LM_bme280.mpy → modules/LM_bme280.mpy} +0 -0
  229. toolkit/workspace/precompiled/{LM_buzzer.mpy → modules/LM_buzzer.mpy} +0 -0
  230. toolkit/workspace/precompiled/modules/LM_cct.mpy +0 -0
  231. toolkit/workspace/precompiled/modules/LM_cluster.mpy +0 -0
  232. toolkit/workspace/precompiled/{LM_co2.mpy → modules/LM_co2.mpy} +0 -0
  233. toolkit/workspace/precompiled/{LM_dht11.mpy → modules/LM_dht11.mpy} +0 -0
  234. toolkit/workspace/precompiled/{LM_dht22.mpy → modules/LM_dht22.mpy} +0 -0
  235. toolkit/workspace/precompiled/modules/LM_dimmer.mpy +0 -0
  236. toolkit/workspace/precompiled/modules/LM_distance.mpy +0 -0
  237. toolkit/workspace/precompiled/{LM_ds18.mpy → modules/LM_ds18.mpy} +0 -0
  238. toolkit/workspace/precompiled/{LM_esp32.py → modules/LM_esp32.py} +5 -0
  239. toolkit/workspace/precompiled/modules/LM_espnow.py +53 -0
  240. toolkit/workspace/precompiled/modules/LM_fileserver.mpy +0 -0
  241. toolkit/workspace/precompiled/{LM_gameOfLife.mpy → modules/LM_gameOfLife.mpy} +0 -0
  242. toolkit/workspace/precompiled/modules/LM_genIO.mpy +0 -0
  243. toolkit/workspace/precompiled/{LM_haptic.mpy → modules/LM_haptic.mpy} +0 -0
  244. {micrOS/source → toolkit/workspace/precompiled/modules}/LM_i2c.py +5 -4
  245. toolkit/workspace/precompiled/modules/LM_i2s_mic.mpy +0 -0
  246. toolkit/workspace/precompiled/{LM_ld2410.mpy → modules/LM_ld2410.mpy} +0 -0
  247. toolkit/workspace/precompiled/modules/LM_light_sensor.mpy +0 -0
  248. toolkit/workspace/precompiled/modules/LM_mh_z19c.py +198 -0
  249. toolkit/workspace/precompiled/modules/LM_neoeffects.mpy +0 -0
  250. toolkit/workspace/precompiled/modules/LM_neopixel.mpy +0 -0
  251. toolkit/workspace/precompiled/{LM_oled.mpy → modules/LM_oled.mpy} +0 -0
  252. toolkit/workspace/precompiled/{LM_oled_sh1106.mpy → modules/LM_oled_sh1106.mpy} +0 -0
  253. toolkit/workspace/precompiled/modules/LM_oled_ui.mpy +0 -0
  254. toolkit/workspace/precompiled/modules/LM_pacman.mpy +0 -0
  255. toolkit/workspace/precompiled/modules/LM_presence.mpy +0 -0
  256. toolkit/workspace/precompiled/modules/LM_qmi8658.py +204 -0
  257. toolkit/workspace/precompiled/{LM_rencoder.py → modules/LM_rencoder.py} +2 -2
  258. toolkit/workspace/precompiled/modules/LM_rest.mpy +0 -0
  259. toolkit/workspace/precompiled/modules/LM_rgb.mpy +0 -0
  260. toolkit/workspace/precompiled/{LM_rgbcct.mpy → modules/LM_rgbcct.mpy} +0 -0
  261. toolkit/workspace/precompiled/modules/LM_roboarm.mpy +0 -0
  262. toolkit/workspace/precompiled/modules/LM_robustness.py +137 -0
  263. toolkit/workspace/precompiled/{LM_servo.mpy → modules/LM_servo.mpy} +0 -0
  264. toolkit/workspace/precompiled/{LM_sound_event.mpy → modules/LM_sound_event.mpy} +0 -0
  265. toolkit/workspace/precompiled/{LM_stepper.mpy → modules/LM_stepper.mpy} +0 -0
  266. toolkit/workspace/precompiled/modules/LM_switch.mpy +0 -0
  267. toolkit/workspace/precompiled/modules/LM_system.mpy +0 -0
  268. toolkit/workspace/precompiled/modules/LM_tcs3472.py +187 -0
  269. toolkit/workspace/precompiled/modules/LM_telegram.mpy +0 -0
  270. toolkit/workspace/precompiled/{LM_tinyrgb.mpy → modules/LM_tinyrgb.mpy} +0 -0
  271. toolkit/workspace/precompiled/{LM_trackball.mpy → modules/LM_trackball.mpy} +0 -0
  272. toolkit/workspace/precompiled/{LM_veml7700.mpy → modules/LM_veml7700.mpy} +0 -0
  273. toolkit/workspace/precompiled/modules/LM_web.mpy +0 -0
  274. toolkit/workspace/precompiled/urequests.mpy +0 -0
  275. {micrOS/source → toolkit/workspace/precompiled/web}/dashboard.html +4 -0
  276. toolkit/workspace/precompiled/web/editor.js +440 -0
  277. toolkit/workspace/precompiled/web/filesui.html +178 -0
  278. toolkit/workspace/precompiled/web/filesui.js +338 -0
  279. {micrOS/source → toolkit/workspace/precompiled/web}/index.html +44 -2
  280. toolkit/workspace/precompiled/{uapi.js → web/uapi.js} +48 -7
  281. toolkit/workspace/precompiled/{ustyle.css → web/ustyle.css} +6 -3
  282. micrOS/micropython/esp32-20241129-v1.24.1.bin +0 -0
  283. micrOS/micropython/esp32c3-20240222-v1.22.2.bin +0 -0
  284. micrOS/micropython/esp32s2-20240602-v1.23.0.bin +0 -0
  285. micrOS/micropython/esp32s2-LOLIN_MINI-20220618-v1.19.1.bin +0 -0
  286. micrOS/micropython/esp32s2-LOLIN_MINI-20240602-v1.23.0.bin +0 -0
  287. micrOS/micropython/esp32s3-20240105-v1.22.1.bin +0 -0
  288. micrOS/micropython/esp32s3_spiram_oct-20231005-v1.21.0.bin +0 -0
  289. micrOS/micropython/esp32s3_spiram_oct-20241129-v1.24.1.bin +0 -0
  290. micrOS/micropython/rpi-pico-w-20241129-v1.24.1.uf2 +0 -0
  291. micrOS/micropython/tinypico-20241129-v1.24.1.bin +0 -0
  292. micrOS/source/LM_L298N_DCmotor.py +0 -86
  293. micrOS/source/LM_catgame.py +0 -75
  294. micrOS/source/LM_dashboard_be.py +0 -37
  295. micrOS/source/LM_demo.py +0 -97
  296. micrOS/source/LM_espnow.py +0 -23
  297. micrOS/source/LM_intercon.py +0 -57
  298. micrOS/source/LM_keychain.py +0 -322
  299. micrOS/source/LM_lmpacman.py +0 -126
  300. micrOS/source/LM_neoeffects.py +0 -331
  301. micrOS/source/LM_oledui.py +0 -972
  302. micrOS/source/LM_pet_feeder.py +0 -78
  303. micrOS/source/LM_ph_sensor.py +0 -51
  304. micrOS/source/LM_robustness.py +0 -74
  305. micrOS/source/reset.py +0 -11
  306. micrOSDevToolKit-2.9.1.dist-info/RECORD +0 -365
  307. toolkit/dashboard_apps/AirQualityBME280.py +0 -36
  308. toolkit/dashboard_apps/AirQualityDHT22_CO2.py +0 -36
  309. toolkit/lib/file_extensions.py +0 -16
  310. toolkit/simulator_lib/__pycache__/sim_console.cpython-312.pyc +0 -0
  311. toolkit/simulator_lib/__pycache__/sim_console.cpython-38.pyc +0 -0
  312. toolkit/simulator_lib/__pycache__/sim_console.cpython-39.pyc +0 -0
  313. toolkit/workspace/precompiled/IO_esp32s3.mpy +0 -0
  314. toolkit/workspace/precompiled/IO_m5stamp.mpy +0 -0
  315. toolkit/workspace/precompiled/IO_qtpy.mpy +0 -0
  316. toolkit/workspace/precompiled/IO_rp2.mpy +0 -0
  317. toolkit/workspace/precompiled/IO_tinypico.mpy +0 -0
  318. toolkit/workspace/precompiled/LM_L298N_DCmotor.mpy +0 -0
  319. toolkit/workspace/precompiled/LM_OV2640.mpy +0 -0
  320. toolkit/workspace/precompiled/LM_catgame.py +0 -75
  321. toolkit/workspace/precompiled/LM_cct.mpy +0 -0
  322. toolkit/workspace/precompiled/LM_dashboard_be.py +0 -37
  323. toolkit/workspace/precompiled/LM_demo.py +0 -97
  324. toolkit/workspace/precompiled/LM_dimmer.mpy +0 -0
  325. toolkit/workspace/precompiled/LM_distance.mpy +0 -0
  326. toolkit/workspace/precompiled/LM_espnow.py +0 -23
  327. toolkit/workspace/precompiled/LM_genIO.mpy +0 -0
  328. toolkit/workspace/precompiled/LM_i2s_mic.mpy +0 -0
  329. toolkit/workspace/precompiled/LM_intercon.mpy +0 -0
  330. toolkit/workspace/precompiled/LM_keychain.mpy +0 -0
  331. toolkit/workspace/precompiled/LM_light_sensor.mpy +0 -0
  332. toolkit/workspace/precompiled/LM_lmpacman.mpy +0 -0
  333. toolkit/workspace/precompiled/LM_neoeffects.mpy +0 -0
  334. toolkit/workspace/precompiled/LM_neopixel.mpy +0 -0
  335. toolkit/workspace/precompiled/LM_oled_ui.mpy +0 -0
  336. toolkit/workspace/precompiled/LM_oledui.mpy +0 -0
  337. toolkit/workspace/precompiled/LM_pet_feeder.py +0 -78
  338. toolkit/workspace/precompiled/LM_ph_sensor.py +0 -51
  339. toolkit/workspace/precompiled/LM_presence.mpy +0 -0
  340. toolkit/workspace/precompiled/LM_rest.mpy +0 -0
  341. toolkit/workspace/precompiled/LM_rgb.mpy +0 -0
  342. toolkit/workspace/precompiled/LM_roboarm.mpy +0 -0
  343. toolkit/workspace/precompiled/LM_robustness.py +0 -74
  344. toolkit/workspace/precompiled/LM_switch.mpy +0 -0
  345. toolkit/workspace/precompiled/LM_system.mpy +0 -0
  346. toolkit/workspace/precompiled/LM_telegram.mpy +0 -0
  347. toolkit/workspace/precompiled/node_config.json +0 -1
  348. toolkit/workspace/precompiled/reset.mpy +0 -0
  349. /micrOS/source/{IO_esp32.py → modules/IO_esp32.py} +0 -0
  350. /micrOS/source/{IO_esp32c3.py → modules/IO_esp32c3.py} +0 -0
  351. /micrOS/source/{IO_esp32s2.py → modules/IO_esp32s2.py} +0 -0
  352. /micrOS/source/{IO_rp2.py → modules/IO_rp2.py} +0 -0
  353. /micrOS/source/{LM_gameOfLife.py → modules/LM_gameOfLife.py} +0 -0
  354. /micrOS/source/{LM_rgbcct.py → modules/LM_rgbcct.py} +0 -0
  355. /micrOS/source/{LM_rp2w.py → modules/LM_rp2w.py} +0 -0
  356. /micrOS/source/{LM_sdcard.py → modules/LM_sdcard.py} +0 -0
  357. /micrOS/source/{LM_sound_event.py → modules/LM_sound_event.py} +0 -0
  358. /micrOS/source/{LM_tinyrgb.py → modules/LM_tinyrgb.py} +0 -0
  359. /micrOS/source/{udashboard.js → web/udashboard.js} +0 -0
  360. /micrOS/source/{uwidgets.js → web/uwidgets.js} +0 -0
  361. /micrOS/source/{uwidgets_pro.js → web/uwidgets_pro.js} +0 -0
  362. {micrOSDevToolKit-2.9.1.dist-info → microsdevtoolkit-2.26.1.dist-info/licenses}/LICENSE +0 -0
  363. {micrOSDevToolKit-2.9.1.dist-info → microsdevtoolkit-2.26.1.dist-info}/top_level.txt +0 -0
  364. /toolkit/workspace/precompiled/{LM_rp2w.py → modules/LM_rp2w.py} +0 -0
  365. /toolkit/workspace/precompiled/{LM_sdcard.py → modules/LM_sdcard.py} +0 -0
  366. /toolkit/workspace/precompiled/{udashboard.js → web/udashboard.js} +0 -0
  367. /toolkit/workspace/precompiled/{uwidgets.js → web/uwidgets.js} +0 -0
  368. /toolkit/workspace/precompiled/{uwidgets_pro.js → web/uwidgets_pro.js} +0 -0
@@ -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)