用于多阶段蓝牙命令的 RxBluetoothKit 代码模式

Posted

技术标签:

【中文标题】用于多阶段蓝牙命令的 RxBluetoothKit 代码模式【英文标题】:RxBluetoothKit Code Pattern for Multiple Stage Bluetooth Commands 【发布时间】:2017-05-29 16:55:11 【问题描述】:

我已经开始使用 RxBluetoothKit 并在我们正在开发的外围设备上取得了不错的效果。它工作得很好,我能够执行我们需要的交易。

我有一个设计模式问题。我们有几个命令,其中我们的 API 包含多步命令。例如,App 编写命令启动代码,Peripheral 用 ACK 确认,然后 App 编写命令,等待 ACK,发出另一个命令,等待另一个 ACK​​,等等。这可以一直持续到 App 发出一个命令停止代码,它将在未来某个不确定的时间点出现——例如,当用户告诉应用停止时。

在 Rx 世界中是否有合适的编码习惯或模式来实现这一点?总的来说,我是 Rx 的新手,我很好奇这类东西的最简单、最干净的实现。

谢谢。

【问题讨论】:

【参考方案1】:

细节始终取决于您非常具体的用例。我喜欢将 Rx 视为基于流的构建块,需要连接起来以对您的业务逻辑进行建模。

有一个例子:

enum DeviceService: String, ServiceIdentifier 
    case myService = "ffff"

    var uuid: CBUUID 
        return CBUUID(string: self.rawValue)
    


enum DeviceCharacteristic: String, CharacteristicIdentifier 
    case startCharacteristic = "0001"
    case stopCharacteristic = "0002"
    case ackCharacteristic = "ffff"
    case command1Characteristic = "0003"
    case command2Characteristic = "0004"

    var uuid: CBUUID 
        return CBUUID(string: self.rawValue)
    

    var service: ServiceIdentifier 
        return DeviceService.myService
    


let peripheral : Peripheral? = nil

// Some internal command 1
let command1 = peripheral!.writeValue(Data(bytes: [0xff, 0xfe]),
                                      for: DeviceCharacteristic.command1Characteristic,
                                      type: .withResponse)

// Some internal command 2
let command2 = peripheral!.writeValue(Data(bytes: [0xdd, 0xee]),
                                      for: DeviceCharacteristic.command2Characteristic,
                                      type: .withResponse)

func batchCommands(commands: [Observable<Characteristic>]) -> Observable<Characteristic> 

    let commandsWithAck = commands.map  command in
        return command.flatMap  characteristic in
            return peripheral!.monitorValueUpdate(for: DeviceCharacteristic.ackCharacteristic).take(1)
        
    

    let start = peripheral!.writeValue(Data(bytes: [0x01]),
                                            for: DeviceCharacteristic.startCharacteristic,
                                            type: .withResponse)
    let stop = peripheral!.writeValue(Data(bytes: [0x00]),
                                           for: DeviceCharacteristic.startCharacteristic,
                                           type: .withResponse)

    return start.concat(Observable.concat(commandsWithAck)).concat(stop)


// Call it:
let subscription = batchCommands(commands: [command1, command2])
    .subscribe(onNext: nil, onError: nil, onCompleted: nil, onDisposed: nil)

在那里,startstop 可观察对象可以更改以监控用户的行为并在实际开始/停止操作应该发生时发出项目。

【讨论】:

谢谢你。也许我应该指出的一点是,设备端的服务是一个 UART 服务,所以有两个特性——TX 和 RX。在这种情况下,我在 TX 上使用适当的命令数据 writeValue,然后监视 RX 的结果。我很好奇的是如何在写入 TX 后干净地监视 RX,然后适当地处理 ACK(或 NACK 或错误),然后在启动后继续执行任何命令。从您的示例中我可以看到,批处理从startack,其中ack 被监控。但是monitorValueUpdate 会在stop 之前阻塞吗?

以上是关于用于多阶段蓝牙命令的 RxBluetoothKit 代码模式的主要内容,如果未能解决你的问题,请参考以下文章

RxBluetoothKit 文档?

RxBluetoothKit 与 RxAndroidBle

RxBluetoothkit 调用retrievePeripherals 第二次失败

NRF52833蓝牙5.1可用于105℃环境温度的Nordic蓝牙5.1 SoC能实现更广泛的并发多协议低功耗蓝牙mesh和Thread应用

sh 用于修复(Arch)Linux中的蓝牙问题的命令

怎样在Linux中使用蓝牙