草庐IT

ios - 从 Swift 写入 BLE 外设

coder 2023-09-09 原文

我正在构建一个连接到 BLE device (Redbear Labs Duo) 的 iOS Swift 应用程序.

什么有效?

  1. 我能够启动设备扫描
  2. 连接到设备
  3. 收集 BLE 设备的服务和特征 - 一切正常

问题出在哪里?

  1. BLE 设备 (Redbear Labs Duo) 也有一个板载 Wifi Controller ,能够扫描可用网络。 The documentation声明要扫描 Wifi 必须
    • 使用 UUID 3EC61400-89CD-49C3-A0D9-7A85669E901E 连接到主要服务
    • 找到UUID为3EC61401-89CD-49C3-A0D9-7A85669E901E的命令特征
    • 发送一个2字节的命令[0x20, 0xA0]到命令特征
    • 还设置一个 1 字节状态指示符 0xB1 到具有 UUID 3EC61402-89CD-49C3-A0D9-7A85669E901E 的扫描特征

我执行上述步骤的代码如下..

func scanWifi() {
    print("[DEBUG] - Scanning for Wifi")

    let command:[UInt8] = [0x02, 0xA0]
    let commandData = NSData(bytes: command, length: command.count)
    BLE.sharedInstance.write(toCharacteristic: BLE.sharedInstance.RBL_CHAR_CMD_UUID, data: commandData, withType: .withResponse)

    let state:[UInt8] = [0xB1]
    let stateData = NSData(bytes: state, length: state.count)
    BLE.sharedInstance.write(toCharacteristic: BLE.sharedInstance.RBL_CHAR_SCN_UUID, data: stateData, withType: .withResponse)

    BLE.sharedInstance.read(fromCharacteristic: BLE.sharedInstance.RBL_CHAR_SCN_UUID)
}

一切正常...但是...将上述数据写入外围设备后,我期待调用下面的方法 - 它从来没有调用过..我做错了什么?

func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
        if error != nil {

            print("[ERROR] Error updating value. \(error!.localizedDescription)")
            return
        }

        if characteristic.uuid.uuidString == RBL_CHAR_CMD_UUID {

            self.delegate?.bleDidReceiveData(data: characteristic.value as NSData?)
        }
    }

更新:

我设置了一堆调试语句并得到了以下输出 - 从下面可以明显看出

  1. 我能够识别并连接到正确的设备和特征
  2. 我能够适本地设置通知值

[DEBUG] Connecting to peripheral: 547BC3C9-4823-431C-B888-A8F3E8C699F5
[DEBUG] Connected to peripheral 547BC3C9-4823-431C-B888-A8F3E8C699F5
[DEBUG] Did connect to peripheral
[DEBUG] Found service: 3EC61400-89CD-49C3-A0D9-7A85669E901E for peripheral: 547BC3C9-4823-431C-B888-A8F3E8C699F5
[DEBUG] Found characteristic: 3EC61401-89CD-49C3-A0D9-7A85669E901E for peripheral: 547BC3C9-4823-431C-B888-A8F3E8C699F5
[DEBUG] Found characteristic: 3EC61402-89CD-49C3-A0D9-7A85669E901E for peripheral: 547BC3C9-4823-431C-B888-A8F3E8C699F5
("3EC61402-89CD-49C3-A0D9-7A85669E901E", )
("3EC61401-89CD-49C3-A0D9-7A85669E901E", )
[DEBUG] didUpdateNotification state for characteristic CBCharacteristic: 0x1702a6c60, UUID = 3EC61401-89CD-49C3-A0D9-7A85669E901E, properties = 0x14, value = (null), notifying = YES on peripheral: CBPeripheral: 0x1740fba80, identifier = 547BC3C9-4823-431C-B888-A8F3E8C699F5, name = Duo-ZKBY, state = connected
[DEBUG] didUpdateNotification state for characteristic: CBCharacteristic: 0x1742a3c60, UUID = 3EC61402-89CD-49C3-A0D9-7A85669E901E, properties = 0x10, value = (null), notifying = YES on peripheral: CBPeripheral: 0x1740fba80, identifier = 547BC3C9-4823-431C-B888-A8F3E8C699F5, name = Duo-ZKBY, state = connected

最佳答案

找到解决方案 - 在此发布以造福他人。

阅读Redbear Labs 提供的文档,需要注意的关键是Command 特性仅支持两种类型的属性- PROPERTY_WRITE_NO_RESPONSE | PROPERTY_NOTIFY

同样,Scan 特性仅支持 PROPERTY_NOTIFY

此外,要让设备扫描所有可用的 Wifi - 我们应该只向命令特征写入一个 2 字节的命令 [0x20, 0xA0] - 相同的代码如下

func scanWifi() {
        print("[DEBUG] - Scanning for Wifi")

        let command:[UInt8] = [0x02, 0xA0]
        let commandData = NSData(bytes: command, length: command.count)
        BLE.sharedInstance.writeTo(characteristic: BLE.sharedInstance.RBL_CHAR_CMD_UUID, data: commandData, withType: .withoutResponse)
}

无需向扫描特征写入任何内容。当 Wifi 扫描开始时,Scan 特性将发送一个值为 0xB1 的通知以指示扫描开始,然后发送一个值为 0xB2 的通知以指示扫描结束。

扫描到的实际 Wifi 网络将通过命令特征本身的通知发送。

关于ios - 从 Swift 写入 BLE 外设,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41029477/

有关ios - 从 Swift 写入 BLE 外设的更多相关文章

  1. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  2. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  3. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  4. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  5. ruby - Ruby 是否使用 $stdout 来写入 puts 和 return 的输出? - 2

    我想知道Ruby用来在命令行打印这些东西的输出流:irb(main):001:0>a="test"=>"test"irb(main):002:0>putsatest=>nilirb(main):003:0>a=>"test"$stdout是否用于irb(main):002:0>和irb(main):003:0>?而且,在这两次调用之间,$stdout的值是否有任何变化?另外,有人能告诉我打印/写入这些内容的Ruby源代码吗? 最佳答案 是的。而且很容易向自己测试/证明。在命令行试试这个:ruby-e'puts"foo"'>test.

  6. ruby - 为什么不能使用类IO的实例方法noecho? - 2

    print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上

  7. Ruby:写入 stdin 并从 stdout 读取? - 2

    我正在编写一个ruby​​程序,它应该执行另一个程序,通过stdin向它传递值,从它的stdout读取响应,然后打印响应。这是我目前所拥有的。#!/usr/bin/envrubyrequire'open3'stdin,stdout,stderr=Open3.popen3('./MyProgram')stdin.puts"helloworld!"output=stdout.readerrors=stderr.readstdin.closestdout.closestderr.closeputs"Output:"puts"-------"putsoutputputs"\nErrors:"p

  8. Ruby -> 写入二维数组 - 2

    我正在处理http://prepwork.appacademy.io/mini-curriculum/array/中概述的数组问题我正在尝试创建函数my_transpose,它接受一个矩阵并返回其转置。我对写入二维数组感到很困惑!这是一个代码片段,突出了我的困惑。rows=[[0,1,2],[3,4,5],[6,7,8]]columns=Array.new(3,Array.new(3))putscolumns.to_s#Outputisa3x3arrayfilledwithnilcolumns[0][0]=0putscolumns.to_s#Outputis[[0,nil,nil],[

  9. ruby - 使写入文件线程安全 - 2

    我在一个ruby​​文件中有一个函数可以像这样写入一个文件File.open("myfile",'a'){|f|f.puts("#{sometext}")}这个函数在不同的线程中被调用,使得像上面这样的文件写入不是线程安全的。有谁知道如何以最简单的方式使这个文件写入线程安全?更多信息:如果重要的话,我正在使用rspec框架。 最佳答案 您可以通过File#flock给锁File.open("myfile",'a'){|f|f.flock(File::LOCK_EX)f.puts("#{sometext}")}

  10. ruby - Rmagick 在图像中写入文本 - 2

    有人可以花我一些代码,在图像底部添加文本吗?我想使用Rmagick,但我也愿意使用其他工具。 最佳答案 我也发现了这个,它非常适合我。require'RMagick'includeMagick#Dimisionsbasedonanimage3072x2048unlessARGV[0]andFile.exists?(ARGV[0])puts"\n\n\nYouneedtospecifyafilename:watermark.rb\n\n\n"exitendimg=Image.read(ARGV[0]).firstnew_img="wm

随机推荐