micrOSDevToolKit 2.10.6__py3-none-any.whl → 2.11.0__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.
- env/driver_cp210x/macOS_VCP_Driver/SiLabsUSBDriverDisk.dmg +0 -0
- env/driver_cp210x/macOS_VCP_Driver/macOS_VCP_Driver_Release_Notes.txt +17 -1
- micrOS/micropython/esp32c6-GENERIC-20250415-v1.25.0.bin +0 -0
- micrOS/micropython/esp32s3-4MBflash-20241129-v1.24.1.bin +0 -0
- micrOS/release_info/micrOS_ReleaseInfo/system_analysis_sum.json +45 -49
- micrOS/source/Common.py +262 -87
- micrOS/source/Debug.py +44 -88
- micrOS/source/Espnow.py +1 -1
- micrOS/source/Files.py +21 -2
- micrOS/source/Hooks.py +60 -17
- micrOS/source/IO_esp32c6.py +16 -0
- micrOS/source/IO_esp32s3.py +37 -1
- micrOS/source/IO_m5stamp.py +35 -1
- micrOS/source/IO_qtpy.py +22 -17
- micrOS/source/IO_s3matrix.py +21 -0
- micrOS/source/IO_tinypico.py +38 -0
- micrOS/source/LM_VL53L0X.py +1 -1
- micrOS/source/LM_buzzer.py +6 -7
- micrOS/source/LM_cct.py +6 -5
- micrOS/source/LM_dimmer.py +6 -5
- micrOS/source/LM_espnow.py +15 -10
- micrOS/source/LM_i2c.py +3 -2
- micrOS/source/LM_neoeffects.py +173 -230
- micrOS/source/LM_neomatrix.py +305 -0
- micrOS/source/LM_neopixel.py +10 -10
- micrOS/source/LM_pacman.py +25 -21
- micrOS/source/LM_qmi8658.py +204 -0
- micrOS/source/LM_rgb.py +6 -6
- micrOS/source/LM_roboarm.py +5 -4
- micrOS/source/LM_switch.py +6 -4
- micrOS/source/LM_tcs3472.py +75 -0
- micrOS/source/LM_telegram.py +5 -4
- micrOS/source/Logger.py +46 -32
- micrOS/source/Shell.py +1 -1
- micrOS/source/Tasks.py +7 -4
- micrOS/source/Time.py +5 -3
- micrOS/source/__pycache__/Common.cpython-312.pyc +0 -0
- micrOS/source/__pycache__/Logger.cpython-312.pyc +0 -0
- micrOS/source/micrOS.py +5 -2
- micrOS/source/microIO.py +8 -6
- {microsdevtoolkit-2.10.6.dist-info → microsdevtoolkit-2.11.0.dist-info}/METADATA +2 -1
- {microsdevtoolkit-2.10.6.dist-info → microsdevtoolkit-2.11.0.dist-info}/RECORD +92 -87
- toolkit/DevEnvUSB.py +5 -0
- toolkit/LM_to_compile.dat +1 -0
- toolkit/dashboard_apps/NeoEffectsDemo.py +8 -15
- toolkit/dashboard_apps/QMI8685_GYRO.py +68 -0
- toolkit/dashboard_apps/_app_base.py +2 -2
- toolkit/dashboard_apps/_gyro_visualizer.py +78 -0
- toolkit/simulator_lib/__pycache__/IO_darwin.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/machine.cpython-312.pyc +0 -0
- toolkit/simulator_lib/__pycache__/neopixel.cpython-312.pyc +0 -0
- toolkit/simulator_lib/machine.py +0 -1
- toolkit/simulator_lib/neopixel.py +3 -2
- toolkit/socketClient.py +3 -2
- toolkit/workspace/precompiled/Common.mpy +0 -0
- toolkit/workspace/precompiled/Debug.mpy +0 -0
- toolkit/workspace/precompiled/Espnow.mpy +0 -0
- toolkit/workspace/precompiled/Files.mpy +0 -0
- toolkit/workspace/precompiled/Hooks.mpy +0 -0
- toolkit/workspace/precompiled/IO_esp32c6.mpy +0 -0
- toolkit/workspace/precompiled/IO_esp32s3.mpy +0 -0
- toolkit/workspace/precompiled/IO_m5stamp.mpy +0 -0
- toolkit/workspace/precompiled/IO_qtpy.mpy +0 -0
- toolkit/workspace/precompiled/IO_s3matrix.mpy +0 -0
- toolkit/workspace/precompiled/IO_tinypico.mpy +0 -0
- toolkit/workspace/precompiled/LM_VL53L0X.py +1 -1
- toolkit/workspace/precompiled/LM_buzzer.mpy +0 -0
- toolkit/workspace/precompiled/LM_cct.mpy +0 -0
- toolkit/workspace/precompiled/LM_dimmer.mpy +0 -0
- toolkit/workspace/precompiled/LM_espnow.py +15 -10
- toolkit/workspace/precompiled/LM_i2c.py +3 -2
- toolkit/workspace/precompiled/LM_neoeffects.mpy +0 -0
- toolkit/workspace/precompiled/LM_neomatrix.mpy +0 -0
- toolkit/workspace/precompiled/LM_neopixel.mpy +0 -0
- toolkit/workspace/precompiled/LM_pacman.mpy +0 -0
- toolkit/workspace/precompiled/LM_qmi8658.py +204 -0
- toolkit/workspace/precompiled/LM_rgb.mpy +0 -0
- toolkit/workspace/precompiled/LM_roboarm.mpy +0 -0
- toolkit/workspace/precompiled/LM_switch.mpy +0 -0
- toolkit/workspace/precompiled/LM_tcs3472.py +75 -0
- toolkit/workspace/precompiled/LM_telegram.mpy +0 -0
- toolkit/workspace/precompiled/Logger.mpy +0 -0
- toolkit/workspace/precompiled/Shell.mpy +0 -0
- toolkit/workspace/precompiled/Tasks.mpy +0 -0
- toolkit/workspace/precompiled/Time.mpy +0 -0
- toolkit/workspace/precompiled/micrOS.mpy +0 -0
- toolkit/workspace/precompiled/microIO.mpy +0 -0
- micrOS/micropython/esp32s3-20240105-v1.22.1.bin +0 -0
- micrOS/source/LM_catgame.py +0 -75
- micrOS/source/LM_demo.py +0 -97
- micrOS/source/LM_intercon.py +0 -60
- micrOS/source/LM_ph_sensor.py +0 -51
- toolkit/workspace/precompiled/LM_catgame.py +0 -75
- toolkit/workspace/precompiled/LM_demo.py +0 -97
- toolkit/workspace/precompiled/LM_intercon.mpy +0 -0
- toolkit/workspace/precompiled/LM_ph_sensor.py +0 -51
- /micrOS/micropython/{esp32s3-20241129-v1.24.1.bin → esp32s3-8MBflash-20241129-v1.24.1.bin} +0 -0
- {microsdevtoolkit-2.10.6.data → microsdevtoolkit-2.11.0.data}/scripts/devToolKit.py +0 -0
- {microsdevtoolkit-2.10.6.dist-info → microsdevtoolkit-2.11.0.dist-info}/WHEEL +0 -0
- {microsdevtoolkit-2.10.6.dist-info → microsdevtoolkit-2.11.0.dist-info}/licenses/LICENSE +0 -0
- {microsdevtoolkit-2.10.6.dist-info → microsdevtoolkit-2.11.0.dist-info}/top_level.txt +0 -0
|
Binary file
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
CP210x Macintosh OS VCP Driver v6 Release Notes
|
|
2
|
-
Copyright (C) 2017-
|
|
2
|
+
Copyright (C) 2017-2025 Silicon Laboratories Inc.
|
|
3
3
|
|
|
4
4
|
This release contains the following components:
|
|
5
5
|
|
|
@@ -32,6 +32,7 @@ Uninstalling the Driver
|
|
|
32
32
|
|
|
33
33
|
Release Dates
|
|
34
34
|
-------------
|
|
35
|
+
CP210x Macintosh OS VCP Driver 6.0.3 - May 23, 2025
|
|
35
36
|
CP210x Macintosh OS VCP Driver 6.0.2 - October 26, 2021
|
|
36
37
|
CP210x Macintosh OS VCP Driver 6.0.1 - March 26, 2021
|
|
37
38
|
CP210x Macintosh OS VCP Driver 6.0 - December 18, 2020
|
|
@@ -73,6 +74,21 @@ Release Dates
|
|
|
73
74
|
|
|
74
75
|
CP210x Macintosh OS Driver Revision History
|
|
75
76
|
--------------------------------------------
|
|
77
|
+
Version 6.0.3
|
|
78
|
+
Added a feature where the CP210x device sends an XOFF signal to the connected device when macOS goes to sleep.
|
|
79
|
+
Resolved an issue with driver uninstallation on macOS 13.
|
|
80
|
+
Fixed an issue where the Mac OSX CP210x v6.0.2 VCP Driver could crash during stress testing.
|
|
81
|
+
Added VID/PID for UAB DIELEKTRIK.
|
|
82
|
+
Added VID/PID for Quell Tech Ltd.
|
|
83
|
+
Added VID/PID for Profoto.
|
|
84
|
+
Added VID/PID for Cambo Fotografische Industrie BV.
|
|
85
|
+
Added VID/PID for ZTC WND-7300.
|
|
86
|
+
Added VID/PID for Integrel Solutions Ltd.
|
|
87
|
+
Added VID/PID for BRAIN MAGIC.
|
|
88
|
+
Added VID/PID for ELV Elektronik AG.
|
|
89
|
+
Added VID/PID for TDK Corporation.
|
|
90
|
+
Added VID/PID for Regula Forensics.
|
|
91
|
+
Added VID/PID for ALC Embedded Systems Ltd.
|
|
76
92
|
Version 6.0.2
|
|
77
93
|
On macOS Big Sur:
|
|
78
94
|
Fix issue that Xoff state is not remembered when macOS goes to sleep.
|
|
Binary file
|
|
Binary file
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"files": {
|
|
3
3
|
"Time.py": [
|
|
4
|
-
9.
|
|
5
|
-
|
|
4
|
+
9.17,
|
|
5
|
+
6
|
|
6
6
|
],
|
|
7
7
|
"Files.py": [
|
|
8
|
-
9.
|
|
9
|
-
|
|
8
|
+
9.35,
|
|
9
|
+
8
|
|
10
10
|
],
|
|
11
11
|
"micrOSloader.py": [
|
|
12
12
|
7.33,
|
|
13
13
|
1
|
|
14
14
|
],
|
|
15
15
|
"Hooks.py": [
|
|
16
|
-
9.
|
|
16
|
+
9.67,
|
|
17
17
|
1
|
|
18
18
|
],
|
|
19
19
|
"Server.py": [
|
|
@@ -46,22 +46,22 @@
|
|
|
46
46
|
],
|
|
47
47
|
"Types.py": [
|
|
48
48
|
8.91,
|
|
49
|
-
|
|
49
|
+
28
|
|
50
50
|
],
|
|
51
51
|
"Logger.py": [
|
|
52
|
-
|
|
52
|
+
9.05,
|
|
53
53
|
4
|
|
54
54
|
],
|
|
55
55
|
"Common.py": [
|
|
56
|
-
9.
|
|
57
|
-
|
|
56
|
+
9.84,
|
|
57
|
+
34
|
|
58
58
|
],
|
|
59
59
|
"InterConnect.py": [
|
|
60
60
|
9.41,
|
|
61
|
-
|
|
61
|
+
2
|
|
62
62
|
],
|
|
63
63
|
"Debug.py": [
|
|
64
|
-
|
|
64
|
+
7.37,
|
|
65
65
|
18
|
|
66
66
|
],
|
|
67
67
|
"Network.py": [
|
|
@@ -69,19 +69,19 @@
|
|
|
69
69
|
8
|
|
70
70
|
],
|
|
71
71
|
"Espnow.py": [
|
|
72
|
-
9.
|
|
73
|
-
|
|
72
|
+
9.57,
|
|
73
|
+
2
|
|
74
74
|
],
|
|
75
75
|
"Scheduler.py": [
|
|
76
76
|
9.62,
|
|
77
77
|
1
|
|
78
78
|
],
|
|
79
79
|
"microIO.py": [
|
|
80
|
-
9.
|
|
81
|
-
|
|
80
|
+
9.44,
|
|
81
|
+
43
|
|
82
82
|
],
|
|
83
83
|
"micrOS.py": [
|
|
84
|
-
9.
|
|
84
|
+
9.27,
|
|
85
85
|
1
|
|
86
86
|
],
|
|
87
87
|
"Interrupts.py": [
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
5
|
|
98
98
|
],
|
|
99
99
|
"LM_roboarm.py": [
|
|
100
|
-
7.
|
|
100
|
+
7.78,
|
|
101
101
|
0
|
|
102
102
|
],
|
|
103
103
|
"LM_stepper.py": [
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
1
|
|
106
106
|
],
|
|
107
107
|
"LM_pacman.py": [
|
|
108
|
-
8.
|
|
108
|
+
8.95,
|
|
109
109
|
0
|
|
110
110
|
],
|
|
111
111
|
"LM_genIO.py": [
|
|
@@ -124,6 +124,10 @@
|
|
|
124
124
|
7.57,
|
|
125
125
|
0
|
|
126
126
|
],
|
|
127
|
+
"LM_qmi8658.py": [
|
|
128
|
+
9.1,
|
|
129
|
+
0
|
|
130
|
+
],
|
|
127
131
|
"LM_co2.py": [
|
|
128
132
|
8.5,
|
|
129
133
|
0
|
|
@@ -132,6 +136,10 @@
|
|
|
132
136
|
8.18,
|
|
133
137
|
0
|
|
134
138
|
],
|
|
139
|
+
"LM_tcs3472.py": [
|
|
140
|
+
9.02,
|
|
141
|
+
0
|
|
142
|
+
],
|
|
135
143
|
"LM_oled.py": [
|
|
136
144
|
9.09,
|
|
137
145
|
4
|
|
@@ -148,21 +156,17 @@
|
|
|
148
156
|
8.04,
|
|
149
157
|
0
|
|
150
158
|
],
|
|
151
|
-
"LM_ph_sensor.py": [
|
|
152
|
-
5.79,
|
|
153
|
-
0
|
|
154
|
-
],
|
|
155
159
|
"LM_buzzer.py": [
|
|
156
|
-
|
|
160
|
+
9.11,
|
|
157
161
|
0
|
|
158
162
|
],
|
|
159
163
|
"LM_switch.py": [
|
|
160
|
-
8.
|
|
164
|
+
8.68,
|
|
161
165
|
1
|
|
162
166
|
],
|
|
163
167
|
"LM_servo.py": [
|
|
164
168
|
7.73,
|
|
165
|
-
|
|
169
|
+
2
|
|
166
170
|
],
|
|
167
171
|
"LM_rgbcct.py": [
|
|
168
172
|
8.62,
|
|
@@ -181,11 +185,11 @@
|
|
|
181
185
|
0
|
|
182
186
|
],
|
|
183
187
|
"LM_neopixel.py": [
|
|
184
|
-
7.
|
|
188
|
+
7.54,
|
|
185
189
|
2
|
|
186
190
|
],
|
|
187
191
|
"LM_cct.py": [
|
|
188
|
-
9.
|
|
192
|
+
9.04,
|
|
189
193
|
1
|
|
190
194
|
],
|
|
191
195
|
"LM_L9110_DCmotor.py": [
|
|
@@ -193,7 +197,7 @@
|
|
|
193
197
|
0
|
|
194
198
|
],
|
|
195
199
|
"LM_neoeffects.py": [
|
|
196
|
-
|
|
200
|
+
9.09,
|
|
197
201
|
0
|
|
198
202
|
],
|
|
199
203
|
"LM_i2c.py": [
|
|
@@ -253,7 +257,7 @@
|
|
|
253
257
|
0
|
|
254
258
|
],
|
|
255
259
|
"LM_rgb.py": [
|
|
256
|
-
8.
|
|
260
|
+
8.88,
|
|
257
261
|
1
|
|
258
262
|
],
|
|
259
263
|
"LM_distance.py": [
|
|
@@ -289,25 +293,13 @@
|
|
|
289
293
|
0
|
|
290
294
|
],
|
|
291
295
|
"LM_dimmer.py": [
|
|
292
|
-
8.
|
|
296
|
+
8.33,
|
|
293
297
|
1
|
|
294
298
|
],
|
|
295
|
-
"LM_demo.py": [
|
|
296
|
-
8.57,
|
|
297
|
-
0
|
|
298
|
-
],
|
|
299
299
|
"LM_gameOfLife.py": [
|
|
300
300
|
9.29,
|
|
301
301
|
3
|
|
302
302
|
],
|
|
303
|
-
"LM_catgame.py": [
|
|
304
|
-
8.85,
|
|
305
|
-
0
|
|
306
|
-
],
|
|
307
|
-
"LM_intercon.py": [
|
|
308
|
-
8.18,
|
|
309
|
-
0
|
|
310
|
-
],
|
|
311
303
|
"LM_ds18.py": [
|
|
312
304
|
6.0,
|
|
313
305
|
2
|
|
@@ -319,16 +311,20 @@
|
|
|
319
311
|
"LM_sdcard.py": [
|
|
320
312
|
7.88,
|
|
321
313
|
0
|
|
314
|
+
],
|
|
315
|
+
"LM_neomatrix.py": [
|
|
316
|
+
8.72,
|
|
317
|
+
0
|
|
322
318
|
]
|
|
323
319
|
},
|
|
324
320
|
"summary": {
|
|
325
321
|
"core": [
|
|
326
|
-
|
|
322
|
+
3723,
|
|
327
323
|
24
|
|
328
324
|
],
|
|
329
325
|
"load": [
|
|
330
|
-
|
|
331
|
-
|
|
326
|
+
9410,
|
|
327
|
+
55
|
|
332
328
|
],
|
|
333
329
|
"core_dep": [
|
|
334
330
|
true,
|
|
@@ -336,10 +332,10 @@
|
|
|
336
332
|
],
|
|
337
333
|
"load_dep": [
|
|
338
334
|
true,
|
|
339
|
-
|
|
335
|
+
5
|
|
340
336
|
],
|
|
341
|
-
"core_score": 9.
|
|
342
|
-
"load_score": 8.
|
|
343
|
-
"version": "2.
|
|
337
|
+
"core_score": 9.19,
|
|
338
|
+
"load_score": 8.35,
|
|
339
|
+
"version": "2.11.0-0"
|
|
344
340
|
}
|
|
345
341
|
}
|
micrOS/source/Common.py
CHANGED
|
@@ -5,92 +5,23 @@ micrOS Load Module programming Official API-s
|
|
|
5
5
|
from Server import Server, WebCli
|
|
6
6
|
from Debug import errlog_add, console_write
|
|
7
7
|
from Logger import logger, log_get
|
|
8
|
+
from Files import OSPath, path_join
|
|
8
9
|
from microIO import resolve_pin
|
|
9
10
|
from Tasks import TaskBase, Manager, lm_exec
|
|
10
11
|
from machine import Pin, ADC
|
|
11
12
|
from Notify import Notify
|
|
12
13
|
|
|
13
|
-
################## Common LM features ##################
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
:param from_val: from value - start from
|
|
19
|
-
:param to_val: to value - target value
|
|
20
|
-
:param step_ms: step to reach to_val - timirq_seq
|
|
21
|
-
:param interval_sec: time of full interval
|
|
22
|
-
"""
|
|
23
|
-
if interval_sec > 0:
|
|
24
|
-
step_cnt = round((interval_sec*1000)/step_ms)
|
|
25
|
-
delta = abs((from_val-to_val)/step_cnt)
|
|
26
|
-
direc = -1 if from_val > to_val else 1
|
|
27
|
-
for cnt in range(0, step_cnt+1):
|
|
28
|
-
yield round(from_val + (cnt * delta) * direc)
|
|
29
|
-
else:
|
|
30
|
-
yield round(to_val)
|
|
15
|
+
#####################################################################################
|
|
16
|
+
# SYSTEM #
|
|
17
|
+
#####################################################################################
|
|
31
18
|
|
|
32
|
-
|
|
33
|
-
def transition_gen(*args, interval_sec=1.0):
|
|
19
|
+
def micro_task(tag:str, task=None):
|
|
34
20
|
"""
|
|
35
|
-
[LM]
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
:param interval_sec: interval in sec to calculate optimal fade/transition effect
|
|
40
|
-
return: gen, step_ms OR gen list, step_ms
|
|
41
|
-
"""
|
|
42
|
-
step_ms_min = 5 # min calculated step is 5 ms - good enough
|
|
43
|
-
delta = max((abs(args[ch_from_i] - args[ch_from_i+1]) for ch_from_i in range(0, len(args)-1, 2)))
|
|
44
|
-
step_ms = 0 if delta == 0 else int(interval_sec*1000 / delta)
|
|
45
|
-
step_ms = step_ms_min if step_ms < step_ms_min else step_ms
|
|
46
|
-
transitions = list((transition(args[ch_from_i], args[ch_from_i+1], step_ms, interval_sec) for ch_from_i in range(0, len(args)-1, 2)))
|
|
47
|
-
if len(transitions) == 1:
|
|
48
|
-
return transitions[0], step_ms
|
|
49
|
-
return list(transitions), step_ms
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
class SmartADC:
|
|
53
|
-
"""
|
|
54
|
-
[LM] General ADC implementation for auto scaled output: raw, percent, volt
|
|
55
|
-
https://docs.micropython.org/en/latest/esp32/quickref.html#adc-analog-to-digital-conversion
|
|
56
|
-
ADC.ATTN_0DB: 0 dB attenuation, resulting in a full-scale voltage range of 0-1.1V
|
|
57
|
-
ADC.ATTN_2_5DB: 2.5 dB ... of 0-1.5V
|
|
58
|
-
ADC.ATTN_6DB: 6 dB ... of 0-2.2V
|
|
59
|
-
ADC.ATTN_11DB: 11 dB ... of 0-2450mV/
|
|
60
|
-
Note that the absolute maximum voltage rating for input pins is 3.6V. Going near to this boundary risks damage to the IC!
|
|
61
|
-
"""
|
|
62
|
-
OBJS = {}
|
|
63
|
-
|
|
64
|
-
def __init__(self, pin):
|
|
65
|
-
self.adp_prop = (65535, 2450) # raw value, 2450mV (so 2,45V)
|
|
66
|
-
self.adc = None
|
|
67
|
-
if not isinstance(pin, int):
|
|
68
|
-
pin = resolve_pin(pin)
|
|
69
|
-
self.adc = ADC(Pin(pin))
|
|
70
|
-
self.adc.atten(ADC.ATTN_11DB) # 2450mV measure range
|
|
71
|
-
|
|
72
|
-
def get(self):
|
|
73
|
-
raw = int((self.adc.read_u16() + self.adc.read_u16())/2) # 16-bit ADC value (0-65535)
|
|
74
|
-
percent = raw / self.adp_prop[0]
|
|
75
|
-
volt = round(percent * self.adp_prop[1] / 1000, 2) # devide with 1000 to get V from mV
|
|
76
|
-
return {'raw': raw, 'percent': round(percent*100, 1), 'volt': volt}
|
|
77
|
-
|
|
78
|
-
@staticmethod
|
|
79
|
-
def get_instance(pin):
|
|
80
|
-
if pin in SmartADC.OBJS.keys():
|
|
81
|
-
return SmartADC.OBJS[pin]
|
|
82
|
-
SmartADC.OBJS[pin] = SmartADC(pin)
|
|
83
|
-
return SmartADC.OBJS[pin]
|
|
84
|
-
|
|
85
|
-
################# micrOS feature interfaces #################
|
|
86
|
-
|
|
87
|
-
def micro_task(tag, task=None):
|
|
88
|
-
"""
|
|
89
|
-
[LM] Async task creation
|
|
90
|
-
:param tag:
|
|
91
|
-
[1] tag=None: return task generator object
|
|
92
|
-
[2] tag=taskID: return existing task object by tag
|
|
93
|
-
:param task: coroutine to execute (with built-in overload protection and lcm)
|
|
21
|
+
[LM] Async task manager.
|
|
22
|
+
:param tag: task tag string
|
|
23
|
+
:param task: coroutine (or list of command arguments) to contract a task with the given async task callback
|
|
24
|
+
return bool|callable
|
|
94
25
|
"""
|
|
95
26
|
if task is None:
|
|
96
27
|
# [1] Task is None -> Get task mode by tag
|
|
@@ -103,11 +34,11 @@ def micro_task(tag, task=None):
|
|
|
103
34
|
return None
|
|
104
35
|
# [3] Create task (not running) + task coroutine was provided
|
|
105
36
|
# RETURN task creation state - success (True) / fail (False)
|
|
106
|
-
state = Manager().create_task(callback=task, tag=tag)
|
|
37
|
+
state:bool = Manager().create_task(callback=task, tag=tag)
|
|
107
38
|
return state
|
|
108
39
|
|
|
109
40
|
|
|
110
|
-
def manage_task(tag, operation):
|
|
41
|
+
def manage_task(tag:str, operation:str):
|
|
111
42
|
"""
|
|
112
43
|
[LM] Async task management
|
|
113
44
|
:param tag: task tag
|
|
@@ -125,19 +56,15 @@ def manage_task(tag, operation):
|
|
|
125
56
|
raise Exception(f"Invalid operation: {operation}")
|
|
126
57
|
|
|
127
58
|
|
|
128
|
-
def exec_cmd(cmd:list, jsonify:bool=None, skip_check=
|
|
59
|
+
def exec_cmd(cmd:list, jsonify:bool=None, skip_check=None):
|
|
129
60
|
"""
|
|
130
61
|
[LM] Single (sync) LM execution
|
|
131
62
|
:param cmd: command string list, ex.: ['system', 'clock']
|
|
132
63
|
:param jsonify: request json output
|
|
133
|
-
:param skip_check:
|
|
64
|
+
:param skip_check: legacy (check was removed) - remove parameter
|
|
134
65
|
return state, output
|
|
135
66
|
"""
|
|
136
|
-
|
|
137
|
-
# Invalid type, must be list: <class list>" ...
|
|
138
|
-
if skip_check:
|
|
139
|
-
return lm_exec(cmd, jsonify=jsonify)
|
|
140
|
-
return lm_exec(cmd, jsonify=jsonify) if isinstance(cmd, list) else False, f"CMD {type(cmd)}, must be list!"
|
|
67
|
+
return lm_exec(cmd, jsonify=jsonify)
|
|
141
68
|
|
|
142
69
|
|
|
143
70
|
def notify(text=None) -> bool:
|
|
@@ -216,3 +143,251 @@ def syslog(msg):
|
|
|
216
143
|
def console(msg):
|
|
217
144
|
""" Wrapper of console_write """
|
|
218
145
|
return console_write(msg)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def data_dir(f_name=None):
|
|
149
|
+
"""
|
|
150
|
+
Access for data dir path
|
|
151
|
+
:param f_name: if given, returns full path, otherwise returns data dir root path
|
|
152
|
+
"""
|
|
153
|
+
root_path = OSPath.DATA
|
|
154
|
+
if f_name is None:
|
|
155
|
+
return root_path
|
|
156
|
+
return path_join(root_path, f_name)
|
|
157
|
+
|
|
158
|
+
#####################################################################################
|
|
159
|
+
# CHANNEL: SIGNAL GENERATORS #
|
|
160
|
+
#####################################################################################
|
|
161
|
+
|
|
162
|
+
def transition(from_val, to_val, step_ms, interval_sec):
|
|
163
|
+
"""
|
|
164
|
+
[LM] Single Generator for color/value transition:
|
|
165
|
+
:param from_val: from value - start from
|
|
166
|
+
:param to_val: to value - target value
|
|
167
|
+
:param step_ms: step to reach to_val - timirq_seq
|
|
168
|
+
:param interval_sec: time of full interval
|
|
169
|
+
"""
|
|
170
|
+
if interval_sec > 0:
|
|
171
|
+
step_cnt = round((interval_sec*1000)/step_ms)
|
|
172
|
+
delta = abs((from_val-to_val)/step_cnt)
|
|
173
|
+
direc = -1 if from_val > to_val else 1
|
|
174
|
+
for cnt in range(0, step_cnt+1):
|
|
175
|
+
yield round(from_val + (cnt * delta) * direc)
|
|
176
|
+
else:
|
|
177
|
+
yield round(to_val)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def transition_gen(*args, interval_sec=1.0):
|
|
181
|
+
"""
|
|
182
|
+
[LM] Multiple Generator for color/value transitions:
|
|
183
|
+
- calculate minimum step count -> step_ms
|
|
184
|
+
- autofill and use transition(from_val, to_val, step_ms, interval_sec)
|
|
185
|
+
:param args: ch1_from, ch1_to, ch2_from, ch2_to, etc...
|
|
186
|
+
:param interval_sec: interval in sec to calculate optimal fade/transition effect
|
|
187
|
+
return: gen, step_ms OR gen list, step_ms
|
|
188
|
+
"""
|
|
189
|
+
step_ms_min = 5 # min calculated step is 5 ms - good enough
|
|
190
|
+
delta = max((abs(args[ch_from_i] - args[ch_from_i+1]) for ch_from_i in range(0, len(args)-1, 2)))
|
|
191
|
+
step_ms = 0 if delta == 0 else int(interval_sec*1000 / delta)
|
|
192
|
+
step_ms = step_ms_min if step_ms < step_ms_min else step_ms
|
|
193
|
+
transitions = list((transition(args[ch_from_i], args[ch_from_i+1], step_ms, interval_sec) for ch_from_i in range(0, len(args)-1, 2)))
|
|
194
|
+
if len(transitions) == 1:
|
|
195
|
+
return transitions[0], step_ms
|
|
196
|
+
return list(transitions), step_ms
|
|
197
|
+
|
|
198
|
+
#####################################################################################
|
|
199
|
+
# EXTRAS #
|
|
200
|
+
#####################################################################################
|
|
201
|
+
|
|
202
|
+
class SmartADC:
|
|
203
|
+
"""
|
|
204
|
+
[LM] General ADC implementation for auto scaled output: raw, percent, volt
|
|
205
|
+
https://docs.micropython.org/en/latest/esp32/quickref.html#adc-analog-to-digital-conversion
|
|
206
|
+
ADC.ATTN_0DB: 0 dB attenuation, resulting in a full-scale voltage range of 0-1.1V
|
|
207
|
+
ADC.ATTN_2_5DB: 2.5 dB ... of 0-1.5V
|
|
208
|
+
ADC.ATTN_6DB: 6 dB ... of 0-2.2V
|
|
209
|
+
ADC.ATTN_11DB: 11 dB ... of 0-2450mV/
|
|
210
|
+
Note that the absolute maximum voltage rating for input pins is 3.6V. Going near to this boundary risks damage to the IC!
|
|
211
|
+
"""
|
|
212
|
+
OBJS = {}
|
|
213
|
+
|
|
214
|
+
def __init__(self, pin):
|
|
215
|
+
self.adp_prop = (65535, 2450) # raw value, 2450mV (so 2,45V)
|
|
216
|
+
self.adc = None
|
|
217
|
+
if not isinstance(pin, int):
|
|
218
|
+
pin = resolve_pin(pin)
|
|
219
|
+
self.adc = ADC(Pin(pin))
|
|
220
|
+
self.adc.atten(ADC.ATTN_11DB) # 2450mV measure range
|
|
221
|
+
|
|
222
|
+
def get(self):
|
|
223
|
+
raw = int((self.adc.read_u16() + self.adc.read_u16())/2) # 16-bit ADC value (0-65535)
|
|
224
|
+
percent = raw / self.adp_prop[0]
|
|
225
|
+
volt = round(percent * self.adp_prop[1] / 1000, 2) # devide with 1000 to get V from mV
|
|
226
|
+
return {'raw': raw, 'percent': round(percent*100, 1), 'volt': volt}
|
|
227
|
+
|
|
228
|
+
@staticmethod
|
|
229
|
+
def get_instance(pin):
|
|
230
|
+
if pin in SmartADC.OBJS.keys():
|
|
231
|
+
return SmartADC.OBJS[pin]
|
|
232
|
+
SmartADC.OBJS[pin] = SmartADC(pin)
|
|
233
|
+
return SmartADC.OBJS[pin]
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
class AnimationPlayer:
|
|
237
|
+
"""
|
|
238
|
+
Generic async animation (generator) player.
|
|
239
|
+
"""
|
|
240
|
+
|
|
241
|
+
def __init__(self, animation:callable=None, tag:str=None, batch_draw:bool=False, batch_size:int=None):
|
|
242
|
+
"""
|
|
243
|
+
Initialize the AnimationPlayer with an optional animation.
|
|
244
|
+
:param animation: Function to GENERATE animation data
|
|
245
|
+
:param tag: Optional task tag for micro_task management.
|
|
246
|
+
:param batch_draw: If True - draw in batches
|
|
247
|
+
:param batch_size: Number of pixels per batch when drawing
|
|
248
|
+
"""
|
|
249
|
+
self.animation:callable = None
|
|
250
|
+
self.batch_draw:bool = batch_draw
|
|
251
|
+
self.__max_batch_size:int = 256 # MAX BATCH SIZE - ASYNC PROTECTION
|
|
252
|
+
self.__batch_size:int = 8 # Default batch size: 8
|
|
253
|
+
self._set_batch_size(batch_size) # Set batch size from parameter
|
|
254
|
+
self._player_speed_ms:int = 10 # Default speed in ms between frames
|
|
255
|
+
main_tag:str = tag if tag else "animation"
|
|
256
|
+
self._task_tag:str = f"{main_tag}.player"
|
|
257
|
+
if animation is not None and not self._set_animation(animation):
|
|
258
|
+
raise Exception("Invalid animation function provided.")
|
|
259
|
+
self._running:bool = True
|
|
260
|
+
|
|
261
|
+
def _set_animation(self, animation:callable) -> bool:
|
|
262
|
+
"""
|
|
263
|
+
Setter to change/set current animation.
|
|
264
|
+
"""
|
|
265
|
+
if callable(animation):
|
|
266
|
+
self.animation = animation
|
|
267
|
+
return True
|
|
268
|
+
return False
|
|
269
|
+
|
|
270
|
+
def _set_batch_size(self, batch_size:int) -> None:
|
|
271
|
+
"""
|
|
272
|
+
Setter to change/set batch size.
|
|
273
|
+
- with max batch size check (due to async event loop feeding)
|
|
274
|
+
"""
|
|
275
|
+
if batch_size is None:
|
|
276
|
+
return
|
|
277
|
+
self.__batch_size = max(0, min(batch_size, self.__max_batch_size))
|
|
278
|
+
|
|
279
|
+
async def _render(self, my_task):
|
|
280
|
+
# Cache methods for speed
|
|
281
|
+
clear = self.clear
|
|
282
|
+
update = self.update
|
|
283
|
+
draw = self.draw
|
|
284
|
+
# Cache the current animation for comparison
|
|
285
|
+
current_animation = self.animation
|
|
286
|
+
frame_counter = 0
|
|
287
|
+
# Clear the display before each frame
|
|
288
|
+
if not self.batch_draw:
|
|
289
|
+
clear()
|
|
290
|
+
for data in self.animation():
|
|
291
|
+
# Check if animation has changed under the loop
|
|
292
|
+
if not self._running or self.animation != current_animation:
|
|
293
|
+
# Animation changed — break — clean and restart animation loop.
|
|
294
|
+
clear()
|
|
295
|
+
break
|
|
296
|
+
# Update data cache
|
|
297
|
+
update(*data)
|
|
298
|
+
if self.batch_draw:
|
|
299
|
+
# Batched draw mode
|
|
300
|
+
frame_counter += 1
|
|
301
|
+
if frame_counter >= self.__batch_size:
|
|
302
|
+
draw()
|
|
303
|
+
frame_counter = 0
|
|
304
|
+
await my_task.feed(sleep_ms=self._player_speed_ms)
|
|
305
|
+
else:
|
|
306
|
+
# Real-time draw mode
|
|
307
|
+
draw()
|
|
308
|
+
await my_task.feed(sleep_ms=self._player_speed_ms)
|
|
309
|
+
|
|
310
|
+
async def _player(self):
|
|
311
|
+
"""
|
|
312
|
+
Async task to play the current animation.
|
|
313
|
+
"""
|
|
314
|
+
with micro_task(tag=self._task_tag) as my_task:
|
|
315
|
+
while self._running:
|
|
316
|
+
my_task.out = f"Play {self.animation.__name__} ({self._player_speed_ms}ms/frame)"
|
|
317
|
+
try:
|
|
318
|
+
await self._render(my_task)
|
|
319
|
+
except IndexError:
|
|
320
|
+
# Draw after generator exhausted and Restart animation if IndexError occurs
|
|
321
|
+
self.draw()
|
|
322
|
+
await my_task.feed(sleep_ms=self._player_speed_ms)
|
|
323
|
+
my_task.out = "Restart animation"
|
|
324
|
+
except Exception as e:
|
|
325
|
+
my_task.out = f"Error: {e}"
|
|
326
|
+
break
|
|
327
|
+
my_task.out = f"Animation stopped...{my_task.out}"
|
|
328
|
+
|
|
329
|
+
def control(self, play_speed_ms:int, bt_draw:bool=None, bt_size:int=None):
|
|
330
|
+
"""
|
|
331
|
+
Set/Get current play speed of the animation.
|
|
332
|
+
:param play_speed_ms: player loop speed in milliseconds.
|
|
333
|
+
:param bt_draw: batch drawing flag.
|
|
334
|
+
:param bt_size: batch drawing size.
|
|
335
|
+
"""
|
|
336
|
+
if isinstance(play_speed_ms, int):
|
|
337
|
+
self._player_speed_ms = max(0, min(10000, int(play_speed_ms)))
|
|
338
|
+
if isinstance(bt_draw, bool):
|
|
339
|
+
self.batch_draw = bt_draw
|
|
340
|
+
if isinstance(bt_size, int):
|
|
341
|
+
self._set_batch_size(bt_size)
|
|
342
|
+
return {"realtime": not self.batch_draw, "batched": self.batch_draw,
|
|
343
|
+
"size": self.__batch_size, "speed_ms": self._player_speed_ms}
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
def play(self, animation=None, speed_ms=None, bt_draw=False, bt_size=None):
|
|
347
|
+
"""
|
|
348
|
+
Play animation via generator function.
|
|
349
|
+
:param animation: Animation generator function.
|
|
350
|
+
:param speed_ms: Speed of the animation in milliseconds. (min.: 3ms)
|
|
351
|
+
:param bt_draw: batch drawing flag.
|
|
352
|
+
:param bt_size: batch drawing size.
|
|
353
|
+
"""
|
|
354
|
+
|
|
355
|
+
if animation is not None:
|
|
356
|
+
if not self._set_animation(animation):
|
|
357
|
+
return "Invalid animation"
|
|
358
|
+
if self.animation is None:
|
|
359
|
+
return "No animation to play"
|
|
360
|
+
# Handle player settings
|
|
361
|
+
settings = self.control(play_speed_ms=speed_ms, bt_draw=bt_draw, bt_size=bt_size)
|
|
362
|
+
# Ensure async loop set up correctly. (After stop operation, it is needed)
|
|
363
|
+
self._running = True
|
|
364
|
+
# [!] ASYNC TASK CREATION
|
|
365
|
+
raw_state:bool = micro_task(tag=self._task_tag, task=self._player())
|
|
366
|
+
state = "starting" if raw_state else "running"
|
|
367
|
+
settings["state"] = state
|
|
368
|
+
return settings
|
|
369
|
+
|
|
370
|
+
def stop(self):
|
|
371
|
+
"""
|
|
372
|
+
Stop the animation.
|
|
373
|
+
"""
|
|
374
|
+
self._running = False
|
|
375
|
+
return "Stop animation player"
|
|
376
|
+
|
|
377
|
+
def update(self, *arg, **kwargs):
|
|
378
|
+
"""
|
|
379
|
+
Child class must implement this method to handle drawing logic.
|
|
380
|
+
"""
|
|
381
|
+
raise NotImplementedError("Child class must implement update method.")
|
|
382
|
+
|
|
383
|
+
def draw(self):
|
|
384
|
+
"""
|
|
385
|
+
Draw the current frame.
|
|
386
|
+
"""
|
|
387
|
+
raise NotImplementedError("Child class must implement draw method.")
|
|
388
|
+
|
|
389
|
+
def clear(self):
|
|
390
|
+
"""
|
|
391
|
+
Clear the display.
|
|
392
|
+
"""
|
|
393
|
+
raise NotImplementedError("Child class must implement clear method.")
|