How Adaptive Battery Optimization Works in BitChat's BLE Service Duty Cycling
BitChat's BLE transport dynamically adjusts scanning and advertising intervals based on real-time mesh traffic, node degree, and battery level to minimize power consumption while maintaining connectivity.
BitChat is an open-source mesh messaging application that relies on Bluetooth Low Energy (BLE) for peer-to-peer communication. To prevent excessive battery drain during idle periods, the codebase implements an intelligent duty-cycling system within BLEService.swift that continuously adapts to network conditions and device state.
Core Mechanisms of Adaptive Duty Cycling
The adaptive battery optimization in BitChat operates through five interconnected mechanisms that balance connectivity against power consumption.
High-Degree Threshold and Probabilistic Relays
BitChat uses a configurable high-degree threshold defined in TransportConfig.swift to identify nodes with many neighboring peers.
// TransportConfig.swift - Line 10
static var bleHighDegreeThreshold: Int = 6
When a node's neighbor count exceeds this threshold, it enters a probabilistic relay mode. This mode applies adaptive TTL (Time-To-Live) values to packets, shortening packet lifespans to reduce unnecessary retransmissions. According to the implementation in BLEService.swift at line 232, this adaptation prevents high-degree nodes from wasting energy relaying stale packets throughout the mesh.
Traffic-Based Scan Planning
The BLEScanDutyPolicy class (implemented in BLEScanDutyPolicy.swift) monitors recent traffic timestamps stored by the BLE service to determine optimal scan frequencies.
When the mesh has been quiet, the policy returns a low-frequency scan plan. During traffic spikes, it returns higher-frequency plans. As referenced at line 6997 of BLEService.swift, this traffic-aware approach ensures BLE scanning only consumes power when the network is active.
// Simplified logic from BLEScanDutyPolicy.swift
struct BLEScanDutyPolicy {
static func plan(recentTraffic: [Date]) -> ScanPlan {
let idleDuration = Date().timeIntervalSince(recentTraffic.last ?? .distantPast)
if idleDuration > 30 * 60 { // >30 min idle
return ScanPlan(interval: 300, window: 5) // 5 min interval, 5s window
} else if idleDuration > 5 * 60 { // moderate activity
return ScanPlan(interval: 30, window: 10) // 30s interval, 10s window
} else { // active traffic
return ScanPlan(interval: 5, window: 20) // 5s interval, 20s window
}
}
}
Back-Pressure Buffer Management
The system monitors the BLEOutboundWriteBuffer to detect congestion. As documented in ARCHITECTURE_V2.md at line 46, when the outbound buffer accumulates pending packets, the scan duty cycle automatically increases to clear the backlog faster. Conversely, when the buffer remains empty, the duty cycle reduces to conserve power.
Battery-Sensitive Scheduling
During initialization, BLEService checks the device's battery level using UIDevice.current.batteryLevel. When the battery falls below a safe threshold, the service forces the scan plan to its most conservative setting. This ensures that BLE activity does not drain the battery excessively during low-power states.
Adaptive TTL Implementation
High-degree nodes implement adaptive TTL to limit packet propagation distances. By reducing TTL values when connected to many peers, the system prevents energy-intensive network flooding. This mechanism is particularly important for devices acting as mesh relays in dense network environments.
Practical Implementation Examples
To initialize a BLE service with adaptive duty cycling:
import CoreBluetooth
let bleService = BLEService(
config: TransportConfig(),
scanDutyPolicy: BLEScanDutyPolicy()
)
// Trigger manual recalculation after battery level changes
bleService.updateDutyCycleIfNeeded()
Adjusting the high-degree threshold at runtime alters when probabilistic relaying activates:
// Make adaptive relay trigger later (more conservative)
TransportConfig.bleHighDegreeThreshold = 8
// Make adaptive relay trigger earlier (more aggressive power saving)
TransportConfig.bleHighDegreeThreshold = 4
Key Source Files
The following files contain the core adaptive battery optimization logic:
bitchat/Services/TransportConfig.swift- DefinesbleHighDegreeThresholdfor node degree calculationsbitchat/Services/BLE/BLEService.swift- Core implementation tracking traffic timestamps and applying duty cyclesbitchat/Services/BLE/BLEScanDutyPolicy.swift- Algorithm for determining scan intervals based on recent activitydocs/ARCHITECTURE_V2.md- Documentation explaining the back-pressure buffer and scheduling state separation
Summary
BitChat's adaptive battery optimization works by:
- Monitoring node degree through
bleHighDegreeThresholdto enable probabilistic relaying - Tracking traffic patterns via
BLEScanDutyPolicyto adjust scan intervals dynamically - Managing back-pressure through outbound buffer monitoring to clear congestion efficiently
- Respecting battery levels by forcing conservative scan plans when power is low
- Limiting packet propagation using adaptive TTL to prevent unnecessary retransmissions
These mechanisms allow BitChat to maintain mesh connectivity while significantly reducing BLE power consumption during idle periods.
Frequently Asked Questions
How does BitChat detect when to switch between scan intervals?
BitChat's BLEScanDutyPolicy examines the timestamps of recent mesh traffic stored in BLEService. If no packets have been received for over 30 minutes, it switches to a 5-minute scan interval. If traffic arrives within 5 minutes, it uses aggressive 5-second intervals. This traffic-aware approach ensures the radio only activates when necessary.
What happens when a BitChat node connects to many peers simultaneously?
When a node exceeds the bleHighDegreeThreshold (default 6 peers), it activates probabilistic relay mode. This mode applies shorter TTL values to packets and probabilistically drops relay requests, preventing the node from wasting energy broadcasting messages to an already well-connected neighborhood.
Can developers adjust the battery optimization sensitivity?
Yes. Developers can modify TransportConfig.bleHighDegreeThreshold to change when high-degree mode activates, or implement custom BLEScanDutyPolicy classes with different idle timeout thresholds. The architecture in ARCHITECTURE_V2.md specifically separates scheduling state from BLEService to enable such customizations.
Does adaptive duty cycling affect message delivery reliability?
The system maintains reliability through back-pressure monitoring. When the BLEOutboundWriteBuffer detects pending messages, it temporarily increases scan frequency to ensure packets clear quickly. Additionally, the traffic detection algorithm responds rapidly to new activity, ramping up from 5-minute intervals to 5-second intervals within seconds of detecting incoming mesh traffic.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →