micrOSDevToolKit 2.1.5__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 (400) hide show
  1. env/driver_cp210x/.DS_Store +0 -0
  2. env/driver_cp210x/macOS_VCP_Driver/SiLabsUSBDriverDisk.dmg +0 -0
  3. env/driver_cp210x/macOS_VCP_Driver/macOS_VCP_Driver_Release_Notes.txt +17 -1
  4. micrOS/micropython/esp32-20251209-v1.27.0.bin +0 -0
  5. micrOS/micropython/esp32c3-20251209-v1.27.0.bin +0 -0
  6. micrOS/micropython/esp32c6-20251209-v1.27.0.bin +0 -0
  7. micrOS/micropython/esp32s2-20251209-v1.27.0.bin +0 -0
  8. micrOS/micropython/esp32s2-LOLIN_MINI-20251209-v1.27.0.bin +0 -0
  9. micrOS/micropython/esp32s3-4MBflash-20241129-v1.24.1.bin +0 -0
  10. micrOS/micropython/esp32s3-8MBflash-20251209-v1.27.0.bin +0 -0
  11. micrOS/micropython/esp32s3_spiram_oct-20251209-v1.27.0.bin +0 -0
  12. micrOS/micropython/rpi-pico-w-20251209-v1.27.0.uf2 +0 -0
  13. micrOS/micropython/tinypico-20251209-v1.27.0.bin +0 -0
  14. micrOS/release_info/micrOS_ReleaseInfo/system_analysis_sum.json +191 -151
  15. micrOS/source/Auth.py +37 -0
  16. micrOS/source/Common.py +376 -102
  17. micrOS/source/Config.py +55 -25
  18. micrOS/source/Debug.py +54 -193
  19. micrOS/source/Espnow.py +404 -0
  20. micrOS/source/Files.py +207 -0
  21. micrOS/source/Hooks.py +88 -16
  22. micrOS/source/InterConnect.py +130 -46
  23. micrOS/source/Interrupts.py +8 -8
  24. micrOS/source/Logger.py +131 -0
  25. micrOS/source/Network.py +41 -21
  26. micrOS/source/Notify.py +74 -198
  27. micrOS/source/Pacman.py +326 -0
  28. micrOS/source/Scheduler.py +18 -55
  29. micrOS/source/Server.py +84 -217
  30. micrOS/source/Shell.py +103 -93
  31. micrOS/source/Tasks.py +239 -173
  32. micrOS/source/Time.py +21 -22
  33. micrOS/source/Types.py +89 -54
  34. micrOS/source/Web.py +485 -0
  35. micrOS/source/__pycache__/Common.cpython-312.pyc +0 -0
  36. micrOS/source/__pycache__/Debug.cpython-312.pyc +0 -0
  37. micrOS/source/__pycache__/Files.cpython-312.pyc +0 -0
  38. micrOS/source/__pycache__/Logger.cpython-312.pyc +0 -0
  39. micrOS/source/__pycache__/Scheduler.cpython-312.pyc +0 -0
  40. micrOS/source/__pycache__/Server.cpython-312.pyc +0 -0
  41. micrOS/source/__pycache__/Shell.cpython-312.pyc +0 -0
  42. micrOS/source/__pycache__/replhelper.cpython-312.pyc +0 -0
  43. micrOS/source/helpers.py +132 -0
  44. micrOS/source/micrOS.py +25 -21
  45. micrOS/source/micrOSloader.py +14 -23
  46. micrOS/source/microIO.py +94 -57
  47. toolkit/simulator_lib/LP_darwin.py → micrOS/source/modules/IO_esp32.py +22 -11
  48. micrOS/source/{IO_esp32c3.py → modules/IO_esp32c3.py} +6 -1
  49. micrOS/source/modules/IO_esp32c6.py +38 -0
  50. micrOS/source/{IO_esp32s2.py → modules/IO_esp32s2.py} +6 -1
  51. micrOS/source/{IO_esp32s3.py → modules/IO_esp32s3.py} +43 -2
  52. micrOS/source/modules/IO_m5stamp.py +86 -0
  53. micrOS/source/{IO_qtpy.py → modules/IO_qtpy.py} +28 -18
  54. micrOS/source/{IO_tinypico.py → modules/IO_tinypico.py} +48 -3
  55. micrOS/source/modules/LM_L298N.py +161 -0
  56. {toolkit/workspace/precompiled → micrOS/source/modules}/LM_L9110_DCmotor.py +4 -4
  57. micrOS/source/{LM_OV2640.py → modules/LM_OV2640.py} +53 -42
  58. micrOS/source/{LM_VL53L0X.py → modules/LM_VL53L0X.py} +5 -5
  59. micrOS/source/{LM_aht10.py → modules/LM_aht10.py} +12 -4
  60. micrOS/source/{LM_bme280.py → modules/LM_bme280.py} +13 -25
  61. micrOS/source/{LM_buzzer.py → modules/LM_buzzer.py} +42 -40
  62. micrOS/source/{LM_cct.py → modules/LM_cct.py} +22 -27
  63. micrOS/source/modules/LM_cluster.py +255 -0
  64. micrOS/source/{LM_co2.py → modules/LM_co2.py} +13 -6
  65. micrOS/source/{LM_dht11.py → modules/LM_dht11.py} +13 -29
  66. micrOS/source/{LM_dht22.py → modules/LM_dht22.py} +13 -28
  67. micrOS/source/{LM_dimmer.py → modules/LM_dimmer.py} +19 -16
  68. micrOS/source/modules/LM_distance.py +135 -0
  69. micrOS/source/{LM_ds18.py → modules/LM_ds18.py} +12 -4
  70. micrOS/source/{LM_esp32.py → modules/LM_esp32.py} +16 -4
  71. micrOS/source/modules/LM_espnow.py +53 -0
  72. micrOS/source/modules/LM_fileserver.py +265 -0
  73. micrOS/source/{LM_gameOfLife.py → modules/LM_gameOfLife.py} +5 -5
  74. micrOS/source/{LM_genIO.py → modules/LM_genIO.py} +49 -35
  75. micrOS/source/modules/LM_haptic.py +111 -0
  76. micrOS/source/modules/LM_i2c.py +61 -0
  77. micrOS/source/{LM_i2s_mic.py → modules/LM_i2s_mic.py} +20 -23
  78. micrOS/source/{LM_ld2410.py → modules/LM_ld2410.py} +3 -3
  79. micrOS/source/{LM_light_sensor.py → modules/LM_light_sensor.py} +22 -26
  80. micrOS/source/modules/LM_mh_z19c.py +198 -0
  81. micrOS/source/modules/LM_neoeffects.py +284 -0
  82. micrOS/source/{LM_neopixel.py → modules/LM_neopixel.py} +26 -31
  83. micrOS/source/{LM_oled.py → modules/LM_oled.py} +28 -20
  84. micrOS/source/{LM_oled_sh1106.py → modules/LM_oled_sh1106.py} +28 -24
  85. micrOS/source/{LM_oled_ui.py → modules/LM_oled_ui.py} +132 -174
  86. micrOS/source/modules/LM_pacman.py +320 -0
  87. micrOS/source/{LM_presence.py → modules/LM_presence.py} +24 -36
  88. micrOS/source/modules/LM_qmi8658.py +204 -0
  89. micrOS/source/{LM_rencoder.py → modules/LM_rencoder.py} +40 -11
  90. micrOS/source/modules/LM_rest.py +81 -0
  91. micrOS/source/{LM_rgb.py → modules/LM_rgb.py} +25 -34
  92. micrOS/source/{LM_rgbcct.py → modules/LM_rgbcct.py} +5 -5
  93. micrOS/source/{LM_roboarm.py → modules/LM_roboarm.py} +37 -45
  94. micrOS/source/modules/LM_robustness.py +137 -0
  95. micrOS/source/{LM_rp2w.py → modules/LM_rp2w.py} +3 -0
  96. micrOS/source/{LM_sdcard.py → modules/LM_sdcard.py} +3 -0
  97. micrOS/source/{LM_servo.py → modules/LM_servo.py} +4 -4
  98. micrOS/source/modules/LM_sound_event.py +751 -0
  99. micrOS/source/{LM_stepper.py → modules/LM_stepper.py} +8 -8
  100. micrOS/source/{LM_switch.py → modules/LM_switch.py} +21 -18
  101. micrOS/source/{LM_system.py → modules/LM_system.py} +96 -59
  102. micrOS/source/modules/LM_tcs3472.py +187 -0
  103. micrOS/source/modules/LM_telegram.py +388 -0
  104. micrOS/source/modules/LM_trackball.py +287 -0
  105. micrOS/source/modules/LM_veml7700.py +159 -0
  106. micrOS/source/modules/LM_web.py +38 -0
  107. micrOS/source/urequests.py +204 -91
  108. {toolkit/workspace/precompiled → micrOS/source/web}/dashboard.html +9 -4
  109. micrOS/source/web/editor.js +440 -0
  110. micrOS/source/web/filesui.html +178 -0
  111. micrOS/source/web/filesui.js +338 -0
  112. micrOS/source/{index.html → web/index.html} +44 -2
  113. micrOS/source/web/uapi.js +103 -0
  114. micrOS/source/web/udashboard.js +129 -0
  115. micrOS/source/web/ustyle.css +55 -0
  116. micrOS/source/web/uwidgets.js +172 -0
  117. micrOS/source/web/uwidgets_pro.js +99 -0
  118. micrOS/utests/__init__.py +0 -0
  119. micrOS/utests/test_scheduler.py +435 -0
  120. {micrOSDevToolKit-2.1.5.data → microsdevtoolkit-2.26.1.data}/scripts/devToolKit.py +47 -4
  121. {micrOSDevToolKit-2.1.5.dist-info → microsdevtoolkit-2.26.1.dist-info}/METADATA +392 -279
  122. microsdevtoolkit-2.26.1.dist-info/RECORD +396 -0
  123. {micrOSDevToolKit-2.1.5.dist-info → microsdevtoolkit-2.26.1.dist-info}/WHEEL +1 -1
  124. toolkit/DevEnvCompile.py +63 -33
  125. toolkit/DevEnvOTA.py +72 -22
  126. toolkit/DevEnvUSB.py +147 -77
  127. toolkit/Gateway.py +9 -9
  128. toolkit/LM_to_compile.dat +12 -4
  129. toolkit/MicrOSDevEnv.py +129 -51
  130. toolkit/WebRepl.py +73 -0
  131. toolkit/dashboard_apps/BackupRestore.py +171 -0
  132. toolkit/dashboard_apps/CCTDemo.py +12 -17
  133. toolkit/dashboard_apps/CCTTest.py +20 -24
  134. toolkit/dashboard_apps/CamStream.py +2 -6
  135. toolkit/dashboard_apps/CatGame.py +14 -16
  136. toolkit/dashboard_apps/Dimmer.py +11 -21
  137. toolkit/dashboard_apps/GetVersion.py +11 -19
  138. toolkit/dashboard_apps/MicrophoneTest.py +2 -7
  139. toolkit/dashboard_apps/NeoEffectsDemo.py +22 -35
  140. toolkit/dashboard_apps/NeopixelTest.py +20 -25
  141. toolkit/dashboard_apps/PresenceTest.py +2 -8
  142. toolkit/dashboard_apps/QMI8685_GYRO.py +68 -0
  143. toolkit/dashboard_apps/RGBTest.py +20 -24
  144. toolkit/dashboard_apps/RoboArm.py +24 -32
  145. toolkit/dashboard_apps/SED_test.py +10 -14
  146. toolkit/dashboard_apps/SensorsTest.py +61 -0
  147. toolkit/dashboard_apps/SystemTest.py +219 -117
  148. toolkit/dashboard_apps/Template_app.py +12 -19
  149. toolkit/dashboard_apps/_app_base.py +34 -0
  150. toolkit/dashboard_apps/_gyro_visualizer.py +78 -0
  151. toolkit/dashboard_apps/uLightDemo.py +15 -24
  152. toolkit/index.html +6 -5
  153. toolkit/lib/LocalMachine.py +6 -1
  154. toolkit/lib/MicrosFiles.py +46 -0
  155. toolkit/lib/Repository.py +64 -0
  156. toolkit/lib/TerminalColors.py +4 -0
  157. toolkit/lib/macroScript.py +371 -0
  158. toolkit/lib/micrOSClient.py +124 -51
  159. toolkit/lib/micrOSClientHistory.py +156 -0
  160. toolkit/lib/pip_package_installer.py +31 -4
  161. toolkit/micrOSdashboard.py +16 -21
  162. toolkit/micrOSlint.py +28 -10
  163. toolkit/simulator_lib/.DS_Store +0 -0
  164. micrOS/source/IO_esp32.py → toolkit/simulator_lib/IO_darwin.py +3 -0
  165. toolkit/simulator_lib/__pycache__/IO_darwin.cpython-312.pyc +0 -0
  166. toolkit/simulator_lib/__pycache__/aioespnow.cpython-312.pyc +0 -0
  167. toolkit/simulator_lib/__pycache__/camera.cpython-312.pyc +0 -0
  168. toolkit/simulator_lib/__pycache__/framebuf.cpython-312.pyc +0 -0
  169. toolkit/simulator_lib/__pycache__/machine.cpython-312.pyc +0 -0
  170. toolkit/simulator_lib/__pycache__/micropython.cpython-312.pyc +0 -0
  171. toolkit/simulator_lib/__pycache__/mip.cpython-312.pyc +0 -0
  172. toolkit/simulator_lib/__pycache__/neopixel.cpython-312.pyc +0 -0
  173. toolkit/simulator_lib/__pycache__/network.cpython-312.pyc +0 -0
  174. toolkit/simulator_lib/__pycache__/sim_common.cpython-312.pyc +0 -0
  175. toolkit/simulator_lib/__pycache__/simgc.cpython-312.pyc +0 -0
  176. toolkit/simulator_lib/__pycache__/simulator.cpython-312.pyc +0 -0
  177. toolkit/simulator_lib/__pycache__/uasyncio.cpython-312.pyc +0 -0
  178. toolkit/simulator_lib/__pycache__/uos.cpython-312.pyc +0 -0
  179. toolkit/simulator_lib/__pycache__/urandom.cpython-312.pyc +0 -0
  180. toolkit/simulator_lib/__pycache__/usocket.cpython-312.pyc +0 -0
  181. toolkit/simulator_lib/__pycache__/ussl.cpython-312.pyc +0 -0
  182. toolkit/simulator_lib/aioespnow.py +28 -0
  183. toolkit/simulator_lib/camera.py +84 -0
  184. toolkit/simulator_lib/dht.py +1 -1
  185. toolkit/simulator_lib/framebuf.py +49 -1
  186. toolkit/simulator_lib/machine.py +32 -2
  187. toolkit/simulator_lib/micropython.py +3 -3
  188. toolkit/simulator_lib/mip.py +165 -0
  189. toolkit/simulator_lib/neopixel.py +3 -2
  190. toolkit/simulator_lib/network.py +2 -1
  191. toolkit/simulator_lib/node_config.json +2 -3
  192. toolkit/simulator_lib/ntptime.py +1 -1
  193. toolkit/simulator_lib/{sim_console.py → sim_common.py} +2 -3
  194. toolkit/simulator_lib/simgc.py +6 -2
  195. toolkit/simulator_lib/simulator.py +138 -46
  196. toolkit/simulator_lib/uasyncio.py +34 -3
  197. toolkit/simulator_lib/uos.py +147 -0
  198. toolkit/simulator_lib/urandom.py +4 -0
  199. toolkit/simulator_lib/usocket.py +5 -1
  200. toolkit/simulator_lib/view01.jpg +0 -0
  201. toolkit/simulator_lib/view02.jpg +0 -0
  202. toolkit/socketClient.py +43 -23
  203. toolkit/user_data/webhooks/generic.py +1 -1
  204. toolkit/user_data/webhooks/macro.py +44 -0
  205. toolkit/user_data/webhooks/template.macro +20 -0
  206. toolkit/user_data/webhooks/template.py +1 -1
  207. toolkit/workspace/precompiled/Auth.mpy +0 -0
  208. toolkit/workspace/precompiled/Common.mpy +0 -0
  209. toolkit/workspace/precompiled/Config.mpy +0 -0
  210. toolkit/workspace/precompiled/Debug.mpy +0 -0
  211. toolkit/workspace/precompiled/Espnow.mpy +0 -0
  212. toolkit/workspace/precompiled/Files.mpy +0 -0
  213. toolkit/workspace/precompiled/Hooks.mpy +0 -0
  214. toolkit/workspace/precompiled/InterConnect.mpy +0 -0
  215. toolkit/workspace/precompiled/Interrupts.mpy +0 -0
  216. toolkit/workspace/precompiled/Logger.mpy +0 -0
  217. toolkit/workspace/precompiled/Network.mpy +0 -0
  218. toolkit/workspace/precompiled/Notify.mpy +0 -0
  219. toolkit/workspace/precompiled/Pacman.mpy +0 -0
  220. toolkit/workspace/precompiled/Scheduler.mpy +0 -0
  221. toolkit/workspace/precompiled/Server.mpy +0 -0
  222. toolkit/workspace/precompiled/Shell.mpy +0 -0
  223. toolkit/workspace/precompiled/Tasks.mpy +0 -0
  224. toolkit/workspace/precompiled/Time.mpy +0 -0
  225. toolkit/workspace/precompiled/Types.mpy +0 -0
  226. toolkit/workspace/precompiled/Web.mpy +0 -0
  227. toolkit/workspace/precompiled/_mpy.version +1 -1
  228. toolkit/workspace/precompiled/config/_git.keep +0 -0
  229. toolkit/workspace/precompiled/helpers.mpy +0 -0
  230. toolkit/workspace/precompiled/micrOS.mpy +0 -0
  231. toolkit/workspace/precompiled/micrOSloader.mpy +0 -0
  232. toolkit/workspace/precompiled/microIO.mpy +0 -0
  233. toolkit/workspace/precompiled/modules/IO_esp32.mpy +0 -0
  234. toolkit/workspace/precompiled/modules/IO_esp32c3.mpy +0 -0
  235. toolkit/workspace/precompiled/modules/IO_esp32c6.mpy +0 -0
  236. toolkit/workspace/precompiled/modules/IO_esp32s2.mpy +0 -0
  237. toolkit/workspace/precompiled/modules/IO_esp32s3.mpy +0 -0
  238. toolkit/workspace/precompiled/modules/IO_m5stamp.mpy +0 -0
  239. toolkit/workspace/precompiled/modules/IO_qtpy.mpy +0 -0
  240. toolkit/workspace/precompiled/modules/IO_rp2.mpy +0 -0
  241. toolkit/workspace/precompiled/modules/IO_tinypico.mpy +0 -0
  242. toolkit/workspace/precompiled/modules/LM_L298N.mpy +0 -0
  243. {micrOS/source → toolkit/workspace/precompiled/modules}/LM_L9110_DCmotor.py +4 -4
  244. toolkit/workspace/precompiled/modules/LM_OV2640.mpy +0 -0
  245. toolkit/workspace/precompiled/{LM_VL53L0X.py → modules/LM_VL53L0X.py} +5 -5
  246. toolkit/workspace/precompiled/modules/LM_aht10.mpy +0 -0
  247. toolkit/workspace/precompiled/modules/LM_bme280.mpy +0 -0
  248. toolkit/workspace/precompiled/{LM_buzzer.mpy → modules/LM_buzzer.mpy} +0 -0
  249. toolkit/workspace/precompiled/modules/LM_cct.mpy +0 -0
  250. toolkit/workspace/precompiled/modules/LM_cluster.mpy +0 -0
  251. toolkit/workspace/precompiled/modules/LM_co2.mpy +0 -0
  252. toolkit/workspace/precompiled/modules/LM_dht11.mpy +0 -0
  253. toolkit/workspace/precompiled/modules/LM_dht22.mpy +0 -0
  254. toolkit/workspace/precompiled/modules/LM_dimmer.mpy +0 -0
  255. toolkit/workspace/precompiled/modules/LM_distance.mpy +0 -0
  256. toolkit/workspace/precompiled/modules/LM_ds18.mpy +0 -0
  257. toolkit/workspace/precompiled/{LM_esp32.py → modules/LM_esp32.py} +16 -4
  258. toolkit/workspace/precompiled/modules/LM_espnow.py +53 -0
  259. toolkit/workspace/precompiled/modules/LM_fileserver.mpy +0 -0
  260. toolkit/workspace/precompiled/{LM_gameOfLife.mpy → modules/LM_gameOfLife.mpy} +0 -0
  261. toolkit/workspace/precompiled/modules/LM_genIO.mpy +0 -0
  262. toolkit/workspace/precompiled/modules/LM_haptic.mpy +0 -0
  263. toolkit/workspace/precompiled/modules/LM_i2c.py +61 -0
  264. toolkit/workspace/precompiled/modules/LM_i2s_mic.mpy +0 -0
  265. toolkit/workspace/precompiled/{LM_ld2410.mpy → modules/LM_ld2410.mpy} +0 -0
  266. toolkit/workspace/precompiled/modules/LM_light_sensor.mpy +0 -0
  267. toolkit/workspace/precompiled/modules/LM_mh_z19c.py +198 -0
  268. toolkit/workspace/precompiled/modules/LM_neoeffects.mpy +0 -0
  269. toolkit/workspace/precompiled/modules/LM_neopixel.mpy +0 -0
  270. toolkit/workspace/precompiled/modules/LM_oled.mpy +0 -0
  271. toolkit/workspace/precompiled/modules/LM_oled_sh1106.mpy +0 -0
  272. toolkit/workspace/precompiled/modules/LM_oled_ui.mpy +0 -0
  273. toolkit/workspace/precompiled/modules/LM_pacman.mpy +0 -0
  274. toolkit/workspace/precompiled/modules/LM_presence.mpy +0 -0
  275. toolkit/workspace/precompiled/modules/LM_qmi8658.py +204 -0
  276. toolkit/workspace/precompiled/{LM_rencoder.py → modules/LM_rencoder.py} +40 -11
  277. toolkit/workspace/precompiled/modules/LM_rest.mpy +0 -0
  278. toolkit/workspace/precompiled/modules/LM_rgb.mpy +0 -0
  279. toolkit/workspace/precompiled/{LM_rgbcct.mpy → modules/LM_rgbcct.mpy} +0 -0
  280. toolkit/workspace/precompiled/modules/LM_roboarm.mpy +0 -0
  281. toolkit/workspace/precompiled/modules/LM_robustness.py +137 -0
  282. toolkit/workspace/precompiled/{LM_rp2w.py → modules/LM_rp2w.py} +3 -0
  283. toolkit/workspace/precompiled/{LM_sdcard.py → modules/LM_sdcard.py} +3 -0
  284. toolkit/workspace/precompiled/{LM_servo.mpy → modules/LM_servo.mpy} +0 -0
  285. toolkit/workspace/precompiled/modules/LM_sound_event.mpy +0 -0
  286. toolkit/workspace/precompiled/{LM_stepper.mpy → modules/LM_stepper.mpy} +0 -0
  287. toolkit/workspace/precompiled/modules/LM_switch.mpy +0 -0
  288. toolkit/workspace/precompiled/modules/LM_system.mpy +0 -0
  289. toolkit/workspace/precompiled/modules/LM_tcs3472.py +187 -0
  290. toolkit/workspace/precompiled/modules/LM_telegram.mpy +0 -0
  291. toolkit/workspace/precompiled/{LM_tinyrgb.mpy → modules/LM_tinyrgb.mpy} +0 -0
  292. toolkit/workspace/precompiled/modules/LM_trackball.mpy +0 -0
  293. toolkit/workspace/precompiled/modules/LM_veml7700.mpy +0 -0
  294. toolkit/workspace/precompiled/modules/LM_web.mpy +0 -0
  295. toolkit/workspace/precompiled/urequests.mpy +0 -0
  296. {micrOS/source → toolkit/workspace/precompiled/web}/dashboard.html +9 -4
  297. toolkit/workspace/precompiled/web/editor.js +440 -0
  298. toolkit/workspace/precompiled/web/filesui.html +178 -0
  299. toolkit/workspace/precompiled/web/filesui.js +338 -0
  300. toolkit/workspace/precompiled/{index.html → web/index.html} +44 -2
  301. toolkit/workspace/precompiled/web/uapi.js +103 -0
  302. toolkit/workspace/precompiled/web/udashboard.js +129 -0
  303. toolkit/workspace/precompiled/web/ustyle.css +55 -0
  304. toolkit/workspace/precompiled/web/uwidgets.js +172 -0
  305. toolkit/workspace/precompiled/web/uwidgets_pro.js +99 -0
  306. env/driver_cp210x/CH34XSER_MAC/CH34X_DRV_INSTALL_INSTRUCTIONS.pdf +0 -0
  307. env/driver_cp210x/CH34XSER_MAC/CH34xVCPDriver.pkg +0 -0
  308. micrOS/micropython/esp32-20231005-v1.21.0.bin +0 -0
  309. micrOS/micropython/esp32c3-GENERIC-20240105-v1.22.1.bin +0 -0
  310. micrOS/micropython/esp32c3-GENERIC-20240222-v1.22.2.bin +0 -0
  311. micrOS/micropython/esp32s2-GENERIC-20240105-v1.22.1.bin +0 -0
  312. micrOS/micropython/esp32s2-LOLIN_MINI-20220618-v1.19.1.bin +0 -0
  313. micrOS/micropython/esp32s3-GENERIC-20240105-v1.22.1.bin +0 -0
  314. micrOS/micropython/esp32s3_spiram_oct-20231005-v1.21.0.bin +0 -0
  315. micrOS/micropython/rpi-pico-w-20231005-v1.21.0.uf2 +0 -0
  316. micrOS/micropython/tinypico-20231005-v1.21.0.bin +0 -0
  317. micrOS/micropython/tinypico-usbc-UM-20240105-v1.22.1.bin +0 -0
  318. micrOS/source/LM_L298N_DCmotor.py +0 -86
  319. micrOS/source/LM_catgame.py +0 -74
  320. micrOS/source/LM_dashboard_be.py +0 -37
  321. micrOS/source/LM_demo.py +0 -85
  322. micrOS/source/LM_distance.py +0 -88
  323. micrOS/source/LM_i2c.py +0 -44
  324. micrOS/source/LM_intercon.py +0 -57
  325. micrOS/source/LM_keychain.py +0 -318
  326. micrOS/source/LM_lmpacman.py +0 -126
  327. micrOS/source/LM_neoeffects.py +0 -327
  328. micrOS/source/LM_pet_feeder.py +0 -76
  329. micrOS/source/LM_ph_sensor.py +0 -51
  330. micrOS/source/LM_rest.py +0 -40
  331. micrOS/source/LM_robustness.py +0 -73
  332. micrOS/source/LM_telegram.py +0 -96
  333. micrOS/source/reset.py +0 -11
  334. micrOS/source/uapi.js +0 -76
  335. micrOS/source/udashboard.js +0 -137
  336. micrOS/source/ustyle.css +0 -28
  337. micrOS/source/uwidgets.js +0 -179
  338. micrOSDevToolKit-2.1.5.dist-info/RECORD +0 -337
  339. toolkit/dashboard_apps/AirQualityBME280.py +0 -36
  340. toolkit/dashboard_apps/AirQualityDHT22_CO2.py +0 -36
  341. toolkit/lib/file_extensions.py +0 -16
  342. toolkit/simulator_lib/__pycache__/LP_darwin.cpython-312.pyc +0 -0
  343. toolkit/simulator_lib/__pycache__/LP_darwin.cpython-38.pyc +0 -0
  344. toolkit/simulator_lib/__pycache__/LP_darwin.cpython-39.pyc +0 -0
  345. toolkit/simulator_lib/__pycache__/sim_console.cpython-312.pyc +0 -0
  346. toolkit/simulator_lib/__pycache__/sim_console.cpython-38.pyc +0 -0
  347. toolkit/simulator_lib/__pycache__/sim_console.cpython-39.pyc +0 -0
  348. toolkit/workspace/precompiled/IO_esp32.mpy +0 -0
  349. toolkit/workspace/precompiled/IO_esp32c3.mpy +0 -0
  350. toolkit/workspace/precompiled/IO_esp32s2.mpy +0 -0
  351. toolkit/workspace/precompiled/IO_esp32s3.mpy +0 -0
  352. toolkit/workspace/precompiled/IO_qtpy.mpy +0 -0
  353. toolkit/workspace/precompiled/IO_rp2.mpy +0 -0
  354. toolkit/workspace/precompiled/IO_tinypico.mpy +0 -0
  355. toolkit/workspace/precompiled/LM_L298N_DCmotor.mpy +0 -0
  356. toolkit/workspace/precompiled/LM_OV2640.mpy +0 -0
  357. toolkit/workspace/precompiled/LM_aht10.mpy +0 -0
  358. toolkit/workspace/precompiled/LM_bme280.mpy +0 -0
  359. toolkit/workspace/precompiled/LM_catgame.py +0 -74
  360. toolkit/workspace/precompiled/LM_cct.mpy +0 -0
  361. toolkit/workspace/precompiled/LM_co2.mpy +0 -0
  362. toolkit/workspace/precompiled/LM_dashboard_be.py +0 -37
  363. toolkit/workspace/precompiled/LM_demo.py +0 -85
  364. toolkit/workspace/precompiled/LM_dht11.mpy +0 -0
  365. toolkit/workspace/precompiled/LM_dht22.mpy +0 -0
  366. toolkit/workspace/precompiled/LM_dimmer.mpy +0 -0
  367. toolkit/workspace/precompiled/LM_distance.py +0 -88
  368. toolkit/workspace/precompiled/LM_ds18.mpy +0 -0
  369. toolkit/workspace/precompiled/LM_genIO.mpy +0 -0
  370. toolkit/workspace/precompiled/LM_i2c.py +0 -44
  371. toolkit/workspace/precompiled/LM_i2s_mic.mpy +0 -0
  372. toolkit/workspace/precompiled/LM_intercon.mpy +0 -0
  373. toolkit/workspace/precompiled/LM_keychain.mpy +0 -0
  374. toolkit/workspace/precompiled/LM_light_sensor.mpy +0 -0
  375. toolkit/workspace/precompiled/LM_lmpacman.mpy +0 -0
  376. toolkit/workspace/precompiled/LM_neoeffects.mpy +0 -0
  377. toolkit/workspace/precompiled/LM_neopixel.mpy +0 -0
  378. toolkit/workspace/precompiled/LM_oled.mpy +0 -0
  379. toolkit/workspace/precompiled/LM_oled_sh1106.mpy +0 -0
  380. toolkit/workspace/precompiled/LM_oled_ui.mpy +0 -0
  381. toolkit/workspace/precompiled/LM_pet_feeder.py +0 -76
  382. toolkit/workspace/precompiled/LM_ph_sensor.py +0 -51
  383. toolkit/workspace/precompiled/LM_presence.mpy +0 -0
  384. toolkit/workspace/precompiled/LM_rest.mpy +0 -0
  385. toolkit/workspace/precompiled/LM_rgb.mpy +0 -0
  386. toolkit/workspace/precompiled/LM_roboarm.mpy +0 -0
  387. toolkit/workspace/precompiled/LM_robustness.py +0 -73
  388. toolkit/workspace/precompiled/LM_switch.mpy +0 -0
  389. toolkit/workspace/precompiled/LM_system.mpy +0 -0
  390. toolkit/workspace/precompiled/LM_telegram.mpy +0 -0
  391. toolkit/workspace/precompiled/reset.mpy +0 -0
  392. toolkit/workspace/precompiled/uapi.js +0 -76
  393. toolkit/workspace/precompiled/udashboard.js +0 -137
  394. toolkit/workspace/precompiled/ustyle.css +0 -28
  395. toolkit/workspace/precompiled/uwidgets.js +0 -179
  396. /toolkit/user_data/node_config_archive/.include → /micrOS/source/config/_git.keep +0 -0
  397. /micrOS/source/{IO_rp2.py → modules/IO_rp2.py} +0 -0
  398. /micrOS/source/{LM_tinyrgb.py → modules/LM_tinyrgb.py} +0 -0
  399. {micrOSDevToolKit-2.1.5.dist-info → microsdevtoolkit-2.26.1.dist-info/licenses}/LICENSE +0 -0
  400. {micrOSDevToolKit-2.1.5.dist-info → microsdevtoolkit-2.26.1.dist-info}/top_level.txt +0 -0
