Skip to content

Commit 875f5a7

Browse files
committed
chan management
1 parent e4ab7e2 commit 875f5a7

File tree

1 file changed

+132
-22
lines changed

1 file changed

+132
-22
lines changed

src/meshcore_cli/meshcore_cli.py

Lines changed: 132 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,11 @@ async def process_event_message(mc, ev, json_output, end="\n", above=False):
154154

155155
elif (data['type'] == "CHAN") :
156156
path_str = f"{ANSI_YELLOW}({path_str}){ANSI_END}"
157-
if data["channel_idx"] == 0: #public
157+
if hasattr(mc, "channels"):
158+
ch_name = mc.channels[data['channel_idx']]['channel_name']
159+
disp = f"{ANSI_GREEN}{ch_name} {path_str}"
160+
process_event_message.last_node = {"adv_name" : ch_name, "type" : 0, "chan_nb" : data['channel_idx']}
161+
elif data["channel_idx"] == 0: #public
158162
disp = f"{ANSI_GREEN}public {path_str}"
159163
process_event_message.last_node = {"adv_name" : "public", "type" : 0, "chan_nb" : 0}
160164
else :
@@ -287,7 +291,7 @@ async def subscribe_to_msgs(mc, json_output=False, above=False):
287291
CS = mc.subscribe(EventType.CHANNEL_MSG_RECV, handle_message)
288292
await mc.start_auto_message_fetching()
289293

290-
def make_completion_dict(contacts, pending={}, to=None):
294+
def make_completion_dict(contacts, pending={}, to=None, channels=None):
291295
contact_list = {}
292296
pending_list = {}
293297
to_list = {}
@@ -312,6 +316,11 @@ def make_completion_dict(contacts, pending={}, to=None):
312316
to_list["ch"] = None
313317
to_list["ch0"] = None
314318

319+
if not channels is None:
320+
for c in channels :
321+
if c["channel_name"] != "":
322+
to_list[c["channel_name"]] = None
323+
315324
completion_list = {
316325
"to" : to_list,
317326
"public" : None,
@@ -357,6 +366,8 @@ def make_completion_dict(contacts, pending={}, to=None):
357366
"self_telemetry" : None,
358367
"get_channel": None,
359368
"set_channel": None,
369+
"get_channels": None,
370+
"remove_channel": None,
360371
"set" : {
361372
"name" : None,
362373
"pin" : None,
@@ -461,9 +472,9 @@ def make_completion_dict(contacts, pending={}, to=None):
461472
"neighbors" : None,
462473
"req_acl":None,
463474
"setperm":contact_list,
464-
"gps" : {"on": None, "off": None, "sync": None, "setloc": None,
475+
"gps" : {"on":None,"off":None,"sync":None,"setloc":None,
465476
"advert" : {"none": None, "share": None, "prefs": None},
466-
}
477+
},
467478
"sensor": {"list": None, "set": {"gps": None}, "get": {"gps": None}},
468479
"get" : {"name" : None,
469480
"role":None,
@@ -512,7 +523,7 @@ def make_completion_dict(contacts, pending={}, to=None):
512523
"lon" : None,
513524
"timeout" : None,
514525
"perm":contact_list,
515-
"bridge.enabled": {"on": None, "off": None},
526+
"bridge.enabled":{"on": None, "off": None},
516527
"bridge.delay":None,
517528
"bridge.source":None,
518529
"bridge.baud":None,
@@ -552,6 +563,7 @@ async def interactive_loop(mc, to=None) :
552563
prev_contact = None
553564

554565
await mc.ensure_contacts()
566+
await get_channels(mc)
555567
await subscribe_to_msgs(mc, above=True)
556568

557569
handle_new_contact.print_new_contacts = True
@@ -644,7 +656,8 @@ def _(event):
644656
completer = NestedCompleter.from_nested_dict(
645657
make_completion_dict(mc.contacts,
646658
mc.pending_contacts,
647-
to=contact))
659+
to=contact,
660+
channels = mc.channels))
648661

649662
line = await session.prompt_async(ANSI(prompt),
650663
complete_while_typing=False,
@@ -667,18 +680,28 @@ def _(event):
667680
if nc is None:
668681
if dest == "public" :
669682
nc = {"adv_name" : "public", "type" : 0, "chan_nb" : 0}
683+
if hasattr(mc, "channels"):
684+
nc["adv_name"] = mc.channels[0]["channel_name"]
670685
elif dest.startswith("ch"):
671686
dest = int(dest[2:])
672687
nc = {"adv_name" : "chan" + str(dest), "type" : 0, "chan_nb" : dest}
688+
if hasattr(mc, "channels"):
689+
nc["adv_name"] = mc.channels[dest]["channel_name"]
673690
elif dest == ".." : # previous recipient
674691
nc = prev_contact
675692
elif dest == "~" or dest == "/" or dest == mc.self_info['name']:
676693
nc = None
677694
elif dest == "!" :
678695
nc = process_event_message.last_node
679696
else :
680-
print(f"Contact '{dest}' not found in contacts.")
681-
nc = contact
697+
chan = await get_channel_by_name(mc, dest)
698+
if chan is None :
699+
print(f"Contact '{dest}' not found in contacts.")
700+
nc = contact
701+
else:
702+
nc = {"adv_name": chan["channel_name"],
703+
"type": 0,
704+
"chan_nb": chan["channel_idx"],}
682705
if nc != contact :
683706
last_ack = True
684707
prev_contact = contact
@@ -898,6 +921,75 @@ async def msg_ack (mc, contact, msg) :
898921
msg_ack.flood_after=2
899922
msg_ack.max_flood_attempts=1
900923

924+
async def get_channel (mc, chan) :
925+
if not chan.isnumeric():
926+
return await get_channel_by_name(mc, chan)
927+
928+
nb = int(chan)
929+
if hasattr(mc, 'channels') and nb < len(mc.channels) :
930+
return mc.channels[nb]
931+
932+
res = await mc.commands.get_channel(nb)
933+
if res.type == EventType.ERROR:
934+
return None
935+
936+
info = res.payload
937+
info["channel_secret"] = info["channel_secret"].hex()
938+
return info
939+
940+
async def set_channel (mc, chan, name, key=None):
941+
942+
if chan.isnumeric():
943+
nb = int(chan)
944+
else:
945+
c = await get_channel_by_name(mc, chan)
946+
if c is None:
947+
return None
948+
nb = c['channel_idx']
949+
950+
res = await mc.commands.set_channel(nb, name, key)
951+
952+
if res.type == EventType.ERROR:
953+
return None
954+
955+
res = await mc.commands.get_channel(nb)
956+
if res.type == EventType.ERROR:
957+
return None
958+
959+
info = res.payload
960+
info["channel_secret"] = info["channel_secret"].hex()
961+
962+
if hasattr(mc,'channels') :
963+
mc.channels[nb] = info
964+
965+
return info
966+
967+
async def get_channel_by_name (mc, name):
968+
if not hasattr(mc, 'channels') :
969+
get_channels(mc)
970+
971+
for c in mc.channels:
972+
if c['channel_name'] == name:
973+
return c
974+
975+
return None
976+
977+
async def get_channels (mc) :
978+
if hasattr(mc, 'channels') :
979+
return mc.channels
980+
981+
ch = 0;
982+
mc.channels = []
983+
while True:
984+
res = await mc.commands.get_channel(ch)
985+
if res.type == EventType.ERROR:
986+
break
987+
info = res.payload
988+
info["channel_secret"] = info["channel_secret"].hex()
989+
mc.channels.append(info)
990+
ch = ch + 1
991+
return mc.channels
992+
901993
async def next_cmd(mc, cmds, json_output=False):
902994
""" process next command """
903995
try :
@@ -1419,25 +1511,38 @@ async def next_cmd(mc, cmds, json_output=False):
14191511

14201512
case "get_channel":
14211513
argnum = 1
1422-
res = await mc.commands.get_channel(int(cmds[1]))
1423-
logger.debug(res)
1424-
if res.type == EventType.ERROR:
1514+
res = await get_channel(mc, cmds[1])
1515+
if res is None:
14251516
print(f"Error while requesting channel info")
14261517
else:
1427-
info = res.payload
1428-
info["channel_secret"] = info["channel_secret"].hex()
1429-
print(json.dumps(info))
1518+
print(res)
1519+
1520+
case "get_channels":
1521+
res = await get_channels(mc)
1522+
if json_output:
1523+
print(json.dumps(res))
1524+
else:
1525+
for c in mc.channels:
1526+
if c["channel_name"] != "":
1527+
print(f"{c['channel_idx']}: {c['channel_name']} [{c['channel_secret']}]")
14301528

14311529
case "set_channel":
14321530
argnum = 3
14331531
if cmds[2].startswith("#") or len(cmds) == 3:
14341532
argnum = 2
1435-
res = await mc.commands.set_channel(int(cmds[1]), cmds[2])
1436-
else:
1437-
res = await mc.commands.set_channel(int(cmds[1]), cmds[2], bytes.fromhex(cmds[3]))
1438-
logger.debug(res)
1439-
if res.type == EventType.ERROR:
1440-
print(f"Error while setting channel")
1533+
res = await set_channel(mc, cmds[1], cmds[2])
1534+
elif len(cmds[3]) != 32:
1535+
res = None
1536+
else:
1537+
res = await set_channel(mc, cmds[1], cmds[2], bytes.fromhex(cmds[3]))
1538+
if res is None:
1539+
print("Error setting channel")
1540+
1541+
case "remove_channel":
1542+
argnum = 1
1543+
res = await set_channel(mc, cmds[1], "", bytes.fromhex(16*"00"))
1544+
if res is None:
1545+
print("Error deleting channel")
14411546

14421547
case "reboot" :
14431548
res = await mc.commands.reboot()
@@ -2126,8 +2231,10 @@ def command_help():
21262231
wait_msg : wait for a message and read it wm
21272232
sync_msgs : gets all unread msgs from the node sm
21282233
msgs_subscribe : display msgs as they arrive ms
2129-
get_channel <n> : get info for channel n
2234+
get_channels : prints all channel info
2235+
get_channel <n> : get info for channel (by number or name)
21302236
set_channel n nm k : set channel info (nb, name, key)
2237+
remove_channel <n> : remove channel (by number or name)
21312238
Management
21322239
advert : sends advert a
21332240
floodadv : flood advert
@@ -2323,7 +2430,10 @@ async def main(argv):
23232430
# Store device address in configuration
23242431
if os.path.isdir(MCCLI_CONFIG_DIR) :
23252432
with open(MCCLI_ADDRESS, "w", encoding="utf-8") as f :
2326-
f.write(address)
2433+
if not device is None:
2434+
f.write(device.address)
2435+
elif not address is None:
2436+
f.write(address)
23272437

23282438
handle_message.mc = mc # connect meshcore to handle_message
23292439
handle_advert.mc = mc

0 commit comments

Comments
 (0)