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/Hooks.py CHANGED
@@ -17,12 +17,21 @@ Designed by Marcell Ban aka BxNxM
17
17
  #################################################################
18
18
  # IMPORTS #
19
19
  #################################################################
20
- from Config import cfgget
20
+ from Config import cfgget, cfgput
21
21
  from microIO import detect_platform
22
- from Debug import console_write
22
+ from Debug import console_write, syslog
23
23
  from Tasks import exec_lm_pipe
24
+ from Auth import resolve_secret
24
25
  from micropython import mem_info
25
26
  from machine import freq
27
+ try:
28
+ from machine import reset_cause, PWRON_RESET, HARD_RESET, WDT_RESET, DEEPSLEEP_RESET, SOFT_RESET
29
+ except ImportError:
30
+ reset_cause = None
31
+ try:
32
+ from gc import mem_free
33
+ except ImportError:
34
+ from simgc import mem_free
26
35
 
27
36
  #################################################################
28
37
  # FUNCTIONS #
@@ -34,29 +43,58 @@ def bootup():
34
43
  Executes when system boots up.
35
44
  """
36
45
  # Execute LMs from boothook config parameter
37
- console_write("[BOOT] EXECUTION ...")
46
+ console_write("[BOOT] EXECUTION...")
38
47
  bootasks = cfgget('boothook')
39
48
  if bootasks is not None and bootasks.lower() != 'n/a':
40
49
  console_write(f"|-[BOOT] TASKS: {bootasks}")
41
- if exec_lm_pipe(bootasks):
50
+ if exec_lm_pipe(resolve_secret(bootasks)):
42
51
  console_write("|-[BOOT] DONE")
43
52
  else:
44
53
  console_write("|-[BOOT] ERROR")
45
54
 
46
- # Set boostmd (boost mode)
55
+ # Load and Save boot cause
56
+ boot_cause()
57
+ # Autotune queue size
58
+ _tune_queue_size()
59
+ # Configure CPU performance
60
+ _tune_performance()
61
+
62
+
63
+ def _tune_queue_size():
64
+ """
65
+ Tune queue size based on available ram
66
+ between 5-50
67
+ """
68
+ min_queue, max_queue, task_req_kb = 5, 20, 20 # 400kb max for tasks management
69
+ est_queue = int(mem_free()/1000/task_req_kb)
70
+ est_queue = max(est_queue, min_queue)
71
+ est_queue = min(est_queue, max_queue)
72
+ current_queue = cfgget('aioqueue')
73
+ if est_queue > current_queue:
74
+ cfgput('aioqueue', est_queue)
75
+
76
+
77
+ def _tune_performance():
78
+ # {(platforms, ...): (min_clock, max_clock), ...}
79
+ cpu_clocks = {
80
+ ('esp32c3', 'esp32c6'): (80_000_000, 160_000_000),
81
+ ('esp32',): (160_000_000, 240_000_000), # default
82
+ }
47
83
  platform = detect_platform()
48
- if cfgget('boostmd') is True:
49
- console_write(f"[BOOT HOOKS] Set up CPU high Hz - boostmd: {cfgget('boostmd')}")
50
- if platform == 'esp32c3':
51
- freq(160_000_000) # 160 Mhz (max)
52
- elif 'esp32' in platform:
53
- freq(240_000_000) # 240 Mhz (max)
84
+ cpu_min_max = cpu_clocks[('esp32',)]
85
+ for platforms, clocks in cpu_clocks.items():
86
+ if platform in platforms:
87
+ cpu_min_max = clocks
88
+ break
89
+ # Set boosted (boost mode)
90
+ if cfgget('boostmd'):
91
+ max_hz = cpu_min_max[1]
92
+ console_write(f"[BOOT HOOKS] CPU boost mode ON: {max_hz} Hz")
93
+ freq(max_hz)
54
94
  else:
55
- console_write(f"[BOOT HOOKS] Set up CPU low Hz - boostmd: {cfgget('boostmd')}")
56
- if platform == 'esp32c3':
57
- freq(80_000_000) # 80 Mhz / Half the max CPU clock
58
- elif 'esp32' in platform:
59
- freq(160_000_000) # 160 Mhz / Half the max CPU clock
95
+ min_hz = cpu_min_max[0]
96
+ console_write(f"[BOOT HOOKS] CPU boost mode OFF: {min_hz} Hz")
97
+ freq(min_hz)
60
98
 
61
99
 
62
100
  def profiling_info(label=""):
@@ -67,3 +105,37 @@ def profiling_info(label=""):
67
105
  console_write(f"{'~'*5} [PROFILING INFO] - {label} {'~'*5}")
68
106
  mem_info()
69
107
  console_write("~"*30)
108
+
109
+
110
+ def boot_cause():
111
+ reason = 0, "-Unknown"
112
+ if callable(reset_cause):
113
+ reason = 0, "Unknown"
114
+ reset_reason = reset_cause()
115
+ if reset_reason == PWRON_RESET:
116
+ reason = 1, "PowerOn"
117
+ elif reset_reason == HARD_RESET:
118
+ reason = 2, "HardReset"
119
+ elif reset_reason == WDT_RESET:
120
+ reason = 3, "WDTWakeUp"
121
+ elif reset_reason == DEEPSLEEP_RESET:
122
+ reason = 4, "DSWakeUp"
123
+ elif reset_reason == SOFT_RESET:
124
+ reason = 5, "SoftReset"
125
+ syslog(f"[BOOT] info: {reason[1]}")
126
+ return reason
127
+
128
+
129
+ def enableESPNow() -> str:
130
+ """
131
+ Enable ESP-NOW communication
132
+ """
133
+ if cfgget('espnow'):
134
+ try:
135
+ from Espnow import ESPNowSS
136
+ verdict = ESPNowSS().start_server()
137
+ console_write(f"[TASK] Start ESPNow-InterCon server: {verdict}")
138
+ except Exception as e:
139
+ syslog(f"[ERR] Start ESPNow-InterCon server: {e}")
140
+ return str(e)
141
+ return "ESPNow disabled"
@@ -1,14 +1,35 @@
1
+ """
2
+ Module is responsible for device-device communication
3
+ dedicated to micrOS framework.
4
+ Built-in-function:
5
+ - Socket InterConnect interface
6
+ - ESPNow redirection
7
+
8
+ Designed by
9
+ Marcell Ban aka BxNxM
10
+ Kristof Kasza aka KKristof452
11
+ """
12
+
1
13
  from socket import getaddrinfo, SOCK_STREAM
2
- from re import compile
3
- import uasyncio as asyncio
4
- from Debug import errlog_add
14
+ from re import compile as re_compile
15
+ from json import loads
16
+ from binascii import hexlify
17
+ from uasyncio import open_connection
18
+
19
+ from Debug import syslog
5
20
  from Config import cfgget
6
- from Server import SocketServer
21
+ from Server import Server
7
22
  from Tasks import NativeTask
8
23
 
24
+ if cfgget('espnow'):
25
+ from Espnow import ESPNowSS
26
+ else:
27
+ ESPNowSS = None
28
+
9
29
 
10
30
  class InterCon:
11
- CONN_MAP = {}
31
+ CONN_MAP: dict[str, str] = {} # hostname: IP address pairs
32
+ NO_ESPNOW: list[str] = [] # disabled ESPNow hostname list (cache for fallback speed-up)
12
33
  PORT = cfgget('socport')
13
34
 
14
35
  def __init__(self):
@@ -19,10 +40,10 @@ class InterCon:
19
40
 
20
41
  @staticmethod
21
42
  def validate_ipv4(str_in):
22
- pattern = compile(r'^(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$')
43
+ pattern = re_compile(r'^(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$')
23
44
  return bool(pattern.match(str_in))
24
45
 
25
- async def send_cmd(self, host, cmd):
46
+ async def send_cmd(self, host:str, cmd:list):
26
47
  """