micrOS/source/Common.py CHANGED
@@ -1,32 +1,225 @@
1
1
  """
2
- micrOS Load Module programming API-s
2
+ micrOS Load Module programming Official API-s
3
3
  Designed by Marcell Ban aka BxNxM
4
4
  """
5
-
6
- from Server import SocketServer
5
+ from Server import Server, WebCli
6
+ from Debug import syslog as debug_syslog, console_write
7
+ from Logger import logger, log_get
8
+ from Files import OSPath, path_join
9
+ from microIO import resolve_pin
10
+ from Tasks import TaskBase, Manager, lm_exec, lm_is_loaded
7
11
  from machine import Pin, ADC
8
- from microIO import physical_pin
9
- from Debug import logger, log_get, errlog_add
10
- from Server import WebCli
11
- try:
12
- from Tasks import TaskBase, Manager
13
- except Exception as e:
14
- print(f"Import ERROR, TaskManager: {e}")
15
- TaskBase, Manager = None, None
16
- TELEGRAM = None
12
+ from Notify import Notify
13
+
14
+
15
+ #####################################################################################
16
+ # SYSTEM #
17
+ #####################################################################################
18
+ def micro_task(tag:str, task=None, _wrap=False):
19
+ """
20
+ [LM] Async task manager.
21
+ Modes:
22
+ A) GET:
23
+ micro_task("tag") -> existing task object or None
24
+ B) CREATE:
25
+ micro_task("tag", task=...) -> True | None | False
26
+ Creates a new async task with the given tag if not already running.
27
+ C) CREATE AS DECORATOR (shortcut):
28
+ @micro_task("main", _wrap=True)
29
+ async def mytask(tag, ...): ...
30
+ # Calling mytask(...) will create/start a new task under "main._mytask"
31
+
32
+ :param tag: Task tag string
33
+ :param task: Coroutine (or list of command arguments) to contract a task with
34
+ the given async task callback
35
+ :param _wrap: When True, return a decorator factory (for use as @micro_task(...))
36
+ :return: Task object (GET), bool|None|False (CREATE), or decorator (DECORATOR)
37
+ """
38
+ # --- CREATE (original) ---
39
+ if task is not None:
40
+ return Manager().create_task(callback=task, tag=tag)
41
+
42
+ # --- CREATE WITH DECORATOR FACTORY (simplified) ---
43
+ if _wrap:
44
+ def _decorator(async_fn):
45
+ task_tag = f"{tag}._{async_fn.__name__}"
46
+ _launcher = (lambda *args, **kwargs: Manager().create_task(callback=async_fn(task_tag, *args, **kwargs),
47
+ tag=task_tag))
48
+ return _launcher
49
+ return _decorator
50
+
51
+ # --- GET (_wrap=False): return task object or None if not existing ---
52
+ return TaskBase.TASKS.get(tag, None)
53
+
54
+
55
+ def manage_task(tag:str, operation:str):
56
+ """
57
+ [LM] Async task management
58
+ :param tag: task tag
59
+ :param operation: kill / show / isbusy
60
+ """
61
+ if operation == "show":
62
+ return str(Manager().show(tag=tag))
63
+ if operation == "kill":
64
+ return Manager().kill(tag=tag)
65
+ if operation == "isbusy":
66
+ return TaskBase.is_busy(tag=tag)
67
+ raise Exception(f"Invalid operation: {operation}")
68
+
69
+
70
+ def exec_cmd(cmd:list, jsonify:bool=None, secure=False):
71
+ """
72
+ [LM] Single (sync) LM execution
73
+ :param cmd: command string list, ex.: ['system', 'clock']
74
+ :param jsonify: request json output
75
+ :param secure: check LM is loaded, if NOT skip execution 'NotAllowed'
76
+ return state, output
77
+ """
78
+ if secure and not lm_is_loaded(cmd[0]):
79
+ return False, f"NotAllowed {cmd[0]}"
80
+ return lm_exec(cmd, jsonify=jsonify)
81
+
82
+
83
+ def notify(*args, **kwargs) -> bool:
84
+ """
85
+ [LM] micrOS common notification handler (Telegram, etc.)
86
+ text (0): notification text / None (return notification state)
87
+ :param channels (optional): select communication interface(s) by class name or an iterable of these.
88
+ If omitted or empty, sends over all available channels.
89
+ Examples (optional parameters):
90
+ Telegram params:
91
+ reply_to: message id to reply to (optional) - default: None
92
+ chat_id: chat identifier - default: None -> auto resolve in child class
93
+ MQTTClient params:
94
+ topic: mqtt topic to send the message - default: None -> auto resolve in child class
95
+ return: verdict: True/False
96
+ """
97
+ # (1) Return notification state (if no text input given)
98
+ if kwargs.get("text", args[0] if args else None) is None:
99
+ return Notify.GLOBAL_NOTIFY
100
+ # (2) Send notification
101
+ try:
102
+ out = Notify.notify(*args, **kwargs)
103
+ except Exception as e:
104
+ debug_syslog(f"[ERR] Notify: {e}")
105
+ out = str(e)
106
+ if out is not None and (out.startswith('Sent') or out.endswith('disabled')):
107
+ return True
108
+ return False
109
+
110
+
111
+ def web_endpoint(endpoint, function, method='GET') -> bool:
112
+ """
113
+ [LM] Add test endpoint <localhost.local>/endpoint from Load Modules
114
+ :param endpoint: simple string, name of the endpoint
115
+ :param function:
116
+ [1] Normal function return tuple (html_type, data):
117
+ image/jpeg | text/html | text/plain, <data>
118
+ <data>: binary | string
119
+ [2] Stream function return tuple (multipart_type, data):
120
+ multipart/x-mixed-replace | multipart/form-data, <data>
121
+ <data>: {'callback':<func>, 'content-type': image/jpeg | audio/l16;*}
122
+ [3] String as file reference from /web
123
+ Example: 'filesui.html'
124
+ :param method: HTTP method name
125
+ """
126
+ WebCli.register(endpoint=endpoint, callback=function, method=method)
127
+ return True
128
+
129
+
130
+ def web_mounts(*args, **kwargs):
131
+ """
132
+ Extend web engine shared root path list
133
+ :param modules: add /modules to web shared path
134
+ :param data: add /data to web shared path
135
+ """
136
+ try:
137
+ return WebCli.web_mounts(*args, **kwargs)
138
+ except Exception as e:
139
+ syslog(f"[ERR] web_mounts error: {e}")
140
+ return {}
17
141
 
