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/Server.py CHANGED
@@ -13,21 +13,34 @@ Designed by Marcell Ban aka BxNxM GitHub
13
13
  import uasyncio as asyncio
14
14
  from utime import ticks_ms, ticks_diff
15
15
  from Config import cfgget
16
- from Debug import console_write, errlog_add
16
+ from Debug import console_write, syslog
17
17
  from Network import ifconfig
18
18
  from Tasks import Manager
19
19
  from Shell import Shell
20
20
  try:
21
- from gc import collect, mem_free
21
+ from gc import collect
22
22
  except:
23
23
  console_write("[SIMULATOR MODE GC IMPORT]")
24
- from simgc import collect, mem_free
24
+ from simgc import collect
25
25
 
26
26
  # Module load optimization, needed only for webui
27
27
  if cfgget('webui'):
28
- from json import dumps, loads
29
- from Tasks import lm_exec, NativeTask, lm_is_loaded
30
-
28
+ from Web import WebEngine
29
+ else:
30
+ # Create dummy web engine - Lazy loading
31
+ class WebEngine:
32
+ __slots__ = []
33
+ def __init__(self, *args, **kwargs):
34
+ pass
35
+ @staticmethod
36
+ def register(*args, **kwargs) -> None:
37
+ """Child class can implement"""
38
+ syslog(f"[WARN] webui disabled, skip register: {kwargs.get('endpoint')}")
39
+ @staticmethod
40
+ def web_mounts(*args, **kwargs) -> dict:
41
+ """Child class can implement"""
42
+ syslog(f"[WARN] webui disabled, skip web_mounts: {kwargs.get('endpoint')}")
43
+ return {}
31
44
 
32
45
  #########################################################
33
46
  # SOCKET SERVER-CLIENT HANDLER CLASSES #
@@ -59,19 +72,25 @@ class Client:
59
72
  console_write("|" + "-" * Client.INDENT + msg)
60
73
  Client.INDENT += 1 if Client.INDENT < 50 else 0 # Auto indent
61
74
 
62
- async def read(self):
75
+ async def read(self, decoding='utf8', timeout_seconds=0):
63
76
  """
64
77
  [Base] Implements client read function, reader size: 2048
65
- - set timeout counter
66
- - read input from client (run: return False)
67
- - connection error handling (stop: return True)
68
- - exit command handling (stop: return True)
78
+ :return tuple: read_error, data
79
+ - read_error is set to true upon timeout or other exception
80
+ - data holds bytes or decoded string read from the socket
69
81
  """
70
82
  Client.console(f"[Client] read {self.client_id}")
71
83
  self.last_msg_t = ticks_ms()
72
84
  try:
73
- request = await self.reader.read(self.read_bytes)
74
- request = request.decode('utf8').strip()
85
+ if timeout_seconds:
86
+ request = await asyncio.wait_for(self.reader.read(self.read_bytes), timeout_seconds)
87
+ else:
88
+ request = await self.reader.read(self.read_bytes)
89
+ if decoding:
90
+ request = request.decode(decoding)
91
+ except asyncio.TimeoutError:
92
+ Client.console(f"[Client] Stream read timeout ({self.client_id}), timeout={timeout_seconds}s")
93
+ return True, ''
75
94
  except Exception as e:
76
95
  Client.console(f"[Client] Stream read error ({self.client_id}): {e}")
77
96
  collect() # gc collection: "fix" for memory allocation failed, allocating 2049 bytes
@@ -79,8 +98,6 @@ class Client:
79
98
 
80
99
  # Input handling
81
100
  Client.console(f"[Client] raw request ({self.client_id}): |{request}|")
82
- if request in ('exit', ''):
83
- return True, request
84
101
  return False, request
85
102
 
86
103
  async def a_send(self, response, encode='utf8'):
@@ -95,7 +112,7 @@ class Client:
95
112
  except Exception as e:
96
113
  # Maintain ACTIVE_CLIS - remove closed connection by peer.
97
114
  await self.close()
98
- errlog_add(f"[WARN] Client.a_send (auto-drop) {self.client_id}: {e}")
115
+ syslog(f"[WARN] Client.a_send (auto-drop) {self.client_id}: {e}")
99
116
  return # Abort async send (no drain)
