# PEAT-BTLE API Reference
This document provides a comprehensive guide to the main types, traits, and APIs in the `peat-btle` crate.
## Table of Contents
- [Overview](#overview)
- [Core Types](#core-types)
- [NodeId](#nodeid)
- [HierarchyLevel](#hierarchylevel)
- [Capabilities](#capabilities)
- [Entry Points](#entry-points)
- [PeatMesh (High-Level)](#hivemesh-high-level)
- [BluetoothLETransport (Low-Level)](#bluetoothletransport-low-level)
- [Configuration](#configuration)
- [BleConfig](#bleconfig)
- [PeatMeshConfig](#hivemeshconfig)
- [PowerProfile](#powerprofile)
- [BlePhy](#blephy)
- [Platform Abstraction](#platform-abstraction)
- [BleAdapter Trait](#bleadapter-trait)
- [BleConnection Trait](#bleconnection-trait)
- [Security](#security)
- [Mesh-Wide Encryption](#mesh-wide-encryption)
- [Per-Peer E2EE](#per-peer-e2ee)
- [Events and Observers](#events-and-observers)
- [PeatEvent](#hiveevent)
- [PeatObserver Trait](#hiveobserver-trait)
- [Error Handling](#error-handling)
- [Feature Flags](#feature-flags)
---
## Overview
`peat-btle` provides two main entry points:
| `PeatMesh` | Full mesh management with peers, sync, events | High-level |
| `BluetoothLETransport` | Raw BLE transport for custom implementations | Low-level |
For most applications, use `PeatMesh`. It handles peer discovery, document synchronization, encryption, and event notification automatically.
---
## Core Types
### NodeId
A 32-bit unique identifier for nodes in the mesh.
```rust
use peat_btle::NodeId;
// From explicit value
let node = NodeId::new(0x12345678);
// From MAC address
let mac = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF];
let node = NodeId::from_mac_address(&mac); // Uses last 4 bytes
// From MAC string
let node = NodeId::from_mac_string("AA:BB:CC:DD:EE:FF").unwrap();
// Parse hex string
let node = NodeId::parse("12345678").unwrap();
let node = NodeId::parse("0x12345678").unwrap();
// Display
println!("{}", node); // "12345678" (uppercase hex)
// Conversions
let raw: u32 = node.as_u32();
let node: NodeId = 0x12345678.into();
```
### HierarchyLevel
Represents the node's position in the tactical hierarchy.
```rust
use peat_btle::HierarchyLevel;
let level = HierarchyLevel::Platform; // Leaf node (soldier)
let level = HierarchyLevel::Squad; // Squad leader
let level = HierarchyLevel::Platoon; // Platoon leader
let level = HierarchyLevel::Company; // Company command
// Conversions
let byte: u8 = level.into();
let level: HierarchyLevel = 2u8.into(); // Platoon
```
### Capabilities
Bitflags indicating node capabilities, advertised in the Peat beacon.
```rust
use peat_btle::capabilities;
let caps = capabilities::LITE_NODE // Peat-Lite node
| capabilities::SENSOR_ACCEL // Has accelerometer
| capabilities::HAS_GPS // Has GPS
| capabilities::CAN_RELAY; // Can relay messages
// Check capabilities
if caps & capabilities::CODED_PHY != 0 {
// Node supports Coded PHY for long range
}
```
Available flags:
- `LITE_NODE` (0x0001): Peat-Lite node (minimal state)
- `SENSOR_ACCEL` (0x0002): Has accelerometer
- `SENSOR_TEMP` (0x0004): Has temperature sensor
- `SENSOR_BUTTON` (0x0008): Has button input
- `ACTUATOR_LED` (0x0010): Has LED output
- `ACTUATOR_VIBRATE` (0x0020): Has vibration motor
- `HAS_DISPLAY` (0x0040): Has display
- `CAN_RELAY` (0x0080): Can relay messages
- `CODED_PHY` (0x0100): Supports Coded PHY
- `HAS_GPS` (0x0200): Has GPS
---
## Entry Points
### PeatMesh (High-Level)
`PeatMesh` is the main facade for Peat BLE mesh operations. It composes peer management, document sync, and observer notifications.
**Creation:**
```rust
use peat_btle::{PeatMesh, PeatMeshConfig, NodeId};
let config = PeatMeshConfig::new(
NodeId::new(0x12345678),
"ALPHA-1", // Callsign
"DEMO", // Mesh ID
);
let mesh = PeatMesh::new(config);
```
**Configuration Options:**
```rust
let config = PeatMeshConfig::new(node_id, "ALPHA-1", "DEMO")
.with_encryption([0x42u8; 32]) // Enable mesh-wide encryption
.with_strict_encryption() // Reject unencrypted docs
.with_sync_interval(5000) // Sync every 5 seconds
.with_peer_timeout(30_000) // 30 second peer timeout
.with_max_peers(10) // Maximum 10 peers
.with_peripheral_type(PeripheralType::SoldierSensor);
```
**BLE Callbacks (Platform Integration):**
Your platform BLE layer calls these methods:
```rust
// When a device is discovered
mesh.on_ble_discovered(
"device-uuid", // Platform identifier
Some("HIVE_DEMO-AABBCCDD"), // Device name
-65, // RSSI in dBm
Some("DEMO"), // Mesh ID from name
now_ms, // Current timestamp
);
// When connected
mesh.on_ble_connected("device-uuid", now_ms);
// When disconnected
mesh.on_ble_disconnected("device-uuid", DisconnectReason::RemoteRequest);
// When data received
let result = mesh.on_ble_data_received("device-uuid", &data, now_ms);
if let Some(result) = result {
if result.is_emergency {
// Handle emergency!
}
}
// Periodic maintenance (call every ~1 second)
if let Some(sync_data) = mesh.tick(now_ms) {
// Broadcast sync_data to connected peers
}
```
**User Actions:**
```rust
// Send emergency alert
let doc = mesh.send_emergency(timestamp);
// Broadcast `doc` to all peers
// Send ACK
let doc = mesh.send_ack(timestamp);
// Clear event
mesh.clear_event();
// Check state
mesh.is_emergency_active();
mesh.is_ack_active();
```
**Emergency with ACK Tracking:**
```rust
// Start emergency with known peers
let doc = mesh.start_emergency_with_known_peers(timestamp);
// Check ACK status
let (source, timestamp, acked, pending) = mesh.get_emergency_status().unwrap();
println!("{} of {} peers ACKed", acked, acked + pending);
// Check if specific peer ACKed
if mesh.has_peer_acked(peer_node_id) { /* ... */ }
// Check if all peers ACKed
if mesh.all_peers_acked() { /* ... */ }
```
**State Queries:**
```rust
mesh.node_id() // Our NodeId
mesh.callsign() // Our callsign
mesh.mesh_id() // Mesh identifier
mesh.device_name() // BLE device name (e.g., "HIVE_DEMO-12345678")
mesh.peer_count() // Number of known peers
mesh.connected_count() // Number of connected peers
mesh.get_peers() // Vec<PeatPeer> of all peers
mesh.get_connected_peers() // Vec<PeatPeer> of connected peers
mesh.get_peer(node_id) // Option<PeatPeer>
mesh.total_count() // CRDT counter total
mesh.version() // Document version
```
**Health Updates:**
```rust
mesh.update_health(battery_percent); // 0-100
mesh.update_activity(activity_level); // 0=still, 1=walking, 2=running, 3=fall
mesh.update_health_full(battery, activity);
```
### BluetoothLETransport (Low-Level)
For custom transport implementations that need direct control.
```rust
use peat_btle::{BluetoothLETransport, BleConfig, NodeId, MeshTransport};
let config = BleConfig::hive_lite(NodeId::new(0x12345678));
let adapter = platform::linux::BluerAdapter::new()?;
let transport = BluetoothLETransport::new(config, adapter);
// Start transport
transport.start().await?;
// Connect to peer
let conn = transport.connect(&peer_id).await?;
// Query state
transport.peer_count();
transport.connected_peers();
transport.capabilities();
// Stop
transport.stop().await?;
```
---
## Configuration
### BleConfig
Main configuration structure for the BLE transport.
```rust
use peat_btle::{BleConfig, NodeId, PowerProfile, BlePhy};
// Default configuration
let config = BleConfig::new(NodeId::new(0x12345678));
// Peat-Lite optimized (low power, leaf node)
let config = BleConfig::hive_lite(NodeId::new(0x12345678));
```
**Fields:**
| `node_id` | `NodeId` | This node's identifier |
| `capabilities` | `u16` | Capability flags |
| `hierarchy_level` | `u8` | Position in hierarchy (0-3) |
| `geohash` | `u32` | 24-bit geohash location |
| `discovery` | `DiscoveryConfig` | Scan/advertise settings |
| `gatt` | `GattConfig` | GATT settings |
| `mesh` | `MeshConfig` | Mesh topology settings |
| `power_profile` | `PowerProfile` | Power management profile |
| `phy` | `PhyConfig` | PHY selection settings |
| `security` | `SecurityConfig` | Security settings |
### PeatMeshConfig
Configuration for the high-level `PeatMesh` facade.
```rust
use peat_btle::{PeatMeshConfig, NodeId};
use peat_btle::sync::crdt::PeripheralType;
let config = PeatMeshConfig::new(
NodeId::new(0x12345678),
"ALPHA-1", // callsign
"DEMO", // mesh_id
);
```
**Builder Methods:**
| `.with_encryption(secret)` | Enable mesh-wide encryption |
| `.with_strict_encryption()` | Reject unencrypted documents |
| `.with_peripheral_type(type)` | Set device type |
| `.with_sync_interval(ms)` | Set sync broadcast interval |
| `.with_peer_timeout(ms)` | Set peer timeout |
| `.with_max_peers(n)` | Set maximum peer count |
### PowerProfile
Controls radio duty cycle for power management.
```rust
use peat_btle::PowerProfile;
// Preset profiles
let profile = PowerProfile::Aggressive; // ~20% duty, ~6h battery
let profile = PowerProfile::Balanced; // ~10% duty, ~12h battery
let profile = PowerProfile::LowPower; // ~2% duty, ~20h battery
// Custom profile
let profile = PowerProfile::Custom {
scan_interval_ms: 5000,
scan_window_ms: 100,
adv_interval_ms: 2000,
conn_interval_ms: 100,
};
// Query profile
profile.scan_interval_ms();
profile.scan_window_ms();
profile.adv_interval_ms();
profile.conn_interval_ms();
profile.duty_cycle_percent();
```
### BlePhy
BLE Physical Layer options (BLE 5.0+).
```rust
use peat_btle::BlePhy;
let phy = BlePhy::Le1M; // 1 Mbps, ~100m range (default)
let phy = BlePhy::Le2M; // 2 Mbps, ~50m range
let phy = BlePhy::LeCodedS2; // 500 kbps, ~200m range
let phy = BlePhy::LeCodedS8; // 125 kbps, ~400m range
// Query PHY properties
phy.bandwidth_bps(); // Theoretical bandwidth
phy.typical_range_meters(); // Typical range
phy.requires_ble5(); // Needs BLE 5.0?
```
---
## Platform Abstraction
### BleAdapter Trait
Each platform implements this trait to provide BLE functionality.
```rust
use peat_btle::platform::BleAdapter;
#[async_trait]
pub trait BleAdapter: Send + Sync {
// Lifecycle
async fn init(&mut self, config: &BleConfig) -> Result<()>;
async fn start(&self) -> Result<()>;
async fn stop(&self) -> Result<()>;
fn is_powered(&self) -> bool;
fn address(&self) -> Option<String>;
// Discovery
async fn start_scan(&self, config: &DiscoveryConfig) -> Result<()>;
async fn stop_scan(&self) -> Result<()>;
async fn start_advertising(&self, config: &DiscoveryConfig) -> Result<()>;
async fn stop_advertising(&self) -> Result<()>;
fn set_discovery_callback(&mut self, callback: Option<DiscoveryCallback>);
// Connections
async fn connect(&self, peer_id: &NodeId) -> Result<Box<dyn BleConnection>>;
async fn disconnect(&self, peer_id: &NodeId) -> Result<()>;
fn get_connection(&self, peer_id: &NodeId) -> Option<Box<dyn BleConnection>>;
fn peer_count(&self) -> usize;
fn connected_peers(&self) -> Vec<NodeId>;
fn set_connection_callback(&mut self, callback: Option<ConnectionCallback>);
// GATT
async fn register_gatt_service(&self) -> Result<()>;
async fn unregister_gatt_service(&self) -> Result<()>;
// Capabilities
fn supports_coded_phy(&self) -> bool;
fn supports_extended_advertising(&self) -> bool;
fn max_mtu(&self) -> u16;
fn max_connections(&self) -> u8;
}
```
**Platform Implementations:**
| Linux | `platform::linux` | `BluerAdapter` |
| Android | `platform::android` | `AndroidAdapter` |
| macOS/iOS | `platform::apple` | `CoreBluetoothAdapter` |
| Windows | `platform::windows` | `WinRTAdapter` |
| ESP32 | `platform::esp32` | `NimBLEAdapter` |
| Testing | `platform::mock` | `MockAdapter` |
### BleConnection Trait
Represents an active GATT connection.
```rust
pub trait BleConnection: Send + Sync {
fn peer_id(&self) -> &NodeId;
fn is_alive(&self) -> bool;
fn mtu(&self) -> u16;
fn phy(&self) -> BlePhy;
fn rssi(&self) -> Option<i8>;
fn connected_duration(&self) -> Duration;
}
```
---
## Security
### Mesh-Wide Encryption
All mesh members share a secret. Protects against external eavesdroppers.
**Via PeatMesh:**
```rust
// At creation
let config = PeatMeshConfig::new(node_id, "ALPHA", "DEMO")
.with_encryption([0x42u8; 32]);
let mesh = PeatMesh::new(config);
// At runtime
mesh.enable_encryption(&[0x42u8; 32]);
mesh.disable_encryption();
// Query state
mesh.is_encryption_enabled();
mesh.is_strict_encryption_enabled();
```
**Direct API (Advanced):**
```rust
use peat_btle::security::MeshEncryptionKey;
let secret = [0x42u8; 32];
let key = MeshEncryptionKey::from_shared_secret("DEMO", &secret);
// Encrypt
let ciphertext = key.encrypt(b"plaintext").unwrap();
// Decrypt
let plaintext = key.decrypt(&ciphertext).unwrap();
// Byte format for transmission
let bytes = key.encrypt_to_bytes(b"plaintext").unwrap();
let plaintext = key.decrypt_from_bytes(&bytes).unwrap();
```
**Overhead:** 30 bytes (2 marker + 12 nonce + 16 auth tag)
### Per-Peer E2EE
Two specific peers establish encrypted sessions via X25519 key exchange. Only sender and recipient can decrypt.
**Via PeatMesh:**
```rust
// Enable E2EE capability
mesh.enable_peer_e2ee();
// Initiate session with specific peer
let key_exchange = mesh.initiate_peer_e2ee(peer_node_id, now_ms);
// Send key_exchange bytes to peer
// After key exchange completes
if mesh.has_peer_e2ee_session(peer_node_id) {
// Send encrypted message
let encrypted = mesh.send_peer_e2ee(peer_node_id, b"secret", now_ms);
// Send encrypted bytes to peer
}
// Query state
mesh.is_peer_e2ee_enabled();
mesh.peer_e2ee_public_key();
mesh.peer_e2ee_session_state(peer_node_id);
mesh.peer_e2ee_session_count();
mesh.peer_e2ee_established_count();
// Close session
mesh.close_peer_e2ee(peer_node_id);
```
**Direct API (Advanced):**
```rust
use peat_btle::security::PeerSessionManager;
use peat_btle::NodeId;
let mut alice = PeerSessionManager::new(NodeId::new(0x11111111));
let mut bob = PeerSessionManager::new(NodeId::new(0x22222222));
// Alice initiates
let alice_msg = alice.initiate_session(NodeId::new(0x22222222), now_ms);
// Bob responds
let (bob_response, established) = bob.handle_key_exchange(&alice_msg, now_ms).unwrap();
// Alice completes
alice.handle_key_exchange(&bob_response, now_ms).unwrap();
// Now both can encrypt/decrypt
let encrypted = alice.encrypt_for_peer(NodeId::new(0x22222222), b"secret", now_ms).unwrap();
let decrypted = bob.decrypt_from_peer(&encrypted, now_ms).unwrap();
```
**Overhead:** 46 bytes (2 marker + 4 recipient + 4 sender + 8 counter + 12 nonce + 16 tag)
---
## Events and Observers
### PeatEvent
Events emitted by the mesh.
```rust
use peat_btle::observer::PeatEvent;
match event {
// Peer lifecycle
PeatEvent::PeerDiscovered { peer } => { /* new peer found */ }
PeatEvent::PeerConnected { node_id } => { /* peer connected */ }
PeatEvent::PeerDisconnected { node_id, reason } => { /* peer disconnected */ }
PeatEvent::PeerLost { node_id } => { /* peer timed out */ }
// Mesh events
PeatEvent::EmergencyReceived { from_node } => { /* emergency! */ }
PeatEvent::AckReceived { from_node } => { /* peer ACKed */ }
PeatEvent::DocumentSynced { from_node, total_count } => { /* sync complete */ }
PeatEvent::MeshStateChanged { peer_count, connected_count } => { /* state change */ }
// Per-peer E2EE
PeatEvent::PeerE2eeEstablished { peer_node_id } => { /* E2EE ready */ }
PeatEvent::PeerE2eeClosed { peer_node_id } => { /* E2EE ended */ }
PeatEvent::PeerE2eeMessageReceived { from_node, data } => { /* encrypted msg */ }
// Security
PeatEvent::SecurityViolation { kind, source } => { /* security issue */ }
}
```
### PeatObserver Trait
Implement to receive mesh events.
```rust
use peat_btle::observer::{PeatEvent, PeatObserver};
use std::sync::Arc;
struct MyObserver;
impl PeatObserver for MyObserver {
fn on_event(&self, event: PeatEvent) {
match event {
PeatEvent::EmergencyReceived { from_node } => {
println!("EMERGENCY from {:08X}!", from_node.as_u32());
// Play alarm, show notification, etc.
}
_ => {}
}
}
}
// Register observer
let observer = Arc::new(MyObserver);
mesh.add_observer(observer.clone());
// Remove when done
mesh.remove_observer(&observer);
```
**Testing Helper:**
```rust
use peat_btle::observer::CollectingObserver;
let observer = Arc::new(CollectingObserver::new());
mesh.add_observer(observer.clone());
// ... perform operations ...
let events = observer.events();
---
## Error Handling
All fallible operations return `Result<T, BleError>`.
```rust
use peat_btle::{BleError, Result};
fn example() -> Result<()> {
// Errors you may encounter:
Err(BleError::AdapterNotAvailable)?;
Err(BleError::NotPowered)?;
Err(BleError::PermissionDenied("location".into()))?;
Err(BleError::NotSupported("coded_phy".into()))?;
Err(BleError::ConnectionFailed("timeout".into()))?;
Err(BleError::ConnectionLost("link_loss".into()))?;
Err(BleError::GattError("write failed".into()))?;
Err(BleError::Timeout)?;
Err(BleError::InvalidConfig("bad interval".into()))?;
Err(BleError::ResourceExhausted("max connections".into()))?;
Ok(())
}
```
---
## Feature Flags
| `std` | Standard library support | Yes |
| `linux` | Linux/BlueZ support | No |
| `android` | Android JNI support | No |
| `macos` | macOS CoreBluetooth | No |
| `ios` | iOS CoreBluetooth | No |
| `windows` | Windows WinRT | No |
| `embedded` | Embedded/no_std support | No |
| `esp32` | ESP32 NimBLE support | No |
| `coded-phy` | Enable Coded PHY | No |
| `extended-adv` | Extended advertising | No |
**Usage in Cargo.toml:**
```toml
[dependencies]
peat-btle = { version = "0.1", features = ["linux", "coded-phy"] }
```
**Conditional Compilation:**
```rust
#[cfg(feature = "linux")]
use peat_btle::platform::linux::BluerAdapter;
#[cfg(feature = "android")]
use peat_btle::platform::android::AndroidAdapter;
```
---
## Constants
```rust
use peat_btle::{
PEAT_SERVICE_UUID, // 128-bit service UUID
PEAT_SERVICE_UUID_16BIT, // 16-bit short form (0xF47A)
CHAR_NODE_INFO_UUID, // Node info characteristic
CHAR_SYNC_STATE_UUID, // Sync state characteristic
CHAR_SYNC_DATA_UUID, // Sync data characteristic
CHAR_COMMAND_UUID, // Command characteristic
CHAR_STATUS_UUID, // Status characteristic
VERSION, // Crate version
};
```
---
## Common Patterns
### Basic Mesh Setup
```rust
use peat_btle::{PeatMesh, PeatMeshConfig, NodeId};
use peat_btle::observer::{PeatEvent, PeatObserver};
use std::sync::Arc;
// 1. Create config
let config = PeatMeshConfig::new(
NodeId::new(0x12345678),
"ALPHA-1",
"DEMO",
);
// 2. Create mesh
let mesh = PeatMesh::new(config);
// 3. Add observer
struct Handler;
impl PeatObserver for Handler {
fn on_event(&self, event: PeatEvent) {
// Handle events
}
}
mesh.add_observer(Arc::new(Handler));
// 4. Platform integration (called from BLE callbacks)
// mesh.on_ble_discovered(...)
// mesh.on_ble_connected(...)
// mesh.on_ble_data_received(...)
// 5. Periodic tick
loop {
if let Some(data) = mesh.tick(now_ms()) {
// Broadcast data to peers
}
sleep(Duration::from_secs(1));
}
```
### Emergency Flow
```rust
// Sender
let doc = mesh.start_emergency_with_known_peers(now_ms());
broadcast_to_peers(&doc);
// Receivers automatically get EmergencyReceived event
// Receiver sends ACK
let ack_doc = mesh.ack_emergency(now_ms());
broadcast_to_peers(&ack_doc.unwrap());
// Sender checks ACK status
while !mesh.all_peers_acked() {
let (_, _, acked, pending) = mesh.get_emergency_status().unwrap();
println!("ACK: {}/{}", acked, acked + pending);
}
```
### Encrypted Mesh
```rust
let secret = derive_key_from_password("formation-password");
let config = PeatMeshConfig::new(node_id, "ALPHA", "DEMO")
.with_encryption(secret)
.with_strict_encryption();
let mesh = PeatMesh::new(config);
// All documents automatically encrypted/decrypted
// SecurityViolation events for unauthorized messages
```