meshcore-cli 1.1.35__tar.gz → 1.1.37__tar.gz
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.
- {meshcore_cli-1.1.35 → meshcore_cli-1.1.37}/PKG-INFO +2 -2
- {meshcore_cli-1.1.35 → meshcore_cli-1.1.37}/pyproject.toml +2 -2
- {meshcore_cli-1.1.35 → meshcore_cli-1.1.37}/src/meshcore_cli/meshcore_cli.py +86 -26
- {meshcore_cli-1.1.35 → meshcore_cli-1.1.37}/.gitignore +0 -0
- {meshcore_cli-1.1.35 → meshcore_cli-1.1.37}/LICENSE +0 -0
- {meshcore_cli-1.1.35 → meshcore_cli-1.1.37}/README.md +0 -0
- {meshcore_cli-1.1.35 → meshcore_cli-1.1.37}/flake.lock +0 -0
- {meshcore_cli-1.1.35 → meshcore_cli-1.1.37}/flake.nix +0 -0
- {meshcore_cli-1.1.35 → meshcore_cli-1.1.37}/src/meshcore_cli/__init__.py +0 -0
- {meshcore_cli-1.1.35 → meshcore_cli-1.1.37}/src/meshcore_cli/__main__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meshcore-cli
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.37
|
|
4
4
|
Summary: Command line interface to meshcore companion radios
|
|
5
5
|
Project-URL: Homepage, https://github.com/fdlamotte/meshcore-cli
|
|
6
6
|
Project-URL: Issues, https://github.com/fdlamotte/meshcore-cli/issues
|
|
@@ -10,7 +10,7 @@ License-File: LICENSE
|
|
|
10
10
|
Classifier: Operating System :: OS Independent
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
12
12
|
Requires-Python: >=3.10
|
|
13
|
-
Requires-Dist: meshcore>=2.1.
|
|
13
|
+
Requires-Dist: meshcore>=2.1.17
|
|
14
14
|
Requires-Dist: prompt-toolkit>=3.0.50
|
|
15
15
|
Requires-Dist: requests>=2.28.0
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "meshcore-cli"
|
|
7
|
-
version = "1.1.
|
|
7
|
+
version = "1.1.37"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name="Florent de Lamotte", email="florent@frizoncorrea.fr" },
|
|
10
10
|
]
|
|
@@ -17,7 +17,7 @@ classifiers = [
|
|
|
17
17
|
]
|
|
18
18
|
license = "MIT"
|
|
19
19
|
license-files = ["LICEN[CS]E*"]
|
|
20
|
-
dependencies = [ "meshcore >= 2.1.
|
|
20
|
+
dependencies = [ "meshcore >= 2.1.17", "prompt_toolkit >= 3.0.50", "requests >= 2.28.0" ]
|
|
21
21
|
|
|
22
22
|
[project.urls]
|
|
23
23
|
Homepage = "https://github.com/fdlamotte/meshcore-cli"
|
|
@@ -23,7 +23,7 @@ from prompt_toolkit.shortcuts import radiolist_dialog
|
|
|
23
23
|
from meshcore import MeshCore, EventType, logger
|
|
24
24
|
|
|
25
25
|
# Version
|
|
26
|
-
VERSION = "v1.1.
|
|
26
|
+
VERSION = "v1.1.37"
|
|
27
27
|
|
|
28
28
|
# default ble address is stored in a config file
|
|
29
29
|
MCCLI_CONFIG_DIR = str(Path.home()) + "/.config/meshcore/"
|
|
@@ -69,7 +69,7 @@ def escape_ansi(line):
|
|
|
69
69
|
ansi_escape = re.compile(r'(?:\x1B[@-_]|[\x80-\x9F])[0-?]*[ -/]*[@-~]')
|
|
70
70
|
return ansi_escape.sub('', line)
|
|
71
71
|
|
|
72
|
-
def
|
|
72
|
+
def print_one_line_above(str):
|
|
73
73
|
""" prints a string above current line """
|
|
74
74
|
width = os.get_terminal_size().columns
|
|
75
75
|
stringlen = len(escape_ansi(str))-1
|
|
@@ -85,6 +85,11 @@ def print_above(str):
|
|
|
85
85
|
print(str, end="") # Print output status msg
|
|
86
86
|
print("\u001B[u", end="", flush=True) # Jump back to saved cursor position
|
|
87
87
|
|
|
88
|
+
def print_above(str):
|
|
89
|
+
lines = str.split('\n')
|
|
90
|
+
for l in lines:
|
|
91
|
+
print_one_line_above(l)
|
|
92
|
+
|
|
88
93
|
async def process_event_message(mc, ev, json_output, end="\n", above=False):
|
|
89
94
|
""" display incoming message """
|
|
90
95
|
if ev is None :
|
|
@@ -350,6 +355,7 @@ def make_completion_dict(contacts, pending={}, to=None, channels=None):
|
|
|
350
355
|
"share_contact" : contact_list,
|
|
351
356
|
"path": contact_list,
|
|
352
357
|
"disc_path" : contact_list,
|
|
358
|
+
"trace" : None,
|
|
353
359
|
"reset_path" : contact_list,
|
|
354
360
|
"change_path" : contact_list,
|
|
355
361
|
"change_flags" : contact_list,
|
|
@@ -779,28 +785,31 @@ Line starting with \"$\" or \".\" will issue a meshcli command.
|
|
|
779
785
|
# special treatment for setperm to support contact name as param
|
|
780
786
|
elif contact["type"] > 1 and\
|
|
781
787
|
(line.startswith("setperm ") or line.startswith("set perm ")):
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
perm = int(perm_string,16)
|
|
792
|
-
ct=mc.get_contact_by_name(name)
|
|
793
|
-
if ct is None:
|
|
794
|
-
ct=mc.get_contact_by_key_prefix(name)
|
|
795
|
-
if ct is None:
|
|
796
|
-
if name == "self" or mc.self_info["public_key"].startswith(name):
|
|
797
|
-
key = mc.self_info["public_key"]
|
|
788
|
+
try:
|
|
789
|
+
cmds = shlex.split(line)
|
|
790
|
+
off = 1 if line.startswith("set perm") else 0
|
|
791
|
+
name = cmds[1 + off]
|
|
792
|
+
perm_string = cmds[2 + off]
|
|
793
|
+
if (perm_string.startswith("0x")):
|
|
794
|
+
perm = int(perm_string,0)
|
|
795
|
+
elif (perm_string.startswith("#")):
|
|
796
|
+
perm = int(perm_string[1:])
|
|
798
797
|
else:
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
798
|
+
perm = int(perm_string,16)
|
|
799
|
+
ct=mc.get_contact_by_name(name)
|
|
800
|
+
if ct is None:
|
|
801
|
+
ct=mc.get_contact_by_key_prefix(name)
|
|
802
|
+
if ct is None:
|
|
803
|
+
if name == "self" or mc.self_info["public_key"].startswith(name):
|
|
804
|
+
key = mc.self_info["public_key"]
|
|
805
|
+
else:
|
|
806
|
+
key = name
|
|
807
|
+
else:
|
|
808
|
+
key=ct["public_key"]
|
|
809
|
+
newline=f"setperm {key} {perm}"
|
|
810
|
+
await process_cmds(mc, ["cmd", contact["adv_name"], newline])
|
|
811
|
+
except IndexError:
|
|
812
|
+
print("Wrong number of parameters")
|
|
804
813
|
|
|
805
814
|
# same but for commands with a parameter
|
|
806
815
|
elif contact["type"] > 0 and (line.startswith("cmd ") or\
|
|
@@ -1694,6 +1703,46 @@ async def next_cmd(mc, cmds, json_output=False):
|
|
|
1694
1703
|
print(res.payload)
|
|
1695
1704
|
print(json.dumps(res.payload, indent=4))
|
|
1696
1705
|
|
|
1706
|
+
case "trace" :
|
|
1707
|
+
argnum = 1
|
|
1708
|
+
res = await mc.commands.send_trace(path=cmds[1])
|
|
1709
|
+
if res and res.type != EventType.ERROR:
|
|
1710
|
+
tag= int.from_bytes(res.payload['expected_ack'], byteorder="little")
|
|
1711
|
+
timeout = res.payload["suggested_timeout"] / 1000 * 1.2
|
|
1712
|
+
ev = await mc.wait_for_event(EventType.TRACE_DATA,
|
|
1713
|
+
attribute_filters={"tag": tag},
|
|
1714
|
+
timeout=timeout)
|
|
1715
|
+
if ev is None:
|
|
1716
|
+
if json_output:
|
|
1717
|
+
print(json.dumps({"error" : "timeout waiting trace"}))
|
|
1718
|
+
else :
|
|
1719
|
+
print("Timeout waiting trace")
|
|
1720
|
+
elif ev.type == EventType.ERROR:
|
|
1721
|
+
if json_output:
|
|
1722
|
+
print(json.dumps(ev.payload))
|
|
1723
|
+
else :
|
|
1724
|
+
print("Error waiting trace")
|
|
1725
|
+
else:
|
|
1726
|
+
if json_output:
|
|
1727
|
+
print(json.dumps(ev.payload, indent=2))
|
|
1728
|
+
else :
|
|
1729
|
+
print("]",end="")
|
|
1730
|
+
for t in ev.payload["path"]:
|
|
1731
|
+
print("→",end="")
|
|
1732
|
+
snr = t['snr']
|
|
1733
|
+
if snr >= 10 :
|
|
1734
|
+
print(ANSI_GREEN, end="")
|
|
1735
|
+
elif snr <= 0:
|
|
1736
|
+
print(ANSI_RED, end="")
|
|
1737
|
+
print(f"{snr:.2f}",end="")
|
|
1738
|
+
if snr >= 10 or snr <= 0:
|
|
1739
|
+
print(ANSI_END, end="")
|
|
1740
|
+
print("→",end="")
|
|
1741
|
+
if "hash" in t:
|
|
1742
|
+
print(f"[{t['hash']}]",end="")
|
|
1743
|
+
else:
|
|
1744
|
+
print("[")
|
|
1745
|
+
|
|
1697
1746
|
case "login" | "l" :
|
|
1698
1747
|
argnum = 2
|
|
1699
1748
|
await mc.ensure_contacts()
|
|
@@ -2356,6 +2405,7 @@ def command_help():
|
|
|
2356
2405
|
import_contact <URI> : import a contact from its URI ic
|
|
2357
2406
|
remove_contact <ct> : removes a contact from this node
|
|
2358
2407
|
path <ct> : diplays path for a contact
|
|
2408
|
+
disc_path <ct> : discover new path and display dp
|
|
2359
2409
|
reset_path <ct> : resets path to a contact to flood rp
|
|
2360
2410
|
change_path <ct> <pth> : change the path to a contact cp
|
|
2361
2411
|
change_flags <ct> <f> : change contact flags (tel_l|tel_a|star)cf
|
|
@@ -2364,13 +2414,14 @@ def command_help():
|
|
|
2364
2414
|
req_acl <ct> : requests access control list for sensor
|
|
2365
2415
|
pending_contacts : show pending contacts
|
|
2366
2416
|
add_pending <key> : manually add pending contact from key
|
|
2367
|
-
flush_pending : flush pending contact
|
|
2417
|
+
flush_pending : flush pending contact list
|
|
2368
2418
|
Repeaters
|
|
2369
2419
|
login <name> <pwd> : log into a node (rep) with given pwd l
|
|
2370
2420
|
logout <name> : log out of a repeater
|
|
2371
2421
|
cmd <name> <cmd> : sends a command to a repeater (no ack) c [
|
|
2372
2422
|
wmt8 : wait for a msg (reply) with a timeout ]
|
|
2373
|
-
req_status <name> : requests status from a node rs
|
|
2423
|
+
req_status <name> : requests status from a node rs
|
|
2424
|
+
trace <path> : run a trace, path is comma separated""")
|
|
2374
2425
|
|
|
2375
2426
|
def usage () :
|
|
2376
2427
|
""" Prints some help """
|
|
@@ -2528,7 +2579,16 @@ async def main(argv):
|
|
|
2528
2579
|
logger.info(f"Couldn't find device {address}")
|
|
2529
2580
|
return
|
|
2530
2581
|
|
|
2531
|
-
|
|
2582
|
+
try :
|
|
2583
|
+
mc = await MeshCore.create_ble(address=address, device=device, client=client, debug=debug, only_error=json_output, pin=pin)
|
|
2584
|
+
except ConnectionError :
|
|
2585
|
+
logger.info("Error while connecting, retrying once ...")
|
|
2586
|
+
try :
|
|
2587
|
+
mc = await MeshCore.create_ble(address=address, device=device, client=client, debug=debug, only_error=json_output, pin=pin)
|
|
2588
|
+
except ConnectionError :
|
|
2589
|
+
logger.error("Can't connect to node, exiting")
|
|
2590
|
+
return
|
|
2591
|
+
|
|
2532
2592
|
|
|
2533
2593
|
# Store device address in configuration
|
|
2534
2594
|
if os.path.isdir(MCCLI_CONFIG_DIR) :
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|