100
117
  # Send buffered data with async task - hacky
101
118
  try:
@@ -107,10 +124,10 @@ class Client:
107
124
  Client.console(f"[Client] Drain error -> close conn: {e}")
108
125
  await self.close()
109
126
  else:
110
- console_write(f"[Client] NoCon: response>dev/nul")
127
+ console_write("[Client] NoCon: response>dev/nul")
111
128
 
112
129
  def send(self, response):
113
- # Implement in child class - synchronous send method
130
+ # Optional - Implement in child class - synchronous send (all) method
114
131
  pass
115
132
 
116
133
  async def close(self):
@@ -138,7 +155,7 @@ class Client:
138
155
  if Client.ACTIVE_CLIS.get(client_id, None) is not None:
139
156
  Client.ACTIVE_CLIS.pop(client_id)
140
157
  # Update server task output (? test ?)
141
- Manager().server_task_msg(','.join(list(Client.ACTIVE_CLIS)))
158
+ Manager().task_msg('server', ','.join(list(Client.ACTIVE_CLIS)))
142
159
 
143
160
  def __del__(self):
144
161
  """Client GC collect"""
@@ -146,176 +163,31 @@ class Client:
146
163
  Client.console(f"[Client] del: {self.client_id}")
147
164
 
148
165
 
149
- class WebCli(Client):
150
- REST_ENDPOINTS = {}
151
- AUTH = cfgget('auth')
152
- REQ200 = "HTTP/1.1 200 OK\r\nContent-Type: {dtype}\r\nContent-Length:{len}\r\n\r\n{data}"
153
- REQ400 = "HTTP/1.1 400 Bad Request\r\nContent-Type: text/plain\r\nContent-Length: {len}\r\n\r\n{data}"
154
- REQ404 = "HTTP/1.1 404 Not Found\r\nContent-Type: text/plain\r\nContent-Length: {len}\r\n\r\n{data}"
166
+ class WebCli(Client, WebEngine):
155
167
 
156
168
  def __init__(self, reader, writer):
157
169
  Client.__init__(self, reader, writer, r_size=512)
158
-
159
- @staticmethod
160
- def rest_setter(endpoint, callback):
161
- # AUTO ENABLE webui when rest_setter called and webui is False
162
- if not cfgget('webui'):
163
- from Config import cfgput
164
- if cfgput('webui', True): # SET webui to True
165
- from machine import reset
166
- reset() # HARD RESET (REBOOT)
167
- WebCli.REST_ENDPOINTS[endpoint] = callback
170
+ WebEngine.__init__(self, client=self, version=Shell.MICROS_VERSION)
168
171
 
169
172
  async def run_web(self):
170
173
  # Update server task output
171
- Manager().server_task_msg(','.join(list(Client.ACTIVE_CLIS)))
174
+ Manager().task_msg('server', ','.join(list(Client.ACTIVE_CLIS)))
172
175
 
173
176
  # Run async connection handling
174
177
  while self.connected:
175
178
  try:
176
179
  # Read request msg from client
177
- state, request = await self.read()
178
- if state:
180
+ state, request = await self.read(decoding=None)
181
+ if state or not request:
182
+ break
183
+ if not await self.response(request):
179
184
  break
180
- await self.response(request)
181
185
  except Exception as e:
182
- errlog_add(f"[ERR] Client.run_web: {e}")
186
+ syslog(f"[ERR] Client.run_web: {e}")
183
187
  break
184
188
  # Close connection
185
189
  await self.close()
186
190
 
