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
@@ -0,0 +1,178 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Files</title>
6
+ <!-- Mobile viewport -->
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
8
+ <!-- Base micrOS style -->
9
+ <link rel="stylesheet" href="../ustyle.css">
10
+
11
+ <!-- Files UI layout-only CSS -->
12
+ <style>
13
+ /* Main layout */
14
+ #ui {
15
+ display: flex;
16
+ gap: 40px;
17
+ height: 100%;
18
+ max-width: 95%;
19
+ }
20
+ #folders {
21
+ width: clamp(120px, 20vw, 200px);
22
+ flex-shrink: 0;
23
+ display: flex;
24
+ flex-direction: column;
25
+ }
26
+ /* Disk bar on top of sidebar */
27
+ #diskbar {
28
+ position: sticky;
29
+ top: 0;
30
+ margin-bottom: 12px;
31
+ padding: 6px 10px;
32
+ font-size: 12px;
33
+ background: rgba(255,255,255,.1);
34
+ border-radius: 6px;
35
+ backdrop-filter: blur(2px);
36
+ z-index: 5;
37
+ }
38
+ /* Disk Usage Widget */
39
+ #diskmeter {
40
+ height: 6px;
41
+ background: rgba(255,255,255,.2);
42
+ border-radius: 3px;
43
+ overflow: hidden;
44
+ }
45
+ #diskused {
46
+ height: 100%;
47
+ width: 0%;
48
+ background: #4caf50;
49
+ }
50
+ /* Files column */
51
+ #files {
52
+ flex: 1;
53
+ min-width: 0;
54
+ display: flex;
55
+ flex-direction: column;
56
+ }
57
+ /* Always-visible header in Files */
58
+ #files-header {
59
+ position: sticky;
60
+ top: 0;
61
+ z-index: 5;
62
+ padding-bottom: 8px;
63
+ background: rgba(255,255,255,.1);
64
+ border-radius: 6px;
65
+ backdrop-filter: blur(2px);
66
+ }
67
+ /* Toolbar */
68
+ #top {
69
+ display: flex;
70
+ align-items: center;
71
+ gap: 8px;
72
+ min-height: 44px;
73
+ flex-wrap: wrap;
74
+ }
75
+ #top input[type="file"] {
76
+ max-width: 100%;
77
+ }
78
+ /* Scrollable file list ONLY */
79
+ #list {
80
+ flex: 1;
81
+ overflow-y: auto;
82
+ }
83
+ #list div {
84
+ padding: 6px 8px;
85
+ border-radius: 4px;
86
+ cursor: pointer;
87
+ word-break: break-word;
88
+ }
89
+ #list div:hover {
90
+ background: rgba(255,255,255,.1);
91
+ }
92
+ /* Default selection style (files, editor, etc) */
93
+ .sel {
94
+ background: color-mix(in srgb, white 40%, transparent);
95
+ box-shadow: inset 0 0 0 2px color-mix(in srgb, white 60%, transparent);
96
+ }
97
+ /* Softer selection for folders only */
98
+ #folder-path .sel {
99
+ background: color-mix(in srgb, white 15%, transparent);
100
+ box-shadow: none;
101
+ }
102
+ /* Folder list spacing */
103
+ #folder-path {
104
+ display: flex;
105
+ flex-direction: column;
106
+ gap: 5px;
107
+ }
108
+ /* Folder item padding + touch-friendly */
109
+ #folder-path .dir-item {
110
+ padding: 5px 6px; /*makes them easier to tap*/
111
+ border-radius: 3px;
112
+ cursor: pointer;
113
+ }
114
+ /* Hover effect for folders */
115
+ #folder-path .dir-item:hover {
116
+ background: rgba(255,255,255,.08);
117
+ }
118
+ .folders {
119
+ margin-bottom: 8px;
120
+ }
121
+ /* Keep Folders title + list sticky as ONE block under disk bar */
122
+ #folders-sticky {
123
+ position: sticky;
124
+ top: 60px; /* sits just below diskbar */
125
+ z-index: 4;
126
+ }
127
+ /* directory file listing effect */
128
+ #list.loading {
129
+ filter: blur(3px);
130
+ opacity: 0.5;
131
+ pointer-events: none; /* prevents clicking while loading */
132
+ transition: filter 0.15s ease, opacity 0.15s ease;
133
+ }
134
+ </style>
135
+ </head>
136
+
137
+ <body>
138
+ <h1> micrOS Files </h1>
139
+
140
+ <div id="ui">
141
+ <!-- Left sidebar (fixed, no scroll) -->
142
+ <aside id="folders">
143
+ <header id="diskbar">
144
+ <div id="disktext">Disk: — MB used / — MB free</div>
145
+ <div id="diskmeter">
146
+ <div id="diskused"></div>
147
+ </div>
148
+ </header>
149
+
150
+ <!-- Sticky folder block -->
151
+ <div id="folders-sticky">
152
+ <div class="folders">📂 Folders</div>
153
+ <div id="folder-path">/user_data</div>
154
+ </div>
155
+ </aside>
156
+
157
+ <!-- Files column -->
158
+ <main id="files">
159
+ <!-- Sticky files header -->
160
+ <div id="files-header">
161
+ <div id="top">
162
+ <input type="file" id="file">
163
+ <button onclick="uploadFile()">🔼 Upload</button>
164
+ <button onclick="openFile()">📖 Open</button>
165
+ <button onclick="download()">🔽 Download</button>
166
+ <button onclick="deleteFile()"> 🗑️ Delete</button>
167
+ <button onclick="editor()">📄 Edit</button>
168
+ </div>
169
+ </div>
170
+
171
+ <!-- Only this scrolls -->
172
+ <div id="list"></div>
173
+ </main>
174
+ </div>
175
+
176
+ <script src="../filesui.js"></script>
177
+ </body>
178
+ </html>
@@ -0,0 +1,338 @@
1
+ let selected = null;
2
+ let selectedEl = null; // DOM element of selected file row
3
+ let selectedDir = 'user_data'; // fallback
4
+ let _editorScriptLoaded = false;
5
+ let editorFile = null; // 🔹 track what's currently opened in editor
6
+
7
+ // 🔹 Simple root message output
8
+ let _msgTimer, _fadeTimer;
9
+ function popUpMsg(msg) {
10
+ let el = document.getElementById('root-message');
11
+ if (!el) {
12
+ el = document.createElement('div');
13
+ el.id = 'root-message';
14
+ Object.assign(el.style, {
15
+ position: 'fixed',
16
+ top: '8px',
17
+ left: '50%',
18
+ transform: 'translateX(-50%)',
19
+ background: 'rgba(220, 60, 60, 0.9)', // warm UI red
20
+ color: '#fff',
21
+ padding: '6px 12px',
22
+ borderRadius: '4px',
23
+ fontSize: '12px',
24
+ zIndex: '99999',
25
+ transition: 'opacity 0.4s ease',
26
+ opacity: '0'
27
+ });
28
+ document.body.appendChild(el);
29
+ }
30
+ el.textContent = msg;
31
+ el.style.display = 'block';
32
+ requestAnimationFrame(() => el.style.opacity = '1');
33
+ // Clean timers
34
+ clearTimeout(_msgTimer);
35
+ clearTimeout(_fadeTimer);
36
+ // Start timer
37
+ _msgTimer = setTimeout(() => {
38
+ el.style.opacity = '0';
39
+ _fadeTimer = setTimeout(() => el.style.display = 'none', 400);
40
+ }, 5000);
41
+ }
42
+
43
+ // 🔹 centralized selection clear
44
+ function clearSelection() {
45
+ document
46
+ .querySelectorAll('#list .file-item')
47
+ .forEach(x => x.className = 'file-item');
48
+
49
+ selected = null;
50
+ selectedEl = null;
51
+ }
52
+
53
+ function load() {
54
+ console.info('load.loadDirs');
55
+
56
+ loadDirs().then(() => {
57
+ console.info('load.loadFiles:', selectedDir);
58
+ loadFiles();
59
+ });
60
+ console.info('load.loadDiskUsage');
61
+ updateDiskUsage();
62
+ }
63
+
64
+ function loadFiles() {
65
+ const contentList = document.getElementById('list');
66
+
67
+ // 🔹 Enter loading state
68
+ contentList.classList.add('loading');
69
+
70
+ fetch('/fs/list', {
71
+ method: 'POST',
72
+ headers: {
73
+ 'Content-Type': 'text/plain'
74
+ },
75
+ body: selectedDir || '/'
76
+ })
77
+ .then(r => r.json())
78
+ .then(files => {
79
+ list.innerHTML = '';
80
+ clearSelection();
81
+ // 🔹 Empty folder placeholder
82
+ if (!Array.isArray(files) || files.length === 0) {
83
+ const d = document.createElement('div');
84
+ d.className = 'file-item placeholder';
85
+ d.textContent = '.empty';
86
+ d.style.opacity = '0.5';
87
+ d.style.pointerEvents = 'none'; // 🔹 non-clickable
88
+ list.appendChild(d);
89
+
90
+ console.info("Files loaded (empty folder)");
91
+ return;
92
+ }
93
+ // 🔹 Files listing
94
+ files.forEach(f => {
95
+ const name = f.path.split('/').pop();
96
+ const d = document.createElement('div');
97
+ d.className = 'file-item';
98
+ d.textContent = `${name} ${f.size}B`;
99
+
100
+ d.onclick = (e) => {
101
+ e.stopPropagation();
102
+
103
+ if (selectedEl === d) {
104
+ clearSelection();
105
+ return;
106
+ }
107
+
108
+ clearSelection();
109
+ d.className = 'file-item sel';
110
+ selected = name;
111
+ selectedEl = d;
112
+ };
113
+
114
+ list.appendChild(d);
115
+ });
116
+
117
+ console.info("Files loaded");
118
+ })
119
+ .catch(err => {
120
+ console.error("load failed:", err);
121
+ popUpMsg("Failed to load files: " + err.message);
122
+ })
123
+ .finally(() => {
124
+ // 🔹 Exit loading state (success or error)
125
+ contentList.classList.remove('loading');
126
+ });
127
+ }
128
+
129
+ function loadDirs() {
130
+ return fetch('/fs/dirs')
131
+ .then(r => r.json())
132
+ .then(dirs => {
133
+ const container = document.getElementById('folder-path');
134
+ container.innerHTML = '';
135
+
136
+ if (!Array.isArray(dirs) || !dirs.length) return;
137
+
138
+ dirs.forEach(dir => {
139
+ const normalized = dir.replace(/^\/+/, '');
140
+ const d = document.createElement('div');
141
+ d.className = 'dir-item';
142
+ d.textContent = normalized;
143
+
144
+ d.onclick = () => {
145
+ document
146
+ .querySelectorAll('#folder-path .dir-item')
147
+ .forEach(x => x.className = 'dir-item');
148
+
149
+ d.className = 'dir-item sel';
150
+ selectedDir = normalized;
151
+ console.info('dirChange.loadFiles:', selectedDir);
152
+ loadFiles();
153
+ };
154
+
155
+ // 🔹 Selection logic
156
+ if (!selectedDir) {
157
+ selectedDir = normalized;
158
+ d.className = 'dir-item sel';
159
+ }
160
+ else if (normalized === selectedDir) {
161
+ d.className = 'dir-item sel';
162
+ }
163
+
164
+ container.appendChild(d);
165
+ console.info("Folders loaded");
166
+ });
167
+
168
+ // 🔹 Fallback if folder vanished
169
+ if (
170
+ !container.querySelector('.dir-item.sel') &&
171
+ container.firstChild
172
+ ) {
173
+ selectedDir = container.firstChild.textContent;
174
+ container.firstChild.classList.add('sel');
175
+ }
176
+ })
177
+ .catch(err => {
178
+ console.error("dirs load failed:", err);
179
+ popUpMsg("Failed to load folders: " + err.message);
180
+ })
181
+ }
182
+
183
+ function uploadFile() {
184
+ const f = file.files[0];
185
+ if (!f) return;
186
+
187
+ const fd = new FormData();
188
+ const targetPath = `${selectedDir}/${f.name}`;
189
+ // This sets filename="selectedDir/file.txt" in multipart
190
+ fd.append('file', f, targetPath);
191
+
192
+ console.info("uploadFile:", targetPath);
193
+ fetch('/fs/files', { method: 'POST', body: fd })
194
+ .then(async r => {
195
+ if (!r.ok) {
196
+ const resp = (await r.text()) || r.statusText;
197
+ throw new Error(`${r.status} - ${resp}`);
198
+ }
199
+ return r;
200
+ })
201
+ .then(load)
202
+ .catch(err => {
203
+ console.error("uploadFile error:", err);
204
+ popUpMsg("Upload failed: " + err.message);
205
+ });
206
+ }
207
+
208
+ function openFile() {
209
+ if (!selected) return;
210
+ const resource = `/${selectedDir}/${selected}`;
211
+ console.info('openFile:', resource);
212
+ window.open(resource);
213
+ }
214
+
215
+ function download() {
216
+ if (!selected) return;
217
+
218
+ const resource = `/${selectedDir}/${selected}`;
219
+ console.info('download:', resource);
220
+
221
+ const a = document.createElement('a');
222
+ a.href = resource;
223
+ a.download = selected;
224
+ a.click();
225
+ }
226
+
227
+ function deleteFile() {
228
+ if (!selected) return;
229
+
230
+ const toDelete = `/${selectedDir}/${selected}`;
231
+ console.info("deleteFile:", toDelete);
232
+
233
+ fetch('/fs/files', { method: 'DELETE', body: toDelete })
234
+ .then(async r => {
235
+ if (!r.ok) {
236
+ const resp = (await r.text()) || r.statusText;
237
+ throw new Error(`${r.status} - ${resp}`);
238
+ }
239
+ return r;
240
+ })
241
+ .then(() => {
242
+ // 🔹 If the deleted file is open in editor → DESTROY editor
243
+ if (_editorScriptLoaded && editorFile === toDelete) {
244
+ window.destroyEditor?.();
245
+ editorFile = null;
246
+ console.info("deleteFile: editor destroyed");
247
+ }
248
+ })
249
+ .then(load)
250
+ .catch(err => {
251
+ console.error("deleteFile failed:", err);
252
+ popUpMsg("Delete failed: " + err.message);
253
+ });
254
+ }
255
+
256
+ function loadEditorScript() {
257
+ if (_editorScriptLoaded) return Promise.resolve();
258
+
259
+ return new Promise((resolve, reject) => {
260
+ const s = document.createElement('script');
261
+ s.src = '../editor.js';
262
+ s.onload = () => {
263
+ _editorScriptLoaded = true;
264
+ resolve();
265
+ };
266
+ s.onerror = reject;
267
+ document.head.appendChild(s);
268
+ });
269
+ }
270
+
271
+ async function editor() {
272
+ const filename = selected ?? `LM_blinky.py`;
273
+ const resource = `/${selectedDir}/${filename}`;
274
+ console.info('editor:', resource);
275
+
276
+ await loadEditorScript();
277
+
278
+ let container = document.getElementById('editor');
279
+ if (!container) {
280
+ container = document.createElement('div');
281
+ container.id = 'editor';
282
+ }
283
+
284
+ window.createEditor(container);
285
+
286
+ // 🔹 placement delegated to editor.js
287
+ window.openEditor(resource, {
288
+ anchor: selectedEl,
289
+ list: document.getElementById('list')
290
+ });
291
+
292
+ editorFile = resource; // 🔹 track currently opened file
293
+ }
294
+
295
+ function updateDiskUsage() {
296
+ fetch('/fs/usage')
297
+ .then(r => r.json())
298
+ .then(data => {
299
+ const usedMB = (data.used / (1024 * 1024)).toFixed(1);
300
+ const freeMB = (data.free / (1024 * 1024)).toFixed(1);
301
+ const total = data.used + data.free;
302
+ const percent = total ? (data.used / total) * 100 : 0;
303
+
304
+ document.getElementById('disktext').textContent =
305
+ `Disk: ${usedMB} MB used / ${freeMB} MB free`;
306
+
307
+ document.getElementById('diskused').style.width =
308
+ `${percent.toFixed(1)}%`;
309
+
310
+ console.info("DiskUsage: update");
311
+ })
312
+ .catch(err => {
313
+ console.error("disk usage failed:", err);
314
+ popUpMsg("Disk usage unavailable: " + err.message);
315
+ })
316
+ }
317
+
318
+ // 🔹 Global outside-click handler
319
+ document.addEventListener('click', (e) => {
320
+ // Ignore toolbar / editor buttons
321
+ if (e.target.closest('button')) return;
322
+
323
+ // If editor is open, keep selection locked
324
+ if (_editorScriptLoaded && editorFile) return;
325
+
326
+ const list = document.getElementById('list');
327
+ const editor = document.getElementById('editor');
328
+
329
+ if (
330
+ list &&
331
+ !list.contains(e.target) &&
332
+ (!editor || !editor.contains(e.target))
333
+ ) {
334
+ clearSelection();
335
+ }
336
+ });
337
+
338
+ load();
@@ -6,14 +6,56 @@
6
6
  <meta name="theme-color" media="(prefers-color-scheme: dark)" content="black" />