18
142
 
19
143
  def socket_stream(func):
20
144
  """
21
- [LM] Socket message streamer - adds msgobj to the decorated function arg list.
145
+ [LM] Decorator for Socket message stream - adds msgobj to the decorated function arg list.
22
146
  Use msgobj as print function: msgobj("hello")
23
- (SocketServer singleton class - reply all bug/feature)
147
+ (Server singleton class - reply all bug/feature)
24
148
  """
25
149
  def wrapper(*args, **kwargs):
26
- return func(*args, **kwargs, msgobj=SocketServer.reply_all)
150
+ return func(*args, **kwargs, msgobj=Server.reply_all)
27
151
  return wrapper
28
152
 
29
153
 
154
+ @socket_stream
155
+ def data_logger(f_name, data=None, limit=12, msgobj=None):
156
+ """
157
+ [LM] micrOS Common Data logger solution
158
+ - if data None => read mode
159
+ - if data value => write mode
160
+ :param f_name: log name (without extension, automatic: .dat, default folder: /data)
161
+ :param data: data to append
162
+ :param limit: line limit (max.: 12 with short lines: limited disk speed!)
163
+ :param msgobj: socket stream object (set automatically!)
164
+ """
165
+ f_name = f_name if f_name.endswith('.dat') else f'{f_name}.dat'
166
+ # GET LOGGED DATA
167
+ if data is None:
168
+ # return log as msg stream
169
+ log_get(f_name, msgobj=msgobj)
170
+ return True
171
+ # ADD DATA TO LOG
172
+ return logger(data, f_name, limit)
173
+
174
+
175
+ def syslog(msg):
176
+ """ Wrapper of debug_syslog """
177
+ return debug_syslog(f"{msg}")
178
+
179
+
180
+ def console(msg):
181
+ """ Wrapper of console_write """
182
+ return console_write(msg)
183
+
184
+ #####################################################################################
185
+ # SYSTEM DIRECTORY ACCESS #
186
+ #####################################################################################
187
+
188
+ def data_dir(f_name=None):
189
+ """
190
+ Access for data dir path
191
+ :param f_name: if given, returns full path, otherwise returns data dir root path
192
+ """
193
+ root_path = OSPath.DATA
194
+ if f_name is None:
195
+ return root_path
196
+ return path_join(root_path, f_name)
197
+
198
+ def web_dir(f_name=None):
199
+ """
200
+ Access for web dir path
201
+ :param f_name: if given, returns full path, otherwise returns web dir root path
202
+ """
203
+ root_path = OSPath.WEB
204
+ if f_name is None:
205
+ return root_path
206
+ return path_join(root_path, f_name)
207
+
208
+ def conf_dir(f_name):
209
+ """
210
+ Create application configs under config directory
211
+ - node_config.json and config dir read restriction/protection (basic)
212
+ :param f_name: creates custom config path with f_name
213
+ """
214
+ root_path = OSPath.CONFIG
215
+ if f_name.strip().lstrip("/") == "node_config.json":
216
+ raise Exception("Protected resource: config!")
217
+ return path_join(root_path, f_name)
218
+
219
+ #####################################################################################
220
+ # CHANNEL: SIGNAL GENERATORS #
221
+ #####################################################################################
222
+
30
223
  def transition(from_val, to_val, step_ms, interval_sec):
