micrOSDevToolKit 2.9.1__py3-none-any.whl → 2.9.4__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.

@@ -13,7 +13,7 @@
13
13
  1
14
14
  ],
15
15
  "Server.py": [
16
- 9.52,
16
+ 9.5,
17
17
  3
18
18
  ],
19
19
  "Web.py": [
@@ -45,7 +45,7 @@
45
45
  29
46
46
  ],
47
47
  "Logger.py": [
48
- 8.78,
48
+ 8.75,
49
49
  4
50
50
  ],
51
51
  "Common.py": [
@@ -315,7 +315,7 @@
315
315
  },
316
316
  "summary": {
317
317
  "core": [
318
- 3276,
318
+ 3274,
319
319
  23
320
320
  ],
321
321
  "load": [
@@ -332,6 +332,6 @@
332
332
  ],
333
333
  "core_score": 9.06,
334
334
  "load_score": 8.22,
335
- "version": "2.9.1-0"
335
+ "version": "2.9.4-0"
336
336
  }
337
337
  }
micrOS/source/Common.py CHANGED
@@ -210,7 +210,7 @@ def data_logger(f_name, data=None, limit=12, msgobj=None):
210
210
 
211
211
  def syslog(msg):
212
212
  """ Wrapper of errlog_add """
213
- return errlog_add(f"[U] {msg}")
213
+ return errlog_add(f"{msg}")
214
214
 
215
215
 
216
216
  def console(msg):
micrOS/source/Logger.py CHANGED
@@ -6,6 +6,7 @@ Designed by Marcell Ban aka BxNxM
6
6
  """
7
7
  from time import localtime
8
8
  from os import listdir, remove
9
+ from re import match
9
10
 
10
11
  #############################################
11
12
  # LOGGING WITH DATA ROTATION #
@@ -66,6 +67,8 @@ def log_get(f_name, msgobj=None):
66
67
  """
67
68
  err_cnt = 0
68
69
  try:
70
+ if msgobj is not None:
71
+ msgobj(f_name)
69
72
  with open(f_name, 'r') as f:
70
73
  eline = f.readline().strip()
71
74
  while eline:
@@ -73,7 +76,7 @@ def log_get(f_name, msgobj=None):
73
76
  err_cnt += 1 if "[ERR]" in eline else 0
74
77
  # GIVE BACK .log file contents
75
78
  if msgobj is not None:
76
- msgobj(eline)
79
+ msgobj(f"\t{eline}")
77
80
  eline = f.readline().strip()
78
81
  except:
79
82
  pass
@@ -82,8 +85,13 @@ def log_get(f_name, msgobj=None):
82
85
 
83
86
  def syslog(data=None, msgobj=None):
84
87
  if data is None:
85
- return log_get('err.log', msgobj)
86
- return logger(data, 'err.log', limit=6)
88
+ err_cnt = sum([log_get(f, msgobj) for f in listdir() if f.endswith(".sys.log")])
89
+ return err_cnt
90
+
91
+ _match = match(r"^\[([^\[\]]+)\]", data)
92
+ log_lvl = _match.group(1).lower() if _match else 'user'
93
+ f_name = f"{log_lvl}.sys.log" if log_lvl in ("err", "warn", "boot") else 'user.sys.log'
94
+ return logger(data, f_name, limit=4)
87
95
 
88
96
 
89
97
  def log_clean(msgobj=None):
micrOS/source/Server.py CHANGED
@@ -114,7 +114,7 @@ class Client:
114
114
  console_write("[Client] NoCon: response>dev/nul")
115
115
 
116
116
  def send(self, response):
117
- # Implement in child class - synchronous send method
117
+ # Implement in child class - synchronous send (all) method
118
118
  pass
119
119
 
120
120
  async def close(self):
@@ -196,7 +196,9 @@ class ShellCli(Client, Shell):
196
196
 
197
197
  def send(self, response):
198
198
  """
199
- Send response to client with non-async function
199
+ Synchronous send function (with drain task)
200
+ - not used in Shell or ShellCli
201
+ - Note: it is a support function for synchronous scenarios: Server.reply_all
200
202
  """
201
203
  if self.connected:
202
204
  if self.prompt() != response:
@@ -219,8 +221,7 @@ class ShellCli(Client, Shell):
219
221
 
220
222
  async def __wait_for_drain(self):
221
223
  """
222
- Handle drain serialization
223
- - solve output data duplicate
224
+ Handle drain serialization - for synchronous send function
224
225
  """
225
226
  try:
226
227
  # send write buffer
@@ -233,55 +234,45 @@ class ShellCli(Client, Shell):
233
234
  # set drain free
234
235
  self.drain_event.set() # set drain free (True)
235
236
 
236
- async def close(self):
237
- Client.console(f"[ShellCli] Close connection {self.client_id}")
238
- self.send("Bye!\n")
239
- # Reset shell state machine
240
- self.reset()
241
- await asyncio.sleep_ms(50)
242
- # Used from Client parent class
243
- await super().close()
244
-
245
- async def __shell_cmd(self, request):
237
+ async def a_send(self, response, encode='utf8'):
246
238
  """
247
- Handle micrOS shell commands
239
+ Async send for Shell (new line + prompt$)
248
240
  """
249
- # Run micrOS shell with request string
250
- try:
251
- # Handle micrOS shell
252
- Client.console("[ShellCli] --- #Run shell")
253
- state = self.shell(request)
254
- if state:
255
- return False # exit_loop
256
- return True # exit_loop : Close session when shell returns False (auth Failed, etc.)
257
- except Exception as e:
258
- Client.console(f"[ShellCli] Shell exception: {e}")
259
- if "ECONNRESET" in str(e):
260
- return True # exit_loop
261
- self.send("[HA] Critical error - disconnect & hard reset")
262
- errlog_add("[ERR] Socket critical error - reboot")
263
- self.reboot()
241
+ if self.prompt() != response:
242
+ # [format] Add new line if not prompt
243
+ response = f"{response}\n"
244
+ await super().a_send(response, encode)
264
245
 
265
246
  async def run_shell(self):
266
247
  # Update server task output
