meshcore-cli 1.1.37__py3-none-any.whl → 1.1.38__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.
- meshcore_cli/meshcore_cli.py +116 -34
- {meshcore_cli-1.1.37.dist-info → meshcore_cli-1.1.38.dist-info}/METADATA +1 -1
- meshcore_cli-1.1.38.dist-info/RECORD +8 -0
- meshcore_cli-1.1.37.dist-info/RECORD +0 -8
- {meshcore_cli-1.1.37.dist-info → meshcore_cli-1.1.38.dist-info}/WHEEL +0 -0
- {meshcore_cli-1.1.37.dist-info → meshcore_cli-1.1.38.dist-info}/entry_points.txt +0 -0
- {meshcore_cli-1.1.37.dist-info → meshcore_cli-1.1.38.dist-info}/licenses/LICENSE +0 -0
meshcore_cli/meshcore_cli.py
CHANGED
|
@@ -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.38"
|
|
27
27
|
|
|
28
28
|
# default ble address is stored in a config file
|
|
29
29
|
MCCLI_CONFIG_DIR = str(Path.home()) + "/.config/meshcore/"
|
|
@@ -445,6 +445,8 @@ def make_completion_dict(contacts, pending={}, to=None, channels=None):
|
|
|
445
445
|
"upload_contact" : None,
|
|
446
446
|
"path": None,
|
|
447
447
|
"disc_path": None,
|
|
448
|
+
"trace": None,
|
|
449
|
+
"dtrace": None,
|
|
448
450
|
"reset_path" : None,
|
|
449
451
|
"change_path" : None,
|
|
450
452
|
"change_flags" : None,
|
|
@@ -810,6 +812,15 @@ Line starting with \"$\" or \".\" will issue a meshcli command.
|
|
|
810
812
|
await process_cmds(mc, ["cmd", contact["adv_name"], newline])
|
|
811
813
|
except IndexError:
|
|
812
814
|
print("Wrong number of parameters")
|
|
815
|
+
|
|
816
|
+
# trace called on a contact
|
|
817
|
+
elif contact["type"] > 0 and (
|
|
818
|
+
line == "trace" or line == "tr") :
|
|
819
|
+
await print_trace_to(mc, contact)
|
|
820
|
+
|
|
821
|
+
elif contact["type"] > 0 and (
|
|
822
|
+
line == "dtrace" or line == "dt") :
|
|
823
|
+
await print_disc_trace_to(mc, contact)
|
|
813
824
|
|
|
814
825
|
# same but for commands with a parameter
|
|
815
826
|
elif contact["type"] > 0 and (line.startswith("cmd ") or\
|
|
@@ -1064,6 +1075,70 @@ async def get_channels (mc, anim=False) :
|
|
|
1064
1075
|
print (" Done")
|
|
1065
1076
|
return mc.channels
|
|
1066
1077
|
|
|
1078
|
+
async def print_trace_to (mc, contact):
|
|
1079
|
+
path = contact["out_path"]
|
|
1080
|
+
path_len = contact["out_path_len"]
|
|
1081
|
+
trace = ""
|
|
1082
|
+
|
|
1083
|
+
if path_len == -1:
|
|
1084
|
+
print ("No path to destination")
|
|
1085
|
+
return
|
|
1086
|
+
|
|
1087
|
+
if contact["type"] == 2 or contact["type"] == 3:
|
|
1088
|
+
# repeater or room, can trace to the contact itself
|
|
1089
|
+
trace = contact["public_key"][0:2]
|
|
1090
|
+
|
|
1091
|
+
for i in range(0, path_len):
|
|
1092
|
+
elem = path[2*(path_len-i-1):2*(path_len-i)]
|
|
1093
|
+
trace = elem if trace=="" else f"{elem},{trace},{elem}"
|
|
1094
|
+
|
|
1095
|
+
await next_cmd(mc, ["trace", trace])
|
|
1096
|
+
|
|
1097
|
+
async def discover_path(mc, contact):
|
|
1098
|
+
await mc.ensure_contacts()
|
|
1099
|
+
res = await mc.commands.send_path_discovery(contact)
|
|
1100
|
+
if res.type == EventType.ERROR:
|
|
1101
|
+
return None
|
|
1102
|
+
else:
|
|
1103
|
+
timeout = res.payload["suggested_timeout"]/600 if not "timeout" in contact or contact['timeout']==0 else contact["timeout"]
|
|
1104
|
+
res = await mc.wait_for_event(EventType.PATH_RESPONSE, timeout=timeout)
|
|
1105
|
+
if res is None:
|
|
1106
|
+
return {"error": "timeout"}
|
|
1107
|
+
else :
|
|
1108
|
+
return res.payload
|
|
1109
|
+
|
|
1110
|
+
async def print_disc_trace_to (mc, contact):
|
|
1111
|
+
p = await discover_path(mc, contact)
|
|
1112
|
+
if p is None:
|
|
1113
|
+
print("Error discovering path")
|
|
1114
|
+
return
|
|
1115
|
+
|
|
1116
|
+
if "error" in p:
|
|
1117
|
+
print("Timeout discovering path")
|
|
1118
|
+
return
|
|
1119
|
+
|
|
1120
|
+
inp = p["in_path"]
|
|
1121
|
+
outp = p["out_path"]
|
|
1122
|
+
inp_l = int(len(inp)/2)
|
|
1123
|
+
outp_l = int(len(outp)/2)
|
|
1124
|
+
|
|
1125
|
+
trace = ""
|
|
1126
|
+
|
|
1127
|
+
for i in range(0, outp_l):
|
|
1128
|
+
elem = outp[2*i:2*(i+1)]
|
|
1129
|
+
trace = elem if trace == "" else f"{trace},{elem}"
|
|
1130
|
+
|
|
1131
|
+
if contact["type"] == 2 or contact["type"] == 3:
|
|
1132
|
+
# repeater or room, can trace to the contact itself
|
|
1133
|
+
elem = contact["public_key"][0:2]
|
|
1134
|
+
trace = elem if trace == "" else f"{trace},{elem}"
|
|
1135
|
+
|
|
1136
|
+
for i in range(0, inp_l):
|
|
1137
|
+
elem = inp[2*i:2*(i+1)]
|
|
1138
|
+
trace = elem if trace == "" else f"{trace},{elem}"
|
|
1139
|
+
|
|
1140
|
+
await next_cmd(mc, ["trace", trace])
|
|
1141
|
+
|
|
1067
1142
|
async def next_cmd(mc, cmds, json_output=False):
|
|
1068
1143
|
""" process next command """
|
|
1069
1144
|
try :
|
|
@@ -1703,7 +1778,7 @@ async def next_cmd(mc, cmds, json_output=False):
|
|
|
1703
1778
|
print(res.payload)
|
|
1704
1779
|
print(json.dumps(res.payload, indent=4))
|
|
1705
1780
|
|
|
1706
|
-
case "trace" :
|
|
1781
|
+
case "trace" | "tr":
|
|
1707
1782
|
argnum = 1
|
|
1708
1783
|
res = await mc.commands.send_trace(path=cmds[1])
|
|
1709
1784
|
if res and res.type != EventType.ERROR:
|
|
@@ -1716,7 +1791,7 @@ async def next_cmd(mc, cmds, json_output=False):
|
|
|
1716
1791
|
if json_output:
|
|
1717
1792
|
print(json.dumps({"error" : "timeout waiting trace"}))
|
|
1718
1793
|
else :
|
|
1719
|
-
print("Timeout waiting trace")
|
|
1794
|
+
print(f"Timeout waiting trace for path {cmds[1]}")
|
|
1720
1795
|
elif ev.type == EventType.ERROR:
|
|
1721
1796
|
if json_output:
|
|
1722
1797
|
print(json.dumps(ev.payload))
|
|
@@ -1726,18 +1801,26 @@ async def next_cmd(mc, cmds, json_output=False):
|
|
|
1726
1801
|
if json_output:
|
|
1727
1802
|
print(json.dumps(ev.payload, indent=2))
|
|
1728
1803
|
else :
|
|
1804
|
+
classic = interactive_loop.classic or not process_event_message.color
|
|
1729
1805
|
print("]",end="")
|
|
1730
1806
|
for t in ev.payload["path"]:
|
|
1731
|
-
|
|
1807
|
+
if classic :
|
|
1808
|
+
print("→",end="")
|
|
1809
|
+
else:
|
|
1810
|
+
print(f" {ANSI_INVERT}", end="")
|
|
1732
1811
|
snr = t['snr']
|
|
1733
1812
|
if snr >= 10 :
|
|
1734
|
-
print(
|
|
1813
|
+
print(ANSI_BGREEN, end="")
|
|
1735
1814
|
elif snr <= 0:
|
|
1736
|
-
print(
|
|
1815
|
+
print(ANSI_BRED, end="")
|
|
1816
|
+
else :
|
|
1817
|
+
print(ANSI_BGRAY, end="")
|
|
1737
1818
|
print(f"{snr:.2f}",end="")
|
|
1738
|
-
if
|
|
1739
|
-
print(
|
|
1740
|
-
|
|
1819
|
+
if classic :
|
|
1820
|
+
print("→",end="")
|
|
1821
|
+
else :
|
|
1822
|
+
print(f"{ANSI_NORMAL}🭬",end="")
|
|
1823
|
+
print(ANSI_END, end="")
|
|
1741
1824
|
if "hash" in t:
|
|
1742
1825
|
print(f"[{t['hash']}]",end="")
|
|
1743
1826
|
else:
|
|
@@ -1840,26 +1923,19 @@ async def next_cmd(mc, cmds, json_output=False):
|
|
|
1840
1923
|
argnum = 1
|
|
1841
1924
|
await mc.ensure_contacts()
|
|
1842
1925
|
contact = mc.get_contact_by_name(cmds[1])
|
|
1843
|
-
res = await mc
|
|
1844
|
-
|
|
1845
|
-
if res.type == EventType.ERROR:
|
|
1926
|
+
res = await discover_path(mc, contact)
|
|
1927
|
+
if res is None:
|
|
1846
1928
|
print(f"Error while discovering path")
|
|
1847
1929
|
else:
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
print(json.dumps({"error" : "Timeout discovering path"}))
|
|
1854
|
-
else:
|
|
1855
|
-
print("Timeout discovering path")
|
|
1856
|
-
else :
|
|
1857
|
-
if json_output :
|
|
1858
|
-
print(json.dumps(res.payload, indent=4))
|
|
1930
|
+
if json_output :
|
|
1931
|
+
print(json.dumps(res, indent=4))
|
|
1932
|
+
else:
|
|
1933
|
+
if "error" in res :
|
|
1934
|
+
print("Timeout while discovering path")
|
|
1859
1935
|
else:
|
|
1860
|
-
outp = res
|
|
1936
|
+
outp = res['out_path']
|
|
1861
1937
|
outp = outp if outp != "" else "direct"
|
|
1862
|
-
inp = res
|
|
1938
|
+
inp = res['in_path']
|
|
1863
1939
|
inp = inp if inp != "" else "direct"
|
|
1864
1940
|
print(f"Path for {contact['adv_name']}: out {outp}, in {inp}")
|
|
1865
1941
|
|
|
@@ -2054,12 +2130,16 @@ async def next_cmd(mc, cmds, json_output=False):
|
|
|
2054
2130
|
else:
|
|
2055
2131
|
print(f"Unknown contact {cmds[1]}")
|
|
2056
2132
|
else:
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2133
|
+
path = cmds[2].replace(",","") # we'll accept path with ,
|
|
2134
|
+
try:
|
|
2135
|
+
res = await mc.commands.change_contact_path(contact, path)
|
|
2136
|
+
logger.debug(res)
|
|
2137
|
+
if res.type == EventType.ERROR:
|
|
2138
|
+
print(f"Error setting path: {res}")
|
|
2139
|
+
elif json_output :
|
|
2140
|
+
print(json.dumps(res.payload, indent=4))
|
|
2141
|
+
except ValueError:
|
|
2142
|
+
print(f"Bad path format {cmds[2]}")
|
|
2063
2143
|
|
|
2064
2144
|
case "change_flags" | "cf":
|
|
2065
2145
|
argnum = 2
|
|
@@ -2355,9 +2435,11 @@ async def process_script(mc, file, json_output=False):
|
|
|
2355
2435
|
lines=f.readlines()
|
|
2356
2436
|
|
|
2357
2437
|
for line in lines:
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2438
|
+
line = line.strip()
|
|
2439
|
+
if not (line == "" or line[0] == "#"):
|
|
2440
|
+
logger.debug(f"processing {line}")
|
|
2441
|
+
cmds = shlex.split(line)
|
|
2442
|
+
await process_cmds(mc, cmds, json_output)
|
|
2361
2443
|
|
|
2362
2444
|
def version():
|
|
2363
2445
|
print (f"meshcore-cli: command line interface to MeshCore companion radios {VERSION}")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meshcore-cli
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.38
|
|
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
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
meshcore_cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
meshcore_cli/__main__.py,sha256=PfYgibmu2LEtC-OV7L1UgmvV3swJ5rQ4bbXHlwUFlgE,83
|
|
3
|
+
meshcore_cli/meshcore_cli.py,sha256=GlPpqekJDG7eEHAb2KjwP16uI0H4vantFGS26ksxqks,115362
|
|
4
|
+
meshcore_cli-1.1.38.dist-info/METADATA,sha256=nBLa9D9f8TuAE1uTox-nxjLzPpq9o_h41WYf5TKrNPE,11630
|
|
5
|
+
meshcore_cli-1.1.38.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
6
|
+
meshcore_cli-1.1.38.dist-info/entry_points.txt,sha256=77V29Pyth11GteDk7tneBN3MMk8JI7bTlS-BGSmxCmI,103
|
|
7
|
+
meshcore_cli-1.1.38.dist-info/licenses/LICENSE,sha256=F9s987VtS0AKxW7LdB2EkLMkrdeERI7ICdLJR60A9M4,1066
|
|
8
|
+
meshcore_cli-1.1.38.dist-info/RECORD,,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
meshcore_cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
meshcore_cli/__main__.py,sha256=PfYgibmu2LEtC-OV7L1UgmvV3swJ5rQ4bbXHlwUFlgE,83
|
|
3
|
-
meshcore_cli/meshcore_cli.py,sha256=5ydfiMoDCL5kKV2X8j3Sm-8qthjTMtLQjMswk8ZmXyU,112748
|
|
4
|
-
meshcore_cli-1.1.37.dist-info/METADATA,sha256=gLPMzBo0_pHHZPr5IQQL4xpkGl28nJIhxQmO6vvB8II,11630
|
|
5
|
-
meshcore_cli-1.1.37.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
6
|
-
meshcore_cli-1.1.37.dist-info/entry_points.txt,sha256=77V29Pyth11GteDk7tneBN3MMk8JI7bTlS-BGSmxCmI,103
|
|
7
|
-
meshcore_cli-1.1.37.dist-info/licenses/LICENSE,sha256=F9s987VtS0AKxW7LdB2EkLMkrdeERI7ICdLJR60A9M4,1066
|
|
8
|
-
meshcore_cli-1.1.37.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|