diff --git a/README.md b/README.md index 5296d87..9460e68 100644 --- a/README.md +++ b/README.md @@ -462,6 +462,7 @@ All events in MeshCore are represented by the `EventType` enum. These events are | `ACL_RESPONSE` | `"acl_response"` | Access Control List data | List of keys and permissions | | **Channel Events** ||| | `CHANNEL_INFO` | `"channel_info"` | Channel configuration | Channel name, secret, index | +| `CHANNEL_FLAG_NOSTORE` | `"channel_flag_nostore"` | State of no-store channel flag | Flag state | | **Raw Data Events** ||| | `RAW_DATA` | `"raw_data"` | Raw radio data | SNR, RSSI, payload hex | | `RX_LOG_DATA` | `"rx_log_data"` | RF log data | SNR, RSSI, raw payload | @@ -512,6 +513,8 @@ All commands are async methods that return `Event` objects. Commands are organiz | **Channel Management** |||| | `get_channel(channel_idx)` | `channel_idx: int` | `CHANNEL_INFO` | Get channel configuration | | `set_channel(channel_idx, name, secret)` | `channel_idx: int, name: str, secret: bytes` | `OK` | Configure channel (secret must be 16 bytes) | +| `get_channel_flag_nostore(channel_idx)` | `channel_idx: int` | `CHANNEL_FLAG_NOSTORE` | Get state of channel's no-store flag | +| `set_channel_flag_nostore(channel_idx, enabled)` | `channel_idx: int, enabled: bool` | `OK` | Set state of channel's no-store flag | | **Device Actions** |||| | `send_advert(flood=False)` | `flood: bool` | `OK` | Send advertisement (optionally flood network) | | `reboot()` | None | None | Reboot device (no response expected) | diff --git a/src/meshcore/commands/device.py b/src/meshcore/commands/device.py index 958d4bc..2dc64b3 100644 --- a/src/meshcore/commands/device.py +++ b/src/meshcore/commands/device.py @@ -220,3 +220,13 @@ async def get_stats_packets(self) -> Event: logger.debug("Getting packet statistics") # CMD_GET_STATS (56) + STATS_TYPE_PACKETS (2) return await self.send(b"\x38\x02", [EventType.STATS_PACKETS, EventType.ERROR]) + + async def get_channel_flag_nostore(self, channel_idx: int) -> Event: + logger.debug(f"Getting channel flag nostore for channel {channel_idx}") + data = b"\x39" + channel_idx.to_bytes(1, "little") + return await self.send(data, [EventType.CHANNEL_FLAG_NOSTORE, EventType.ERROR]) + + async def set_channel_flag_nostore(self, channel_idx: int, no_store: bool) -> Event: + logger.debug(f"Setting channel flag nostore for channel {channel_idx} to {no_store}") + data = b"\x3a" + channel_idx.to_bytes(1, "little") + no_store.to_bytes(1, "little") + return await self.send(data, [EventType.OK, EventType.ERROR]) \ No newline at end of file diff --git a/src/meshcore/events.py b/src/meshcore/events.py index 56a5611..cf125a1 100644 --- a/src/meshcore/events.py +++ b/src/meshcore/events.py @@ -50,6 +50,7 @@ class EventType(Enum): CONTROL_DATA = "control_data" DISCOVER_RESPONSE = "discover_response" NEIGHBOURS_RESPONSE = "neighbours_response" + CHANNEL_FLAG_NOSTORE = "channel_flag_nostore" # Command response types OK = "command_ok" diff --git a/src/meshcore/packets.py b/src/meshcore/packets.py index 7257c99..69b7d1b 100644 --- a/src/meshcore/packets.py +++ b/src/meshcore/packets.py @@ -37,6 +37,7 @@ class PacketType(Enum): SIGNATURE = 20 CUSTOM_VARS = 21 STATS = 24 + CHANNEL_FLAG_NOSTORE = 25 BINARY_REQ = 50 FACTORY_RESET = 51 PATH_DISCOVERY = 52 diff --git a/src/meshcore/reader.py b/src/meshcore/reader.py index 69fb669..30d6819 100644 --- a/src/meshcore/reader.py +++ b/src/meshcore/reader.py @@ -290,6 +290,13 @@ async def handle_rx(self, data: bytearray): res[psplit[0]] = psplit[1] logger.debug(f"got custom vars : {res}") await self.dispatcher.dispatch(Event(EventType.CUSTOM_VARS, res)) + + elif packet_type_value == PacketType.CHANNEL_FLAG_NOSTORE.value: + logger.debug(f"received channel flag nostore response: {data.hex()}") + res = {} + res["channel_flag_nostore"] = (bool)(dbuf.read(1)[0]) + logger.debug(f"got channel flags : {res}") + await self.dispatcher.dispatch(Event(EventType.CHANNEL_FLAG_NOSTORE, res)) elif packet_type_value == PacketType.STATS.value: # RESP_CODE_STATS (24) logger.debug(f"received stats response: {data.hex()}")