31
224
  """
32
225
  [LM] Single Generator for color/value transition:
@@ -49,20 +242,23 @@ def transition_gen(*args, interval_sec=1.0):
49
242
  """
50
243
  [LM] Multiple Generator for color/value transitions:
51
244
  - calculate minimum step count -> step_ms
52
- - autofill and use use transition(from_val, to_val, step_ms, interval_sec)
245
+ - autofill and use transition(from_val, to_val, step_ms, interval_sec)
53
246
  :param args: ch1_from, ch1_to, ch2_from, ch2_to, etc...
54
247
  :param interval_sec: interval in sec to calculate optimal fade/transition effect
55
248
  return: gen, step_ms OR gen list, step_ms
56
249
  """
57
250
  step_ms_min = 5 # min calculated step is 5 ms - good enough
58
- delta = max([abs(args[ch_from_i] - args[ch_from_i+1]) for ch_from_i in range(0, len(args)-1, 2)])
251
+ delta = max((abs(args[ch_from_i] - args[ch_from_i+1]) for ch_from_i in range(0, len(args)-1, 2)))
59
252
  step_ms = 0 if delta == 0 else int(interval_sec*1000 / delta)
60
253
  step_ms = step_ms_min if step_ms < step_ms_min else step_ms
61
- transitions = list([transition(args[ch_from_i], args[ch_from_i+1], step_ms, interval_sec) for ch_from_i in range(0, len(args)-1, 2)])
254
+ transitions = list((transition(args[ch_from_i], args[ch_from_i+1], step_ms, interval_sec) for ch_from_i in range(0, len(args)-1, 2)))
62
255
  if len(transitions) == 1:
63
256
  return transitions[0], step_ms
64
257
  return list(transitions), step_ms
65
258
 
259
+ #####################################################################################
260
+ # EXTRAS #
261
+ #####################################################################################
66
262
 
67
263
  class SmartADC:
68
264
  """
