feat(demo): SDK 暴露 rawJsonEvents 调试通道;Demo 日志显示 BLE 收发原始 JSON
- BleTypes.kt 新增 BleRawJsonEvent(TX/RX,含 cmd 名/十六进制类型/JSON 字符串),KDoc 标注调试用、非业务契约 - BleProtocolService.sendJSON 内 emit TX;新增 rawJsonEmitter 注入回调避免协议层反向依赖 - DuooomiBleSDK 公开 SharedFlow<BleRawJsonEvent>;handleIncomingMessage 入口尽力 UTF-8 解码 emit RX(非 JSON 字节流静默跳过) - DemoScreen LaunchedEffect 订阅,前缀 → TX / ← RX 写入现有 logs 列表 - iOS 当前无对应通道,本通道为 Android Demo 调试增强 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -54,6 +54,13 @@ class DuooomiBleSDK(context: Context, val config: DuooomiBleConfig) {
|
||||
private val _error = MutableStateFlow<String?>(null)
|
||||
val error: StateFlow<String?> = _error.asStateFlow()
|
||||
|
||||
/**
|
||||
* BLE JSON 协议层原始收发事件流。**调试用**——日志/抓包/UI 联调展示,
|
||||
* 不属业务行为契约(iOS 版无对应通道)。集成方不要依赖它做业务逻辑。
|
||||
*/
|
||||
private val _rawJsonEvents = MutableSharedFlow<BleRawJsonEvent>(extraBufferCapacity = 32)
|
||||
val rawJsonEvents: SharedFlow<BleRawJsonEvent> = _rawJsonEvents.asSharedFlow()
|
||||
|
||||
// MARK: - Internal Services
|
||||
|
||||
private val bleClient = BleClient(context)
|
||||
@@ -85,6 +92,7 @@ class DuooomiBleSDK(context: Context, val config: DuooomiBleConfig) {
|
||||
init {
|
||||
BleLog.i("SDK initialized (apiHost=${config.apiHost}, brand=${config.brand})", "SDK")
|
||||
setupDisconnectHandler()
|
||||
protocolService.rawJsonEmitter = { evt -> _rawJsonEvents.tryEmit(evt) }
|
||||
// 启动时把持久化记录回放到 StateFlow
|
||||
_upgradeRecords.value = upgradeRecordStore.all
|
||||
upgradeRecordStore.onChange = { records ->
|
||||
@@ -702,6 +710,7 @@ class DuooomiBleSDK(context: Context, val config: DuooomiBleConfig) {
|
||||
|
||||
private fun handleIncomingMessage(commandType: Byte, data: ByteArray) {
|
||||
val typeValue = commandType.toInt() and 0xFF
|
||||
emitRawJsonRx(typeValue, data)
|
||||
val opId = "$typeValue"
|
||||
|
||||
// Check for prepareTransfer with key-based opId
|
||||
@@ -746,6 +755,26 @@ class DuooomiBleSDK(context: Context, val config: DuooomiBleConfig) {
|
||||
throw DuooomiBleError.BrandMismatch(expected = expected, actual = actual)
|
||||
}
|
||||
|
||||
private fun emitRawJsonRx(typeValue: Int, data: ByteArray) {
|
||||
runCatching {
|
||||
val cleaned = data.filter { it != 0.toByte() }.toByteArray()
|
||||
if (cleaned.isEmpty()) return@runCatching
|
||||
val jsonStr = String(cleaned, Charsets.UTF_8)
|
||||
if (jsonStr.startsWith("{") || jsonStr.startsWith("[")) {
|
||||
val name = CommandType.fromValue(typeValue)?.name
|
||||
?: "UNKNOWN(0x%02X)".format(typeValue)
|
||||
_rawJsonEvents.tryEmit(
|
||||
BleRawJsonEvent(
|
||||
direction = BleRawJsonEvent.Direction.RX,
|
||||
commandType = typeValue,
|
||||
commandName = name,
|
||||
json = jsonStr
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseJsonResponse(data: ByteArray): JSONObject {
|
||||
// Device responses may contain null bytes
|
||||
val cleaned = data.filter { it != 0.toByte() }.toByteArray()
|
||||
|
||||
Reference in New Issue
Block a user