Преглед изворни кода

Update companion protocol documentation and enhance data type definitions for clarity

zjs81 пре 3 месеци
родитељ
комит
b705d5489f
2 измењених фајлова са 109 додато и 29 уклоњено
  1. 106 29
      docs/companion_protocol.md
  2. 3 0
      src/helpers/TxtDataHelpers.h

+ 106 - 29
docs/companion_protocol.md

@@ -283,32 +283,101 @@ Bytes 7+: Message Text (UTF-8, variable length)
 
 ### 6. Send Channel Data Datagram
 
-**Purpose**: Send binary datagram data to a channel.
+**Purpose**: Send a binary datagram to a channel. Unlike channel text messages, datagrams carry no built-in sender identity and no timestamp — applications needing either must encode them inside the binary payload.
 
 **Command Format**:
 ```
-Byte 0: 0x3E
-Bytes 1-2: Data Type (`data_type`, 16-bit little-endian)
-Byte 3: Channel Index (0-7)
-Bytes 4+: Binary payload bytes (variable length)
+Byte 0:                         0x3E
+Byte 1:                         Channel Index (0-7)
+Byte 2:                         Path Length (0xFF = flood, otherwise actual path length)
+Bytes 3 .. 2+path_len:          Path (omitted when path_len == 0xFF)
+Next 2 bytes (little-endian):   Data Type (`data_type`, uint16)
+Remaining bytes:                Binary payload (variable length)
+```
+
+**Example** (flood, `DATA_TYPE_DEV`, payload `A1 B2 C3`, channel 1):
+```
+3E 01 FF FF FF A1 B2 C3
 ```
 
 **Data Type / Transport Mapping**:
-- `0x0000` is invalid for this command.
+- `0x0000` (`DATA_TYPE_RESERVED`) is invalid and rejected with `PACKET_ERROR`.
 - `0xFFFF` (`DATA_TYPE_DEV`) is the developer namespace for experimenting and developing apps.
