meshcore-cli 1.3.0__tar.gz → 1.3.2__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.3.0 → meshcore_cli-1.3.2}/PKG-INFO +14 -2
- {meshcore_cli-1.3.0 → meshcore_cli-1.3.2}/README.md +12 -0
- {meshcore_cli-1.3.0 → meshcore_cli-1.3.2}/pyproject.toml +2 -2
- {meshcore_cli-1.3.0 → meshcore_cli-1.3.2}/src/meshcore_cli/meshcore_cli.py +141 -45
- {meshcore_cli-1.3.0 → meshcore_cli-1.3.2}/.gitignore +0 -0
- {meshcore_cli-1.3.0 → meshcore_cli-1.3.2}/LICENSE +0 -0
- {meshcore_cli-1.3.0 → meshcore_cli-1.3.2}/flake.lock +0 -0
- {meshcore_cli-1.3.0 → meshcore_cli-1.3.2}/flake.nix +0 -0
- {meshcore_cli-1.3.0 → meshcore_cli-1.3.2}/src/meshcore_cli/__init__.py +0 -0
- {meshcore_cli-1.3.0 → meshcore_cli-1.3.2}/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.3.
|
|
3
|
+
Version: 1.3.2
|
|
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.
|
|
13
|
+
Requires-Dist: meshcore>=2.2.0
|
|
14
14
|
Requires-Dist: prompt-toolkit>=3.0.50
|
|
15
15
|
Requires-Dist: pycryptodome
|
|
16
16
|
Requires-Dist: requests>=2.28.0
|
|
@@ -198,6 +198,18 @@ f1down/#fdl|*> 8
|
|
|
198
198
|
#fdl f1down: 8 [2521] 1.00-109
|
|
199
199
|
```
|
|
200
200
|
|
|
201
|
+
### Contact management
|
|
202
|
+
|
|
203
|
+
To receive a message from another user, it is necessary to have its public key. This key is stored on a contact list in the device, and this list has a finite size (50 when meshcore started, now over 350 for most devices).
|
|
204
|
+
|
|
205
|
+
By default contacts are automatically added to the device contact list when an advertisement is received, so as soon as you receive an advert, you can talk with your buddy.
|
|
206
|
+
|
|
207
|
+
With growing number of users, it becomes necessary to manage contact list and one of the ways is to add contacts manually to the device. This is done by turning on `manual_add_contacts`. Once this option has been turned on, a pending list is built by meshcore-cli from the received adverts. You can view the list issuing a `pending_contacts` command, flush the list using `flush_pending` or add a contact from the list with `add_pending` followed by the key of the contact or its name (both will be auto-completed with tab).
|
|
208
|
+
|
|
209
|
+
This feature only really works in interactive mode.
|
|
210
|
+
|
|
211
|
+
Note: There is also an `auto_update_contacts` setting that has nothing to do with adding contacts, it permits to automatically sync contact lists between device and meshcore-cli (when there is an update in name, location or path).
|
|
212
|
+
|
|
201
213
|
### Issuing batch commands to contacts with apply to
|
|
202
214
|
|
|
203
215
|
`apply_to <f> <cmd>` : applies cmd to contacts matching filter `<f>` it can be used to apply the same command to a pool of repeaters, or remove some contacts matching a condition.
|
|
@@ -180,6 +180,18 @@ f1down/#fdl|*> 8
|
|
|
180
180
|
#fdl f1down: 8 [2521] 1.00-109
|
|
181
181
|
```
|
|
182
182
|
|
|
183
|
+
### Contact management
|
|
184
|
+
|
|
185
|
+
To receive a message from another user, it is necessary to have its public key. This key is stored on a contact list in the device, and this list has a finite size (50 when meshcore started, now over 350 for most devices).
|
|
186
|
+
|
|
187
|
+
By default contacts are automatically added to the device contact list when an advertisement is received, so as soon as you receive an advert, you can talk with your buddy.
|
|
188
|
+
|
|
189
|
+
With growing number of users, it becomes necessary to manage contact list and one of the ways is to add contacts manually to the device. This is done by turning on `manual_add_contacts`. Once this option has been turned on, a pending list is built by meshcore-cli from the received adverts. You can view the list issuing a `pending_contacts` command, flush the list using `flush_pending` or add a contact from the list with `add_pending` followed by the key of the contact or its name (both will be auto-completed with tab).
|
|
190
|
+
|
|
191
|
+
This feature only really works in interactive mode.
|
|
192
|
+
|
|
193
|
+
Note: There is also an `auto_update_contacts` setting that has nothing to do with adding contacts, it permits to automatically sync contact lists between device and meshcore-cli (when there is an update in name, location or path).
|
|
194
|
+
|
|
183
195
|
### Issuing batch commands to contacts with apply to
|
|
184
196
|
|
|
185
197
|
`apply_to <f> <cmd>` : applies cmd to contacts matching filter `<f>` it can be used to apply the same command to a pool of repeaters, or remove some contacts matching a condition.
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "meshcore-cli"
|
|
7
|
-
version = "1.3.
|
|
7
|
+
version = "1.3.2"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name="Florent de Lamotte", email="florent@frizoncorrea.fr" },
|
|
10
10
|
]
|
|
@@ -17,7 +17,7 @@ classifiers = [
|
|
|
17
17
|
]
|
|
18
18
|
license = "MIT"
|
|
19
19
|
license-files = ["LICEN[CS]E*"]
|
|
20
|
-
dependencies = [ "meshcore >= 2.
|
|
20
|
+
dependencies = [ "meshcore >= 2.2.0", "prompt_toolkit >= 3.0.50", "requests >= 2.28.0", "pycryptodome" ]
|
|
21
21
|
|
|
22
22
|
[project.urls]
|
|
23
23
|
Homepage = "https://github.com/fdlamotte/meshcore-cli"
|
|
@@ -32,7 +32,7 @@ import re
|
|
|
32
32
|
from meshcore import MeshCore, EventType, logger
|
|
33
33
|
|
|
34
34
|
# Version
|
|
35
|
-
VERSION = "v1.3.
|
|
35
|
+
VERSION = "v1.3.2"
|
|
36
36
|
|
|
37
37
|
# default ble address is stored in a config file
|
|
38
38
|
MCCLI_CONFIG_DIR = str(Path.home()) + "/.config/meshcore/"
|
|
@@ -40,6 +40,10 @@ MCCLI_ADDRESS = MCCLI_CONFIG_DIR + "default_address"
|
|
|
40
40
|
MCCLI_HISTORY_FILE = MCCLI_CONFIG_DIR + "history"
|
|
41
41
|
MCCLI_INIT_SCRIPT = MCCLI_CONFIG_DIR + "init"
|
|
42
42
|
|
|
43
|
+
PAYLOAD_TYPENAMES = ["REQ", "RESPONSE", "TEXT_MSG", "ACK", "ADVERT", "GRP_TXT", "GRP_DATA", "ANON_REQ", "PATH", "TRACE", "MULTIPART", "CONTROL"]
|
|
44
|
+
ROUTE_TYPENAMES = ["TC_FLOOD", "FLOOD", "DIRECT", "TC_DIRECT"]
|
|
45
|
+
CONTACT_TYPENAMES = ["NONE","CLI","REP","ROOM","SENS"]
|
|
46
|
+
|
|
43
47
|
# Fallback address if config file not found
|
|
44
48
|
# if None or "" then a scan is performed
|
|
45
49
|
ADDRESS = ""
|
|
@@ -203,9 +207,6 @@ process_event_message.print_snr=False
|
|
|
203
207
|
process_event_message.color=True
|
|
204
208
|
process_event_message.last_node=None
|
|
205
209
|
|
|
206
|
-
PAYLOAD_TYPENAMES = ["REQ", "RESPONSE", "TEXT_MSG", "ACK", "ADVERT", "GRP_TXT", "GRP_DATA", "ANON_REQ", "PATH", "TRACE", "MULTIPART", "CONTROL"]
|
|
207
|
-
ROUTE_TYPENAMES = ["TC_FLOOD", "FLOOD", "DIRECT", "TC_DIRECT"]
|
|
208
|
-
|
|
209
210
|
async def handle_log_rx(event):
|
|
210
211
|
mc = handle_log_rx.mc
|
|
211
212
|
|
|
@@ -284,7 +285,7 @@ async def handle_log_rx(event):
|
|
|
284
285
|
if chan_name != "" :
|
|
285
286
|
width = os.get_terminal_size().columns
|
|
286
287
|
cars = width - 13 - 2 * path_len - len(chan_name) - 1
|
|
287
|
-
dispmsg = message[0:cars]
|
|
288
|
+
dispmsg = message.replace("\n","")[0:cars]
|
|
288
289
|
txt = f"{ANSI_LIGHT_GRAY}{chan_name} {ANSI_DGREEN}{dispmsg+(cars-len(dispmsg))*' '} {ANSI_YELLOW}[{path}]{ANSI_LIGHT_GRAY}{event.payload['snr']:6,.2f}{event.payload['rssi']:4}{ANSI_END}"
|
|
289
290
|
if handle_message.above:
|
|
290
291
|
print_above(txt)
|
|
@@ -431,7 +432,7 @@ class MyNestedCompleter(NestedCompleter):
|
|
|
431
432
|
opts = self.options.keys()
|
|
432
433
|
completer = WordCompleter(
|
|
433
434
|
opts, ignore_case=self.ignore_case,
|
|
434
|
-
pattern=re.compile(r"([a-zA-Z0-9_
|
|
435
|
+
pattern=re.compile(r"([a-zA-Z0-9_\\/\#\?]+|[^a-zA-Z0-9_\s\#\?]+)"))
|
|
435
436
|
yield from completer.get_completions(document, complete_event)
|
|
436
437
|
else: # normal behavior for remainder
|
|
437
438
|
yield from super().get_completions(document, complete_event)
|
|
@@ -582,11 +583,24 @@ def make_completion_dict(contacts, pending={}, to=None, channels=None):
|
|
|
582
583
|
"flood_after":None,
|
|
583
584
|
"custom":None,
|
|
584
585
|
},
|
|
586
|
+
"?get":None,
|
|
587
|
+
"?set":None,
|
|
588
|
+
"?scope":None,
|
|
589
|
+
"?contact_info":None,
|
|
590
|
+
"?apply_to":None,
|
|
591
|
+
"?at":None,
|
|
592
|
+
"?node_discover":None,
|
|
593
|
+
"?nd":None,
|
|
594
|
+
"?pending_contacts":None,
|
|
595
|
+
"?add_pending":None,
|
|
596
|
+
"?flush_pending":None,
|
|
585
597
|
}
|
|
586
598
|
|
|
587
599
|
contact_completion_list = {
|
|
588
600
|
"contact_info": None,
|
|
589
601
|
"contact_name": None,
|
|
602
|
+
"contact_key": None,
|
|
603
|
+
"contact_type": None,
|
|
590
604
|
"contact_lastmod": None,
|
|
591
605
|
"export_contact" : None,
|
|
592
606
|
"share_contact" : None,
|
|
@@ -749,7 +763,7 @@ make_completion_dict.custom_vars = {}
|
|
|
749
763
|
async def interactive_loop(mc, to=None) :
|
|
750
764
|
print("""Interactive mode, most commands from terminal chat should work.
|
|
751
765
|
Use \"to\" to select recipient, use Tab to complete name ...
|
|
752
|
-
|
|
766
|
+
Some cmds have an help accessible with ?<cmd>. Do ?[Tab] to get a list.
|
|
753
767
|
\"quit\", \"q\", CTRL+D will end interactive mode""")
|
|
754
768
|
|
|
755
769
|
contact = to
|
|
@@ -1102,6 +1116,26 @@ async def process_contact_chat_line(mc, contact, line):
|
|
|
1102
1116
|
await process_cmds(mc, args)
|
|
1103
1117
|
return True
|
|
1104
1118
|
|
|
1119
|
+
if line.startswith("contact_key") or line.startswith("ck"):
|
|
1120
|
+
print(contact['public_key'],end="")
|
|
1121
|
+
if " " in line:
|
|
1122
|
+
print(" ", end="", flush=True)
|
|
1123
|
+
secline = line.split(" ", 1)[1]
|
|
1124
|
+
await process_contact_chat_line(mc, contact, secline)
|
|
1125
|
+
else:
|
|
1126
|
+
print("")
|
|
1127
|
+
return True
|
|
1128
|
+
|
|
1129
|
+
if line.startswith("contact_type") or line.startswith("ct"):
|
|
1130
|
+
print(f"{CONTACT_TYPENAMES[contact['type']]:4}",end="")
|
|
1131
|
+
if " " in line:
|
|
1132
|
+
print(" ", end="", flush=True)
|
|
1133
|
+
secline = line.split(" ", 1)[1]
|
|
1134
|
+
await process_contact_chat_line(mc, contact, secline)
|
|
1135
|
+
else:
|
|
1136
|
+
print("")
|
|
1137
|
+
return True
|
|
1138
|
+
|
|
1105
1139
|
if line.startswith("contact_name") or line.startswith("cn"):
|
|
1106
1140
|
print(contact['adv_name'],end="")
|
|
1107
1141
|
if " " in line:
|
|
@@ -1112,7 +1146,22 @@ async def process_contact_chat_line(mc, contact, line):
|
|
|
1112
1146
|
print("")
|
|
1113
1147
|
return True
|
|
1114
1148
|
|
|
1115
|
-
if line.startswith("
|
|
1149
|
+
if line.startswith("path") :
|
|
1150
|
+
if contact['out_path_len'] == -1:
|
|
1151
|
+
print("Flood", end="")
|
|
1152
|
+
elif contact['out_path_len'] == 0:
|
|
1153
|
+
print("0 hop", end="")
|
|
1154
|
+
else:
|
|
1155
|
+
print(contact['out_path'],end="")
|
|
1156
|
+
if " " in line:
|
|
1157
|
+
print(" ", end="", flush=True)
|
|
1158
|
+
secline = line.split(" ", 1)[1]
|
|
1159
|
+
await process_contact_chat_line(mc, contact, secline)
|
|
1160
|
+
else:
|
|
1161
|
+
print("")
|
|
1162
|
+
return True
|
|
1163
|
+
|
|
1164
|
+
if line.startswith("sleep ") or line.startswith("s "):
|
|
1116
1165
|
try:
|
|
1117
1166
|
sleeptime = int(line.split(" ",2)[1])
|
|
1118
1167
|
cmd_pos = 2
|
|
@@ -1143,20 +1192,24 @@ async def process_contact_chat_line(mc, contact, line):
|
|
|
1143
1192
|
return True
|
|
1144
1193
|
|
|
1145
1194
|
# commands that take contact as second arg will be sent to recipient
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
line
|
|
1149
|
-
line
|
|
1150
|
-
line
|
|
1151
|
-
line
|
|
1152
|
-
line
|
|
1153
|
-
line
|
|
1154
|
-
line
|
|
1155
|
-
line
|
|
1156
|
-
line
|
|
1157
|
-
line
|
|
1158
|
-
|
|
1195
|
+
# and can be chained ...
|
|
1196
|
+
if line.startswith("sc") or line.startswith("share_contact") or\
|
|
1197
|
+
line.startswith("ec") or line.startswith("export_contact") or\
|
|
1198
|
+
line.startswith("uc") or line.startswith("upload_contact") or\
|
|
1199
|
+
line.startswith("rp") or line.startswith("reset_path") or\
|
|
1200
|
+
line.startswith("dp") or line.startswith("disc_path") or\
|
|
1201
|
+
line.startswith("contact_info") or line.startswith("ci") or\
|
|
1202
|
+
line.startswith("req_status") or line.startswith("rs") or\
|
|
1203
|
+
line.startswith("req_neighbours") or line.startswith("rn") or\
|
|
1204
|
+
line.startswith("req_telemetry") or line.startswith("rt") or\
|
|
1205
|
+
line.startswith("req_acl") or\
|
|
1206
|
+
line.startswith("path") or\
|
|
1207
|
+
line.startswith("logout") :
|
|
1208
|
+
args = [line.split()[0], contact['adv_name']]
|
|
1159
1209
|
await process_cmds(mc, args)
|
|
1210
|
+
if " " in line:
|
|
1211
|
+
secline = line.split(" ", 1)[1]
|
|
1212
|
+
await process_contact_chat_line(mc, contact, secline)
|
|
1160
1213
|
return True
|
|
1161
1214
|
|
|
1162
1215
|
# special case for rp that can be chained from cmdline
|
|
@@ -1169,6 +1222,8 @@ async def process_contact_chat_line(mc, contact, line):
|
|
|
1169
1222
|
|
|
1170
1223
|
if line.startswith("set timeout "):
|
|
1171
1224
|
cmds=line.split(" ")
|
|
1225
|
+
#args = ["contact_timeout", contact['adv_name'], cmds[2]]
|
|
1226
|
+
#await process_cmds(mc, args)
|
|
1172
1227
|
contact["timeout"] = float(cmds[2])
|
|
1173
1228
|
return True
|
|
1174
1229
|
|
|
@@ -1306,12 +1361,13 @@ async def process_contact_chat_line(mc, contact, line):
|
|
|
1306
1361
|
|
|
1307
1362
|
return False
|
|
1308
1363
|
|
|
1309
|
-
async def apply_command_to_contacts(mc, contact_filter, line):
|
|
1364
|
+
async def apply_command_to_contacts(mc, contact_filter, line, json_output=False):
|
|
1310
1365
|
upd_before = None
|
|
1311
1366
|
upd_after = None
|
|
1312
1367
|
contact_type = None
|
|
1313
1368
|
min_hops = None
|
|
1314
1369
|
max_hops = None
|
|
1370
|
+
count = 0
|
|
1315
1371
|
|
|
1316
1372
|
await mc.ensure_contacts()
|
|
1317
1373
|
|
|
@@ -1366,6 +1422,9 @@ async def apply_command_to_contacts(mc, contact_filter, line):
|
|
|
1366
1422
|
(upd_after is None or contact["lastmod"] > upd_after) and\
|
|
1367
1423
|
(min_hops is None or contact["out_path_len"] >= min_hops) and\
|
|
1368
1424
|
(max_hops is None or contact["out_path_len"] <= max_hops):
|
|
1425
|
+
|
|
1426
|
+
count = count + 1
|
|
1427
|
+
|
|
1369
1428
|
if await process_contact_chat_line(mc, contact, line):
|
|
1370
1429
|
pass
|
|
1371
1430
|
|
|
@@ -1390,6 +1449,9 @@ async def apply_command_to_contacts(mc, contact_filter, line):
|
|
|
1390
1449
|
else:
|
|
1391
1450
|
logger.error(f"Can't send {line} to {contact['adv_name']}")
|
|
1392
1451
|
|
|
1452
|
+
if not json_output:
|
|
1453
|
+
print(f"> {count} matches in contacts")
|
|
1454
|
+
|
|
1393
1455
|
async def send_cmd (mc, contact, cmd) :
|
|
1394
1456
|
res = await mc.commands.send_cmd(contact, cmd)
|
|
1395
1457
|
if not res is None and not res.type == EventType.ERROR:
|
|
@@ -1780,7 +1842,7 @@ async def next_cmd(mc, cmds, json_output=False):
|
|
|
1780
1842
|
|
|
1781
1843
|
case "apply_to"|"at":
|
|
1782
1844
|
argnum = 2
|
|
1783
|
-
await apply_command_to_contacts(mc, cmds[1], cmds[2])
|
|
1845
|
+
await apply_command_to_contacts(mc, cmds[1], cmds[2], json_output=json_output)
|
|
1784
1846
|
|
|
1785
1847
|
case "set":
|
|
1786
1848
|
argnum = 2
|
|
@@ -2532,20 +2594,16 @@ async def next_cmd(mc, cmds, json_output=False):
|
|
|
2532
2594
|
await mc.ensure_contacts()
|
|
2533
2595
|
print(f"Discovered {len(dn)} nodes:")
|
|
2534
2596
|
for n in dn:
|
|
2535
|
-
|
|
2536
|
-
|
|
2597
|
+
try :
|
|
2598
|
+
name = f"{n['pubkey'][0:2]} {mc.get_contact_by_key_prefix(n['pubkey'])['adv_name']}"
|
|
2599
|
+
except TypeError:
|
|
2537
2600
|
name = n["pubkey"][0:16]
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
type = "ROOM"
|
|
2545
|
-
elif n['node_type'] == 4:
|
|
2546
|
-
type = "SENS"
|
|
2547
|
-
|
|
2548
|
-
print(f" {name:16} {type:>4} SNR: {n['SNR_in']:6,.2f}->{n['SNR']:6,.2f} RSSI: ->{n['RSSI']:4}")
|
|
2601
|
+
if n['node_type'] >= len(CONTACT_TYPENAMES):
|
|
2602
|
+
type = f"t:{n['node_type']}"
|
|
2603
|
+
else:
|
|
2604
|
+
type = CONTACT_TYPENAMES[n['node_type']]
|
|
2605
|
+
|
|
2606
|
+
print(f" {name:22} {type:>4} SNR: {n['SNR_in']:6,.2f}->{n['SNR']:6,.2f} RSSI: ->{n['RSSI']:4}")
|
|
2549
2607
|
|
|
2550
2608
|
case "req_telemetry"|"rt" :
|
|
2551
2609
|
argnum = 1
|
|
@@ -2561,7 +2619,7 @@ async def next_cmd(mc, cmds, json_output=False):
|
|
|
2561
2619
|
else :
|
|
2562
2620
|
print(json.dumps({
|
|
2563
2621
|
"name": contact["adv_name"],
|
|
2564
|
-
"pubkey_pre": contact["public_key"][0:
|
|
2622
|
+
"pubkey_pre": contact["public_key"][0:16],
|
|
2565
2623
|
"lpp": res,
|
|
2566
2624
|
}, indent = 4))
|
|
2567
2625
|
|
|
@@ -2695,7 +2753,13 @@ async def next_cmd(mc, cmds, json_output=False):
|
|
|
2695
2753
|
print(json.dumps(res, indent=4))
|
|
2696
2754
|
else :
|
|
2697
2755
|
for c in res.items():
|
|
2698
|
-
|
|
2756
|
+
if c[1]['out_path_len'] == -1:
|
|
2757
|
+
path_str = "Flood"
|
|
2758
|
+
elif c[1]['out_path_len'] == 0:
|
|
2759
|
+
path_str = "0 hop"
|
|
2760
|
+
else:
|
|
2761
|
+
path_str = f"{c[1]['out_path']}"
|
|
2762
|
+
print(f"{c[1]['adv_name']:30} {CONTACT_TYPENAMES[c[1]['type']]:4} {c[1]['public_key'][:12]} {path_str}")
|
|
2699
2763
|
print(f"> {len(mc.contacts)} contacts in device")
|
|
2700
2764
|
|
|
2701
2765
|
case "reload_contacts" | "rc":
|
|
@@ -2763,7 +2827,7 @@ async def next_cmd(mc, cmds, json_output=False):
|
|
|
2763
2827
|
if (path_len == 0) :
|
|
2764
2828
|
print("0 hop")
|
|
2765
2829
|
elif (path_len == -1) :
|
|
2766
|
-
print("
|
|
2830
|
+
print("Flood")
|
|
2767
2831
|
else:
|
|
2768
2832
|
print(path)
|
|
2769
2833
|
|
|
@@ -2790,6 +2854,8 @@ async def next_cmd(mc, cmds, json_output=False):
|
|
|
2790
2854
|
print(f"Unknown contact {cmds[1]}")
|
|
2791
2855
|
else:
|
|
2792
2856
|
path = cmds[2].replace(",","") # we'll accept path with ,
|
|
2857
|
+
if path == "0":
|
|
2858
|
+
path = ""
|
|
2793
2859
|
try:
|
|
2794
2860
|
res = await mc.commands.change_contact_path(contact, path)
|
|
2795
2861
|
logger.debug(res)
|
|
@@ -3213,7 +3279,7 @@ def get_help_for (cmdname, context="line") :
|
|
|
3213
3279
|
- d, direct, similar to h>-1
|
|
3214
3280
|
- f, flood, similar to h<0 or h=-1
|
|
3215
3281
|
|
|
3216
|
-
Note: Some commands like contact_name (aka cn), reset_path (aka rp), forget_password (aka fp) can be chained. There is also a sleep command taking an optional event. The sleep will be issued after the command, it helps limiting rate through repeaters ...
|
|
3282
|
+
Note: Some commands like contact_name (aka cn), contact_key (aka ck), contact_type (aka ct), reset_path (aka rp), forget_password (aka fp) can be chained. There is also a sleep command taking an optional event. The sleep will be issued after the command, it helps limiting rate through repeaters ...
|
|
3217
3283
|
|
|
3218
3284
|
Examples:
|
|
3219
3285
|
# removes all clients that have not been updated in last 2 days
|
|
@@ -3252,7 +3318,8 @@ def get_help_for (cmdname, context="line") :
|
|
|
3252
3318
|
print_new_contacts : display new pending contacts when available
|
|
3253
3319
|
print_path_updates : display path updates as they come
|
|
3254
3320
|
custom : all custom variables in json format
|
|
3255
|
-
each custom var can also be get/set directly
|
|
3321
|
+
each custom var can also be get/set directly
|
|
3322
|
+
""")
|
|
3256
3323
|
|
|
3257
3324
|
elif cmdname == "set" :
|
|
3258
3325
|
print("""Available parameters :
|
|
@@ -3265,12 +3332,15 @@ def get_help_for (cmdname, context="line") :
|
|
|
3265
3332
|
lat <lat> : latitude
|
|
3266
3333
|
lon <lon> : longitude
|
|
3267
3334
|
coords <lat,lon> : coordinates
|
|
3268
|
-
auto_update_contacts <> : automatically updates contact list
|
|
3269
3335
|
multi_ack <on/off> : multi-acks feature
|
|
3270
3336
|
telemetry_mode_base <mode> : set basic telemetry mode all/selected/off
|
|
3271
3337
|
telemetry_mode_loc <mode> : set location telemetry mode all/selected/off
|
|
3272
3338
|
telemetry_mode_env <mode> : set env telemetry mode all/selected/off
|
|
3273
3339
|
advert_loc_policy <policy> : "share" means loc will be shared in adv
|
|
3340
|
+
manual_add_contacts <on/off>: let user manually add contacts to device
|
|
3341
|
+
- when off device automatically adds contacts from adverts
|
|
3342
|
+
- when on contacts must be added manually using add_pending
|
|
3343
|
+
(pending contacts list is built by meshcli from adverts while connected)
|
|
3274
3344
|
display:
|
|
3275
3345
|
print_snr <on/off> : toggle snr display in messages
|
|
3276
3346
|
print_adverts <on/off> : display adverts as they come
|
|
@@ -3280,12 +3350,14 @@ def get_help_for (cmdname, context="line") :
|
|
|
3280
3350
|
channel_echoes <on/off> : print repeats for channel data
|
|
3281
3351
|
echo_unk_channels <on/off> : also dump unk channels (encrypted)
|
|
3282
3352
|
color <on/off> : color off should remove ANSI codes from output
|
|
3283
|
-
|
|
3353
|
+
meshcore-cli behaviour:
|
|
3284
3354
|
classic_prompt <on/off> : activates less fancier prompt
|
|
3285
3355
|
arrow_head <string> : change arrow head in prompt
|
|
3286
3356
|
slash_start <string> : idem for slash start
|
|
3287
3357
|
slash_end <string> : slash end
|
|
3288
|
-
invert_slash <on/off> : apply color inversion to slash
|
|
3358
|
+
invert_slash <on/off> : apply color inversion to slash
|
|
3359
|
+
auto_update_contacts <on/of>: auto sync contact list with device
|
|
3360
|
+
""")
|
|
3289
3361
|
|
|
3290
3362
|
elif cmdname == "scope":
|
|
3291
3363
|
print("""scope <scope> : changes flood scope of the node
|
|
@@ -3296,7 +3368,31 @@ Managing Flood Scope in interactive mode
|
|
|
3296
3368
|
Flood scope has recently been introduced in meshcore (from v1.10.0). It limits the scope of packets to regions, using transport codes in the frame.
|
|
3297
3369
|
When entering chat mode, scope will be reset to *, meaning classic flood.
|
|
3298
3370
|
You can switch scope using the scope command, or postfixing the to command with %<scope>.
|
|
3299
|
-
Scope can also be applied to a command using % before the scope name. For instance login%#Morbihan will limit diffusion of the login command (which is usually sent flood to get the path to a repeater) to the #Morbihan region.
|
|
3371
|
+
Scope can also be applied to a command using % before the scope name. For instance login%#Morbihan will limit diffusion of the login command (which is usually sent flood to get the path to a repeater) to the #Morbihan region.
|
|
3372
|
+
""")
|
|
3373
|
+
|
|
3374
|
+
elif cmdname == "contact_info":
|
|
3375
|
+
print("""contact_info <ct> : displays contact info
|
|
3376
|
+
|
|
3377
|
+
in interactive mode, there are some lighter commands that can be chained to give more compact information
|
|
3378
|
+
- contact_name (cn)
|
|
3379
|
+
- contact_key (ck)
|
|
3380
|
+
- contact_type (ct)
|
|
3381
|
+
""")
|
|
3382
|
+
|
|
3383
|
+
elif cmdname == "pending_contacts" or cmdname == "flush_pending" or cmdname == "add_pending":
|
|
3384
|
+
print("""Contact management
|
|
3385
|
+
|
|
3386
|
+
To receive a message from another user, it is necessary to have its public key. This key is stored on a contact list in the device, and this list has a finite size (50 when meshcore started, now over 350 for most devices).
|
|
3387
|
+
|
|
3388
|
+
By default contacts are automatically added to the device contact list when an advertisement is received, so as soon as you receive an advert, you can talk with your buddy.
|
|
3389
|
+
|
|
3390
|
+
With growing number of users, it becomes necessary to manage contact list and one of the ways is to add contacts manually to the device. This is done by turning on manual_add_contacts. Once this option has been turned on, a pending list is built by meshcore-cli from the received adverts. You can view the list issuing a pending_contacts command, flush the list using flush_pending or add a contact from the list with add_pending followed by the key of the contact or its name (both will be auto-completed with tab).
|
|
3391
|
+
|
|
3392
|
+
This feature only really works in interactive mode.
|
|
3393
|
+
|
|
3394
|
+
Note: There is also an auto_update_contacts setting that has nothing to do with adding contacts, it permits to automatically sync contact lists between device and meshcore-cli (when there is an update in name, location or path).
|
|
3395
|
+
""")
|
|
3300
3396
|
|
|
3301
3397
|
else:
|
|
3302
3398
|
print(f"Sorry, no help yet for {cmdname}")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|