@@ -80,7 +276,7 @@ class SmartADC:
80
276
  self.adp_prop = (65535, 2450) # raw value, 2450mV (so 2,45V)
81
277
  self.adc = None
82
278
  if not isinstance(pin, int):
83
- pin = physical_pin(pin)
279
+ pin = resolve_pin(pin)
84
280
  self.adc = ADC(Pin(pin))
85
281
  self.adc.atten(ADC.ATTN_11DB) # 2450mV measure range
86
282
 
@@ -91,99 +287,177 @@ class SmartADC:
91
287
  return {'raw': raw, 'percent': round(percent*100, 1), 'volt': volt}
92
288
 
93
289
  @staticmethod
94
- def get_singleton(pin):
290
+ def get_instance(pin):
95
291
  if pin in SmartADC.OBJS.keys():
96
292
  return SmartADC.OBJS[pin]
97
293
  SmartADC.OBJS[pin] = SmartADC(pin)
98
294
  return SmartADC.OBJS[pin]
99
295
 
100
296
 
101
- def micro_task(tag, task=None):
102
- """
103
- [LM] Async task creation
104
- - Indirect interface
105
- tag:
106
- [1] tag=None: return task generator object
107
- [2] tag=taskID: return existing task object by tag
108
- task: coroutine to execute (built in overload protection and lcm)
109
- """
110
- # [0] Check dependencies
111
- if TaskBase is None or Manager is None:
112
- # RETURN: None - cannot utilize async task functionality
113
- return None
114
- if task is None:
115
- # [1] Task is None -> Get task mode by tag
116
- # RETURN task obj (access obj.out + obj.done (automatic - with keyword arg))
117
- async_task = TaskBase.TASKS.get(tag, None)
118
- return async_task
119
- if TaskBase.is_busy(tag):
120
- # [2] Shortcut: Check task state by tag
121
- # RETURN: None - if task is already running
122
- return None
123
- # [3] Create task (not running) + task coroutine was provided
124
- # RETURN task creation state - success (True) / fail (False)
125
- state = Manager().create_task(callback=task, tag=tag)
126
- return state
127
-
128
-
129
- @socket_stream
130
- def data_logger(f_name, data=None, limit=12, msgobj=None):
297
+ class AnimationPlayer:
131
298
  """
132
- [LM] micrOS Common Data logger solution
133
- - if data None => read mode
134
- - if data value => write mode
135
- :param f_name: log name (without extension, automatic: .dat)
136
- :param data: data to append
137
- :param limit: line limit (max.: 12 with short lines: limited disk speed!)
138
- :param msgobj: socket stream object (set automatically!)
299
+ Generic async animation (generator) player.
139
300
  """
140
- f_name = f_name if f_name.endswith('.dat') else f'{f_name}.dat'
141
- # GET LOGGED DATA
142
- if data is None:
143
- # return log as msg stream
144
- log_get(f_name, msgobj=msgobj)
145
- return True
146
- # ADD DATA TO LOG
147
- return logger(data, f_name, limit)
148
301
 
302
+ def __init__(self, animation:callable=None, tag:str=None, batch_draw:bool=False, batch_size:int=None, loop:bool=True):
303
+ """
304
+ Initialize the AnimationPlayer with an optional animation.
305
+ :param animation: Function to GENERATE animation data
306
+ :param tag: Optional task tag for micro_task management.
307
+ :param batch_draw: If True - draw in batches
308
+ :param batch_size: Number of pixels per batch when drawing
309
+ :param loop: If True - loop the animation (default)
310
+ """
311
+ self.animation:callable = None
312
+ self.batch_draw:bool = batch_draw
313
+ self.__max_batch_size:int = 256 # MAX BATCH SIZE - ASYNC PROTECTION
314
+ self.__batch_size:int = 8 # Default batch size: 8
315
+ self.__loop:bool = loop # Loop the animation (generator)
316
+ self._set_batch_size(batch_size) # Set batch size from parameter
317
+ self._player_speed_ms:int = 10 # Default speed in ms between frames
318
+ main_tag:str = tag if tag else "animation"
319
+ self._task_tag:str = f"{main_tag}.player"
320
+ if animation is not None and not self._set_animation(animation):
321
+ raise Exception("Invalid animation function provided.")
322
+ self.__running:bool = True
149
323
 