27
48
  Async Main method to implement device-device communication with
28
49
  - dhcp host resolve and IP caching
@@ -34,14 +55,19 @@ class InterCon:
34
55
  # Check if host is a hostname (example.local) and resolve its IP address
35
56
  if not InterCon.validate_ipv4(host):
36
57
  hostname = host
37
- # Retrieve IP address by hostname dynamically
58
+ # Lookup hostname without .domain (sub-hostname matching)
59
+ if '.' not in hostname:
60
+ _hosts = list([d for d in InterCon.CONN_MAP if hostname in d])
61
+ if len(_hosts) > 0:
62
+ hostname = _hosts[0]
63
+ # Retrieve IP address by hostname.domain dynamically
38
64
  if InterCon.CONN_MAP.get(hostname, None) is None:
39
65
  try:
40
66
  addr_info = getaddrinfo(host, InterCon.PORT, 0, SOCK_STREAM)
41
67
  host = addr_info[-1][4][0]
42
68
  except OSError as e:
43
- SocketServer.reply_all(f"[intercon] NoHost: {e}")
44
- errlog_add(f"[intercon] send_cmd {host} oserr: {e}")
69
+ Server.reply_all(f"[intercon] NoHost: {e}")
70
+ syslog(f"[intercon] send_cmd {host} oserr: {e}")
45
71
  return ''