187
- @staticmethod
188
- def file_type(path):
189
- """File dynamic Content-Type handling"""
190
- if path.endswith(".html"):
191
- return "text/html"
192
- elif path.endswith(".css"):
193
- return "text/css"
194
- elif path.endswith(".js"):
195
- return "application/javascript"
196
- else:
197
- return "text/plain"
198
-
199
- async def response(self, request):
200
- """HTTP GET REQUEST - WEB INTERFACE"""
201
- # Parse request line (first line)
202
- _method, url, _version = request.split('\n')[0].split()
203
- # Protocol validation
204
- if _method != "GET" and _version.startswith('HTTP'):
205
- _err = f"Bad Request: not GET HTTP/1.1"
206
- await self.a_send(self.REQ400.format(len=len(_err), data=_err))
207
- return
208
-
209
- # [1] REST API GET ENDPOINT [/rest]
210
- if url.startswith('/rest'):
211
- Client.console("[WebCli] --- /rest ACCEPT")
212
- try:
213
- await self.a_send(WebCli.rest(url))
214
- except Exception as e:
215
- await self.a_send(self.REQ404.format(len=len(str(e)), data=e))
216
- return
217
- # [2] DYNAMIC/USER ENDPOINTS (from Load Modules)
218
- if await self.endpoints(url):
219
- return
220
- # [3] HOME/PAGE ENDPOINT(s) [default: / -> /index.html]
221
- if url.startswith('/'):
222
- resource = 'index.html' if url == '/' else url.replace('/', '')
223
- Client.console(f"[WebCli] --- {url} ACCEPT")
224
- if resource.split('.')[-1] not in ('html', 'js', 'css'):
225
- await self.a_send(self.REQ404.format(len=27, data='404 Not supported file type'))
226
- return
227
- try:
228
- # SEND RESOURCE CONTENT: HTML, JS, CSS
229
- with open(resource, 'r') as file:
230
- html = file.read()
231
- await self.a_send(self.REQ200.format(dtype=WebCli.file_type(resource), len=len(html), data=html))
232
- except OSError:
233
- await self.a_send(self.REQ404.format(len=13, data='404 Not Found'))
234
- return
235
- # INVALID/BAD REQUEST
236
- await self.a_send(self.REQ400.format(len=15, data='400 Bad Request'))
237
-
238
- async def endpoints(self, url):
239
- url = url[1:] # Cut first / char
240
- if url in WebCli.REST_ENDPOINTS:
241
- console_write(f"[WebCli] endpoint: {url}")
242
- # Registered endpoint was found - exec callback
243
- try:
244
- # RESOLVE ENDPOINT CALLBACK
245
- # dtype:
246
- # one-shot: image/jpeg | text/html | text/plain - data: raw
247
- # task: multipart/x-mixed-replace | multipart/form-data - data: dict=callback,content-type
248
- # content-type: image/jpeg | audio/l16;*
249
- dtype, data = WebCli.REST_ENDPOINTS[url]()
250
- if dtype == 'image/jpeg':
251
- resp = f"HTTP/1.1 200 OK\r\nContent-Type: {dtype}\r\nContent-Length:{len(data)}\r\n\r\n".encode('utf8') + data
252
- await self.a_send(resp, encode=None)
253
- elif dtype in ('multipart/x-mixed-replace', 'multipart/form-data'):
254
- headers = (f"HTTP/1.1 200 OK\r\nContent-Type: {dtype}; boundary=\"micrOS_boundary\"\r\n\r\n").encode('utf-8')
255
- await self.a_send(headers, encode=None)
256
- # Start Native stream async task
257
- task = NativeTask()
258
- task.create(callback=self.stream(data['callback'], task, data['content-type']),
259
- tag=f"web.stream_{self.client_id.replace('W', '')}")
260
- else: # dtype: text/html or text/plain
261
- await self.a_send(f"HTTP/1.1 200 OK\r\nContent-Type: {dtype}\r\nContent-Length:{len(data)}\r\n\r\n{data}")
262
- except Exception as e:
263
- await self.a_send(self.REQ404.format(len=len(str(e)), data=e))
264
- errlog_add(f"[ERR] WebCli endpoints {url}: {e}")
265
- return True # Registered endpoint was found and executed
266
- return False # Not registered endpoint
267
-
268
- async def stream(self, callback, task, content_type):
269
- """
270
- Async stream method
271
- :param callback: sync or async function callback (auto-detect) WARNING: works for functions only (not methods!)
272
- """
273
- is_coroutine = 'generator' in str(type(callback)) # async function callback auto-detect
274
- with task:
275
- task.out = 'Stream started'
276
- data_to_send = b''
277
-
278
- while self.connected and data_to_send is not None:
279
- data_to_send = await callback() if is_coroutine else callback()
280
- part = (f"\r\n--micrOS_boundary\r\nContent-Type: {content_type}\r\n\r\n").encode('utf-8') + data_to_send
281
- task.out = 'Data sent'
282
- await self.a_send(part, encode=None)
283
- await asyncio.sleep_ms(10)
284
-
285
- # Gracefully terminate the stream
286
- if self.connected:
287
- closing_boundary = '\r\n--micrOS_boundary--\r\n'
288
- await self.a_send(closing_boundary, encode=None)
289
- await self.close()
290
- task.out = 'Finished stream'
291
-
292
- @staticmethod
293
- def rest(url):
294
- resp_schema = {'result': None, 'state': False}
295
- cmd = url.replace('/rest', '')
296
- if len(cmd) > 1:
297
- # REST sub-parameter handling (rest commands)
298
- cmd = (cmd.replace('/', ' ').replace('%22', '"').replace('%E2%80%9C', '"')
299
- .replace('%E2%80%9D', '"').replace('-', ' ').strip().split())
300
- # request json format instead of default string output (+ handle & tasks syntax)
301
- cmd.insert(-1, '>json') if cmd[-1].startswith('&') else cmd.append('>json')
302
- # EXECUTE COMMAND - LoadModule
303
- if WebCli.AUTH:
304
- state, out = lm_exec(cmd) if lm_is_loaded(cmd[0]) else (True, 'Auth:Protected')
305
- else:
306
- state, out = lm_exec(cmd)
307
- try:
308
- resp_schema['result'] = loads(out) # Load again ... hack for embedded shell json converter...
309
- except:
310
- resp_schema['result'] = out
311
- resp_schema['state'] = state
312
- else:
313
- resp_schema['result'] = {"micrOS": Shell.MICROS_VERSION, 'node': cfgget('devfid'), 'auth': WebCli.AUTH}
314
- if len(tuple(WebCli.REST_ENDPOINTS.keys())) > 0:
315
- resp_schema['result']['usr_endpoints'] = tuple(WebCli.REST_ENDPOINTS)
316
- resp_schema['state'] = True
317
- response = dumps(resp_schema)
318
- return WebCli.REQ200.format(dtype='text/html', len=len(response), data=response)
319
191
 
