micrOSDevToolKit 2.9.1__py3-none-any.whl → 2.26.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (368) hide show
  1. env/driver_cp210x/macOS_VCP_Driver/SiLabsUSBDriverDisk.dmg +0 -0
  2. env/driver_cp210x/macOS_VCP_Driver/macOS_VCP_Driver_Release_Notes.txt +17 -1
  3. micrOS/micropython/esp32-20251209-v1.27.0.bin +0 -0
  4. micrOS/micropython/esp32c3-20251209-v1.27.0.bin +0 -0
  5. micrOS/micropython/esp32c6-20251209-v1.27.0.bin +0 -0
  6. micrOS/micropython/esp32s2-20251209-v1.27.0.bin +0 -0
  7. micrOS/micropython/esp32s2-LOLIN_MINI-20251209-v1.27.0.bin +0 -0
  8. micrOS/micropython/{esp32s3-20241129-v1.24.1.bin → esp32s3-4MBflash-20241129-v1.24.1.bin} +0 -0
  9. micrOS/micropython/esp32s3-8MBflash-20251209-v1.27.0.bin +0 -0
  10. micrOS/micropython/esp32s3_spiram_oct-20251209-v1.27.0.bin +0 -0
  11. micrOS/micropython/rpi-pico-w-20251209-v1.27.0.uf2 +0 -0
  12. micrOS/micropython/tinypico-20251209-v1.27.0.bin +0 -0
  13. micrOS/release_info/micrOS_ReleaseInfo/system_analysis_sum.json +167 -163
  14. micrOS/source/Auth.py +37 -0
  15. micrOS/source/Common.py +361 -116
  16. micrOS/source/Config.py +32 -22
  17. micrOS/source/Debug.py +50 -94
  18. micrOS/source/Espnow.py +377 -100
  19. micrOS/source/Files.py +207 -0
  20. micrOS/source/Hooks.py +48 -20
  21. micrOS/source/InterConnect.py +126 -42
  22. micrOS/source/Interrupts.py +6 -6
  23. micrOS/source/Logger.py +63 -26
  24. micrOS/source/Network.py +41 -21
  25. micrOS/source/Notify.py +48 -22
  26. micrOS/source/Pacman.py +326 -0
  27. micrOS/source/Scheduler.py +14 -54
  28. micrOS/source/Server.py +67 -69
  29. micrOS/source/Shell.py +99 -91
  30. micrOS/source/Tasks.py +141 -95
  31. micrOS/source/Time.py +19 -18
  32. micrOS/source/Types.py +53 -9
  33. micrOS/source/Web.py +381 -76
  34. micrOS/source/__pycache__/Common.cpython-312.pyc +0 -0
  35. micrOS/source/__pycache__/Debug.cpython-312.pyc +0 -0
  36. micrOS/source/__pycache__/Files.cpython-312.pyc +0 -0
  37. micrOS/source/__pycache__/Logger.cpython-312.pyc +0 -0
  38. micrOS/source/__pycache__/Scheduler.cpython-312.pyc +0 -0
  39. micrOS/source/__pycache__/Server.cpython-312.pyc +0 -0
  40. micrOS/source/__pycache__/Shell.cpython-312.pyc +0 -0
  41. micrOS/source/__pycache__/replhelper.cpython-312.pyc +0 -0
  42. micrOS/source/config/_git.keep +0 -0
  43. micrOS/source/helpers.py +132 -0
  44. micrOS/source/micrOS.py +17 -7
  45. micrOS/source/micrOSloader.py +5 -12
  46. micrOS/source/microIO.py +44 -20
  47. micrOS/source/modules/IO_esp32c6.py +38 -0
  48. micrOS/source/{IO_esp32s3.py → modules/IO_esp32s3.py} +37 -1
  49. micrOS/source/{IO_m5stamp.py → modules/IO_m5stamp.py} +35 -1
  50. micrOS/source/{IO_qtpy.py → modules/IO_qtpy.py} +22 -17
  51. micrOS/source/{IO_tinypico.py → modules/IO_tinypico.py} +38 -0
  52. micrOS/source/modules/LM_L298N.py +161 -0
  53. {toolkit/workspace/precompiled → micrOS/source/modules}/LM_L9110_DCmotor.py +3 -3
  54. micrOS/source/{LM_OV2640.py → modules/LM_OV2640.py} +45 -27
  55. micrOS/source/{LM_VL53L0X.py → modules/LM_VL53L0X.py} +3 -3
  56. micrOS/source/{LM_aht10.py → modules/LM_aht10.py} +2 -2
  57. micrOS/source/{LM_bme280.py → modules/LM_bme280.py} +3 -3
  58. micrOS/source/{LM_buzzer.py → modules/LM_buzzer.py} +18 -25
  59. micrOS/source/{LM_cct.py → modules/LM_cct.py} +17 -21
  60. micrOS/source/modules/LM_cluster.py +255 -0
  61. micrOS/source/{LM_co2.py → modules/LM_co2.py} +3 -3
  62. micrOS/source/{LM_dht11.py → modules/LM_dht11.py} +2 -2
  63. micrOS/source/{LM_dht22.py → modules/LM_dht22.py} +2 -2
  64. micrOS/source/{LM_dimmer.py → modules/LM_dimmer.py} +9 -9
  65. micrOS/source/{LM_distance.py → modules/LM_distance.py} +4 -6
  66. micrOS/source/{LM_ds18.py → modules/LM_ds18.py} +2 -2
  67. micrOS/source/{LM_esp32.py → modules/LM_esp32.py} +5 -0
  68. micrOS/source/modules/LM_espnow.py +53 -0
  69. micrOS/source/modules/LM_fileserver.py +265 -0
  70. micrOS/source/{LM_genIO.py → modules/LM_genIO.py} +52 -37
  71. micrOS/source/{LM_haptic.py → modules/LM_haptic.py} +2 -2
  72. {toolkit/workspace/precompiled → micrOS/source/modules}/LM_i2c.py +5 -4
  73. micrOS/source/{LM_i2s_mic.py → modules/LM_i2s_mic.py} +6 -7
  74. micrOS/source/{LM_ld2410.py → modules/LM_ld2410.py} +2 -2
  75. micrOS/source/{LM_light_sensor.py → modules/LM_light_sensor.py} +10 -21
  76. micrOS/source/modules/LM_mh_z19c.py +198 -0
  77. micrOS/source/modules/LM_neoeffects.py +284 -0
  78. micrOS/source/{LM_neopixel.py → modules/LM_neopixel.py} +19 -23
  79. micrOS/source/{LM_oled.py → modules/LM_oled.py} +2 -2
  80. micrOS/source/{LM_oled_sh1106.py → modules/LM_oled_sh1106.py} +3 -3
  81. micrOS/source/{LM_oled_ui.py → modules/LM_oled_ui.py} +72 -64
  82. micrOS/source/modules/LM_pacman.py +320 -0
  83. micrOS/source/{LM_presence.py → modules/LM_presence.py} +11 -15
  84. micrOS/source/modules/LM_qmi8658.py +204 -0
  85. micrOS/source/{LM_rencoder.py → modules/LM_rencoder.py} +2 -2
  86. micrOS/source/{LM_rest.py → modules/LM_rest.py} +4 -6
  87. micrOS/source/{LM_rgb.py → modules/LM_rgb.py} +21 -29
  88. micrOS/source/{LM_roboarm.py → modules/LM_roboarm.py} +8 -8
  89. micrOS/source/modules/LM_robustness.py +137 -0
  90. micrOS/source/{LM_servo.py → modules/LM_servo.py} +3 -3
  91. micrOS/source/{LM_stepper.py → modules/LM_stepper.py} +5 -5
  92. micrOS/source/{LM_switch.py → modules/LM_switch.py} +11 -9
  93. micrOS/source/{LM_system.py → modules/LM_system.py} +38 -32
  94. micrOS/source/modules/LM_tcs3472.py +187 -0
  95. micrOS/source/{LM_telegram.py → modules/LM_telegram.py} +164 -116
  96. micrOS/source/{LM_trackball.py → modules/LM_trackball.py} +3 -3
  97. micrOS/source/{LM_veml7700.py → modules/LM_veml7700.py} +2 -2
  98. micrOS/source/modules/LM_web.py +38 -0
  99. micrOS/source/urequests.py +39 -15
  100. {toolkit/workspace/precompiled → micrOS/source/web}/dashboard.html +4 -0
  101. micrOS/source/web/editor.js +440 -0
  102. micrOS/source/web/filesui.html +178 -0
  103. micrOS/source/web/filesui.js +338 -0
  104. {toolkit/workspace/precompiled → micrOS/source/web}/index.html +44 -2
  105. micrOS/source/{uapi.js → web/uapi.js} +48 -7
  106. micrOS/source/{ustyle.css → web/ustyle.css} +6 -3
  107. micrOS/utests/__init__.py +0 -0
  108. micrOS/utests/test_scheduler.py +435 -0
  109. {micrOSDevToolKit-2.9.1.data → microsdevtoolkit-2.26.1.data}/scripts/devToolKit.py +33 -3
  110. {micrOSDevToolKit-2.9.1.dist-info → microsdevtoolkit-2.26.1.dist-info}/METADATA +327 -268
  111. microsdevtoolkit-2.26.1.dist-info/RECORD +396 -0
  112. {micrOSDevToolKit-2.9.1.dist-info → microsdevtoolkit-2.26.1.dist-info}/WHEEL +1 -1
  113. toolkit/DevEnvCompile.py +63 -33
  114. toolkit/DevEnvOTA.py +58 -22
  115. toolkit/DevEnvUSB.py +110 -55
  116. toolkit/Gateway.py +6 -6
  117. toolkit/LM_to_compile.dat +6 -4
  118. toolkit/MicrOSDevEnv.py +127 -57
  119. toolkit/WebRepl.py +73 -0
  120. toolkit/dashboard_apps/BackupRestore.py +20 -35
  121. toolkit/dashboard_apps/CCTDemo.py +12 -17
  122. toolkit/dashboard_apps/CCTTest.py +20 -24
  123. toolkit/dashboard_apps/CamStream.py +2 -6
  124. toolkit/dashboard_apps/CatGame.py +14 -16
  125. toolkit/dashboard_apps/Dimmer.py +11 -21
  126. toolkit/dashboard_apps/GetVersion.py +11 -19
  127. toolkit/dashboard_apps/MicrophoneTest.py +1 -6
  128. toolkit/dashboard_apps/NeoEffectsDemo.py +22 -35
  129. toolkit/dashboard_apps/NeopixelTest.py +20 -25
  130. toolkit/dashboard_apps/PresenceTest.py +2 -8
  131. toolkit/dashboard_apps/QMI8685_GYRO.py +68 -0
  132. toolkit/dashboard_apps/RGBTest.py +20 -24
  133. toolkit/dashboard_apps/RoboArm.py +24 -32
  134. toolkit/dashboard_apps/SED_test.py +10 -14
  135. toolkit/dashboard_apps/SensorsTest.py +61 -0
  136. toolkit/dashboard_apps/SystemTest.py +202 -105
  137. toolkit/dashboard_apps/Template_app.py +11 -23
  138. toolkit/dashboard_apps/_app_base.py +34 -0
  139. toolkit/dashboard_apps/_gyro_visualizer.py +78 -0
  140. toolkit/dashboard_apps/uLightDemo.py +15 -24
  141. toolkit/index.html +4 -4
  142. toolkit/lib/LocalMachine.py +6 -1
  143. toolkit/lib/MicrosFiles.py +46 -0
  144. toolkit/lib/Repository.py +64 -0
  145. toolkit/lib/TerminalColors.py +4 -0
  146. toolkit/lib/macroScript.py +6 -0
  147. toolkit/lib/micrOSClient.py +123 -50
  148. toolkit/lib/micrOSClientHistory.py +156 -0
  149. toolkit/lib/pip_package_installer.py +5 -2
  150. toolkit/micrOSdashboard.py +12 -17
  151. toolkit/micrOSlint.py +20 -8
  152. toolkit/simulator_lib/__pycache__/IO_darwin.cpython-312.pyc +0 -0
  153. toolkit/simulator_lib/__pycache__/aioespnow.cpython-312.pyc +0 -0
  154. toolkit/simulator_lib/__pycache__/framebuf.cpython-312.pyc +0 -0
  155. toolkit/simulator_lib/__pycache__/machine.cpython-312.pyc +0 -0
  156. toolkit/simulator_lib/__pycache__/micropython.cpython-312.pyc +0 -0
  157. toolkit/simulator_lib/__pycache__/mip.cpython-312.pyc +0 -0
  158. toolkit/simulator_lib/__pycache__/neopixel.cpython-312.pyc +0 -0
  159. toolkit/simulator_lib/__pycache__/network.cpython-312.pyc +0 -0
  160. toolkit/simulator_lib/__pycache__/sim_common.cpython-312.pyc +0 -0
  161. toolkit/simulator_lib/__pycache__/simgc.cpython-312.pyc +0 -0
  162. toolkit/simulator_lib/__pycache__/simulator.cpython-312.pyc +0 -0
  163. toolkit/simulator_lib/__pycache__/uasyncio.cpython-312.pyc +0 -0
  164. toolkit/simulator_lib/__pycache__/uos.cpython-312.pyc +0 -0
  165. toolkit/simulator_lib/__pycache__/urandom.cpython-312.pyc +0 -0
  166. toolkit/simulator_lib/__pycache__/usocket.cpython-312.pyc +0 -0
  167. toolkit/simulator_lib/__pycache__/ussl.cpython-312.pyc +0 -0
  168. toolkit/simulator_lib/aioespnow.py +28 -0
  169. toolkit/simulator_lib/dht.py +1 -1
  170. toolkit/simulator_lib/framebuf.py +49 -1
  171. toolkit/simulator_lib/machine.py +17 -2
  172. toolkit/simulator_lib/micropython.py +3 -3
  173. toolkit/simulator_lib/mip.py +165 -0
  174. toolkit/simulator_lib/neopixel.py +3 -2
  175. toolkit/simulator_lib/network.py +2 -1
  176. toolkit/simulator_lib/node_config.json +2 -3
  177. toolkit/simulator_lib/ntptime.py +1 -1
  178. toolkit/simulator_lib/{sim_console.py → sim_common.py} +2 -3
  179. toolkit/simulator_lib/simgc.py +6 -2
  180. toolkit/simulator_lib/simulator.py +137 -59
  181. toolkit/simulator_lib/uasyncio.py +33 -2
  182. toolkit/simulator_lib/uos.py +147 -0
  183. toolkit/simulator_lib/urandom.py +4 -0
  184. toolkit/socketClient.py +43 -23
  185. toolkit/user_data/webhooks/generic.py +1 -1
  186. toolkit/user_data/webhooks/macro.py +1 -1
  187. toolkit/user_data/webhooks/template.py +1 -1
  188. toolkit/workspace/precompiled/Auth.mpy +0 -0
  189. toolkit/workspace/precompiled/Common.mpy +0 -0
  190. toolkit/workspace/precompiled/Config.mpy +0 -0
  191. toolkit/workspace/precompiled/Debug.mpy +0 -0
  192. toolkit/workspace/precompiled/Espnow.mpy +0 -0
  193. toolkit/workspace/precompiled/Files.mpy +0 -0
  194. toolkit/workspace/precompiled/Hooks.mpy +0 -0
  195. toolkit/workspace/precompiled/InterConnect.mpy +0 -0
  196. toolkit/workspace/precompiled/Interrupts.mpy +0 -0
  197. toolkit/workspace/precompiled/Logger.mpy +0 -0
  198. toolkit/workspace/precompiled/Network.mpy +0 -0
  199. toolkit/workspace/precompiled/Notify.mpy +0 -0
  200. toolkit/workspace/precompiled/Pacman.mpy +0 -0
  201. toolkit/workspace/precompiled/Scheduler.mpy +0 -0
  202. toolkit/workspace/precompiled/Server.mpy +0 -0
  203. toolkit/workspace/precompiled/Shell.mpy +0 -0
  204. toolkit/workspace/precompiled/Tasks.mpy +0 -0
  205. toolkit/workspace/precompiled/Time.mpy +0 -0
  206. toolkit/workspace/precompiled/Types.mpy +0 -0
  207. toolkit/workspace/precompiled/Web.mpy +0 -0
  208. toolkit/workspace/precompiled/_mpy.version +1 -1
  209. toolkit/workspace/precompiled/config/_git.keep +0 -0
  210. toolkit/workspace/precompiled/helpers.mpy +0 -0
  211. toolkit/workspace/precompiled/micrOS.mpy +0 -0
  212. toolkit/workspace/precompiled/micrOSloader.mpy +0 -0
  213. toolkit/workspace/precompiled/microIO.mpy +0 -0
  214. toolkit/workspace/precompiled/{IO_esp32.mpy → modules/IO_esp32.mpy} +0 -0
  215. toolkit/workspace/precompiled/{IO_esp32c3.mpy → modules/IO_esp32c3.mpy} +0 -0
  216. toolkit/workspace/precompiled/modules/IO_esp32c6.mpy +0 -0
  217. toolkit/workspace/precompiled/{IO_esp32s2.mpy → modules/IO_esp32s2.mpy} +0 -0
  218. toolkit/workspace/precompiled/modules/IO_esp32s3.mpy +0 -0
  219. toolkit/workspace/precompiled/modules/IO_m5stamp.mpy +0 -0
  220. toolkit/workspace/precompiled/modules/IO_qtpy.mpy +0 -0
  221. toolkit/workspace/precompiled/modules/IO_rp2.mpy +0 -0
  222. toolkit/workspace/precompiled/modules/IO_tinypico.mpy +0 -0
  223. toolkit/workspace/precompiled/modules/LM_L298N.mpy +0 -0
  224. {micrOS/source → toolkit/workspace/precompiled/modules}/LM_L9110_DCmotor.py +3 -3
  225. toolkit/workspace/precompiled/modules/LM_OV2640.mpy +0 -0
  226. toolkit/workspace/precompiled/{LM_VL53L0X.py → modules/LM_VL53L0X.py} +3 -3
  227. toolkit/workspace/precompiled/{LM_aht10.mpy → modules/LM_aht10.mpy} +0 -0
  228. toolkit/workspace/precompiled/{LM_bme280.mpy → modules/LM_bme280.mpy} +0 -0
  229. toolkit/workspace/precompiled/{LM_buzzer.mpy → modules/LM_buzzer.mpy} +0 -0
  230. toolkit/workspace/precompiled/modules/LM_cct.mpy +0 -0
  231. toolkit/workspace/precompiled/modules/LM_cluster.mpy +0 -0
  232. toolkit/workspace/precompiled/{LM_co2.mpy → modules/LM_co2.mpy} +0 -0
  233. toolkit/workspace/precompiled/{LM_dht11.mpy → modules/LM_dht11.mpy} +0 -0
  234. toolkit/workspace/precompiled/{LM_dht22.mpy → modules/LM_dht22.mpy} +0 -0
  235. toolkit/workspace/precompiled/modules/LM_dimmer.mpy +0 -0
  236. toolkit/workspace/precompiled/modules/LM_distance.mpy +0 -0
  237. toolkit/workspace/precompiled/{LM_ds18.mpy → modules/LM_ds18.mpy} +0 -0
  238. toolkit/workspace/precompiled/{LM_esp32.py → modules/LM_esp32.py} +5 -0
  239. toolkit/workspace/precompiled/modules/LM_espnow.py +53 -0
  240. toolkit/workspace/precompiled/modules/LM_fileserver.mpy +0 -0
  241. toolkit/workspace/precompiled/{LM_gameOfLife.mpy → modules/LM_gameOfLife.mpy} +0 -0
  242. toolkit/workspace/precompiled/modules/LM_genIO.mpy +0 -0
  243. toolkit/workspace/precompiled/{LM_haptic.mpy → modules/LM_haptic.mpy} +0 -0
  244. {micrOS/source → toolkit/workspace/precompiled/modules}/LM_i2c.py +5 -4
  245. toolkit/workspace/precompiled/modules/LM_i2s_mic.mpy +0 -0
  246. toolkit/workspace/precompiled/{LM_ld2410.mpy → modules/LM_ld2410.mpy} +0 -0
  247. toolkit/workspace/precompiled/modules/LM_light_sensor.mpy +0 -0
  248. toolkit/workspace/precompiled/modules/LM_mh_z19c.py +198 -0
  249. toolkit/workspace/precompiled/modules/LM_neoeffects.mpy +0 -0
  250. toolkit/workspace/precompiled/modules/LM_neopixel.mpy +0 -0
  251. toolkit/workspace/precompiled/{LM_oled.mpy → modules/LM_oled.mpy} +0 -0
  252. toolkit/workspace/precompiled/{LM_oled_sh1106.mpy → modules/LM_oled_sh1106.mpy} +0 -0
  253. toolkit/workspace/precompiled/modules/LM_oled_ui.mpy +0 -0
  254. toolkit/workspace/precompiled/modules/LM_pacman.mpy +0 -0
  255. toolkit/workspace/precompiled/modules/LM_presence.mpy +0 -0
  256. toolkit/workspace/precompiled/modules/LM_qmi8658.py +204 -0
  257. toolkit/workspace/precompiled/{LM_rencoder.py → modules/LM_rencoder.py} +2 -2
  258. toolkit/workspace/precompiled/modules/LM_rest.mpy +0 -0
  259. toolkit/workspace/precompiled/modules/LM_rgb.mpy +0 -0
  260. toolkit/workspace/precompiled/{LM_rgbcct.mpy → modules/LM_rgbcct.mpy} +0 -0
  261. toolkit/workspace/precompiled/modules/LM_roboarm.mpy +0 -0
  262. toolkit/workspace/precompiled/modules/LM_robustness.py +137 -0
  263. toolkit/workspace/precompiled/{LM_servo.mpy → modules/LM_servo.mpy} +0 -0
  264. toolkit/workspace/precompiled/{LM_sound_event.mpy → modules/LM_sound_event.mpy} +0 -0
  265. toolkit/workspace/precompiled/{LM_stepper.mpy → modules/LM_stepper.mpy} +0 -0
  266. toolkit/workspace/precompiled/modules/LM_switch.mpy +0 -0
  267. toolkit/workspace/precompiled/modules/LM_system.mpy +0 -0
  268. toolkit/workspace/precompiled/modules/LM_tcs3472.py +187 -0
  269. toolkit/workspace/precompiled/modules/LM_telegram.mpy +0 -0
  270. toolkit/workspace/precompiled/{LM_tinyrgb.mpy → modules/LM_tinyrgb.mpy} +0 -0
  271. toolkit/workspace/precompiled/{LM_trackball.mpy → modules/LM_trackball.mpy} +0 -0
  272. toolkit/workspace/precompiled/{LM_veml7700.mpy → modules/LM_veml7700.mpy} +0 -0
  273. toolkit/workspace/precompiled/modules/LM_web.mpy +0 -0
  274. toolkit/workspace/precompiled/urequests.mpy +0 -0
  275. {micrOS/source → toolkit/workspace/precompiled/web}/dashboard.html +4 -0
  276. toolkit/workspace/precompiled/web/editor.js +440 -0
  277. toolkit/workspace/precompiled/web/filesui.html +178 -0
  278. toolkit/workspace/precompiled/web/filesui.js +338 -0
  279. {micrOS/source → toolkit/workspace/precompiled/web}/index.html +44 -2
  280. toolkit/workspace/precompiled/{uapi.js → web/uapi.js} +48 -7
  281. toolkit/workspace/precompiled/{ustyle.css → web/ustyle.css} +6 -3
  282. micrOS/micropython/esp32-20241129-v1.24.1.bin +0 -0
  283. micrOS/micropython/esp32c3-20240222-v1.22.2.bin +0 -0
  284. micrOS/micropython/esp32s2-20240602-v1.23.0.bin +0 -0
  285. micrOS/micropython/esp32s2-LOLIN_MINI-20220618-v1.19.1.bin +0 -0
  286. micrOS/micropython/esp32s2-LOLIN_MINI-20240602-v1.23.0.bin +0 -0
  287. micrOS/micropython/esp32s3-20240105-v1.22.1.bin +0 -0
  288. micrOS/micropython/esp32s3_spiram_oct-20231005-v1.21.0.bin +0 -0
  289. micrOS/micropython/esp32s3_spiram_oct-20241129-v1.24.1.bin +0 -0
  290. micrOS/micropython/rpi-pico-w-20241129-v1.24.1.uf2 +0 -0
  291. micrOS/micropython/tinypico-20241129-v1.24.1.bin +0 -0
  292. micrOS/source/LM_L298N_DCmotor.py +0 -86
  293. micrOS/source/LM_catgame.py +0 -75
  294. micrOS/source/LM_dashboard_be.py +0 -37
  295. micrOS/source/LM_demo.py +0 -97
  296. micrOS/source/LM_espnow.py +0 -23
  297. micrOS/source/LM_intercon.py +0 -57
  298. micrOS/source/LM_keychain.py +0 -322
  299. micrOS/source/LM_lmpacman.py +0 -126
  300. micrOS/source/LM_neoeffects.py +0 -331
  301. micrOS/source/LM_oledui.py +0 -972
  302. micrOS/source/LM_pet_feeder.py +0 -78
  303. micrOS/source/LM_ph_sensor.py +0 -51
  304. micrOS/source/LM_robustness.py +0 -74
  305. micrOS/source/reset.py +0 -11
  306. micrOSDevToolKit-2.9.1.dist-info/RECORD +0 -365
  307. toolkit/dashboard_apps/AirQualityBME280.py +0 -36
  308. toolkit/dashboard_apps/AirQualityDHT22_CO2.py +0 -36
  309. toolkit/lib/file_extensions.py +0 -16
  310. toolkit/simulator_lib/__pycache__/sim_console.cpython-312.pyc +0 -0
  311. toolkit/simulator_lib/__pycache__/sim_console.cpython-38.pyc +0 -0
  312. toolkit/simulator_lib/__pycache__/sim_console.cpython-39.pyc +0 -0
  313. toolkit/workspace/precompiled/IO_esp32s3.mpy +0 -0
  314. toolkit/workspace/precompiled/IO_m5stamp.mpy +0 -0
  315. toolkit/workspace/precompiled/IO_qtpy.mpy +0 -0
  316. toolkit/workspace/precompiled/IO_rp2.mpy +0 -0
  317. toolkit/workspace/precompiled/IO_tinypico.mpy +0 -0
  318. toolkit/workspace/precompiled/LM_L298N_DCmotor.mpy +0 -0
  319. toolkit/workspace/precompiled/LM_OV2640.mpy +0 -0
  320. toolkit/workspace/precompiled/LM_catgame.py +0 -75
  321. toolkit/workspace/precompiled/LM_cct.mpy +0 -0
  322. toolkit/workspace/precompiled/LM_dashboard_be.py +0 -37
  323. toolkit/workspace/precompiled/LM_demo.py +0 -97
  324. toolkit/workspace/precompiled/LM_dimmer.mpy +0 -0
  325. toolkit/workspace/precompiled/LM_distance.mpy +0 -0
  326. toolkit/workspace/precompiled/LM_espnow.py +0 -23
  327. toolkit/workspace/precompiled/LM_genIO.mpy +0 -0
  328. toolkit/workspace/precompiled/LM_i2s_mic.mpy +0 -0
  329. toolkit/workspace/precompiled/LM_intercon.mpy +0 -0
  330. toolkit/workspace/precompiled/LM_keychain.mpy +0 -0
  331. toolkit/workspace/precompiled/LM_light_sensor.mpy +0 -0
  332. toolkit/workspace/precompiled/LM_lmpacman.mpy +0 -0
  333. toolkit/workspace/precompiled/LM_neoeffects.mpy +0 -0
  334. toolkit/workspace/precompiled/LM_neopixel.mpy +0 -0
  335. toolkit/workspace/precompiled/LM_oled_ui.mpy +0 -0
  336. toolkit/workspace/precompiled/LM_oledui.mpy +0 -0
  337. toolkit/workspace/precompiled/LM_pet_feeder.py +0 -78
  338. toolkit/workspace/precompiled/LM_ph_sensor.py +0 -51
  339. toolkit/workspace/precompiled/LM_presence.mpy +0 -0
  340. toolkit/workspace/precompiled/LM_rest.mpy +0 -0
  341. toolkit/workspace/precompiled/LM_rgb.mpy +0 -0
  342. toolkit/workspace/precompiled/LM_roboarm.mpy +0 -0
  343. toolkit/workspace/precompiled/LM_robustness.py +0 -74
  344. toolkit/workspace/precompiled/LM_switch.mpy +0 -0
  345. toolkit/workspace/precompiled/LM_system.mpy +0 -0
  346. toolkit/workspace/precompiled/LM_telegram.mpy +0 -0
  347. toolkit/workspace/precompiled/node_config.json +0 -1
  348. toolkit/workspace/precompiled/reset.mpy +0 -0
  349. /micrOS/source/{IO_esp32.py → modules/IO_esp32.py} +0 -0
  350. /micrOS/source/{IO_esp32c3.py → modules/IO_esp32c3.py} +0 -0
  351. /micrOS/source/{IO_esp32s2.py → modules/IO_esp32s2.py} +0 -0
  352. /micrOS/source/{IO_rp2.py → modules/IO_rp2.py} +0 -0
  353. /micrOS/source/{LM_gameOfLife.py → modules/LM_gameOfLife.py} +0 -0
  354. /micrOS/source/{LM_rgbcct.py → modules/LM_rgbcct.py} +0 -0
  355. /micrOS/source/{LM_rp2w.py → modules/LM_rp2w.py} +0 -0
  356. /micrOS/source/{LM_sdcard.py → modules/LM_sdcard.py} +0 -0
  357. /micrOS/source/{LM_sound_event.py → modules/LM_sound_event.py} +0 -0
  358. /micrOS/source/{LM_tinyrgb.py → modules/LM_tinyrgb.py} +0 -0
  359. /micrOS/source/{udashboard.js → web/udashboard.js} +0 -0
  360. /micrOS/source/{uwidgets.js → web/uwidgets.js} +0 -0
  361. /micrOS/source/{uwidgets_pro.js → web/uwidgets_pro.js} +0 -0
  362. {micrOSDevToolKit-2.9.1.dist-info → microsdevtoolkit-2.26.1.dist-info/licenses}/LICENSE +0 -0
  363. {micrOSDevToolKit-2.9.1.dist-info → microsdevtoolkit-2.26.1.dist-info}/top_level.txt +0 -0
  364. /toolkit/workspace/precompiled/{LM_rp2w.py → modules/LM_rp2w.py} +0 -0
  365. /toolkit/workspace/precompiled/{LM_sdcard.py → modules/LM_sdcard.py} +0 -0
  366. /toolkit/workspace/precompiled/{udashboard.js → web/udashboard.js} +0 -0
  367. /toolkit/workspace/precompiled/{uwidgets.js → web/uwidgets.js} +0 -0
  368. /toolkit/workspace/precompiled/{uwidgets_pro.js → web/uwidgets_pro.js} +0 -0
