From d2aca51296fea2223cb27ebeda2575cd743a60a5 Mon Sep 17 00:00:00 2001 From: Florent Date: Mon, 24 Aug 2026 08:13:34 -0400 Subject: [PATCH] send raw packets --- README.md | 2 ++ src/meshcore/commands/device.py | 17 ++++++++++++++--- src/meshcore/commands/messaging.py | 9 ++++----- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index db9b467..58ea6f6 100644 --- a/README.md +++ b/README.md @@ -518,6 +518,8 @@ All commands are async methods that return `Event` objects. Commands are organiz | **Device Actions** |||| | `send_advert(flood=False)` | `flood: bool` | `OK` | Send advertisement (optionally flood network) | | `reboot()` | None | None | Reboot device (no response expected) | +| `run_cli_command()` | `cmd: str` | `CLI_REPLY/ERROR` | Send a cli command to device | +| `send_raw_packet()` | `data: str/bytes, priority=0` | `OK/ERROR` | Send a raw packet through device, can be an hex string or bytes | | **Security** |||| | `export_private_key()` | None | `PRIVATE_KEY/DISABLED` | Export device private key (requires PIN auth & enabled firmware) | | `import_private_key(key)` | `key: bytes` | `OK` | Import private key to device | diff --git a/src/meshcore/commands/device.py b/src/meshcore/commands/device.py index 74c5465..973d660 100644 --- a/src/meshcore/commands/device.py +++ b/src/meshcore/commands/device.py @@ -16,15 +16,26 @@ class DeviceCommands(CommandHandlerBase): b1 = bytearray(b"\x01\x03 mccli") return await self.send(b1, [EventType.SELF_INFO, EventType.ERROR]) + async def send_device_query(self) -> Event: + logger.debug("Sending device query command") + return await self.send(b"\x16\x03", [EventType.DEVICE_INFO, EventType.ERROR]) + async def run_cli_command(self, cmd: str) -> Event: logger.debug(f"Sending cli command: {cmd}") cmd_data = bytearray([CommandType.RUN_CLI_COMMAND.value]) cmd_data.extend(cmd.encode("utf-8")) return await self.send(cmd_data, [EventType.CLI_REPLY, EventType.ERROR]) - async def send_device_query(self) -> Event: - logger.debug("Sending device query command") - return await self.send(b"\x16\x03", [EventType.DEVICE_INFO, EventType.ERROR]) + async def send_raw_packet(self, data, priority=0): + if isinstance(data, str): # got a string (assuming hex), change it to bytes + data=bytes.fromhex(data) + + cmd_data = bytearray([CommandType.SEND_RAW_PACKET.value]) + cmd_data.append(priority) + cmd_data.extend(data) + + logger.debug(f"Sending raw packet {data.hex()}") + return await self.send(cmd_data, [EventType.OK, EventType.ERROR]) async def send_advert(self, flood: bool = False) -> Event: logger.debug(f"Sending advertisement command (flood={flood})") diff --git a/src/meshcore/commands/messaging.py b/src/meshcore/commands/messaging.py index 8f400cf..ce1cd99 100644 --- a/src/meshcore/commands/messaging.py +++ b/src/meshcore/commands/messaging.py @@ -72,11 +72,10 @@ class MessagingCommands(CommandHandlerBase): timestamp = int(time.time()) if dst_type is None: - if isinstance(dst, dict) and "type" in dst : - dst_type = dst["type"] - else: # assume destination is a repeater - logger.warning("Can't determine destination type, please ensure contacts first or specify dst_type when calling `send_cmd`. Assuming it's a repeater.") - dst_type = AdvType.REPEATER.value + dst_type = dst["type"] + else: # assume destination is a repeater + logger.warning("Can't determine destination type, please ensure contacts first or specify dst_type when calling `send_cmd`. Assuming it's a repeater.") + dst_type = AdvType.REPEATER.value cmd_data = bytearray([CommandType.SEND_TXT_MSG.value]) if dst_type == AdvType.REPEATER.value :