Android Channel Presence SDK
SDK Version: 1.0.0
The Channel Presence SDK scans an explicit RF channel plan, sends silent Mesh probes, correlates acknowledgements with the channel on which they were sent, and returns reachable channels plus optional friend markers. It does not own device connection, RF switching UI, friend storage, or fallback RSSI scanning.
Setup and host contract
Add the supplied Channel Presence SDK artifact and implement the synchronous host adapter:
class ScanHost : ChannelPresenceScanSdk.Host {
override fun switchToChannel(channel: ChannelPresenceChannel) {
radio.setFrequencyAndBeacon(channel.frequencyHz, channel.bcnId)
}
override fun sendProbe(probe: ChannelPresenceBuiltProbe): Boolean =
radio.sendAndWaitForCompletion(probe.rfPayload)
override fun waitForMeshAck(
packetIds: Set<Int>,
timeoutMs: Long,
): ChannelPresenceMeshAck? = ackQueue.await(packetIds, timeoutMs)
}
The host must report the real receive/reply channelId; never fill it with whichever channel the UI currently displays. An acknowledgement is accepted only when its packet and channel match the tracked probe.
Run a scan
val channels = AiTalkMeshRadioProfile.channels.map {
ChannelPresenceChannel(it.channelId, it.frequencyHz, it.bcnId)
}
val request = ChannelPresenceScanRequest(
localNodeId = localNodeId,
scanId = scanId,
channelPlanId = AiTalkMeshRadioProfile.PROFILE_ID,
channels = channels,
candidates = friends,
trigger = ChannelPresenceScanTrigger.SettingsRescan,
requestedProbeCount = 8,
dwellMs = 800,
hopLimit = 3,
)
val result = ChannelPresenceScanSdk(ScanHost()).scan(request) { progress ->
showProgress(progress.percent, progress.currentChannelId)
}
When candidates is empty the SDK sends a generic presence probe on every channel. Generic evidence marks a channel reachable but never marks a friend.
Public models
| Type | Purpose |
|---|---|
ChannelPresenceChannel | channelId, frequencyHz, and bcnId record supplied by the caller. |
ChannelPresenceFriendCandidate | Friend node ID, display name, 16-byte key, and optional last-known channel. |
ChannelPresenceScanRequest | Full channel plan, candidates, trigger, dwell, hop limit, and probe count. |
ChannelPresenceBuiltProbe | Packet ID, channel, target, and complete RF payload passed to the host. |
ChannelPresenceMeshAck | Mesh acknowledgement with packet, channel, source/relay, and optional RSSI. |
ChannelPresenceAppAck | Explicit friend application acknowledgement. |
ChannelPresenceScanProgress | Scanned/total counts, current channel, and computed 0–100 percent. |
ChannelPresenceScanResult | Reachable channels and optional host-selected RSSI fallback. |
ChannelPresenceChannelResult | Evidence, friend markers, and strongest calibrated RSSI for one channel. |
ChannelPresenceScannedChannel | Host RSSI fallback result. |
ChannelPresenceAckKind values are MeshImplicitAck, TargetRoutingAck, and FriendAppAck. Scan triggers are FirstInstall and SettingsRescan.
Utility APIs
ChannelPresenceChannelPlan.channels(startFrequencyHz, count)creates a caller-defined legacy/custom 2 MHz plan. It is not the official profile.nonMessageChannel(channelId, frequencyHz)creates a record withbcnId=0.channelRange(count)returns the logical range.channelPlanId(startFrequencyHz)creates a compatibility plan ID.ChannelPresenceCandidateSelector.select(...)deterministically selects 3–8 candidates.ChannelPresenceProbeTiming.genericProbeJitterMs(...)returns a stable collision-reduction delay.ChannelPresenceScanReducer.trackProbe,applyMeshAck,applyAppAck, andsnapshotsupport hosts that consume explicit application acknowledgements outsidescan().ChannelPresenceResidentChannelSelector.select(result)prefers a channel containing a friend, otherwise the last reachable channel.ChannelPresenceMeshFrameBuilder.buildProbeFrame(...)andbuildGenericPresenceProbeFrame(...)build complete RF probe frames;readToNode,readFromNode, andreadPacketIdinspect their Mesh header.
Evidence and RSSI rules
An implicit rebroadcast proves that a Mesh participant was reachable on the dwell channel. A target routing or friend application acknowledgement may add a friend marker. RSSI must come from real receive metadata and be calibrated by the host; null means unavailable. For repeated hits the SDK keeps the numerically strongest value, for example -79 dBm instead of -88 dBm.
After an empty scan, the host may perform its own RSSI sweep, switch to the best record, and return it as bestScannedChannel. Automatic cross-frequency friend roaming is not performed by this SDK.
Errors and threading
scan() is blocking and must run off the main thread. Host exceptions abort the scan. An interrupted dwell restores the thread interruption flag and throws IllegalStateException. Validate connection and RF lease availability before starting, and restore or select the final resident channel in a finally/completion path.