micrOSDevToolKit 2.19.0__py3-none-any.whl → 2.20.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.

Files changed (52) hide show
  1. micrOS/release_info/micrOS_ReleaseInfo/system_analysis_sum.json +21 -25
  2. micrOS/source/Common.py +5 -13
  3. micrOS/source/Espnow.py +3 -6
  4. micrOS/source/InterConnect.py +1 -2
  5. micrOS/source/Shell.py +1 -1
  6. micrOS/source/Tasks.py +55 -53
  7. micrOS/source/modules/LM_buzzer.py +1 -4
  8. micrOS/source/modules/LM_cct.py +2 -4
  9. micrOS/source/modules/LM_dimmer.py +1 -2
  10. micrOS/source/modules/LM_distance.py +1 -3
  11. micrOS/source/modules/LM_i2s_mic.py +1 -2
  12. micrOS/source/modules/LM_keychain.py +1 -2
  13. micrOS/source/modules/LM_light_sensor.py +1 -4
  14. micrOS/source/modules/LM_mqtt_client.py +13 -10
  15. micrOS/source/modules/LM_neopixel.py +1 -2
  16. micrOS/source/modules/LM_oledui.py +2 -4
  17. micrOS/source/modules/LM_presence.py +1 -2
  18. micrOS/source/modules/LM_rest.py +1 -2
  19. micrOS/source/modules/LM_rgb.py +1 -2
  20. micrOS/source/modules/LM_roboarm.py +3 -4
  21. micrOS/source/modules/LM_robustness.py +1 -2
  22. micrOS/source/modules/LM_telegram.py +1 -2
  23. {microsdevtoolkit-2.19.0.dist-info → microsdevtoolkit-2.20.0.dist-info}/METADATA +149 -213
  24. {microsdevtoolkit-2.19.0.dist-info → microsdevtoolkit-2.20.0.dist-info}/RECORD +50 -52
  25. toolkit/dashboard_apps/SystemTest.py +17 -14
  26. toolkit/workspace/precompiled/Common.mpy +0 -0
  27. toolkit/workspace/precompiled/Espnow.mpy +0 -0
  28. toolkit/workspace/precompiled/InterConnect.mpy +0 -0
  29. toolkit/workspace/precompiled/Shell.mpy +0 -0
  30. toolkit/workspace/precompiled/Tasks.mpy +0 -0
  31. toolkit/workspace/precompiled/modules/LM_buzzer.mpy +0 -0
  32. toolkit/workspace/precompiled/modules/LM_cct.mpy +0 -0
  33. toolkit/workspace/precompiled/modules/LM_dimmer.mpy +0 -0
  34. toolkit/workspace/precompiled/modules/LM_distance.mpy +0 -0
  35. toolkit/workspace/precompiled/modules/LM_i2s_mic.mpy +0 -0
  36. toolkit/workspace/precompiled/modules/LM_keychain.mpy +0 -0
  37. toolkit/workspace/precompiled/modules/LM_light_sensor.mpy +0 -0
  38. toolkit/workspace/precompiled/modules/LM_mqtt_client.mpy +0 -0
  39. toolkit/workspace/precompiled/modules/LM_neopixel.mpy +0 -0
  40. toolkit/workspace/precompiled/modules/LM_oledui.mpy +0 -0
  41. toolkit/workspace/precompiled/modules/LM_presence.mpy +0 -0
  42. toolkit/workspace/precompiled/modules/LM_rest.mpy +0 -0
  43. toolkit/workspace/precompiled/modules/LM_rgb.mpy +0 -0
  44. toolkit/workspace/precompiled/modules/LM_roboarm.mpy +0 -0
  45. toolkit/workspace/precompiled/modules/LM_robustness.py +1 -2
  46. toolkit/workspace/precompiled/modules/LM_telegram.mpy +0 -0
  47. micrOS/source/modules/LM_pet_feeder.py +0 -78
  48. toolkit/workspace/precompiled/modules/LM_pet_feeder.py +0 -78
  49. {microsdevtoolkit-2.19.0.data → microsdevtoolkit-2.20.0.data}/scripts/devToolKit.py +0 -0
  50. {microsdevtoolkit-2.19.0.dist-info → microsdevtoolkit-2.20.0.dist-info}/WHEEL +0 -0
  51. {microsdevtoolkit-2.19.0.dist-info → microsdevtoolkit-2.20.0.dist-info}/licenses/LICENSE +0 -0
  52. {microsdevtoolkit-2.19.0.dist-info → microsdevtoolkit-2.20.0.dist-info}/top_level.txt +0 -0
@@ -25,7 +25,7 @@
25
25
  1
26
26
  ],
27
27
  "Tasks.py": [
28
- 9.46,
28
+ 9.48,
29
29
  12
30
30
  ],
31
31
  "Config.py": [
@@ -54,7 +54,7 @@
54
54
  ],
55
55
  "Common.py": [
56
56
  9.85,
57
- 35
57
+ 34
58
58
  ],
59
59
  "InterConnect.py": [
60
60
  9.62,
@@ -69,7 +69,7 @@
69
69
  8
70
70
  ],
71
71
  "Espnow.py": [
72
- 9.48,
72
+ 9.47,
73
73
  4
74
74
  ],
75
75
  "Scheduler.py": [
@@ -97,7 +97,7 @@
97
97
  5
98
98
  ],
99
99
  "modules/LM_roboarm.py": [
100
- 7.78,
100
+ 7.83,
101
101
  0
102
102
  ],
103
103
  "modules/LM_stepper.py": [
@@ -125,7 +125,7 @@
125
125
  0
126
126
  ],
127
127
  "modules/LM_robustness.py": [
128
- 8.36,
128
+ 8.33,
129
129
  0
130
130
  ],
131
131
  "modules/LM_qmi8658.py": [
@@ -137,7 +137,7 @@
137
137
  0
138
138
  ],
139
139
  "modules/LM_rest.py": [
140
- 8.18,
140
+ 8.6,
141
141
  0
142
142
  ],
143
143
  "modules/LM_tcs3472.py": [
@@ -161,7 +161,7 @@
161
161
  0
162
162
  ],
163
163
  "modules/LM_buzzer.py": [
164
- 9.11,
164
+ 9.09,
165
165
  0
166
166
  ],
167
167
  "modules/LM_switch.py": [
@@ -189,11 +189,11 @@
189
189
  0
190
190
  ],
191
191
  "modules/LM_neopixel.py": [
192
- 7.78,
192
+ 7.77,
193
193
  0
194
194
  ],
195
195
  "modules/LM_cct.py": [
196
- 9.04,
196
+ 9.03,
197
197
  0
198
198
  ],
199
199
  "modules/LM_L9110_DCmotor.py": [
@@ -220,10 +220,6 @@
220
220
  7.62,
221
221
  0
222
222
  ],
223
- "modules/LM_pet_feeder.py": [
224
- 7.94,
225
- 0
226
- ],
227
223
  "modules/LM_rencoder.py": [
228
224
  8.65,
229
225
  0
@@ -253,7 +249,7 @@
253
249
  0
254
250
  ],
255
251
  "modules/LM_telegram.py": [
256
- 9.63,
252
+ 9.62,
257
253
  0
258
254
  ],
259
255
  "modules/LM_OV2640.py": [
@@ -265,7 +261,7 @@
265
261
  0
266
262
  ],
267
263
  "modules/LM_distance.py": [
268
- 8.87,
264
+ 8.86,
269
265
  0
270
266
  ],
271
267
  "modules/LM_VL53L0X.py": [
@@ -273,7 +269,7 @@
273
269
  0
274
270
  ],
275
271
  "modules/LM_light_sensor.py": [
276
- 9.17,
272
+ 9.12,
277
273
  0
278
274
  ],
279
275
  "modules/LM_rp2w.py": [
@@ -281,7 +277,7 @@
281
277
  0
282
278
  ],
283
279
  "modules/LM_presence.py": [
284
- 8.9,
280
+ 8.89,
285
281
  0
286
282
  ],
287
283
  "modules/LM_trackball.py": [
@@ -289,7 +285,7 @@
289
285
  0
290
286
  ],
291
287
  "modules/LM_mqtt_client.py": [
292
- 8.45,
288
+ 8.68,
293
289
  0
294
290
  ],
295
291
  "modules/LM_dashboard_be.py": [
@@ -297,7 +293,7 @@
297
293
  0
298
294
  ],
299
295
  "modules/LM_dimmer.py": [
300
- 8.33,
296
+ 8.32,
301
297
  0
302
298
  ],
303
299
  "modules/LM_gameOfLife.py": [
@@ -309,7 +305,7 @@
309
305
  0
310
306
  ],
311
307
  "modules/LM_i2s_mic.py": [
312
- 8.43,
308
+ 8.42,
313
309
  0
314
310
  ],