micrOS/source/Logger.py CHANGED
@@ -5,32 +5,49 @@ Module is responsible for System and User logging
5
5
  Designed by Marcell Ban aka BxNxM
6
6
  """
7
7
  from time import localtime
8
- from os import listdir, remove
8
+ from re import match
9
+ from uos import remove
10
+ from Files import OSPath, path_join, ilist_fs, is_dir
9
11
 
10
12
  #############################################
11
13
  # LOGGING WITH DATA ROTATION #
12
14
  #############################################
13
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
14
21
 
15
- def logger(data, f_name, limit):
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):
16
34
  """
17
- Create generic logger function
18
- - implements log line rotation
19
- - automatic time stump
20
- :param data: input string data to log
35
+ Generic logger function with line rotation and time
36
+ :param data: data to log
21
37
  :param f_name: file name to use
22
38
  :param limit: line limit for log rotation
23
39
  return write verdict - true / false
24
40
  INFO: hardcoded max data number = 30
25
41
  """
26
- def _logger(_data, _f_name, _limit, f_mode='r+'):
27
- _limit = 30 if _limit > 30 else _limit
42
+ def _logger(f_mode='r+'):
43
+ nonlocal data, f_path, limit
44
+ limit = min(limit, 30) # Hardcoded max data line = 30
28
45
  # [1] GET TIME STUMP
29
46
  ts_buff = [str(k) for k in localtime()]
30
47
  ts = ".".join(ts_buff[0:3]) + "-" + ":".join(ts_buff[3:6])
31
48
  # [2] OPEN FILE - WRITE DATA WITH TS
32
- with open(_f_name, f_mode) as f:
33
- _data = f"{ts} {_data}\n"
49
+ with open(f_path, f_mode) as f:
50
+ _data = f"{ts} {data}\n"
34
51
  # read file lines and filter by time stump chunks (hack for replace truncate)
35
52
  lines = [_l for _l in f.readlines() if '-' in _l and '.' in _l]
36
53
  # get file params
@@ -38,42 +55,43 @@ def logger(data, f_name, limit):
38
55
  lines.append(_data)
39
56
  f.seek(0)
40
57
  # line data rotate
41
- if lines_len >= _limit:
42
- lines = lines[-_limit:]
43
- lines_str = ''.join(lines)
44
- else:
45
- lines_str = ''.join(lines)
58
+ if lines_len >= limit:
59
+ lines = lines[-limit:]
46
60
  # write file
47
- f.write(lines_str)
61
+ f.write(''.join(lines))
48
62
 
63
+ f_path = path_join(_dir_select(f_name), f_name)
49
64
  # Run logger
50
65
  try:
51
66
  # There is file - append 'r+'
52
- _logger(data, f_name, limit)
67
+ _logger()
53
68
  except:
54
69
  try:
55
70
  # There is no file - create 'a+'
56
- _logger(data, f_name, limit, 'a+')
71
+ _logger('a+')
57
72
  except:
58
73
  return False
59
74
  return True
60
75
 
61
76
 
62
- def log_get(f_name, msgobj=None):
77
+ def log_get(f_name:str, msgobj=None):
63
78
  """
