mirror of
https://github.com/meshcore-dev/MeshCore.git
synced 2026-04-20 22:13:47 +00:00
refactor documentation
This commit is contained in:
parent
384e482052
commit
4af31e552e
8 changed files with 314 additions and 429 deletions
|
|
@ -9,3 +9,8 @@
|
|||
.md-source__fact--version {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* underline links */
|
||||
.md-typeset a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
# MeshCore Repeater & Room Server CLI Commands
|
||||
# CLI Commands
|
||||
|
||||
This document provides an overview of CLI commands that can be sent to MeshCore Repeaters, Room Servers and Sensors.
|
||||
|
||||
## Navigation
|
||||
|
||||
|
|
|
|||
|
|
@ -1,26 +1,42 @@
|
|||
# MeshCore Device Communication Protocol Guide
|
||||
# Companion Protocol
|
||||
|
||||
This document provides a comprehensive guide for communicating with MeshCore devices over Bluetooth Low Energy (BLE). It is platform-agnostic and can be used for Android, iOS, Python, JavaScript, or any other platform that supports BLE.
|
||||
- **Last Updated**: 2026-01-03
|
||||
- **Protocol Version**: Companion Firmware v1.12.0+
|
||||
|
||||
## ⚠️ Important Security Note
|
||||
> NOTE: This document is still in development. Some information may be inaccurate.
|
||||
|
||||
**All secrets, hashes, and cryptographic values shown in this guide are EXAMPLE VALUES ONLY and are NOT real secrets.**
|
||||
This document provides a comprehensive guide for communicating with MeshCore devices over Bluetooth Low Energy (BLE).
|
||||
|
||||
- The secret `9b647d242d6e1c5883fde0c5cf5c4c5e` used in examples is a made-up example value
|
||||
- All hex values, public keys, and hashes in examples are for demonstration purposes only
|
||||
- **Never use example secrets in production** - always generate new cryptographically secure random secrets
|
||||
- This guide is for protocol documentation only - implement proper security practices in your actual implementation
|
||||
It is platform-agnostic and can be used for Android, iOS, Python, JavaScript, or any other platform that supports BLE.
|
||||
|
||||
## Official Libraries
|
||||
|
||||
Please see the following repos for existing MeshCore Companion Protocol libraries.
|
||||
|
||||
- JavaScript: [https://github.com/meshcore-dev/meshcore.js](https://github.com/meshcore-dev/meshcore.js)
|
||||
- Python: [https://github.com/meshcore-dev/meshcore_py](https://github.com/meshcore-dev/meshcore_py)
|
||||
|
||||
## Important Security Note
|
||||
|
||||
All secrets, hashes, and cryptographic values shown in this guide are example values only.
|
||||
|
||||
- All hex values, public keys and hashes are for demonstration purposes only
|
||||
- Never use example secrets in production
|
||||
- Always generate new cryptographically secure random secrets
|
||||
- Please implement proper security practices in your implementation
|
||||
- This guide is for protocol documentation only
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [BLE Connection](#ble-connection)
|
||||
2. [Protocol Overview](#protocol-overview)
|
||||
2. [Packet Structure](#packet-structure)
|
||||
3. [Commands](#commands)
|
||||
4. [Channel Management](#channel-management)
|
||||
5. [Secret Generation and QR Codes](#secret-generation-and-qr-codes)
|
||||
6. [Message Handling](#message-handling)
|
||||
7. [Response Parsing](#response-parsing)
|
||||
8. [Example Implementation Flow](#example-implementation-flow)
|
||||
5. [Message Handling](#message-handling)
|
||||
6. [Response Parsing](#response-parsing)
|
||||
7. [Example Implementation Flow](#example-implementation-flow)
|
||||
8. [Best Practices](#best-practices)
|
||||
9. [Troubleshooting](#troubleshooting)
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -28,181 +44,111 @@ This document provides a comprehensive guide for communicating with MeshCore dev
|
|||
|
||||
### Service and Characteristics
|
||||
|
||||
MeshCore devices expose a BLE service with the following UUIDs:
|
||||
MeshCore Companion devices expose a BLE service with the following UUIDs:
|
||||
|
||||
- **Service UUID**: `0000ff00-0000-1000-8000-00805f9b34fb`
|
||||
- **RX Characteristic** (Device → Client): `0000ff01-0000-1000-8000-00805f9b34fb`
|
||||
- **TX Characteristic** (Client → Device): `0000ff02-0000-1000-8000-00805f9b34fb`
|
||||
- **Service UUID**: `6E400001-B5A3-F393-E0A9-E50E24DCCA9E`
|
||||
- **RX Characteristic** (App → Firmware): `6E400002-B5A3-F393-E0A9-E50E24DCCA9E`
|
||||
- **TX Characteristic** (Firmware → App): `6E400003-B5A3-F393-E0A9-E50E24DCCA9E`
|
||||
|
||||
### Connection Steps
|
||||
|
||||
1. **Scan for Devices**
|
||||
- Scan for BLE devices advertising the MeshCore service UUID
|
||||
- Filter by device name (typically contains "MeshCore" or similar)
|
||||
- Note the device MAC address for reconnection
|
||||
- Scan for BLE devices advertising the MeshCore Service UUID
|
||||
- Optionally filter by device name (typically contains "MeshCore" prefix)
|
||||
- Note the device MAC address for reconnection
|
||||
|
||||
2. **Connect to GATT**
|
||||
- Connect to the device using the discovered MAC address
|
||||
- Wait for connection to be established
|
||||
- Connect to the device using the discovered MAC address
|
||||
- Wait for connection to be established
|
||||
|
||||
3. **Discover Services and Characteristics**
|
||||
- Discover the service with UUID `0000ff00-0000-1000-8000-00805f9b34fb`
|
||||
- Discover RX characteristic (`0000ff01-...`) for receiving data
|
||||
- Discover TX characteristic (`0000ff02-...`) for sending commands
|
||||
- Discover the service with UUID `6E400001-B5A3-F393-E0A9-E50E24DCCA9E`
|
||||
- Discover the RX characteristic `6E400002-B5A3-F393-E0A9-E50E24DCCA9E`
|
||||
- Your app writes to this, the firmware reads from this
|
||||
- Discover the TX characteristic `6E400003-B5A3-F393-E0A9-E50E24DCCA9E`
|
||||
- The firmware writes to this, your app reads from this
|
||||
|
||||
4. **Enable Notifications**
|
||||
- Subscribe to notifications on the RX characteristic
|
||||
- Enable notifications/indications to receive data from the device
|
||||
- On some platforms, you may need to write to a descriptor (e.g., `0x2902`) with value `0x01` or `0x02`
|
||||
- Subscribe to notifications on the TX characteristic to receive data from the firmware
|
||||
|
||||
5. **Send AppStart Command**
|
||||
- Send the app start command (see [Commands](#commands)) to initialize communication
|
||||
- Wait for OK response before sending other commands
|
||||
|
||||
### Connection State Management
|
||||
|
||||
- **Disconnected**: No connection established
|
||||
- **Connecting**: Connection attempt in progress
|
||||
- **Connected**: GATT connection established, ready for commands
|
||||
- **Error**: Connection failed or lost
|
||||
5. **Send Initial Commands**
|
||||
- Send `CMD_APP_START` to identify your app to firmware and get radio settings
|
||||
- Send `CMD_DEVICE_QEURY` to fetch device info and negotiate supported protocol versions
|
||||
- Send `CMD_SET_DEVICE_TIME` to set the firmware clock
|
||||
- Send `CMD_GET_CONTACTS` to fetch all contacts
|
||||
- Send `CMD_GET_CHANNEL` multiple times to fetch all channel slots
|
||||
- Send `CMD_SYNC_NEXT_MESSAGE` to fetch the next message stored in firmware
|
||||
- Setup listeners for push codes, such as `PUSH_CODE_MSG_WAITING` or `PUSH_CODE_ADVERT`
|
||||
- See [Commands](#commands) section for information on other commands
|
||||
|
||||
**Note**: MeshCore devices may disconnect after periods of inactivity. Implement auto-reconnect logic with exponential backoff.
|
||||
|
||||
### BLE Write Type
|
||||
|
||||
When writing commands to the TX characteristic, specify the write type:
|
||||
When writing commands to the RX characteristic, specify the write type:
|
||||
|
||||
- **Write with Response** (default): Waits for acknowledgment from device
|
||||
- **Write without Response**: Faster but no acknowledgment
|
||||
|
||||
**Platform-specific**:
|
||||
|
||||
- **Android**: Use `BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT` or `WRITE_TYPE_NO_RESPONSE`
|
||||
- **iOS**: Use `CBCharacteristicWriteType.withResponse` or `.withoutResponse`
|
||||
- **Python (bleak)**: Use `write_gatt_char()` with `response=True` or `False`
|
||||
|
||||
**Recommendation**: Use write with response for reliability, especially for critical commands like `SET_CHANNEL`.
|
||||
**Recommendation**: Use write with response for reliability.
|
||||
|
||||
### MTU (Maximum Transmission Unit)
|
||||
|
||||
The default BLE MTU is 23 bytes (20 bytes payload). For larger commands like `SET_CHANNEL` (66 bytes), you may need to:
|
||||
|
||||
1. **Request Larger MTU**: Request MTU of 512 bytes if supported
|
||||
- Android: `gatt.requestMtu(512)`
|
||||
- iOS: `peripheral.maximumWriteValueLength(for:)`
|
||||
- Python (bleak): MTU is negotiated automatically
|
||||
- Android: `gatt.requestMtu(512)`
|
||||
- iOS: `peripheral.maximumWriteValueLength(for:)`
|
||||
- Python (bleak): MTU is negotiated automatically
|
||||
|
||||
2. **Handle Chunking**: If MTU is small, commands may be split automatically by the BLE stack
|
||||
- Ensure all chunks are sent before waiting for response
|
||||
- Responses may also arrive in chunks - buffer until complete
|
||||
|
||||
### Command Sequencing and Timing
|
||||
### Command Sequencing
|
||||
|
||||
**Critical**: Commands must be sent in the correct sequence:
|
||||
|
||||
1. **After Connection**:
|
||||
- Wait for GATT connection established
|
||||
- Wait for services/characteristics discovered
|
||||
- Wait for notifications enabled (descriptor write complete)
|
||||
- **Wait 200-1000ms** for device to be ready (some devices need initialization time)
|
||||
- Send `APP_START` command
|
||||
- **Wait for `PACKET_OK` response** before sending any other commands
|
||||
- Wait for BLE connection to be established
|
||||
- Wait for services/characteristics to be discovered
|
||||
- Wait for notifications to be enabled
|
||||
- Now you can safely send commands to the firmware
|
||||
|
||||
2. **Command-Response Matching**:
|
||||
- Send one command at a time
|
||||
- Wait for response before sending next command
|
||||
- Use timeout (typically 5 seconds)
|
||||
- Match response to command by:
|
||||
- Command type (e.g., `GET_CHANNEL` → `PACKET_CHANNEL_INFO`)
|
||||
- Sequence number (if implemented)
|
||||
- First-in-first-out queue
|
||||
|
||||
3. **Timing Considerations**:
|
||||
- Minimum delay between commands: 50-100ms
|
||||
- After `APP_START`: Wait 200-500ms before next command
|
||||
- After `SET_CHANNEL`: Wait 500-1000ms for channel to be created
|
||||
- After enabling notifications: Wait 200ms before sending commands
|
||||
|
||||
**Example Flow**:
|
||||
```python
|
||||
# 1. Connect and discover
|
||||
await connect_to_device(device)
|
||||
await discover_services()
|
||||
await enable_notifications()
|
||||
await asyncio.sleep(0.2) # Wait for device ready
|
||||
|
||||
# 2. Send AppStart
|
||||
send_command(build_app_start())
|
||||
response = await wait_for_response(PACKET_OK, timeout=5.0)
|
||||
if response.type != PACKET_OK:
|
||||
raise Exception("AppStart failed")
|
||||
|
||||
# 3. Now safe to send other commands
|
||||
await asyncio.sleep(0.1) # Small delay between commands
|
||||
send_command(build_device_query())
|
||||
response = await wait_for_response(PACKET_DEVICE_INFO, timeout=5.0)
|
||||
```
|
||||
- Send one command at a time
|
||||
- Wait for a response before sending another command
|
||||
- Use a timeout (typically 5 seconds)
|
||||
- Match response to command by type (e.g: `CMD_GET_CHANNEL` → `RESP_CODE_CHANNEL_INFO`)
|
||||
|
||||
### Command Queue Management
|
||||
|
||||
For reliable operation, implement a command queue:
|
||||
For reliable operation, implement a command queue.
|
||||
|
||||
1. **Queue Structure**:
|
||||
- Maintain a queue of pending commands
|
||||
- Track which command is currently waiting for response
|
||||
- Only send next command after receiving response or timeout
|
||||
**Queue Structure**:
|
||||
|
||||
2. **Implementation**:
|
||||
```python
|
||||
class CommandQueue:
|
||||
def __init__(self):
|
||||
self.queue = []
|
||||
self.waiting_for_response = False
|
||||
self.current_command = None
|
||||
|
||||
async def send_command(self, command, expected_response_type, timeout=5.0):
|
||||
if self.waiting_for_response:
|
||||
# Queue the command
|
||||
self.queue.append((command, expected_response_type, timeout))
|
||||
return
|
||||
|
||||
self.waiting_for_response = True
|
||||
self.current_command = (command, expected_response_type, timeout)
|
||||
|
||||
# Send command
|
||||
await write_to_tx_characteristic(command)
|
||||
|
||||
# Wait for response
|
||||
response = await wait_for_response(expected_response_type, timeout)
|
||||
|
||||
self.waiting_for_response = False
|
||||
self.current_command = None
|
||||
|
||||
# Process next queued command
|
||||
if self.queue:
|
||||
next_cmd, next_type, next_timeout = self.queue.pop(0)
|
||||
await self.send_command(next_cmd, next_type, next_timeout)
|
||||
|
||||
return response
|
||||
```
|
||||
- Maintain a queue of pending commands
|
||||
- Track which command is currently waiting for a response
|
||||
- Only send next command after receiving response or timeout
|
||||
|
||||
3. **Error Handling**:
|
||||
- On timeout: Clear current command, process next in queue
|
||||
- On error: Log error, clear current command, process next
|
||||
- Don't block queue on single command failure
|
||||
**Error Handling**:
|
||||
|
||||
- On timeout, clear current command, process next in queue
|
||||
- On error, log error, clear current command, process next
|
||||
|
||||
---
|
||||
|
||||
## Protocol Overview
|
||||
## Packet Structure
|
||||
|
||||
The MeshCore protocol uses a binary format with the following structure:
|
||||
|
||||
- **Commands**: Sent from client to device via TX characteristic
|
||||
- **Responses**: Received from device via RX characteristic (notifications)
|
||||
- **All multi-byte integers**: Little-endian byte order
|
||||
- **Commands**: Sent from app to firmware via RX characteristic
|
||||
- **Responses**: Received from firmware via TX characteristic notifications
|
||||
- **All multi-byte integers**: Little-endian byte order (except CayenneLPP which is Big-endian)
|
||||
- **All strings**: UTF-8 encoding
|
||||
|
||||
### Packet Structure
|
||||
|
||||
Most packets follow this format:
|
||||
```
|
||||
[Packet Type (1 byte)] [Data (variable length)]
|
||||
|
|
@ -283,7 +229,7 @@ Byte 1: Channel Index (0-7)
|
|||
Byte 0: 0x20
|
||||
Byte 1: Channel Index (0-7)
|
||||
Bytes 2-33: Channel Name (32 bytes, UTF-8, null-padded)
|
||||
Bytes 34-65: Secret (32 bytes, see [Secret Generation](#secret-generation))
|
||||
Bytes 34-65: Secret (32 bytes)
|
||||
```
|
||||
|
||||
**Total Length**: 66 bytes
|
||||
|
|
@ -298,7 +244,7 @@ Bytes 34-65: Secret (32 bytes, see [Secret Generation](#secret-generation))
|
|||
- Padded with null bytes (0x00) if shorter
|
||||
|
||||
**Secret Field** (32 bytes):
|
||||
- For **private channels**: 32-byte secret (see [Secret Generation](#secret-generation))
|
||||
- For **private channels**: 32-byte secret
|
||||
- For **public channels**: All zeros (0x00)
|
||||
|
||||
**Example** (create channel "YourChannelName" at index 1 with secret):
|
||||
|
|
@ -380,170 +326,33 @@ Byte 0: 0x14
|
|||
|
||||
### Channel Types
|
||||
|
||||
1. **Public Channels** (Index 0)
|
||||
- No secret required
|
||||
- Anyone with the channel name can join
|
||||
- Use for open communication
|
||||
|
||||
2. **Private Channels** (Indices 1-7)
|
||||
- Require a 16-byte secret
|
||||
- Secret is expanded to 32 bytes using SHA-512 (see [Secret Generation](#secret-generation))
|
||||
- Only devices with the secret can access the channel
|
||||
1. **Public Channel**
|
||||
- Uses a publicly known 16-byte key: `8b3387e9c5cdea6ac9e5edbaa115cd72`
|
||||
- Anyone can join this channel, messages should be considered public
|
||||
- Used as the default public group chat
|
||||
2. **Hashtag Channels**
|
||||
- Uses a secret key derived from the channel name
|
||||
- It is the first 16 bytes of `sha256("#test")`
|
||||
- For example hashtag channel `#test` has the key: `9cd8fcf22a47333b591d96a2b848b73f`
|
||||
- Used as a topic based public group chat, separate from the default public channel
|
||||
3. **Private Channels**
|
||||
- Uses a randomly generated 16-byte secret key
|
||||
- Messages should be considered private between those that know the secret
|
||||
- Users should keep the key secret, and only share with those you want to communicate with
|
||||
- Used as a secure private group chat
|
||||
|
||||
### Channel Lifecycle
|
||||
|
||||
1. **Create Channel**:
|
||||
- Choose an available index (1-7 for private channels)
|
||||
- Generate or provide a 16-byte secret
|
||||
- Send `SET_CHANNEL` command with name and secret
|
||||
- **Store the secret locally** (device does not return it)
|
||||
|
||||
2. **Query Channel**:
|
||||
- Send `GET_CHANNEL` command with channel index
|
||||
- Parse `PACKET_CHANNEL_INFO` response
|
||||
- Note: Secret will be null in response (security feature)
|
||||
|
||||
1. **Set Channel**:
|
||||
- Fetch all channel slots, and find one with empty name and all-zero secret
|
||||
- Generate or provide a 16-byte secret
|
||||
- Send `CMD_SET_CHANNEL` with name and secret
|
||||
2. **Get Channel**:
|
||||
- Send `CMD_GET_CHANNEL` with channel index
|
||||
- Parse `RESP_CODE_CHANNEL_INFO` response
|
||||
3. **Delete Channel**:
|
||||
- Send `SET_CHANNEL` command with empty name and all-zero secret
|
||||
- Or overwrite with a new channel
|
||||
|
||||
### Channel Index Management
|
||||
|
||||
- **Index 0**: Reserved for public channels
|
||||
- **Indices 1-7**: Available for private channels
|
||||
- If a channel exists at index 0 but should be private, migrate it to index 1-7
|
||||
|
||||
---
|
||||
|
||||
## Secret Generation and QR Codes
|
||||
|
||||
### Secret Generation
|
||||
|
||||
For private channels, generate a cryptographically secure 16-byte secret:
|
||||
|
||||
**Pseudocode**:
|
||||
```python
|
||||
import secrets
|
||||
|
||||
# Generate 16 random bytes
|
||||
secret_bytes = secrets.token_bytes(16)
|
||||
|
||||
# Convert to hex string for storage/sharing
|
||||
secret_hex = secret_bytes.hex() # 32 hex characters
|
||||
```
|
||||
|
||||
**Important**: Use a cryptographically secure random number generator (CSPRNG). Do not use predictable values.
|
||||
|
||||
### Secret Expansion
|
||||
|
||||
When sending the secret to the device via `SET_CHANNEL`, the 16-byte secret must be expanded to 32 bytes:
|
||||
|
||||
**Process**:
|
||||
1. Take the 16-byte secret
|
||||
2. Compute SHA-512 hash: `hash = SHA-512(secret)`
|
||||
3. Use the first 32 bytes of the hash as the secret field in the command
|
||||
|
||||
**Pseudocode**:
|
||||
```python
|
||||
import hashlib
|
||||
|
||||
secret_16_bytes = ... # Your 16-byte secret
|
||||
sha512_hash = hashlib.sha512(secret_16_bytes).digest() # 64 bytes
|
||||
secret_32_bytes = sha512_hash[:32] # First 32 bytes
|
||||
```
|
||||
|
||||
This matches MeshCore's ED25519 key expansion method.
|
||||
|
||||
### QR Code Format
|
||||
|
||||
QR codes for sharing channel secrets use the following format:
|
||||
|
||||
**URL Scheme**:
|
||||
```
|
||||
meshcore://channel/add?name=<ChannelName>&secret=<32HexChars>
|
||||
```
|
||||
|
||||
**Parameters**:
|
||||
- `name`: Channel name (URL-encoded if needed)
|
||||
- `secret`: 32-character hexadecimal representation of the 16-byte secret
|
||||
|
||||
**Example** (using example secret - NOT a real secret):
|
||||
```
|
||||
meshcore://channel/add?name=YourChannelName&secret=9b647d242d6e1c5883fde0c5cf5c4c5e
|
||||
```
|
||||
|
||||
**Alternative Formats** (for backward compatibility):
|
||||
|
||||
1. **JSON Format**:
|
||||
```json
|
||||
{
|
||||
"name": "YourChannelName",
|
||||
"secret": "9b647d242d6e1c5883fde0c5cf5c4c5e"
|
||||
}
|
||||
```
|
||||
*Note: The secret value above is an example only - generate your own secure random secret.*
|
||||
|
||||
2. **Plain Hex** (32 hex characters):
|
||||
```
|
||||
9b647d242d6e1c5883fde0c5cf5c4c5e
|
||||
```
|
||||
*Note: This is an example hex value - always generate your own cryptographically secure random secret.*
|
||||
|
||||
### QR Code Generation
|
||||
|
||||
**Steps**:
|
||||
1. Generate or use existing 16-byte secret
|
||||
2. Convert to 32-character hex string (lowercase)
|
||||
3. URL-encode the channel name
|
||||
4. Construct the `meshcore://` URL
|
||||
5. Generate QR code from the URL string
|
||||
|
||||
**Example** (Python with `qrcode` library):
|
||||
```python
|
||||
import qrcode
|
||||
from urllib.parse import quote
|
||||
import secrets
|
||||
|
||||
channel_name = "YourChannelName"
|
||||
# Generate a real cryptographically secure secret (NOT the example value)
|
||||
secret_bytes = secrets.token_bytes(16)
|
||||
secret_hex = secret_bytes.hex() # This will be a different value each time
|
||||
|
||||
# Example value shown in documentation: "9b647d242d6e1c5883fde0c5cf5c4c5e"
|
||||
# DO NOT use the example value - always generate your own!
|
||||
|
||||
url = f"meshcore://channel/add?name={quote(channel_name)}&secret={secret_hex}"
|
||||
qr = qrcode.QRCode(version=1, box_size=10, border=5)
|
||||
qr.add_data(url)
|
||||
qr.make(fit=True)
|
||||
img = qr.make_image(fill_color="black", back_color="white")
|
||||
img.save("channel_qr.png")
|
||||
```
|
||||
|
||||
### QR Code Scanning
|
||||
|
||||
When scanning a QR code:
|
||||
|
||||
1. **Parse URL Format**:
|
||||
- Extract `name` and `secret` query parameters
|
||||
- Validate secret is 32 hex characters
|
||||
|
||||
2. **Parse JSON Format**:
|
||||
- Parse JSON object
|
||||
- Extract `name` and `secret` fields
|
||||
|
||||
3. **Parse Plain Hex**:
|
||||
- Extract only hex characters (0-9, a-f, A-F)
|
||||
- Validate length is 32 characters
|
||||
- Convert to lowercase
|
||||
|
||||
4. **Validate Secret**:
|
||||
- Must be exactly 32 hex characters (16 bytes)
|
||||
- Convert hex string to bytes
|
||||
|
||||
5. **Create Channel**:
|
||||
- Use extracted name and secret
|
||||
- Send `SET_CHANNEL` command
|
||||
- Send `CMD_SET_CHANNEL` with empty name and all-zero secret
|
||||
- Or overwrite with a new channel
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -693,28 +502,28 @@ Use the `SEND_CHANNEL_MESSAGE` command (see [Commands](#commands)).
|
|||
|
||||
### Packet Types
|
||||
|
||||
| Value | Name | Description |
|
||||
|-------|------|-------------|
|
||||
| 0x00 | PACKET_OK | Command succeeded |
|
||||
| 0x01 | PACKET_ERROR | Command failed |
|
||||
| 0x02 | PACKET_CONTACT_START | Start of contact list |
|
||||
| 0x03 | PACKET_CONTACT | Contact information |
|
||||
| 0x04 | PACKET_CONTACT_END | End of contact list |
|
||||
| 0x05 | PACKET_SELF_INFO | Device self-information |
|
||||
| 0x06 | PACKET_MSG_SENT | Message sent confirmation |
|
||||
| 0x07 | PACKET_CONTACT_MSG_RECV | Contact message (standard) |
|
||||
| 0x08 | PACKET_CHANNEL_MSG_RECV | Channel message (standard) |
|
||||
| 0x09 | PACKET_CURRENT_TIME | Current time response |
|
||||
| 0x0A | PACKET_NO_MORE_MSGS | No more messages available |
|
||||
| 0x0C | PACKET_BATTERY | Battery level |
|
||||
| 0x0D | PACKET_DEVICE_INFO | Device information |
|
||||
| 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 |
|
||||
| 0x80 | PACKET_ADVERTISEMENT | Advertisement packet |
|
||||
| 0x82 | PACKET_ACK | Acknowledgment |
|
||||
| 0x83 | PACKET_MESSAGES_WAITING | Messages waiting notification |
|
||||
| 0x88 | PACKET_LOG_DATA | RF log data (can be ignored) |
|
||||
| Value | Name | Description |
|
||||
|-------|----------------------------|-------------------------------|
|
||||
| 0x00 | PACKET_OK | Command succeeded |
|
||||
| 0x01 | PACKET_ERROR | Command failed |
|
||||
| 0x02 | PACKET_CONTACT_START | Start of contact list |
|
||||
| 0x03 | PACKET_CONTACT | Contact information |
|
||||
| 0x04 | PACKET_CONTACT_END | End of contact list |
|
||||
| 0x05 | PACKET_SELF_INFO | Device self-information |
|
||||
| 0x06 | PACKET_MSG_SENT | Message sent confirmation |
|
||||
| 0x07 | PACKET_CONTACT_MSG_RECV | Contact message (standard) |
|
||||
| 0x08 | PACKET_CHANNEL_MSG_RECV | Channel message (standard) |
|
||||
| 0x09 | PACKET_CURRENT_TIME | Current time response |
|
||||
| 0x0A | PACKET_NO_MORE_MSGS | No more messages available |
|
||||
| 0x0C | PACKET_BATTERY | Battery level |
|
||||
| 0x0D | PACKET_DEVICE_INFO | Device information |
|
||||
| 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 |
|
||||
| 0x80 | PACKET_ADVERTISEMENT | Advertisement packet |
|
||||
| 0x82 | PACKET_ACK | Acknowledgment |
|
||||
| 0x83 | PACKET_MESSAGES_WAITING | Messages waiting notification |
|
||||
| 0x88 | PACKET_LOG_DATA | RF log data (can be ignored) |
|
||||
|
||||
### Parsing Responses
|
||||
|
||||
|
|
@ -1081,33 +890,6 @@ def on_notification_received(data):
|
|||
send_command(tx_char, build_get_message())
|
||||
```
|
||||
|
||||
### QR Code Sharing
|
||||
|
||||
```python
|
||||
import secrets
|
||||
from urllib.parse import quote
|
||||
|
||||
# 1. Generate QR code data
|
||||
channel_name = "YourChannelName"
|
||||
# Generate a real secret (NOT the example value from documentation)
|
||||
secret_bytes = secrets.token_bytes(16)
|
||||
secret_hex = secret_bytes.hex()
|
||||
|
||||
# Example value in documentation: "9b647d242d6e1c5883fde0c5cf5c4c5e"
|
||||
# DO NOT use example values - always generate your own secure random secrets!
|
||||
|
||||
url = f"meshcore://channel/add?name={quote(channel_name)}&secret={secret_hex}"
|
||||
|
||||
# 2. Generate QR code image
|
||||
qr = qrcode.QRCode(version=1, box_size=10, border=5)
|
||||
qr.add_data(url)
|
||||
qr.make(fit=True)
|
||||
img = qr.make_image(fill_color="black", back_color="white")
|
||||
|
||||
# 3. Display or save QR code
|
||||
img.save("channel_qr.png")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
|
@ -1121,81 +903,37 @@ img.save("channel_qr.png")
|
|||
- Always use cryptographically secure random number generators
|
||||
- Store secrets securely (encrypted storage)
|
||||
- Never log or transmit secrets in plain text
|
||||
- Device does not return secrets - you must store them locally
|
||||
|
||||
3. **Message Handling**:
|
||||
- Poll `GET_MESSAGE` periodically or when `PACKET_MESSAGES_WAITING` is received
|
||||
- Handle message chunking for long messages (>133 characters)
|
||||
- Implement message deduplication to avoid processing the same message twice
|
||||
- Send `CMD_SYNC_NEXT_MESSAGE` when `PUSH_CODE_MSG_WAITING` is received
|
||||
- Implement message deduplication to avoid display the same message twice
|
||||
|
||||
4. **Error Handling**:
|
||||
4. **Channel Management**:
|
||||
- Fetch all channel slots even if you encounter an empty slot
|
||||
- Ideally save new channels into the first empty slot
|
||||
|
||||
5. **Error Handling**:
|
||||
- Implement timeouts for all commands (typically 5 seconds)
|
||||
- Handle `PACKET_ERROR` responses appropriately
|
||||
- Log errors for debugging but don't expose sensitive information
|
||||
|
||||
5. **Channel Management**:
|
||||
- Avoid using channel index 0 for private channels
|
||||
- Migrate channels from index 0 to 1-7 if needed
|
||||
- Query channels after connection to discover existing channels
|
||||
|
||||
---
|
||||
|
||||
## Platform-Specific Notes
|
||||
|
||||
### Android
|
||||
- Use `BluetoothGatt` API
|
||||
- Request `BLUETOOTH_CONNECT` and `BLUETOOTH_SCAN` permissions (Android 12+)
|
||||
- Enable notifications by writing to descriptor `0x2902` with value `0x01` or `0x02`
|
||||
|
||||
### iOS
|
||||
- Use `CoreBluetooth` framework
|
||||
- Implement `CBPeripheralDelegate` for notifications
|
||||
- Request Bluetooth permissions in Info.plist
|
||||
|
||||
### Python
|
||||
- Use `bleak` library for cross-platform BLE support
|
||||
- Handle async/await for BLE operations
|
||||
- Use `asyncio` for command-response patterns
|
||||
|
||||
### JavaScript/Node.js
|
||||
- Use `noble` or `@abandonware/noble` for BLE
|
||||
- Handle callbacks or promises for async operations
|
||||
- Use `Buffer` for binary data manipulation
|
||||
- Handle `RESP_CODE_ERR` responses appropriately
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Connection Issues
|
||||
|
||||
- **Device not found**: Ensure device is powered on and advertising
|
||||
- **Connection timeout**: Check Bluetooth permissions and device proximity
|
||||
- **GATT errors**: Ensure proper service/characteristic discovery
|
||||
|
||||
### Command Issues
|
||||
|
||||
- **No response**: Verify notifications are enabled, check connection state
|
||||
- **Error responses**: Verify command format, check channel index validity
|
||||
- **Timeout**: Increase timeout value or check device responsiveness
|
||||
- **Error responses**: Verify command format and check error code
|
||||
- **Timeout**: Increase timeout value or try again
|
||||
|
||||
### Message Issues
|
||||
|
||||
- **Messages not received**: Poll `GET_MESSAGE` command periodically
|
||||
- **Duplicate messages**: Implement message deduplication using timestamps/hashes
|
||||
- **Message truncation**: Split long messages into chunks
|
||||
|
||||
### Secret/Channel Issues
|
||||
- **Secret not working**: Verify secret expansion (SHA-512) is correct
|
||||
- **Channel not found**: Query channels after connection to discover existing channels
|
||||
- **Channel index 0**: Migrate to index 1-7 for private channels
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- MeshCore Python implementation: `meshcore_py-main/src/meshcore/`
|
||||
- BLE GATT Specification: Bluetooth SIG Core Specification
|
||||
- ED25519 Key Expansion: RFC 8032
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: 2025-01-01
|
||||
**Protocol Version**: Based on MeshCore v1.36.0+
|
||||
|
||||
- **Duplicate messages**: Implement message deduplication using timestamp/content as a unique id
|
||||
- **Message truncation**: Send long messages as separate shorter messages
|
||||
13
docs/docs.md
Normal file
13
docs/docs.md
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# Local Documentation
|
||||
|
||||
This document explains how to build and view the MeshCore documentation locally.
|
||||
|
||||
## Building and viewing Docs
|
||||
|
||||
```
|
||||
pip install mkdocs
|
||||
pip install mkdocs-material
|
||||
```
|
||||
|
||||
- `mkdocs serve` - Start the live-reloading docs server.
|
||||
- `mkdocs build` - Build the documentation site.
|
||||
25
docs/faq.md
25
docs/faq.md
|
|
@ -1,12 +1,7 @@
|
|||
**MeshCore-FAQ**<!-- omit from toc -->
|
||||
# Frequently Asked Questions
|
||||
|
||||
A list of frequently-asked questions and answers for MeshCore
|
||||
|
||||
The current version of this MeshCore FAQ is at https://github.com/meshcore-dev/MeshCore/blob/main/docs/faq.md.
|
||||
This MeshCore FAQ is also mirrored at https://github.com/LitBomb/MeshCore-FAQ and might have newer updates if pull requests on Scott's MeshCore repo are not approved yet.
|
||||
|
||||
author: https://github.com/LitBomb<!-- omit from toc -->
|
||||
---
|
||||
|
||||
- [1. Introduction](#1-introduction)
|
||||
- [1.1. Q: What is MeshCore?](#11-q-what-is-meshcore)
|
||||
- [1.2. Q: What do you need to start using MeshCore?](#12-q-what-do-you-need-to-start-using-meshcore)
|
||||
|
|
@ -112,15 +107,15 @@ Anyone is able to build anything they like on top of MeshCore without paying any
|
|||
|
||||
### 1.2. Q: What do you need to start using MeshCore?
|
||||
**A:** Everything you need for MeshCore is available at:
|
||||
Main web site: [https://meshcore.co.uk/](https://meshcore.co.uk/)
|
||||
Firmware Flasher: https://flasher.meshcore.co.uk/
|
||||
Phone Client Applications: https://meshcore.co.uk/apps.html
|
||||
MeshCore Firmware GitHub: https://github.com/ripplebiz/MeshCore
|
||||
|
||||
NOTE: Andy Kirby has a very useful [intro video](https://www.youtube.com/watch?v=t1qne8uJBAc) for beginners.
|
||||
- Main web site: [https://meshcore.co.uk](https://meshcore.co.uk)
|
||||
- Firmware Flasher: [https://flasher.meshcore.co.uk](https://flasher.meshcore.co.uk)
|
||||
- MeshCore Firmware on GitHub: [https://github.com/meshcore-dev/MeshCore](https://github.com/meshcore-dev/MeshCore)
|
||||
- MeshCore Companion App: [https://meshcore.nz](https://meshcore.nz)
|
||||
- MeshCore Map: [https://meshcore.co.uk/map.html](https://meshcore.co.uk/map.html)
|
||||
- Andy Kirby has a very useful [intro video](https://www.youtube.com/watch?v=t1qne8uJBAc) for beginners.
|
||||
|
||||
|
||||
You need LoRa hardware devices to run MeshCore firmware as clients or server (repeater and room server).
|
||||
You need LoRa hardware devices to run MeshCore firmware as clients or server (repeater and room server).
|
||||
|
||||
#### 1.2.1. Hardware
|
||||
MeshCore is available on a variety of 433MHz, 868MHz and 915MHz LoRa devices. For example, Lilygo T-Deck, T-Pager, RAK Wireless WisBlock RAK4631 devices (e.g. 19003, 19007, 19026), Heltec V3, Xiao S3 WIO, Xiao C3, Heltec T114, Station G2, Nano G2 Ultra, Seeed Studio T1000-E. More devices are being added regularly.
|
||||
|
|
@ -535,7 +530,7 @@ MeshCore clients would need to reset path constantly and flood traffic across th
|
|||
This could change in the future if MeshCore develops a client firmware that repeats.
|
||||
[Source](https://discord.com/channels/826570251612323860/1330643963501351004/1354780032140054659)
|
||||
|
||||
### 5.12. Q: How do I add a node to the [MeshCore Map]([url](https://meshcore.co.uk/map.html))
|
||||
### 5.12. Q: How do I add a node to the [MeshCore Map](https://meshcore.co.uk/map.html)
|
||||
**A:**
|
||||
|
||||
To add a BLE Companion radio, connect to the BLE Companion radio from the MeshCore smartphone app. In the app, tap the `3 dot` menu icon at the top right corner, then tap `Internet Map`. Tap the `3 dot` menu icon again and choose `Add me to the Map`
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
# Welcome
|
||||
# Introduction
|
||||
|
||||
Welcome to the MeshCore documentation.
|
||||
|
||||
## Building and viewing Docs
|
||||
Below are a few quick start guides.
|
||||
|
||||
```
|
||||
pip install mkdocs
|
||||
pip install mkdocs-material
|
||||
```
|
||||
- [Frequently Asked Questions](./faq.md)
|
||||
- [CLI Commands](./cli_commands.md)
|
||||
- [Companion Protocol](./companion_protocol.md)
|
||||
- [Packet Structure](./packet_structure.md)
|
||||
- [QR Codes](./qr_codes.md)
|
||||
|
||||
* `mkdocs serve` - Start the live-reloading docs server.
|
||||
* `mkdocs build` - Build the documentation site.
|
||||
If you find a mistake in any of our documentation, or find something is missing, please feel free to open a pull request for us to review.
|
||||
|
||||
- [Documentation Source](https://github.com/meshcore-dev/MeshCore/tree/main/docs)
|
||||
|
|
|
|||
34
docs/qr_codes.md
Normal file
34
docs/qr_codes.md
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# QR Codes
|
||||
|
||||
This document provides an overview of QR Code formats that can be used for sharing MeshCore channels and contacts. The formats described below are supported by the MeshCore mobile app.
|
||||
|
||||
## Add Channel
|
||||
|
||||
**Example URL**:
|
||||
|
||||
```
|
||||
meshcore://channel/add?name=Public&secret=8b3387e9c5cdea6ac9e5edbaa115cd72
|
||||
```
|
||||
|
||||
**Parameters**:
|
||||
|
||||
- `name`: Channel name (URL-encoded if needed)
|
||||
- `secret`: 16-byte secret represented as 32 hex characters
|
||||
|
||||
## Add Contact
|
||||
|
||||
**Example URL**:
|
||||
|
||||
```
|
||||
meshcore://contact/add?name=Example+Contact&public_key=9cd8fcf22a47333b591d96a2b848b73f457b1bb1a3ea2453a885f9e5787765b1&type=1
|
||||
```
|
||||
|
||||
**Parameters**:
|
||||
|
||||
- `name`: Contact name (URL-encoded if needed)
|
||||
- `public_key`: 32-byte public key represented as 64 hex characters
|
||||
- `type`: numeric contact type
|
||||
- `1`: Companion
|
||||
- `2`: Repeater
|
||||
- `3`: Room Server
|
||||
- `4`: Sensor
|
||||
96
docs/terminal_chat_cli.md
Normal file
96
docs/terminal_chat_cli.md
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
# Terminal Chat CLI
|
||||
|
||||
Below are the commands you can enter into the Terminal Chat clients:
|
||||
|
||||
```
|
||||
set freq {frequency}
|
||||
```
|
||||
Set the LoRa frequency. Example: set freq 915.8
|
||||
|
||||
```
|
||||
set tx {tx-power-dbm}
|
||||
```
|
||||
Sets LoRa transmit power in dBm.
|
||||
|
||||
```
|
||||
set name {name}
|
||||
```
|
||||
Sets your advertisement name.
|
||||
|
||||
```
|
||||
set lat {latitude}
|
||||
```
|
||||
Sets your advertisement map latitude. (decimal degrees)
|
||||
|
||||
```
|
||||
set lon {longitude}
|
||||
```
|
||||
Sets your advertisement map longitude. (decimal degrees)
|
||||
|
||||
```
|
||||
set af {air-time-factor}
|
||||
```
|
||||
Sets the transmit air-time-factor.
|
||||
|
||||
|
||||
```
|
||||
time {epoch-secs}
|
||||
```
|
||||
Set the device clock using UNIX epoch seconds. Example: time 1738242833
|
||||
|
||||
|
||||
```
|
||||
advert
|
||||
```
|
||||
Sends an advertisement packet
|
||||
|
||||
```
|
||||
clock
|
||||
```
|
||||
Displays current time per device's clock.
|
||||
|
||||
|
||||
```
|
||||
ver
|
||||
```
|
||||
Shows the device version and firmware build date.
|
||||
|
||||
```
|
||||
card
|
||||
```
|
||||
Displays *your* 'business card', for other to manually _import_
|
||||
|
||||
```
|
||||
import {card}
|
||||
```
|
||||
Imports the given card to your contacts.
|
||||
|
||||
```
|
||||
list {n}
|
||||
```
|
||||
List all contacts by most recent. (optional {n}, is the last n by advertisement date)
|
||||
|
||||
```
|
||||
to
|
||||
```
|
||||
Shows the name of current recipient contact. (for subsequent 'send' commands)
|
||||
|
||||
```
|
||||
to {name-prefix}
|
||||
```
|
||||
Sets the recipient to the _first_ matching contact (in 'list') by the name prefix. (ie. you don't have to type whole name)
|
||||
|
||||
```
|
||||
send {text}
|
||||
```
|
||||
Sends the text message (as DM) to current recipient.
|
||||
|
||||
```
|
||||
reset path
|
||||
```
|
||||
Resets the path to current recipient, for new path discovery.
|
||||
|
||||
```
|
||||
public {text}
|
||||
```
|
||||
Sends the text message to the built-in 'public' group channel
|
||||
Loading…
Add table
Add a link
Reference in a new issue