mirror of
https://github.com/zjs81/meshcore-open.git
synced 2026-07-12 11:52:07 +10:00
multi-byte paths-doc
This commit is contained in:
@@ -1287,105 +1287,6 @@ if (reactionInfo != null) {
|
||||
|
||||
Reactions are parsed, processed to update target message's reaction counts, but never displayed as standalone messages.
|
||||
|
||||
## Routing Paths
|
||||
|
||||
MeshCore supports variable-length multi-byte routing paths to scale mesh networks from 256 unique nodes (1-byte hashes) to millions (3-byte hashes).
|
||||
|
||||
### Path Encoding Format
|
||||
|
||||
**Single Byte Encodes Both Hop Count and Hash Mode**:
|
||||
```
|
||||
Path Byte Format:
|
||||
Bit 7-6: Hash mode (2 bits) → hash_bytes = 1 << mode
|
||||
Bit 5-0: Hop count (6 bits) → max 63 hops
|
||||
```
|
||||
|
||||
**Supported Modes**:
|
||||
|
||||
| Mode | Hash Bytes | Max Hops | Max Unique Nodes | Firmware |
|
||||
|------|-----------|----------|------------------|----------|
|
||||
| 0 | 1 | 63 | 256 | v1.13+ |
|
||||
| 1 | 2 | 63 | 65,536 | v1.14+ |
|
||||
| 2 | 3 | 63 | 16.7M | v1.14+ |
|
||||
| 3 | 4 | 63 | 4.3B | v1.14+ |
|
||||
|
||||
**Special Values**:
|
||||
- Path byte = **255** → Direct or flooded message (no path)
|
||||
- Path byte = **0** → End of contact path data (padding byte)
|
||||
|
||||
### Path Byte Calculation
|
||||
|
||||
```dart
|
||||
// Extract mode and hop count from wire byte
|
||||
final pathLenRaw = frameData[index]; // Single byte
|
||||
final hopCount = pathLenRaw & 0x3F; // Bits 5-0
|
||||
final hashMode = (pathLenRaw >> 6) & 0x03; // Bits 7-6
|
||||
final hashBytes = 1 << hashMode; // 1, 2, 4, or 8
|
||||
|
||||
// Total path bytes = hopCount * hashBytes
|
||||
final pathByteLength = hopCount * hashBytes;
|
||||
final pathData = frameData.sublist(index + 1, index + 1 + pathByteLength);
|
||||
```
|
||||
|
||||
### Device Capability Detection
|
||||
|
||||
The device firmware version determines multi-byte path support:
|
||||
|
||||
**Firmware Byte 81** (from `RESP_CODE_SELF_INFO` and device initialization):
|
||||
- Bits 3-0: Path hash mode capability (0-3)
|
||||
- v1.13 and earlier: Hardcoded mode 0 (1-byte only)
|
||||
- v1.14+: Firmware reports mode in byte 81; device generates paths in this mode
|
||||
|
||||
**Detection in App**:
|
||||
```dart
|
||||
// After receiving RESP_CODE_SELF_INFO
|
||||
if (firmwareBytes.length >= 82) {
|
||||
final mode = (firmwareBytes[81] & 0xFF).clamp(0, 2);
|
||||
pathHashByteWidth = mode + 1; // Sets to 1, 2, 3, or 4 bytes
|
||||
} else {
|
||||
pathHashByteWidth = 1; // Fallback for v1.13
|
||||
}
|
||||
```
|
||||
|
||||
### Path Usage in Different Message Types
|
||||
|
||||
**Direct Messages** (`RESP_CODE_CONTACT_MSG_RECV`/`RESP_CODE_CONTACT_MSG_RECV_V3`):
|
||||
- Path extracted from payload after decryption
|
||||
- Used to trace back to sender
|
||||
|
||||
**Channel Messages** (`RESP_CODE_CHANNEL_MSG_RECV`/`RESP_CODE_CHANNEL_MSG_RECV_V3`):
|
||||
- Group address + encrypted path in payload
|
||||
- Decrypted to reveal hop-by-hop routing chain
|
||||
|
||||
**Contact Storage** (from `RESP_CODE_CONTACT` frames):
|
||||
- Byte 32: Path length encoding (hop_count | (mode << 6))
|
||||
- Bytes 33-96: Path data (max 64 bytes stored, variable interpretation)
|
||||
|
||||
**Example Contact Path Parsing**:
|
||||
```dart
|
||||
// Mode 0 (1-byte): 3 hops = 3 bytes needed
|
||||
// [0x83, 0xA1, 0xB2, 0xC3] → hopCount=3, mode=0, path=[A1,B2,C3]
|
||||
|
||||
// Mode 1 (2-byte): 3 hops = 6 bytes needed
|
||||
// [0xC3, 0xA1, 0xA2, 0xB1, 0xB2, 0xC1, 0xC2]
|
||||
// → hopCount=3, mode=1, path=[A1A2, B1B2, C1C2]
|
||||
```
|
||||
|
||||
### Path Validation During Input
|
||||
|
||||
When user enters custom paths in the UI:
|
||||
|
||||
1. **Parse comma-separated hex segments**: `"A1B2,C1C2,D1D2"`
|
||||
2. **Validate segment length**: Each must be exactly `hashBytes * 2` hex characters
|
||||
3. **Convert to bytes**: Group hex pairs into single bytes
|
||||
4. **Check hop count**: Total bytes ÷ hashBytes must be ≤ 63
|
||||
|
||||
**Example with 2-byte mode**:
|
||||
- Device reports: `pathHashByteWidth = 2`
|
||||
- User enters: `"A1B2,C1C2"` (2 hops)
|
||||
- Parse result: `[0xA1, 0xB2, 0xC1, 0xC2]` (4 bytes total)
|
||||
- Validation: `4 bytes ÷ 2 bytes/hop = 2 hops` ✓
|
||||
|
||||
## References
|
||||
|
||||
- **Firmware Repository**: https://github.com/nonik0/meshcore
|
||||
|
||||
@@ -14,7 +14,8 @@ MeshCore Open is an open-source Flutter client for MeshCore LoRa mesh networking
|
||||
8. [Notifications](notifications.md) - System notifications, unread badges, and notification preferences
|
||||
9. [Repeater Management](repeater-management.md) - Repeater hub, status, CLI, telemetry, and neighbors
|
||||
10. [Additional Features](additional-features.md) - GIF picker, localization, debug logs, SMAZ compression, and more
|
||||
11. [BLE Protocol & Data Layer](ble-protocol.md) - Technical reference for the communication protocol and data architecture
|
||||
11. [Routing Paths](routing-paths.md) - Path encoding, validation, device capability detection, and storage
|
||||
12. [BLE Protocol & Data Layer](ble-protocol.md) - Technical reference for the communication protocol and data architecture
|
||||
|
||||
## App Overview
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ From the Contacts screen, tap any Chat-type contact to open the ChatScreen.
|
||||
- **Action buttons**:
|
||||
- **Routing mode** (waves icon): Switch between Auto, Direct, and Flood routing
|
||||
- **Path management** (timeline icon): View recent paths with hop count, round-trip time, age, and success count. Paths are color-coded by direct repeater (green/yellow/red/blue for ranked repeaters, grey for unknown). Tap a path to activate it (the device verifies and confirms via snackbar), long-press to view full path details, set custom paths, or force flood mode. A warning banner appears when history reaches 100 entries.
|
||||
- Custom path entry follows the device's current hash width, so multibyte paths are entered as comma-separated hex prefixes such as `A1B2,C1C2` when that mode is enabled.
|
||||
- **Info** (info icon): Contact info dialog showing type, path, GPS coordinates, public key, and SMAZ compression toggle
|
||||
|
||||
### Message List
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
# Routing Paths
|
||||
|
||||
This page covers how MeshCore Open represents, selects, validates, and stores routing paths in the UI and data layer.
|
||||
|
||||
## Path Routing
|
||||
|
||||
MeshCore supports variable-length multi-byte routing paths so the app can scale from small meshes to very large node sets.
|
||||
|
||||
### Path Encoding Format
|
||||
|
||||
Each path byte packs both the hop count and the hash width:
|
||||
|
||||
```
|
||||
Bit 7-6: Hash mode (2 bits) → hash_bytes = 1 << mode
|
||||
Bit 5-0: Hop count (6 bits) → max 63 hops
|
||||
```
|
||||
|
||||
| Mode | Hash Bytes | Max Hops | Max Unique Nodes | Firmware |
|
||||
|------|-----------|----------|------------------|----------|
|
||||
| 0 | 1 | 63 | 256 | v1.13+ |
|
||||
| 1 | 2 | 63 | 65,536 | v1.14+ |
|
||||
| 2 | 3 | 63 | 16.7M | v1.14+ |
|
||||
| 3 | 4 | 63 | 4.3B | v1.14+ |
|
||||
|
||||
### Path Byte Calculation
|
||||
|
||||
```dart
|
||||
final pathLenRaw = frameData[index];
|
||||
final hopCount = pathLenRaw & 0x3F;
|
||||
final hashMode = (pathLenRaw >> 6) & 0x03;
|
||||
final hashBytes = 1 << hashMode;
|
||||
|
||||
final pathByteLength = hopCount * hashBytes;
|
||||
final pathData = frameData.sublist(index + 1, index + 1 + pathByteLength);
|
||||
```
|
||||
|
||||
### Device Capability Detection
|
||||
|
||||
The app reads the device's reported capability byte to determine whether multi-byte paths are available:
|
||||
|
||||
```dart
|
||||
if (firmwareBytes.length >= 82) {
|
||||
final mode = (firmwareBytes[81] & 0xFF).clamp(0, 2);
|
||||
pathHashByteWidth = mode + 1;
|
||||
} else {
|
||||
pathHashByteWidth = 1;
|
||||
}
|
||||
```
|
||||
|
||||
### Path Usage in Different Message Types
|
||||
|
||||
- Direct messages extract the path from the decrypted payload to trace the sender route.
|
||||
- Channel messages decrypt a hop-by-hop routing chain from the payload.
|
||||
- Contact storage keeps the path length encoding in byte 32 and the raw path bytes in bytes 33-96.
|
||||
|
||||
### Example Contact Path Parsing
|
||||
|
||||
```dart
|
||||
// Mode 0 (1-byte): 3 hops = 3 bytes needed
|
||||
// [0x83, 0xA1, 0xB2, 0xC3] → hopCount=3, mode=0, path=[A1,B2,C3]
|
||||
|
||||
// Mode 1 (2-byte): 3 hops = 6 bytes needed
|
||||
// [0xC3, 0xA1, 0xA2, 0xB1, 0xB2, 0xC1, 0xC2]
|
||||
// → hopCount=3, mode=1, path=[A1A2, B1B2, C1C2]
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user