RadioClient
The main entry point to the Meshtastic SDK.
A RadioClient manages a single radio device over a chosen transport (BLE, TCP, serial, etc.) and exposes a clean async/reactive API:
Lifecycle: connect and disconnect (suspend functions; may throw).
State: connection, ownNode, nodes (reactive StateFlows and Flows).
Messaging: send and sendText (enqueue immediately; return a MessageHandle).
Operations: admin, telemetry, routing, storeForward sub-APIs.
Drop-in philosophy: configure once with Builder, then observe and call:
val client = RadioClient.Builder()
.transport(TcpTransport(host = "192.168.1.42", port = 4403))
.storage(MyStorageProvider())
.build()
client.connect() // suspends until Connected or throws
client.sendText("Hello mesh!") // non-suspending; returns a MessageHandle
client.packets.collect { packet -> // reactive inbound stream
println(packet.decoded?.portnum)
}
client.disconnect() // graceful shutdownMulti-radio: instantiate one RadioClient per physical radio. They share nothing.
No host plumbing: foreground services, permissions, notifications, and WorkManager are the app's responsibility. The SDK owns only the engine.
Resource management: call the suspending disconnect when done — typically from the same structured scope that owns the session, e.g. try { … } finally { client.disconnect() }. There is deliberately no blocking close()/AutoCloseable: a blocking bridge invites ANR on Android's main thread and deadlock on iOS main, and a radio session has no non-suspending way to tear down safely.
Since
0.1.0
Types
Properties
Most recently committed ConfigBundle for the active session.
The current connection state.
Side-channel advisory events: queue status, transport errors, key-verification prompts, drop notifications, and identity-rebind signals (MeshEvent.IdentityRebound — emitted before the engine clears storage when the device reports a different NodeNum than the one previously persisted).
A typed flow of NeighborInfo domain objects, decoded from inbound NEIGHBORINFO_APP packets.
Filters RadioClient.packets to only neighbor-info packets — those with decoded.portnum == [PortNum.NEIGHBORINFO_APP].
Node-change deltas. Every subscriber — early or late — first receives a NodeChange.Snapshot of the engine's current node map (seeded per-subscription via onSubscription), then live NodeChange.Added / NodeChange.Updated / NodeChange.Removed / NodeChange.WentOffline / NodeChange.CameOnline in causal order. A delta whose change is already reflected in the seeded snapshot re-applies idempotently. The handshake additionally emits a live NodeChange.Snapshot at Stage-2 commit (and after each reconnect), which existing subscribers must treat as a full replacement.
Routing API for traceRoute and neighbor enumeration. Available while connected.
Store-and-Forward API for requesting stored messages. Available while connected.
Telemetry API for device and environment metrics. Available while connected.
Filters RadioClient.packets to only text-message packets — those with decoded.portnum == [PortNum.TEXT_MESSAGE_APP].
Functions
Suspend until the device finishes streaming its NodeDB during handshake, then return the current node-snapshot map.
Connect and suspend until the handshake settles, returning the resolved ConfigBundle (HLP-34).
Gracefully disconnect from the device.
The live node map for this client: RadioClient.nodes folded via asNodeMap.
Pull a snapshot of all known nodes on demand.
Request a remote node to send its NodeInfo (user identity + position).
Request the current Position from node from.
Enqueue an outbound packet for transmission.
Constructs a packet with decoded = Data(portnum, payload, want_response = false) and forwards to send. Exists so callers do not need to import org.meshtastic.proto.Data to send a typed application payload.
Convenience: build a MeshPacket for the given portnum from an okio.ByteString payload.
DSL form of RadioClient.send. Builds a MeshPacket via SendBuilder and enqueues it.
Send a PKI-encrypted unicast text message to to.
Send a Position payload to to (defaults to broadcast).
Convenience: send an emoji reaction to an existing message.
Convenience: send a text message.
Run block against a connected session, guaranteeing teardown.