feat: PlayMode 切换 + bind/unbind/setPlayMode 携带北京时间
主要改动(与 iOS SDK 1:1 对齐): - 新增 BeijingTimeProvider:苏宁公开 API → header Date → 本地+8h 三级 fallback; 5 秒缓存 + Mutex 单飞复用 - 新增 PlayMode enum (SINGLE=0, LOOP=1) - DeviceInfo 增加可选 loop 字段(旧固件无此字段时为 null) - DeviceInfoService.bind/unbind/setPlayMode 共用 payload,带 time 字段; loop == null 时严格省略 key(与 expo zod.optional 对齐) - DuooomiBleSDK.setPlayMode(mode, userId):复用 BIND_DEVICE 命令通道, isActivated 守卫;成功后自动刷新 deviceInfo - Demo 增加 Single / Loop 按钮(gated by isActivated) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import com.duooomi.ble.core.*
|
||||
import com.duooomi.ble.models.*
|
||||
import com.duooomi.ble.protocol.CommandType
|
||||
import com.duooomi.ble.services.*
|
||||
import com.duooomi.ble.utils.BeijingTimeProvider
|
||||
import com.duooomi.ble.utils.BleLog
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.*
|
||||
@@ -45,7 +46,8 @@ class DuooomiBleSDK(context: Context, val config: DuooomiBleConfig) {
|
||||
|
||||
private val bleClient = BleClient(context)
|
||||
private val protocolService = BleProtocolService(bleClient)
|
||||
private val deviceInfoService = DeviceInfoService(protocolService)
|
||||
private val timeProvider = BeijingTimeProvider()
|
||||
private val deviceInfoService = DeviceInfoService(protocolService, timeProvider)
|
||||
private val fileTransferService = FileTransferService(protocolService)
|
||||
private val aniConverter = AniConverter(config)
|
||||
private val firmwareService = FirmwareService(config)
|
||||
@@ -229,6 +231,36 @@ class DuooomiBleSDK(context: Context, val config: DuooomiBleConfig) {
|
||||
return resp
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换播放模式(0=单播 / 1=循环播放)。
|
||||
*
|
||||
* 复用 [CommandType.BIND_DEVICE] (0x0F) 命令通道;响应类型为 [BindingResponse]。
|
||||
* 成功后自动刷新一次 `deviceInfo`(含最新 `loop` 字段),与 expo 端行为对齐。
|
||||
*
|
||||
* 前置:必须已 [bind] 完成(`isActivated == true`)。
|
||||
* `bind` / `unbind` / `setPlayMode` 共享 0x0F / 0x12 opId 通道,**不能并发**。
|
||||
*/
|
||||
suspend fun setPlayMode(mode: com.duooomi.ble.models.PlayMode, userId: String): BindingResponse {
|
||||
ensureConnected()
|
||||
if (!_isActivated.value) {
|
||||
BleLog.w("setPlayMode called before bind (isActivated=false)", "Command")
|
||||
throw DuooomiBleError.BindingFailed("Device not bound; call bind(userId) first")
|
||||
}
|
||||
BleLog.d("Sending setPlayMode (mode=$mode, userId=$userId)", "Command")
|
||||
val data = sendAndWait(CommandType.BIND_DEVICE) {
|
||||
deviceInfoService.setPlayMode(userId, mode)
|
||||
}
|
||||
val resp = BindingResponse.fromJson(parseJsonResponse(data))
|
||||
if (resp.success != 1) {
|
||||
BleLog.w("setPlayMode failed: device rejected", "Command")
|
||||
throw DuooomiBleError.BindingFailed("Set play mode failed")
|
||||
}
|
||||
BleLog.i("setPlayMode success: mode=$mode", "Command")
|
||||
// 自动刷新 deviceInfo(含最新 loop 字段)
|
||||
runCatching { getDeviceInfo() }
|
||||
return resp
|
||||
}
|
||||
|
||||
suspend fun unbind(userId: String): UnbindResponse {
|
||||
ensureConnected()
|
||||
BleLog.d("Sending unbind (userId=$userId)", "Command")
|
||||
|
||||
Reference in New Issue
Block a user