meshcore-cli 1.2.12__tar.gz → 1.2.13__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.2.12 → meshcore_cli-1.2.13}/PKG-INFO +1 -1
- {meshcore_cli-1.2.12 → meshcore_cli-1.2.13}/pyproject.toml +1 -1
- {meshcore_cli-1.2.12 → meshcore_cli-1.2.13}/src/meshcore_cli/meshcore_cli.py +46 -89
- {meshcore_cli-1.2.12 → meshcore_cli-1.2.13}/.gitignore +0 -0
- {meshcore_cli-1.2.12 → meshcore_cli-1.2.13}/LICENSE +0 -0
- {meshcore_cli-1.2.12 → meshcore_cli-1.2.13}/PXL_20251107_184348511.jpg +0 -0
- {meshcore_cli-1.2.12 → meshcore_cli-1.2.13}/README.md +0 -0
- {meshcore_cli-1.2.12 → meshcore_cli-1.2.13}/flake.lock +0 -0
- {meshcore_cli-1.2.12 → meshcore_cli-1.2.13}/flake.nix +0 -0
- {meshcore_cli-1.2.12 → meshcore_cli-1.2.13}/src/meshcore_cli/__init__.py +0 -0
- {meshcore_cli-1.2.12 → meshcore_cli-1.2.13}/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.2.
|
|
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
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
import asyncio
|
|
7
|
-
import os, sys, io
|
|
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.
|
|
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
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
-
"
|
|
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,6 @@ 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,
|
|
581
576
|
"req_neighbours": None,
|
|
582
577
|
"cmd" : None,
|
|
583
578
|
"ver" : None,
|
|
@@ -765,26 +760,32 @@ Line starting with \"$\" or \".\" will issue a meshcli command.
|
|
|
765
760
|
|
|
766
761
|
color = process_event_message.color
|
|
767
762
|
classic = interactive_loop.classic or not color
|
|
768
|
-
print_name = interactive_loop.print_name
|
|
769
763
|
|
|
770
764
|
if classic:
|
|
771
765
|
prompt = ""
|
|
772
766
|
else:
|
|
773
767
|
prompt = f"{ANSI_INVERT}"
|
|
774
768
|
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
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 :
|
|
782
776
|
if classic :
|
|
783
|
-
prompt = prompt + ">
|
|
777
|
+
prompt = prompt + ">"
|
|
784
778
|
else :
|
|
785
|
-
prompt = prompt + f"{ANSI_NORMAL}{ARROW_HEAD}
|
|
786
|
-
|
|
787
|
-
|
|
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}"
|
|
788
789
|
if not last_ack:
|
|
789
790
|
prompt = prompt + f"{ANSI_BRED}"
|
|
790
791
|
if classic :
|
|
@@ -800,11 +801,9 @@ Line starting with \"$\" or \".\" will issue a meshcli command.
|
|
|
800
801
|
else :
|
|
801
802
|
prompt = prompt + f"{ANSI_BBLUE}"
|
|
802
803
|
if not classic:
|
|
804
|
+
prompt = prompt + f"{SLASH_END}"
|
|
803
805
|
prompt = prompt + f"{ANSI_INVERT}"
|
|
804
806
|
|
|
805
|
-
if print_name and not classic :
|
|
806
|
-
prompt = prompt + f"{ANSI_NORMAL}{ARROW_TAIL}{ANSI_INVERT}"
|
|
807
|
-
|
|
808
807
|
prompt = prompt + f"{contact['adv_name']}"
|
|
809
808
|
if contact["type"] == 0 or contact["out_path_len"]==-1:
|
|
810
809
|
if scope is None:
|
|
@@ -818,14 +817,15 @@ Line starting with \"$\" or \".\" will issue a meshcli command.
|
|
|
818
817
|
prompt = prompt + "|" + contact["out_path"]
|
|
819
818
|
|
|
820
819
|
if classic :
|
|
821
|
-
prompt = prompt + f"{ANSI_NORMAL}>
|
|
820
|
+
prompt = prompt + f"{ANSI_NORMAL}>"
|
|
822
821
|
else:
|
|
823
822
|
prompt = prompt + f"{ANSI_NORMAL}{ARROW_HEAD}"
|
|
824
823
|
|
|
825
824
|
prompt = prompt + f"{ANSI_END}"
|
|
826
825
|
|
|
827
|
-
|
|
828
|
-
|
|
826
|
+
prompt = prompt + " "
|
|
827
|
+
if not color :
|
|
828
|
+
prompt=escape_ansi(prompt)
|
|
829
829
|
|
|
830
830
|
session.app.ttimeoutlen = 0.2
|
|
831
831
|
session.app.timeoutlen = 0.2
|
|
@@ -1037,7 +1037,6 @@ Line starting with \"$\" or \".\" will issue a meshcli command.
|
|
|
1037
1037
|
# Handle task cancellation from KeyboardInterrupt in asyncio.run()
|
|
1038
1038
|
print("Exiting cli")
|
|
1039
1039
|
interactive_loop.classic = False
|
|
1040
|
-
interactive_loop.print_name = True
|
|
1041
1040
|
|
|
1042
1041
|
async def process_contact_chat_line(mc, contact, line):
|
|
1043
1042
|
if contact["type"] == 0:
|
|
@@ -1085,7 +1084,6 @@ async def process_contact_chat_line(mc, contact, line):
|
|
|
1085
1084
|
line == "contact_info" or line == "ci" or\
|
|
1086
1085
|
line == "req_status" or line == "rs" or\
|
|
1087
1086
|
line == "req_neighbours" or line == "rn" or\
|
|
1088
|
-
line == "req_bstatus" or line == "rbs" or\
|
|
1089
1087
|
line == "req_telemetry" or line == "rt" or\
|
|
1090
1088
|
line == "req_acl" or\
|
|
1091
1089
|
line == "path" or\
|
|
@@ -1615,7 +1613,7 @@ async def print_disc_trace_to (mc, contact):
|
|
|
1615
1613
|
|
|
1616
1614
|
async def next_cmd(mc, cmds, json_output=False):
|
|
1617
1615
|
""" process next command """
|
|
1618
|
-
global
|
|
1616
|
+
global ARROW_HEAD, SLASH_START, SLASH_END, INVERT_SLASH
|
|
1619
1617
|
try :
|
|
1620
1618
|
argnum = 0
|
|
1621
1619
|
|
|
@@ -1741,18 +1739,18 @@ async def next_cmd(mc, cmds, json_output=False):
|
|
|
1741
1739
|
msg_ack.max_attempts=int(cmds[2])
|
|
1742
1740
|
case "flood_after":
|
|
1743
1741
|
msg_ack.flood_after=int(cmds[2])
|
|
1744
|
-
case "print_name":
|
|
1745
|
-
interactive_loop.print_name = (cmds[2] == "on")
|
|
1746
|
-
if json_output :
|
|
1747
|
-
print(json.dumps({"cmd" : cmds[1], "param" : cmds[2]}))
|
|
1748
1742
|
case "classic_prompt":
|
|
1749
1743
|
interactive_loop.classic = (cmds[2] == "on")
|
|
1750
1744
|
if json_output :
|
|
1751
1745
|
print(json.dumps({"cmd" : cmds[1], "param" : cmds[2]}))
|
|
1752
|
-
case "arrow_tail":
|
|
1753
|
-
ARROW_TAIL = cmds[2]
|
|
1754
1746
|
case "arrow_head":
|
|
1755
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"
|
|
1756
1754
|
case "color" :
|
|
1757
1755
|
process_event_message.color = (cmds[2] == "on")
|
|
1758
1756
|
if json_output :
|
|
@@ -1983,11 +1981,6 @@ async def next_cmd(mc, cmds, json_output=False):
|
|
|
1983
1981
|
print(json.dumps({"flood_after" : msg_ack.flood_after}))
|
|
1984
1982
|
else:
|
|
1985
1983
|
print(f"flood_after: {msg_ack.flood_after}")
|
|
1986
|
-
case "print_name":
|
|
1987
|
-
if json_output :
|
|
1988
|
-
print(json.dumps({"print_name" : interactive_loop.print_name}))
|
|
1989
|
-
else:
|
|
1990
|
-
print(f"{'on' if interactive_loop.print_name else 'off'}")
|
|
1991
1984
|
case "classic_prompt":
|
|
1992
1985
|
if json_output :
|
|
1993
1986
|
print(json.dumps({"classic_prompt" : interactive_loop.classic}))
|
|
@@ -2362,7 +2355,7 @@ async def next_cmd(mc, cmds, json_output=False):
|
|
|
2362
2355
|
if classic :
|
|
2363
2356
|
print("→",end="")
|
|
2364
2357
|
else :
|
|
2365
|
-
print(f"{ANSI_NORMAL}{ARROW_HEAD}",end="")
|
|
2358
|
+
print(f"{ANSI_NORMAL}{ARROW_HEAD} ",end="")
|
|
2366
2359
|
if color:
|
|
2367
2360
|
print(ANSI_END, end="")
|
|
2368
2361
|
if "hash" in t:
|
|
@@ -2428,46 +2421,6 @@ async def next_cmd(mc, cmds, json_output=False):
|
|
|
2428
2421
|
contact = mc.get_contact_by_name(cmds[1])
|
|
2429
2422
|
contact["timeout"] = float(cmds[2])
|
|
2430
2423
|
|
|
2431
|
-
case "req_status" | "rs" :
|
|
2432
|
-
argnum = 1
|
|
2433
|
-
await mc.ensure_contacts()
|
|
2434
|
-
contact = mc.get_contact_by_name(cmds[1])
|
|
2435
|
-
res = await mc.commands.send_statusreq(contact)
|
|
2436
|
-
logger.debug(res)
|
|
2437
|
-
if res.type == EventType.ERROR:
|
|
2438
|
-
print(f"Error while requesting status: {res}")
|
|
2439
|
-
else :
|
|
2440
|
-
timeout = res.payload["suggested_timeout"]/800 if not "timeout" in contact or contact['timeout']==0 else contact["timeout"]
|
|
2441
|
-
res = await mc.wait_for_event(EventType.STATUS_RESPONSE, timeout=timeout)
|
|
2442
|
-
logger.debug(res)
|
|
2443
|
-
if res is None:
|
|
2444
|
-
if json_output :
|
|
2445
|
-
print(json.dumps({"error" : "Timeout waiting status"}))
|
|
2446
|
-
else:
|
|
2447
|
-
print("Timeout waiting status")
|
|
2448
|
-
else :
|
|
2449
|
-
print(json.dumps(res.payload, indent=4))
|
|
2450
|
-
|
|
2451
|
-
case "req_telemetry" | "rt" :
|
|
2452
|
-
argnum = 1
|
|
2453
|
-
await mc.ensure_contacts()
|
|
2454
|
-
contact = mc.get_contact_by_name(cmds[1])
|
|
2455
|
-
res = await mc.commands.send_telemetry_req(contact)
|
|
2456
|
-
logger.debug(res)
|
|
2457
|
-
if res.type == EventType.ERROR:
|
|
2458
|
-
print(f"Error while requesting telemetry")
|
|
2459
|
-
else:
|
|
2460
|
-
timeout = res.payload["suggested_timeout"]/800 if not "timeout" in contact or contact['timeout']==0 else contact["timeout"]
|
|
2461
|
-
res = await mc.wait_for_event(EventType.TELEMETRY_RESPONSE, timeout=timeout)
|
|
2462
|
-
logger.debug(res)
|
|
2463
|
-
if res is None:
|
|
2464
|
-
if json_output :
|
|
2465
|
-
print(json.dumps({"error" : "Timeout waiting telemetry"}))
|
|
2466
|
-
else:
|
|
2467
|
-
print("Timeout waiting telemetry")
|
|
2468
|
-
else :
|
|
2469
|
-
print(json.dumps(res.payload, indent=4))
|
|
2470
|
-
|
|
2471
2424
|
case "disc_path" | "dp" :
|
|
2472
2425
|
argnum = 1
|
|
2473
2426
|
await mc.ensure_contacts()
|
|
@@ -2553,7 +2506,7 @@ async def next_cmd(mc, cmds, json_output=False):
|
|
|
2553
2506
|
|
|
2554
2507
|
print(f" {name:16} {type:>4} SNR: {n['SNR_in']:6,.2f}->{n['SNR']:6,.2f} RSSI: ->{n['RSSI']:4}")
|
|
2555
2508
|
|
|
2556
|
-
case "
|
|
2509
|
+
case "req_telemetry"|"rt" :
|
|
2557
2510
|
argnum = 1
|
|
2558
2511
|
await mc.ensure_contacts()
|
|
2559
2512
|
contact = mc.get_contact_by_name(cmds[1])
|
|
@@ -2565,9 +2518,13 @@ async def next_cmd(mc, cmds, json_output=False):
|
|
|
2565
2518
|
else:
|
|
2566
2519
|
print("Error getting data")
|
|
2567
2520
|
else :
|
|
2568
|
-
print(json.dumps(
|
|
2521
|
+
print(json.dumps({
|
|
2522
|
+
"name": contact["adv_name"],
|
|
2523
|
+
"pubkey_pre": contact["public_key"][0:12],
|
|
2524
|
+
"lpp": res,
|
|
2525
|
+
}, indent = 4))
|
|
2569
2526
|
|
|
2570
|
-
case "
|
|
2527
|
+
case "req_status"|"rs" :
|
|
2571
2528
|
argnum = 1
|
|
2572
2529
|
await mc.ensure_contacts()
|
|
2573
2530
|
contact = mc.get_contact_by_name(cmds[1])
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|