micrOSDevToolKit 2.17.2__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 (73) hide show
  1. micrOS/release_info/micrOS_ReleaseInfo/system_analysis_sum.json +29 -33
  2. micrOS/source/Common.py +5 -13
  3. micrOS/source/Config.py +2 -2
  4. micrOS/source/Espnow.py +32 -18
  5. micrOS/source/InterConnect.py +106 -31
  6. micrOS/source/Server.py +2 -3
  7. micrOS/source/Shell.py +1 -1
  8. micrOS/source/Tasks.py +66 -62
  9. micrOS/source/micrOSloader.py +1 -1
  10. micrOS/source/modules/LM_buzzer.py +1 -4
  11. micrOS/source/modules/LM_cct.py +2 -4
  12. micrOS/source/modules/LM_dimmer.py +1 -2
  13. micrOS/source/modules/LM_distance.py +1 -3
  14. micrOS/source/modules/LM_espnow.py +18 -1
  15. micrOS/source/modules/LM_i2s_mic.py +1 -2
  16. micrOS/source/modules/LM_keychain.py +1 -2
  17. micrOS/source/modules/LM_light_sensor.py +1 -4
  18. micrOS/source/modules/LM_mqtt_client.py +13 -10
  19. micrOS/source/modules/LM_neoeffects.py +1 -1
  20. micrOS/source/modules/LM_neomatrix.py +1 -1
  21. micrOS/source/modules/LM_neopixel.py +1 -2
  22. micrOS/source/modules/LM_oled_ui.py +4 -3
  23. micrOS/source/modules/LM_oledui.py +6 -7
  24. micrOS/source/modules/LM_presence.py +1 -2
  25. micrOS/source/modules/LM_rest.py +1 -2
  26. micrOS/source/modules/LM_rgb.py +1 -2
  27. micrOS/source/modules/LM_roboarm.py +3 -4
  28. micrOS/source/modules/LM_robustness.py +1 -2
  29. micrOS/source/modules/LM_tcs3472.py +131 -17
  30. micrOS/source/modules/LM_telegram.py +17 -18
  31. {microsdevtoolkit-2.17.2.dist-info → microsdevtoolkit-2.20.0.dist-info}/METADATA +151 -215
  32. {microsdevtoolkit-2.17.2.dist-info → microsdevtoolkit-2.20.0.dist-info}/RECORD +69 -73
  33. toolkit/Gateway.py +1 -1
  34. toolkit/dashboard_apps/SystemTest.py +39 -32
  35. toolkit/micrOSdashboard.py +8 -13
  36. toolkit/socketClient.py +27 -7
  37. toolkit/workspace/precompiled/Common.mpy +0 -0
  38. toolkit/workspace/precompiled/Config.mpy +0 -0
  39. toolkit/workspace/precompiled/Espnow.mpy +0 -0
  40. toolkit/workspace/precompiled/InterConnect.mpy +0 -0
  41. toolkit/workspace/precompiled/Server.mpy +0 -0
  42. toolkit/workspace/precompiled/Shell.mpy +0 -0
  43. toolkit/workspace/precompiled/Tasks.mpy +0 -0
  44. toolkit/workspace/precompiled/micrOSloader.mpy +0 -0
  45. toolkit/workspace/precompiled/modules/LM_buzzer.mpy +0 -0
  46. toolkit/workspace/precompiled/modules/LM_cct.mpy +0 -0
  47. toolkit/workspace/precompiled/modules/LM_dimmer.mpy +0 -0
  48. toolkit/workspace/precompiled/modules/LM_distance.mpy +0 -0
  49. toolkit/workspace/precompiled/modules/LM_espnow.py +18 -1
  50. toolkit/workspace/precompiled/modules/LM_i2s_mic.mpy +0 -0
  51. toolkit/workspace/precompiled/modules/LM_keychain.mpy +0 -0
  52. toolkit/workspace/precompiled/modules/LM_light_sensor.mpy +0 -0
  53. toolkit/workspace/precompiled/modules/LM_mqtt_client.mpy +0 -0
  54. toolkit/workspace/precompiled/modules/LM_neoeffects.mpy +0 -0
  55. toolkit/workspace/precompiled/modules/LM_neomatrix.mpy +0 -0
  56. toolkit/workspace/precompiled/modules/LM_neopixel.mpy +0 -0
  57. toolkit/workspace/precompiled/modules/LM_oled_ui.mpy +0 -0
  58. toolkit/workspace/precompiled/modules/LM_oledui.mpy +0 -0
  59. toolkit/workspace/precompiled/modules/LM_presence.mpy +0 -0
  60. toolkit/workspace/precompiled/modules/LM_rest.mpy +0 -0
  61. toolkit/workspace/precompiled/modules/LM_rgb.mpy +0 -0
  62. toolkit/workspace/precompiled/modules/LM_roboarm.mpy +0 -0
  63. toolkit/workspace/precompiled/modules/LM_robustness.py +1 -2
  64. toolkit/workspace/precompiled/modules/LM_tcs3472.py +131 -17
  65. toolkit/workspace/precompiled/modules/LM_telegram.mpy +0 -0
  66. micrOS/micropython/esp32s2-LOLIN_MINI-20220618-v1.19.1.bin +0 -0
  67. micrOS/micropython/esp32s3_spiram_oct-20231005-v1.21.0.bin +0 -0
  68. micrOS/source/modules/LM_pet_feeder.py +0 -78
  69. toolkit/workspace/precompiled/modules/LM_pet_feeder.py +0 -78
  70. {microsdevtoolkit-2.17.2.data → microsdevtoolkit-2.20.0.data}/scripts/devToolKit.py +0 -0
  71. {microsdevtoolkit-2.17.2.dist-info → microsdevtoolkit-2.20.0.dist-info}/WHEEL +0 -0
  72. {microsdevtoolkit-2.17.2.dist-info → microsdevtoolkit-2.20.0.dist-info}/licenses/LICENSE +0 -0
  73. {microsdevtoolkit-2.17.2.dist-info → microsdevtoolkit-2.20.0.dist-info}/top_level.txt +0 -0