315
311
  "modules/LM_sdcard.py": [
@@ -323,12 +319,12 @@
323
319
  },
324
320
  "summary": {
325
321
  "core": [
326
- 4004,
322
+ 3994,
327
323
  24
328
324
  ],
329
325
  "load": [
330
- 9988,
331
- 56
326
+ 9912,
327
+ 55
332
328
  ],
333
329
  "core_dep": [
334
330
  true,
@@ -339,7 +335,7 @@
339
335
  4
340
336
  ],
341
337
  "core_score": 9.25,
342
- "load_score": 8.4,
343
- "version": "2.19.0-0"
338
+ "load_score": 8.42,
339
+ "version": "2.20.0-0"
344
340
  }
345
341
  }
micrOS/source/Common.py CHANGED
@@ -15,7 +15,7 @@ from Notify import Notify
15
15
  #####################################################################################
16
16
  # SYSTEM #
17
17
  #####################################################################################
18
- def micro_task(tag: str, task=None, _wrap=False):
18
+ def micro_task(tag:str, task=None, _wrap=False):
19
19
  """
20
20
  [LM] Async task manager.
21
21
  Modes:
@@ -37,21 +37,14 @@ def micro_task(tag: str, task=None, _wrap=False):
37
37
  """
38
38
  # --- CREATE (original) ---
39
39
  if task is not None:
40
- if TaskBase.is_busy(tag):
41
- return None # task already running
42
40
  return Manager().create_task(callback=task, tag=tag)
43
41
 
44
42
  # --- CREATE WITH DECORATOR FACTORY (simplified) ---
45
43
  if _wrap:
46
44
  def _decorator(async_fn):
47
45
  task_tag = f"{tag}._{async_fn.__name__}"
48
- _launcher = (
49
- lambda *args, **kwargs:
50
- None if TaskBase.is_busy(task_tag)
51
- else Manager().create_task(
52
- callback=async_fn(task_tag, *args, **kwargs),
53
- tag=task_tag)
54
- )
46
+ _launcher = (lambda *args, **kwargs: Manager().create_task(callback=async_fn(task_tag, *args, **kwargs),
47
+ tag=task_tag))
55
48
  return _launcher
56
49
  return _decorator
57
50
 
@@ -404,9 +397,8 @@ class AnimationPlayer:
404
397
  # Ensure async loop set up correctly. (After stop operation, it is needed)
405
398
  self.__running = True
406
399
  # [!] ASYNC TASK CREATION
407
- raw_state:bool = micro_task(tag=self._task_tag, task=self._player())
408
- state = "starting" if raw_state else "running"
409
- settings["state"] = state
400
+ state:dict = micro_task(tag=self._task_tag, task=self._player())
401
+ settings["state"] = list(state.values())[0]
410
402
  return settings
411
403
 
412
404
  def stop(self):
micrOS/source/Espnow.py CHANGED
@@ -201,8 +201,7 @@ class ESPNowSS:
201
201
  """
202
202
  # Create an asynchronous task with tag 'espnow.server'
203
203
  tag = 'espnow.server'
204
- state = NativeTask().create(callback=self._server(tag), tag=tag)
205
- return {tag: "Starting"} if state else {tag: "Already running"}
204
+ return NativeTask().create(callback=self._server(tag), tag=tag)
206
205
 
207
206
  #----------- SEND METHODS --------------
208
207
  async def __asend_raw(self, mac:bytes, msg:str):
@@ -249,8 +248,7 @@ class ESPNowSS:
249
248
  peer_name = hexlify(peer, ':').decode() if peer_name is None else peer_name
250
249
  task_id = f"con.espnow.{peer_name}"
251
250
  # Create an asynchronous sending task.
252
- state = NativeTask().create(callback=self._asend_task(peer, task_id, msg), tag=task_id)
253
- return {task_id: "Starting"} if state else {task_id: "Already running"}
251
+ return NativeTask().create(callback=self._asend_task(peer, task_id, msg), tag=task_id)
254
252
 
255
253
  def cluster_send(self, msg):
256
254
  """
@@ -304,8 +302,7 @@ class ESPNowSS:
304
302
  # Convert 50:02:91:86:34:28 format to b'P\x02\x91\x864(' bytes
305
303
  peer = bytes(int(x, 16) for x in peer.split(":"))
306
304
  if isinstance(peer, bytes):
307
- state = NativeTask().create(callback=self._handshake(peer, task_id), tag=task_id)
308
- return {task_id: "Starting"} if state else {task_id: "Already running"}
305
+ return NativeTask().create(callback=self._handshake(peer, task_id), tag=task_id)
309
306
  else:
310
307
  return {None: "Invalid MAC address format. Use 50:02:91:86:34:28 or b'P\\x02\\x91\\x864('"}
311
308
 
@@ -258,8 +258,7 @@ def send_cmd(host:str, cmd:list|str) -> dict:
258
258
 
259
259
  com_obj = InterCon()
260
260
  task_id = f"con.{_tagify()}" # CHECK TASK ID CONFLICT
261
- state = com_obj.task.create(callback=_send_cmd(host, cmd, com_obj), tag=task_id)
262
- return {task_id: "Starting"} if state else {task_id: "Already running"}
261
+ return com_obj.task.create(callback=_send_cmd(host, cmd, com_obj), tag=task_id)
263
262
 
264
263
 
265
264
  def host_cache() -> dict:
micrOS/source/Shell.py CHANGED
@@ -25,7 +25,7 @@ from Debug import syslog
25
25
 
26
26
  class Shell:
27
27
  __slots__ = ['__devfid', '__auth_mode', '__hwuid', '__auth_ok', '__conf_mode']
28
- MICROS_VERSION = '2.19.0-0'
28
+ MICROS_VERSION = '2.20.0-0'
29
29
 
30
30
  def __init__(self):
31
31
  """
micrOS/source/Tasks.py CHANGED
@@ -18,10 +18,10 @@ from Config import cfgget
18
18
  from Network import sta_high_avail
19
19
 
20
20
  try:
21
- from gc import collect
21
+ from gc import collect as gcollect
22
22
  except ImportError:
23
23
  console_write("[SIMULATOR MODE GC IMPORT]")
24
- from simgc import collect
24
+ from simgc import collect as gcollect
25
25
 
26
26
  #################################################################
27
27
  # Implement custom task class #
@@ -43,32 +43,20 @@ class TaskBase:
43
43
  self.done = asyncio.Event() # Store task done state
44
44
  self.out = "" # Store task output
45
45
 
46
- def _create(self, callback:callable) -> bool:
46
+ ###### BASE METHODS FOR CHILD CLASSES ####
47
+ def _create(self, callback:callable) -> dict:
47
48
  """
48
49
  Create async task and register it to TASKS dict by tag
49
50
  :param callback: coroutine function
50
51
  """
51
- if TaskBase.is_busy(self.tag):
52
- # Skip task if already running
53
- return False
54
52
  # Create async task from coroutine function
55
53
  self.task = asyncio.get_event_loop().create_task(callback)
56
54
  # Store Task object by key - for task control
57
55
  TaskBase.TASKS[self.tag] = self
58
- return True
59
-
60
- @staticmethod
61
- def is_busy(tag:str) -> bool:
62
- """
63
- Check task is busy by tag
64
- :param tag: for task selection
65
- """
66
- task = TaskBase.TASKS.get(tag, None)
67
- # return True: busy OR False: not busy (inactive) OR None: not exists
68
- return bool(task is not None and not task.done.is_set())
56
+ return {self.tag: "Starting"}
69
57
 
70
58
  @staticmethod
71
- def task_gc():
59
+ def _task_gc():
72
60
  """
73
61
  Automatic passive task deletion over QUEUE_SIZE
74
62
  """
@@ -77,18 +65,18 @@ class TaskBase:
77
65
  if len(passive) >= keep:
78
66
  for i in range(0, len(passive)-keep+1):
79
67
  del TaskBase.TASKS[passive[i]]
80
- collect() # GC collect
68
+ gcollect()
81
69
 
70
+ ###### PUBLIC TASK METHODS #####
82
71
  @staticmethod
83
- async def feed(sleep_ms=1):
72
+ def is_busy(tag:str) -> bool:
84
73
  """
85
- Feed event loop
86
- :param sleep_ms: in millisecond
74
+ Check task is busy by tag
75
+ :param tag: for task selection
87
76
  """
88
- # TODO: feed WDT - preemptive cooperative multitasking aka reboot if no feed until X time period
89
- if sleep_ms <= 0:
90
- return await asyncio.sleep(0.000_000_1) # 0 means: 100ns (Absolute minimum)
91
- return await asyncio.sleep_ms(sleep_ms)
77
+ task = TaskBase.TASKS.get(tag, None)
78
+ # return True: busy OR False: not busy (inactive) OR None: not exists
79
+ return bool(task is not None and not task.done.is_set())
92
80
 
93
81
  def cancel(self) -> bool:
94
82
  """
@@ -109,15 +97,16 @@ class TaskBase:
109
97
  return False
110
98
  return True
111
99
 
112
- def __task_del(self, keep_cache=False):
100
+ @staticmethod
101
+ async def feed(sleep_ms=1):
113
102
  """
114
- Delete task from TASKS
103
+ Feed event loop
104
+ :param sleep_ms: in millisecond
115
105
  """
116
- self.done.set()
117
- if self.tag in TaskBase.TASKS:
118
- if not keep_cache: # True - In case of destructor
119
- del TaskBase.TASKS[self.tag]
120
- collect() # GC collect
106
+ # TODO?: feed WDT - auto restart when system is frozen
107
+ if sleep_ms <= 0:
108
+ return await asyncio.sleep(0.000_000_1) # 0 means: 100ns (Absolute minimum)
109
+ return await asyncio.sleep_ms(sleep_ms)
121
110
 
122
111
  async def await_result(self, timeout:int=5):
123
112
  """
@@ -130,6 +119,17 @@ class TaskBase:
130
119
  return "Timeout has beed exceeded"
131
120
  return self.out
132
121
 
122
+ ###### PRIVATE LCM METHODS #####
123
+ def __task_del(self, keep_cache=False):
124
+ """
125
+ Delete task from TASKS
126
+ """
127
+ self.done.set()
128
+ if self.tag in TaskBase.TASKS:
129
+ if not keep_cache: # True - In case of destructor
130
+ del TaskBase.TASKS[self.tag]
131
+ gcollect()
132
+
133
133
  def __del__(self):
134
134
  try:
135
135
  self.__task_del(keep_cache=True)
@@ -143,7 +143,7 @@ class NativeTask(TaskBase):
143
143
  - could be built in function or custom code from load modules
144
144
  """
145
145
 
146
- def create(self, callback:callable=None, tag:str=None) -> bool:
146
+ def create(self, callback:callable=None, tag:str=None) -> dict:
147
147
  """
148
148
  Create async task with coroutine callback (no queue limit check!)
149
149
  + async socket server task
@@ -152,6 +152,9 @@ class NativeTask(TaskBase):
152
152
  """
153
153
  # Create task tag
154
154
  self.tag = f"aio.{ticks_ms()}" if tag is None else tag
155
+ if self.is_busy(self.tag):
156
+ # Skip task if already running
157
+ return {self.tag: "Already running"}
155
158
  # Create task with coroutine callback
156
159
  return super()._create(callback)
157
160
 
@@ -170,7 +173,7 @@ class NativeTask(TaskBase):
170
173
  Helper function for Task creation in Load Modules
171
174
  [HINT] Use python with feature to utilize this feature
172
175
  """
173
- self.task_gc() # Task pool cleanup
176
+ self._task_gc() # Task pool cleanup
174
177
  self.done.set()
175
178
 
176
179
 
@@ -186,7 +189,7 @@ class MagicTask(TaskBase):
186
189
  self.__inloop = False # [LM] Task while loop for LM callback
187
190
  self.__sleep = 20 # [LM] Task while loop - async wait (proc feed) [ms]
188
191
 
189
- def create(self, callback:list=None, loop:bool=None, sleep:int=None) -> bool:
192
+ def create(self, callback:list=None, loop:bool=None, sleep:int=None) -> dict:
190
193
  """
191
194
  Create async task with function callback (with queue limit check)
192
195
  - wrap (sync) function into async task (task_wrapper)
@@ -196,13 +199,14 @@ class MagicTask(TaskBase):
196
199
  """
197
200
  # Create task tag
198
201
  self.tag = '.'.join(callback[0:2])
199
-
202
+ if self.is_busy(self.tag):
203
+ # Skip task if already running
204
+ return {self.tag: "Already running"}
200
205
  # Set parameters for async wrapper
201
206
  self.__callback = callback
202
207
  self.__inloop = self.__inloop if loop is None else loop
203
208
  # Set sleep value for async loop - optional parameter with min sleep limit check (20ms)
204
209
  self.__sleep = self.__sleep if sleep is None else sleep if sleep > 19 else self.__sleep
205
-
206
210
  # Create task with coroutine callback
207
211
  return super()._create(self.__task_wrapper())
208
212
 
@@ -219,7 +223,7 @@ class MagicTask(TaskBase):
219
223
  state, self.out = _exec_lm_core(self.__callback)
220
224
  if not state or not self.__inloop:
221
225
  break
222
- self.task_gc() # Task pool cleanup
226
+ self._task_gc() # Task pool cleanup
223
227
  self.done.set()
224
228
 
225
229
  def cancel(self):
@@ -310,12 +314,16 @@ class Manager:
310
314
  my_task.done.set()
311
315
 
312
316
  @staticmethod
313
- def create_task(callback, tag:str=None, loop:bool=False, delay:int=None):
317
+ def create_task(callback, tag:str=None, loop:bool=False, delay:int=None) -> dict:
314
318
  """