150
- def syslog(msg):
151
- """ Wrapper of errlog_add """
152
- errlog_add(msg)
324
+ def _set_animation(self, animation:callable) -> bool:
325
+ """
326
+ Setter to change/set current animation.
327
+ """
328
+ if callable(animation):
329
+ self.animation = animation
330
+ return True
331
+ return False
153
332
 
333
+ def _set_batch_size(self, batch_size:int) -> None:
334
+ """
335
+ Setter to change/set batch size.
336
+ - with max batch size check (due to async event loop feeding)
337
+ """
338
+ if batch_size is None:
339
+ return
340
+ self.__batch_size = max(0, min(batch_size, self.__max_batch_size))
154
341
 
155
- def notify(text):
156
- """
157
- micrOS common notification handler (Telegram)
158
- :param text: notification text
159
- return: verdict: True/False
160
- """
161
- global TELEGRAM
162
- if TELEGRAM is None:
163
- try:
164
- from Notify import Telegram
165
- TELEGRAM = Telegram
166
- except Exception as e:
167
- print(f"Import ERROR, Notify.Telegram: {e}")
168
- return False
169
- try:
170
- out = TELEGRAM().send_msg(text)
171
- except Exception as e:
172
- print(f"Notify ERROR: {e}")
173
- out = str(e)
174
- if out is not None and out == 'Sent':
175
- return True
176
- return False
342
+ async def _render(self, my_task):
343
+ # Cache methods for speed
344
+ clear = self.clear
345
+ update = self.update
346
+ draw = self.draw
347
+ # Cache the current animation for comparison
348
+ current_animation = self.animation
349
+ frame_counter = 0
350
+ # Clear the display before each frame
351
+ if not self.batch_draw:
352
+ clear()
353
+ for data in self.animation():
354
+ # Check if animation has changed under the loop
355
+ if not self.__running or self.animation != current_animation:
356
+ # Animation changed — break — clean and restart animation loop.
357
+ clear()
358
+ break
359
+ # Update data cache
360
+ update(*data)
361
+ if self.batch_draw:
362
+ # Batched draw mode
363
+ frame_counter += 1
364
+ if frame_counter >= self.__batch_size:
365
+ draw()
366
+ frame_counter = 0
367
+ await my_task.feed(sleep_ms=self._player_speed_ms)
368
+ else:
369
+ # Real-time draw mode
370
+ draw()
371
+ await my_task.feed(sleep_ms=self._player_speed_ms)
177
372
 
