micrOSDevToolKit 2.13.1__py3-none-any.whl → 2.17.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.

Potentially problematic release.


This version of micrOSDevToolKit might be problematic. Click here for more details.

Files changed (220) hide show
  1. micrOS/release_info/micrOS_ReleaseInfo/system_analysis_sum.json +125 -121
  2. micrOS/source/Common.py +48 -26
  3. micrOS/source/Config.py +13 -5
  4. micrOS/source/Espnow.py +100 -58
  5. micrOS/source/Files.py +77 -41
  6. micrOS/source/Hooks.py +18 -34
  7. micrOS/source/Logger.py +2 -7
  8. micrOS/source/Network.py +36 -16
  9. micrOS/source/Server.py +22 -8
  10. micrOS/source/Shell.py +9 -6
  11. micrOS/source/Tasks.py +34 -13
  12. micrOS/source/Web.py +69 -31
  13. micrOS/source/__pycache__/Common.cpython-312.pyc +0 -0
  14. micrOS/source/__pycache__/Files.cpython-312.pyc +0 -0
  15. micrOS/source/__pycache__/Logger.cpython-312.pyc +0 -0
  16. micrOS/source/__pycache__/Server.cpython-312.pyc +0 -0
  17. micrOS/source/config/_git.keep +0 -0
  18. micrOS/source/micrOS.py +7 -0
  19. micrOS/source/micrOSloader.py +4 -10
  20. micrOS/source/microIO.py +2 -2
  21. micrOS/source/modules/IO_esp32c6.py +38 -0
  22. micrOS/source/modules/LM_L298N.py +161 -0
  23. micrOS/source/modules/LM_cluster.py +255 -0
  24. {toolkit/workspace/precompiled → micrOS/source/modules}/LM_esp32.py +5 -0
  25. micrOS/source/modules/LM_espnow.py +36 -0
  26. micrOS/source/{LM_i2c.py → modules/LM_i2c.py} +1 -1
  27. micrOS/source/{LM_light_sensor.py → modules/LM_light_sensor.py} +2 -2
  28. micrOS/source/modules/LM_mqtt_client.py +246 -0
  29. micrOS/source/{LM_neoeffects.py → modules/LM_neoeffects.py} +14 -4
  30. micrOS/source/{LM_neomatrix.py → modules/LM_neomatrix.py} +140 -38
  31. micrOS/source/{LM_oled_ui.py → modules/LM_oled_ui.py} +2 -2
  32. micrOS/source/{LM_oledui.py → modules/LM_oledui.py} +2 -2
  33. micrOS/source/{LM_pacman.py → modules/LM_pacman.py} +74 -29
  34. micrOS/source/{LM_presence.py → modules/LM_presence.py} +2 -2
  35. micrOS/source/{LM_robustness.py → modules/LM_robustness.py} +49 -2
  36. micrOS/source/{LM_tcs3472.py → modules/LM_tcs3472.py} +4 -6
  37. micrOS/source/web/dashboard.html +2 -0
  38. micrOS/source/web/matrix_draw.html +390 -0
  39. micrOS/source/web/uapi.js +9 -6
  40. {microsdevtoolkit-2.13.1.dist-info → microsdevtoolkit-2.17.1.dist-info}/METADATA +30 -37
  41. {microsdevtoolkit-2.13.1.dist-info → microsdevtoolkit-2.17.1.dist-info}/RECORD +200 -190
  42. toolkit/DevEnvCompile.py +21 -12
  43. toolkit/DevEnvOTA.py +27 -16
  44. toolkit/DevEnvUSB.py +35 -21
  45. toolkit/LM_to_compile.dat +3 -1
  46. toolkit/MicrOSDevEnv.py +37 -21
  47. toolkit/dashboard_apps/QMI8685_GYRO.py +1 -1
  48. toolkit/dashboard_apps/SystemTest.py +8 -5
  49. toolkit/{MicrosFiles.py → lib/MicrosFiles.py} +24 -4
  50. toolkit/micrOSdashboard.py +2 -2
  51. toolkit/micrOSlint.py +17 -7
  52. toolkit/simulator_lib/__pycache__/simulator.cpython-312.pyc +0 -0
  53. toolkit/simulator_lib/__pycache__/uos.cpython-312.pyc +0 -0
  54. toolkit/simulator_lib/mqtt_as/Note.md +15 -0
  55. toolkit/simulator_lib/mqtt_as/__init__.py +950 -0
  56. toolkit/simulator_lib/mqtt_as/__pycache__/__init__.cpython-312.pyc +0 -0
  57. toolkit/simulator_lib/mqtt_as/clean.py +69 -0
  58. toolkit/simulator_lib/mqtt_as/mqtt_v5_properties.py +239 -0
  59. toolkit/simulator_lib/mqtt_as/range.py +90 -0
  60. toolkit/simulator_lib/mqtt_as/range_ex.py +119 -0
  61. toolkit/simulator_lib/simulator.py +14 -1
  62. toolkit/simulator_lib/uos.py +2 -0
  63. toolkit/workspace/precompiled/Common.mpy +0 -0
  64. toolkit/workspace/precompiled/Config.mpy +0 -0
  65. toolkit/workspace/precompiled/Espnow.mpy +0 -0
  66. toolkit/workspace/precompiled/Files.mpy +0 -0
  67. toolkit/workspace/precompiled/Hooks.mpy +0 -0
  68. toolkit/workspace/precompiled/Logger.mpy +0 -0
  69. toolkit/workspace/precompiled/Network.mpy +0 -0
  70. toolkit/workspace/precompiled/Server.mpy +0 -0
  71. toolkit/workspace/precompiled/Shell.mpy +0 -0
  72. toolkit/workspace/precompiled/Tasks.mpy +0 -0
  73. toolkit/workspace/precompiled/Web.mpy +0 -0
  74. toolkit/workspace/precompiled/config/_git.keep +0 -0
  75. toolkit/workspace/precompiled/micrOS.mpy +0 -0
  76. toolkit/workspace/precompiled/micrOSloader.mpy +0 -0
  77. toolkit/workspace/precompiled/microIO.mpy +0 -0
  78. toolkit/workspace/precompiled/{IO_esp32.mpy → modules/IO_esp32.mpy} +0 -0
  79. toolkit/workspace/precompiled/{IO_esp32c3.mpy → modules/IO_esp32c3.mpy} +0 -0
  80. toolkit/workspace/precompiled/modules/IO_esp32c6.mpy +0 -0
  81. toolkit/workspace/precompiled/{IO_esp32s2.mpy → modules/IO_esp32s2.mpy} +0 -0
  82. toolkit/workspace/precompiled/{IO_esp32s3.mpy → modules/IO_esp32s3.mpy} +0 -0
  83. toolkit/workspace/precompiled/{IO_m5stamp.mpy → modules/IO_m5stamp.mpy} +0 -0
  84. toolkit/workspace/precompiled/{IO_qtpy.mpy → modules/IO_qtpy.mpy} +0 -0
  85. toolkit/workspace/precompiled/modules/IO_rp2.mpy +0 -0
  86. toolkit/workspace/precompiled/modules/IO_s3matrix.mpy +0 -0
  87. toolkit/workspace/precompiled/{IO_tinypico.mpy → modules/IO_tinypico.mpy} +0 -0
  88. toolkit/workspace/precompiled/modules/LM_L298N.mpy +0 -0
  89. toolkit/workspace/precompiled/{LM_OV2640.mpy → modules/LM_OV2640.mpy} +0 -0
  90. toolkit/workspace/precompiled/{LM_aht10.mpy → modules/LM_aht10.mpy} +0 -0
  91. toolkit/workspace/precompiled/{LM_bme280.mpy → modules/LM_bme280.mpy} +0 -0
  92. toolkit/workspace/precompiled/{LM_buzzer.mpy → modules/LM_buzzer.mpy} +0 -0
  93. toolkit/workspace/precompiled/{LM_cct.mpy → modules/LM_cct.mpy} +0 -0
  94. toolkit/workspace/precompiled/modules/LM_cluster.mpy +0 -0
  95. toolkit/workspace/precompiled/{LM_co2.mpy → modules/LM_co2.mpy} +0 -0
  96. toolkit/workspace/precompiled/{LM_dht11.mpy → modules/LM_dht11.mpy} +0 -0
  97. toolkit/workspace/precompiled/{LM_dht22.mpy → modules/LM_dht22.mpy} +0 -0
  98. toolkit/workspace/precompiled/{LM_dimmer.mpy → modules/LM_dimmer.mpy} +0 -0
  99. toolkit/workspace/precompiled/{LM_distance.mpy → modules/LM_distance.mpy} +0 -0
  100. toolkit/workspace/precompiled/{LM_ds18.mpy → modules/LM_ds18.mpy} +0 -0
  101. {micrOS/source → toolkit/workspace/precompiled/modules}/LM_esp32.py +5 -0
  102. toolkit/workspace/precompiled/modules/LM_espnow.py +36 -0
  103. toolkit/workspace/precompiled/{LM_gameOfLife.mpy → modules/LM_gameOfLife.mpy} +0 -0
  104. toolkit/workspace/precompiled/{LM_genIO.mpy → modules/LM_genIO.mpy} +0 -0
  105. toolkit/workspace/precompiled/{LM_haptic.mpy → modules/LM_haptic.mpy} +0 -0
  106. toolkit/workspace/precompiled/{LM_i2c.py → modules/LM_i2c.py} +1 -1
  107. toolkit/workspace/precompiled/{LM_i2s_mic.mpy → modules/LM_i2s_mic.mpy} +0 -0
  108. toolkit/workspace/precompiled/{LM_keychain.mpy → modules/LM_keychain.mpy} +0 -0
  109. toolkit/workspace/precompiled/{LM_ld2410.mpy → modules/LM_ld2410.mpy} +0 -0
  110. toolkit/workspace/precompiled/modules/LM_light_sensor.mpy +0 -0
  111. toolkit/workspace/precompiled/modules/LM_mqtt_client.mpy +0 -0
  112. toolkit/workspace/precompiled/{LM_neoeffects.mpy → modules/LM_neoeffects.mpy} +0 -0
  113. toolkit/workspace/precompiled/modules/LM_neomatrix.mpy +0 -0
  114. toolkit/workspace/precompiled/{LM_neopixel.mpy → modules/LM_neopixel.mpy} +0 -0
  115. toolkit/workspace/precompiled/{LM_oled.mpy → modules/LM_oled.mpy} +0 -0
  116. toolkit/workspace/precompiled/{LM_oled_sh1106.mpy → modules/LM_oled_sh1106.mpy} +0 -0
  117. toolkit/workspace/precompiled/modules/LM_oled_ui.mpy +0 -0
  118. toolkit/workspace/precompiled/modules/LM_oledui.mpy +0 -0
  119. toolkit/workspace/precompiled/modules/LM_pacman.mpy +0 -0
  120. toolkit/workspace/precompiled/modules/LM_presence.mpy +0 -0
  121. toolkit/workspace/precompiled/{LM_rest.mpy → modules/LM_rest.mpy} +0 -0
  122. toolkit/workspace/precompiled/{LM_rgb.mpy → modules/LM_rgb.mpy} +0 -0
  123. toolkit/workspace/precompiled/{LM_rgbcct.mpy → modules/LM_rgbcct.mpy} +0 -0
  124. toolkit/workspace/precompiled/{LM_roboarm.mpy → modules/LM_roboarm.mpy} +0 -0
  125. toolkit/workspace/precompiled/{LM_robustness.py → modules/LM_robustness.py} +49 -2
  126. toolkit/workspace/precompiled/{LM_servo.mpy → modules/LM_servo.mpy} +0 -0
  127. toolkit/workspace/precompiled/{LM_sound_event.mpy → modules/LM_sound_event.mpy} +0 -0
  128. toolkit/workspace/precompiled/{LM_stepper.mpy → modules/LM_stepper.mpy} +0 -0
  129. toolkit/workspace/precompiled/{LM_switch.mpy → modules/LM_switch.mpy} +0 -0
  130. toolkit/workspace/precompiled/{LM_system.mpy → modules/LM_system.mpy} +0 -0
  131. toolkit/workspace/precompiled/{LM_tcs3472.py → modules/LM_tcs3472.py} +4 -6
  132. toolkit/workspace/precompiled/{LM_telegram.mpy → modules/LM_telegram.mpy} +0 -0
  133. toolkit/workspace/precompiled/{LM_tinyrgb.mpy → modules/LM_tinyrgb.mpy} +0 -0
  134. toolkit/workspace/precompiled/{LM_trackball.mpy → modules/LM_trackball.mpy} +0 -0
  135. toolkit/workspace/precompiled/{LM_veml7700.mpy → modules/LM_veml7700.mpy} +0 -0
  136. toolkit/workspace/precompiled/web/dashboard.html +2 -0
  137. toolkit/workspace/precompiled/web/matrix_draw.html +390 -0
  138. toolkit/workspace/precompiled/web/uapi.js +9 -6
  139. micrOS/source/IO_esp32c6.py +0 -16
  140. micrOS/source/LM_L298N_DCmotor.py +0 -86
  141. micrOS/source/LM_espnow.py +0 -57
  142. micrOS/source/LM_mqtt_pro.py +0 -211
  143. toolkit/lib/file_extensions.py +0 -22
  144. toolkit/workspace/precompiled/Common.cpython-312.pyc +0 -0
  145. toolkit/workspace/precompiled/IO_esp32c6.mpy +0 -0
  146. toolkit/workspace/precompiled/IO_rp2.mpy +0 -0
  147. toolkit/workspace/precompiled/IO_s3matrix.mpy +0 -0
  148. toolkit/workspace/precompiled/LM_L298N_DCmotor.mpy +0 -0
  149. toolkit/workspace/precompiled/LM_espnow.py +0 -57
  150. toolkit/workspace/precompiled/LM_light_sensor.mpy +0 -0
  151. toolkit/workspace/precompiled/LM_mqtt_pro.py +0 -211
  152. toolkit/workspace/precompiled/LM_neomatrix.mpy +0 -0
  153. toolkit/workspace/precompiled/LM_oled_ui.mpy +0 -0
  154. toolkit/workspace/precompiled/LM_oledui.mpy +0 -0
  155. toolkit/workspace/precompiled/LM_pacman.mpy +0 -0
  156. toolkit/workspace/precompiled/LM_presence.mpy +0 -0
  157. toolkit/workspace/precompiled/Logger.cpython-312.pyc +0 -0
  158. toolkit/workspace/precompiled/Server.cpython-312.pyc +0 -0
  159. /micrOS/source/{IO_esp32.py → modules/IO_esp32.py} +0 -0
  160. /micrOS/source/{IO_esp32c3.py → modules/IO_esp32c3.py} +0 -0
  161. /micrOS/source/{IO_esp32s2.py → modules/IO_esp32s2.py} +0 -0
  162. /micrOS/source/{IO_esp32s3.py → modules/IO_esp32s3.py} +0 -0
  163. /micrOS/source/{IO_m5stamp.py → modules/IO_m5stamp.py} +0 -0
  164. /micrOS/source/{IO_qtpy.py → modules/IO_qtpy.py} +0 -0
  165. /micrOS/source/{IO_rp2.py → modules/IO_rp2.py} +0 -0
  166. /micrOS/source/{IO_s3matrix.py → modules/IO_s3matrix.py} +0 -0
  167. /micrOS/source/{IO_tinypico.py → modules/IO_tinypico.py} +0 -0
  168. /micrOS/source/{LM_L9110_DCmotor.py → modules/LM_L9110_DCmotor.py} +0 -0
  169. /micrOS/source/{LM_OV2640.py → modules/LM_OV2640.py} +0 -0
  170. /micrOS/source/{LM_VL53L0X.py → modules/LM_VL53L0X.py} +0 -0
  171. /micrOS/source/{LM_aht10.py → modules/LM_aht10.py} +0 -0
  172. /micrOS/source/{LM_bme280.py → modules/LM_bme280.py} +0 -0
  173. /micrOS/source/{LM_buzzer.py → modules/LM_buzzer.py} +0 -0
  174. /micrOS/source/{LM_cct.py → modules/LM_cct.py} +0 -0
  175. /micrOS/source/{LM_co2.py → modules/LM_co2.py} +0 -0
  176. /micrOS/source/{LM_dashboard_be.py → modules/LM_dashboard_be.py} +0 -0
  177. /micrOS/source/{LM_dht11.py → modules/LM_dht11.py} +0 -0
  178. /micrOS/source/{LM_dht22.py → modules/LM_dht22.py} +0 -0
  179. /micrOS/source/{LM_dimmer.py → modules/LM_dimmer.py} +0 -0
  180. /micrOS/source/{LM_distance.py → modules/LM_distance.py} +0 -0
  181. /micrOS/source/{LM_ds18.py → modules/LM_ds18.py} +0 -0
  182. /micrOS/source/{LM_gameOfLife.py → modules/LM_gameOfLife.py} +0 -0
  183. /micrOS/source/{LM_genIO.py → modules/LM_genIO.py} +0 -0
  184. /micrOS/source/{LM_haptic.py → modules/LM_haptic.py} +0 -0
  185. /micrOS/source/{LM_i2s_mic.py → modules/LM_i2s_mic.py} +0 -0
  186. /micrOS/source/{LM_keychain.py → modules/LM_keychain.py} +0 -0
  187. /micrOS/source/{LM_ld2410.py → modules/LM_ld2410.py} +0 -0
  188. /micrOS/source/{LM_neopixel.py → modules/LM_neopixel.py} +0 -0
  189. /micrOS/source/{LM_oled.py → modules/LM_oled.py} +0 -0
  190. /micrOS/source/{LM_oled_sh1106.py → modules/LM_oled_sh1106.py} +0 -0
  191. /micrOS/source/{LM_pet_feeder.py → modules/LM_pet_feeder.py} +0 -0
  192. /micrOS/source/{LM_qmi8658.py → modules/LM_qmi8658.py} +0 -0
  193. /micrOS/source/{LM_rencoder.py → modules/LM_rencoder.py} +0 -0
  194. /micrOS/source/{LM_rest.py → modules/LM_rest.py} +0 -0
  195. /micrOS/source/{LM_rgb.py → modules/LM_rgb.py} +0 -0
  196. /micrOS/source/{LM_rgbcct.py → modules/LM_rgbcct.py} +0 -0
  197. /micrOS/source/{LM_roboarm.py → modules/LM_roboarm.py} +0 -0
  198. /micrOS/source/{LM_rp2w.py → modules/LM_rp2w.py} +0 -0
  199. /micrOS/source/{LM_sdcard.py → modules/LM_sdcard.py} +0 -0
  200. /micrOS/source/{LM_servo.py → modules/LM_servo.py} +0 -0
  201. /micrOS/source/{LM_sound_event.py → modules/LM_sound_event.py} +0 -0
  202. /micrOS/source/{LM_stepper.py → modules/LM_stepper.py} +0 -0
  203. /micrOS/source/{LM_switch.py → modules/LM_switch.py} +0 -0
  204. /micrOS/source/{LM_system.py → modules/LM_system.py} +0 -0
  205. /micrOS/source/{LM_telegram.py → modules/LM_telegram.py} +0 -0
  206. /micrOS/source/{LM_tinyrgb.py → modules/LM_tinyrgb.py} +0 -0
  207. /micrOS/source/{LM_trackball.py → modules/LM_trackball.py} +0 -0
  208. /micrOS/source/{LM_veml7700.py → modules/LM_veml7700.py} +0 -0
  209. {microsdevtoolkit-2.13.1.data → microsdevtoolkit-2.17.1.data}/scripts/devToolKit.py +0 -0
  210. {microsdevtoolkit-2.13.1.dist-info → microsdevtoolkit-2.17.1.dist-info}/WHEEL +0 -0
  211. {microsdevtoolkit-2.13.1.dist-info → microsdevtoolkit-2.17.1.dist-info}/licenses/LICENSE +0 -0
  212. {microsdevtoolkit-2.13.1.dist-info → microsdevtoolkit-2.17.1.dist-info}/top_level.txt +0 -0
  213. /toolkit/workspace/precompiled/{LM_L9110_DCmotor.py → modules/LM_L9110_DCmotor.py} +0 -0
  214. /toolkit/workspace/precompiled/{LM_VL53L0X.py → modules/LM_VL53L0X.py} +0 -0
  215. /toolkit/workspace/precompiled/{LM_dashboard_be.py → modules/LM_dashboard_be.py} +0 -0
  216. /toolkit/workspace/precompiled/{LM_pet_feeder.py → modules/LM_pet_feeder.py} +0 -0
  217. /toolkit/workspace/precompiled/{LM_qmi8658.py → modules/LM_qmi8658.py} +0 -0
  218. /toolkit/workspace/precompiled/{LM_rencoder.py → modules/LM_rencoder.py} +0 -0
  219. /toolkit/workspace/precompiled/{LM_rp2w.py → modules/LM_rp2w.py} +0 -0
  220. /toolkit/workspace/precompiled/{LM_sdcard.py → modules/LM_sdcard.py} +0 -0