315
- Primary interface
316
- Generic task creator method
317
- Create async Task with coroutine/list(lm call) callback
318
- :param callback: list|callable
319
+ Primary interface of micrOS Generic task creator method
320
+ :param tag: task unique identifier
321
+ NativeTask:
322
+ :param callback: callable, coroutine to start a task
323
+ MagicTask with queue limiter:
324
+ :param callback: list of staring (command)
325
+ :param loop: MagicTask looping parameter
326
+ :param delay: MagicTask delay parameter
319
327
  """
320
328
  if isinstance(callback, list):
321
329
  # Check queue if task is Load Module
@@ -513,15 +521,9 @@ def lm_exec(arg_list:list, jsonify:bool=None):
513
521
  delay = int(delay) if delay.isdigit() else None
514
522
  # Create and start async lm task
515
523
  try:
516
- state = Manager.create_task(arg_list, loop=loop, delay=delay)
524
+ return True, Manager.create_task(arg_list, loop=loop, delay=delay)
517
525
  except Exception as e:
518
- # Valid & handled task command
519
- return True, str(e)
520
- tag = '.'.join(arg_list[0:2])
521
- # Valid & handled task command
522
- if state:
523
- return True, f"Start {tag}"
524
- return True, f"{tag} is Busy"
526
+ return False, {".".join(arg_list[0:2]): str(e)}
525
527
 
526
528
  # [2] Sync "realtime" task execution
527
529
  state, out = _exec_lm_core(arg_list, jsonify)
@@ -590,7 +592,7 @@ def _exec_lm_core(cmd_list, jsonify):
590
592
  # UNLOAD MODULE IF MEMORY ERROR HAPPENED + gc.collect
591
593
  if lm_mod in modules:
592
594
  del modules[lm_mod]
593
- collect()
595
+ gcollect()
594
596
  # LM EXECUTION ERROR
595
597
  return False, f"Core error: {lm_mod}->{lm_func}: {e}"
596
598
  return False, "Shell: for hints type help.\nShell: for LM exec: [1](LM)module [2]function [3...]optional params"
@@ -270,10 +270,7 @@ def play(rtttlstr='Indiana'):
270
270
  global CHECK_NOTIFY
271
271
  if CHECK_NOTIFY and not notify():
272
272
  return "NoBipp - notify off"
273
- state = micro_task(tag=__TASK_TAG, task=_play(rtttlstr))
274
- if state:
275
- return 'Play song'
276
- return 'Song already playing'
273
+ return micro_task(tag=__TASK_TAG, task=_play(rtttlstr))
277
274
 
278
275
 
279
276
  def list_tones():
@@ -238,8 +238,7 @@ def transition(cw=None, ww=None, sec=1.0, wake=False):
238
238
  # Create transition generator and calculate step_ms
239
239
  cct_gen, step_ms = transition_gen(cw_from, cw_to, ww_from, ww_to, interval_sec=sec)
240
240
  # [!] ASYNC TASK CREATION [1*] with async task callback + taskID (TAG) handling
241
- state = micro_task(tag=Data.CCT_TASK_TAG, task=_task(ms_period=step_ms, iterable=cct_gen))
242
- return "Starting transition" if state else "Transition already running"
241
+ return micro_task(tag=Data.CCT_TASK_TAG, task=_task(ms_period=step_ms, iterable=cct_gen))
243
242
 
244
243
 
245
244
  def hue_transition(percent, sec=1.0, wake=False):
@@ -288,8 +287,7 @@ def hue_transition(percent, sec=1.0, wake=False):
288
287
  #print("Actual percent: {}, target percent: {}".format(actual_percent, warm_percent))
289
288
  hue_gen, step_ms = transition_gen(hue_curr_percent, percent*10, interval_sec=sec)
290
289
  # [!] ASYNC TASK CREATION [1*] with async task callback + taskID (TAG) handling
291
- state = micro_task(tag=Data.HUE_TASK_TAG, task=_task(ms_period=step_ms, iterable=hue_gen))
292
- return "Starting transition" if state else "Transition already running"
290
+ return micro_task(tag=Data.HUE_TASK_TAG, task=_task(ms_period=step_ms, iterable=hue_gen))
293
291
  else:
294
292
  return "Invalid range, percent=<0-100>"
295
293
 
@@ -184,8 +184,7 @@ def transition(value, sec=1.0, wake=False):
184
184
  # Create transition generator and calculate step_ms
185
185
  fade_gen, fade_step_ms = transition_gen(from_dim, value, interval_sec=sec)
186
186
  # [!] ASYNC TASK CREATION [1*] with async task callback + taskID (TAG) handling
187
- state = micro_task(tag=Data.DIMM_TASK_TAG, task=_task(ms_period=fade_step_ms, iterable=fade_gen))
188
- return "Starting transition" if state else "Transition already running"
187
+ return micro_task(tag=Data.DIMM_TASK_TAG, task=_task(ms_period=fade_step_ms, iterable=fade_gen))
189
188
 
190
189
 
191
190
  def subscribe_presence():
@@ -70,9 +70,7 @@ def start_dimmer_indicator(idle_distance=180):
70
70
  """Distance visualization on LED brightness (LM_dimmer)"""
71
71
  from LM_dimmer import set_value
72
72
  # [!] ASYNC TASK CREATION [1*] with async task callback + taskID (TAG) handling
73
- state = micro_task(tag="distance.visual", task=__task(period_ms=200, dimmer=set_value, idle_cm=idle_distance))
74
- return "Starting" if state else "Already running"
75
-
73
+ return micro_task(tag="distance.visual", task=__task(period_ms=200, dimmer=set_value, idle_cm=idle_distance))
76
74
 
77
75
 
78
76
  #########################
@@ -94,8 +94,7 @@ def background_capture():
94
94
  if not Data.MIC_ENABLED:
95
95
  return "Microphone is disabled"
96
96
 
97
- state = micro_task(tag=Data.TASK_TAG, task=__task(ms_period=1))
98
- return "Starting" if state else "Already running"
97
+ return micro_task(tag=Data.TASK_TAG, task=__task(ms_period=1))
99
98
 
100
99
 
101
100
  def get_from_buffer(capture_duration=Data.CAPTURE_DURATION,
@@ -216,8 +216,7 @@ def display(period=1000, tts=30):
216
216
  # [!] ASYNC TASK CREATION [1*] with async task callback + taskID (TAG) handling
217
217
  period_ms = 500 if period < 500 else period
218
218
  tts_ms = 5000 if tts < 5 else tts*1000
219
- state = micro_task(tag="keychain.display", task=_ui_task(period_ms, tts_ms))
220
- return "Starting" if state else "Already running"
219
+ return micro_task(tag="keychain.display", task=_ui_task(period_ms, tts_ms))
221
220
 
222
221
 
223
222
  def temperature():
@@ -96,11 +96,8 @@ def subscribe_intercon(on, off, threshold=4, tolerance=2, sample_sec=60):
96
96
  """
