Connect to dive computers from Kotlin.
A Kotlin library that downloads dives from a dive computer over Bluetooth Low Energy.
- Language
- Kotlin
- Platforms
- Android 8.0 (API 26) and later
- Install
- AAR
- Transport
- Bluetooth Low Energy
Install
Add the library
The library ships as an AAR. The AAR carries the native code, so your build needs no NDK and no CMake. The build links libdivecomputer as its own shared library, which keeps the LGPL-2.1 relink obligation simple for the app that you ship.
There is no public artifact yet. The license gives you the AAR.
dependencies {
implementation(files("libs/<aar>.aar"))
} - The AAR carries the native code for arm64-v8a, armeabi-v7a, and x86_64.
- libdivecomputer is a separate shared library, linked at run time.
- The library records the exact upstream revision of libdivecomputer that it uses.
- Every local change to the C code is a patch in a patch series.
Download
Scan, connect, and download
The scan suspends and returns what is in range. The download is a Flow of events: the progress, the device info, the clock drift, and each dive as it arrives.
The app holds the BLUETOOTH_SCAN and BLUETOOTH_CONNECT permissions before the first scan. The library never asks for them.
import codes.divecomputer.DiveComputer
val diveComputer = DiveComputer(context)
val found = diveComputer.scan(timeoutMillis = 10_000)
for (device in found) {
// The descriptor is null when no known device matches the name.
val descriptor = device.descriptor ?: continue
println("${descriptor.vendor} ${descriptor.product} ${device.name}")
} val device = diveComputer.connect(found.first())
// The fingerprint stops the download at the newest dive you hold.
device.downloadDives(fingerprint = lastKnown).collect { event ->
when (event) {
is DownloadEvent.Progress -> ui.show(event.progress.percent)
is DownloadEvent.Info -> ui.showDevice(event.info)
is DownloadEvent.Clock -> log.record(event.drift)
is DownloadEvent.DiveDownloaded -> event.dive?.let(store::insert)
}
}
// The same download, dives only, when the interface shows no progress.
device.dives(fingerprint = lastKnown).collect(store::insert) What the library does
- The scan reports each dive computer in range with its vendor and its product.
- A fingerprint stops the download at the newest dive that you hold.
- Each dive carries typed samples and the original device bytes.
- The parse path reads a stored blob without a device.
Parse
Parse without a device
The parse path takes a stored blob and a parser type. It runs on a phone, and it runs on the host JVM, so a test or a tool parses an archived dive with no device attached.
A parse that the bytes do not support fails with an error. The library never returns a partial dive.
import codes.divecomputer.parsing.DiveParsing
// The parse path needs no device. It also runs on the host JVM.
val dive = DiveParsing.parseDive(bytes, "shearwater_petrel")
// Resolve a parser from a vendor and a model.
DiveParsing.parserType("Shearwater", "Perdix")
// List every device the parser recognises.
DiveParsing.supportedDevices() License the Kotlin library
A license covers the Kotlin library, one license per app. Tell us what you build and when you need it. You get a quote, the terms, and the artifact.