267
248
  Manager().server_task_msg(','.join(list(Client.ACTIVE_CLIS)))
268
249
  # Init prompt
269
- self.send(self.prompt())
250
+ await self.a_send(self.prompt())
270
251
  # Run async connection handling
252
+ _exit = False
271
253
  while self.connected:
272
254
  try:
273
255
  # Read request msg from client
274
256
  state, request = await self.read()
275
257
  if state:
276
258
  break
277
- _exit = await self.__shell_cmd(request)
278
- if _exit:
279
- collect()
280
- break
259
+ # Run micrOS shell with request string
260
+ Client.console("[ShellCli] --- #Run shell")
261
+ # Shell -> True (OK) or False (NOK) -> NOK->Close session (auth Failed, etc.)
262
+ _exit = not await self.shell(request)
281
263
  except Exception as e:
282
- errlog_add(f"[ERR] handle_client: {e}")
264
+ errlog_add(f"[ERR] Shell client: {e}")
265
+ if "ECONNRESET" in str(e):
266
+ _exit = True # exit_loop
267
+ else:
268
+ await self.a_send("[HA] Critical error - disconnect & hard reset")
269
+ errlog_add("[ERR] Socket critical error - reboot")
270
+ await self.reboot()
271
+ if _exit:
272
+ collect()
283
273
  break
284
274
  # Close connection
275
+ await self.a_send("Bye!")
285
276
  await self.close()
286
277
 
287
278
 
@@ -418,7 +409,7 @@ class Server:
418
409
  """
419
410
  for _, cli in Client.ACTIVE_CLIS.items():
420
411
  if cli.connected:
421
- cli.send(msg)
412
+ cli.send(f"~~~ {msg}")
422
413
 
423
414
  def __del__(self):
424
415
  Client.console("[ socket server ] <<destructor>>")
micrOS/source/Shell.py CHANGED
@@ -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.9.1-0'
28
+ MICROS_VERSION = '2.9.4-0'
29
29
 
30
30
  def __init__(self):
31
31
  """
@@ -45,10 +45,8 @@ class Shell:
45
45
  except Exception as e:
46
46
  errlog_add(f"[ERR] micrOS version export failed (config): {e}")
47
47
 
48
- def send(self, msg):
49
- """
50
- Must be defined by child class...
51
- """
48
+ async def a_send(self, msg):
49
+ """ Must be defined by parent class... """
52
50
  pass
53
51
 
54
52
  def reset(self):
@@ -56,44 +54,43 @@ class Shell:
56
54
  self.__auth_ok = False
57
55
  self.__conf_mode = False
58
56
 
59
- def reboot(self, hard=False):
60
- """Reboot micropython VM"""
61
- self.send(f"{'[HARD] ' if hard else ''}Reboot micrOS system.")
62
- self.send("Bye!")
57
+ async def reboot(self, hard=False):
58
+ """ Reboot micropython VM """
59
+ await self.a_send(f"{'[HARD] ' if hard else ''}Reboot micrOS system.\nBye!")
63
60
  if hard:
64
61
  hard_reset()
65
62
  soft_reset()
66
63
 
67
64
  def prompt(self):
68
- """Generate prompt"""
65
+ """ Generate prompt """
69
66
  auth = "[password] " if self.__auth_mode and not self.__auth_ok else ""
70
67
  mode = "[configure] " if self.__conf_mode else ""
71
68
  return f"{auth}{mode}{self.__devfid} $ "
72
69
 
73
- def __auth(self, msg_list):
74
- """Authorize user"""
70
+ async def __auth(self, msg_list):
71
+ """ Authorize user """
75
72
  # Set user auth state
76
73
  if self.__auth_mode and not self.__auth_ok:
77
74
  # check password
78
75
  usrpwd = cfgget('appwd')
79
76
  if usrpwd == msg_list[0].strip():
80
77
  self.__auth_ok = True
81
- self.send("AuthOk")
78
+ await self.a_send("AuthOk")
82
79
  return True, []
83
- self.send("AuthFailed\nBye!")
80
+ await self.a_send("AuthFailed\nBye!")
84
81
  return False, []
85
82
  return True, msg_list
86
83
 
87
- def shell(self, msg):
84
+ async def shell(self, msg):
88
85
  """
89
86
  micrOS Shell main - input string handling
90
87
  :param msg: incoming shell command (command or load module call)
91
88
  """
92
- state = self.__shell(msg)
93
- self.send(self.prompt())
89
+ state = await self.__shell(msg)
90
+ await self.a_send(self.prompt())
94
91
  return state
95
92
 
