pub struct PeatMesh { /* private fields */ }Expand description
Main facade for Peat BLE mesh operations
Composes peer management, document sync, and observer notifications. Platform implementations call into this from their BLE callbacks.
Implementations§
Source§impl PeatMesh
impl PeatMesh
Sourcepub fn new(config: PeatMeshConfig) -> Self
pub fn new(config: PeatMeshConfig) -> Self
Create a new PeatMesh instance
Sourcepub fn with_identity(config: PeatMeshConfig, identity: DeviceIdentity) -> Self
pub fn with_identity(config: PeatMeshConfig, identity: DeviceIdentity) -> Self
Create a new PeatMesh with a cryptographic identity
The node_id will be derived from the identity’s public key, overriding any node_id specified in the config. This ensures cryptographic binding between node_id and identity.
Sourcepub fn from_genesis(
genesis: &MeshGenesis,
identity: DeviceIdentity,
callsign: &str,
) -> Self
pub fn from_genesis( genesis: &MeshGenesis, identity: DeviceIdentity, callsign: &str, ) -> Self
Create a new PeatMesh from genesis data
This is the recommended way to create a mesh for production use. The mesh will be configured with:
- node_id derived from identity
- mesh_id from genesis
- encryption enabled using genesis-derived secret
Sourcepub fn from_persisted(
state: PersistedState,
callsign: &str,
) -> Result<Self, PersistenceError>
pub fn from_persisted( state: PersistedState, callsign: &str, ) -> Result<Self, PersistenceError>
Create a PeatMesh from persisted state.
Restores mesh configuration from previously saved state, including:
- Device identity (Ed25519 keypair)
- Mesh genesis (if present)
- Identity registry (TOFU cache)
Use this on device boot to restore mesh membership without re-provisioning.
§Arguments
state- Previously persisted statecallsign- Human-readable identifier (may differ from original)
§Errors
Returns PersistenceError if the identity cannot be restored.
§Example
// On boot, restore from secure storage
let state = PersistedState::load(&storage)?;
let mesh = PeatMesh::from_persisted(state, "SENSOR-01")?;Sourcepub fn to_persisted_state(
&self,
genesis: Option<&MeshGenesis>,
) -> Option<PersistedState>
pub fn to_persisted_state( &self, genesis: Option<&MeshGenesis>, ) -> Option<PersistedState>
Create persisted state from current mesh state.
Captures the current identity, genesis, and registry for persistence. Call this periodically or before shutdown to save state.
§Arguments
genesis- Optional genesis to include (if mesh was created from genesis)
§Returns
None if the mesh has no identity bound.
Sourcepub fn acknowledge_polled_translator_consumer(&self)
pub fn acknowledge_polled_translator_consumer(&self)
Mark this PeatMesh as having a polled-field consumer (ADR-059
Amendment 3). Hosts that read
DataReceivedResult::decoded_translator_frame per receive and
forward through their own publish path SHOULD call this once at
startup, after constructing PeatMesh and before any GATT
receive arrives. Without this attestation, the receive dispatch
has no way to distinguish a polled-consumer host from one that
decoded the frame and dropped it on the floor, and
PeatEvent::TranslatorNoCallback will fire for every frame.
Idempotent — calling again is a no-op. Defined unconditionally
so the binding shape is stable across feature combos; when
translator-codec is off the suppression-check read site is
gated alongside the rest of the dispatch logic, so the flag has
no effect (still safe to call).
Sourcepub fn is_encryption_enabled(&self) -> bool
pub fn is_encryption_enabled(&self) -> bool
Check if mesh-wide encryption is enabled
Sourcepub fn is_strict_encryption_enabled(&self) -> bool
pub fn is_strict_encryption_enabled(&self) -> bool
Check if strict encryption mode is enabled
Returns true only if both encryption and strict_encryption are enabled.
Sourcepub fn enable_encryption(&mut self, secret: &[u8; 32])
pub fn enable_encryption(&mut self, secret: &[u8; 32])
Enable mesh-wide encryption with a shared secret
Derives a ChaCha20-Poly1305 key from the secret using HKDF-SHA256. All mesh participants must use the same secret to communicate.
Sourcepub fn disable_encryption(&mut self)
pub fn disable_encryption(&mut self)
Disable mesh-wide encryption
Sourcepub fn decrypt_only(&self, data: &[u8]) -> Option<Vec<u8>>
pub fn decrypt_only(&self, data: &[u8]) -> Option<Vec<u8>>
Decrypt data without parsing (transport-only operation)
This method provides raw decrypted bytes for apps that want to handle message parsing themselves (using peat-lite or other libraries).
§Arguments
data- Potentially encrypted data (0xAE marker indicates encryption)
§Returns
Some(plaintext)- Decrypted bytes if successful, or original bytes if unencryptedNone- If decryption failed (wrong key, corrupted, or strict mode violation)
Sourcepub fn has_identity(&self) -> bool
pub fn has_identity(&self) -> bool
Check if this mesh has a cryptographic identity
Sourcepub fn public_key(&self) -> Option<[u8; 32]>
pub fn public_key(&self) -> Option<[u8; 32]>
Get this node’s public key (if identity is configured)
Sourcepub fn create_attestation(&self, now_ms: u64) -> Option<IdentityAttestation>
pub fn create_attestation(&self, now_ms: u64) -> Option<IdentityAttestation>
Create an identity attestation for this node
Returns None if no identity is configured.
Sourcepub fn verify_peer_identity(
&self,
attestation: &IdentityAttestation,
) -> RegistryResult
pub fn verify_peer_identity( &self, attestation: &IdentityAttestation, ) -> RegistryResult
Verify and register a peer’s identity attestation
Implements TOFU (Trust On First Use):
- On first contact, registers the node_id → public_key binding
- On subsequent contacts, verifies the public key matches
Returns the verification result. Security violations should be handled by the caller (e.g., disconnect, alert).
Sourcepub fn is_peer_identity_known(&self, node_id: NodeId) -> bool
pub fn is_peer_identity_known(&self, node_id: NodeId) -> bool
Check if a peer’s identity is known (has been registered)
Sourcepub fn peer_public_key(&self, node_id: NodeId) -> Option<[u8; 32]>
pub fn peer_public_key(&self, node_id: NodeId) -> Option<[u8; 32]>
Get a peer’s public key if known
Sourcepub fn known_identity_count(&self) -> usize
pub fn known_identity_count(&self) -> usize
Get the number of known peer identities
Sourcepub fn pre_register_peer_identity(
&self,
node_id: NodeId,
public_key: [u8; 32],
now_ms: u64,
)
pub fn pre_register_peer_identity( &self, node_id: NodeId, public_key: [u8; 32], now_ms: u64, )
Pre-register a peer’s identity (for out-of-band key exchange)
Use this when keys are exchanged through a secure side channel (e.g., QR code, NFC tap, or provisioning server).
Sourcepub fn forget_peer_identity(&self, node_id: NodeId)
pub fn forget_peer_identity(&self, node_id: NodeId)
Remove a peer’s identity from the registry
Use with caution - this allows re-registration with a different key.
Sourcepub fn sign(&self, data: &[u8]) -> Option<[u8; 64]>
pub fn sign(&self, data: &[u8]) -> Option<[u8; 64]>
Sign arbitrary data with this node’s identity
Returns None if no identity is configured.
Sourcepub fn verify_peer_signature(
&self,
node_id: NodeId,
data: &[u8],
signature: &[u8; 64],
) -> bool
pub fn verify_peer_signature( &self, node_id: NodeId, data: &[u8], signature: &[u8; 64], ) -> bool
Verify a signature from a peer
Uses the peer’s public key from the identity registry. Returns false if peer is unknown or signature is invalid.
Sourcepub fn is_relay_enabled(&self) -> bool
pub fn is_relay_enabled(&self) -> bool
Check if multi-hop relay is enabled
Sourcepub fn enable_relay(&mut self)
pub fn enable_relay(&mut self)
Enable multi-hop relay
Sourcepub fn disable_relay(&mut self)
pub fn disable_relay(&mut self)
Disable multi-hop relay
Sourcepub fn has_seen_message(&self, message_id: &MessageId) -> bool
pub fn has_seen_message(&self, message_id: &MessageId) -> bool
Check if a message has been seen before (for deduplication)
Returns true if the message was already seen (duplicate).
Sourcepub fn mark_message_seen(
&self,
message_id: MessageId,
origin: NodeId,
now_ms: u64,
) -> bool
pub fn mark_message_seen( &self, message_id: MessageId, origin: NodeId, now_ms: u64, ) -> bool
Mark a message as seen
Returns true if this is a new message (first time seen).
Sourcepub fn seen_cache_size(&self) -> usize
pub fn seen_cache_size(&self) -> usize
Get the number of entries in the seen message cache
Sourcepub fn clear_seen_cache(&self)
pub fn clear_seen_cache(&self)
Clear the seen message cache
Sourcepub fn wrap_for_relay(&self, payload: Vec<u8>) -> Vec<u8> ⓘ
pub fn wrap_for_relay(&self, payload: Vec<u8>) -> Vec<u8> ⓘ
Wrap a document in a relay envelope for multi-hop transmission
The returned bytes can be sent to peers and will be automatically relayed through the mesh if relay is enabled on receiving nodes.
Sourcepub fn get_relay_targets(&self, exclude_peer: Option<NodeId>) -> Vec<PeatPeer>
pub fn get_relay_targets(&self, exclude_peer: Option<NodeId>) -> Vec<PeatPeer>
Get peers to relay a message to
Uses the configured gossip strategy to select relay targets. Excludes the source peer (if provided) to avoid sending back to sender.
Sourcepub fn process_relay_envelope(
&self,
data: &[u8],
source_peer: NodeId,
now_ms: u64,
) -> Option<RelayDecision>
pub fn process_relay_envelope( &self, data: &[u8], source_peer: NodeId, now_ms: u64, ) -> Option<RelayDecision>
Process an incoming relay envelope
Handles deduplication, TTL checking, and determines if the message should be processed and/or relayed.
Returns:
Ok(Some(RelayDecision))if message should be processed/relayedOk(None)if message was a duplicate or TTL expiredErrif parsing failed
Sourcepub fn build_relay_document(&self) -> Vec<u8> ⓘ
pub fn build_relay_document(&self) -> Vec<u8> ⓘ
Build a document wrapped in a relay envelope
Convenience method that builds the document, encrypts it (if enabled), and wraps it in a relay envelope for multi-hop transmission.
Sourcepub fn register_peer_for_delta(&self, peer_id: &NodeId)
pub fn register_peer_for_delta(&self, peer_id: &NodeId)
Register a peer for delta sync tracking
Call this when a peer connects to start tracking what data has been sent to them. This enables future delta sync (sending only changes).
Sourcepub fn unregister_peer_for_delta(&self, peer_id: &NodeId)
pub fn unregister_peer_for_delta(&self, peer_id: &NodeId)
Unregister a peer from delta sync tracking
Call this when a peer disconnects to clean up tracking state.
Sourcepub fn reset_peer_delta_state(&self, peer_id: &NodeId)
pub fn reset_peer_delta_state(&self, peer_id: &NodeId)
Reset delta sync state for a peer
Call this when a peer reconnects to force a full sync on next communication. This clears the record of what was previously sent.
Sourcepub fn record_delta_sent(&self, peer_id: &NodeId, bytes: usize)
pub fn record_delta_sent(&self, peer_id: &NodeId, bytes: usize)
Record bytes sent to a peer (for delta statistics)
Sourcepub fn record_delta_received(
&self,
peer_id: &NodeId,
bytes: usize,
timestamp: u64,
)
pub fn record_delta_received( &self, peer_id: &NodeId, bytes: usize, timestamp: u64, )
Record bytes received from a peer (for delta statistics)
Sourcepub fn delta_stats(&self) -> DeltaStats
pub fn delta_stats(&self) -> DeltaStats
Get delta sync statistics
Returns aggregate statistics about delta sync across all peers, including bytes sent/received and sync counts.
Sourcepub fn peer_delta_stats(&self, peer_id: &NodeId) -> Option<(u64, u64, u32)>
pub fn peer_delta_stats(&self, peer_id: &NodeId) -> Option<(u64, u64, u32)>
Get delta sync statistics for a specific peer
Returns the bytes sent/received and sync count for a single peer.
Sourcepub fn build_delta_document_for_peer(
&self,
peer_id: &NodeId,
now_ms: u64,
) -> Option<Vec<u8>>
pub fn build_delta_document_for_peer( &self, peer_id: &NodeId, now_ms: u64, ) -> Option<Vec<u8>>
Build a delta document for a specific peer
This only includes operations that have changed since the last sync with this peer. Uses the delta encoder to track per-peer state.
Returns the encoded delta document bytes, or None if there’s nothing new to send to this peer.
Sourcepub fn build_full_delta_document(&self, now_ms: u64) -> Vec<u8> ⓘ
pub fn build_full_delta_document(&self, now_ms: u64) -> Vec<u8> ⓘ
Build a full delta document (for broadcast or new peers)
Unlike build_delta_document_for_peer, this includes all state
regardless of what has been sent before. Use this for broadcasts.
Sourcepub fn enable_peer_e2ee(&self)
pub fn enable_peer_e2ee(&self)
Enable per-peer E2EE capability
Creates a new identity key for this node. This allows establishing encrypted sessions with specific peers where only the sender and recipient can read messages (other mesh members cannot).
Sourcepub fn disable_peer_e2ee(&self)
pub fn disable_peer_e2ee(&self)
Disable per-peer E2EE capability
Clears all peer sessions and disables E2EE.
Sourcepub fn is_peer_e2ee_enabled(&self) -> bool
pub fn is_peer_e2ee_enabled(&self) -> bool
Check if per-peer E2EE is enabled
Sourcepub fn peer_e2ee_public_key(&self) -> Option<[u8; 32]>
pub fn peer_e2ee_public_key(&self) -> Option<[u8; 32]>
Get our E2EE public key (for sharing with peers)
Returns None if per-peer E2EE is not enabled.
Sourcepub fn initiate_peer_e2ee(
&self,
peer_node_id: NodeId,
now_ms: u64,
) -> Option<Vec<u8>>
pub fn initiate_peer_e2ee( &self, peer_node_id: NodeId, now_ms: u64, ) -> Option<Vec<u8>>
Initiate E2EE session with a specific peer
Returns the key exchange message bytes to send to the peer. The message should be broadcast/sent to the peer. Returns None if per-peer E2EE is not enabled.
Sourcepub fn has_peer_e2ee_session(&self, peer_node_id: NodeId) -> bool
pub fn has_peer_e2ee_session(&self, peer_node_id: NodeId) -> bool
Check if we have an established E2EE session with a peer
Sourcepub fn peer_e2ee_session_state(
&self,
peer_node_id: NodeId,
) -> Option<SessionState>
pub fn peer_e2ee_session_state( &self, peer_node_id: NodeId, ) -> Option<SessionState>
Get E2EE session state with a peer
Sourcepub fn send_peer_e2ee(
&self,
peer_node_id: NodeId,
plaintext: &[u8],
now_ms: u64,
) -> Option<Vec<u8>>
pub fn send_peer_e2ee( &self, peer_node_id: NodeId, plaintext: &[u8], now_ms: u64, ) -> Option<Vec<u8>>
Send an E2EE encrypted message to a specific peer
Returns the encrypted message bytes to send, or None if no session exists. The message should be sent directly to the peer (not broadcast).
Sourcepub fn close_peer_e2ee(&self, peer_node_id: NodeId)
pub fn close_peer_e2ee(&self, peer_node_id: NodeId)
Close E2EE session with a peer
Sourcepub fn peer_e2ee_session_count(&self) -> usize
pub fn peer_e2ee_session_count(&self) -> usize
Get count of active E2EE sessions
Sourcepub fn peer_e2ee_established_count(&self) -> usize
pub fn peer_e2ee_established_count(&self) -> usize
Get count of established E2EE sessions
Sourcepub fn device_name(&self) -> String
pub fn device_name(&self) -> String
Get the device name for BLE advertising
Sourcepub fn get_peer_callsign(&self, node_id: NodeId) -> Option<String>
pub fn get_peer_callsign(&self, node_id: NodeId) -> Option<String>
Get a peer’s callsign by node ID
Returns the callsign from the peer’s most recently received peripheral data, or None if no peripheral data has been received from this peer.
Sourcepub fn get_peer_peripheral(&self, node_id: NodeId) -> Option<Peripheral>
pub fn get_peer_peripheral(&self, node_id: NodeId) -> Option<Peripheral>
Get a peer’s full peripheral data by node ID
Returns a clone of the peripheral data from the peer’s most recently received document, or None if no peripheral data has been received from this peer.
Sourcepub fn document_registry(&self) -> &DocumentRegistry
pub fn document_registry(&self) -> &DocumentRegistry
Sourcepub fn store_app_document<T: DocumentType>(&self, doc: T) -> bool
pub fn store_app_document<T: DocumentType>(&self, doc: T) -> bool
Store an app-layer document.
If a document with the same identity (type_id, source_node, timestamp) already exists, it will be merged using CRDT semantics.
Returns true if the document was newly added or changed via merge.
Sourcepub fn store_app_document_boxed(
&self,
type_id: u8,
source_node: u32,
timestamp: u64,
doc: Box<dyn Any + Send + Sync>,
) -> bool
pub fn store_app_document_boxed( &self, type_id: u8, source_node: u32, timestamp: u64, doc: Box<dyn Any + Send + Sync>, ) -> bool
Store a type-erased app-layer document.
Used when receiving documents from the network where the type is determined at runtime.
Returns true if the document was newly added or changed via merge.
Sourcepub fn get_app_document<T: DocumentType>(
&self,
source_node: u32,
timestamp: u64,
) -> Option<T>
pub fn get_app_document<T: DocumentType>( &self, source_node: u32, timestamp: u64, ) -> Option<T>
Get a stored app-layer document by identity.
Returns None if not found or if downcast to T fails.
Sourcepub fn get_all_app_documents_of_type<T: DocumentType>(&self) -> Vec<T>
pub fn get_all_app_documents_of_type<T: DocumentType>(&self) -> Vec<T>
Get all stored app-layer documents of a specific type.
Returns a vector of all documents of type T currently stored.
Sourcepub fn app_document_delta_ops(&self) -> Vec<AppOperation>
pub fn app_document_delta_ops(&self) -> Vec<AppOperation>
Get delta operations for all stored app documents.
Used during sync to include app documents in the delta stream.
Sourcepub fn app_document_keys(&self, type_id: u8) -> Vec<(u32, u64)>
pub fn app_document_keys(&self, type_id: u8) -> Vec<(u32, u64)>
Get all document keys for a given type.
Returns (source_node, timestamp) pairs for all documents of the specified type.
Sourcepub fn app_document_count(&self) -> usize
pub fn app_document_count(&self) -> usize
Get the number of stored app documents.
Sourcepub fn add_observer(&self, observer: Arc<dyn PeatObserver>)
pub fn add_observer(&self, observer: Arc<dyn PeatObserver>)
Add an observer for mesh events
Sourcepub fn remove_observer(&self, observer: &Arc<dyn PeatObserver>)
pub fn remove_observer(&self, observer: &Arc<dyn PeatObserver>)
Remove an observer
Sourcepub fn send_emergency(&self, timestamp: u64) -> Vec<u8> ⓘ
pub fn send_emergency(&self, timestamp: u64) -> Vec<u8> ⓘ
Send an emergency alert
Returns the document bytes to broadcast to all peers. If encryption is enabled, the document is encrypted.
Sourcepub fn send_ack(&self, timestamp: u64) -> Vec<u8> ⓘ
pub fn send_ack(&self, timestamp: u64) -> Vec<u8> ⓘ
Send an ACK response
Returns the document bytes to broadcast to all peers. If encryption is enabled, the document is encrypted.
Sourcepub fn broadcast_bytes(&self, payload: &[u8]) -> Vec<u8> ⓘ
pub fn broadcast_bytes(&self, payload: &[u8]) -> Vec<u8> ⓘ
Broadcast arbitrary bytes over the mesh.
Takes raw payload bytes, encrypts them (if encryption is enabled), and returns bytes ready to send to all connected peers.
This is useful for sending extension data like CannedMessages from peat-lite.
Sourcepub fn clear_event(&self)
pub fn clear_event(&self)
Clear the current event (emergency or ack)
Sourcepub fn is_emergency_active(&self) -> bool
pub fn is_emergency_active(&self) -> bool
Check if emergency is active
Sourcepub fn is_ack_active(&self) -> bool
pub fn is_ack_active(&self) -> bool
Check if ACK is active
Sourcepub fn current_event(&self) -> Option<EventType>
pub fn current_event(&self) -> Option<EventType>
Get current event type
Sourcepub fn start_emergency(&self, timestamp: u64, known_peers: &[u32]) -> Vec<u8> ⓘ
pub fn start_emergency(&self, timestamp: u64, known_peers: &[u32]) -> Vec<u8> ⓘ
Start a new emergency event with ACK tracking
Creates an emergency event that tracks ACKs from all known peers. Pass the list of known peer node IDs to track. Returns the document bytes to broadcast. If encryption is enabled, the document is encrypted.
Sourcepub fn start_emergency_with_known_peers(&self, timestamp: u64) -> Vec<u8> ⓘ
pub fn start_emergency_with_known_peers(&self, timestamp: u64) -> Vec<u8> ⓘ
Start a new emergency using all currently known peers
Convenience method that automatically includes all discovered peers.
Sourcepub fn ack_emergency(&self, timestamp: u64) -> Option<Vec<u8>>
pub fn ack_emergency(&self, timestamp: u64) -> Option<Vec<u8>>
Record our ACK for the current emergency
Returns the document bytes to broadcast, or None if no emergency is active. If encryption is enabled, the document is encrypted.
Sourcepub fn clear_emergency(&self)
pub fn clear_emergency(&self)
Clear the current emergency event
Sourcepub fn has_active_emergency(&self) -> bool
pub fn has_active_emergency(&self) -> bool
Check if there’s an active emergency
Sourcepub fn get_emergency_status(&self) -> Option<(u32, u64, usize, usize)>
pub fn get_emergency_status(&self) -> Option<(u32, u64, usize, usize)>
Get emergency status info
Returns (source_node, timestamp, acked_count, pending_count) if emergency is active.
Sourcepub fn has_peer_acked(&self, peer_id: u32) -> bool
pub fn has_peer_acked(&self, peer_id: u32) -> bool
Check if a specific peer has ACKed the current emergency
Sourcepub fn all_peers_acked(&self) -> bool
pub fn all_peers_acked(&self) -> bool
Check if all peers have ACKed the current emergency
Sourcepub fn on_ble_discovered(
&self,
identifier: &str,
name: Option<&str>,
rssi: i8,
mesh_id: Option<&str>,
now_ms: u64,
) -> Option<PeatPeer>
pub fn on_ble_discovered( &self, identifier: &str, name: Option<&str>, rssi: i8, mesh_id: Option<&str>, now_ms: u64, ) -> Option<PeatPeer>
Called when a BLE device is discovered
Returns Some(PeatPeer) if this is a new Peat peer on our mesh.
Sourcepub fn on_ble_connected(&self, identifier: &str, now_ms: u64) -> Option<NodeId>
pub fn on_ble_connected(&self, identifier: &str, now_ms: u64) -> Option<NodeId>
Called when a BLE connection is established (outgoing)
Returns the NodeId if this identifier is known.
Sourcepub fn on_ble_disconnected(
&self,
identifier: &str,
reason: DisconnectReason,
) -> Option<NodeId>
pub fn on_ble_disconnected( &self, identifier: &str, reason: DisconnectReason, ) -> Option<NodeId>
Called when a BLE connection is lost
Sourcepub fn on_peer_disconnected(&self, node_id: NodeId, reason: DisconnectReason)
pub fn on_peer_disconnected(&self, node_id: NodeId, reason: DisconnectReason)
Called when a BLE connection is lost, using NodeId directly
Alternative to on_ble_disconnected() when only NodeId is known (e.g., ESP32).
Sourcepub fn on_incoming_connection(
&self,
identifier: &str,
node_id: NodeId,
now_ms: u64,
) -> bool
pub fn on_incoming_connection( &self, identifier: &str, node_id: NodeId, now_ms: u64, ) -> bool
Called when a remote device connects to us (incoming connection)
Use this when we’re acting as a peripheral and a central connects to us.
Sourcepub fn on_ble_data_received(
&self,
identifier: &str,
data: &[u8],
now_ms: u64,
) -> Option<DataReceivedResult>
pub fn on_ble_data_received( &self, identifier: &str, data: &[u8], now_ms: u64, ) -> Option<DataReceivedResult>
Called when data is received from a peer
Parses the document, merges it, and generates appropriate events. If encryption is enabled, decrypts the document first. Handles per-peer E2EE messages (KEY_EXCHANGE and PEER_E2EE markers). Returns the source NodeId and whether the document contained an event.
Sourcepub fn on_ble_data_received_from_node(
&self,
node_id: NodeId,
data: &[u8],
now_ms: u64,
) -> Option<DataReceivedResult>
pub fn on_ble_data_received_from_node( &self, node_id: NodeId, data: &[u8], now_ms: u64, ) -> Option<DataReceivedResult>
Called when data is received but we don’t have the identifier mapped
Use this when receiving data from a peripheral we discovered. If encryption is enabled, decrypts the document first. Handles per-peer E2EE messages (KEY_EXCHANGE and PEER_E2EE markers). Handles relay envelopes for multi-hop mesh operation.
Sourcepub fn on_ble_data_received_anonymous(
&self,
identifier: &str,
data: &[u8],
now_ms: u64,
) -> Option<DataReceivedResult>
pub fn on_ble_data_received_anonymous( &self, identifier: &str, data: &[u8], now_ms: u64, ) -> Option<DataReceivedResult>
Called when encrypted data is received from an unknown peer
This handles the case where we receive an encrypted document from a BLE address that isn’t registered in our peer manager (e.g., due to BLE address rotation). The function decrypts first using the mesh key, then extracts the source_node from the decrypted document header and registers the peer.
Returns Some(DataReceivedResult) if decryption and processing succeed.
Returns None if decryption fails or the document is invalid.
Sourcepub fn on_ble_data(
&self,
identifier: &str,
data: &[u8],
now_ms: u64,
) -> Option<DataReceivedResult>
pub fn on_ble_data( &self, identifier: &str, data: &[u8], now_ms: u64, ) -> Option<DataReceivedResult>
Called when data is received without a known identifier
This is the simplest data receive method - it extracts the source node_id from the document itself. Use this when you don’t track identifiers (e.g., ESP32 NimBLE). If encryption is enabled, decrypts the document first. Handles per-peer E2EE messages (KEY_EXCHANGE and PEER_E2EE markers). Handles relay envelopes for multi-hop mesh operation.
Sourcepub fn tick(&self, now_ms: u64) -> Option<Vec<u8>>
pub fn tick(&self, now_ms: u64) -> Option<Vec<u8>>
Periodic tick - call this regularly (e.g., every second)
Performs:
- Stale peer cleanup
- Periodic sync broadcast (if interval elapsed)
Returns Some(data) if a sync broadcast is needed.
Sourcepub fn tick_with_peer_deltas(&self, now_ms: u64) -> Vec<(NodeId, Vec<u8>)>
pub fn tick_with_peer_deltas(&self, now_ms: u64) -> Vec<(NodeId, Vec<u8>)>
Periodic tick returning per-peer delta documents
Unlike tick() which broadcasts a single document to all peers,
this returns targeted deltas that only include changes each peer
hasn’t seen. Use this for platforms that support per-peer transmission.
Returns a list of (NodeId, encrypted_delta) tuples, one per connected peer. Empty vector if no sync is needed (interval not elapsed or no connected peers).
Sourcepub fn get_connected_peers(&self) -> Vec<PeatPeer>
pub fn get_connected_peers(&self) -> Vec<PeatPeer>
Get connected peers only
Sourcepub fn peer_count(&self) -> usize
pub fn peer_count(&self) -> usize
Get peer count
Sourcepub fn connected_count(&self) -> usize
pub fn connected_count(&self) -> usize
Get connected peer count
Sourcepub fn matches_mesh(&self, device_mesh_id: Option<&str>) -> bool
pub fn matches_mesh(&self, device_mesh_id: Option<&str>) -> bool
Check if a device mesh ID matches our mesh
Sourcepub fn get_connection_graph(&self) -> Vec<PeerConnectionState>
pub fn get_connection_graph(&self) -> Vec<PeerConnectionState>
Get the connection state graph with all peer states
Returns a snapshot of all tracked peers and their connection lifecycle state. Apps can use this to display appropriate UI indicators:
- Green for Connected peers
- Yellow for Degraded or RecentlyDisconnected peers
- Gray for Lost peers
§Example
let states = mesh.get_connection_graph();
for peer in states {
match peer.state {
ConnectionState::Connected => show_green_indicator(&peer),
ConnectionState::Degraded => show_yellow_indicator(&peer),
ConnectionState::Disconnected => show_stale_indicator(&peer),
ConnectionState::Lost => show_gray_indicator(&peer),
_ => {}
}
}Sourcepub fn get_peer_connection_state(
&self,
node_id: NodeId,
) -> Option<PeerConnectionState>
pub fn get_peer_connection_state( &self, node_id: NodeId, ) -> Option<PeerConnectionState>
Get a specific peer’s connection state
Sourcepub fn get_connected_states(&self) -> Vec<PeerConnectionState>
pub fn get_connected_states(&self) -> Vec<PeerConnectionState>
Get all currently connected peers from the connection graph
Sourcepub fn get_degraded_peers(&self) -> Vec<PeerConnectionState>
pub fn get_degraded_peers(&self) -> Vec<PeerConnectionState>
Get peers in degraded state (connected but poor signal quality)
Sourcepub fn get_recently_disconnected(
&self,
within_ms: u64,
now_ms: u64,
) -> Vec<PeerConnectionState>
pub fn get_recently_disconnected( &self, within_ms: u64, now_ms: u64, ) -> Vec<PeerConnectionState>
Get peers that disconnected within the specified time window
Useful for showing “stale” peers that were recently connected.
Sourcepub fn get_lost_peers(&self) -> Vec<PeerConnectionState>
pub fn get_lost_peers(&self) -> Vec<PeerConnectionState>
Get peers in Lost state (disconnected and no longer advertising)
Sourcepub fn get_connection_state_counts(&self) -> StateCountSummary
pub fn get_connection_state_counts(&self) -> StateCountSummary
Get summary counts of peers in each connection state
Sourcepub fn get_indirect_peers(&self) -> Vec<IndirectPeer>
pub fn get_indirect_peers(&self) -> Vec<IndirectPeer>
Get all indirect (multi-hop) peers
Returns peers discovered via relay messages that are not directly connected via BLE. Each indirect peer includes the minimum hop count and the direct peers through which they can be reached.
Sourcepub fn get_peer_degree(&self, node_id: NodeId) -> Option<PeerDegree>
pub fn get_peer_degree(&self, node_id: NodeId) -> Option<PeerDegree>
Get the degree (hop count) for a specific peer
Returns:
Some(PeerDegree::Direct)for directly connected BLE peersSome(PeerDegree::OneHop/TwoHop/ThreeHop)for indirect peersNoneif peer is not known
Sourcepub fn get_full_state_counts(&self) -> FullStateCountSummary
pub fn get_full_state_counts(&self) -> FullStateCountSummary
Get full state counts including indirect peers
Returns counts of direct peers by connection state plus counts of indirect peers by hop count (1-hop, 2-hop, 3-hop).
Sourcepub fn get_paths_to_peer(&self, node_id: NodeId) -> Vec<(NodeId, u8)>
pub fn get_paths_to_peer(&self, node_id: NodeId) -> Vec<(NodeId, u8)>
Get all paths to reach an indirect peer
Returns a list of (via_peer_id, hop_count) pairs showing all known routes to the specified peer.
Sourcepub fn is_peer_known(&self, node_id: NodeId) -> bool
pub fn is_peer_known(&self, node_id: NodeId) -> bool
Check if a node is known (either direct or indirect)
Sourcepub fn indirect_peer_count(&self) -> usize
pub fn indirect_peer_count(&self) -> usize
Get number of indirect peers
Sourcepub fn cleanup_indirect_peers(&self, now_ms: u64) -> Vec<NodeId>
pub fn cleanup_indirect_peers(&self, now_ms: u64) -> Vec<NodeId>
Cleanup stale indirect peers
Removes indirect peers that haven’t been seen within the timeout. Returns the list of removed peer IDs.
Sourcepub fn total_count(&self) -> u64
pub fn total_count(&self) -> u64
Get total counter value
Sourcepub fn document_version(&self) -> u32
pub fn document_version(&self) -> u32
Get document version
Sourcepub fn update_health(&self, battery_percent: u8)
pub fn update_health(&self, battery_percent: u8)
Update health status (battery percentage)
Sourcepub fn update_activity(&self, activity: u8)
pub fn update_activity(&self, activity: u8)
Update activity level. The wire field is a non-validated u8
render hint (see HealthStatus::decode); receivers map known
values and silently ignore unknown ones. Current emitters use:
0=still/standing, 3=PossibleFall, 4+=reserved for sender-side
extensions.
Sourcepub fn update_health_full(&self, battery_percent: u8, activity: u8)
pub fn update_health_full(&self, battery_percent: u8, activity: u8)
Update full health status (battery and activity)
Sourcepub fn update_heart_rate(&self, heart_rate: u8)
pub fn update_heart_rate(&self, heart_rate: u8)
Update heart rate
Sourcepub fn update_alerts(&self, alerts: u8)
pub fn update_alerts(&self, alerts: u8)
Replace the alert flags bitfield. Callers OR together
HealthStatus::ALERT_* constants (e.g. ALERT_MAN_DOWN) to
express which alerts are currently active. Passing 0 clears all.
Sourcepub fn update_location(
&self,
latitude: f32,
longitude: f32,
altitude: Option<f32>,
)
pub fn update_location( &self, latitude: f32, longitude: f32, altitude: Option<f32>, )
Update location
Sourcepub fn clear_location(&self)
pub fn clear_location(&self)
Clear location
Sourcepub fn update_callsign(&self, callsign: &str)
pub fn update_callsign(&self, callsign: &str)
Update callsign
Sourcepub fn set_peripheral_event(&self, event_type: EventType, timestamp: u64)
pub fn set_peripheral_event(&self, event_type: EventType, timestamp: u64)
Set peripheral event type
Sourcepub fn clear_peripheral_event(&self)
pub fn clear_peripheral_event(&self)
Clear peripheral event
Sourcepub fn update_peripheral_state(
&self,
callsign: &str,
battery_percent: u8,
heart_rate: Option<u8>,
latitude: Option<f32>,
longitude: Option<f32>,
altitude: Option<f32>,
event_type: Option<EventType>,
timestamp: u64,
)
pub fn update_peripheral_state( &self, callsign: &str, battery_percent: u8, heart_rate: Option<u8>, latitude: Option<f32>, longitude: Option<f32>, altitude: Option<f32>, event_type: Option<EventType>, timestamp: u64, )
Update full peripheral state in one call
This is the most efficient way to update all peripheral data before
calling build_document() for encrypted transmission.
Sourcepub fn build_document(&self) -> Vec<u8> ⓘ
pub fn build_document(&self) -> Vec<u8> ⓘ
Build current document for transmission
If encryption is enabled, the document is encrypted.
Sourcepub fn peers_needing_sync(&self, now_ms: u64) -> Vec<PeatPeer>
pub fn peers_needing_sync(&self, now_ms: u64) -> Vec<PeatPeer>
Get peers that should be synced with
Sourcepub fn check_canned_message(
&self,
source_node: u32,
timestamp: u64,
_ttl_ms: u64,
) -> bool
pub fn check_canned_message( &self, source_node: u32, timestamp: u64, _ttl_ms: u64, ) -> bool
Check if a CannedMessage should be processed.
Uses document identity (source_node + timestamp) for deduplication. This prevents broadcast storms when relaying CannedMessages across the mesh.
§Arguments
source_node- The source node ID from the CannedMessagetimestamp- The timestamp from the CannedMessage_ttl_ms- TTL parameter (currently unused, uses cache’s default TTL)
§Returns
true if this message is new and should be processed,
false if it was seen recently and should be skipped.
Sourcepub fn mark_canned_message_seen(&self, source_node: u32, timestamp: u64)
pub fn mark_canned_message_seen(&self, source_node: u32, timestamp: u64)
Mark a CannedMessage as seen (for deduplication).
Call this after processing a CannedMessage to prevent reprocessing the same message from other relay paths.
Sourcepub fn get_connected_peer_identifiers(&self) -> Vec<String>
pub fn get_connected_peer_identifiers(&self) -> Vec<String>
Get list of connected peer identifiers for relay.
Used by the platform layer (Kotlin/Swift) to relay CannedMessages to other peers after deduplication check.