46
72
  else:
47
73
  # Restore IP from cache by hostname
@@ -50,12 +76,12 @@ class InterCon:
50
76
  if InterCon.validate_ipv4(host):
51
77
  try:
52
78
  # Create socket object
53
- self.reader, self.writer = await asyncio.open_connection(host, InterCon.PORT)
79
+ self.reader, self.writer = await open_connection(host, InterCon.PORT)
54
80
  # Send command over TCP/IP
55
81
  output = await self.__run_command(cmd, hostname)
56
82
  except OSError as e:
57
- SocketServer.reply_all(f"[intercon] NoHost: {e}")
58
- errlog_add(f"[intercon] send_cmd {host} oserr: {e}")
83
+ Server.reply_all(f"[intercon] NoHost: {e}")
84
+ syslog(f"[intercon] send_cmd {host} oserr: {e}")
59
85
  output = None
60
86
  finally:
61
87
  if self.writer:
@@ -68,26 +94,23 @@ class InterCon:
68
94
  InterCon.CONN_MAP[hostname] = None if output is None else host
69
95
  # None: ServerBusy(or \0) or Prompt mismatch (auto delete cached IP), STR: valid comm. output
70
96
  return output
71
- else:
72
- errlog_add(f"[ERR][intercon] Invalid host: {host}")
97
+ syslog(f"[ERR][intercon] Invalid host: {host}")
73
98
  return ''
74
99
 
75
- async def __run_command(self, cmd, hostname):
100
+ async def __run_command(self, cmd:list, hostname:str):
76
101
  """
77
102
  Implements receive data on open connection, command query and result collection
78
103
  :param cmd: command string to server socket shell
79
104
  :param hostname: hostname for prompt checking
80
105
  Return None here will trigger retry mechanism... + deletes cached IP
81
106
  """
82
- cmd = str.encode(cmd)
83
107
  data, prompt = await self.__receive_data()
84
108
  if "Connection is busy. Bye!" in prompt:
85
109
  return None
86
110
  # Compare prompt |node01 $| with hostname 'node01.local'
87
111
  if hostname is None or prompt is None or str(prompt).replace('$', '').strip() == str(hostname).split('.')[0]:
88
112
  # Run command on validated device
89
- # TODO: Handle multiple cmd as input, separated by ; (????)
90
- self.writer.write(cmd)
113
+ self.writer.write(str.encode(' '.join(cmd)))
91
114
  await self.writer.drain()