64
- Get and stream (ver osocket/stdout) .log file's content and count "critical" errors
65
- - critical error tag in log line: [ERR]
79
+ Generic file getter for .log files
80
+ - log content critical [ERR] counter
66
81
  """
82
+ f_path = path_join(_dir_select(f_name), f_name)
67
83
  err_cnt = 0
68
84
  try:
69
- with open(f_name, 'r') as f:
85
+ if msgobj is not None:
86
+ msgobj(f_path)
87
+ with open(f_path, 'r') as f:
70
88
  eline = f.readline().strip()
71
89
  while eline:
72
90
  # GET error from log line (tag: [ERR])
73
91
  err_cnt += 1 if "[ERR]" in eline else 0
74
92
  # GIVE BACK .log file contents
75
93
  if msgobj is not None:
76
- msgobj(eline)
94
+ msgobj(f"\t{eline}")
77
95
  eline = f.readline().strip()
78
96
  except:
79
97
  pass
@@ -81,14 +99,33 @@ def log_get(f_name, msgobj=None):
81
99
 
82
100
 
83
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
+ """
84
107
  if data is None:
85
- return log_get('err.log', msgobj)
86
- return logger(data, 'err.log', limit=6)
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)
87
116
 
88
117
 
89
118
  def log_clean(msgobj=None):
