micrOSDevToolKit 2.9.11__py3-none-any.whl → 2.10.5__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.
- micrOS/release_info/micrOS_ReleaseInfo/system_analysis_sum.json +37 -29
- micrOS/source/Common.py +5 -5
- micrOS/source/Espnow.py +245 -123
- micrOS/source/Files.py +101 -0
- micrOS/source/InterConnect.py +14 -11
- micrOS/source/LM_espnow.py +10 -7
- micrOS/source/LM_intercon.py +3 -0
- micrOS/source/LM_light_sensor.py +7 -15
- micrOS/source/LM_mqtt_pro.py +211 -0
- micrOS/source/LM_oled_ui.py +18 -22
- micrOS/source/LM_oledui.py +13 -16
- micrOS/source/LM_pacman.py +37 -57
- micrOS/source/LM_presence.py +8 -11
- micrOS/source/LM_system.py +8 -7
- micrOS/source/LM_telegram.py +21 -16
- micrOS/source/Logger.py +5 -11
- micrOS/source/Shell.py +37 -30
- micrOS/source/Tasks.py +32 -17
- micrOS/source/Web.py +3 -2
- micrOS/source/__pycache__/Common.cpython-312.pyc +0 -0
- micrOS/source/__pycache__/Logger.cpython-312.pyc +0 -0
- micrOS/source/microIO.py +3 -2
- micrOS/source/urequests.py +10 -1
- {micrOSDevToolKit-2.9.11.dist-info → microsdevtoolkit-2.10.5.dist-info}/METADATA +13 -15
- {micrOSDevToolKit-2.9.11.dist-info → microsdevtoolkit-2.10.5.dist-info}/RECORD +54 -50
- {micrOSDevToolKit-2.9.11.dist-info → microsdevtoolkit-2.10.5.dist-info}/WHEEL +1 -1
- toolkit/dashboard_apps/SystemTest.py +17 -6
- toolkit/lib/micrOSClient.py +25 -6
- toolkit/simulator_lib/__pycache__/uos.cpython-312.pyc +0 -0
- toolkit/simulator_lib/uos.py +5 -5
- toolkit/socketClient.py +2 -3
- toolkit/workspace/precompiled/Common.mpy +0 -0
- toolkit/workspace/precompiled/Espnow.mpy +0 -0
- toolkit/workspace/precompiled/Files.mpy +0 -0
- toolkit/workspace/precompiled/InterConnect.mpy +0 -0
- toolkit/workspace/precompiled/LM_espnow.py +10 -7
- toolkit/workspace/precompiled/LM_intercon.mpy +0 -0
- toolkit/workspace/precompiled/LM_light_sensor.mpy +0 -0
- toolkit/workspace/precompiled/LM_mqtt_pro.py +211 -0
- toolkit/workspace/precompiled/LM_oled_ui.mpy +0 -0
- toolkit/workspace/precompiled/LM_oledui.mpy +0 -0
- toolkit/workspace/precompiled/LM_pacman.mpy +0 -0
- toolkit/workspace/precompiled/LM_presence.mpy +0 -0
- toolkit/workspace/precompiled/LM_system.mpy +0 -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/Web.mpy +0 -0
- toolkit/workspace/precompiled/microIO.mpy +0 -0
- toolkit/workspace/precompiled/urequests.mpy +0 -0
- {micrOSDevToolKit-2.9.11.data → microsdevtoolkit-2.10.5.data}/scripts/devToolKit.py +0 -0
- {micrOSDevToolKit-2.9.11.dist-info → microsdevtoolkit-2.10.5.dist-info/licenses}/LICENSE +0 -0
- {micrOSDevToolKit-2.9.11.dist-info → microsdevtoolkit-2.10.5.dist-info}/top_level.txt +0 -0
micrOS/source/LM_oledui.py
CHANGED
|
@@ -4,13 +4,8 @@ from Types import resolve
|
|
|
4
4
|
# Core modules
|
|
5
5
|
from Config import cfgget
|
|
6
6
|
from Time import uptime
|
|
7
|
-
|
|
8
7
|
# Load Modules
|
|
9
|
-
from LM_system import top, memory_usage, ifconfig, rssi as sta_rssi, list_stations
|
|
10
|
-
try:
|
|
11
|
-
import LM_intercon as InterCon
|
|
12
|
-
except:
|
|
13
|
-
InterCon = None # Optional function handling
|
|
8
|
+
from LM_system import top, memory_usage, ifconfig, rssi as sta_rssi, list_stations, hosts
|
|
14
9
|
try:
|
|
15
10
|
from LM_esp32 import temp as cpu_temp
|
|
16
11
|
except Exception as e:
|
|
@@ -785,10 +780,13 @@ class PageUI:
|
|
|
785
780
|
# Check open host connection
|
|
786
781
|
try:
|
|
787
782
|
# Send CMD to other device & show result
|
|
788
|
-
data_meta =
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
783
|
+
state, data_meta = exec_cmd(cmd + [f">>{host}"], jsonify=True, skip_check=True)
|
|
784
|
+
if state:
|
|
785
|
+
self._cmd_task_tag = data_meta['tag']
|
|
786
|
+
if "Task is Busy" in data_meta['verdict'] and not run:
|
|
787
|
+
self.app_frame.press_output = data_meta['verdict'] # Otherwise the task start output not relevant on UI
|
|
788
|
+
else:
|
|
789
|
+
self.app_frame.press_output = f"Error: {data_meta}"
|
|
792
790
|
except Exception as e:
|
|
793
791
|
self.app_frame.press_output = str(e)
|
|
794
792
|
|
|
@@ -803,7 +801,7 @@ class PageUI:
|
|
|
803
801
|
self._cmd_task_tag = None
|
|
804
802
|
PageUI.write_lines(self.app_frame.press_output, display, x, y + 20, line_limit=2)
|
|
805
803
|
|
|
806
|
-
PageUI.write_lines(f"{host.split(".")[0]}:{cmd}", display, x, y, line_limit=2)
|
|
804
|
+
PageUI.write_lines(f"{host.split(".")[0]}:{' '.join(cmd)}", display, x, y, line_limit=2)
|
|
807
805
|
if run:
|
|
808
806
|
if self._cmd_task_tag is None:
|
|
809
807
|
_execute(display, w, h, x, y)
|
|
@@ -829,14 +827,13 @@ def _system_page(display, w, h, x, y):
|
|
|
829
827
|
return True
|
|
830
828
|
|
|
831
829
|
def _intercon_nodes_page(display, w, h, x, y):
|
|
832
|
-
if InterCon is None:
|
|
833
|
-
return False
|
|
834
830
|
line_limit = 3
|
|
835
831
|
line_start = y+5
|
|
836
832
|
line_cnt = 1
|
|
837
833
|
display.text("InterCon cache", x, line_start)
|
|
838
|
-
|
|
839
|
-
|
|
834
|
+
cache = hosts()["intercon"]
|
|
835
|
+
if sum([1 for _ in cache]) > 0:
|
|
836
|
+
for key, val in cache.items():
|
|
840
837
|
key = key.split('.')[0]
|
|
841
838
|
val = '.'.join(val.split('.')[-2:])
|
|
842
839
|
display.text(f" {val} {key}", x, line_start + (line_cnt * 10))
|
|
@@ -934,7 +931,7 @@ def intercon_genpage(cmd=None, run=False):
|
|
|
934
931
|
"""
|
|
935
932
|
raw = cmd.split()
|
|
936
933
|
host = raw[0]
|
|
937
|
-
cmd =
|
|
934
|
+
cmd = raw[1:]
|
|
938
935
|
try:
|
|
939
936
|
# Create page for intercon command
|
|
940
937
|
PageUI.INSTANCE.add_page(lambda display, w, h, x, y: PageUI.INSTANCE.intercon_exec_page(host, cmd, run, display, w, h, x, y))
|
micrOS/source/LM_pacman.py
CHANGED
|
@@ -1,73 +1,56 @@
|
|
|
1
|
-
from uos import listdir, remove, stat
|
|
2
1
|
from sys import modules
|
|
3
2
|
from Common import socket_stream
|
|
4
|
-
|
|
5
|
-
WEB_EXT = ('html', 'js', 'css')
|
|
6
|
-
DATA_TYPES = ('log', 'pds', 'dat')
|
|
7
|
-
|
|
8
|
-
def _is_app_resource(path='/'):
|
|
9
|
-
if stat(path)[0] & 0x4000: # Dir check
|
|
10
|
-
return True, 'd'
|
|
11
|
-
file_name = path.split("/")[-1]
|
|
12
|
-
if file_name.startswith('LM_') or file_name.split('.')[-1] in WEB_EXT + DATA_TYPES:
|
|
13
|
-
return True, 'f'
|
|
14
|
-
return False, '?'
|
|
3
|
+
from Files import _is_module, list_fs, ilist_fs, remove_fs
|
|
15
4
|
|
|
16
5
|
|
|
17
6
|
#############################################
|
|
18
7
|
# Safe file system handler functions #
|
|
19
8
|
#############################################
|
|
20
9
|
|
|
21
|
-
def ls(path="/", content='*', raw=False):
|
|
10
|
+
def ls(path="/", content='*', raw=False, select='*'):
|
|
22
11
|
"""
|
|
23
12
|
Linux like ls command - list app resources and app folders
|
|
24
13
|
:param path: path to list, default: /
|
|
25
14
|
:param content: content type, default all, f-file, d-dir can be selected
|
|
26
15
|
:param raw: keep raw output [(is_app, type), ...]
|
|
16
|
+
:param select: select specific app resource: LM or IO, default: all
|
|
27
17
|
"""
|
|
28
|
-
|
|
29
|
-
items = []
|
|
30
|
-
for item in listdir(path):
|
|
31
|
-
is_app, item_type = _is_app_resource(path + item)
|
|
32
|
-
if is_app and (content == "*" or item_type == content):
|
|
33
|
-
items.append((item_type, item))
|
|
18
|
+
items = list_fs(path, content, select=select)
|
|
34
19
|
if raw:
|
|
35
20
|
return items
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
spacer = " " * (4 - len(str(i)))
|
|
41
|
-
|
|
42
|
-
|
|
21
|
+
|
|
22
|
+
# Build a formatted output (just like `ls -l` style index)
|
|
23
|
+
lines = ""
|
|
24
|
+
for i, f in enumerate(items):
|
|
25
|
+
spacer = " " * (4 - len(str(i+1)))
|
|
26
|
+
if content == "*":
|
|
27
|
+
lines += f"{i+1}{spacer}{f[0]} {f[1]}\n"
|
|
28
|
+
else:
|
|
29
|
+
lines += f"{i + 1}{spacer}{f}\n"
|
|
30
|
+
return lines
|
|
43
31
|
|
|
44
32
|
|
|
45
|
-
def rm(path):
|
|
33
|
+
def rm(path, allow_dir=False):
|
|
46
34
|
"""
|
|
47
35
|
Linux like rm command - delete app resources and folders
|
|
48
36
|
:param path: app resource name/path, ex.: LM_robustness.py
|
|
37
|
+
:param allow_dir: enable directory deletion, default: False
|
|
49
38
|
"""
|
|
50
|
-
|
|
51
|
-
return f'Load module {path} is protected, skip delete.'
|
|
52
|
-
is_app, item_type = _is_app_resource(path)
|
|
53
|
-
if is_app:
|
|
54
|
-
remove(path)
|
|
55
|
-
return f"Remove: {path} {'dir' if item_type == 'd' else 'file'}"
|
|
56
|
-
return f"Invalid path {path}"
|
|
39
|
+
return remove_fs(path, allow_dir)
|
|
57
40
|
|
|
58
41
|
|
|
59
42
|
def dirtree(path="/", raw=False):
|
|
60
43
|
"""Return only directories from a given path."""
|
|
61
44
|
path = path if path.endswith('/') else f"{path}/"
|
|
62
|
-
folders = [f"{path}/{item}" for item in
|
|
63
|
-
folder_contents = {folder:
|
|
45
|
+
folders = [f"{path}/{item}" for item in ilist_fs(path, type_filter='d')]
|
|
46
|
+
folder_contents = {folder:list_fs(folder) for folder in folders}
|
|
64
47
|
if raw:
|
|
65
48
|
return folder_contents
|
|
66
49
|
formatted_output = ""
|
|
67
50
|
for k, v in folder_contents.items():
|
|
68
51
|
formatted_output += f"{k}\n"
|
|
69
52
|
for val in v:
|
|
70
|
-
formatted_output += f"\t{val}\n"
|
|
53
|
+
formatted_output += f"\t{val[0]} {val[1]}\n"
|
|
71
54
|
return formatted_output
|
|
72
55
|
|
|
73
56
|
|
|
@@ -108,18 +91,20 @@ def del_duplicates():
|
|
|
108
91
|
- delete duplicated .mpy and .py resources, keep .mpy resource!
|
|
109
92
|
"""
|
|
110
93
|
msg_buf = []
|
|
111
|
-
|
|
112
|
-
|
|
94
|
+
files = list_fs(type_filter='f', select='LM')
|
|
95
|
+
py = list((res.split('.')[0] for res in files if res.endswith('.py'))) # Normally smaller list
|
|
96
|
+
mpy = (res.split('.')[0] for res in files if res.endswith('.mpy'))
|
|
113
97
|
for m in mpy:
|
|
114
98
|
# Iterate over mpy resources
|
|
115
99
|
state = True
|
|
116
100
|
if m in py and m != 'main':
|
|
117
101
|
to_delete = f'{m}.py'
|
|
118
102
|
try:
|
|
119
|
-
|
|
103
|
+
verdict = remove_fs(to_delete)
|
|
120
104
|
except:
|
|
105
|
+
verdict = "n/a"
|
|
121
106
|
state = False
|
|
122
|
-
msg_buf.append(f' Delete {to_delete} {state}')
|
|
107
|
+
msg_buf.append(f' Delete {to_delete} {state} - {verdict}')
|
|
123
108
|
return '\n'.join(msg_buf) if len(msg_buf) > 0 else 'Nothing to delete.'
|
|
124
109
|
|
|
125
110
|
|
|
@@ -147,7 +132,7 @@ def cachedump(delpds=None, msgobj=None):
|
|
|
147
132
|
if delpds is None:
|
|
148
133
|
# List pds files aka application cache
|
|
149
134
|
msg_buf = []
|
|
150
|
-
for pds in (_pds for _pds in
|
|
135
|
+
for pds in (_pds for _pds in ilist_fs(type_filter='f') if _pds.endswith('.pds')):
|
|
151
136
|
with open(pds, 'r') as f:
|
|
152
137
|
if msgobj is None:
|
|
153
138
|
msg_buf.append(f'{pds}: {f.read()}')
|
|
@@ -156,8 +141,8 @@ def cachedump(delpds=None, msgobj=None):
|
|
|
156
141
|
return msg_buf if len(msg_buf) > 0 else ''
|
|
157
142
|
# Remove given pds file
|
|
158
143
|
try:
|
|
159
|
-
|
|
160
|
-
return f'{delpds}.pds delete done
|
|
144
|
+
verdict = remove_fs(f'{delpds}.pds')
|
|
145
|
+
return f'{delpds}.pds delete done.: {verdict}'
|
|
161
146
|
except:
|
|
162
147
|
return f'{delpds}.pds not exists'
|
|
163
148
|
|
|
@@ -168,7 +153,7 @@ def dat_dump():
|
|
|
168
153
|
- logged data from LMs, sensor datat, etc...
|
|
169
154
|
"""
|
|
170
155
|
logs_dir = "/logs/"
|
|
171
|
-
dats = (f for f in
|
|
156
|
+
dats = (f for f in ilist_fs(type_filter='f') if f.endswith('.dat'))
|
|
172
157
|
out = {}
|
|
173
158
|
for dat in dats:
|
|
174
159
|
with open(f"{logs_dir}{dat}", 'r') as f:
|
|
@@ -188,8 +173,7 @@ def listmods(msgobj=None):
|
|
|
188
173
|
"""
|
|
189
174
|
# Dump available LMs
|
|
190
175
|
msg_buf = []
|
|
191
|
-
for k in (res.replace('LM_', '') for res in
|
|
192
|
-
if res.startswith('LM_') or res.split('.')[-1] in WEB_EXT):
|
|
176
|
+
for k in (res.replace('LM_', '') for res in ilist_fs(type_filter='f', select='LM')):
|
|
193
177
|
if msgobj is None:
|
|
194
178
|
msg_buf.append(f' {k}')
|
|
195
179
|
else:
|
|
@@ -197,21 +181,17 @@ def listmods(msgobj=None):
|
|
|
197
181
|
return msg_buf if len(msg_buf) > 0 else ''
|
|
198
182
|
|
|
199
183
|
|
|
200
|
-
def delmod(mod
|
|
184
|
+
def delmod(mod):
|
|
201
185
|
"""
|
|
202
186
|
Module package manager
|
|
203
187
|
:param mod:
|
|
204
188
|
Delete Load Module with full name: module.py or module.mpy
|
|
205
189
|
OR delete any web resource: *.js, *.css, *.html
|
|
206
190
|
"""
|
|
207
|
-
if mod
|
|
208
|
-
# LM exception list - system and pacman cannot be deleted
|
|
209
|
-
if 'pacman.' in mod or 'system.' in mod:
|
|
210
|
-
return f'Load module {mod} is in use, skip delete.'
|
|
191
|
+
if mod.endswith('py') or _is_module(mod):
|
|
211
192
|
try:
|
|
212
|
-
to_remove = mod if mod.
|
|
213
|
-
|
|
214
|
-
return f'Delete module: {mod}'
|
|
193
|
+
to_remove = f'LM_{mod}' if mod.endswith('py') else mod
|
|
194
|
+
return remove_fs(to_remove)
|
|
215
195
|
except Exception as e:
|
|
216
196
|
return f'Cannot delete: {mod}: {e}'
|
|
217
197
|
return f'Invalid value: {mod}'
|
|
@@ -223,7 +203,7 @@ def micros_checksum(msgobj=None):
|
|
|
223
203
|
from binascii import hexlify
|
|
224
204
|
from Config import cfgget
|
|
225
205
|
|
|
226
|
-
for f_name in (
|
|
206
|
+
for f_name in ilist_fs(type_filter='f', select='LM'):
|
|
227
207
|
with open(f_name, 'rb') as f:
|
|
228
208
|
cs = hexlify(sha1(f.read()).digest()).decode('utf-8')
|
|
229
209
|
msgobj(f"{cs} {f_name}")
|
|
@@ -244,5 +224,5 @@ def help(widgets=False):
|
|
|
244
224
|
'dat_dump',
|
|
245
225
|
'download url="BxNxM/micrOS/master/toolkit/workspace/precompiled/LM_robustness.py"',
|
|
246
226
|
'micros_checksum',
|
|
247
|
-
'ls path="/" content="*/f/d"',
|
|
227
|
+
'ls path="/" content="*/f/d" select="*/LM/IO"',
|
|
248
228
|
'rm <path>', 'dirtree path="/"')
|
micrOS/source/LM_presence.py
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
from microIO import bind_pin, pinmap_search
|
|
2
|
-
from Common import SmartADC, micro_task, notify, syslog
|
|
2
|
+
from Common import SmartADC, micro_task, notify, syslog, exec_cmd
|
|
3
3
|
from utime import ticks_ms
|
|
4
|
-
|
|
5
|
-
import LM_intercon as InterCon
|
|
6
|
-
except:
|
|
7
|
-
InterCon = None
|
|
4
|
+
|
|
8
5
|
|
|
9
6
|
class Data:
|
|
10
7
|
TASK_TAG = 'presence._capture'
|
|
@@ -68,9 +65,9 @@ def __run_intercon(state):
|
|
|
68
65
|
try:
|
|
69
66
|
cmd = Data.ON_INTERCON_CLBK.split()
|
|
70
67
|
host = cmd[0]
|
|
71
|
-
cmd =
|
|
72
|
-
# Send CMD to other device
|
|
73
|
-
|
|
68
|
+
cmd = cmd[1:]
|
|
69
|
+
# Send CMD to other device
|
|
70
|
+
state, _ = exec_cmd(cmd + [f">>{host}"], jsonify=True, skip_check=True)
|
|
74
71
|
except Exception as e:
|
|
75
72
|
syslog(f"__run_intercon error: {e}")
|
|
76
73
|
if state.lower() == "off":
|
|
@@ -79,9 +76,9 @@ def __run_intercon(state):
|
|
|
79
76
|
try:
|
|
80
77
|
cmd = Data.OFF_INTERCON_CLBK.split()
|
|
81
78
|
host = cmd[0]
|
|
82
|
-
cmd =
|
|
83
|
-
# Send CMD to other device
|
|
84
|
-
|
|
79
|
+
cmd = cmd[1:]
|
|
80
|
+
# Send CMD to other device
|
|
81
|
+
state, _ = exec_cmd(cmd + [f">>{host}"], jsonify=True, skip_check=True)
|
|
85
82
|
except Exception as e:
|
|
86
83
|
syslog(f"__run_intercon error: {e}")
|
|
87
84
|
|
micrOS/source/LM_system.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from uos import statvfs, getcwd,
|
|
1
|
+
from uos import statvfs, getcwd, uname
|
|
2
2
|
from utime import localtime
|
|
3
3
|
from network import WLAN, STA_IF, AP_IF
|
|
4
4
|
from binascii import hexlify
|
|
@@ -212,14 +212,15 @@ def ifconfig():
|
|
|
212
212
|
return network_config()
|
|
213
213
|
|
|
214
214
|
|
|
215
|
-
def
|
|
215
|
+
def hosts():
|
|
216
216
|
"""
|
|
217
|
-
|
|
218
|
-
-
|
|
219
|
-
-
|
|
217
|
+
Dump cached hosts
|
|
218
|
+
- urequests (only memory cache)
|
|
219
|
+
- intercon connection cache
|
|
220
220
|
"""
|
|
221
221
|
from urequests import host_cache
|
|
222
|
-
|
|
222
|
+
from InterConnect import host_cache as ihost_cache
|
|
223
|
+
return {"urequests": host_cache(), "intercon": ihost_cache()}
|
|
223
224
|
|
|
224
225
|
|
|
225
226
|
def notifications(enable=None):
|
|
@@ -246,4 +247,4 @@ def help(widgets=False):
|
|
|
246
247
|
'ntp', 'rssi', 'list_stations', 'pinmap key="dhtpin"/None', 'alarms clean=False',
|
|
247
248
|
'notifications enable=<None,True,False>',
|
|
248
249
|
'sun refresh=False', 'ifconfig', 'memory_usage',
|
|
249
|
-
'disk_usage', '
|
|
250
|
+
'disk_usage', 'hosts'), widgets=widgets)
|
micrOS/source/LM_telegram.py
CHANGED
|
@@ -4,6 +4,11 @@ from Notify import Notify
|
|
|
4
4
|
from Config import cfgget
|
|
5
5
|
from Common import micro_task, syslog, console_write
|
|
6
6
|
from LM_system import ifconfig
|
|
7
|
+
from utime import localtime
|
|
8
|
+
|
|
9
|
+
def _timestamp():
|
|
10
|
+
_time = [str(k) for k in localtime()[3:6]]
|
|
11
|
+
return ':'.join(_time)
|
|
7
12
|
|
|
8
13
|
|
|
9
14
|
class Telegram(Notify):
|
|
@@ -106,12 +111,12 @@ class Telegram(Notify):
|
|
|
106
111
|
Update known chat_id-s and cache them
|
|
107
112
|
- return active chat_id frm resp_json
|
|
108
113
|
"""
|
|
109
|
-
console_write("[NTFY GET] update chatIDs")
|
|
110
114
|
_cid = None
|
|
111
115
|
if resp_json.get("ok", None) and len(resp_json["result"]) > 0:
|
|
112
116
|
_cid = resp_json["result"][-1]["message"]["chat"]["id"]
|
|
113
117
|
# LIMIT Telegram._CHAT_IDS NOTIFICATION CACHE TO 3 IDs
|
|
114
|
-
if len(Telegram._CHAT_IDS) < 4:
|
|
118
|
+
if len(Telegram._CHAT_IDS) < 4 and _cid not in Telegram._CHAT_IDS:
|
|
119
|
+
console_write("[NTFY GET] update chatIDs")
|
|
115
120
|
_ids = len(Telegram._CHAT_IDS)
|
|
116
121
|
Telegram._CHAT_IDS.add(_cid)
|
|
117
122
|
if len(Telegram._CHAT_IDS) - _ids > 0: # optimized save (slow storage access)
|
|
@@ -135,7 +140,7 @@ class Telegram(Notify):
|
|
|
135
140
|
return None
|
|
136
141
|
response = {'sender': None, 'text': None, 'm_id': -1, 'c_id': None}
|
|
137
142
|
url = f"https://api.telegram.org/bot{bot_token}/getUpdates{Telegram._API_PARAMS}"
|
|
138
|
-
console_write(f"\
|
|
143
|
+
console_write(f"\t[GET] request: {url}")
|
|
139
144
|
|
|
140
145
|
_, resp_json = urequests.get(url, jsonify=True, sock_size=128)
|
|
141
146
|
|
|
@@ -145,7 +150,7 @@ class Telegram(Notify):
|
|
|
145
150
|
response['sender'] = f"{resp['chat']['first_name']}{resp['chat']['last_name']}" if resp['chat'].get(
|
|
146
151
|
'username', None) is None else resp['chat']['username']
|
|
147
152
|
response['text'], response['m_id'] = resp['text'], resp['message_id']
|
|
148
|
-
console_write(f"\
|
|
153
|
+
console_write(f"\t\t[GET] response: {response}")
|
|
149
154
|
return response
|
|
150
155
|
|
|
151
156
|
@staticmethod
|
|
@@ -160,7 +165,7 @@ class Telegram(Notify):
|
|
|
160
165
|
return None
|
|
161
166
|
response = {'sender': None, 'text': None, 'm_id': -1, 'c_id': None}
|
|
162
167
|
url = f"https://api.telegram.org/bot{bot_token}/getUpdates{Telegram._API_PARAMS}"
|
|
163
|
-
console_write(f"\
|
|
168
|
+
console_write(f"\t[aGET] request: {url}")
|
|
164
169
|
|
|
165
170
|
_, resp_json = await urequests.aget(url, jsonify=True, sock_size=128)
|
|
166
171
|
|
|
@@ -170,7 +175,7 @@ class Telegram(Notify):
|
|
|
170
175
|
response['sender'] = f"{resp['chat']['first_name']}{resp['chat']['last_name']}" if resp['chat'].get(
|
|
171
176
|
'username', None) is None else resp['chat']['username']
|
|
172
177
|
response['text'], response['m_id'] = resp['text'], resp['message_id']
|
|
173
|
-
console_write(f"\
|
|
178
|
+
console_write(f"\t\t[aGET] response: {response}")
|
|
174
179
|
return response
|
|
175
180
|
|
|
176
181
|
@staticmethod
|
|
@@ -183,14 +188,14 @@ class Telegram(Notify):
|
|
|
183
188
|
console_write("[NTFY] EVAL sequence")
|
|
184
189
|
verdict = None
|
|
185
190
|
|
|
186
|
-
def
|
|
191
|
+
def _lm_execute(cmd_args):
|
|
187
192
|
nonlocal verdict, m_id
|
|
188
193
|
access, output = Telegram.lm_execute(cmd_args)
|
|
189
194
|
if access:
|
|
190
|
-
verdict = f'[UP] Exec: {" ".join(cmd_args[0])}'
|
|
195
|
+
verdict = f'{_timestamp()} [UP] Exec: {" ".join(cmd_args[0])}'
|
|
191
196
|
Telegram.send_msg(output, reply_to=m_id)
|
|
192
197
|
else:
|
|
193
|
-
verdict = f'[UP] NoAccess: {cmd_args[0]}'
|
|
198
|
+
verdict = f'{_timestamp()} [UP] NoAccess: {cmd_args[0]}'
|
|
194
199
|
Telegram._IN_MSG_ID = m_id
|
|
195
200
|
|
|
196
201
|
# -------------------------- FUNCTION MAIN -------------------------- #
|
|
@@ -211,12 +216,12 @@ class Telegram(Notify):
|
|
|
211
216
|
cmd_lm = msg_in.strip().split()[1:]
|
|
212
217
|
# [Compare] cmd selected device param with DEVFID (device/prompt name)
|
|
213
218
|
if cmd_lm[0] in Telegram._DEVFID:
|
|
214
|
-
|
|
219
|
+
_lm_execute(cmd_lm[1:])
|
|
215
220
|
else:
|
|
216
|
-
verdict = f'[UP] NoSelected: {cmd_lm[0]}'
|
|
221
|
+
verdict = f'{_timestamp()} [UP] NoSelected: {cmd_lm[0]}'
|
|
217
222
|
elif msg_in.startswith('/cmd'):
|
|
218
223
|
cmd_lm = msg_in.strip().split()[1:]
|
|
219
|
-
|
|
224
|
+
_lm_execute(cmd_lm)
|
|
220
225
|
elif msg_in.startswith('/notify'):
|
|
221
226
|
param = msg_in.strip().split()[1:]
|
|
222
227
|
if len(param) > 0:
|
|
@@ -226,8 +231,7 @@ class Telegram(Notify):
|
|
|
226
231
|
# Send is still synchronous (OK)
|
|
227
232
|
Telegram.send_msg(verdict, reply_to=m_id)
|
|
228
233
|
else:
|
|
229
|
-
verdict = "[UP] NoExec"
|
|
230
|
-
console_write(f"\tBOT: {verdict}")
|
|
234
|
+
verdict = f"{_timestamp()} [UP] NoExec"
|
|
231
235
|
return verdict
|
|
232
236
|
|
|
233
237
|
@staticmethod
|
|
@@ -241,11 +245,12 @@ class Telegram(Notify):
|
|
|
241
245
|
period = period if period > 0 else 1
|
|
242
246
|
period_ms = period * 1000
|
|
243
247
|
with micro_task(tag=tag) as my_task:
|
|
244
|
-
my_task.out = "[UP] Running"
|
|
248
|
+
my_task.out = f"{_timestamp()} [UP] Running"
|
|
245
249
|
while True:
|
|
246
250
|
# Normal task period
|
|
247
251
|
await my_task.feed(sleep_ms=period_ms)
|
|
248
252
|
try:
|
|
253
|
+
# await asyncio.wait_for(Telegram.receive_eval(), 5) # 5 sec timeout???
|
|
249
254
|
v = await Telegram.receive_eval()
|
|
250
255
|
my_task.out = "Missing bot token" if v is None else f"{v} ({period}s)"
|
|
251
256
|
cancel_cnt = 0
|
|
@@ -254,7 +259,7 @@ class Telegram(Notify):
|
|
|
254
259
|
# Auto scale - blocking nature - in case of serial failures (5) - hibernate task (increase async sleep)
|
|
255
260
|
cancel_cnt += 1
|
|
256
261
|
if cancel_cnt > 5:
|
|
257
|
-
my_task.out = f"[DOWN] {e} (wait 1min)"
|
|
262
|
+
my_task.out = f"{_timestamp()} [DOWN] {e} (wait 1min)"
|
|
258
263
|
cancel_cnt = 5
|
|
259
264
|
# SLOW DOWN - hibernate task
|
|
260
265
|
await my_task.feed(sleep_ms=60_000)
|
micrOS/source/Logger.py
CHANGED
|
@@ -6,7 +6,8 @@ Designed by Marcell Ban aka BxNxM
|
|
|
6
6
|
"""
|
|
7
7
|
from time import localtime
|
|
8
8
|
from re import match
|
|
9
|
-
from uos import
|
|
9
|
+
from uos import remove, mkdir, getcwd
|
|
10
|
+
from Files import ilist_fs, is_dir
|
|
10
11
|
|
|
11
12
|
#############################################
|
|
12
13
|
# LOGGING WITH DATA ROTATION #
|
|
@@ -18,14 +19,7 @@ def _init_logger():
|
|
|
18
19
|
global LOG_FOLDER
|
|
19
20
|
if LOG_FOLDER is None:
|
|
20
21
|
LOG_FOLDER = f"{getcwd()}logs"
|
|
21
|
-
|
|
22
|
-
try:
|
|
23
|
-
if stat(LOG_FOLDER)[0] & 0x4000:
|
|
24
|
-
# Dir exists - skip create
|
|
25
|
-
do_create = False
|
|
26
|
-
except:
|
|
27
|
-
pass
|
|
28
|
-
if do_create:
|
|
22
|
+
if not is_dir(LOG_FOLDER):
|
|
29
23
|
try:
|
|
30
24
|
mkdir(LOG_FOLDER)
|
|
31
25
|
syslog(f"[BOOT] log dir {LOG_FOLDER} init")
|
|
@@ -107,7 +101,7 @@ def log_get(f_name, msgobj=None):
|
|
|
107
101
|
|
|
108
102
|
def syslog(data=None, msgobj=None):
|
|
109
103
|
if data is None:
|
|
110
|
-
err_cnt = sum([log_get(f, msgobj) for f in
|
|
104
|
+
err_cnt = sum([log_get(f, msgobj) for f in ilist_fs(LOG_FOLDER, type_filter='f') if f.endswith(".sys.log")])
|
|
111
105
|
return err_cnt
|
|
112
106
|
|
|
113
107
|
_match = match(r"^\[([^\[\]]+)\]", data)
|
|
@@ -117,7 +111,7 @@ def syslog(data=None, msgobj=None):
|
|
|
117
111
|
|
|
118
112
|
|
|
119
113
|
def log_clean(msgobj=None):
|
|
120
|
-
to_del = [file for file in
|
|
114
|
+
to_del = [file for file in ilist_fs(LOG_FOLDER, type_filter='f') if file.endswith('.log')]
|
|
121
115
|
for _del in to_del:
|
|
122
116
|
_del = f"{LOG_FOLDER}/{_del}"
|
|
123
117
|
if msgobj is not None:
|