178
- def rest_endpoint(endpoint, function):
179
- """
180
- Add test endpoint <localhost.local>/endpoint from Load Modules
181
- Simple:
182
- image/jpeg | text/html | text/plain, <data>
183
- <data>: binary | string
184
- Stream:
185
- multipart/x-mixed-replace | multipart/form-data, <data>
186
- <data>: {'callback':<func>, 'content-type': image/jpeg | audio/l16;*}
187
- """
188
- WebCli.rest_setter(endpoint=endpoint, callback=function)
189
- return True
373
+ async def _player(self):
374
+ """
375
+ Async task to play the current animation.
376
+ """
377
+ with micro_task(tag=self._task_tag) as my_task:
378
+ while self.__running:
379
+ my_task.out = f"Play {self.animation.__name__} ({self._player_speed_ms}ms/frame)"
380
+ try:
381
+ await self._render(my_task)
382
+ except IndexError:
383
+ # Draw after generator exhausted and Restart animation if IndexError occurs
384
+ self.draw()
385
+ if not self.__loop:
386
+ break
387
+ await my_task.feed(sleep_ms=self._player_speed_ms)
388
+ my_task.out = "Restart animation"
389
+ except Exception as e:
390
+ my_task.out = f"Error: {e}"
391
+ break
392
+ my_task.out = f"Animation stopped...{my_task.out}"
393
+
394
+ def control(self, play_speed_ms:int, bt_draw:bool=None, bt_size:int=None, loop:bool=None):
395
+ """
396
+ Set/Get current play speed of the animation.
397
+ :param play_speed_ms: player loop speed in milliseconds.
398
+ :param bt_draw: batch drawing flag.
399
+ :param bt_size: batch drawing size.
400
+ :param loop: loop flag.
401
+ """
402
+ if isinstance(play_speed_ms, int):
403
+ self._player_speed_ms = max(0, min(10000, int(play_speed_ms)))
404
+ if isinstance(bt_draw, bool):
405
+ self.batch_draw = bt_draw
406
+ if isinstance(bt_size, int):
407
+ self._set_batch_size(bt_size)
408
+ if isinstance(loop, bool):
409
+ self.__loop = loop
410
+ return {"realtime": not self.batch_draw, "batched": self.batch_draw,
411
+ "size": self.__batch_size, "speed_ms": self._player_speed_ms,
412
+ "loop": self.__loop}
413
+
414
+
415
+ def play(self, animation=None, speed_ms=None, bt_draw=False, bt_size=None, loop=True):
416
+ """
417
+ Play animation via generator function.
418
+ :param animation: Animation generator function.
419
+ :param speed_ms: Speed of the animation in milliseconds. (min.: 3ms)
420
+ :param bt_draw: batch drawing flag.
421
+ :param bt_size: batch drawing size.
422
+ :param loop: Loop the animation.
423
+ :return: Player settings.
424
+ """
425
+
426
+ if animation is not None:
427
+ if not self._set_animation(animation):
428
+ return "Invalid animation"
429
+ if self.animation is None:
430
+ return "No animation to play"
431
+ # Handle player settings
432
+ settings = self.control(play_speed_ms=speed_ms, bt_draw=bt_draw, bt_size=bt_size, loop=loop)
433
+ # Ensure async loop set up correctly. (After stop operation, it is needed)
434
+ self.__running = True
435
+ # [!] ASYNC TASK CREATION
436
+ state:dict = micro_task(tag=self._task_tag, task=self._player())
437
+ settings["state"] = list(state.values())[0]
438
+ return settings
439
+
440
+ def stop(self):
441
+ """
442
+ Stop the animation.
443
+ """
444
+ self.__running = False
445
+ return "Stop animation player"
446
+
447
+ def update(self, *arg, **kwargs):
448
+ """
449
+ Child class must implement this method to handle drawing logic.
450
+ """
451
+ raise NotImplementedError("Child class must implement update method.")
452
+
453
+ def draw(self):
454
+ """
455
+ Draw the current frame.
456
+ """
457
+ raise NotImplementedError("Child class must implement draw method.")
458
+
459
+ def clear(self):
460
+ """
461
+ Clear the display.
462
+ """
463
+ raise NotImplementedError("Child class must implement clear method.")