-- Other non-zero values can be used as assigned application/community namespaces.
-
-**Note**: Applications that need a timestamp should encode it inside the binary payload.
+- Values `0x0001`–`0xFFFE` are available for registered application/community namespaces. See the [Registered data_type values](#registered-data_type-values) table below.
 
 **Limits**:
-- Maximum payload length is `163` bytes.
-- Larger payloads are rejected with `PACKET_ERROR`.
+- Maximum payload length is `MAX_CHANNEL_DATA_LENGTH = MAX_FRAME_SIZE - 9 = 163` bytes.
+- Larger payloads are rejected with `PACKET_ERROR` (`ERR_CODE_ILLEGAL_ARG`).
+
+**Response**: `PACKET_OK` (0x00) on success, or `PACKET_ERROR` (0x01) with one of:
+- `ERR_CODE_NOT_FOUND` (2) — unknown `channel_idx`
+- `ERR_CODE_ILLEGAL_ARG` (6) — invalid `path_len`, reserved `data_type` (`0x0000`), or payload larger than `MAX_CHANNEL_DATA_LENGTH`
+- `ERR_CODE_TABLE_FULL` (3) — outbound send queue is full; retry later
+
+**Inbound datagrams** are delivered to the host via `RESP_CODE_CHANNEL_DATA_RECV` (0x1B); see [Receive Channel Data Datagram](#receive-channel-data-datagram).
+
+#### Registered `data_type` values
+
+Declared in `src/helpers/TxtDataHelpers.h`. These values have agreed-upon payload schemas so different client apps on the same channel can interoperate.
+
+| Value  | Constant             | Purpose                                     | Payload schema                                                                                         |
+|--------|----------------------|---------------------------------------------|--------------------------------------------------------------------------------------------------------|
+| 0x0000 | `DATA_TYPE_RESERVED` | Reserved; invalid on send                    | —                                                                                                      |
+| 0x0001 | `DATA_TYPE_SMAZ_TEXT`| Raw SMAZ-compressed UTF-8 text               | `[sender_name_len: u8][sender_name: UTF-8 × sender_name_len][smaz_bytes: remaining]`                   |
+| 0x0002 | `DATA_TYPE_GIPHY_GIF`| Giphy GIF id (avoids base64 tax)             | `[sender_name_len: u8][sender_name: UTF-8 × sender_name_len][giphy_id: ASCII, remaining]`              |
+| 0x0003 | `DATA_TYPE_REACTION` | Emoji reaction targeting a prior message     | `[target_hash: 2 bytes LE][emoji_index: u8][sender_name_len: u8][sender_name: UTF-8 × sender_name_len]` |
+| 0xFFFF | `DATA_TYPE_DEV`      | Developer/experimental namespace             | Application-defined                                                                                     |
+
+The firmware does not inspect the payload contents — `data_type` is transported opaquely, and the schemas above are a client-side contract between cooperating apps.
+
+To request a new registered value, submit a PR adding a `#define` to `TxtDataHelpers.h` and a row to this table.
+
+---
+
+### Receive Channel Data Datagram
+
+Inbound group datagrams (radio-level `PAYLOAD_TYPE_GRP_DATA`, 0x06) are forwarded to the host as `RESP_CODE_CHANNEL_DATA_RECV` notifications.
+
+**Frame Format** (`RESP_CODE_CHANNEL_DATA_RECV`, 0x1B):
+```
+Byte 0:                 0x1B (packet type)
+Byte 1:                 SNR (signed int8, scaled ×4 — divide by 4.0 to recover dB)
+Bytes 2-3:              Reserved
+Byte 4:                 Channel Index (0-7)
+Byte 5:                 Path Length (actual path when flooded, otherwise 0xFF)
+Bytes 6-7:              Data Type (uint16 little-endian)
+Byte 8:                 Data Length
+Bytes 9 .. 8+data_len:  Payload
+```
 
-**Response**: `PACKET_OK` (0x00) on success
+**Note**: The device may also emit `PACKET_MESSAGES_WAITING` (0x83) to notify the host that datagrams are queued; poll with `CMD_SYNC_NEXT_MESSAGE` (0x0A) to retrieve them.
+
+**Parsing Pseudocode**:
+```python
+def parse_channel_data_recv(data):
+    if len(data) < 9:
+        return None
+    snr_byte = data[1]
+    snr = (snr_byte if snr_byte < 128 else snr_byte - 256) / 4.0
+    channel_idx = data[4]
+    path_len = data[5]
+    data_type = int.from_bytes(data[6:8], 'little')
+    data_len = data[8]
+    if 9 + data_len > len(data):
+        return None
+    payload = data[9:9 + data_len]
+    return {
+        'snr': snr,
+        'channel_idx': channel_idx,
+        'path_len': path_len,
+        'data_type': data_type,
+        'payload': bytes(payload),
+    }
+```
 
 ---
 
-### 6. Get Message
+### 7. Get Message
 
 **Purpose**: Request the next queued message from the device.
 
@@ -325,13 +394,14 @@ Byte 0: 0x0A
 **Response**: 
 - `PACKET_CHANNEL_MSG_RECV` (0x08) or `PACKET_CHANNEL_MSG_RECV_V3` (0x11) for channel messages
 - `PACKET_CONTACT_MSG_RECV` (0x07) or `PACKET_CONTACT_MSG_RECV_V3` (0x10) for contact messages
+- `PACKET_CHANNEL_DATA_RECV` (0x1B) for channel data datagrams
 - `PACKET_NO_MORE_MSGS` (0x0A) if no messages available
 
 **Note**: Poll this command periodically to retrieve queued messages. The device may also send `PACKET_MESSAGES_WAITING` (0x83) as a notification when messages are available.
 
 ---
 
-### 7. Get Battery and Storage
+### 8. Get Battery and Storage
 
 **Purpose**: Query device battery voltage and storage usage.
 
@@ -527,6 +597,15 @@ Use the `SEND_CHANNEL_MESSAGE` command (see [Commands](#commands)).
 
 ## Response Parsing
 
+### Terminology
+
+This document uses a spec-level naming convention (`PACKET_*`) for bytes the firmware sends back to the host. In the firmware source these same values are split across two `#define` families by purpose:
+
+- `RESP_CODE_*` — direct replies to a command (e.g. `RESP_CODE_CHANNEL_DATA_RECV` = `PACKET_CHANNEL_DATA_RECV` = 0x1B).
+- `PUSH_CODE_*` — asynchronous notifications not tied to a specific command (e.g. `PUSH_CODE_MSG_WAITING` = `PACKET_MESSAGES_WAITING` = 0x83).
+
+Byte values are authoritative; names are aliases. When reading firmware source, `RESP_CODE_X` / `PUSH_CODE_X` correspond to this doc's `PACKET_X` of the same numeric value.
+
 ### Packet Types
 
 | Value | Name                       | Description                   |
@@ -547,6 +626,7 @@ Use the `SEND_CHANNEL_MESSAGE` command (see [Commands](#commands)).
 | 0x10  | PACKET_CONTACT_MSG_RECV_V3 | Contact message (V3 with SNR) |
 | 0x11  | PACKET_CHANNEL_MSG_RECV_V3 | Channel message (V3 with SNR) |
 | 0x12  | PACKET_CHANNEL_INFO        | Channel information           |
+| 0x1B  | PACKET_CHANNEL_DATA_RECV   | Channel data datagram         |
 | 0x80  | PACKET_ADVERTISEMENT       | Advertisement packet          |
 | 0x82  | PACKET_ACK                 | Acknowledgment                |
 | 0x83  | PACKET_MESSAGES_WAITING    | Messages waiting notification |
@@ -718,22 +798,18 @@ Bytes 1-6: ACK Code (6 bytes, hex)
 
 ### Error Codes
 
-**PACKET_ERROR** (0x01) may include an error code in byte 1:
+`PACKET_ERROR` (0x01) carries a single-byte error code in byte 1. Values match the `ERR_CODE_*` constants defined in `examples/companion_radio/MyMesh.cpp`:
 
-| Error Code | Description |
-|------------|-------------|
-| 0x00 | Generic error (no specific code) |
-| 0x01 | Invalid command |
-| 0x02 | Invalid parameter |
-| 0x03 | Channel not found |
-| 0x04 | Channel already exists |
-| 0x05 | Channel index out of range |
-| 0x06 | Secret mismatch |
-| 0x07 | Message too long |
-| 0x08 | Device busy |
-| 0x09 | Not enough storage |
+| Code | Constant (firmware)        | Description                                                                  |
+|------|----------------------------|------------------------------------------------------------------------------|
+| 1    | `ERR_CODE_UNSUPPORTED_CMD` | Unknown or unsupported command byte / sub-command                            |
+| 2    | `ERR_CODE_NOT_FOUND`       | Target not found (channel, contact, message, etc.)                           |
+| 3    | `ERR_CODE_TABLE_FULL`      | Internal queue or table is full — retry later                                |
+| 4    | `ERR_CODE_BAD_STATE`       | Operation not valid in current device state (e.g. iterator already running)  |
+| 5    | `ERR_CODE_FILE_IO_ERROR`   | Filesystem or storage I/O failure                                            |
+| 6    | `ERR_CODE_ILLEGAL_ARG`     | Invalid argument (bad length, out-of-range value, reserved field, etc.)      |
 
-**Note**: Error codes may vary by firmware version. Always check byte 1 of `PACKET_ERROR` response.
+**Note**: Error codes may vary by firmware version. Always check byte 1 of `PACKET_ERROR` response, and treat unknown codes as generic errors.
 
 ### Frame Handling
 
@@ -765,7 +841,8 @@ BLE implementations enqueue and deliver one protocol frame per BLE write/notific
      - `GET_CHANNEL` → `PACKET_CHANNEL_INFO`
      - `SET_CHANNEL` → `PACKET_OK` or `PACKET_ERROR`
      - `SEND_CHANNEL_MESSAGE` → `PACKET_MSG_SENT`
-     - `GET_MESSAGE` → `PACKET_CHANNEL_MSG_RECV`, `PACKET_CONTACT_MSG_RECV`, or `PACKET_NO_MORE_MSGS`
+     - `GET_MESSAGE` → `PACKET_CHANNEL_MSG_RECV`, `PACKET_CONTACT_MSG_RECV`, `PACKET_CHANNEL_DATA_RECV`, or `PACKET_NO_MORE_MSGS`
+     - `SEND_CHANNEL_DATA` → `PACKET_OK` or `PACKET_ERROR`
      - `GET_BATTERY` → `PACKET_BATTERY`
 
 4. **Timeout Handling**:

+ 3 - 0
src/helpers/TxtDataHelpers.h

@@ -7,6 +7,9 @@
 #define TXT_TYPE_CLI_DATA       1      // a CLI command
 #define TXT_TYPE_SIGNED_PLAIN   2      // plain text, signed by sender
 #define DATA_TYPE_RESERVED      0x0000 // reserved for future use
+#define DATA_TYPE_SMAZ_TEXT     0x0001 // raw SMAZ-compressed UTF-8 text meshcore-open Flutter client.
+#define DATA_TYPE_GIPHY_GIF     0x0002 // ASCII Giphy GIF id meshcore-open Flutter client.
+#define DATA_TYPE_REACTION      0x0003 // 2-byte target message hash + 1-byte emoji index meshcore-open Flutter client.
 #define DATA_TYPE_DEV           0xFFFF // developer namespace for experimenting with group/channel datagrams and building apps
 
 class StrHelper {