meshcore-cli 1.2.11__py3-none-any.whl → 1.2.13__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.
@@ -4,7 +4,7 @@
4
4
  """
5
5
 
6
6
  import asyncio
7
- import os, sys, io, platform
7
+ import os, sys, io
8
8
  import time, datetime
9
9
  import getopt, json, shlex, re
10
10
  import logging
@@ -32,7 +32,7 @@ import re
32
32
  from meshcore import MeshCore, EventType, logger
33
33
 
34
34
  # Version
35
- VERSION = "v1.2.11"
35
+ VERSION = "v1.2.13"
36
36
 
37
37
  # default ble address is stored in a config file
38
38
  MCCLI_CONFIG_DIR = str(Path.home()) + "/.config/meshcore/"
@@ -76,13 +76,11 @@ ANSI_YELLOW = "\033[0;33m"
76
76
  ANSI_BYELLOW = "\033[1;33m"
77
77
 
78
78
  #Unicode chars
79
- # some possible symbols for prompts 🭬🬛🬗🭬🬛🬃🬗🭬🬛🬃🬗🬏🭀🭋🭨🮋
80
- ARROW_TAIL = "🭨"
81
- ARROW_HEAD = "🭬"
82
-
83
- if platform.system() == 'Windows' or platform.system() == 'Darwin':
84
- ARROW_TAIL = ""
85
- ARROW_HEAD = " "
79
+ # some possible symbols for prompts 🭬🬛🬗🭬🬛🬃🬗🭬🬛🬃🬗🬏🭀🭋🭨🮋
80
+ ARROW_HEAD = ""
81
+ SLASH_END = ""
82
+ SLASH_START = ""
83
+ INVERT_SLASH = False
86
84
 
87
85
  def escape_ansi(line):
88
86
  ansi_escape = re.compile(r'(?:\x1B[@-_]|[\x80-\x9F])[0-?]*[ -/]*[@-~]')
@@ -470,7 +468,7 @@ def make_completion_dict(contacts, pending={}, to=None, channels=None):
470
468
  "login" : contact_list,
471
469
  "cmd" : contact_list,
472
470
  "req_status" : contact_list,
473
- "req_bstatus" : contact_list,
471
+ "req_neighbours": contact_list,
474
472
  "logout" : contact_list,
475
473
  "req_telemetry" : contact_list,
476
474
  "req_binary" : contact_list,
@@ -495,7 +493,6 @@ def make_completion_dict(contacts, pending={}, to=None, channels=None):
495
493
  "print_snr" : {"on":None, "off": None},
496
494
  "json_msgs" : {"on":None, "off": None},
497
495
  "color" : {"on":None, "off":None},
498
- "print_name" : {"on":None, "off":None},
499
496
  "print_adverts" : {"on":None, "off":None},
500
497
  "json_log_rx" : {"on":None, "off":None},
501
498
  "channel_echoes" : {"on":None, "off":None},
@@ -525,7 +522,6 @@ def make_completion_dict(contacts, pending={}, to=None, channels=None):
525
522
  "print_snr":None,
526
523
  "json_msgs":None,
527
524
  "color":None,
528
- "print_name":None,
529
525
  "print_adverts":None,
530
526
  "json_log_rx":None,
531
527
  "channel_echoes":None,
@@ -577,7 +573,7 @@ def make_completion_dict(contacts, pending={}, to=None, channels=None):
577
573
  "login" : None,
578
574
  "logout" : None,
579
575
  "req_status" : None,
580
- "req_bstatus" : None,
576
+ "req_neighbours": None,
581
577
  "cmd" : None,
582
578
  "ver" : None,
583
579
  "advert" : None,
@@ -764,26 +760,32 @@ Line starting with \"$\" or \".\" will issue a meshcli command.
764
760
 
765
761
  color = process_event_message.color
766
762
  classic = interactive_loop.classic or not color
767
- print_name = interactive_loop.print_name
768
763
 
769
764
  if classic:
770
765
  prompt = ""
771
766
  else:
772
767
  prompt = f"{ANSI_INVERT}"
773
768
 
774
- if print_name or contact is None :
775
- if color:
776
- prompt = prompt + f"{ANSI_BGRAY}"
777
- prompt = prompt + f"{mc.self_info['name']}"
778
- if contact is None: # display scope
779
- if not scope is None:
780
- prompt = prompt + f"|{scope}"
769
+ prompt = prompt + f"{ANSI_BGRAY}"
770
+ prompt = prompt + f"{mc.self_info['name']}"
771
+ if contact is None: # display scope
772
+ if not scope is None:
773
+ prompt = prompt + f"|{scope}"
774
+
775
+ if contact is None :
781
776
  if classic :
782
- prompt = prompt + "> "
777
+ prompt = prompt + ">"
783
778
  else :
784
- prompt = prompt + f"{ANSI_NORMAL}{ARROW_HEAD}{ANSI_INVERT}"
785
-
786
- if not contact is None :
779
+ prompt = prompt + f"{ANSI_NORMAL}{ARROW_HEAD}"
780
+ else:
781
+ if classic :
782
+ prompt = prompt + "/"
783
+ else :
784
+ if INVERT_SLASH:
785
+ prompt = prompt + f"{ANSI_INVERT}"
786
+ else:
787
+ prompt = prompt + f"{ANSI_NORMAL}"
788
+ prompt = prompt + f"{SLASH_START}"
787
789
  if not last_ack:
788
790
  prompt = prompt + f"{ANSI_BRED}"
789
791
  if classic :
@@ -799,11 +801,9 @@ Line starting with \"$\" or \".\" will issue a meshcli command.
799
801
  else :
800
802
  prompt = prompt + f"{ANSI_BBLUE}"
801
803
  if not classic:
804
+ prompt = prompt + f"{SLASH_END}"
802
805
  prompt = prompt + f"{ANSI_INVERT}"
803
806
 
804
- if print_name and not classic :
805
- prompt = prompt + f"{ANSI_NORMAL}{ARROW_TAIL}{ANSI_INVERT}"
806
-
807
807
  prompt = prompt + f"{contact['adv_name']}"
808
808
  if contact["type"] == 0 or contact["out_path_len"]==-1:
809
809
  if scope is None:
@@ -817,14 +817,15 @@ Line starting with \"$\" or \".\" will issue a meshcli command.
817
817
  prompt = prompt + "|" + contact["out_path"]
818
818
 
819
819
  if classic :
820
- prompt = prompt + f"{ANSI_NORMAL}> "
820
+ prompt = prompt + f"{ANSI_NORMAL}>"
821
821
  else:
822
822
  prompt = prompt + f"{ANSI_NORMAL}{ARROW_HEAD}"
823
823
 
824
824
  prompt = prompt + f"{ANSI_END}"
825
825
 
826
- if not color :
827
- prompt=escape_ansi(prompt)
826
+ prompt = prompt + " "
827
+ if not color :
828
+ prompt=escape_ansi(prompt)
828
829
 
829
830
  session.app.ttimeoutlen = 0.2
830
831
  session.app.timeoutlen = 0.2
@@ -1036,7 +1037,6 @@ Line starting with \"$\" or \".\" will issue a meshcli command.
1036
1037
  # Handle task cancellation from KeyboardInterrupt in asyncio.run()
1037
1038
  print("Exiting cli")
1038
1039
  interactive_loop.classic = False
1039
- interactive_loop.print_name = True
1040
1040
 
1041
1041
  async def process_contact_chat_line(mc, contact, line):
1042
1042
  if contact["type"] == 0:
@@ -1083,7 +1083,7 @@ async def process_contact_chat_line(mc, contact, line):
1083
1083
  line == "dp" or line == "disc_path" or\
1084
1084
  line == "contact_info" or line == "ci" or\
1085
1085
  line == "req_status" or line == "rs" or\
1086
- line == "req_bstatus" or line == "rbs" or\
1086
+ line == "req_neighbours" or line == "rn" or\
1087
1087
  line == "req_telemetry" or line == "rt" or\
1088
1088
  line == "req_acl" or\
1089
1089
  line == "path" or\
@@ -1613,7 +1613,7 @@ async def print_disc_trace_to (mc, contact):
1613
1613
 
1614
1614
  async def next_cmd(mc, cmds, json_output=False):
1615
1615
  """ process next command """
1616
- global ARROW_TAIL, ARROW_HEAD
1616
+ global ARROW_HEAD, SLASH_START, SLASH_END, INVERT_SLASH
1617
1617
  try :
1618
1618
  argnum = 0
1619
1619
 
@@ -1739,18 +1739,18 @@ async def next_cmd(mc, cmds, json_output=False):
1739
1739
  msg_ack.max_attempts=int(cmds[2])
1740
1740
  case "flood_after":
1741
1741
  msg_ack.flood_after=int(cmds[2])
1742
- case "print_name":
1743
- interactive_loop.print_name = (cmds[2] == "on")
1744
- if json_output :
1745
- print(json.dumps({"cmd" : cmds[1], "param" : cmds[2]}))
1746
1742
  case "classic_prompt":
1747
1743
  interactive_loop.classic = (cmds[2] == "on")
1748
1744
  if json_output :
1749
1745
  print(json.dumps({"cmd" : cmds[1], "param" : cmds[2]}))
1750
- case "arrow_tail":
1751
- ARROW_TAIL = cmds[2]
1752
1746
  case "arrow_head":
1753
1747
  ARROW_HEAD = cmds[2]
1748
+ case "slash_start":
1749
+ SLASH_START = cmds[2]
1750
+ case "slash_end":
1751
+ SLASH_END = cmds[2]
1752
+ case "invert_slash":
1753
+ INVERT_SLASH = cmds[2] == "on"
1754
1754
  case "color" :
1755
1755
  process_event_message.color = (cmds[2] == "on")
1756
1756
  if json_output :
@@ -1981,11 +1981,6 @@ async def next_cmd(mc, cmds, json_output=False):
1981
1981
  print(json.dumps({"flood_after" : msg_ack.flood_after}))
1982
1982
  else:
1983
1983
  print(f"flood_after: {msg_ack.flood_after}")
1984
- case "print_name":
1985
- if json_output :
1986
- print(json.dumps({"print_name" : interactive_loop.print_name}))
1987
- else:
1988
- print(f"{'on' if interactive_loop.print_name else 'off'}")
1989
1984
  case "classic_prompt":
1990
1985
  if json_output :
1991
1986
  print(json.dumps({"classic_prompt" : interactive_loop.classic}))
@@ -2360,7 +2355,7 @@ async def next_cmd(mc, cmds, json_output=False):
2360
2355
  if classic :
2361
2356
  print("→",end="")
2362
2357
  else :
2363
- print(f"{ANSI_NORMAL}{ARROW_HEAD}",end="")
2358
+ print(f"{ANSI_NORMAL}{ARROW_HEAD} ",end="")
2364
2359
  if color:
2365
2360
  print(ANSI_END, end="")
2366
2361
  if "hash" in t:
@@ -2426,46 +2421,6 @@ async def next_cmd(mc, cmds, json_output=False):
2426
2421
  contact = mc.get_contact_by_name(cmds[1])
2427
2422
  contact["timeout"] = float(cmds[2])
2428
2423
 
2429
- case "req_status" | "rs" :
2430
- argnum = 1
2431
- await mc.ensure_contacts()
2432
- contact = mc.get_contact_by_name(cmds[1])
2433
- res = await mc.commands.send_statusreq(contact)
2434
- logger.debug(res)
2435
- if res.type == EventType.ERROR:
2436
- print(f"Error while requesting status: {res}")
2437
- else :
2438
- timeout = res.payload["suggested_timeout"]/800 if not "timeout" in contact or contact['timeout']==0 else contact["timeout"]
2439
- res = await mc.wait_for_event(EventType.STATUS_RESPONSE, timeout=timeout)
2440
- logger.debug(res)
2441
- if res is None:
2442
- if json_output :
2443
- print(json.dumps({"error" : "Timeout waiting status"}))
2444
- else:
2445
- print("Timeout waiting status")
2446
- else :
2447
- print(json.dumps(res.payload, indent=4))
2448
-
2449
- case "req_telemetry" | "rt" :
2450
- argnum = 1
2451
- await mc.ensure_contacts()
2452
- contact = mc.get_contact_by_name(cmds[1])
2453
- res = await mc.commands.send_telemetry_req(contact)
2454
- logger.debug(res)
2455
- if res.type == EventType.ERROR:
2456
- print(f"Error while requesting telemetry")
2457
- else:
2458
- timeout = res.payload["suggested_timeout"]/800 if not "timeout" in contact or contact['timeout']==0 else contact["timeout"]
2459
- res = await mc.wait_for_event(EventType.TELEMETRY_RESPONSE, timeout=timeout)
2460
- logger.debug(res)
2461
- if res is None:
2462
- if json_output :
2463
- print(json.dumps({"error" : "Timeout waiting telemetry"}))
2464
- else:
2465
- print("Timeout waiting telemetry")
2466
- else :
2467
- print(json.dumps(res.payload, indent=4))
2468
-
2469
2424
  case "disc_path" | "dp" :
2470
2425
  argnum = 1
2471
2426
  await mc.ensure_contacts()
@@ -2551,7 +2506,7 @@ async def next_cmd(mc, cmds, json_output=False):
2551
2506
 
2552
2507
  print(f" {name:16} {type:>4} SNR: {n['SNR_in']:6,.2f}->{n['SNR']:6,.2f} RSSI: ->{n['RSSI']:4}")
2553
2508
 
2554
- case "req_btelemetry"|"rbt" :
2509
+ case "req_telemetry"|"rt" :
2555
2510
  argnum = 1
2556
2511
  await mc.ensure_contacts()
2557
2512
  contact = mc.get_contact_by_name(cmds[1])
@@ -2563,9 +2518,13 @@ async def next_cmd(mc, cmds, json_output=False):
2563
2518
  else:
2564
2519
  print("Error getting data")
2565
2520
  else :
2566
- print(json.dumps(res))
2521
+ print(json.dumps({
2522
+ "name": contact["adv_name"],
2523
+ "pubkey_pre": contact["public_key"][0:12],
2524
+ "lpp": res,
2525
+ }, indent = 4))
2567
2526
 
2568
- case "req_bstatus"|"rbs" :
2527
+ case "req_status"|"rs" :
2569
2528
  argnum = 1
2570
2529
  await mc.ensure_contacts()
2571
2530
  contact = mc.get_contact_by_name(cmds[1])
@@ -2634,6 +2593,31 @@ async def next_cmd(mc, cmds, json_output=False):
2634
2593
  name = f"{ct['adv_name']:<20} [{e['key']}]"
2635
2594
  print(f"{name:{' '}<35}: {e['perm']:02x}")
2636
2595
 
2596
+ case "req_neighbours"|"rn" :
2597
+ argnum = 1
2598
+ await mc.ensure_contacts()
2599
+ contact = mc.get_contact_by_name(cmds[1])
2600
+ timeout = 0 if not "timeout" in contact else contact["timeout"]
2601
+ res = await mc.commands.fetch_all_neighbours(contact, timeout=timeout)
2602
+ if res is None :
2603
+ if json_output :
2604
+ print(json.dumps({"error" : "Getting data"}))
2605
+ else:
2606
+ print("Error getting data")
2607
+ else :
2608
+ if json_output:
2609
+ print(json.dumps(res, indent=4))
2610
+ else:
2611
+ print(f"Got {res['results_count']} neighbours out of {res['neighbours_count']} from {contact['adv_name']}:")
2612
+ for n in res['neighbours']:
2613
+ ct = mc.get_contact_by_key_prefix(n["pubkey"])
2614
+ if ct :
2615
+ name = f"[{n['pubkey'][0:8]}] {ct['adv_name']}"
2616
+ else:
2617
+ name = f"[{n['pubkey']}]"
2618
+
2619
+ print(f" {name:30} last viewed {n['secs_ago']} sec ago at {n['snr']} ")
2620
+
2637
2621
  case "req_binary" :
2638
2622
  argnum = 2
2639
2623
  await mc.ensure_contacts()
@@ -3131,6 +3115,7 @@ def command_help():
3131
3115
  cmd <name> <cmd> : sends a command to a repeater (no ack) c [
3132
3116
  wmt8 : wait for a msg (reply) with a timeout ]
3133
3117
  req_status <name> : requests status from a node rs
3118
+ req_neighbours <name> : requests for neighbours in binary form rn
3134
3119
  trace <path> : run a trace, path is comma separated""")