90
- to_del = [file for file in listdir() if file.endswith('.log')]
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')]
91
124
  for _del in to_del:
125
+ _del = path_join(logs_dir, _del)
92
126
  if msgobj is not None:
93
127
  msgobj(f" Delete: {_del}")
94
128
  remove(_del)
129
+
130
+ # Init log folder at module load
131
+ _init_logger()
micrOS/source/Network.py CHANGED
@@ -19,7 +19,8 @@ from utime import sleep_ms
19
19
  from network import AP_IF, STA_IF, WLAN
20
20
  from machine import unique_id
21
21
  from Config import cfgget, cfgput
22
- from Debug import console_write, errlog_add
22
+ from Debug import console_write, syslog
23
+ from microIO import detect_platform
23
24
 
24
25
 
25
26
  class NW:
@@ -48,23 +49,36 @@ def ifconfig():
48
49
 
49
50
 
50
51
  def set_dev_uid():
52
+ if detect_platform() == "esp32c6":
53
+ # ESP32-C6: unique_id() not unique (can return same ID on different boards)
54
+ try:
55
+ sta = WLAN(STA_IF)
56
+ was = sta.active()
57
+ if not was: sta.active(True)
58
+ uid = hexlify(sta.config('mac')).decode()
59
+ if not was: sta.active(False)
60
+ cfgput('hwuid', f"micr{uid}OS")
61
+ return
62
+ except Exception as e:
63
+ syslog(f"[ERR] set_dev_uid (esp32c6): {e}")
64
+ # Legacy micrOS device UID generation (+fallback)
51
65
  try:
52
66
  cfgput('hwuid', f'micr{hexlify(unique_id()).decode("utf-8")}OS')
53
67
  except Exception as e:
54
- errlog_add(f"[ERR] set_dev_uid error: {e}")
68
+ syslog(f"[ERR] set_dev_uid: {e}")
55
69
 
56
70
 
57
71
  def get_mac():
58
- return WLAN().config('mac')
72
+ """ Get AP/STA mac address as raw binary data"""
73
+ return NW.NIF.config('mac')
59
74
 
60
75
  #################################################################
61
76
  # SET WIFI STA MODE #
62
77
  #################################################################
63
78
 
64
79
 
65
- def __select_available_wifi_nw(sta_if, raw_essid, raw_pwd):
80
+ def _select_available_wifi_nw(raw_essid:str, raw_pwd:str):
66
81
  """
67
- raw_essid: essid parameter, in case of multiple values separator is ;
68
82
  raw_pwd: essid pwd parameter, in case of multiple values separator is ;
69
83
  return detected essid with corresponding password
70
84
  """
@@ -72,18 +86,18 @@ def __select_available_wifi_nw(sta_if, raw_essid, raw_pwd):
72
86
  essid = essid.strip()
73
87
  # Scan wifi network - retry workaround
74
88
  for _ in range(0, 2):
