micrOSDevToolKit 2.10.6__py3-none-any.whl → 2.13.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 +57 -61
- micrOS/source/Common.py +286 -91
- micrOS/source/Config.py +7 -7
- micrOS/source/Debug.py +50 -94
- micrOS/source/Espnow.py +7 -7
- micrOS/source/Files.py +23 -2
- micrOS/source/Hooks.py +62 -19
- 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/InterConnect.py +5 -5
- micrOS/source/Interrupts.py +2 -2
- micrOS/source/LM_VL53L0X.py +1 -1
- micrOS/source/LM_buzzer.py +6 -7
- micrOS/source/LM_cct.py +6 -5
- micrOS/source/LM_dashboard_be.py +2 -2
- 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 +335 -0
- micrOS/source/LM_neopixel.py +10 -10
- micrOS/source/LM_pacman.py +40 -23
- 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 +47 -33
- micrOS/source/Network.py +6 -6
- micrOS/source/Notify.py +2 -2
- micrOS/source/Scheduler.py +5 -5
- micrOS/source/Server.py +6 -6
- micrOS/source/Shell.py +4 -4
- micrOS/source/Tasks.py +20 -17
- micrOS/source/Time.py +12 -10
- micrOS/source/Types.py +2 -2
- micrOS/source/Web.py +20 -13
- micrOS/source/__pycache__/Common.cpython-312.pyc +0 -0
- micrOS/source/__pycache__/Debug.cpython-312.pyc +0 -0
- micrOS/source/__pycache__/Logger.cpython-312.pyc +0 -0
- micrOS/source/__pycache__/Server.cpython-312.pyc +0 -0
- micrOS/source/micrOS.py +10 -7
- micrOS/source/micrOSloader.py +6 -6
- micrOS/source/microIO.py +8 -6
- micrOS/source/urequests.py +4 -4
- {microsdevtoolkit-2.10.6.dist-info → microsdevtoolkit-2.13.0.dist-info}/METADATA +24 -22
- {microsdevtoolkit-2.10.6.dist-info → microsdevtoolkit-2.13.0.dist-info}/RECORD +142 -132
- toolkit/DevEnvCompile.py +20 -15
- toolkit/DevEnvOTA.py +29 -8
- toolkit/DevEnvUSB.py +52 -10
- toolkit/LM_to_compile.dat +1 -0
- toolkit/MicrOSDevEnv.py +10 -2
- toolkit/MicrosFiles.py +26 -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/lib/LocalMachine.py +6 -1
- toolkit/lib/file_extensions.py +9 -3
- toolkit/micrOSlint.py +3 -1
- 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.cpython-312.pyc +0 -0
- toolkit/workspace/precompiled/Common.mpy +0 -0
- toolkit/workspace/precompiled/Config.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/InterConnect.mpy +0 -0
- toolkit/workspace/precompiled/Interrupts.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_dashboard_be.py +2 -2
- 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.cpython-312.pyc +0 -0
- toolkit/workspace/precompiled/Logger.mpy +0 -0
- toolkit/workspace/precompiled/Network.mpy +0 -0
- toolkit/workspace/precompiled/Notify.mpy +0 -0
- toolkit/workspace/precompiled/Scheduler.mpy +0 -0
- toolkit/workspace/precompiled/Server.cpython-312.pyc +0 -0
- toolkit/workspace/precompiled/Server.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/Types.mpy +0 -0
- toolkit/workspace/precompiled/Web.mpy +0 -0
- toolkit/workspace/precompiled/micrOS.mpy +0 -0
- toolkit/workspace/precompiled/micrOSloader.mpy +0 -0
- toolkit/workspace/precompiled/microIO.mpy +0 -0
- toolkit/workspace/precompiled/urequests.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
- /micrOS/source/{dashboard.html → web/dashboard.html} +0 -0
- /micrOS/source/{index.html → web/index.html} +0 -0
- /micrOS/source/{uapi.js → web/uapi.js} +0 -0
- /micrOS/source/{udashboard.js → web/udashboard.js} +0 -0
- /micrOS/source/{ustyle.css → web/ustyle.css} +0 -0
- /micrOS/source/{uwidgets.js → web/uwidgets.js} +0 -0
- /micrOS/source/{uwidgets_pro.js → web/uwidgets_pro.js} +0 -0
- {microsdevtoolkit-2.10.6.data → microsdevtoolkit-2.13.0.data}/scripts/devToolKit.py +0 -0
- {microsdevtoolkit-2.10.6.dist-info → microsdevtoolkit-2.13.0.dist-info}/WHEEL +0 -0
- {microsdevtoolkit-2.10.6.dist-info → microsdevtoolkit-2.13.0.dist-info}/licenses/LICENSE +0 -0
- {microsdevtoolkit-2.10.6.dist-info → microsdevtoolkit-2.13.0.dist-info}/top_level.txt +0 -0
- /toolkit/workspace/precompiled/{dashboard.html → web/dashboard.html} +0 -0
- /toolkit/workspace/precompiled/{index.html → web/index.html} +0 -0
- /toolkit/workspace/precompiled/{uapi.js → web/uapi.js} +0 -0
- /toolkit/workspace/precompiled/{udashboard.js → web/udashboard.js} +0 -0
- /toolkit/workspace/precompiled/{ustyle.css → web/ustyle.css} +0 -0
- /toolkit/workspace/precompiled/{uwidgets.js → web/uwidgets.js} +0 -0
- /toolkit/workspace/precompiled/{uwidgets_pro.js → web/uwidgets_pro.js} +0 -0
micrOS/source/Scheduler.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from time import localtime
|
|
2
2
|
from re import compile
|
|
3
3
|
from Tasks import exec_lm_pipe_schedule
|
|
4
|
-
from Debug import console_write,
|
|
4
|
+
from Debug import console_write, syslog
|
|
5
5
|
from Time import Sun, suntime, ntp_time
|
|
6
6
|
|
|
7
7
|
"""
|
|
@@ -101,7 +101,7 @@ def __resolve_time_tag(check_time, crontask):
|
|
|
101
101
|
# Resolve tag
|
|
102
102
|
value = Sun.TIME.get(tag, None)
|
|
103
103
|
if value is None or len(value) < 3:
|
|
104
|
-
|
|
104
|
+
syslog(f'[ERR] cron syntax error: {tag}:{value}')
|
|
105
105
|
return ()
|
|
106
106
|
|
|
107
107
|
# Update check_time with resolved value by tag
|
|
@@ -186,7 +186,7 @@ def __scheduler_trigger(cron_time_now, crontask, deltasec=2):
|
|
|
186
186
|
console_write(f"[builtin cron] {crontask[1]()}")
|
|
187
187
|
lm_state = True
|
|
188
188
|
except Exception as e:
|
|
189
|
-
|
|
189
|
+
syslog(f"[ERR] cron function exec error: {e}")
|
|
190
190
|
if not lm_state:
|
|
191
191
|
console_write(f"[cron]now[{cron_time_now}] \
|
|
192
192
|
{__convert_sec_to_time(tolerance_min_sec)} <-> {__convert_sec_to_time(tolerance_max_sec)} \
|
|
@@ -224,7 +224,7 @@ def deserialize_raw_input(cron_data):
|
|
|
224
224
|
sep = ';;' if ';;' in cd else ';' # support multi command with ;;
|
|
225
225
|
return (tuple(cron.split('!')) for cron in cd.split(sep))
|
|
226
226
|
except Exception as e:
|
|
227
|
-
|
|
227
|
+
syslog(f"[ERR] cron deserialize - syntax error: {e}")
|
|
228
228
|
return ()
|
|
229
229
|
|
|
230
230
|
|
|
@@ -256,5 +256,5 @@ def scheduler(cron_data, irqperiod):
|
|
|
256
256
|
state |= __scheduler_trigger(cron_time_now, cron, deltasec=irqperiod)
|
|
257
257
|
return state
|
|
258
258
|
except Exception as e:
|
|
259
|
-
|
|
259
|
+
syslog(f'[ERR] cron callback error: {e}')
|
|
260
260
|
return False
|
micrOS/source/Server.py
CHANGED
|
@@ -13,7 +13,7 @@ Designed by Marcell Ban aka BxNxM GitHub
|
|
|
13
13
|
import uasyncio as asyncio
|
|
14
14
|
from utime import ticks_ms, ticks_diff
|
|
15
15
|
from Config import cfgget
|
|
16
|
-
from Debug import console_write,
|
|
16
|
+
from Debug import console_write, syslog
|
|
17
17
|
from Network import ifconfig
|
|
18
18
|
from Tasks import Manager
|
|
19
19
|
from Shell import Shell
|
|
@@ -99,7 +99,7 @@ class Client:
|
|
|
99
99
|
except Exception as e:
|
|
100
100
|
# Maintain ACTIVE_CLIS - remove closed connection by peer.
|
|
101
101
|
await self.close()
|
|
102
|
-
|
|
102
|
+
syslog(f"[WARN] Client.a_send (auto-drop) {self.client_id}: {e}")
|
|
103
103
|
return # Abort async send (no drain)
|
|
104
104
|
# Send buffered data with async task - hacky
|
|
105
105
|
try:
|
|
@@ -169,7 +169,7 @@ class WebCli(Client, WebEngine):
|
|
|
169
169
|
break
|
|
170
170
|
await self.response(request)
|
|
171
171
|
except Exception as e:
|
|
172
|
-
|
|
172
|
+
syslog(f"[ERR] Client.run_web: {e}")
|
|
173
173
|
break
|
|
174
174
|
# Close connection
|
|
175
175
|
await self.close()
|
|
@@ -211,7 +211,7 @@ class ShellCli(Client, Shell):
|
|
|
211
211
|
except:
|
|
212
212
|
# Maintain ACTIVE_CLIS - remove closed connection by peer.
|
|
213
213
|
Client.drop_client(self.client_id)
|
|
214
|
-
|
|
214
|
+
syslog(f"[WARN] ShellCli.send (auto-drop) {self.client_id}")
|
|
215
215
|
# Send buffered data with async task - hacky
|
|
216
216
|
if self.drain_event.is_set():
|
|
217
217
|
self.drain_event.clear() # set drain busy (False)
|
|
@@ -261,12 +261,12 @@ class ShellCli(Client, Shell):
|
|
|
261
261
|
# Shell -> True (OK) or False (NOK) -> NOK->Close session (auth Failed, etc.)
|
|
262
262
|
_exit = not await self.shell(request)
|
|
263
263
|
except Exception as e:
|
|
264
|
-
|
|
264
|
+
syslog(f"[ERR] Shell client: {e}")
|
|
265
265
|
if "ECONNRESET" in str(e):
|
|
266
266
|
_exit = True # exit_loop
|
|
267
267
|
else:
|
|
268
268
|
await self.a_send("[HA] Critical error - disconnect & hard reset")
|
|
269
|
-
|
|
269
|
+
syslog("[ERR] Socket critical error - reboot")
|
|
270
270
|
await self.reboot()
|
|
271
271
|
if _exit:
|
|
272
272
|
collect()
|
micrOS/source/Shell.py
CHANGED
|
@@ -16,7 +16,7 @@ from machine import reset as hard_reset, soft_reset
|
|
|
16
16
|
from Config import cfgget, cfgput
|
|
17
17
|
from Files import ilist_fs
|
|
18
18
|
from Tasks import lm_exec
|
|
19
|
-
from Debug import
|
|
19
|
+
from Debug import syslog
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
#################################################################
|
|
@@ -25,7 +25,7 @@ from Debug import errlog_add
|
|
|
25
25
|
|
|
26
26
|
class Shell:
|
|
27
27
|
__slots__ = ['__devfid', '__auth_mode', '__hwuid', '__auth_ok', '__conf_mode']
|
|
28
|
-
MICROS_VERSION = '2.
|
|
28
|
+
MICROS_VERSION = '2.13.0-0'
|
|
29
29
|
|
|
30
30
|
def __init__(self):
|
|
31
31
|
"""
|
|
@@ -43,7 +43,7 @@ class Shell:
|
|
|
43
43
|
try:
|
|
44
44
|
cfgput('version', Shell.MICROS_VERSION)
|
|
45
45
|
except Exception as e:
|
|
46
|
-
|
|
46
|
+
syslog(f"[ERR] micrOS version export failed (config): {e}")
|
|
47
47
|
|
|
48
48
|
async def a_send(self, msg):
|
|
49
49
|
""" Must be defined by child class... """
|
|
@@ -306,5 +306,5 @@ class Shell:
|
|
|
306
306
|
except Exception as e:
|
|
307
307
|
_err_msg = f"[ERR] while starting webrepl: {e}"
|
|
308
308
|
await msg_obj(_err_msg)
|
|
309
|
-
|
|
309
|
+
syslog(_err_msg)
|
|
310
310
|
return True
|
micrOS/source/Tasks.py
CHANGED
|
@@ -13,7 +13,7 @@ from json import dumps
|
|
|
13
13
|
import uasyncio as asyncio
|
|
14
14
|
from micropython import schedule
|
|
15
15
|
from utime import ticks_ms, ticks_diff
|
|
16
|
-
from Debug import console_write,
|
|
16
|
+
from Debug import console_write, syslog
|
|
17
17
|
from Config import cfgget
|
|
18
18
|
from Network import sta_high_avail
|
|
19
19
|
|
|
@@ -75,12 +75,12 @@ class TaskBase:
|
|
|
75
75
|
self.task.cancel() # Try to cancel task by asyncio
|
|
76
76
|
except Exception as e:
|
|
77
77
|
if "can't cancel self" != str(e):
|
|
78
|
-
|
|
78
|
+
syslog(f"[WARN] IRQ Task cancel: {e}")
|
|
79
79
|
self.__task_del()
|
|
80
80
|
else:
|
|
81
81
|
return False
|
|
82
82
|
except Exception as e:
|
|
83
|
-
|
|
83
|
+
syslog(f"[ERR] Task kill: {e}")
|
|
84
84
|
return False
|
|
85
85
|
return True
|
|
86
86
|
|
|
@@ -98,16 +98,18 @@ class TaskBase:
|
|
|
98
98
|
async def feed(sleep_ms=1):
|
|
99
99
|
"""
|
|
100
100
|
Feed event loop
|
|
101
|
-
:param sleep_ms: in millisecond
|
|
101
|
+
:param sleep_ms: in millisecond
|
|
102
102
|
"""
|
|
103
103
|
# TODO: feed WDT - preemptive cooperative multitasking aka reboot if no feed until X time period
|
|
104
|
+
if sleep_ms <= 0:
|
|
105
|
+
return await asyncio.sleep(0.000_000_1) # 0 means: 100ns (Absolute minimum)
|
|
104
106
|
return await asyncio.sleep_ms(sleep_ms)
|
|
105
107
|
|
|
106
108
|
def __del__(self):
|
|
107
109
|
try:
|
|
108
110
|
self.__task_del(keep_cache=True)
|
|
109
111
|
except Exception as e:
|
|
110
|
-
|
|
112
|
+
syslog(f"[ERR] TaskBase.__del__: {e}")
|
|
111
113
|
|
|
112
114
|
|
|
113
115
|
class NativeTask(TaskBase):
|
|
@@ -116,7 +118,7 @@ class NativeTask(TaskBase):
|
|
|
116
118
|
- could be built in function or custom code from load modules
|
|
117
119
|
"""
|
|
118
120
|
|
|
119
|
-
def create(self, callback=None, tag=None):
|
|
121
|
+
def create(self, callback:callable=None, tag:str=None) -> bool:
|
|
120
122
|
"""
|
|
121
123
|
Create async task with coroutine callback (no queue limit check!)
|
|
122
124
|
+ async socket server task
|
|
@@ -166,7 +168,7 @@ class MagicTask(TaskBase):
|
|
|
166
168
|
self.__inloop = False # [LM] Task while loop for LM callback
|
|
167
169
|
self.__sleep = 20 # [LM] Task while loop - async wait (proc feed) [ms]
|
|
168
170
|
|
|
169
|
-
def create(self, callback=None, loop=None, sleep=None):
|
|
171
|
+
def create(self, callback:list=None, loop:bool=None, sleep:int=None) -> bool:
|
|
170
172
|
"""
|
|
171
173
|
Create async task with function callback (with queue limit check)
|
|
172
174
|
- wrap (sync) function into async task (task_wrapper)
|
|
@@ -238,7 +240,7 @@ class Manager:
|
|
|
238
240
|
cls.INSTANCE._initialized = False
|
|
239
241
|
# Set async event loop exception handler
|
|
240
242
|
asyncio.get_event_loop().set_exception_handler(lambda loop=None, context=None:
|
|
241
|
-
|
|
243
|
+
syslog(f"[aio] exception: {loop}:{context}"))
|
|
242
244
|
return cls.INSTANCE
|
|
243
245
|
|
|
244
246
|
def __init__(self):
|
|
@@ -263,7 +265,7 @@ class Manager:
|
|
|
263
265
|
"""
|
|
264
266
|
if Manager._queue_len() >= TaskBase.QUEUE_SIZE:
|
|
265
267
|
msg = f"[aio] Task queue full: {TaskBase.QUEUE_SIZE}"
|
|
266
|
-
|
|
268
|
+
syslog(msg)
|
|
267
269
|
raise Exception(msg)
|
|
268
270
|
|
|
269
271
|
async def idle_task(self):
|
|
@@ -291,15 +293,16 @@ class Manager:
|
|
|
291
293
|
sta_high_avail()
|
|
292
294
|
self.idle_counter += 1 # Increase counter
|
|
293
295
|
except Exception as e:
|
|
294
|
-
|
|
296
|
+
syslog(f"[ERR] Idle task exists: {e}")
|
|
295
297
|
my_task.done.set()
|
|
296
298
|
|
|
297
299
|
@staticmethod
|
|
298
|
-
def create_task(callback, tag=None, loop=False, delay=None):
|
|
300
|
+
def create_task(callback, tag:str=None, loop:bool=False, delay:int=None):
|
|
299
301
|
"""
|
|
300
302
|
Primary interface
|
|
301
303
|
Generic task creator method
|
|
302
304
|
Create async Task with coroutine/list(lm call) callback
|
|
305
|
+
:param callback: list|callable
|
|
303
306
|
"""
|
|
304
307
|
if isinstance(callback, list):
|
|
305
308
|
# Check queue if task is Load Module
|
|
@@ -371,7 +374,7 @@ class Manager:
|
|
|
371
374
|
try:
|
|
372
375
|
return False if to_kill is None else to_kill.cancel()
|
|
373
376
|
except Exception as e:
|
|
374
|
-
|
|
377
|
+
syslog(f"[ERR] Task kill: {e}")
|
|
375
378
|
return False
|
|
376
379
|
|
|
377
380
|
# Handle task group kill (module.*)
|
|
@@ -397,7 +400,7 @@ class Manager:
|
|
|
397
400
|
try:
|
|
398
401
|
asyncio.get_event_loop().run_forever()
|
|
399
402
|
except Exception as e:
|
|
400
|
-
|
|
403
|
+
syslog(f"[aio] loop stopped: {e}")
|
|
401
404
|
asyncio.get_event_loop().close()
|
|
402
405
|
|
|
403
406
|
@staticmethod
|
|
@@ -438,7 +441,7 @@ def exec_builtins(func):
|
|
|
438
441
|
out = Manager.INTERCON(host=intercon_target, cmd=arg_list)
|
|
439
442
|
except Exception as e:
|
|
440
443
|
out = {}
|
|
441
|
-
|
|
444
|
+
syslog(f"[ERR] Intercon: {e}")
|
|
442
445
|
return True, out
|
|
443
446
|
|
|
444
447
|
# MODULES
|
|
@@ -599,9 +602,9 @@ def exec_lm_pipe(taskstr):
|
|
|
599
602
|
console_write(f"[SKIP] exec_lm_pipe: {' '.join(cmd)}")
|
|
600
603
|
continue
|
|
601
604
|
if not lm_exec(cmd)[0]:
|
|
602
|
-
|
|
605
|
+
syslog(f"[WARN] exec_lm_pipe: {cmd}")
|
|
603
606
|
except Exception as e:
|
|
604
|
-
|
|
607
|
+
syslog(f"[ERR] exec_lm_pipe {taskstr}: {e}")
|
|
605
608
|
return False
|
|
606
609
|
return True
|
|
607
610
|
|
|
@@ -614,5 +617,5 @@ def exec_lm_pipe_schedule(taskstr):
|
|
|
614
617
|
schedule(exec_lm_pipe, taskstr)
|
|
615
618
|
return True
|
|
616
619
|
except Exception as e:
|
|
617
|
-
|
|
620
|
+
syslog(f"[ERR] exec_lm_pipe_schedule: {e}")
|
|
618
621
|
return False
|
micrOS/source/Time.py
CHANGED
|
@@ -14,14 +14,16 @@ from network import WLAN, STA_IF
|
|
|
14
14
|
from utime import sleep_ms, time, mktime, localtime
|
|
15
15
|
|
|
16
16
|
from Config import cfgput, cfgget
|
|
17
|
-
from Debug import
|
|
17
|
+
from Debug import syslog, console_write
|
|
18
18
|
from urequests import get as http_get
|
|
19
|
+
from Files import OSPath, path_join
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
class Sun:
|
|
22
23
|
TIME = {}
|
|
23
24
|
UTC = cfgget('utc') # STORED IN MINUTE
|
|
24
25
|
BOOTIME = None # Initialize BOOTIME: Not SUN, but for system uptime
|
|
26
|
+
FILE_CACHE = path_join(OSPath.DATA, 'sun.cache')
|
|
25
27
|
|
|
26
28
|
|
|
27
29
|
def set_time(year, month, mday, hour, minute, sec):
|
|
@@ -47,7 +49,7 @@ def ntp_time():
|
|
|
47
49
|
:return: ntp date struct
|
|
48
50
|
"""
|
|
49
51
|
if not WLAN(STA_IF).isconnected():
|
|
50
|
-
|
|
52
|
+
syslog("[WARN] STA not connected: ntptime")
|
|
51
53
|
return False
|
|
52
54
|
|
|
53
55
|
def get_ntp():
|
|
@@ -83,28 +85,28 @@ def ntp_time():
|
|
|
83
85
|
console_write(f"ntptime error.:{e}")
|
|
84
86
|
err = e
|
|
85
87
|
sleep_ms(100)
|
|
86
|
-
|
|
88
|
+
syslog(f"[ERR] ntptime: {err}")
|
|
87
89
|
return False
|
|
88
90
|
|
|
89
91
|
|
|
90
92
|
def __sun_cache(mode):
|
|
91
93
|
"""
|
|
92
|
-
|
|
94
|
+
File cache
|
|
93
95
|
modes:
|
|
94
96
|
r - recover, s - save
|
|
95
97
|
"""
|
|
96
98
|
if mode == 's':
|
|
97
99
|
# SAVE CACHE
|
|
98
100
|
try:
|
|
99
|
-
with open(
|
|
101
|
+
with open(Sun.FILE_CACHE, 'w') as f:
|
|
100
102
|
cache = {k:tuple([str(t) for t in v]) for k, v in Sun.TIME.items()}
|
|
101
103
|
f.write(';'.join([f'{k}:{"-".join(v)}' for k, v in cache.items()]))
|
|
102
104
|
except:
|
|
103
|
-
|
|
105
|
+
syslog("[ERR] Cannot write sun cache")
|
|
104
106
|
return
|
|
105
107
|
try:
|
|
106
108
|
# RESTORE CACHE
|
|
107
|
-
with open(
|
|
109
|
+
with open(Sun.FILE_CACHE, 'r') as f:
|
|
108
110
|
buff = {data.split(':')[0]: data.split(':')[1].split('-')
|
|
109
111
|
for data in f.read().strip().split(';')}
|
|
110
112
|
for k, v in buff.items():
|
|
@@ -139,7 +141,7 @@ def suntime():
|
|
|
139
141
|
Sun.UTC = int(response.get('offset') / 60) # IN MINUTE
|
|
140
142
|
cfgput('utc', Sun.UTC, True)
|
|
141
143
|
except Exception as e:
|
|
142
|
-
|
|
144
|
+
syslog(f'[ERR] ip-api: {e} data: {response}')
|
|
143
145
|
return Sun.TIME
|
|
144
146
|
|
|
145
147
|
# SUNSET-SUNRISE API REQUEST HANDLING
|
|
@@ -154,7 +156,7 @@ def suntime():
|
|
|
154
156
|
sun = {'sunrise': time_regex.search(results.get('sunrise')).group(1).split(':'),
|
|
155
157
|
'sunset': time_regex.search(results.get('sunset')).group(1).split(':')}
|
|
156
158
|
except Exception as e:
|
|
157
|
-
|
|
159
|
+
syslog(f'[ERR] sunrise-api: {e} data: {response}')
|
|
158
160
|
# Try to parse response by expected sun_keys
|
|
159
161
|
try:
|
|
160
162
|
for key in sun:
|
|
@@ -162,7 +164,7 @@ def suntime():
|
|
|
162
164
|
sun[key][0] += int(Sun.UTC / 60)
|
|
163
165
|
sun[key] = tuple(sun[key])
|
|
164
166
|
except Exception as e:
|
|
165
|
-
|
|
167
|
+
syslog(f'[WARN] sunrise-api parse error: {e} sun: {sun}')
|
|
166
168
|
# Retrieve cached data and return
|
|
167
169
|
__sun_cache('r') # Using Sun.TIME
|
|
168
170
|
console_write('[suntime] loaded from cache')
|
micrOS/source/Types.py
CHANGED
|
@@ -12,7 +12,7 @@ USAGE:
|
|
|
12
12
|
SLIDER brightness br=<0-100-5>
|
|
13
13
|
"""
|
|
14
14
|
from json import dumps
|
|
15
|
-
from Debug import
|
|
15
|
+
from Debug import syslog
|
|
16
16
|
|
|
17
17
|
########################################################
|
|
18
18
|
# HELP TUPLE RESOLVER #
|
|
@@ -90,7 +90,7 @@ def resolve(help_data, widgets=False):
|
|
|
90
90
|
try:
|
|
91
91
|
help_msg.append(_generate(resolved_tag, msg))
|
|
92
92
|
except Exception as e:
|
|
93
|
-
|
|
93
|
+
syslog(f"[ERR] resolve {tag} help msg: {e}")
|
|
94
94
|
continue
|
|
95
95
|
help_msg.append(msg.replace(tag, '').strip())
|
|
96
96
|
elif not widgets:
|
micrOS/source/Web.py
CHANGED
|
@@ -15,8 +15,9 @@ Designed by Marcell Ban aka BxNxM
|
|
|
15
15
|
from json import dumps, loads
|
|
16
16
|
import uasyncio as asyncio
|
|
17
17
|
from Tasks import lm_exec, NativeTask, lm_is_loaded
|
|
18
|
-
from Debug import
|
|
18
|
+
from Debug import syslog, console_write
|
|
19
19
|
from Config import cfgget
|
|
20
|
+
from Files import OSPath, path_join
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
class WebEngine:
|
|
@@ -27,6 +28,14 @@ class WebEngine:
|
|
|
27
28
|
REQ200 = "HTTP/1.1 200 OK\r\nContent-Type: {dtype}\r\nContent-Length:{len}\r\n\r\n{data}"
|
|
28
29
|
REQ400 = "HTTP/1.1 400 Bad Request\r\nContent-Type: text/plain\r\nContent-Length: {len}\r\n\r\n{data}"
|
|
29
30
|
REQ404 = "HTTP/1.1 404 Not Found\r\nContent-Type: text/plain\r\nContent-Length: {len}\r\n\r\n{data}"
|
|
31
|
+
CONTENT_TYPES = {"html": "text/html",
|
|
32
|
+
"css": "text/css",
|
|
33
|
+
"js": "application/javascript",
|
|
34
|
+
"json": "application/json",
|
|
35
|
+
"ico": "image/x-icon", # favicon
|
|
36
|
+
"jpeg": "image/jpeg",
|
|
37
|
+
"png": "image/png",
|
|
38
|
+
"gif": "image/gif"}
|
|
30
39
|
|
|
31
40
|
def __init__(self, client, version):
|
|
32
41
|
self.client = client
|
|
@@ -35,14 +44,11 @@ class WebEngine:
|
|
|
35
44
|
@staticmethod
|
|
36
45
|
def file_type(path):
|
|
37
46
|
"""File dynamic Content-Type handling"""
|
|
38
|
-
|
|
39
|
-
".css": "text/css",
|
|
40
|
-
".js": "application/javascript",
|
|
41
|
-
".jpeg": "image/jpeg"}
|
|
47
|
+
default_type = "text/plain"
|
|
42
48
|
# Extract the file extension
|
|
43
49
|
ext = path.rsplit('.', 1)[-1]
|
|
44
50
|
# Return the content type based on the file extension
|
|
45
|
-
return
|
|
51
|
+
return WebEngine.CONTENT_TYPES.get(ext, default_type)
|
|
46
52
|
|
|
47
53
|
async def response(self, request):
|
|
48
54
|
"""HTTP GET REQUEST - WEB INTERFACE"""
|
|
@@ -68,13 +74,14 @@ class WebEngine:
|
|
|
68
74
|
# [3] HOME/PAGE ENDPOINT(s) [default: / -> /index.html]
|
|
69
75
|
if url.startswith('/'):
|
|
70
76
|
resource = 'index.html' if url == '/' else url.replace('/', '')
|
|
71
|
-
|
|
72
|
-
|
|
77
|
+
web_resource = path_join(OSPath.WEB, resource) # Redirect path to web folder
|
|
78
|
+
self.client.console(f"[WebCli] --- {url} ACCEPT -> {web_resource}")
|
|
79
|
+
if resource.split('.')[-1] not in tuple(self.CONTENT_TYPES.keys()):
|
|
73
80
|
await self.client.a_send(self.REQ404.format(len=27, data='404 Not supported file type'))
|
|
74
81
|
return
|
|
75
82
|
try:
|
|
76
|
-
# SEND RESOURCE CONTENT: HTML, JS, CSS
|
|
77
|
-
with open(
|
|
83
|
+
# SEND RESOURCE CONTENT: HTML, JS, CSS (WebEngine.CONTENT_TYPES)
|
|
84
|
+
with open(web_resource, 'r') as file:
|
|
78
85
|
data = file.read()
|
|
79
86
|
response = self.REQ200.format(dtype=WebEngine.file_type(resource), len=len(data), data=data)
|
|
80
87
|
# Send entire response data
|
|
@@ -90,7 +97,7 @@ class WebEngine:
|
|
|
90
97
|
# position += next_chunk_size
|
|
91
98
|
except Exception as e:
|
|
92
99
|
if 'memory allocation failed' in str(e):
|
|
93
|
-
|
|
100
|
+
syslog(f"[ERR] WebCli {resource}: {e}")
|
|
94
101
|
await self.client.a_send(self.REQ404.format(len=13, data='404 Not Found'))
|
|
95
102
|
return
|
|
96
103
|
# INVALID/BAD REQUEST
|
|
@@ -98,7 +105,7 @@ class WebEngine:
|
|
|
98
105
|
|
|
99
106
|
@staticmethod
|
|
100
107
|
def rest(url):
|
|
101
|
-
resp_schema = {'result':
|
|
108
|
+
resp_schema = {'result': {}, 'state': False}
|
|
102
109
|
cmd = url.replace('/rest', '')
|
|
103
110
|
if len(cmd) > 1:
|
|
104
111
|
# REST sub-parameter handling (rest commands)
|
|
@@ -149,7 +156,7 @@ class WebEngine:
|
|
|
149
156
|
await self.client.a_send(WebEngine.REQ200.format(dtype=dtype, len=len(data), data=data))
|
|
150
157
|
except Exception as e:
|
|
151
158
|
await self.client.a_send(self.REQ404.format(len=len(str(e)), data=e))
|
|
152
|
-
|
|
159
|
+
syslog(f"[ERR] WebCli endpoints {url}: {e}")
|
|
153
160
|
return True # Registered endpoint was found and executed
|
|
154
161
|
return False # Not registered endpoint
|
|
155
162
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
micrOS/source/micrOS.py
CHANGED
|
@@ -9,11 +9,11 @@ Designed by Marcell Ban aka BxNxM
|
|
|
9
9
|
#################################################################
|
|
10
10
|
from Time import ntp_time, suntime
|
|
11
11
|
from Tasks import Manager
|
|
12
|
-
from Hooks import bootup, profiling_info
|
|
12
|
+
from Hooks import bootup, profiling_info, enableESPNow
|
|
13
13
|
from Network import auto_nw_config
|
|
14
14
|
from Server import Server
|
|
15
15
|
from Interrupts import enableInterrupt, enableCron, initEventIRQs
|
|
16
|
-
from Debug import
|
|
16
|
+
from Debug import syslog
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
#################################################################
|
|
@@ -26,7 +26,7 @@ def irq_handler():
|
|
|
26
26
|
enableCron()
|
|
27
27
|
except Exception as e:
|
|
28
28
|
print(f"[micrOS main] InterruptHandler.enableInterrupt/CronInterrupt error: {e}")
|
|
29
|
-
|
|
29
|
+
syslog(f"[ERR] irq_handler error: {e}")
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
def external_irq_handler():
|
|
@@ -34,7 +34,7 @@ def external_irq_handler():
|
|
|
34
34
|
initEventIRQs()
|
|
35
35
|
except Exception as e:
|
|
36
36
|
print(f"[micrOS main] InterruptHandler.initEventIRQs error: {e}")
|
|
37
|
-
|
|
37
|
+
syslog(f"[ERR] external_irq_handler error: {e}")
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
#################################################################
|
|
@@ -53,7 +53,7 @@ def micrOS():
|
|
|
53
53
|
bootup()
|
|
54
54
|
except Exception as e:
|
|
55
55
|
print(f"[micrOS main] Hooks.boot() error: {e}")
|
|
56
|
-
|
|
56
|
+
syslog(f"[ERR] safe_boot: {e}")
|
|
57
57
|
|
|
58
58
|
# NETWORK setup
|
|
59
59
|
nwmd = auto_nw_config()
|
|
@@ -74,10 +74,13 @@ def micrOS():
|
|
|
74
74
|
|
|
75
75
|
# [Server] as async task
|
|
76
76
|
aio.create_task(Server().run_server(), tag='server')
|
|
77
|
-
|
|
77
|
+
|
|
78
|
+
# [ESPNow] server as async task
|
|
79
|
+
enableESPNow()
|
|
80
|
+
profiling_info(label='[memUsage] SYSTEM IS UP AND RUNNING')
|
|
78
81
|
|
|
79
82
|
# [EVENT LOOP] Start async event loop
|
|
80
83
|
aio.run_forever()
|
|
81
84
|
|
|
82
85
|
# UNEXPECTED RESTART ???
|
|
83
|
-
|
|
86
|
+
syslog("[ERR] !!! Unexpected micrOS restart")
|
micrOS/source/micrOSloader.py
CHANGED
|
@@ -12,10 +12,10 @@ try:
|
|
|
12
12
|
except:
|
|
13
13
|
traceback = None
|
|
14
14
|
try:
|
|
15
|
-
from Debug import
|
|
15
|
+
from Debug import syslog
|
|
16
16
|
except Exception as e:
|
|
17
17
|
print(f"[loader] Import error: {e}")
|
|
18
|
-
|
|
18
|
+
syslog = None
|
|
19
19
|
from machine import reset
|
|
20
20
|
|
|
21
21
|
|
|
@@ -70,8 +70,8 @@ def __recovery_mode():
|
|
|
70
70
|
import webrepl
|
|
71
71
|
webrepl.start(password=pwd)
|
|
72
72
|
except Exception as e:
|
|
73
|
-
if callable(
|
|
74
|
-
|
|
73
|
+
if callable(syslog):
|
|
74
|
+
syslog(f"[ERR][micrOSloader] webrepl failed: {e}")
|
|
75
75
|
print("[loader] Reset .if_mode to micros and reboot")
|
|
76
76
|
with open('.if_mode', 'w') as f:
|
|
77
77
|
f.write("micros")
|
|
@@ -126,8 +126,8 @@ def main():
|
|
|
126
126
|
# Handle micrOS system crash (never happened...but) -> webrepl mode default pwd: ADmin123
|
|
127
127
|
print(f"[loader][main mode] micrOS start failed: {e}")
|
|
128
128
|
print("[loader][main mode] -> [recovery mode]")
|
|
129
|
-
if callable(
|
|
130
|
-
|
|
129
|
+
if callable(syslog):
|
|
130
|
+
syslog(f"[ERR][micrOSloader] start failed: {e}")
|
|
131
131
|
# Recovery aka webrepl mode
|
|
132
132
|
__recovery_mode()
|
|
133
133
|
__auto_restart_event()
|
micrOS/source/microIO.py
CHANGED
|
@@ -30,17 +30,19 @@ def detect_platform():
|
|
|
30
30
|
"""
|
|
31
31
|
Unified platform detection for micrOS
|
|
32
32
|
"""
|
|
33
|
-
if 'esp32' in platform:
|
|
33
|
+
if 'esp32' in platform: # esp32 family
|
|
34
34
|
board = str(uname()[-1]).lower()
|
|
35
35
|
if 'tinypico' in board:
|
|
36
|
-
return 'tinypico'
|
|
36
|
+
return 'tinypico'
|
|
37
37
|
if 'esp32s2' in board:
|
|
38
|
-
return 'esp32s2'
|
|
38
|
+
return 'esp32s2'
|
|
39
39
|
if 'esp32s3' in board:
|
|
40
|
-
return 'esp32s3'
|
|
40
|
+
return 'esp32s3'
|
|
41
41
|
if 'esp32c3' in board:
|
|
42
|
-
return 'esp32c3'
|
|
43
|
-
|
|
42
|
+
return 'esp32c3'
|
|
43
|
+
if 'esp32c6' in board:
|
|
44
|
+
return 'esp32c6'
|
|
45
|
+
return 'esp32' # esp32 family: general
|
|
44
46
|
return platform # esp8266 or something else
|
|
45
47
|
|
|
46
48
|
|
micrOS/source/urequests.py
CHANGED
|
@@ -11,7 +11,7 @@ try:
|
|
|
11
11
|
from ussl import wrap_socket # Legacy micropython ssl usage (+simulator mode)
|
|
12
12
|
except ImportError:
|
|
13
13
|
from ssl import wrap_socket # From micropython 1.23...
|
|
14
|
-
from Debug import
|
|
14
|
+
from Debug import syslog
|
|
15
15
|
import uasyncio as asyncio
|
|
16
16
|
|
|
17
17
|
|
|
@@ -147,7 +147,7 @@ def request(method:str, url:str, data:str=None, json=None, headers:dict=None, so
|
|
|
147
147
|
try:
|
|
148
148
|
sock = wrap_socket(sock) if proto == 'https:' else sock
|
|
149
149
|
except Exception as e:
|
|
150
|
-
|
|
150
|
+
syslog(f'[ERR] https soc-wrap: {e}')
|
|
151
151
|
|
|
152
152
|
# [1] BUILD REQUEST
|
|
153
153
|
http_request = _build_request(host, method, path, headers, data, json)
|
|
@@ -206,7 +206,7 @@ async def arequest(method:str, url:str, data:str=None, json=None, headers:dict=N
|
|
|
206
206
|
addr = _host_to_addr(host, port, force=True)
|
|
207
207
|
reader, writer = await asyncio.open_connection(addr[0], port, ssl=(proto == 'https:'))
|
|
208
208
|
else:
|
|
209
|
-
|
|
209
|
+
syslog(f"[ERR] arequest connection: {e}")
|
|
210
210
|
|
|
211
211
|
# Send request + Wait for the response
|
|
212
212
|
try:
|
|
@@ -236,7 +236,7 @@ async def arequest(method:str, url:str, data:str=None, json=None, headers:dict=N
|
|
|
236
236
|
body = f"[WARN] arequest: {e}"
|
|
237
237
|
else:
|
|
238
238
|
body = f"[ERR] arequest: {e}"
|
|
239
|
-
|
|
239
|
+
syslog(body)
|
|
240
240
|
finally:
|
|
241
241
|
if writer:
|
|
242
242
|
writer.close()
|