meshtastic-sdk is a Kotlin Multiplatform (KMP) SDK for Meshtastic mesh-network radios. It enables Android, iOS, and JVM applications to communicate with Meshtastic devices over BLE, TCP, or USB-serial using the device's PhoneAPI protocol.
- Language: Kotlin 2.x+
- Platform: Kotlin Multiplatform (JVM, Android, iOS)
- Concurrency: Kotlin Coroutines (Actors, Flows, Channels)
- Serialization:
kotlinx.serialization(Protobuf via Wire) - Storage: SQLDelight (for persistent node/config/channel data)
- Networking: Ktor Sockets (TCP), Kable (BLE), usb-serial-for-android / jSerialComm (Serial)
- Tooling: Gradle (Kotlin DSL), Spotless (ktlint), Detekt, Kover, Dokka, Binary Compatibility Validator (BCV)
- iOS Bridging: SKIE (for Swift-friendly sealed classes and Flows), KMMBridge (for XCFramework distribution)
The SDK follows a strictly defined architecture documented in docs/SPEC.md:
- RadioClient: The public facade for the SDK. Uses a Builder pattern for configuration.
- MeshEngine: Implemented as an Actor (a single coroutine draining a
Channel<EngineMessage>). ALL state mutation must happen within this actor to ensure thread safety without mutexes. - HandshakeMachine: An explicit FSM driving the two-stage protocol handshake.
- CommandDispatcher: Allocates
request_ids and tracks Admin RPC calls. - MessageQueue: Tracks outbound
MessageHandles and delivery states (Queued -> Sent -> Acked/Delivered/Failed). - Transport Layer: Decoupled modules (
transport-ble,transport-tcp, etc.) implementing theRadioTransportinterface. - Storage Layer: Keyed by
TransportIdentity(derived from transport config).
- JDK 21 (e.g.,
sdk install java 21-tem) - Android SDK (API 35 platform)
- Xcode (for iOS targets, macOS only)
- Full Check (CI baseline):
./gradlew check- Runs build, unit tests, lint (Spotless + Detekt), ABI validation (BCV), and coverage (Kover).
- Run Tests:
./gradlew allTests - Linting:
./gradlew spotlessCheck/./gradlew spotlessApply - Static Analysis:
./gradlew detekt - API Documentation:
./gradlew dokkaGenerate(Dokka V2; output incore/build/dokka/html. The legacydokkaHtmltask is removed and errors under V2 mode.) - ABI Management:
./gradlew checkKotlinAbi(validate) or./gradlew updateKotlinAbi(after intentional API changes)
The project includes a sample CLI for testing:
./gradlew :samples:cli:run --args="--host meshtastic.local"- Response Shapes:
suspend funthrowingMeshtasticExceptionfor fatal/programmer errors.- Typed Sealed Outcomes (
SendState,AdminResult) for expected radio/mesh failures (timeouts, NAKs). Flow/StateFlowfor reactive streams and state.
- Proto Types: Use Wire-generated protobuf types (
org.meshtastic.proto.*) directly in the public API where possible. - Snake Case: Wire-generated proto fields are
snake_case(e.g.,user.long_name), notcamelCase.
- Thread Safety: Never use
Mutexor atomics inside theenginepackage; rely on the Actor's single-writer invariant. - Platform Limits: No
java.*orandroid.*incommonMain. Useokio.ByteStringfor byte payloads (Wire's runtime type; kotlinx-io is deliberately not a dependency) andkotlinx-datetimefor time. - Documentation: Every public symbol MUST have a KDoc. Dokka coverage is a CI gate.
- Testing:
- Use
testing/module fakes (FakeRadioTransport,InMemoryStorage) for unit tests. - Property-based testing (Kotest) is preferred for codec and state machine logic.
- Use
- Commits: We use the Developer Certificate of Origin (DCO). Sign every commit with
git commit -s.
docs/SPEC.md: The authoritative implementation plan and architecture bible.docs/protocol.md: The wire-level protocol reference (PhoneAPI).core/: The main SDK engine and public facade.- Protobuf types: the published
org.meshtastic:protobufsMaven artifact (no vendoredproto/dir or submodule); pinned ingradle/libs.versions.toml. build-logic/: Custom Gradle convention plugins for KMP, Android, and Publishing.gradle/libs.versions.toml: The single source of truth for all dependencies and versions.