96
- def __shell(self, msg):
93
+ async def __shell(self, msg):
97
94
  """
98
95
  Socket server - interpreter shell
99
96
  :param msg: socket input string
@@ -118,11 +115,11 @@ class Shell:
118
115
  # Hello message
119
116
  if msg_list[0] == 'hello':
120
117
  # For low level device identification - hello msg
121
- self.send(f"hello:{self.__devfid}:{self.__hwuid}")
118
+ await self.a_send(f"hello:{self.__devfid}:{self.__hwuid}")
122
119
  return True
123
120
 
124
121
  # [!] AUTH
125
- state, msg_list = self.__auth(msg_list)
122
+ state, msg_list = await self.__auth(msg_list)
126
123
  if not state:
127
124
  return False
128
125
  if len(msg_list) == 0:
@@ -131,7 +128,7 @@ class Shell:
131
128
  # Version handling
132
129
  if msg_list[0] == 'version':
133
130
  # For micrOS system version info
134
- self.send(str(Shell.MICROS_VERSION))
131
+ await self.a_send(str(Shell.MICROS_VERSION))
135
132
  return True
136
133
 
137
134
  # Reboot micropython VM
@@ -140,12 +137,12 @@ class Shell:
140
137
  if len(msg_list) >= 2 and "-h" in msg_list[1]:
141
138
  # reboot / reboot -h
142
139
  hard = True
143
- self.reboot(hard)
140
+ await self.reboot(hard)
144
141
 
145
142
  if msg_list[0].startswith('webrepl'):
146
143
  if len(msg_list) == 2 and '-u' in msg_list[1]:
147
- Shell.webrepl(msg_obj=self.send, update=True)
148
- Shell.webrepl(msg_obj=self.send)
144
+ await Shell.webrepl(msg_obj=self.a_send, update=True)
145
+ return await Shell.webrepl(msg_obj=self.a_send)
149
146
 
150
147
  # CONFIGURE MODE STATE: ACCESS FOR NODE_CONFIG.JSON
151
148
  if msg_list[0].startswith('conf'):
@@ -157,34 +154,34 @@ class Shell:
157
154
 
158
155
  # HELP MSG
159
156
  if msg_list[0] == "help":
160
- self.send("[MICROS] - built-in shell commands")
161
- self.send(" hello - hello msg - for device identification")
162
- self.send(" modules - show active Load Modules")
163
- self.send(" version - returns micrOS version")
164
- self.send(" exit - exit from shell socket prompt")
165
- self.send(" reboot - system soft reboot (vm), hard reboot (hw): reboot -h")
166
- self.send(" webrepl - start webrepl, for file transfers use with --update")
167
- self.send("[CONF] Configure mode - built-in shell commands")
168
- self.send(" conf - Enter conf mode")
169
- self.send(" dump - Dump all data")
170
- self.send(" key - Get value")
171
- self.send(" key value - Set value")
172
- self.send(" noconf - Exit conf mode")
173
- self.send("[TASK] postfix: &x - one-time, &&x - periodic, x: wait ms [x min: 20ms]")
174
- self.send(" task list - list tasks with <tag>s")
175
- self.send(" task kill <tag> - stop task")
176
- self.send(" task show <tag> - show task output")
177
- self.send("[EXEC] Command mode (LMs):")
178
- self.send(" help lm - list ALL LoadModules")
157
+ await self.a_send("[MICROS] - built-in shell commands")
158
+ await self.a_send(" hello - hello msg - for device identification")
159
+ await self.a_send(" modules - show active Load Modules")
160
+ await self.a_send(" version - returns micrOS version")
161
+ await self.a_send(" exit - exit from shell socket prompt")
162
+ await self.a_send(" reboot - system soft reboot (vm), hard reboot (hw): reboot -h")
163
+ await self.a_send(" webrepl - start webrepl, for file transfers use with --update")
164
+ await self.a_send("[CONF] Configure mode - built-in shell commands")
165
+ await self.a_send(" conf - Enter conf mode")
166
+ await self.a_send(" dump - Dump all data")
167
+ await self.a_send(" key - Get value")
168
+ await self.a_send(" key value - Set value")
169
+ await self.a_send(" noconf - Exit conf mode")
170
+ await self.a_send("[TASK] postfix: &x - one-time, &&x - periodic, x: wait ms [x min: 20ms]")
171
+ await self.a_send(" task list - list tasks with <tag>s")
172
+ await self.a_send(" task kill <tag> - stop task")
173
+ await self.a_send(" task show <tag> - show task output")
174
+ await self.a_send("[EXEC] Command mode (LMs):")
175
+ await self.a_send(" help lm - list ALL LoadModules")
179
176
  if "lm" in str(msg_list):
180
- return Shell._show_lm_funcs(msg_obj=self.send)
181
- return Shell._show_lm_funcs(msg_obj=self.send, active_only=True)
177
+ return await Shell._show_lm_funcs(msg_obj=self.a_send)
178
+ return await Shell._show_lm_funcs(msg_obj=self.a_send, active_only=True)
182
179
 
183
180
  # [2] EXECUTE:
184
181
  # @1 Configure mode
185
182
  if self.__conf_mode and len(msg_list) > 0:
186
183
  # Lock thread under config handling is threads available
187
- return Shell._configure(self.send, msg_list)
184
+ return await Shell._configure(self.a_send, msg_list)
188
185
  # @2 Command mode
189
186
  """
190
187
  INPUT MSG STRUCTURE
@@ -193,43 +190,43 @@ class Shell:
193
190
  """
194
191
  try:
195
192
  # Execute command via InterpreterCore
196
- self.send(lm_exec(arg_list=msg_list)[1])
193
+ await self.a_send(lm_exec(arg_list=msg_list)[1])
197
194
  return True
198
195
  except Exception as e:
199
- self.send(f"[ERROR] shell.lm_exec internal error: {e}")
196
+ await self.a_send(f"[ERROR] shell.lm_exec internal error: {e}")
200
197
  return False
201
198
 
202
199
  #################################################################
203
200
  # CONFIGURE MODE HANDLER #
204
201
  #################################################################
205
202
  @staticmethod
206
- def _configure(msg_obj, msg_list):
203
+ async def _configure(msg_obj, msg_list):
207
204
  """
208
205
  :param msg_obj: shell output stream function reference (write object)
209
206
  :param msg_list: socket input param list
210
207
  :return: execution status
211
208
  """
212
- def dump():
209
+ async def dump():
213
210
  nonlocal msg_obj, msg_list
214
211
  if msg_list[0] == 'dump':
215
212
  search = msg_list[1] if len(msg_list) == 2 else None
216
213
  # DUMP DATA
217
214
  for _key, value in cfgget().items():
218
215
  if search is None or search in _key:
219
- msg_obj(f" {_key}{' ' * (10 - len(_key))}:{' ' * 7} {value}")
216
+ await msg_obj(f" {_key}{' ' * (10 - len(_key))}:{' ' * 7} {value}")
220
217
  return True
221
218
  return False
222
219
 
223
220
  # [CONFIG] Get value
224
221
  if len(msg_list) == 1:
225
- if dump(): # Simple dump without param filter
222
+ if await dump(): # Simple dump without param filter
226
223
  return True
227
224
  # GET SINGLE PARAMETER VALUE
228
- msg_obj(cfgget(msg_list[0]))
225
+ await msg_obj(cfgget(msg_list[0]))
229
226
  return True
230
227
  # [CONFIG] Set value
231
228
  if len(msg_list) >= 2:
232
- if dump(): # Dump with search option
229
+ if await dump(): # Dump with search option
233
230
  return True
234
231
  # Deserialize params
235
232
  key = msg_list[0]
@@ -237,28 +234,28 @@ class Shell:
237
234
  try:
238
235
  output = cfgput(key, " ".join(msg_list[1:]), type_check=True)
239
236
  except Exception as e:
240
- msg_obj(f"node_config write error: {e}")
237
+ await msg_obj(f"node_config write error: {e}")
241
238
  output = False
242
239
  # Evaluation and reply
243
- msg_obj('Saved' if output else 'Invalid key' if cfgget(key) is None else 'Failed to save')
240
+ await msg_obj('Saved' if output else 'Invalid key' if cfgget(key) is None else 'Failed to save')
244
241
  return True
245
242
 
246
243
  #################################################################
247
244
  # COMMAND MODE & LMS HANDLER #
248
245
  #################################################################
249
246
  @staticmethod
250
- def _show_lm_funcs(msg_obj, active_only=False):
247
+ async def _show_lm_funcs(msg_obj, active_only=False):
251
248
  """
252
249
  Dump LM modules with functions - in case of [py] files
253
250
  Dump LM module with help function call - in case of [mpy] files
254
251
  """
255
- def _help(mod):
252
+ async def _help(mod):
256
253
  for lm_path in (i for i in mod if i.startswith('LM_') and (i.endswith('py'))):
257
254
  lm_name = lm_path.replace('LM_', '').split('.')[0]
258
255
  try:
259
- msg_obj(f" {lm_name}")
256
+ await msg_obj(f" {lm_name}")
260
257
  if lm_path.endswith('.mpy'):
261
- msg_obj(f" {' ' * len(lm_path.replace('LM_', '').split('.')[0])}help")
258
+ await msg_obj(f" {' ' * len(lm_path.replace('LM_', '').split('.')[0])}help")
262
259
  continue
263
260
  with open(lm_path, 'r') as f:
264
261
  line = "micrOSisTheBest"
@@ -266,9 +263,9 @@ class Shell:
266
263
  line = f.readline()
267
264
  ldata = line.strip()
268
265
  if ldata.startswith('def ') and not ldata.split()[1].startswith("_") and 'self' not in ldata:
269
- msg_obj(f" {' ' * len(lm_name)}{ldata.replace('def ', '').split('(')[0]}")
266
+ await msg_obj(f" {' ' * len(lm_name)}{ldata.replace('def ', '').split('(')[0]}")
270
267
  except Exception as e:
271
- msg_obj(f"[{lm_path}] SHOW LM PARSER WARNING: {e}")
268
+ await msg_obj(f"[{lm_path}] SHOW LM PARSER WARNING: {e}")
272
269
  return False
273
270
  return True
274
271
 
@@ -276,29 +273,30 @@ class Shell:
276
273
  if active_only:
277
274
  mod_keys = modules.keys()
278
275
  active_modules = (dir_mod for dir_mod in listdir() if dir_mod.split('.')[0] in mod_keys)
279
- return _help(active_modules)
276
+ return await _help(active_modules)
280
277
  # [2] list all LMs on file system (ALL - help lm) - manual
281
- return _help(listdir())
278
+ return await _help(listdir())
282
279
 
283
280
  @staticmethod
284
- def webrepl(msg_obj, update=False):
281
+ async def webrepl(msg_obj, update=False):
285
282
  from Network import ifconfig
286
283
 
287
- msg_obj(" Start micropython WEBREPL - file transfer and debugging")
288
- msg_obj(" [i] restart machine shortcut: import reset")
289
- msg_obj(f" Connect over http://micropython.org/webrepl/#{ifconfig()[1][0]}:8266/")
290
- msg_obj(f" \t[!] webrepl password: {cfgget('appwd')}")
284
+ await msg_obj(" Start micropython WEBREPL - file transfer and debugging")
285
+ await msg_obj(" [i] restart machine shortcut: import reset")
286
+ await msg_obj(f" Connect over http://micropython.org/webrepl/#{ifconfig()[1][0]}:8266/")
287
+ await msg_obj(f" \t[!] webrepl password: {cfgget('appwd')}")
291
288
  if update:
292
- msg_obj(" Restart node then start webrepl...")
293
- msg_obj(" Bye!")
289
+ await msg_obj(" Restart node then start webrepl...")
290
+ await msg_obj(" Bye!")
294
291
  # Set .if_mode->webrepl (start webrepl after reboot and poll update status...)
295
292
  with open('.if_mode', 'w') as f:
296
293
  f.write('webrepl')
297
294
  hard_reset()
298
295
  try:
299
296
  import webrepl
300
- msg_obj(webrepl.start(password=cfgget('appwd')))
297
+ await msg_obj(webrepl.start(password=cfgget('appwd')))
301
298
  except Exception as e:
302
299
  _err_msg = f"[ERR] while starting webrepl: {e}"
303
- msg_obj(_err_msg)
300
+ await msg_obj(_err_msg)
304
301
  errlog_add(_err_msg)
302
+ return True
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: micrOSDevToolKit
3
- Version: 2.9.1
3
+ Version: 2.9.4
4
4
  Summary: Development and deployment environment for micrOS, the diy micropython automation OS (IoT)
5
5
  Home-page: https://github.com/BxNxM/micrOS
6
6
  Author: Marcell Ban
@@ -32,9 +32,9 @@ micrOS/micropython/esp32s3_spiram_oct-20231005-v1.21.0.bin,sha256=S-sv_QeL_Tylg1
32
32
  micrOS/micropython/esp32s3_spiram_oct-20241129-v1.24.1.bin,sha256=VbOF_F0YeqttkQd2ePTW66Jd34RU8u9ccFfcv8kxO_U,1662672
33
33
  micrOS/micropython/rpi-pico-w-20241129-v1.24.1.uf2,sha256=v4aYIbWaE94_f6DDzBWS-a9L1BzlcdkZwld9R7bOVA4,1727488
34
34
  micrOS/micropython/tinypico-20241129-v1.24.1.bin,sha256=Kf3cr766a5SK99CZy8bwdWjwvAZxls3tBYvaHBsw7ac,1527200
35
- micrOS/release_info/micrOS_ReleaseInfo/system_analysis_sum.json,sha256=KTL6AgDxZMzgT_fRZrf4_dz1yU0t_W8DvCPzMn8vfCY,5762
35
+ micrOS/release_info/micrOS_ReleaseInfo/system_analysis_sum.json,sha256=PTEMH6a2gWZnHxpB41WWkE5hJQwMUk_t6VECFbg2Ecc,5761
36
36
  micrOS/source/.DS_Store,sha256=1lFlJ5EFymdzGAUAaI30vcaaLHt3F1LwpG7xILf9jsM,6148
37
- micrOS/source/Common.py,sha256=wFN5RwNUO7o4I5yU2Hqnm5rq16o4SFTxZI3kCqvebL8,7941
37
+ micrOS/source/Common.py,sha256=PAdtseGY6QxUM-5elOAcApUv8AwGQ_smsYex0FeV5w8,7937
38
38
  micrOS/source/Config.py,sha256=me_mhQaqeIE5pVfd2SSZL5uuO2cTHRtjaiUcau4riJo,8867
39
39
  micrOS/source/Debug.py,sha256=_7HZzZ2OKJrcNqeYsG1ZykBa6iN8YTj-K5FFXlEAcRw,5300
40
40
  micrOS/source/Espnow.py,sha256=5B71XVm19byydMuhLmg-ij8uNmfMSAaRNi4iytvFN08,3715
@@ -104,12 +104,12 @@ micrOS/source/LM_telegram.py,sha256=8mwKUywZWbbjYKN68wnrXw4RnvOBI1OKlJrU4sfbG4U,
104
104
  micrOS/source/LM_tinyrgb.py,sha256=kChL607HPTl3Z2hYN2XnzXXfZ6omdP78PQutHdbdfCo,3031
105
105
  micrOS/source/LM_trackball.py,sha256=pVnL_GoXUbqwT6sflqysFWmamVGZOZwHPphrLt5MZXw,9728
106
106
  micrOS/source/LM_veml7700.py,sha256=p2NXb5o5c_tM68rBfbgcfxBR31-BY2jGS2JVF3AYBfk,5771
107
- micrOS/source/Logger.py,sha256=d8pK8T_K4Yxe1j_eAwkWB5N5xd14AvL34vJCPZRZTQA,2853
107
+ micrOS/source/Logger.py,sha256=5dYTcxcGYRFkZvILuuW88coge1ChbupZvo_M8g0r5yE,3204
108
108
  micrOS/source/Network.py,sha256=wLhAPiRyi376TKJA7tzCQidDBHq-AbZGGp7JabHIyl8,9417
109
109
  micrOS/source/Notify.py,sha256=Fm4TfbiFCTz_95aQkMZBikakNUtAv7eZplI7XyufPRI,2351
110
110
  micrOS/source/Scheduler.py,sha256=K6fw807UJnOmbfzgeJQGzGbTL4s2sTIB120ZcS5qrLs,9648
111
- micrOS/source/Server.py,sha256=2a2hcfMEYSSJJ7ccUzaytT2aYmCuHsIOqzdk5ZnR8VY,16270
112
- micrOS/source/Shell.py,sha256=-sA_vT5puekl-EK85CYLQW8Dkz4SWtxx0r03ioRza-E,11934
111
+ micrOS/source/Server.py,sha256=ytt0-PeoPnuyKdp08UNunna1a9MnVBtQaJQrlUpt4N8,16161
112
+ micrOS/source/Shell.py,sha256=DR_4OxlDty14I7j2AOIl3zCcOVcLMojdzt6z3kopH4g,12388
113
113
  micrOS/source/Tasks.py,sha256=YMYt86TWnUBWa8j1DQjbOavYpktCizzfZXaKXrb6Fmo,22498
114
114
  micrOS/source/Time.py,sha256=96XMJjHCPwQ2qNuBD2Un7FXxzXZNbV1xCQn-RujsggU,6351
115
115
  micrOS/source/Types.py,sha256=3O_Vb1jN92RPtvgbV8ui6_iFzDOD-BUzVXlPB7PgmM4,3507
@@ -127,7 +127,7 @@ micrOS/source/urequests.py,sha256=f6IAPK1_xKVL69t1GlPc3zyKkWIwjOCEN7l8vqMjBp8,84
127
127
  micrOS/source/ustyle.css,sha256=P-s8ENwAcWoZi5bocrK3_kVzEjaRFKtFvEF6JRh4MBY,1429
128
128
  micrOS/source/uwidgets.js,sha256=BGeUSbNHn6PClgIgIE6QszwQVJ6j7lzgCBwvIX8cYgo,6631
129
129
  micrOS/source/uwidgets_pro.js,sha256=gbkk3SVttEVvDCwde-pJhAh4k7GuCFPdcWNq32pcKPE,3639
130
- micrOSDevToolKit-2.9.1.data/scripts/devToolKit.py,sha256=CVgEETK2JwWgtEFw_dAZPEfOpAQTYZfTb6810E1j2Hg,10660
130
+ micrOSDevToolKit-2.9.4.data/scripts/devToolKit.py,sha256=CVgEETK2JwWgtEFw_dAZPEfOpAQTYZfTb6810E1j2Hg,10660
131
131
  toolkit/DevEnvCompile.py,sha256=H19-60ZpHzP30C-wqR5QTzMDHHpWrTk0Uzh--TZHxvw,12148
132
132
  toolkit/DevEnvOTA.py,sha256=OkEtO5cpym-kEgGpE3TQbyZ-nQOzZpGzbFdbgCibe7I,25356
133
133
  toolkit/DevEnvUSB.py,sha256=-Fdigxi8asEJG4npQpvbpgjHhESq0gz0rL6lthRupVA,33848
@@ -139,7 +139,7 @@ toolkit/img_stream.html,sha256=ZGyrUgpi-JhMl4euS-TTjwwGrg66a2pGUQCopWiveds,5135
139
139
  toolkit/index.html,sha256=pnwz1tpBdO-FRlsOLQ4-ah5hT8f-O_hhAI411QdiVJA,10873
140
140
  toolkit/micrOSdashboard.py,sha256=SOBzGU1b-NIn40GMd2gE01Fuo8HZP5d1XyVG24RkPeA,54433
141
141
  toolkit/micrOSlint.py,sha256=Ujmgtt79UFkoPmyp1u_XN8FYjOh2puA8XpaJNk47bZ0,25107
142
- toolkit/socketClient.py,sha256=n8wCojbNLSnsDa6ChxpqmjBPm6aIaDtTn8kzcwBKWmE,18556
142
+ toolkit/socketClient.py,sha256=qBPmDPu9FyASlNZ2Q2gP4e-EGu6VyAC7ByiApQlu-CY,18623
143
143
  toolkit/dashboard_apps/AirQualityBME280.py,sha256=ufYAn_eFpCIcNSQUW6AGQN6Uh_5A3xVqSyoWegUNBuY,747
144
144
  toolkit/dashboard_apps/AirQualityDHT22_CO2.py,sha256=TG8Wkx7WOaGM1rpqD6t2rKFES0aqdCJvK-f5I5IK3a4,749
145
145
  toolkit/dashboard_apps/BackupRestore.py,sha256=zRkj6KDFnO9Cj6QUpE0Av39OQZcI8CycQcrqbvWBHqU,6339
@@ -156,7 +156,7 @@ toolkit/dashboard_apps/PresenceTest.py,sha256=MnWjqh3W3qAR9pKdjrOfx74numQw6-acrR
156
156
  toolkit/dashboard_apps/RGBTest.py,sha256=x9ehV6EGH2B4syKGEQrZQbMy1pBsB1M6in8idJ73Jrw,3920
157
157
  toolkit/dashboard_apps/RoboArm.py,sha256=STFIYYy0Li6gLdJx7eu3FZOucF_f5jupHVNFzU-Ta-Q,2084
158
158
  toolkit/dashboard_apps/SED_test.py,sha256=ASVRcoVQiS80tvjQHBnXd69aAioJ4lt_UnL1KAy01sM,2782
159
- toolkit/dashboard_apps/SystemTest.py,sha256=1fJpKnV2FUJtAEDk1F2koKLvLvEYXGla1f-PKgn6Rps,21738
159
+ toolkit/dashboard_apps/SystemTest.py,sha256=Cc_CBiNLaE1UYw9TIQtDLKgtCUcjCtjKbE5lX6utQJE,21816
160
160
  toolkit/dashboard_apps/Template_app.py,sha256=fKF43E-XqibavvjUrCQzG-kMSTCe-sb3ckbLwDgGuTc,1002
161
161
  toolkit/dashboard_apps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
162
162
  toolkit/dashboard_apps/_capture.py,sha256=75aS8ajhEYWNqoG2DwQgqJyArMouGHZNN-0mo1RH9bU,3076
@@ -167,11 +167,11 @@ toolkit/lib/LocalMachine.py,sha256=m5xaWRx1PumKFLQ5_O8vVxC4NTclF1h9J3__pK8N-C4,1
167
167
  toolkit/lib/SafeInput.py,sha256=gMXsMalPcFCwlN6niJlG2twOHfoGsEgHL9-Uh2YQJHE,855
168
168
  toolkit/lib/SearchDevices.py,sha256=1nnJDwo_U5cCN2xsdNUT6EQqdt2fW-qAWXWzyzXzyyc,5813
169
169
  toolkit/lib/SerialDriverHandler.py,sha256=Zn0zeq4mshTMVc6fzycvrOZiKt6w6YOxJcTWw3BMN2M,7344
170
- toolkit/lib/TerminalColors.py,sha256=GUF6GsiZg8jP0izhEwhtttcteBvPoMhkTMMh-M5ewmQ,847
170
+ toolkit/lib/TerminalColors.py,sha256=Ly_8o9-eBmka1dqA2M3DBlcd1zvCCO2K_BnQ1XbqxcE,947
171
171
  toolkit/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
172
172
  toolkit/lib/file_extensions.py,sha256=0DpayBGjKQg7y2ZGJXf5wVPnre_4C5j-7YIViNGvYz4,372
173
173
  toolkit/lib/macroScript.py,sha256=Hic98kyOR1Up18T6Lrpnnv_8bkNdocnIbiXdv6R7jrI,13854
174
- toolkit/lib/micrOSClient.py,sha256=T-s5vYSnMgmYOkpET_P-AIjU-7M6mmx-oALT9dNsOZc,17009
174
+ toolkit/lib/micrOSClient.py,sha256=Rej1x9IpFmCW6LAoFf6ylua7wjwm7Apil2mf1DNW7QA,17163
175
175
  toolkit/lib/pip_package_installer.py,sha256=jpC-y1KR72_PJlqyUR6-U5b6l1szVqnIZ4nrSgUsOTM,4262
176
176
  toolkit/simulator_lib/.DS_Store,sha256=1lFlJ5EFymdzGAUAaI30vcaaLHt3F1LwpG7xILf9jsM,6148
177
177
  toolkit/simulator_lib/IO_darwin.py,sha256=f8HOfQKJvniShvjpBe6f4nisr6oJd9SnvxPsbdNIGQk,2336
@@ -263,7 +263,7 @@ toolkit/user_data/webhooks/macro.py,sha256=E_Um6fc9P6sBKvChyrKgksHmBmaFUuq_Xxy8I
263
263
  toolkit/user_data/webhooks/template.macro,sha256=XikSl3FsD6W9pUx3sqavM5tWIMBquFx9f3bh_CB8k-A,631
264
264
  toolkit/user_data/webhooks/template.py,sha256=WssXY2BDKIwvObq0SpFCjjpEGzgbLlozFTug4ANswWM,342
265
265
  toolkit/workspace/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
266
- toolkit/workspace/precompiled/Common.mpy,sha256=vpavv1IDKQ8HQOvUj2Z6nh5S5Hxih2UQgl3CjSD3vMs,2144
266
+ toolkit/workspace/precompiled/Common.mpy,sha256=2bUIMJPc9AAVGtgzI_6DaNqF6T-kLyyd4Ys_yjrgI9A,2140
267
267
  toolkit/workspace/precompiled/Config.mpy,sha256=X1SAfiWEMvduP6kFcVSjfY3TJsIKcbITDq1lrEIj67M,3076
268
268
  toolkit/workspace/precompiled/Debug.mpy,sha256=OpoE-QcllAnASSnAC0V364G7zHjbYI_0jSPzPRBhWkI,1823
269
269
  toolkit/workspace/precompiled/Espnow.mpy,sha256=yzC_KeCfVzWKidRbEw_R6LQeKG6DFMu4XAssXqFSuKQ,1438
@@ -333,12 +333,12 @@ toolkit/workspace/precompiled/LM_telegram.mpy,sha256=qdsv0aHVhrpNvrWKzzdIi4xvuT2
333
333
  toolkit/workspace/precompiled/LM_tinyrgb.mpy,sha256=qWR-e8DXuzmstxQlyic0YjwFaGiBBBWpf57Wyn1jjFc,1016
334
334
  toolkit/workspace/precompiled/LM_trackball.mpy,sha256=8OFO02VeETcwkuOACh0e9amRWwTpoRogEXcVmRBrUn4,3474
335
335
  toolkit/workspace/precompiled/LM_veml7700.mpy,sha256=-MPEbH9RzOk0hzBuXf5XzOHKZdeRD0xBgf890GJu6Vg,1956
336
- toolkit/workspace/precompiled/Logger.mpy,sha256=aFGjkv1bozWer4d-OoQQ2pp252zlMWxU0_m7LRhnaIc,854
336
+ toolkit/workspace/precompiled/Logger.mpy,sha256=ztBXR7yqWezXuLSbsmZP41pWUq_4cw9K6aNcQgNe-nM,1081
337
337
  toolkit/workspace/precompiled/Network.mpy,sha256=WtpvhGB2bvEe94dAHV40fpEyk-Fi0D6vL1q_m6k4qBg,3274
338
338
  toolkit/workspace/precompiled/Notify.mpy,sha256=lyl5J16b8X2vnHzHSikzlNCX5XLQ7JaB0midEmVMn58,872
339
339
  toolkit/workspace/precompiled/Scheduler.mpy,sha256=ctCj7FfXj5TchPPxe_9dmnTXWN88egtbAnmJ0N9u_1w,2202
340
- toolkit/workspace/precompiled/Server.mpy,sha256=k-31qSfIxZKBPWaoUWBPQbmcLMcy69SSQMkDFrtuRGA,4899
341
- toolkit/workspace/precompiled/Shell.mpy,sha256=0n6SWX5keDANNW0ACZUcmkntOJdyh8tKPZzX7QX9jHk,4167
340
+ toolkit/workspace/precompiled/Server.mpy,sha256=Rk_Pkg_Pc_7W6tIiRcGfU4S9YChYPYw4-WKOqz0gUZY,4746
341
+ toolkit/workspace/precompiled/Shell.mpy,sha256=z52FjUhn2S345FjXp8KgyQ30rFvgOVkcVDwpcSfDqNk,4334
342
342
  toolkit/workspace/precompiled/Tasks.mpy,sha256=vL3tDV7Us3Wg7qtZA8ovqEsvLndOmu14GHcZF2_DtrY,6253
343
343
  toolkit/workspace/precompiled/Time.mpy,sha256=D6jvLP5tUKQdJGcn6Q4-ru-p0at6hnxfLC5bqC78gv0,2756
344
344
  toolkit/workspace/precompiled/Types.mpy,sha256=LssRbPgvsWuR4d2m3R7VMIvsnkVp9nN0ltwaY2wGop8,1401
@@ -358,8 +358,8 @@ toolkit/workspace/precompiled/urequests.mpy,sha256=FnrzbNJtHfmIJN1PpwhQ__CDx6Vmd
358
358
  toolkit/workspace/precompiled/ustyle.css,sha256=P-s8ENwAcWoZi5bocrK3_kVzEjaRFKtFvEF6JRh4MBY,1429
359
359
  toolkit/workspace/precompiled/uwidgets.js,sha256=BGeUSbNHn6PClgIgIE6QszwQVJ6j7lzgCBwvIX8cYgo,6631
360
360
  toolkit/workspace/precompiled/uwidgets_pro.js,sha256=gbkk3SVttEVvDCwde-pJhAh4k7GuCFPdcWNq32pcKPE,3639
361
- micrOSDevToolKit-2.9.1.dist-info/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
362
- micrOSDevToolKit-2.9.1.dist-info/METADATA,sha256=Og49_Wr05gkkSy5Pm8X_PQ5K30eMxqzic_67UCheC_8,53468
363
- micrOSDevToolKit-2.9.1.dist-info/WHEEL,sha256=UvcQYKBHoFqaQd6LKyqHw9fxEolWLQnlzP0h_LgJAfI,91
364
- micrOSDevToolKit-2.9.1.dist-info/top_level.txt,sha256=rOGOIXqLBdGZAoDTiLdZ9B_leFB7bMv7YabLwuIc2bc,25
365
- micrOSDevToolKit-2.9.1.dist-info/RECORD,,
361
+ micrOSDevToolKit-2.9.4.dist-info/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
362
+ micrOSDevToolKit-2.9.4.dist-info/METADATA,sha256=2UV8fRBCkJApZjqaoF9oIvrKoWke7Bnl_YUoErTz0Pw,53468
363
+ micrOSDevToolKit-2.9.4.dist-info/WHEEL,sha256=UvcQYKBHoFqaQd6LKyqHw9fxEolWLQnlzP0h_LgJAfI,91
364
+ micrOSDevToolKit-2.9.4.dist-info/top_level.txt,sha256=rOGOIXqLBdGZAoDTiLdZ9B_leFB7bMv7YabLwuIc2bc,25
365
+ micrOSDevToolKit-2.9.4.dist-info/RECORD,,
@@ -359,8 +359,9 @@ def check_robustness_recursion():
359
359
  def check_intercon(host=None):
360
360
  def _convert_return_to_dict(data):
361
361
  try:
362
- data_dict = ast.literal_eval(data[1])
362
+ data_dict = ast.literal_eval(data[1].split("\n")[0])
363
363
  except Exception as e:
364
+ print(f"WARNING: cannot parse output as dir: {e}")
364
365
  data_dict = {'tag': None, 'verdict': f'{data}: {str(e)}'}
365
366
  return data[0], data_dict
366
367
 
@@ -16,6 +16,8 @@ class Colors:
16
16
  OKGREEN = '\033[92m'
17
17
  HEADER = '\033[95m'
18
18
  UNDERLINE = '\033[4m'
19
+ LIGHT_GRAY = '\033[37m'
20
+ GRAY = '\033[90m'
19
21
  else:
20
22
  NC = ''
21
23
  OK = ''
@@ -26,6 +28,8 @@ class Colors:
26
28
  OKGREEN = ''
27
29
  HEADER = ''
28
30
  UNDERLINE = ''
31
+ LIGHT_GRAY = ''
32
+ GRAY = ''
29
33
 
30
34
 
31
35
  if __name__ == "__main__":
@@ -160,7 +160,7 @@ class micrOSClient:
160
160
  self.preprompt = ""
161
161
  return _data
162
162
 
163
- def __receive_data(self, read_timeout=20):
163
+ def __receive_data(self, read_timeout=20, stream=False):
164
164
  """
165
165
  Client Receiver Loop
166
166
  - read_timeout - wait for server to reply (should be <15, avoid msg queue-ing)
@@ -173,7 +173,11 @@ class micrOSClient:
173
173
  # Collect answer data
174
174
  if select.select([self.conn], [], [], read_timeout)[0]:
175
175
  while True:
176
- data_buffer += self.conn.recv(4096).decode('utf-8')
176
+ incoming_data = self.conn.recv(4096).decode('utf-8')
177
+ if stream:
178
+ incoming_data = incoming_data.replace(self.prompt, f"{color.NC}{color.BOLD}{self.prompt}{color.NC}")
179
+ print(f"\r{color.LIGHT_GRAY}{incoming_data}{color.NC}", end="")
180
+ data_buffer += incoming_data
177
181
  # Last line from data_buffer (handle fragmented messages - prompt detection)
178
182
  last_line = data_buffer.strip().split("\n")[-1]
179
183
  # Wait for prompt or special cases (exit/prompt)
@@ -200,7 +204,7 @@ class micrOSClient:
200
204
  self.isconn = False
201
205
  self.spacer = 0
202
206
 
203
- def __run_command(self, cmd):
207
+ def __run_command(self, cmd, stream=False):
204
208
  """
205
209
  Run command on server tcp/ip connection
206
210
  - prompt check - validate device ("hostname $" = "prompt")
@@ -218,14 +222,14 @@ class micrOSClient:
218
222
  # Workaround for reboot command - micrOS async server cannot send Bye! msg before reboot.
219
223
  if reboot_request:
220
224
  return 'Bye!'
221
- data = self.__receive_data()
225
+ data = self.__receive_data(stream=stream)
222
226
  return data
223
227
  # Skip command run: prompt and host not the same!
224
228
  print(f"[micrOSClient] {color.ERR}prompt mismatch{color.NC}, hostname: {check_hostname} prompt: {check_prompt} ")
225
229
  # Check UID?
226
230
  return None
227
231
 
228
- def send_cmd(self, cmd, timeout=3, retry=5):
232
+ def send_cmd(self, cmd, timeout=3, retry=5, stream=False):
229
233
  """
