micrOSDevToolKit 2.9.9__py3-none-any.whl → 2.9.10__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 +20 -20
- micrOS/source/LM_oled_ui.py +1 -1
- micrOS/source/LM_system.py +4 -4
- micrOS/source/Notify.py +4 -0
- micrOS/source/Server.py +1 -1
- micrOS/source/Shell.py +3 -3
- micrOS/source/Tasks.py +1 -1
- micrOS/source/Time.py +7 -8
- micrOS/source/__pycache__/Common.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/micrOSloader.py +0 -1
- micrOS/source/urequests.py +8 -6
- {micrOSDevToolKit-2.9.9.data → micrOSDevToolKit-2.9.10.data}/scripts/devToolKit.py +10 -0
- {micrOSDevToolKit-2.9.9.dist-info → micrOSDevToolKit-2.9.10.dist-info}/METADATA +14 -4
- {micrOSDevToolKit-2.9.9.dist-info → micrOSDevToolKit-2.9.10.dist-info}/RECORD +50 -46
- {micrOSDevToolKit-2.9.9.dist-info → micrOSDevToolKit-2.9.10.dist-info}/WHEEL +1 -1
- toolkit/MicrOSDevEnv.py +19 -5
- toolkit/WebRepl.py +73 -0
- toolkit/dashboard_apps/BackupRestore.py +20 -31
- toolkit/dashboard_apps/CCTDemo.py +12 -17
- toolkit/dashboard_apps/CCTTest.py +20 -24
- toolkit/dashboard_apps/CamStream.py +2 -6
- toolkit/dashboard_apps/CatGame.py +14 -16
- toolkit/dashboard_apps/Dimmer.py +11 -21
- toolkit/dashboard_apps/GetVersion.py +11 -19
- toolkit/dashboard_apps/MicrophoneTest.py +1 -6
- toolkit/dashboard_apps/NeoEffectsDemo.py +28 -34
- toolkit/dashboard_apps/NeopixelTest.py +20 -25
- toolkit/dashboard_apps/PresenceTest.py +2 -8
- toolkit/dashboard_apps/RGBTest.py +20 -24
- toolkit/dashboard_apps/RoboArm.py +24 -32
- toolkit/dashboard_apps/SED_test.py +10 -14
- toolkit/dashboard_apps/SensorsTest.py +61 -0
- toolkit/dashboard_apps/SystemTest.py +151 -77
- toolkit/dashboard_apps/Template_app.py +11 -23
- toolkit/dashboard_apps/_app_base.py +34 -0
- toolkit/dashboard_apps/uLightDemo.py +15 -24
- toolkit/lib/micrOSClient.py +11 -9
- toolkit/micrOSlint.py +3 -3
- toolkit/socketClient.py +0 -1
- toolkit/workspace/precompiled/LM_oled_ui.mpy +0 -0
- toolkit/workspace/precompiled/LM_system.mpy +0 -0
- toolkit/workspace/precompiled/Notify.mpy +0 -0
- toolkit/workspace/precompiled/Shell.mpy +0 -0
- toolkit/workspace/precompiled/Time.mpy +0 -0
- toolkit/workspace/precompiled/micrOSloader.mpy +0 -0
- toolkit/workspace/precompiled/urequests.mpy +0 -0
- toolkit/dashboard_apps/AirQualityBME280.py +0 -36
- toolkit/dashboard_apps/AirQualityDHT22_CO2.py +0 -36
- {micrOSDevToolKit-2.9.9.dist-info → micrOSDevToolKit-2.9.10.dist-info}/LICENSE +0 -0
- {micrOSDevToolKit-2.9.9.dist-info → micrOSDevToolKit-2.9.10.dist-info}/top_level.txt +0 -0
|
@@ -5,19 +5,15 @@ import sys
|
|
|
5
5
|
import time
|
|
6
6
|
import random
|
|
7
7
|
MYPATH = os.path.dirname(os.path.abspath(__file__))
|
|
8
|
-
sys.path.append(os.path.dirname(MYPATH))
|
|
9
|
-
import socketClient
|
|
10
|
-
import time
|
|
11
8
|
sys.path.append(os.path.join(MYPATH, '../lib/'))
|
|
12
9
|
from TerminalColors import Colors
|
|
13
10
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def base_cmd():
|
|
19
|
-
return ['--dev', DEVICE]
|
|
11
|
+
try:
|
|
12
|
+
from ._app_base import AppBase
|
|
13
|
+
except:
|
|
14
|
+
from _app_base import AppBase
|
|
20
15
|
|
|
16
|
+
CLIENT = None
|
|
21
17
|
|
|
22
18
|
def test_random_colors(test_len=8, smooth=False):
|
|
23
19
|
main_function = 'neopixel color'
|
|
@@ -31,12 +27,12 @@ def test_random_colors(test_len=8, smooth=False):
|
|
|
31
27
|
|
|
32
28
|
# Generate command
|
|
33
29
|
cmd_list_str = " <a> ".join(["{} {} {} {} {} >json".format(main_function, k[0], k[1], k[2], smooth) for k in color_list])
|
|
34
|
-
args =
|
|
30
|
+
args = [cmd_list_str]
|
|
35
31
|
print("{} Generated command {} - multi message single connection single connection: {} r g b {}\n{}".format(Colors.HEADER, Colors.NC, main_function, smooth, args))
|
|
36
32
|
|
|
37
33
|
start_t = time.time()
|
|
38
34
|
# SEND MESSSAGE OVER micrOS client
|
|
39
|
-
status, answer =
|
|
35
|
+
status, answer = CLIENT.run(args)
|
|
40
36
|
delta_t = round((time.time() - start_t)/test_len, 1)
|
|
41
37
|
|
|
42
38
|
#Evaluate last message
|
|
@@ -53,14 +49,14 @@ def test_random_colors(test_len=8, smooth=False):
|
|
|
53
49
|
|
|
54
50
|
def test_toogle():
|
|
55
51
|
main_function = 'neopixel toggle'
|
|
56
|
-
args_on =
|
|
57
|
-
args_toggle =
|
|
52
|
+
args_on = [f'{main_function} True >json']
|
|
53
|
+
args_toggle = [f'{main_function} >json']
|
|
58
54
|
|
|
59
55
|
# SEND MESSSAGE OVER micrOS client
|
|
60
|
-
status, answer =
|
|
56
|
+
status, answer = CLIENT.run(args_on)
|
|
61
57
|
if status and '"S": 1' in answer:
|
|
62
58
|
# SEND MESSSAGE OVER micrOS client
|
|
63
|
-
status, answer =
|
|
59
|
+
status, answer = CLIENT.run(args_toggle)
|
|
64
60
|
if status and '"S": 0' in answer:
|
|
65
61
|
return True, '{} works {}OK{}'.format(main_function, Colors.OK, Colors.NC)
|
|
66
62
|
return False, '{} not works {}NOK{}: {}'.format(main_function, Colors.ERR, Colors.NC, answer)
|
|
@@ -68,24 +64,23 @@ def test_toogle():
|
|
|
68
64
|
|
|
69
65
|
def test_brightness():
|
|
70
66
|
main_function = 'neopixel brightness'
|
|
71
|
-
args_10 =
|
|
72
|
-
args_50 =
|
|
73
|
-
args_actual_br =
|
|
67
|
+
args_10 = [f'{main_function} 10 >json']
|
|
68
|
+
args_50 = [f'{main_function} 50 >json']
|
|
69
|
+
args_actual_br = [f'{main_function} >json']
|
|
74
70
|
|
|
75
|
-
status, answer =
|
|
71
|
+
status, answer = CLIENT.run(args_10)
|
|
76
72
|
if status:
|
|
77
|
-
status, answer =
|
|
73
|
+
status, answer = CLIENT.run(args_50)
|
|
78
74
|
if status:
|
|
79
|
-
status, answer =
|
|
75
|
+
status, answer = CLIENT.run(args_actual_br)
|
|
80
76
|
if status and "50.0 %" in answer:
|
|
81
77
|
return True, "{} function {}OK{} (50.0 % == {})".format(main_function, Colors.OK, Colors.NC, answer)
|
|
82
78
|
return False, "{} function {}NOK{} (50.0 % == {})".format(main_function, Colors.ERR, Colors.NC, answer)
|
|
83
79
|
|
|
84
80
|
|
|
85
|
-
def app(devfid=None):
|
|
86
|
-
global
|
|
87
|
-
|
|
88
|
-
DEVICE = devfid
|
|
81
|
+
def app(devfid=None, pwd=None):
|
|
82
|
+
global CLIENT
|
|
83
|
+
CLIENT = AppBase(device=devfid, password=pwd)
|
|
89
84
|
|
|
90
85
|
test_pool = { 'Color change test': test_random_colors(test_len=8, smooth=False),
|
|
91
86
|
'Color smooth test': test_random_colors(test_len=4, smooth=True),
|
|
@@ -2,15 +2,9 @@ import sys, os
|
|
|
2
2
|
import subprocess
|
|
3
3
|
MYPATH = os.path.dirname(os.path.abspath(__file__))
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def app(devfid=None):
|
|
5
|
+
def app(devfid=None, pwd=None):
|
|
9
6
|
"""
|
|
10
7
|
Wrapper function to start subprocess plotting... (threading limitation)
|
|
11
8
|
"""
|
|
12
|
-
|
|
13
|
-
if devfid is not None:
|
|
14
|
-
DEVICE = devfid
|
|
15
|
-
result = subprocess.run([f'{sys.executable}', os.path.join(MYPATH, '_presencePlotting.py'), DEVICE])
|
|
9
|
+
result = subprocess.run([f'{sys.executable}', os.path.join(MYPATH, '_presencePlotting.py'), devfid])
|
|
16
10
|
print(result)
|
|
@@ -5,18 +5,15 @@ import sys
|
|
|
5
5
|
import time
|
|
6
6
|
import random
|
|
7
7
|
MYPATH = os.path.dirname(os.path.abspath(__file__))
|
|
8
|
-
sys.path.append(os.path.dirname(MYPATH))
|
|
9
|
-
import socketClient
|
|
10
|
-
import time
|
|
11
8
|
sys.path.append(os.path.join(MYPATH, '../lib/'))
|
|
12
9
|
from TerminalColors import Colors
|
|
13
10
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
try:
|
|
12
|
+
from ._app_base import AppBase
|
|
13
|
+
except:
|
|
14
|
+
from _app_base import AppBase
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
return ['--dev', DEVICE]
|
|
16
|
+
CLIENT = None
|
|
20
17
|
|
|
21
18
|
|
|
22
19
|
def test_random_colors(test_len=8, smooth=False):
|
|
@@ -31,12 +28,12 @@ def test_random_colors(test_len=8, smooth=False):
|
|
|
31
28
|
|
|
32
29
|
# Generate command
|
|
33
30
|
cmd_list_str = " <a> ".join(["{} {} {} {} {} >json".format(main_function, k[0], k[1], k[2], smooth) for k in color_list])
|
|
34
|
-
args =
|
|
31
|
+
args = [cmd_list_str]
|
|
35
32
|
print("{} Generated command {} - multi message single connection single connection: {} r g b {}\n{}".format(Colors.HEADER, Colors.NC, main_function, smooth, args))
|
|
36
33
|
|
|
37
34
|
start_t = time.time()
|
|
38
35
|
# SEND MESSSAGE OVER micrOS client
|
|
39
|
-
status, answer =
|
|
36
|
+
status, answer = CLIENT.run(args)
|
|
40
37
|
delta_t = round((time.time() - start_t)/test_len, 1)
|
|
41
38
|
|
|
42
39
|
#Evaluate last message
|
|
@@ -53,14 +50,14 @@ def test_random_colors(test_len=8, smooth=False):
|
|
|
53
50
|
|
|
54
51
|
def test_toogle():
|
|
55
52
|
main_function = 'rgb toggle'
|
|
56
|
-
args_on =
|
|
57
|
-
args_toggle =
|
|
53
|
+
args_on = [f'{main_function} True >json']
|
|
54
|
+
args_toggle = [f'{main_function} >json']
|
|
58
55
|
|
|
59
56
|
# SEND MESSSAGE OVER micrOS client
|
|
60
|
-
status, answer =
|
|
57
|
+
status, answer = CLIENT.run(args_on)
|
|
61
58
|
if status and '"S": 1' in answer:
|
|
62
59
|
# SEND MESSSAGE OVER micrOS client
|
|
63
|
-
status, answer =
|
|
60
|
+
status, answer = CLIENT.run(args_toggle)
|
|
64
61
|
if status and '"S": 0' in answer:
|
|
65
62
|
return True, '{} works {}OK{}'.format(main_function, Colors.OK, Colors.NC)
|
|
66
63
|
return False, '{} not works {}NOK{}: {}'.format(main_function, Colors.ERR, Colors.NC, answer)
|
|
@@ -68,24 +65,23 @@ def test_toogle():
|
|
|
68
65
|
|
|
69
66
|
def test_brightness():
|
|
70
67
|
main_function = 'rgb brightness'
|
|
71
|
-
args_10 =
|
|
72
|
-
args_50 =
|
|
73
|
-
args_actual_br =
|
|
68
|
+
args_10 = [f'{main_function} 10 >json']
|
|
69
|
+
args_50 = [f'{main_function} 50 >json']
|
|
70
|
+
args_actual_br = [f'{main_function} >json']
|
|
74
71
|
|
|
75
|
-
status, answer =
|
|
72
|
+
status, answer = CLIENT.run(args_10)
|
|
76
73
|
if status:
|
|
77
|
-
status, answer =
|
|
74
|
+
status, answer = CLIENT.run(args_50)
|
|
78
75
|
if status:
|
|
79
|
-
status, answer =
|
|
76
|
+
status, answer = CLIENT.run(args_actual_br)
|
|
80
77
|
if status and "50.0 %" in answer:
|
|
81
78
|
return True, "{} function {}OK{} (50.0 % == {})".format(main_function, Colors.OK, Colors.NC, answer)
|
|
82
79
|
return False, "{} function {}NOK{} (50.0 % == {})".format(main_function, Colors.ERR, Colors.NC, answer)
|
|
83
80
|
|
|
84
81
|
|
|
85
|
-
def app(devfid=None):
|
|
86
|
-
global
|
|
87
|
-
|
|
88
|
-
DEVICE = devfid
|
|
82
|
+
def app(devfid=None, pwd=None):
|
|
83
|
+
global CLIENT
|
|
84
|
+
CLIENT = AppBase(device=devfid, password=pwd)
|
|
89
85
|
|
|
90
86
|
test_pool = { 'Color change test': test_random_colors(test_len=8, smooth=False),
|
|
91
87
|
'Color smooth test': test_random_colors(test_len=4, smooth=True),
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
sys.path.append(os.path.dirname(MYPATH))
|
|
8
|
-
import socketClient
|
|
3
|
+
try:
|
|
4
|
+
from ._app_base import AppBase
|
|
5
|
+
except:
|
|
6
|
+
from _app_base import AppBase
|
|
9
7
|
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
DEVICE = 'RoboArm'
|
|
9
|
+
CLIENT = None
|
|
13
10
|
__TEST_DATA = {'ok': 0, 'err': 0}
|
|
14
11
|
|
|
15
12
|
|
|
@@ -22,58 +19,53 @@ def test_eval(state, msg):
|
|
|
22
19
|
__TEST_DATA['err'] += 1
|
|
23
20
|
|
|
24
21
|
|
|
25
|
-
def
|
|
26
|
-
return ['--dev', DEVICE]
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def app(devfid=None):
|
|
22
|
+
def app(devfid=None, pwd=None):
|
|
30
23
|
"""
|
|
31
24
|
devfid: selected device input
|
|
32
25
|
send command(s) over socket connection [socketClient.run(args)]
|
|
33
26
|
<a> command separator in single connection
|
|
34
27
|
"""
|
|
35
|
-
global
|
|
36
|
-
|
|
37
|
-
DEVICE = devfid
|
|
28
|
+
global CLIENT
|
|
29
|
+
CLIENT = AppBase(device=devfid, password=pwd)
|
|
38
30
|
|
|
39
31
|
def home():
|
|
40
|
-
args =
|
|
41
|
-
status, answer =
|
|
32
|
+
args = ['roboarm control 75 70']
|
|
33
|
+
status, answer = CLIENT.run(args)
|
|
42
34
|
test_eval(status, answer)
|
|
43
35
|
|
|
44
36
|
def switch(state=False):
|
|
45
|
-
args =
|
|
46
|
-
status, answer =
|
|
37
|
+
args = ['switch set_state {}'.format(state)]
|
|
38
|
+
status, answer = CLIENT.run(args)
|
|
47
39
|
print(answer)
|
|
48
40
|
|
|
49
41
|
home()
|
|
50
42
|
switch(True)
|
|
51
43
|
|
|
52
|
-
args =
|
|
53
|
-
status, answer =
|
|
44
|
+
args = ['roboarm control 40 40 speed_ms=7']
|
|
45
|
+
status, answer = CLIENT.run(args)
|
|
54
46
|
test_eval(status, answer)
|
|
55
47
|
|
|
56
48
|
home()
|
|
57
49
|
|
|
58
|
-
args =
|
|
59
|
-
status, answer =
|
|
50
|
+
args = ['roboarm control 115 115']
|
|
51
|
+
status, answer = CLIENT.run(args)
|
|
60
52
|
test_eval(status, answer)
|
|
61
53
|
|
|
62
|
-
args =
|
|
63
|
-
status, answer =
|
|
54
|
+
args = ['roboarm control 40 115']
|
|
55
|
+
status, answer = CLIENT.run(args)
|
|
64
56
|
test_eval(status, answer)
|
|
65
57
|
|
|
66
|
-
args =
|
|
67
|
-
status, answer =
|
|
58
|
+
args = ['roboarm control 115 40']
|
|
59
|
+
status, answer = CLIENT.run(args)
|
|
68
60
|
test_eval(status, answer)
|
|
69
61
|
|
|
70
|
-
args =
|
|
71
|
-
status, answer =
|
|
62
|
+
args = ['roboarm control 40 40']
|
|
63
|
+
status, answer = CLIENT.run(args)
|
|
72
64
|
test_eval(status, answer)
|
|
73
65
|
|
|
74
66
|
# Move back to home pos
|
|
75
|
-
args =
|
|
76
|
-
status, answer =
|
|
67
|
+
args = ['roboarm control 75 70 speed_ms=3']
|
|
68
|
+
status, answer = CLIENT.run(args)
|
|
77
69
|
test_eval(status, answer)
|
|
78
70
|
|
|
79
71
|
switch(False)
|
|
@@ -3,18 +3,15 @@
|
|
|
3
3
|
import os
|
|
4
4
|
import sys
|
|
5
5
|
import time
|
|
6
|
+
|
|
6
7
|
MYPATH = os.path.dirname(os.path.abspath(__file__))
|
|
7
|
-
sys.path.append(os.path.dirname(MYPATH))
|
|
8
|
-
import socketClient
|
|
9
8
|
sys.path.append(os.path.join(MYPATH, '../lib/'))
|
|
10
9
|
from TerminalColors import Colors
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def base_cmd():
|
|
17
|
-
return ['--dev', DEVICE]
|
|
11
|
+
try:
|
|
12
|
+
from ._app_base import AppBase
|
|
13
|
+
except:
|
|
14
|
+
from _app_base import AppBase
|
|
18
15
|
|
|
19
16
|
|
|
20
17
|
def test():
|
|
@@ -68,22 +65,21 @@ def test():
|
|
|
68
65
|
return status
|
|
69
66
|
|
|
70
67
|
|
|
71
|
-
def app(devfid=None):
|
|
68
|
+
def app(devfid=None, pwd=None):
|
|
72
69
|
"""
|
|
73
70
|
devfid: selected device input
|
|
74
71
|
send command(s) over socket connection [socketClient.run(args)]
|
|
75
72
|
"""
|
|
76
|
-
global
|
|
77
|
-
|
|
78
|
-
|
|
73
|
+
global CLIENT
|
|
74
|
+
CLIENT = AppBase(device=devfid, password=pwd)
|
|
75
|
+
|
|
79
76
|
verdict = test()
|
|
80
77
|
col = Colors.OK if verdict else Colors.ERR
|
|
81
78
|
print("VERDICT: {}{}{}".format(col, verdict, Colors.NC))
|
|
82
79
|
|
|
83
80
|
|
|
84
81
|
def send_cmd(cmd_list):
|
|
85
|
-
|
|
86
|
-
status, answer = socketClient.run(args)
|
|
82
|
+
status, answer = CLIENT.run(cmd_list)
|
|
87
83
|
col = Colors.OK if status else Colors.ERR
|
|
88
84
|
print("CMDS: {}\n{}{}{}\n".format(cmd_list, col, answer, Colors.NC))
|
|
89
85
|
return status
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
MYPATH = os.path.dirname(os.path.abspath(__file__))
|
|
5
|
+
|
|
6
|
+
try:
|
|
7
|
+
from ._app_base import AppBase
|
|
8
|
+
except:
|
|
9
|
+
from _app_base import AppBase
|
|
10
|
+
|
|
11
|
+
CLIENT = None
|
|
12
|
+
|
|
13
|
+
def measure(args, req_cnt=5):
|
|
14
|
+
verdict = f"Measure with {args[0]}"
|
|
15
|
+
print(verdict)
|
|
16
|
+
err_cnt = 0
|
|
17
|
+
for k in range(0, req_cnt):
|
|
18
|
+
try:
|
|
19
|
+
status, answer = CLIENT.run(args)
|
|
20
|
+
if status:
|
|
21
|
+
print(f"\t|- [{k+1}/{req_cnt}] OK")
|
|
22
|
+
else:
|
|
23
|
+
print(f"\t|- [{k+1}/{req_cnt}] ERR")
|
|
24
|
+
err_cnt += 1
|
|
25
|
+
except KeyboardInterrupt:
|
|
26
|
+
break
|
|
27
|
+
verdict = f"{verdict}\t" + "[OK]" if err_cnt == 0 else f"[ERR] {err_cnt}"
|
|
28
|
+
return verdict
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def app(devfid=None, pwd=None):
|
|
32
|
+
global CLIENT
|
|
33
|
+
CLIENT = AppBase(device=devfid, password=pwd)
|
|
34
|
+
report = []
|
|
35
|
+
|
|
36
|
+
state, result = CLIENT.run(['modules'])
|
|
37
|
+
if not state:
|
|
38
|
+
return "Error getting models."
|
|
39
|
+
|
|
40
|
+
if "bme280" in result:
|
|
41
|
+
args = ['bme280 measure']
|
|
42
|
+
report.append(measure(args))
|
|
43
|
+
|
|
44
|
+
if "dht22" in result:
|
|
45
|
+
args = ['dht22 measure']
|
|
46
|
+
report.append(measure(args))
|
|
47
|
+
|
|
48
|
+
if "dht11" in result:
|
|
49
|
+
args = ['dht22 measure']
|
|
50
|
+
report.append(measure(args))
|
|
51
|
+
|
|
52
|
+
if "ds18" in result:
|
|
53
|
+
args = ['ds18 measure']
|
|
54
|
+
report.append(measure(args))
|
|
55
|
+
|
|
56
|
+
print(f"\n======== Sensor test report {CLIENT.get_device()} ========")
|
|
57
|
+
for r in report:
|
|
58
|
+
print(f"\t{r}")
|
|
59
|
+
|
|
60
|
+
if __name__ == "__main__":
|
|
61
|
+
app()
|