meshcore-cli 1.2.6__py3-none-any.whl → 1.2.7__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 +102 -5
- {meshcore_cli-1.2.6.dist-info → meshcore_cli-1.2.7.dist-info}/METADATA +2 -2
- meshcore_cli-1.2.7.dist-info/RECORD +8 -0
- meshcore_cli-1.2.6.dist-info/RECORD +0 -8
- {meshcore_cli-1.2.6.dist-info → meshcore_cli-1.2.7.dist-info}/WHEEL +0 -0
- {meshcore_cli-1.2.6.dist-info → meshcore_cli-1.2.7.dist-info}/entry_points.txt +0 -0
- {meshcore_cli-1.2.6.dist-info → meshcore_cli-1.2.7.dist-info}/licenses/LICENSE +0 -0
meshcore_cli/meshcore_cli.py
CHANGED
|
@@ -33,7 +33,7 @@ import re
|
|
|
33
33
|
from meshcore import MeshCore, EventType, logger
|
|
34
34
|
|
|
35
35
|
# Version
|
|
36
|
-
VERSION = "v1.2.
|
|
36
|
+
VERSION = "v1.2.7"
|
|
37
37
|
|
|
38
38
|
# default ble address is stored in a config file
|
|
39
39
|
MCCLI_CONFIG_DIR = str(Path.home()) + "/.config/meshcore/"
|
|
@@ -451,6 +451,7 @@ def make_completion_dict(contacts, pending={}, to=None, channels=None):
|
|
|
451
451
|
"share_contact" : contact_list,
|
|
452
452
|
"path": contact_list,
|
|
453
453
|
"disc_path" : contact_list,
|
|
454
|
+
"node_discover": {"all":None, "sens":None, "rep":None, "comp":None, "room":None, "cli":None},
|
|
454
455
|
"trace" : None,
|
|
455
456
|
"reset_path" : contact_list,
|
|
456
457
|
"change_path" : contact_list,
|
|
@@ -473,6 +474,7 @@ def make_completion_dict(contacts, pending={}, to=None, channels=None):
|
|
|
473
474
|
"remove_channel": None,
|
|
474
475
|
"apply_to": None,
|
|
475
476
|
"at": None,
|
|
477
|
+
"scope": None,
|
|
476
478
|
"set" : {
|
|
477
479
|
"name" : None,
|
|
478
480
|
"pin" : None,
|
|
@@ -579,6 +581,7 @@ def make_completion_dict(contacts, pending={}, to=None, channels=None):
|
|
|
579
581
|
"neighbors" : None,
|
|
580
582
|
"req_acl":None,
|
|
581
583
|
"setperm":contact_list,
|
|
584
|
+
"region" : {"get":None, "allowf": None, "denyf": None, "put": None, "remove": None, "save": None, "home": None},
|
|
582
585
|
"gps" : {"on":None,"off":None,"sync":None,"setloc":None,
|
|
583
586
|
"advert" : {"none": None, "share": None, "prefs": None},
|
|
584
587
|
},
|
|
@@ -707,6 +710,14 @@ Line starting with \"$\" or \".\" will issue a meshcli command.
|
|
|
707
710
|
contact = to
|
|
708
711
|
prev_contact = None
|
|
709
712
|
|
|
713
|
+
res = await mc.commands.set_flood_scope("0")
|
|
714
|
+
if res is None or res.type == EventType.ERROR:
|
|
715
|
+
scope = None
|
|
716
|
+
prev_scope = None
|
|
717
|
+
else:
|
|
718
|
+
scope = "*"
|
|
719
|
+
prev_scope = "*"
|
|
720
|
+
|
|
710
721
|
await get_contacts(mc, anim=True)
|
|
711
722
|
await get_channels(mc, anim=True)
|
|
712
723
|
await subscribe_to_msgs(mc, above=True)
|
|
@@ -758,6 +769,9 @@ Line starting with \"$\" or \".\" will issue a meshcli command.
|
|
|
758
769
|
if print_name or contact is None :
|
|
759
770
|
prompt = prompt + f"{ANSI_BGRAY}"
|
|
760
771
|
prompt = prompt + f"{mc.self_info['name']}"
|
|
772
|
+
if contact is None: # display scope
|
|
773
|
+
if not scope is None:
|
|
774
|
+
prompt = prompt + f"|{scope}"
|
|
761
775
|
if classic :
|
|
762
776
|
prompt = prompt + " > "
|
|
763
777
|
else :
|
|
@@ -785,6 +799,17 @@ Line starting with \"$\" or \".\" will issue a meshcli command.
|
|
|
785
799
|
prompt = prompt + f"{ANSI_NORMAL}🭨{ANSI_INVERT}"
|
|
786
800
|
|
|
787
801
|
prompt = prompt + f"{contact['adv_name']}"
|
|
802
|
+
if contact["type"] == 0 or contact["out_path_len"]==-1:
|
|
803
|
+
if scope is None:
|
|
804
|
+
prompt = prompt + f"|*"
|
|
805
|
+
else:
|
|
806
|
+
prompt = prompt + f"|{scope}"
|
|
807
|
+
else: # display path to dest or 0 if 0 hop
|
|
808
|
+
if contact["out_path_len"] == 0:
|
|
809
|
+
prompt = prompt + f"|0"
|
|
810
|
+
else:
|
|
811
|
+
prompt = prompt + "|" + contact["out_path"]
|
|
812
|
+
|
|
788
813
|
if classic :
|
|
789
814
|
prompt = prompt + f"{ANSI_NORMAL} > "
|
|
790
815
|
else:
|
|
@@ -823,6 +848,12 @@ Line starting with \"$\" or \".\" will issue a meshcli command.
|
|
|
823
848
|
except ValueError:
|
|
824
849
|
logger.error("Error parsing line {line[1:]}")
|
|
825
850
|
|
|
851
|
+
elif line.startswith("/scope") :
|
|
852
|
+
if not scope is None:
|
|
853
|
+
prev_scope = scope
|
|
854
|
+
newscope = line.split(" ", 1)[1]
|
|
855
|
+
scope = await set_scope(mc, newscope)
|
|
856
|
+
|
|
826
857
|
elif line.startswith("/") :
|
|
827
858
|
path = line.split(" ", 1)[0]
|
|
828
859
|
if path.count("/") == 1:
|
|
@@ -1307,6 +1338,14 @@ msg_ack.max_attempts=3
|
|
|
1307
1338
|
msg_ack.flood_after=2
|
|
1308
1339
|
msg_ack.max_flood_attempts=1
|
|
1309
1340
|
|
|
1341
|
+
async def set_scope (mc, scope) :
|
|
1342
|
+
if scope == "None" or scope == "0" or scope == "clear" or scope == "":
|
|
1343
|
+
scope = "*"
|
|
1344
|
+
res = await mc.commands.set_flood_scope(scope)
|
|
1345
|
+
if res is None or res.type == EventType.ERROR:
|
|
1346
|
+
return None
|
|
1347
|
+
return scope
|
|
1348
|
+
|
|
1310
1349
|
async def get_channel (mc, chan) :
|
|
1311
1350
|
if not chan.isnumeric():
|
|
1312
1351
|
return await get_channel_by_name(mc, chan)
|
|
@@ -2110,8 +2149,8 @@ async def next_cmd(mc, cmds, json_output=False):
|
|
|
2110
2149
|
|
|
2111
2150
|
case "scope":
|
|
2112
2151
|
argnum = 1
|
|
2113
|
-
res = await mc
|
|
2114
|
-
if res is None
|
|
2152
|
+
res = await set_scope(mc, cmds[1])
|
|
2153
|
+
if res is None:
|
|
2115
2154
|
print(f"Error while setting scope")
|
|
2116
2155
|
|
|
2117
2156
|
case "remove_channel":
|
|
@@ -2180,7 +2219,7 @@ async def next_cmd(mc, cmds, json_output=False):
|
|
|
2180
2219
|
argnum = 2
|
|
2181
2220
|
dest = None
|
|
2182
2221
|
|
|
2183
|
-
if len(cmds[1]) == 12: # possibly an hex prefix
|
|
2222
|
+
if len(cmds[1]) == 12: # possibly an hex prefix
|
|
2184
2223
|
try:
|
|
2185
2224
|
dest = bytes.fromhex(cmds[1])
|
|
2186
2225
|
except ValueError:
|
|
@@ -2378,6 +2417,52 @@ async def next_cmd(mc, cmds, json_output=False):
|
|
|
2378
2417
|
inp = inp if inp != "" else "direct"
|
|
2379
2418
|
print(f"Path for {contact['adv_name']}: out {outp}, in {inp}")
|
|
2380
2419
|
|
|
2420
|
+
case "node_discover"|"nd" :
|
|
2421
|
+
argnum = 1
|
|
2422
|
+
try: # try to decode type as int
|
|
2423
|
+
types = int(cmds[1])
|
|
2424
|
+
except ValueError:
|
|
2425
|
+
if "all" in cmds[1]:
|
|
2426
|
+
types = 0xFF
|
|
2427
|
+
else :
|
|
2428
|
+
types = 0
|
|
2429
|
+
if "rep" in cmds[1]:
|
|
2430
|
+
types = types | 4
|
|
2431
|
+
if "cli" in cmds[1] or "comp" in cmds[1]:
|
|
2432
|
+
types = types | 2
|
|
2433
|
+
if "room" in cmds[1]:
|
|
2434
|
+
types = types | 8
|
|
2435
|
+
if "sens" in cmds[1]:
|
|
2436
|
+
types = types | 16
|
|
2437
|
+
|
|
2438
|
+
res = await mc.commands.send_node_discover_req(types)
|
|
2439
|
+
if res is None or res.type == EventType.ERROR:
|
|
2440
|
+
print("Error sending discover request")
|
|
2441
|
+
else:
|
|
2442
|
+
exp_tag = res.payload["tag"].to_bytes(4, "little").hex()
|
|
2443
|
+
dn = []
|
|
2444
|
+
while True:
|
|
2445
|
+
r = await mc.wait_for_event(
|
|
2446
|
+
EventType.DISCOVER_RESPONSE,
|
|
2447
|
+
attribute_filters={"tag":exp_tag},
|
|
2448
|
+
timeout = 5
|
|
2449
|
+
)
|
|
2450
|
+
if r is None or r.type == EventType.ERROR:
|
|
2451
|
+
break
|
|
2452
|
+
else:
|
|
2453
|
+
dn.append(r.payload)
|
|
2454
|
+
|
|
2455
|
+
if json_output:
|
|
2456
|
+
print(json.dumps(dn))
|
|
2457
|
+
else:
|
|
2458
|
+
await mc.ensure_contacts()
|
|
2459
|
+
print(f"Discovered {len(dn)} nodes:")
|
|
2460
|
+
for n in dn:
|
|
2461
|
+
name = mc.get_contact_by_key_prefix(n["pubkey"])['adv_name']
|
|
2462
|
+
if name is None:
|
|
2463
|
+
name = n["pubkey"][0:12]
|
|
2464
|
+
print(f" {name:12} type {n['node_type']} SNR: {n['SNR_in']:6,.2f}->{n['SNR']:6,.2f} RSSI: ->{n['RSSI']:4}")
|
|
2465
|
+
|
|
2381
2466
|
case "req_btelemetry"|"rbt" :
|
|
2382
2467
|
argnum = 1
|
|
2383
2468
|
await mc.ensure_contacts()
|
|
@@ -2931,6 +3016,7 @@ def command_help():
|
|
|
2931
3016
|
time <epoch> : sets time to given epoch
|
|
2932
3017
|
clock : get current time
|
|
2933
3018
|
clock sync : sync device clock st
|
|
3019
|
+
node_discover <filter> : discovers nodes based on their type nd
|
|
2934
3020
|
Contacts
|
|
2935
3021
|
contacts / list : gets contact list lc
|
|
2936
3022
|
reload_contacts : force reloading all contacts rc
|
|
@@ -3004,7 +3090,18 @@ def get_help_for (cmdname, context="line") :
|
|
|
3004
3090
|
at t=2,u>1d,d cn trace
|
|
3005
3091
|
# tries to do flood login to all repeaters
|
|
3006
3092
|
at t=2 rp login
|
|
3007
|
-
|
|
3093
|
+
""")
|
|
3094
|
+
|
|
3095
|
+
if cmdname == "node_discover" or cmdname == "nd" :
|
|
3096
|
+
print("""node_discover <filter> : discovers 0-hop nodes and displays signal info
|
|
3097
|
+
|
|
3098
|
+
filter can be "all" for all types or nodes or a comma separated list consisting of :
|
|
3099
|
+
- cli or comp for companions
|
|
3100
|
+
- rep for repeaters
|
|
3101
|
+
- sens for sensors
|
|
3102
|
+
- room for chat rooms
|
|
3103
|
+
""")
|
|
3104
|
+
|
|
3008
3105
|
else:
|
|
3009
3106
|
print(f"Sorry, no help yet for {cmdname}")
|
|
3010
3107
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meshcore-cli
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.7
|
|
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.
|
|
13
|
+
Requires-Dist: meshcore>=2.1.21
|
|
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=E-zWpvbPyhstbU68BgINMxY6QAIM-tmU7zpPERZ_Xpk,138363
|
|
4
|
+
meshcore_cli-1.2.7.dist-info/METADATA,sha256=m8b_jUfFVeLgGlHOcJZTsSO91lTGdP5Jix-TF0v8W9w,11657
|
|
5
|
+
meshcore_cli-1.2.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
6
|
+
meshcore_cli-1.2.7.dist-info/entry_points.txt,sha256=77V29Pyth11GteDk7tneBN3MMk8JI7bTlS-BGSmxCmI,103
|
|
7
|
+
meshcore_cli-1.2.7.dist-info/licenses/LICENSE,sha256=F9s987VtS0AKxW7LdB2EkLMkrdeERI7ICdLJR60A9M4,1066
|
|
8
|
+
meshcore_cli-1.2.7.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=HrfCnKDBvC-Lni4X4rWlSuBnadmRuVK2f5Z7HK0jHNo,134323
|
|
4
|
-
meshcore_cli-1.2.6.dist-info/METADATA,sha256=rsIFIQm9Ne8Ft-ax8PCGAnfpjymhCNjxVg5z4CRDF7s,11657
|
|
5
|
-
meshcore_cli-1.2.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
6
|
-
meshcore_cli-1.2.6.dist-info/entry_points.txt,sha256=77V29Pyth11GteDk7tneBN3MMk8JI7bTlS-BGSmxCmI,103
|
|
7
|
-
meshcore_cli-1.2.6.dist-info/licenses/LICENSE,sha256=F9s987VtS0AKxW7LdB2EkLMkrdeERI7ICdLJR60A9M4,1066
|
|
8
|
-
meshcore_cli-1.2.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|