meshcore-cli 1.1.35__py3-none-any.whl → 1.1.37__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.
@@ -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.35"
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 print_above(str):
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
- cmds = shlex.split(line)
783
- off = 1 if line.startswith("set perm") else 0
784
- name = cmds[1 + off]
785
- perm_string = cmds[2 + off]
786
- if (perm_string.startswith("0x")):
787
- perm = int(perm_string,0)
788
- elif (perm_string.startswith("#")):
789
- perm = int(perm_string[1:])
790
- else:
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
- key = name
800
- else:
801
- key=ct["public_key"]
802
- newline=f"setperm {key} {perm}"
803
- await process_cmds(mc, ["cmd", contact["adv_name"], newline])
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 clist
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
- mc = await MeshCore.create_ble(address=address, device=device, client=client, debug=debug, only_error=json_output, pin=pin)
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) :
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcore-cli
3
- Version: 1.1.35
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.16
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
@@ -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=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,,
@@ -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=7mojBY8PuNFAxXP41v5MqNilLfbk7_NVaRIvRzvp5AY,109861
4
- meshcore_cli-1.1.35.dist-info/METADATA,sha256=Ap3_J9ur3eF4hAo4FTasLz8hCxnlZlEpIrF52ZpZRzE,11630
5
- meshcore_cli-1.1.35.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
6
- meshcore_cli-1.1.35.dist-info/entry_points.txt,sha256=77V29Pyth11GteDk7tneBN3MMk8JI7bTlS-BGSmxCmI,103
7
- meshcore_cli-1.1.35.dist-info/licenses/LICENSE,sha256=F9s987VtS0AKxW7LdB2EkLMkrdeERI7ICdLJR60A9M4,1066
8
- meshcore_cli-1.1.35.dist-info/RECORD,,