75
- if essid in (wifispot[0].decode('utf-8') for wifispot in sta_if.scan()):
89
+ if essid in (wifispot[0].decode('utf-8') for wifispot in NW.NIF.scan()):
76
90
  console_write(f'\t| - [NW: STA] ESSID WAS FOUND: {essid}')
77
91
  try:
78
92
  return essid, str(raw_pwd.split(';')[idx]).strip()
79
93
  except Exception as e:
80
- errlog_add(f'[ERR][SET STA] stapwd config error: {e}')
94
+ syslog(f'[ERR][SET STA] stapwd config error: {e}')
81
95
  sleep_ms(400)
82
96
  return None, ''
83
97
 
84
98
 
85
- def set_wifi(essid, pwd, timeout=60):
86
- console_write(f'[NW: STA] SET WIFI STA NW {essid}')
99
+ def set_wifi(essid:str, pwd:str, timeout=60):
100
+ console_write('[NW: STA] Enable')
87
101
 
88
102
  # Disable AP mode
89
103
  ap_if = WLAN(AP_IF)
@@ -94,18 +108,25 @@ def set_wifi(essid, pwd, timeout=60):
94
108
  # Set STA and Connect
95
109
  sta_if = WLAN(STA_IF)
96
110
  sta_if.active(True)
111
+ NW.NIF = sta_if
97
112
  # Handle rsp2-w limitation (try)
98
113
  try:
99
114
  # Set custom DHCP hostname for dhcp name resolve
100
115
  sta_if.config(dhcp_hostname=cfgget('devfid'))
101
116
  except Exception as e:
102
- console_write(f"dhcp_hostname conf error: {e}")
117
+ syslog(f"[ERR] STA dhcp_hostname: {e}")
118
+ if cfgget("espnow"):
119
+ try:
120
+ # prevents Wi-Fi PS from dropping ESP-NOW frames while STA is connected.
121
+ sta_if.config(pm=sta_if.PM_NONE)
122
+ except Exception as e:
123
+ syslog(f"[ERR] ESPNow STA PM_NONE: {e}")
103
124
  # Check are we already connected
104
125
  if sta_if.isconnected():
105
126
  console_write(f"\t| [NW: STA] ALREADY CONNECTED TO {essid}")
106
127
  else:
107
128
  # Multiple essid and pwd handling with retry mechanism
108
- essid, pwd = __select_available_wifi_nw(sta_if, essid, pwd)
129
+ essid, pwd = _select_available_wifi_nw(essid, pwd)
109
130
 
110
131
  # Connect to the located wifi network
111
132
  if essid is not None:
@@ -118,7 +139,7 @@ def set_wifi(essid, pwd, timeout=60):
118
139
  timeout -= 1
119
140
  sleep_ms(500)
120
141
  # Set static IP - here because some data comes from connection. (subnet, etc.)
121
- if sta_if.isconnected() and __set_wifi_dev_static_ip(sta_if):
142
+ if sta_if.isconnected() and _set_wifi_dev_static_ip(sta_if):
122
143
  sta_if.disconnect()
123
144
  del sta_if
124
145
  return set_wifi(essid, pwd)
@@ -131,11 +152,10 @@ def set_wifi(essid, pwd, timeout=60):
131
152
  # Store STA IP (make it static ip)
132
153
  cfgput("devip", str(sta_if.ifconfig()[0]))
133
154
  set_dev_uid()
134
- NW.NIF = sta_if
135
155
  return sta_if.isconnected()
136
156
 
137
157
 
138
- def __set_wifi_dev_static_ip(sta_if):
158
+ def _set_wifi_dev_static_ip(sta_if:STA_IF):
139
159
  console_write("[NW: STA] Set device static IP.")
140
160
  stored_ip = cfgget('devip')
141
161
  if 'n/a' not in stored_ip.lower() and '.' in stored_ip:
@@ -149,7 +169,7 @@ def __set_wifi_dev_static_ip(sta_if):
149
169
  sta_if.ifconfig(tuple(conn_ips))
150
170
  return True # was reconfigured
151
171
  except Exception as e:
152
- errlog_add(f"[ERR][STA] StaticIP conf failed: {e}")
172
+ syslog(f"[ERR][STA] StaticIP conf failed: {e}")
153
173
  else:
154
174
  console_write(f"[NW: STA][SKIP] StaticIP conf.: {stored_ip} ? {conn_ips[0]}")
155
175
  else:
@@ -162,7 +182,7 @@ def __set_wifi_dev_static_ip(sta_if):
162
182
  #################################################################
163
183
 
164
184
 
165
- def set_access_point(_essid, _pwd, _authmode=3):
185
+ def set_access_point(_essid:str, _pwd:str, _authmode:int=3):
166
186
  console_write(f"[NW: AP] SET AP MODE: {_essid} - {_pwd} - auth mode: {_authmode} (if possible)")
167
187
 
168
188
  sta_if = WLAN(STA_IF)
@@ -171,6 +191,7 @@ def set_access_point(_essid, _pwd, _authmode=3):
171
191
 
172
192
  ap_if = WLAN(AP_IF)
173
193
  ap_if.active(True)
194
+ NW.NIF = ap_if
174
195
  # Set WiFi access point name (formally known as ESSID) and WiFi authmode (3): WPA2-PSK
175
196
  try:
176
197
  # Config #1 (esp)
@@ -184,12 +205,11 @@ def set_access_point(_essid, _pwd, _authmode=3):
184
205
  # Config #2 (rp2-w)???
185
206
  ap_if.config(essid=_essid, password=_pwd)
186
207
  except Exception as e2:
187
- errlog_add(f"[ERR][AP] config failed: {e2}")
208
+ syslog(f"[ERR][AP] config failed: {e2}")
188
209
  if not (ap_if.active() and str(ap_if.config('essid')) == str(_essid)):
189
- errlog_add("[ERR][AP] error")
210
+ syslog("[ERR][AP] error")
190
211
  console_write(f"\t|\t| [NW: AP] network config: {str(ap_if.ifconfig())}")
191
212
  set_dev_uid()
192
- NW.NIF = ap_if
193
213
  return ap_if.active()
194
214
 
195
215
  #################################################################
@@ -228,7 +248,7 @@ def sta_high_avail():
228
248
  raw_essid = cfgget("staessid")
229
249
  wifi_avail = False
230
250
  # [CHECK 2] check known network is available
231
- for idx, essid in enumerate(raw_essid.split(';')):
251
+ for essid in raw_essid.split(';'):
232
252
  essid = essid.strip()
233
253
  # Scan wifi network - retry workaround
234
254
  for _ in range(0, 2):
@@ -241,7 +261,7 @@ def sta_high_avail():
241
261
  if wifi_avail or not ap_if.active():
242
262
  # ACTION: Restart micrOS node (boot phase automatically detects nw mode)
243
263
  from machine import reset
244
- console_write("[Restart] network repair")
264
+ syslog("[WARN] Restart, network repair")
245
265
  reset()
246
266
  return f'{cfgget("nwmd")} mode NOK, wifi avail: {wifi_avail}'
247
267
  return f'{cfgget("nwmd")} mode OK'
micrOS/source/Notify.py CHANGED
@@ -6,12 +6,13 @@ Common:
6
6
  - lm_execute
7
7
  Supported notification subscribers (add_subscriber)
8
8
  - LM_telegram
9
+ - LM_mqtt_client
9
10
  Designed by Marcell Ban aka BxNxM
10
11
  """
11
12
 
12
13
  from Config import cfgget
13
14
  from Tasks import lm_exec, lm_is_loaded
14
- from Debug import errlog_add
15
+ from Debug import syslog
15
16
 
16
17
  #########################################
17
18
  # micrOS Notifications #
@@ -33,44 +34,69 @@ class Notify:
33
34
  raise Exception("Subscribe error, Notify parent missing")
34
35
 
35
36
  @staticmethod
36
- def message(text, reply_to=None, chat_id=None):
37
+ def send_msg(text, *args, **kwargs):
37
38
  """
38
- Send message to all subscribers
39
+ This method has to be implemented by the child class
39
40
  """
40
- exit_code = 0
41
+ raise NotImplementedError("Child class must implement send_msg method")
42
+
43
+ @staticmethod
44
+ def message(text, *args, **kwargs):
45
+ """
46
+ Send message to all subscribers - Notify send_msg(text, ...) agents
47
+ :param text: text message to send
48
+ :param channels (optional): select communication interface(s) by class name
49
+ e.g. "Telegram", "MQTT" or an iterable of these.
50
+ If omitted or empty, sends over all available channels.
51
+ Telegram params (optional):
52
+ reply_to: message id to reply to (optional) - default: None
53
+ chat_id: chat identifier - default: None -> auto resolve in child class
54
+ MQTT client params (optional):
55
+ topic: mqtt topic to send the message - default: None -> auto resolve in child class
56
+ return: verdict and metrics
57
+ """
58
+ errors, channels, interfaces = 0, kwargs.get("channels", ()), set()
59
+ channels = (channels,) if isinstance(channels, str) else tuple(channels)
41
60
  for s in Notify._SUBSCRIBERS:
61
+ name = s.__class__.__name__
42
62
  try:
43
- s.send_msg(text, reply_to, chat_id)
63
+ if len(channels) == 0 or name in channels:
64
+ s.send_msg(text, *args, **kwargs)
65
+ interfaces.add(name)
44
66
  except Exception as e:
45
- errlog_add(f"[ERR] Notify: {e}")
46
- exit_code+=1
47
- return f"Sent N{len(Notify._SUBSCRIBERS)} ({exit_code})"
67
+ syslog(f"[ERR] Notify.{name}: {e}")
68
+ errors+=1
69
+ return (f"Sent over {', '.join(interfaces)} ({len(interfaces)}/{len(Notify._SUBSCRIBERS)}) client(s)"
70
+ f" - errors: ({errors})")
48
71
 
49
72
  @staticmethod
50
73
  def notifications(state=None):
51
74
  """
52
- Setter for disable/enable notification messages
75
+ Setter for disable/enable notification messages (over LM_system)
76
+ :param state: True/False/ None(default) - show current state
53
77
  """
54
78
  if isinstance(state, bool):
55
79
  Notify.GLOBAL_NOTIFY = state
56
- return f"Notifications: {'enabled' if Notify.GLOBAL_NOTIFY else 'disabled'}"
80
+ targets = ", ".join(s.__class__.__name__ for s in Notify._SUBSCRIBERS)
81
+ return f"Notifications[{targets}]: {'enabled' if Notify.GLOBAL_NOTIFY else 'disabled'}"
57
82
 
58
83
  @staticmethod
59
- def notify(text, reply_to=None, chat_id=None):
84
+ def notify(text, *args, **kwargs):
60
85
  """
61
- Notification sender
86
+ Notification sender for Load Modules
62
87
  """
63
88
  if Notify.GLOBAL_NOTIFY:
64
- return Notify.message(text, reply_to, chat_id)
89
+ return Notify.message(text, *args, **kwargs)
65
90
  return "Notifications disabled"
66
91
 
67
92
  @staticmethod
68
- def lm_execute(cmd_args):
69
- """Executor with basic access handling"""
70
- if lm_is_loaded(cmd_args[0]):
71
- try:
72
- _, out = lm_exec(cmd_args)
73
- except Exception as e:
74
- out = str(e)
75
- return True, out
76
- return False, cmd_args[0]
93
+ def lm_execute(cmd_args, jsonify=False, secure=True):
94
+ """Load Module Executor with basic access handling"""
95
+ state = False
96
+ if secure and not lm_is_loaded(cmd_args[0]):
97
+ return state, f"NotAllowed {cmd_args[0]}"
98
+ try:
99
+ state, out = lm_exec(cmd_args, jsonify)
100
+ except Exception as e:
101
+ out = str(e)
102
+ return state, out