7
7
  <title>microWeb</title>
8
8
  <link rel="stylesheet" href="ustyle.css">
9
+ <style>
10
+ hr {
11
+ border: none;
12
+ height: 2px;
13
+ background: rgba(255, 255, 255, 0.25);
14
+ margin: 16px 0;
15
+ }
16
+ #restInfoHeader {
17
+ margin-bottom: 12px;
18
+ }
19
+ /* Container */
20
+ .endpoint-groups {
21
+ display: flex;
22
+ flex-wrap: wrap;
23
+ gap: 12px;
24
+ margin-bottom: 12px;
25
+ width: 100%;
26
+ }
27
+
28
+ /* Group cards */
29
+ .endpoint-group {
30
+ display: flex;
31
+ flex-wrap: wrap;
32
+ align-items: center;
33
+ gap: 6px;
34
+ padding: 8px;
35
+ border-radius: 6px;
36
+ background: rgba(255, 255, 255, 0.12);
37
+ backdrop-filter: blur(2px);
38
+ max-width: 100%;
39
+ }
40
+
41
+ /* Prevent buttons from getting tiny */
42
+ .endpoint-group button {
43
+ white-space: nowrap;
44
+ }
45
+ </style>
9
46
  <script src="uapi.js" defer></script>
10
47
  </head>
11
48
  <body>
12
49
  <img src="https://github.com/BxNxM/micrOS/blob/master/media/logo_mini.png?raw=true" alt="micrOS Logo" width="60" height="60">
13
50
  <h1> microWeb server </h1>
14
- <p id="restInfo"></p>
51
+ <div id="restInfo">
52
+ <div id="restInfoHeader"></div>
53
+ <div id="endpointHint">🔗 Endpoints:</div>
54
+ <div id="endpointGroups" class="endpoint-groups"></div>
55
+ </div>
56
+ <hr>
15
57
  <h2>🚀 REST API</h2>
16
- <p>Clickable examples 🕹</p>
58
+ <p>Shortcuts:</p>
17
59
  <button onclick="restAPI('system/info')">SysInfo</button>
18
60
  <button onclick="restAPI('system/alarms')">Alarms</button>
19
61
  <button onclick="restAPI('system/clock')">Clock</button>
@@ -41,19 +41,60 @@ function restConsole(apiUrl, data, delta) {
41
41
  document.getElementById('restConsoleTime').innerHTML = `⏱ Response time: ${delta} ms`;
42
42
  }
43
43
 
44
- function restInfo() {
44
+ function renderEndpointGroups(endpoints) {
45
+ const container = document.getElementById('endpointGroups');
46
+ if (!container) {return;}
47
+ container.innerHTML = '';
48
+ if (!Array.isArray(endpoints) || endpoints.length === 0) {return;}
49
+ const groups = endpoints.reduce((acc, endpoint) => {
50
+ const trimmed = endpoint.replace(/^\/+/, '');
51
+ if (!trimmed) {return acc;}
52
+ const root = trimmed.split('/')[0];
53
+ acc[root] = acc[root] || [];
54
+ acc[root].push(trimmed);
55
+ return acc;
56
+ }, {});
57
+ Object.keys(groups).sort().forEach(group => {
58
+ const entries = groups[group].sort();
59
+ const isSingle = entries.length === 1 && entries[0] === group;
60
+ if (isSingle) {
61
+ const button = document.createElement('button');
62
+ button.textContent = group;
63
+ button.onclick = () => window.open(`/${group}`, '_blank');
64
+ container.appendChild(button);
65
+ return;
66
+ }
67
+ const groupEl = document.createElement('div');
68
+ groupEl.className = 'endpoint-group';
69
+ const title = document.createElement('span');
70
+ title.className = 'endpoint-group-title';
71
+ title.textContent = group;
72
+ groupEl.appendChild(title);
73
+ entries.forEach(entry => {
74
+ const label = entry === group ? group : entry.replace(`${group}/`, '');
75
+ const button = document.createElement('button');
76
+ button.textContent = label;
77
+ button.onclick = () => window.open(`/${entry}`, '_blank');
78
+ groupEl.appendChild(button);
79
+ });
80
+ container.appendChild(groupEl);
81
+ });
82
+ }
83
+
84
+ function restInfo(showPages=true) {
45
85
  // UPDATES: 'restInfo' and restConsole(...)
46
- restAPICore(cmd='').then(({ response, delta, query }) => {
86
+ restAPICore(cmd = '').then(({ response, delta, query }) => {
47
87
  // Update API Console
48
88
  restConsole(query, response, delta)
49
- // Update 'SysApiInfo' tag
89
+ // Update 'restInfo' tag
50
90
  const result = response['result'];
51
91
  const auth = result.auth ? "🔑" : "";
52
92
  let infoHeader = `micrOS: ${result.micrOS} ❖ node: ${result.node}${auth}`;
53
- let infoSubpages = (response['result']['usr_endpoints'] ? "<br><br>📎 " + Object.entries(response['result']['usr_endpoints'])
54
- .map(([key, value]) => `<a href="${value}" target="_blank" style="color: white;">${value} </a>`)
55
- .join(' | ') : '');
56
- document.getElementById('restInfo').innerHTML = infoHeader + infoSubpages;
93
+ if (showPages) {
94
+ const endpoints = result['usr_endpoints'] ? Array.from(result['usr_endpoints']) : [];
95
+ renderEndpointGroups(endpoints);
96
+ }
97
+ document.getElementById('restInfoHeader').innerHTML = infoHeader;
57
98
  }).catch(error => {
58
99
  console.error('Error in restAPI:', error);
59
100
  });
@@ -4,10 +4,13 @@
4
4
  100% {background-position: 0% 50%;}
5
5
  }
6
6
  body {
7
- height: calc(100vh - 6%); /* Set the height to 100% of the viewport height */
8
- width: calc(100vw - 6%); /* Set the width to 200% of the viewport height */
9
- padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
7
+ min-height: 100vh;
8
+ min-width: 100vw;
10
9
  margin: 3%;
10
+ padding: env(safe-area-inset-top)
11
+ env(safe-area-inset-right)
12
+ env(safe-area-inset-bottom)
13
+ env(safe-area-inset-left);
11
14
  background: linear-gradient(110deg, #4b3c66, #21184f, #712336);
12
15
  background-size: 200% 200%;
13
16
  animation: backgroundAnimation 15s infinite;