320
192
  class ShellCli(Client, Shell):
321
193
 
@@ -328,7 +200,9 @@ class ShellCli(Client, Shell):
328
200
 
329
201
  def send(self, response):
330
202
  """
331
- Send response to client with non-async function
203
+ Synchronous send function (with drain task)
204
+ - not used in Shell or ShellCli
205
+ - Note: it is a support function for synchronous scenarios: Server.reply_all
332
206
  """
333
207
  if self.connected:
334
208
  if self.prompt() != response:
@@ -338,21 +212,20 @@ class ShellCli(Client, Shell):
338
212
  # Store data in stream buffer
339
213
  try:
340
214
  self.writer.write(response.encode('utf8'))
341
- except Exception as e:
215
+ except:
342
216
  # Maintain ACTIVE_CLIS - remove closed connection by peer.
343
217
  Client.drop_client(self.client_id)
344
- errlog_add(f"[WARN] ShellCli.send (auto-drop) {self.client_id}: {e}")
218
+ syslog(f"[WARN] ShellCli.send (auto-drop) {self.client_id}")
345
219
  # Send buffered data with async task - hacky
346
220
  if self.drain_event.is_set():
347
221
  self.drain_event.clear() # set drain busy (False)
348
222
  asyncio.get_event_loop().create_task(self.__wait_for_drain())
349
223
  else:
350
- console_write(f"[ShellCli] NoCon: response>/dev/nul")
224
+ console_write("[ShellCli] NoCon: response>/dev/nul")
351
225
 
352
226
  async def __wait_for_drain(self):
353
227
  """
354
- Handle drain serialization
355
- - solve output data duplicate
228
+ Handle drain serialization - for synchronous send function
356
229
  """
357
230
  try:
358
231
  # send write buffer
@@ -365,55 +238,45 @@ class ShellCli(Client, Shell):
365
238
  # set drain free
366
239
  self.drain_event.set() # set drain free (True)
367
240
 
368
- async def close(self):
369
- Client.console(f"[ShellCli] Close connection {self.client_id}")
370
- self.send("Bye!\n")
371
- # Reset shell state machine
372
- self.reset()
373
- await asyncio.sleep_ms(50)
374
- # Used from Client parent class
375
- await super().close()
376
-
377
- async def __shell_cmd(self, request):
241
+ async def a_send(self, response, encode='utf8'):
378
242
  """
379
- Handle micrOS shell commands
243
+ Async send for Shell (new line + prompt$)
380
244
  """