230
234
  Send command function - main usage for non interactive mode
231
235
  """
@@ -244,7 +248,7 @@ class micrOSClient:
244
248
 
245
249
  # @ Run command
246
250
  try:
247
- out = self.__run_command(cmd)
251
+ out = self.__run_command(cmd, stream=stream)
248
252
  except Exception as e:
249
253
  self.dbg_print("{}[ERR]{} send_cmd error: {}".format(color.ERR, color.NC, e))
250
254
  self.dbg_print("Auto deinit connection")
@@ -261,11 +265,11 @@ class micrOSClient:
261
265
  # return output list
262
266
  return out
263
267
 
264
- def send_cmd_retry(self, cmd, timeout=6, retry=5):
268
+ def send_cmd_retry(self, cmd, timeout=6, retry=5, stream=False):
265
269
  out = None
266
270
  for cnt in range(0, retry):
267
271
  try:
268
- out = self.send_cmd(cmd, timeout)
272
+ out = self.send_cmd(cmd, timeout, stream=stream)
269
273
  if out is None or isinstance(out, list):
270
274
  break
271
275
  except OSError as e:
@@ -287,16 +291,12 @@ class micrOSClient:
287
291
  print("Telnet connect: {}".format(e))
288
292
  if "busy" in str(e) or "timed out" in str(e) or "No route to host" in str(e) or "Host is down" in str(e):
289
293
  return
294
+
295
+ print(f"{color.BOLD}{self.preprompt}{self.prompt}{color.NC} ", end="")
290
296
  while True:
291
- cmd = input("{}{} ".format(self.preprompt, self.prompt))
297
+ cmd = input()
292
298
  # send command
293
- output = self.send_cmd(cmd)
294
- # Format output to human readable
295
- output = '\n'.join(output) if isinstance(output, list) else output
296
- # output to STDOUT
297
- if not (cmd.strip() == '' and output is None):
298
- print(output)
299
- # Close session
299
+ output = self.send_cmd(cmd, stream=True)
300
300
  if 'Bye!' in str(output):
301
301
  break
302
302
  self.close()
toolkit/socketClient.py CHANGED
@@ -210,8 +210,8 @@ class ConnectionData:
210
210
  start_comm = time.time()
211
211
  version_data = SocketDictClient(host=ip, port=port, silent_mode=True, tout=3).non_interactive(['version'])
212
212
  elapsed_time = "{:.3f}".format(time.time() - start_comm)
213
- except:
214
- pass
213
+ except Exception as e:
214
+ print(f"Getting device version {fuid}:{uid} error: {e}")
215
215
 
216
216
  # Generate line printout
217
217
  base_info = "{uid}{spr1}{fuid}".format(uid=uid, spr1=spacer1, fuid=fuid)
Binary file
Binary file
Binary file
Binary file