@@ -6,26 +6,54 @@ Copyright (c) 2021 tti0
6
6
  Licensed under the MIT License
7
7
  """
8
8
 
9
- from machine import I2C, Pin
9
+ from struct import unpack
10
+ from time import sleep
11
+ from machine import I2C, Pin, PWM
10
12
  from microIO import bind_pin, pinmap_search
11
- import struct
13
+ from Types import resolve
12
14
 
15
+ from LM_neopixel import load as neo_load, color as neo_color, toggle as neo_toggle # local neopixel light indicator
16
+ from LM_cluster import run as cluster_run # DEMO: neomatrix cluster
17
+
18
+ CURRENT_ANIMATION_INDEX = 0 # DEMO: neomatrix cluster animation
13
19
 
14
20
  class TCS3472:
15
21
  INSTANCE = None
16
22
 
17
- def __init__(self, bus, address=0x29):
18
- self._bus = bus
23
+ def __init__(self, address=0x29, led_pin=None):
24
+ self._bus = I2C(sda=Pin(bind_pin('i2c_sda')), scl=Pin(bind_pin('i2c_scl')))
19
25
  self._i2c_address = address
20
26
  self._bus.writeto(self._i2c_address, b'\x80\x03')
21
27
  self._bus.writeto(self._i2c_address, b'\x81\x2b')
28
+ self.led = PWM(Pin(bind_pin('led', led_pin), Pin.OUT), freq=20480)
29
+ self.led_brightness = 20
22
30
  TCS3472.INSTANCE = self
23
31
 
24
- def scaled(self):
25
- crgb = self.raw()
26
- if crgb[0] > 0:
27
- return tuple(float(x) / crgb[0] for x in crgb[1:])
28
- return 0, 0, 0
32
+ def scaled(self, saturation=1.5):
33
+ """
34
+ Normalize by strongest color, then adjust saturation.
35
+ saturation = 1.0 -> normal
36
+ saturation > 1.0 -> more vibrant
37
+ saturation < 1.0 -> more pastel
38
+ """
39
+ _, r, g, b = self.raw()
40
+ m = max(r, g, b)
41
+ if m == 0:
42
+ return 0.0, 0.0, 0.0
43
+
44
+ # Normalize by strongest channel
45
+ r, g, b = r / m, g / m, b / m
46
+
47
+ # Grayscale = average of channels
48
+ gray = (r + g + b) / 3
49
+
50
+ # Interpolate between gray and color
51
+ r = gray + (r - gray) * saturation
52
+ g = gray + (g - gray) * saturation
53
+ b = gray + (b - gray) * saturation
54
+
55
+ # Clamp to 0..1
56
+ return max(0, min(1, r)), max(0, min(1, g)), max(0, min(1, b))
29
57
 
30
58
  def rgb(self):
31
59
  return tuple(int(x * 255) for x in self.scaled())
@@ -42,32 +70,118 @@ class TCS3472:
42
70
 
43
71
  def raw(self):
44
72
  self._bus.writeto(self._i2c_address, b'\xb4')
45
- return struct.unpack("<HHHH", self._bus.readfrom(self._i2c_address, 8))
73
+ return unpack("<HHHH", self._bus.readfrom(self._i2c_address, 8))
46
74
 
47
75
 
48
76
  ############################ Exposed functions ############################
49
77
 
50
- def load():
78
+ def load(led_pin=20):
51
79
  """
52
80
  Load the TCS3472 Color sensor instance.
53
81
  """
54
82
  if TCS3472.INSTANCE is None:
55
- bus = I2C(sda=Pin(bind_pin('i2c_sda')), scl=Pin(bind_pin('i2c_scl')))
56
- TCS3472.INSTANCE = TCS3472(bus)
83
+ TCS3472(led_pin=led_pin)
84
+ neo_load(ledcnt=1)
85
+ led(False)
57
86
  return TCS3472.INSTANCE
58
87
 
59
88
 
60
89
  def pinmap():
61
- return pinmap_search(['i2c_scl', 'i2c_sda'])
90
+ """
91
+ Show used pin mapping for this module.
92
+ """
93
+ return pinmap_search(['i2c_scl', 'i2c_sda', 'led'])
62
94
 
63
95
 
64
96
  def measure():
97
+ """
98
+ MEASURE sensor
99
+ """
100
+ sensor = load()
101
+ measurement = {"rgb": sensor.rgb(), "light": sensor.light(), "brightness": sensor.brightness()}
102
+ return measurement
103
+
104
+
105
+ def led(state:bool=None, br:int=None):
106
+ """
107
+ SENSOR LED toggle
108
+ :param state: None-automatic, True-ON, False-OFF
109
+ :param br: brightness 0-100
110
+ """
111
+ def _set_duty(_br):
112
+ _br = sensor.led_brightness if _br is None else _br
113
+ sensor.led.duty(int(_br * 10))
114
+ if _br != 0:
115
+ sensor.led_brightness = _br
116
+
65
117
  sensor = load()
66
- return {"rgb": sensor.rgb(), "light": sensor.light(), "brightness": sensor.brightness()}
118
+ if state is None:
119
+ # INVERT STATE
120
+ led_current_state = sensor.led.duty() > 0
121
+ if led_current_state:
122
+ _set_duty(br)
123
+ _set_duty(0)
124
+ neo_toggle(False)
125
+ else:
126
+ _set_duty(br)
127
+ neo_toggle(True)
128
+ else:
129
+ # SET STATE: ON/OFF
130
+ if state:
131
+ _set_duty(br)
132
+ neo_toggle(True)
133
+ else:
134
+ _set_duty(br)
135
+ _set_duty(0)
136
+ neo_toggle(False)
137
+ return f"LED on, {sensor.led_brightness}%" if sensor.led.duty()>0 else f"LED off"
138
+
139
+
140
+ def indicator(br=5):
141
+ """
142
+ Color indicator Neopixel LED update
143
+ :param br: brightness 0-100
144
+ """
145
+ r, g, b = measure()['rgb']
146
+ br = float(br / 100)
147
+ _r, _g, _b = int(r*br), int(g*br), int(b*br)
148
+ neo_color(_r, _g, _b, smooth=False)
149
+ return r, g, b
150
+
151
+
152
+ def neomatrix_update():
153
+ """
154
+ DEMO - Send color codes for all neomatrix devices over espnow cluster
155
+ """
156
+ r, g, b = indicator()
157
+ command = f"neomatrix color_fill {r} {g} {b}"
158
+ cluster_run(command)
159
+ return {"cmd": command, "cluster": "task show con.espnow.*"}
160
+
161
+
162
+ def neomatrix_animation():
163
+ """
164
+ DEMO - Set random animation on neomatrix espnow cluster
165
+ """
166
+ global CURRENT_ANIMATION_INDEX
167
+ animations = ('spiral', 'snake', 'noise')
168
+
169
+ next_animation = CURRENT_ANIMATION_INDEX + 1
170
+ CURRENT_ANIMATION_INDEX = 0 if next_animation >= len(animations) else next_animation
171
+ command = f"neomatrix {animations[CURRENT_ANIMATION_INDEX]}"
172
+ cluster_run(command)
173
+ return {"cmd": command, "cluster": "task show con.espnow.*"}
67
174
 
68
175
 
69
- def help(widgest=False):
176
+ def help(widgets=False):
70
177
  """
71
178
  TCS3472 Color sensor
72
179
  """
73
- return 'load', 'measure'
180
+ return resolve(('load led_pin=20',
181
+ 'TEXTBOX measure',
182
+ 'BUTTON led state=<True,False>',
183
+ 'SLIDER led state=True br=<0-100-5>',
184
+ 'indicator br=<0-100>',
185
+ 'BUTTON neomatrix_update',
186
+ 'BUTTON neomatrix_animation',
187
+ 'pinmap'), widgets=widgets)
@@ -12,6 +12,7 @@ def _timestamp():
12
12
 
13
13
 
14
14
  class Telegram(Notify):
15
+ INSTANCE = None
15
16
  # Telegram bot token and chat ID
16
17
  # https://core.telegram.org/bots/api
17
18
  _TOKEN = None # Telegram token
@@ -23,6 +24,7 @@ class Telegram(Notify):
23
24
  def __init__(self):
24
25
  # Subscribe to the notification system - provide send_msg method (over self)
25
26
  super().add_subscriber(self)
27
+ Telegram.INSTANCE = self
26
28
 
27
29
  @staticmethod
28
30
  def __id_cache(mode):
@@ -236,7 +238,7 @@ class Telegram(Notify):
236
238
  return verdict
237
239
 
238
240
  @staticmethod
239
- async def bot_repl(tag, period=3):
241
+ async def server_bot(tag, period=3):
240
242
  """
241
243
  BOT - ReceiveEvalPrintLoop
242
244
  :param tag: task tag (access)
@@ -290,17 +292,16 @@ class Telegram(Notify):
290
292
  #########################################
291
293
  # micrOS Notifications #
292
294
  #########################################
293
- TELEGRAM_OBJ = None
294
295
 
295
296
  def __init():
296
- global TELEGRAM_OBJ
297
- if TELEGRAM_OBJ is None:
297
+ if Telegram.INSTANCE is None:
298
298
  # ENABLE TELEGRAM IF NW IS STA - CONNECTED TO THE WEB
299
299
  _sta_available = True if ifconfig()[0] == "STA" else False
300
300
  if _sta_available:
301
- TELEGRAM_OBJ = Telegram()
301
+ Telegram()
302
302
  else:
303
303
  syslog("No STA: cannot init telegram")
304
+ return Telegram.INSTANCE
304
305
 
305
306
  # Auto INIT Telegram at load time (legacy)
306
307
  __init()
@@ -311,10 +312,9 @@ def load():
311
312
  - /ping
312
313
  - /cmd module function (params)
313
314
  """
314
- __init()
315
- if TELEGRAM_OBJ is None:
315
+ if __init() is None:
316
316
  return "Network unavailable."
317
- verdict = TELEGRAM_OBJ.set_commands()
317
+ verdict = Telegram.set_commands()
318
318
  return "Missing telegram bot token" if verdict is None else verdict
319
319
 
320
320
 
@@ -324,9 +324,9 @@ def send(text):
324
324
  :param text: text to send
325
325
  return verdict
326
326
  """
327
- if TELEGRAM_OBJ is None:
327
+ if Telegram.INSTANCE is None:
328
328
  return "Network unavailable."
329
- verdict = TELEGRAM_OBJ.send_msg(text)
329
+ verdict = Telegram.send_msg(text)
330
330
  return "Missing telegram bot token" if verdict is None else verdict
331
331
 
332
332
  def notify(text):
@@ -336,9 +336,9 @@ def notify(text):
336
336
  telegram notification enable=True
337
337
  telegram notification enable=False
338
338
  """
339
- if TELEGRAM_OBJ is None:
339
+ if Telegram.INSTANCE is None:
340
340
  return "Network unavailable."
341
- return TELEGRAM_OBJ.notify(text)
341
+ return Telegram.INSTANCE.notify(text)
342
342
 
343
343
 
344
344
  def receive():
@@ -347,9 +347,9 @@ def receive():
347
347
  - if all value None, then no incoming messages
348
348
  One successful msg receive is necessary to get chat_id for msg send as well!
349
349
  """
350
- if TELEGRAM_OBJ is None:
350
+ if Telegram.INSTANCE is None:
351
351
  return "Network unavailable."
352
- verdict = TELEGRAM_OBJ.get_msg()
352
+ verdict = Telegram.get_msg()
353
353
  return "Missing telegram bot token" if verdict is None else verdict
354
354
 
355
355
 
@@ -359,11 +359,10 @@ def receiver_loop(period=3):
359
359
  - Only executes module (function) if the module is already loaded
360
360
  :param period: polling period in sec, default: 3
361
361
  """
362
- if TELEGRAM_OBJ is None:
362
+ if Telegram.INSTANCE is None:
363
363
  return "Network unavailable."
364
- tag = 'telegram.bot_repl'
365
- state = micro_task(tag=tag, task=TELEGRAM_OBJ.bot_repl(tag=tag, period=period))
366
- return "Starting" if state else "Already running"
364
+ tag = 'telegram.server_bot'
365
+ return micro_task(tag=tag, task=Telegram.server_bot(tag=tag, period=period))
367
366
 
368
367
 
369
368
  def help(widgets=False):