|
|
@ -189,6 +189,7 @@ class BleManager extends GetxService { |
|
|
print('[BLE] BleManager 构造,立即启动杰理 SDK 初始化'); |
|
|
print('[BLE] BleManager 构造,立即启动杰理 SDK 初始化'); |
|
|
_initFuture = _initializeJieli(); |
|
|
_initFuture = _initializeJieli(); |
|
|
_setupEventListener(); |
|
|
_setupEventListener(); |
|
|
|
|
|
_startConnectionWatchdog(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@override |
|
|
@override |
|
|
@ -201,6 +202,7 @@ class BleManager extends GetxService { |
|
|
void onClose() { |
|
|
void onClose() { |
|
|
_eventSub?.cancel(); |
|
|
_eventSub?.cancel(); |
|
|
_stopBatteryWatchdog(); |
|
|
_stopBatteryWatchdog(); |
|
|
|
|
|
_stopConnectionWatchdog(); |
|
|
_callTranslationRequestController.close(); |
|
|
_callTranslationRequestController.close(); |
|
|
_inUplinkPcmController.close(); |
|
|
_inUplinkPcmController.close(); |
|
|
_inDownlinkPcmController.close(); |
|
|
_inDownlinkPcmController.close(); |
|
|
@ -380,6 +382,83 @@ class BleManager extends GetxService { |
|
|
_batteryWatchdog = null; |
|
|
_batteryWatchdog = null; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 连接状态 watchdog:杰理 SDK 在某些时序下不会回调 ConnectionStateEvent |
|
|
|
|
|
// (冷启时设备已经连着、事件订阅 race、原生侧自动重连等),导致本地 Rx |
|
|
|
|
|
// 状态停在 disconnected 但 SDK 内部已经有连接。这里定期直接问 SDK。 |
|
|
|
|
|
// |
|
|
|
|
|
// 重要:只做"单向"同步(disconnected → connected),**不**把已连状态翻回 |
|
|
|
|
|
// disconnected。原因:multi-device 模式下 connectedDevice() 偶发会返回 null, |
|
|
|
|
|
// 上一版把它当真翻成 disconnected 反而把已连接 UI 抹掉了。断开仍走 |
|
|
|
|
|
// ConnectionStateEvent.connectionDisconnect 那条事件路径。 |
|
|
|
|
|
Timer? _connectionWatchdog; |
|
|
|
|
|
static const Duration _connectionWatchdogInterval = Duration(seconds: 5); |
|
|
|
|
|
|
|
|
|
|
|
void _startConnectionWatchdog() { |
|
|
|
|
|
_connectionWatchdog?.cancel(); |
|
|
|
|
|
_connectionWatchdog = Timer.periodic(_connectionWatchdogInterval, (_) { |
|
|
|
|
|
_reconcileConnectionFromSdk(); |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void _stopConnectionWatchdog() { |
|
|
|
|
|
_connectionWatchdog?.cancel(); |
|
|
|
|
|
_connectionWatchdog = null; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Future<void> _reconcileConnectionFromSdk() async { |
|
|
|
|
|
if (!_initSucceeded) return; |
|
|
|
|
|
try { |
|
|
|
|
|
// 步骤 1:尽量找到一个真实在连的 address。 |
|
|
|
|
|
// 优先:本地已有 currentDeviceAddress → 直接 isConnected(addr) 校验。 |
|
|
|
|
|
// 兜底:connectedDevice() 看 SDK 是否能给出当前已连设备。 |
|
|
|
|
|
String? sdkConnectedAddr; |
|
|
|
|
|
String? sdkConnectedName; |
|
|
|
|
|
final localAddr = currentDeviceAddress; |
|
|
|
|
|
if (localAddr != null && localAddr.isNotEmpty) { |
|
|
|
|
|
if (await Jielihome.instance.isConnected(localAddr)) { |
|
|
|
|
|
sdkConnectedAddr = localAddr; |
|
|
|
|
|
sdkConnectedName = _currentDeviceName; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
if (sdkConnectedAddr == null) { |
|
|
|
|
|
final dev = await Jielihome.instance.connectedDevice(); |
|
|
|
|
|
if (dev != null && dev.address.isNotEmpty) { |
|
|
|
|
|
sdkConnectedAddr = dev.address; |
|
|
|
|
|
sdkConnectedName = dev.name; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (sdkConnectedAddr == null) return; // 没拿到,本轮放弃,**不**翻 _isConnected |
|
|
|
|
|
|
|
|
|
|
|
// 步骤 2:本地 Rx 与 SDK 不一致 → 强制同步到「已连」。 |
|
|
|
|
|
final wasConnected = _isConnected.value; |
|
|
|
|
|
final addressChanged = currentDeviceAddress != sdkConnectedAddr; |
|
|
|
|
|
if (!wasConnected || addressChanged) { |
|
|
|
|
|
Logger.w('BleManager', |
|
|
|
|
|
'[WATCHDOG] 本地 isConnected=$wasConnected addr=$currentDeviceAddress' |
|
|
|
|
|
' / SDK 在连 $sdkConnectedAddr → 同步为 connected'); |
|
|
|
|
|
currentDeviceAddress = sdkConnectedAddr; |
|
|
|
|
|
if (sdkConnectedName != null && sdkConnectedName.isNotEmpty) { |
|
|
|
|
|
_currentDeviceName = sdkConnectedName; |
|
|
|
|
|
} |
|
|
|
|
|
_isConnected.value = true; |
|
|
|
|
|
_connectionState.value = BleConnectionState.connected; |
|
|
|
|
|
_ensureDeviceInfoStub(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 步骤 3:兜底电量。冷启场景下 RcspInitEvent 不会再来, |
|
|
|
|
|
// _startBatteryWatchdog 永远不被触发,电量 UI 一直 0。 |
|
|
|
|
|
// 这里发现 SDK 在连且本地电量为 0 时,主动启动一次电量轮询。 |
|
|
|
|
|
final lvl = deviceInfo.value?.batteryLevel ?? 0; |
|
|
|
|
|
if (lvl == 0 && _batteryWatchdog == null) { |
|
|
|
|
|
Logger.i('BleManager', '[WATCHDOG] 已连但电量=0,启动电量轮询补抓'); |
|
|
|
|
|
_startBatteryWatchdog(); |
|
|
|
|
|
} |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
Logger.w('BleManager', '[WATCHDOG] 查询 SDK 连接状态失败: $e'); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void _handleBattery(BatteryEvent e) { |
|
|
void _handleBattery(BatteryEvent e) { |
|
|
final level = e.level ?? 0; |
|
|
final level = e.level ?? 0; |
|
|
_ensureDeviceInfoStub(); |
|
|
_ensureDeviceInfoStub(); |
|
|
|