@@ -0,0 +1,390 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
6
+ <meta name="theme-color" content="black" media="(prefers-color-scheme: dark)" />
7
+ <title>micrOS Matrix Drawer</title>
8
+ <link rel="stylesheet" href="ustyle.css" />
9
+ <script src="uapi.js" defer></script>
10
+ <style>
11
+ body { font-family: sans-serif; margin: 20px; }
12
+ .layout {
13
+ display: flex; justify-content: center; align-items: flex-start;
14
+ gap: 20px; margin: 20px auto; flex-wrap: wrap;
15
+ }
16
+ .matrix { display: grid; gap: 2px; touch-action: none; }
17
+ .pixel {
18
+ width: 30px; height: 30px; background: #000; border: 1px solid #333;
19
+ cursor: pointer; user-select: none; touch-action: none;
20
+ }
21
+ input[type="number"], input[type="color"] { margin: 10px; padding: 4px; }
22
+ button { margin: 6px; padding: 6px 12px; }
23
+ pre {
24
+ text-align: left; max-width: 800px; margin: auto; background: #111;
25
+ color: #0f0; padding: 10px; overflow-x: auto;
26
+ }
27
+ textarea {
28
+ width: 100%; max-width: 400px; display: block; margin: 10px auto;
29
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
30
+ background:#111; color:#0f0; border:1px solid #333; padding:8px;
31
+ resize:vertical; white-space:pre; overflow:auto;
32
+ }
33
+ .side-panel { flex: 0 0 420px; }
34
+ h1, .controls, h3 { text-align: center; }
35
+ </style>
36
+ </head>
37
+ <body>
38
+ <h1>microWeb Matrix LED Drawer</h1>
39
+ <p id="restInfo" class="controls"></p>
40
+
41
+ <!-- Controls -->
42
+ <div class="controls">
43
+ <input type="color" id="colorPicker" value="#00ff00" title="Pick LED color" class="custom-color-picker" />
44
+ <input type="number" id="matrixSize" value="8" min="1" max="64" title="Matrix size (NxN)" />
45
+ <button onclick="applySize()">Resize</button>
46
+ <button onclick="clearMatrix()">🧹 Clear Screen</button>
47
+ <button onclick="restAPI('neomatrix/stop', true)">⏹️ Stop Animation</button>
48
+ <button onclick="restAPI('neomatrix/snake', true)">▶️ Start Animation</button>
49
+ </div>
50
+
51
+ <!-- Matrix left, tools right -->
52
+ <div class="layout">
53
+ <!-- Matrix grid -->
54
+ <div id="matrix" class="matrix"></div>
55
+
56
+ <!-- Side panel -->
57
+ <div class="side-panel">
58
+ <!-- Read device state -->
59
+ <button id="readStateBtn" onclick="getMatrixState()">📥 Read Matrix State</button>
60
+ <textarea id="matrixStateOut" rows="4"
61
+ placeholder="Matrix state (original format) will appear here on ONE line…"></textarea>
62
+
63
+ <!-- Send Matrix Data -->
64
+ <h3>📤 Send Matrix Data</h3>
65
+ <textarea id="matrixInput" rows="6"
66
+ placeholder="Paste like: [(0,0,(131,17,0)), (1,0,(...)), ...]"></textarea>
67
+ <div style="display:flex;gap:10px;flex-wrap:wrap;justify-content:center">
68
+ <button id="sendMatrixBtn" onclick="sendMatrixFromInput()">🚀 Send (batched 15)</button>
69
+ <button onclick="applyMatrixInputLocally()">🖌️ Apply Locally</button>
70
+ </div>
71
+ <p id="matrixInputStatus" style="margin:6px auto;color:#9cf;text-align:center"></p>
72
+ </div>
73
+ </div>
74
+
75
+ <!-- REST Debug Console -->
76
+ <hr>
77
+ <h3>🛠 REST Debug Console</h3>
78
+ <p id="restConsoleUrl"></p>
79
+ <pre id="restConsoleResponse"></pre>
80
+ <p id="restConsoleTime"></p>
81
+
82
+ <!-- === ORIGINAL SCRIPT (unchanged except pointerleave/mouseleave for robustness) === -->
83
+ <script>
84
+ const matrixContainer = document.getElementById('matrix');
85
+ const colorPicker = document.getElementById('colorPicker');
86
+ const sizeInput = document.getElementById('matrixSize');
87
+ let pixels = [];
88
+ let drawing = false;
89
+ let activePointerId = null;
90
+ const supportsPointer = window.PointerEvent;
91
+
92
+ // Track last painted pixel
93
+ let lastX = null;
94
+ let lastY = null;
95
+
96
+ // --- Queue system (no overlapping REST calls) ---
97
+ let updateQueue = [];
98
+ let updating = false;
99
+
100
+ async function processQueue() {
101
+ if (updating || updateQueue.length === 0) return;
102
+ updating = true;
103
+ const { cmd } = updateQueue.shift();
104
+ try {
105
+ await restAPI(cmd, true);
106
+ } catch (err) {
107
+ console.warn("REST call failed:", err);
108
+ }
109
+ updating = false;
110
+ if (updateQueue.length > 0) processQueue();
111
+ }
112
+
113
+ function queueUpdate(cmd) {
114
+ updateQueue.push({ cmd });
115
+ processQueue();
116
+ }
117
+ // -------------------------------------------------
118
+
119
+ function startDrawing(e) {
120
+ drawing = true;
121
+ if (supportsPointer) {
122
+ activePointerId = e.pointerId;
123
+ matrixContainer.setPointerCapture(activePointerId);
124
+ }
125
+ paintPixel(e.target);
126
+ e.preventDefault();
127
+ }
128
+
129
+ function moveDrawing(e) {
130
+ if (!drawing) return;
131
+ let target;
132
+ if (supportsPointer) {
133
+ target = document.elementFromPoint(e.clientX, e.clientY);
134
+ } else if (e.touches && e.touches.length) {
135
+ const t = e.touches[0];
136
+ target = document.elementFromPoint(t.clientX, t.clientY);
137
+ e.preventDefault();
138
+ } else {
139
+ target = document.elementFromPoint(e.clientX, e.clientY);
140
+ }
141
+ if (target && target.classList.contains('pixel')) {
142
+ paintPixel(target);
143
+ }
144
+ }
145
+
146
+ function stopDrawing() {
147
+ drawing = false;
148
+ lastX = null;
149
+ lastY = null;
150
+ if (supportsPointer && activePointerId !== null) {
151
+ matrixContainer.releasePointerCapture(activePointerId);
152
+ activePointerId = null;
153
+ }
154
+ }
155
+
156
+ if (supportsPointer) {
157
+ matrixContainer.addEventListener('pointermove', moveDrawing);
158
+ window.addEventListener('pointerup', stopDrawing);
159
+ window.addEventListener('pointercancel', stopDrawing);
160
+ matrixContainer.addEventListener('pointerleave', stopDrawing); // added
161
+ } else {
162
+ matrixContainer.addEventListener('mousemove', moveDrawing);
163
+ matrixContainer.addEventListener('touchmove', moveDrawing, { passive: false });
164
+ window.addEventListener('mouseup', stopDrawing);
165
+ window.addEventListener('touchend', stopDrawing);
166
+ window.addEventListener('touchcancel', stopDrawing);
167
+ matrixContainer.addEventListener('mouseleave', stopDrawing); // added
168
+ }
169
+
170
+ function hexToRgb(hex) {
171
+ const val = parseInt(hex.slice(1), 16);
172
+ return [(val >> 16) & 255, (val >> 8) & 255, val & 255];
173
+ }
174
+
175
+ function buildMatrix(size) {
176
+ matrixContainer.innerHTML = "";
177
+ pixels = [];
178
+ matrixContainer.style.gridTemplateColumns = `repeat(${size}, 30px)`;
179
+ matrixContainer.style.gridTemplateRows = `repeat(${size}, 30px)`;
180
+
181
+ for (let y = 0; y < size; y++) {
182
+ for (let x = 0; x < size; x++) {
183
+ const cell = document.createElement('div');
184
+ cell.className = "pixel";
185
+ cell.dataset.x = x;
186
+ cell.dataset.y = y;
187
+ cell.dataset.color = "#000000";
188
+ cell.style.backgroundColor = "#000000";
189
+ if (supportsPointer) {
190
+ cell.addEventListener('pointerdown', startDrawing);
191
+ } else {
192
+ cell.addEventListener('mousedown', startDrawing);
193
+ cell.addEventListener('touchstart', startDrawing, { passive: false });
194
+ }
195
+ matrixContainer.appendChild(cell);
196
+ pixels.push(cell);
197
+ }
198
+ }
199
+ sendClearCommand();
200
+ }
201
+
202
+ function paintPixel(pixelDiv) {
203
+ const color = colorPicker.value;
204
+ const x = parseInt(pixelDiv.dataset.x);
205
+ const y = parseInt(pixelDiv.dataset.y);
206
+
207
+ // Only update if new pixel
208
+ if (x === lastX && y === lastY) return;
209
+ lastX = x;
210
+ lastY = y;
211
+
212
+ pixelDiv.dataset.color = color;
213
+ pixelDiv.style.backgroundColor = color;
214
+
215
+ const [r, g, b] = hexToRgb(color);
216
+ const cmd = `neomatrix/draw_colormap/[(${x},${y},(${r},${g},${b}))]`;
217
+ queueUpdate(cmd);
218
+ }
219
+
220
+ function clearMatrix() {
221
+ pixels.forEach(p => {
222
+ p.dataset.color = "#000000";
223
+ p.style.backgroundColor = "#000000";
224
+ });
225
+ sendClearCommand();
226
+ }
227
+
228
+ function sendClearCommand() {
229
+ queueUpdate("neomatrix/draw_colormap/[]");
230
+ }
231
+
232
+ function applySize() {
233
+ buildMatrix(parseInt(sizeInput.value, 10));
234
+ }
235
+
236
+ // Initialize matrix
237
+ buildMatrix(parseInt(sizeInput.value, 10));
238
+
239
+ document.addEventListener("DOMContentLoaded", function() {
240
+ // Add device info
241
+ restInfo(showPages=false);
242
+ });
243
+ </script>
244
+ <!-- === END original script === -->
245
+
246
+ <!-- === getMatrixState (robust parsing + auto-resize) === -->
247
+ <script>
248
+ // tolerant tuple parser used here and by sender
249
+ function parseTuplesRegex(str) {
250
+ if (!str || typeof str !== 'string') return null;
251
+ const out = [];
252
+ const re = /\(\s*(\d+)\s*,\s*(\d+)\s*,\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*\)/g;
253
+ let m;
254
+ while ((m = re.exec(str)) !== null) {
255
+ out.push({ x:+m[1], y:+m[2], r:+m[3], g:+m[4], b:+m[5] });
256
+ }
257
+ return out.length ? out : null;
258
+ }
259
+
260
+ function rgbToHex(r, g, b) {
261
+ const toHex = (n) => Math.max(0, Math.min(255, n|0)).toString(16).padStart(2, '0');
262
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
263
+ }
264
+ function blackoutMatrixUI() {
265
+ const cells = document.querySelectorAll('.pixel');
266
+ cells.forEach(p => { p.dataset.color = "#000000"; p.style.backgroundColor = "#000000"; });
267
+ }
268
+ function ensureGridFits(cells) {
269
+ if (!Array.isArray(cells) || !cells.length) return;
270
+ const maxX = Math.max(...cells.map(c => c.x));
271
+ const maxY = Math.max(...cells.map(c => c.y));
272
+ const need = Math.max(maxX, maxY) + 1;
273
+ const current = parseInt(document.getElementById('matrixSize').value, 10) || 8;
274
+ if (need > current) {
275
+ document.getElementById('matrixSize').value = need;
276
+ applySize();
277
+ }
278
+ }
279
+
280
+ async function getMatrixState() {
281
+ const btn = document.getElementById('readStateBtn');
282
+ const out = document.getElementById('matrixStateOut');
283
+ if (btn) btn.disabled = true;
284
+ if (out) out.value = "Reading…";
285
+
286
+ try {
287
+ const resp = await restAPI('neomatrix/get_colormap', true);
288
+
289
+ // Extract original tuple-like data as a string
290
+ let raw = '';
291
+ if (resp && typeof resp === 'object' && 'result' in resp) raw = String(resp.result);
292
+ else if (typeof resp === 'string') raw = resp;
293
+ else if (resp && typeof resp.text === 'string') raw = resp.text;
294
+ else if (resp && typeof resp.body === 'string') raw = resp.body;
295
+ else raw = JSON.stringify(resp);
296
+
297
+ // Single-line for easy copy
298
+ const oneLine = String(raw).replace(/[\r\n]+/g, ' ').trim();
299
+ if (out) out.value = oneLine;
300
+
301
+ const parsed = parseTuplesRegex(oneLine);
302
+ blackoutMatrixUI();
303
+ if (!parsed) return;
304
+
305
+ ensureGridFits(parsed);
306
+
307
+ for (const {x,y,r,g,b} of parsed) {
308
+ const cell = document.querySelector(`.pixel[data-x="${x}"][data-y="${y}"]`);
309
+ if (!cell) continue;
310
+ const hex = rgbToHex(r,g,b);
311
+ cell.dataset.color = hex;
312
+ cell.style.backgroundColor = hex;
313
+ }
314
+ } catch (e) {
315
+ if (out) out.value = "Error: could not read matrix state.";
316
+ blackoutMatrixUI();
317
+ } finally {
318
+ if (btn) btn.disabled = false;
319
+ }
320
+ }
321
+ // expose globally (matches your original pattern)
322
+ window.getMatrixState = getMatrixState;
323
+ </script>
324
+ <!-- === END getMatrixState === -->
325
+
326
+ <!-- === SENDER: GLOBAL FUNCTIONS (fixes ReferenceError) === -->
327
+ <script>
328
+ function setSenderStatus(msg, isError=false){
329
+ const el = document.getElementById('matrixInputStatus');
330
+ if (!el) return;
331
+ el.textContent = msg;
332
+ el.style.color = isError ? '#f99' : '#9cf';
333
+ }
334
+ function applyCellsToUI(cells){
335
+ for (const {x,y,r,g,b} of cells) {
336
+ const cell = document.querySelector(`.pixel[data-x="${x}"][data-y="${y}"]`);
337
+ if (!cell) continue;
338
+ const toHex = n => Math.max(0,Math.min(255,n|0)).toString(16).padStart(2,'0');
339
+ const hex = `#${toHex(r)}${toHex(g)}${toHex(b)}`;
340
+ cell.dataset.color = hex;
341
+ cell.style.backgroundColor = hex;
342
+ }
343
+ }
344
+ function buildPayload(cells){
345
+ const parts = cells.map(({x,y,r,g,b}) => `(${x},${y},(${r},${g},${b}))`);
346
+ return `[${parts.join(',')}]`.replace(/\//g, '');
347
+ }
348
+
349
+ // Make these GLOBAL so inline onclick finds them:
350
+ function applyMatrixInputLocally(){
351
+ const raw = (document.getElementById('matrixInput')?.value || '').trim();
352
+ const parsed = parseTuplesRegex(raw);
353
+ if (!parsed) { setSenderStatus('Could not parse input. Use [(x,y,(r,g,b)), ...]', true); return; }
354
+ applyCellsToUI(parsed);
355
+ setSenderStatus(`Applied ${parsed.length} cells locally.`);
356
+ }
357
+
358
+ function sendMatrixFromInput(){
359
+ const btn = document.getElementById('sendMatrixBtn');
360
+ const raw = (document.getElementById('matrixInput')?.value || '').trim();
361
+ const parsed = parseTuplesRegex(raw);
362
+ if (!parsed) { setSenderStatus('Could not parse input. Use [(x,y,(r,g,b)), ...]', true); return; }
363
+
364
+ if (btn) btn.disabled = true;
365
+ setSenderStatus(`Sending ${parsed.length} cells in batches of 15…`);
366
+
367
+ // Update UI immediately for responsiveness
368
+ applyCellsToUI(parsed);
369
+
370
+ const CHUNK = 10;
371
+ let sent = 0;
372
+ for (let i = 0; i < parsed.length; i += CHUNK) {
373
+ const chunk = parsed.slice(i, i + CHUNK);
374
+ const payload = buildPayload(chunk);
375
+ const cmd = `neomatrix/draw_colormap/${payload}`;
376
+ queueUpdate(cmd);
377
+ sent += chunk.length;
378
+ }
379
+
380
+ setSenderStatus(`Queued ${sent} cells in ${Math.ceil(parsed.length / CHUNK)} batch(es).`);
381
+ if (btn) btn.disabled = false;
382
+ }
383
+
384
+ // Expose on window explicitly (paranoia, but harmless)
385
+ window.applyMatrixInputLocally = applyMatrixInputLocally;
386
+ window.sendMatrixFromInput = sendMatrixFromInput;
387
+ </script>
388
+ <!-- === END sender === -->
389
+ </body>
390
+ </html>
micrOS/source/web/uapi.js CHANGED
@@ -41,18 +41,21 @@ function restConsole(apiUrl, data, delta) {
41
41
  document.getElementById('restConsoleTime').innerHTML = `⏱ Response time: ${delta} ms`;
42
42
  }
43
43
 
44
- function restInfo() {
44
+ function restInfo(showPages=true) {
45
45
  // UPDATES: 'restInfo' and restConsole(...)
46
- restAPICore(cmd='').then(({ response, delta, query }) => {
46
+ restAPICore(cmd = '').then(({ response, delta, query }) => {
47
47
  // Update API Console
48
48
  restConsole(query, response, delta)
49
- // Update 'SysApiInfo' tag
49
+ // Update 'restInfo' tag
50
50
  const result = response['result'];
51
51
  const auth = result.auth ? "🔑" : "";
52
52
  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(' | ') : '');
53
+ let infoSubpages = "";
54
+ if (showPages && result['usr_endpoints']) {
55
+ infoSubpages = "<br><br>📎 " + Object.entries(result['usr_endpoints'])
56
+ .map(([key, value]) => `<a href="${value}" target="_blank" style="color: white;">${value} </a>`)
57
+ .join(' | ');
58
+ }
56
59
  document.getElementById('restInfo').innerHTML = infoHeader + infoSubpages;
57
60
  }).catch(error => {
58
61
  console.error('Error in restAPI:', error);
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: micrOSDevToolKit
3
- Version: 2.13.1
3
+ Version: 2.17.1
4
4
  Summary: Development and deployment environment for micrOS, the diy micropython automation OS (IoT)
5
5
  Home-page: https://github.com/BxNxM/micrOS
6
6
  Author: Marcell Ban
@@ -93,7 +93,7 @@ Access rest api over browser: `http://<nodename>.local`
93
93
  6. micrOS Node configuration [link](https://github.com/BxNxM/micrOS/#micros-node-configuration-parameters-with-description)
94
94
  7. 🧑‍💻 micrOS create custom Load Modules: [link](./APPLICATION_GUIDE.md)
95
95
  8. micrOS Gateway server with Prometheus&Grafana: [link](https://github.com/BxNxM/micrOS/#micros-gateway-in-docker)
96
- 9. Release notes: [link](https://github.com/BxNxM/micrOS/#relese-note)
96
+ 9. Release notes: [release-note](https://github.com/BxNxM/micrOS/#release-note)
97
97
 
98
98
  ----------------------------------------
99
99
  ----------------------------------------
@@ -366,11 +366,11 @@ So prefer boards with more psram 2Mb-8Mb, **minumum requirement for the full fla
366
366
 
367
367
  LogicalPin lookup tables:
368
368
 
369
- - [tinypico](./micrOS/source/IO_tinypico.py)
370
- - [esp32](./micrOS/source/IO_esp32.py)
371
- - [esp32s2](./micrOS/source/IO_esp32s2.py)
372
- - [esp32s3](./micrOS/source/IO_esp32s3.py)
373
- - [raspberryPicoW](./micrOS/source/IO_rp2.py) - reset needed after ota update (webrepl limitation)
369
+ - [tinypico](micrOS/source/modules/IO_tinypico.py)
370
+ - [esp32](micrOS/source/modules/IO_esp32.py)
371
+ - [esp32s2](micrOS/source/modules/IO_esp32s2.py)
372
+ - [esp32s3](micrOS/source/modules/IO_esp32s3.py)
373
+ - [raspberryPicoW](micrOS/source/modules/IO_rp2.py) - reset needed after ota update (webrepl limitation)
374
374
  - `IO_*.py` [etc.](./micrOS/source)
375
375
 
376
376
  > Note: Good idea to use costant variable for pin map declaration, check the files for more info, These files are also precompiled automatically into byte streams -> `.mpy`
@@ -500,13 +500,13 @@ Version **3.0.0-0** `micrOS-Autonomous`
500
500
  - (3) New intercon syntax - command level integration: [DONE]
501
501
  - rgb toggle >>RingLight.local
502
502
  - similar as (obsolete): intercon sendcmd host="RingLight.local" cmd="rgb toggle"
503
- - (4) Create multi level project structure (curret is flat fs) [TODO] FS
503
+ - (4) Create multi level project structure (curret is flat fs) [WIP] FS
504
504
  - New micrOS FS structure:
505
- - Automatic dir creation at bootup: '/logs', '/web', '/data'
505
+ - Automatic dir creation at bootup: '/logs', '/web', '/data', '/config', '/modules'
506
506
  - Automatic sub-dir handling /source and /precompiled
507
507
  - Automatic dir creation over USB
508
508
 
509
- Structure:
509
+ System Core File Structure:
510
510
  - [DONE] root fs (stays untouched (approx.: 24)): /
511
511
  - micrOS.py (core)
512
512
  - Config.py (core)
@@ -514,31 +514,33 @@ Version **3.0.0-0** `micrOS-Autonomous`
514
514
  - Shell.py (core)
515
515
  - Web.py (core)
516
516
  - Server.py (core)
517
- - node_config,json (core config)
518
517
  - etc... (core)
519
-
520
518
  - [DONE] web folder: /web
521
519
  - *.html
522
520
  - *.js
523
521
  - *.css
524
522
  - etc.
525
-
526
- - [DONE] /logs
527
- - still there (created runtime)
528
-
529
- - [TODO] module folder /modules - (mip complient: /modules/lib)
523
+ - [DONE][RUNTIME] data folder: /data
524
+ - Dynamic/Runtime (approx.: 0-8):
525
+ - *.pds (LM app cache - persistent data storage)
526
+ - *.dat (Common datalogger output)
527
+ - Or store any application data here
528
+ - [DONE][RUNTIME] logs folder: /logs
529
+ - *.log
530
+ - *.sys.log
531
+ - [DONE] config folder /config
532
+ - node_config.json (core config)
533
+ - *.key files (offloaded core config values, like: guimeta)
534
+ - [DONE] module folder /modules - (mip complient: /modules/lib)
530
535
  - LM_* (approx.: 54)
531
536
  - IO_* (approx.: 5)
532
- - *.py/.mpy (driver)
533
- - Dynamic/Runtime (approx.: 0-8):
534
- - *.pds (LM app cache - persistent data storage)
535
- - *.dat (Common datalogger output)
536
537
 
537
- - (5) [TODO] Proper mip installer support (/modules or /modules/lib or /web)
538
+
539
+ - (5) [TODO] Proper mip installer support (/modules or /lib or /web)
538
540
  - Note: Autonomous package management over wifi (github)
539
- - pacman download
540
- - pacman ls
541
- - pacman dirtree
541
+ - pacman download [POC][DONE][TODO]
542
+ - pacman ls [DONE]
543
+ - pacman dirtree [DONE]
542
544
  - pacman ...
543
545
  ```
544
546
 
@@ -552,23 +554,14 @@ Version **3.1.0-0** `micrOS-SecurePower`
552
554
  - Remote controller / Sensor UseCase
553
555
  - --- client mode (fyi: normally micrOS operates in server mode)
554
556
  - Intercon-Wire (?)
555
- - Idea of wired message communication protocol same as Intercon-Shell/Intercon-espnow
557
+ - Idea of wired message communication protocol same as Intercon-Shell/Intercon-ESPNow
556
558
  - Possible HW protocols: i2c / onewire / uart BUT it should support bidirectional message transfers
557
559
  - Goal: CoProcessor easy integration feature - Arduino env support
558
560
  ```
559
561
 
560
- Version **4.0.0-0** `micrOS-???`
561
-
562
- ```
563
- Core:
564
- - Network stack redesign
565
- - Network
566
- - wifi (defualt, current interfaces)
567
- - Study of BLE (Shell)
568
- - Com. (wifi/now/ble...lora?/etc?.) as plugin architecture (?)
569
- - Low power mode (with BLE) and soft-sleep / deep-sleep
570
- ```
571
562
 
563
+ <a id="release-note"></a>
564
+ ## Release notes
572
565
 
573
566
  | VERSION (TAG) | RELEASE INFO | MICROS CORE MEMORY USAGE | SUPPORTED DEVICE(S) | APP PROFILES | Load Modules | NOTE |
574
567
  | :----------: | :----------------: | :------------------------: | :-----------------: | :------------: | :------------:| -------------- |