meshcore-cli 1.1.37__tar.gz → 1.1.38__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcore-cli
3
- Version: 1.1.37
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
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "meshcore-cli"
7
- version = "1.1.37"
7
+ version = "1.1.38"
8
8
  authors = [
9
9
  { name="Florent de Lamotte", email="florent@frizoncorrea.fr" },
10
10
  ]
@@ -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.37"
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
- print("→",end="")
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(ANSI_GREEN, end="")
1813
+ print(ANSI_BGREEN, end="")
1735
1814
  elif snr <= 0:
1736
- print(ANSI_RED, end="")
1815
+ print(ANSI_BRED, end="")
1816
+ else :
1817
+ print(ANSI_BGRAY, end="")
1737
1818
  print(f"{snr:.2f}",end="")
1738
- if snr >= 10 or snr <= 0:
1739
- print(ANSI_END, end="")
1740
- print("→",end="")
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.commands.send_path_discovery(contact)
1844
- logger.debug(res)
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
- timeout = res.payload["suggested_timeout"]/800 if not "timeout" in contact or contact['timeout']==0 else contact["timeout"]
1849
- res = await mc.wait_for_event(EventType.PATH_RESPONSE, timeout=timeout)
1850
- logger.debug(res)
1851
- if res is None:
1852
- if json_output :
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.payload['out_path']
1936
+ outp = res['out_path']
1861
1937
  outp = outp if outp != "" else "direct"
1862
- inp = res.payload['in_path']
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
- res = await mc.commands.change_contact_path(contact, cmds[2])
2058
- logger.debug(res)
2059
- if res.type == EventType.ERROR:
2060
- print(f"Error setting path: {res}")
2061
- elif json_output :
2062
- print(json.dumps(res.payload, indent=4))
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
- logger.debug(f"processing {line}")
2359
- cmds = shlex.split(line[:-1])
2360
- await process_cmds(mc, cmds, json_output)
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}")
File without changes
File without changes
File without changes
File without changes
File without changes