3135
3120
 
3136
3121
  def usage () :
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcore-cli
3
- Version: 1.2.11
3
+ Version: 1.2.13
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.23
13
+ Requires-Dist: meshcore>=2.1.24
14
14
  Requires-Dist: prompt-toolkit>=3.0.50
15
15
  Requires-Dist: pycryptodome
16
16
  Requires-Dist: requests>=2.28.0
@@ -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=f5T9-BokGud7XQoSvuSh-h0bY5bA9UeLudPBTYiuQEo,141172
4
+ meshcore_cli-1.2.13.dist-info/METADATA,sha256=ZrvQ-6jV_2NsHEiUNuTV1mTUq3cjogq37hGDaHjzRhw,11658
5
+ meshcore_cli-1.2.13.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
6
+ meshcore_cli-1.2.13.dist-info/entry_points.txt,sha256=77V29Pyth11GteDk7tneBN3MMk8JI7bTlS-BGSmxCmI,103
7
+ meshcore_cli-1.2.13.dist-info/licenses/LICENSE,sha256=F9s987VtS0AKxW7LdB2EkLMkrdeERI7ICdLJR60A9M4,1066
8
+ meshcore_cli-1.2.13.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=3_pEZET6KLP327yh99zKmRx8a_sfgyx4mVLnT430HP4,142190
4
- meshcore_cli-1.2.11.dist-info/METADATA,sha256=bQTAr3A4YUZ3igdHJD7SgQp3DAPnN20TIVUlD6IKLS0,11658
5
- meshcore_cli-1.2.11.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
6
- meshcore_cli-1.2.11.dist-info/entry_points.txt,sha256=77V29Pyth11GteDk7tneBN3MMk8JI7bTlS-BGSmxCmI,103
7
- meshcore_cli-1.2.11.dist-info/licenses/LICENSE,sha256=F9s987VtS0AKxW7LdB2EkLMkrdeERI7ICdLJR60A9M4,1066
8
- meshcore_cli-1.2.11.dist-info/RECORD,,