381
- # Run micrOS shell with request string
382
- try:
383
- # Handle micrOS shell
384
- Client.console("[ShellCli] --- #Run shell")
385
- state = self.shell(request)
386
- if state:
387
- return False # exit_loop
388
- return True # exit_loop : Close session when shell returns False (auth Failed, etc.)
389
- except Exception as e:
390
- Client.console(f"[ShellCli] Shell exception: {e}")
391
- if "ECONNRESET" in str(e):
392
- return True # exit_loop
393
- self.send("[HA] Critical error - disconnect & hard reset")
394
- errlog_add("[ERR] Socket critical error - reboot")
395
- self.reboot()
245
+ if self.prompt() != response:
246
+ # [format] Add new line if not prompt
247
+ response = f"{response}\n"
248
+ await super().a_send(response, encode)
396
249
 
397
250
  async def run_shell(self):
398
251
  # Update server task output
399
- Manager().server_task_msg(','.join(list(Client.ACTIVE_CLIS)))
252
+ Manager().task_msg('server', ','.join(list(Client.ACTIVE_CLIS)))
400
253
  # Init prompt
401
- self.send(self.prompt())
254
+ await self.a_send(self.prompt())
402
255
  # Run async connection handling
256
+ _exit = False
403
257
  while self.connected:
404
258
  try:
405
259
  # Read request msg from client
406
260
  state, request = await self.read()
407
- if state:
408
- break
409
- _exit = await self.__shell_cmd(request)
410
- if _exit:
411
- collect()
261
+ if state or request in ('exit', ''):
412
262
  break
263
+ # Run micrOS shell with request string
264
+ Client.console("[ShellCli] --- #Run shell")
265
+ # Shell -> True (OK) or False (NOK) -> NOK->Close session (auth Failed, etc.)
266
+ _exit = not await self.shell(request)
413
267
  except Exception as e:
414
- errlog_add(f"[ERR] handle_client: {e}")
268
+ syslog(f"[ERR] Shell client: {e}")
269
+ if "ECONNRESET" in str(e):
270
+ _exit = True # exit_loop
271
+ else:
272
+ await self.a_send("[HA] Critical error - disconnect & hard reset")
273
+ syslog("[ERR] Socket critical error - reboot")
274
+ await self.reboot()
275
+ if _exit:
276
+ collect()
415
277
  break
416
278
  # Close connection
279
+ await self.a_send("Bye!")
417
280
  await self.close()
418
281
 
419
282
 
@@ -421,13 +284,14 @@ class ShellCli(Client, Shell):
421
284
  # SOCKET SERVER CLASS #
422
285
  #########################################################
423
286
 
424
- class SocketServer:
287
+ class Server:
425
288
  """
426
289
  Socket message data packet layer - send and receive
427
290
  Embedded command interpretation:
428
291
  - exit
429
292
  Handle user requests/commands with Shell (bash like experience)
430
293
  """
294
+ __slots__ = ['server', 'web', '_host', '_socqueue', '_port', '_timeout', '_initialized']
431
295
  __instance = None
432
296
 
433
297
  def __new__(cls):
@@ -437,8 +301,8 @@ class SocketServer:
437
301
  cls - class
438
302
  """
439
303
  if not cls.__instance:
440
- # SocketServer singleton properties
441
- cls.__instance = super(SocketServer, cls).__new__(cls)
304
+ # Server singleton properties
305
+ cls.__instance = super(Server, cls).__new__(cls)
442
306
  cls.__instance._initialized = False
443
307
  return cls.__instance
444
308
 
@@ -549,8 +413,11 @@ class SocketServer:
549
413
  """
550
414
  for _, cli in Client.ACTIVE_CLIS.items():
551
415
  if cli.connected:
552
- cli.send(msg)
416
+ cli.send(f"~~~ {msg}")
553
417
 
554
418
  def __del__(self):
555
419
  Client.console("[ socket server ] <<destructor>>")
556
- self.server.close()
420
+ if self.server:
421
+ self.server.close()
422
+ if self.web:
423
+ self.web.close()