92
115
  data, _ = await self.__receive_data(prompt=prompt)
93
116
  if data == '\0':
@@ -95,7 +118,7 @@ class InterCon:
95
118
  # Successful data receive, return data
96
119
  return data
97
120
  # Skip command run: prompt and host not the same!
98
- SocketServer.reply_all(f"[intercon] prompt mismatch, hostname: {hostname} prompt: {prompt}")
121
+ Server.reply_all(f"[intercon] prompt mismatch, hostname: {hostname} prompt: {prompt}")
99
122
  return None
100
123
 
101
124
  async def __auth_handshake(self, prompt):
@@ -104,13 +127,13 @@ class InterCon:
104
127
  await self.writer.drain()
105
128
  data, prompt = await self.__receive_data(prompt=prompt)
106
129
  except Exception as e:
107
- errlog_add(f'[intercon][ERR] Auth: {e}')
130
+ syslog(f'[intercon][ERR] Auth: {e}')
108
131
  data = 'AuthFailed'
109
132
  if 'AuthOk' in data:
110
133
  return True # AuthOk
111
134
  return False # AuthFailed
112
135
 
113
- async def __receive_data(self, prompt=None):
136
+ async def __receive_data(self, prompt=None) -> tuple[str, str]:
114
137
  """
115
138
  Implements data receive loop until prompt / [configure] / Bye!
116
139
  :param prompt: socket shell prompt
@@ -140,8 +163,34 @@ class InterCon:
140
163
  data = data.replace(prompt, '').replace('\n', ' ')
141
164
  return data, prompt
142
165
 
166
+ async def auto_espnow_handshake(self, host:str) -> dict:
167
+ """
168
+ [1] Check espnow.server running on host
169
+ [2] Get MAC address for host (from system info)
170
+ [3] Execute ESPNowSS.handshake
171
+ """
172
+ response = await self.send_cmd(host, ["task", "list", ">json"])
173
+ if not response:
174
+ return {None: f"[ERR] ESPNow auto handshake: task list >>{host}: {response}"}
175
+
176
+ active_tasks = loads(response).get("active")
177
+ if active_tasks and "espnow.server" in active_tasks:
178
+ response = await self.send_cmd(host, ["system", "info", ">json"])
179
+ if not response:
180
+ return {None: "[ERR] ESPNow auto handshake: system info"}
181
+ try:
182
+ host_mac = loads(response).get("mac")
183
+ except Exception as ex:
184
+ return {None: f"[ERR] ESPNow auto handshake: {ex}"}
185
+
186
+ return ESPNowSS().handshake(host_mac)
187
+
188
+ if not InterCon.validate_ipv4(host):
189
+ InterCon.NO_ESPNOW.append(str(host).split(".")[0]) # host.local -> host
190
+ return {None: f"ESPNow auto handshake: espnow disabled on host {host}"}
191
+
143
192
 
144
- async def _send_cmd(host, cmd, com_obj):
193
+ async def _socket_send_cmd(host:str, cmd:list, com_obj:InterCon) -> None:
145
194
  """
146
195
  Async send command wrapper for further async task integration and sync send_cmd usage (main)
147
196
  :param host: hostname / IP address
@@ -149,42 +198,77 @@ async def _send_cmd(host, cmd, com_obj):
149
198
  :param com_obj: InterCon object to utilize send_cmd method and task status updates
150
199
  """
151
200
  # Send command
201
+ for _ in range(0, 2): # Retry mechanism
202
+ out = await com_obj.send_cmd(host, cmd) # Send CMD
203
+ if out is not None: # Retry mechanism
204
+ break
205
+ await com_obj.task.feed(sleep_ms=100) # Retry mechanism
206
+ com_obj.task.out = '' if out is None else out
207
+
208
+
209
+ async def _send_cmd(host:str, cmd:list|str, com_obj:InterCon):
210
+ """
211
+ Top level InterConnect callback function
212
+ [1] node01.domain -> ESPNow, Socket
213
+ (domain: .local, .net, etc.)
214
+ [2] node01 -> ESPNow, Socket fallback in case found in InterConnect cache
215
+ [3] IP address -> Socket
216
+ """
152
217
  with com_obj.task:
153
- for _ in range(0, 4): # Retry mechanism
154
- out = await com_obj.send_cmd(host, cmd) # Send CMD
155
- if out is not None: # Retry mechanism
156
- break
157
- await asyncio.sleep_ms(100) # Retry mechanism
158
- com_obj.task.out = '' if out is None else out
159
- return com_obj.task.out
218
+ if ESPNowSS:
219
+ # [1] ESPNow Active
220
+ name = str(host).split(".")[0] # host.local -> host
221
+ if name not in InterCon.NO_ESPNOW and name in list(ESPNowSS().devices.values()):
222
+ com_obj.task.out = "Redirected to ESPNow"
223
+ if isinstance(cmd, list):
224
+ cmd = ' '.join(cmd)
225
+ # Send command and retrieve result
226
+ sender = ESPNowSS().send(peer=name, msg=cmd)
227
+ sender_task = NativeTask.TASKS.get(list(sender.keys())[0])
228
+ result = await sender_task.await_result(timeout=10)
229
+ if result != "Timeout has beed exceeded":
230
+ # Successful command execution
231
+ com_obj.task.out = result # Output mirroring: Child -> Parent
232
+ sender_task.out = "Redirected to ParentTask" # Remove redundant data in embedded mode
233
+ return
160
234
 
235
+ # Handle legacy string input
236
+ if isinstance(cmd, str):
237
+ cmd = cmd.split()
238
+ # [1][2] Socket send (default and fallback)
239
+ await _socket_send_cmd(host, cmd, com_obj)
161
240
 
162
- def send_cmd(host, cmd):
241
+ if ESPNowSS and name not in InterCon.NO_ESPNOW:
242
+ # [3] Automatic ESPNow handshake
243
+ verdict = await com_obj.auto_espnow_handshake(host)
244
+ if list(verdict.keys())[0] is None:
245
+ syslog(str(list(verdict.values())[0]))
246
+
247
+
248
+ def send_cmd(host:str, cmd:list|str) -> dict:
163
249
  """
164
- Sync wrapper of async _send_cmd (InterCon.send_cmd consumer with retry)
165
- :param host: hostname / IP address
166
- :param cmd: command string to server socket shell
250
+ Top level InterConnect send task creation
251
+ Handles ESPNow and socket communication
167
252
  """
168
253
  def _tagify():
169
254
  nonlocal host, cmd
170
- _mod = cmd.split(' ')[0].strip()
255
+ _mod = cmd[0]
171
256
  if InterCon.validate_ipv4(host):
172
257
  return f"{'.'.join(host.split('.')[-2:])}.{_mod}"
173
- return f"{host.replace('.local', '')}.{_mod}"
258
+ target = ".".join(host.split(".")[0:-1]) if "." in host else host
259
+ return f"{target}.{_mod}"
174
260
 
175
261
  com_obj = InterCon()
176
- tag = f"con.{_tagify()}"
177
- started = com_obj.task.create(callback=_send_cmd(host, cmd, com_obj), tag=tag)
178
- if started:
179
- result = {"verdict": f"Task started: task show {tag}", "tag": tag}
180
- else:
181
- result = {"verdict": "Task is Busy", "tag": tag}
182
- return result
262
+ task_id = f"con.{_tagify()}" # CHECK TASK ID CONFLICT
263
+ return com_obj.task.create(callback=_send_cmd(host, cmd, com_obj), tag=task_id)
183
264
 
184
265
 
185
- def host_cache():
266
+ def host_cache() -> dict:
186
267
  """
187
268
  Dump InterCon connection cache
188
269
  """
189
- return InterCon.CONN_MAP
190
-
270
+ if ESPNowSS is None:
271
+ return InterCon.CONN_MAP
272
+ all_devs = dict({name:hexlify(mac, ':').decode() for mac, name in ESPNowSS().devices.items()})
273
+ all_devs.update(InterCon.CONN_MAP)
274
+ return all_devs
@@ -19,9 +19,9 @@ Reference: https://docs.micropython.org/en/latest/library/machine.Pin.html
19
19
  from machine import Pin
20
20
  from utime import ticks_ms, ticks_diff
21
21
  from Config import cfgget
22
- from Debug import console_write, errlog_add
22
+ from Debug import console_write, syslog
23
23
  from Tasks import exec_lm_pipe_schedule
24
- from microIO import physical_pin
24
+ from microIO import resolve_pin
25
25
  if cfgget('cron'):
26
26
  # Only import when enabled - memory usage optimization
27
27
  from Scheduler import scheduler
@@ -71,8 +71,9 @@ def enableInterrupt():
71
71
 
72
72
  def enableCron():
73
73
  """
74
- Set time stump based scheduler aka cron in timer1
74
+ Set time stump based scheduler aka cron on Timer1
75
75
  Input: cron(bool), crontasks(str)
76
+ This is for low frequency sampling, like 12 or 6 / minute (due to low power mode compatibility)
76
77
  """
77
78
  timer_period = 5000 # Timer period ms: 12 check/min
78
79
  console_write(f"[IRQ] CRON IRQ SETUP: {cfgget('cron')} SEQ: {timer_period}")
@@ -80,11 +81,10 @@ def enableCron():
80
81
  if cfgget("cron") and cfgget('crontasks').lower() != 'n/a':
81
82
  from machine import Timer
82
83
  # INIT TIMER 1 IRQ with callback function wrapper
83
- lm_byte = bytearray(cfgget('crontasks'), 'utf-8') # store as bytearray (cache optimization)
84
- sample = int(timer_period/1000)
84
+ sampling = int(timer_period/1000)
85
85
  timer = Timer(1)
86
86
  timer.init(period=timer_period, mode=Timer.PERIODIC,
87
- callback=lambda timer: scheduler(lm_byte, sample))
87
+ callback=lambda timer: scheduler(sampling))
88
88
 
89
89
 
90
90
  #################################################################
@@ -155,9 +155,9 @@ def initEventIRQs():
155
155
  Resolve pin by name
156
156
  """
157
157
  try:
158
- return physical_pin(_p)
158
+ return resolve_pin(_p)
159
159
  except Exception as e:
160
- errlog_add(f'[ERR][!] EVENT {_p} IO error: {e}')
160
+ syslog(f'[ERR][!] EVENT {_p} IO error: {e}')
161
161
  return None
162
162
 
163
163
  # Load External IRQ (1-4) execution data set from node config
@@ -0,0 +1,131 @@
1
+ """
2
+ Module is responsible for System and User logging
3
+ - built-in log rotation
4
+
5
+ Designed by Marcell Ban aka BxNxM
6
+ """
7
+ from time import localtime
8
+ from re import match
9
+ from uos import remove
10
+ from Files import OSPath, path_join, ilist_fs, is_dir
11
+
12
+ #############################################
13
+ # LOGGING WITH DATA ROTATION #
14
+ #############################################
15
+
16
+ def _init_logger():
17
+ """ Init /logs folder """
18
+ if not is_dir(OSPath.LOGS):
19
+ OSPath.LOGS = OSPath._ROOT
20
+ return OSPath.LOGS
21
+
22
+
23
+ def _dir_select(f_name:str) -> str:
24
+ """
25
+ Select log dir based on file extension
26
+ :param f_name: filename with extension to detect target dir
27
+ """
28
+ if f_name.endswith(".log"):
29
+ return OSPath.LOGS
30
+ return OSPath.DATA
31
+
32
+
33
+ def logger(data, f_name:str, limit:int):
34
+ """
35
+ Generic logger function with line rotation and time
36
+ :param data: data to log
37
+ :param f_name: file name to use
38
+ :param limit: line limit for log rotation
39
+ return write verdict - true / false
40
+ INFO: hardcoded max data number = 30
41
+ """
42
+ def _logger(f_mode='r+'):
43
+ nonlocal data, f_path, limit
44
+ limit = min(limit, 30) # Hardcoded max data line = 30
45
+ # [1] GET TIME STUMP
46
+ ts_buff = [str(k) for k in localtime()]
47
+ ts = ".".join(ts_buff[0:3]) + "-" + ":".join(ts_buff[3:6])
48
+ # [2] OPEN FILE - WRITE DATA WITH TS
49
+ with open(f_path, f_mode) as f:
50
+ _data = f"{ts} {data}\n"
51
+ # read file lines and filter by time stump chunks (hack for replace truncate)
52
+ lines = [_l for _l in f.readlines() if '-' in _l and '.' in _l]
53
+ # get file params
54
+ lines_len = len(lines)
55
+ lines.append(_data)
56
+ f.seek(0)
57
+ # line data rotate
58
+ if lines_len >= limit:
59
+ lines = lines[-limit:]
60
+ # write file
61
+ f.write(''.join(lines))
62
+
63
+ f_path = path_join(_dir_select(f_name), f_name)
64
+ # Run logger
65
+ try:
66
+ # There is file - append 'r+'
67
+ _logger()
68
+ except:
69
+ try:
70
+ # There is no file - create 'a+'
71
+ _logger('a+')
72
+ except:
73
+ return False
74
+ return True
75
+
76
+
77
+ def log_get(f_name:str, msgobj=None):
78
+ """
79
+ Generic file getter for .log files
80
+ - log content critical [ERR] counter
81
+ """
82
+ f_path = path_join(_dir_select(f_name), f_name)
83
+ err_cnt = 0
84
+ try:
85
+ if msgobj is not None:
86
+ msgobj(f_path)
87
+ with open(f_path, 'r') as f:
88
+ eline = f.readline().strip()
89
+ while eline:
90
+ # GET error from log line (tag: [ERR])
91
+ err_cnt += 1 if "[ERR]" in eline else 0
92
+ # GIVE BACK .log file contents
93
+ if msgobj is not None:
94
+ msgobj(f"\t{eline}")
95
+ eline = f.readline().strip()
96
+ except:
97
+ pass
98
+ return err_cnt
99
+
100
+
101
+ def syslog(data=None, msgobj=None):
102
+ """
103
+ System log setter/getter
104
+ :param data: None - read logs, str - write logs
105
+ :param msgobj: function to stream .log files
106
+ """
107
+ if data is None:
108
+ # READ LOGS
109
+ err_cnt = sum([log_get(f, msgobj) for f in ilist_fs(OSPath.LOGS, type_filter='f') if f.endswith(".sys.log")])
110
+ return err_cnt
111
+ # WRITE LOGS - [target].sys.log automatic log level detection
112
+ _match = match(r"^\[([^\[\]]+)\]", data)
113
+ log_lvl = _match.group(1).lower() if _match else 'user'
114
+ f_name = f"{log_lvl}.sys.log" if log_lvl in ("err", "warn", "boot", "info") else 'user.sys.log'
115
+ return logger(data, f_name, limit=4)
116
+
117
+
118
+ def log_clean(msgobj=None):
119
+ """
120
+ Clean logs folder
121
+ """
122
+ logs_dir = OSPath.LOGS
123
+ to_del = [file for file in ilist_fs(logs_dir, type_filter='f') if file.endswith('.log')]
124
+ for _del in to_del:
125
+ _del = path_join(logs_dir, _del)
126
+ if msgobj is not None:
127
+ msgobj(f" Delete: {_del}")
128
+ remove(_del)
129
+
130
+ # Init log folder at module load
131
+ _init_logger()