97
97
  # Start play - servo XY in async task
98
98
  # [!] ASYNC TASK CREATION [1*] with async task callback + taskID (TAG) handling
99
- state = micro_task(tag="light_sensor.intercon", task=_task(on, off, threshold, tolerance=tolerance,
99
+ return micro_task(tag="light_sensor.intercon", task=_task(on, off, threshold, tolerance=tolerance,
100
100
  check_ms=sample_sec*1000))
101
- if state:
102
- return 'Light sensor remote trigger starts'
103
- return 'Light sensor remote trigger - already running'
104
101
 
105
102
 
106
103
  #######################
@@ -123,8 +123,8 @@ def publish(topic: str, message: str, retain: bool = False):
123
123
  :return: Status message string.
124
124
  """
125
125
  unique_tag = f'mqtt.publish.{topic}.{time.ticks_ms()}'
126
- state = micro_task(tag=unique_tag, task=_publish(unique_tag, message, topic, retain))
127
- return f"Message was sent {state}"
126
+ state:dict = micro_task(tag=unique_tag, task=_publish(unique_tag, message, topic, retain))
127
+ return f"Message was sent ({list(state.values())[0]})"
128
128
 
129
129
 
130
130
  ####################
@@ -142,8 +142,8 @@ async def _up():
142
142
  my_task.out = "Wait"
143
143
  await MQTT.CLIENT.up.wait()
144
144
  MQTT.CLIENT.up.clear()
145
- state = micro_task(tag=MQTT.SUB_TASK, task=_subscribe(MQTT.DEFAULT_TOPIC))
146
- my_task.out = f"Re-Subscription {state}"
145
+ state:dict = micro_task(tag=MQTT.SUB_TASK, task=_subscribe(MQTT.DEFAULT_TOPIC))
146
+ my_task.out = f"Re-Subscription ({list(state.values())[0]})"
147
147
  my_task.feed()
148
148
 
149
149
 
@@ -165,10 +165,14 @@ async def _init_client():
165
165
  MQTT.CLIENT.up.clear()
166
166
 
167
167
  # Initialize mqtt topics
168
- if not micro_task(tag=MQTT.SUB_TASK, task=_subscribe(MQTT.DEFAULT_TOPIC)):
169
- syslog(f"Failed start mqtt subscribe")
170
- if not micro_task(tag=MQTT.UP_TASK, task=_up()):
171
- syslog(f"Failed start mqtt up")
168
+ try:
169
+ micro_task(tag=MQTT.SUB_TASK, task=_subscribe(MQTT.DEFAULT_TOPIC))
170
+ except Exception as err:
171
+ syslog(f"Failed start mqtt subscribe: {err}")
172
+ try:
173
+ micro_task(tag=MQTT.UP_TASK, task=_up())
174
+ except Exception as err:
175
+ syslog(f"Failed start mqtt up: {err}")
172
176
  # Async listener loop
173
177
  await _receiver()
174
178
  my_task.out = "Receiver closed"
@@ -230,8 +234,7 @@ def load(username: str, password: str, server_ip: str, server_port: str='1883',
230
234
  MQTT.CLIENT = MQTTClient(_configure(username, password, server_ip, server_port))
231
235
  MQTT.QOS = qos
232
236
 
233
- state = micro_task(tag=MQTT.CLIENT_TASK, task=_init_client())
234
- return {MQTT.CLIENT_TASK: "Starting"} if state else {MQTT.CLIENT_TASK: "Already running"}
237
+ return micro_task(tag=MQTT.CLIENT_TASK, task=_init_client())
235
238
 
236
239
 
237
240
  def help(widgets=False):
@@ -278,8 +278,7 @@ def transition(r=None, g=None, b=None, sec=1.0, wake=False):
278
278
  # Create transition generator and calculate step_ms
279
279
  rgb_gen, step_ms = transition_gen(r_from, r_to, g_from, g_to, b_from, b_to, interval_sec=sec)
280
280
  # [!] ASYNC TASK CREATION [1*] with async task callback + taskID (TAG) handling
281
- state = micro_task(tag=Data.RGB_TASK_TAG, task=_task(ms_period=step_ms, iterable=rgb_gen))
282
- return "Starting transition" if state else "Transition already running"
281
+ return micro_task(tag=Data.RGB_TASK_TAG, task=_task(ms_period=step_ms, iterable=rgb_gen))
283
282
 
284
283
 
285
284
  def random(smooth=True, max_val=255):
@@ -121,8 +121,7 @@ class Frame(BaseFrame):
121
121
  """
122
122
  # [!] ASYNC TASK CREATION [1*] with async task callback + taskID (TAG) handling
123
123
  self._taskid = f"oledui.{tid}"
124
- state = micro_task(tag=self._taskid, task=self._task(period_ms=period_ms))
125
- return "Starting" if state else "Already running"
124
+ return micro_task(tag=self._taskid, task=self._task(period_ms=period_ms))
126
125
 
127
126
  def hover(self):
128
127
  """
@@ -486,8 +485,7 @@ class ScreenSaver(BaseFrame):
486
485
  def run(self, fps=10):
487
486
  # [!] ASYNC TASK CREATION [1*] with async task callback + taskID (TAG) handling
488
487
  period_ms = int(1000/fps)
489
- state = micro_task(tag="oledui.anim", task=self._task(period_ms))
490
- return "Starting" if state else "Already running"
488
+ return micro_task(tag="oledui.anim", task=self._task(period_ms))
491
489
 
492
490
  def cancel(self):
493
491
  if self.running: