ios - 快速将 BLE 特征值转换为字符串
问题描述
我遇到了一个毫无意义的问题。我认为我所做的一切对于 BLE 来说都是非常标准的。无论如何,我有一个 BLE 模块,我正在向 iOS 应用程序发送字符串数据,并且我在界面上显示这些数据。由于这是我第一次在 iOS 应用程序上使用 BLE 代码,我使用 adafruit 的教程作为指南,可以在此处找到:Adafruit 教程
正如我所说,非常标准的东西。这里没什么特别的。我编写的代码能够执行所有 BLE 步骤。但是,当它获取数据时,数据是/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0
. 起初,我认为发送端的来源不正确。但是我打开了另一个测试应用程序,它可以让我看到发送的 BLE 数据,并且输入的数据格式正确。这一定是我的代码的问题。我不确定为什么会发生这种情况或问题是什么。我真的可以用另一双眼睛来看看我的代码是否有任何问题:
我的代码初始化代码:
required init(parent: ViewController) {
self.parent = parent
self.bluetoothOn = false;
bodyTemperature = 0
airPressure = 0
lightLevel = 0
fanSpeed = 0
Humidity = 0
otherBatteryLevel = 0
wifiStatus = "Good"
super.init()
self.centralManager = CBCentralManager(delegate: self, queue: nil)
// self.periphal = CBPeripheralManager(delegate: self, queue: nil)
}
我的 didupdateState 代码:
func centralManagerDidUpdateState(_ central: CBCentralManager) {
if #available(iOS 10.0, *) {
if centralManager.state == CBManagerState.poweredOn{
bluetoothOn = true
self.centralManager.scanForPeripherals(withServices: [ATP_SERVICE_UUID], options: [CBCentralManagerScanOptionAllowDuplicatesKey : false])
}
} else {
// Fallback on earlier versions
}
}
我的 didDiscover 代码:
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
stopScan()
self.blePeripheral = peripheral
self.RSSI = RSSI
self.blePeripheral.delegate = self
centralManager?.connect(blePeripheral, options: nil)
print("Found BLE module")
// blePeripheral.discoverServices([ATP_SERVICE_UUID])
}
我的 didConnect 代码:
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
print("Connected to BLE device")
centralManager?.stopScan()
blePeripheral.delegate = self
blePeripheral.discoverServices([ATP_SERVICE_UUID])
}
我的 didDiscoverServices 代码:
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
guard let services = peripheral.services else{
return
}
for service in services{
peripheral.discoverCharacteristics([ATP_UART_WRITE14_UUID, ATP_UART_READ13_UUID, ATP_NOTIFY_UUID], for: service)
}
print("Discovered Services: \(services)")
}
我的 didDiscoverCharacteristics 代码:
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
guard let characteristics = service.characteristics else{
return
}
print ("Found \(characteristics.count) characteristics")
for characteristic in characteristics{
if characteristic.uuid.isEqual(ATP_UART_READ13_UUID){
readCharacteristic = characteristic
// blePeripheral.setNotifyValue(true, for: readCharacteristic!)
blePeripheral.readValue(for: characteristic)
print("Rx Characteristic: \(characteristic.uuid)")
}
if(characteristic.uuid.isEqual(ATP_UART_WRITE14_UUID)){
writeCharacteristic = characteristic
print("Tx characteristic: \(characteristic.uuid)")
}
}
}
我的 didupdateNotificationState 代码:
func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
if(error != nil){
print("Error changing notification state:\(String(describing: error?.localizedDescription))")
} else {
print("Characteristic's value subscribed")
}
if(characteristic.isNotifying){
print("Subscribed. Notification has begun for: \(characteristic.uuid)")
}
}
最后,我的 didUpdateValueFor:
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
if characteristic == readCharacteristic{
// let ASCIIString = NSString(data: characteristic.value!, encoding: String.Encoding.utf8.rawValue)
var stringFromData = String(data: characteristic.value!, encoding: String.Encoding.ascii)
if stringFromData != "" {
let textArray = stringFromData!.components(separatedBy: "\n\r")
for line in textArray{
if line.hasPrefix("bodyTemperature:") {
var splitString = line.characters.split(separator: ":").map(String.init)
bodyTemperature = Float(splitString[1])!
self.delegate?.PQEData(didRecieveData: bodyTemperature)
} else if line.hasPrefix("enclosurePressure:") {
var splitString = line.characters.split(separator: ":").map(String.init)
airPressure = Float(splitString[1])!
self.delegate?.PQEData(didRecieveData: airPressure)
} else if line.hasPrefix("lightLevel:") {
var splitString = line.characters.split(separator: ":").map(String.init)
lightLevel = Float(splitString[1])!
self.delegate?.PQEData(didRecieveData: lightLevel)
} else if line.hasPrefix("humidity:") {
var splitString = line.characters.split(separator: ":").map(String.init)
Humidity = Float(splitString[1])!
self.delegate?.PQEData(didRecieveData: Humidity)
} else if line.hasPrefix("BATT:") {
var splitString = line.characters.split(separator: ":").map(String.init)
otherBatteryLevel = Float(splitString[1])!
self.delegate?.PQEData(didRecieveData: otherBatteryLevel)
} else if line.hasPrefix("fanSpeed:") {
var splitString = line.characters.split(separator: ":").map(String.init)
fanSpeed = Int(splitString[1])!
self.delegate?.PQEData(didRecieveData: fanSpeed)
} else if line.hasPrefix("wifiStatus:") {
var splitString = line.characters.split(separator: ":").map(String.init)
wifiStatus = splitString[1]
self.delegate?.PQEData(didRecieveData: wifiStatus)
}
}
}
}
}
补充说明:
1)在 didDiscoverCharaceristics 函数中,我已经注释掉了对blePeripheral.setNotifyValue
函数的调用。那是因为在呼叫peripheral.discoverCharacteristics
呼叫的线路上,我已经发现了 NOTIFY 特征。我还使用未注释的 setNotifyValue 进行了测试,结果是相同的。
2) 我有一个名为 blePeriphal 的局部变量,它存储对 ble 设备外围设备的引用。同样适用于 writeCharacteristic 和 readCharacteristic
3) 当blePeripheral.setNotifyValue
函数被取消注释时,didUpdateNotificationStateFor
函数被执行。但是,该if(error != nil)
陈述是正确的,我会得到的错误是:Error changing notification state:Optional("The request is not supported.")
。我不确定这是否相关。但是,该didUpdateValueFor
函数仍将被执行。
4)在函数中找到给我问题的代码,didUpdateValueFor
该行是:var stringFromData = String(data: characteristic.value!, encoding: String.Encoding.ascii)
5)是的,我确实尝试过var stringFromData = String(data: characteristic.value!, encoding: String.Encoding.utf8)
,var stringFromData = String(data: characteristic.value!, encoding: String.Encoding.utf8.rawValue)
结果是一样的。StringFromData
是全部/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0
更新:
6)所以经过一些测试,我遇到了一个可能相关的问题。代表只被调用一次,didUpdateValueFor
之后就再也不会了。我通过每 1/4 秒不断发送一个字符串来验证这一点。
解决方案
推荐阅读
- .net - 有没有一种简单的方法可以让 SQL Server 和/或 .net 使用 NodeJS 对象?
- ios - 使用 Uitextfield 进行用户输入,尝试转换为 int,如果不是 int 则返回 0
- regex - 其中哪一种情况涉及回溯?
- python - 脚本应该创建文件并在其中写入数据,文件被创建但为空
- r - 在 R 中将宽面板 data.frame 转换为长从到(源-目的地)转换格式
- r - 防止因子转换为水平
- .net - 从 xml 流中提取最新日期的记录
- angular - 使用 jasmine/karma 在 Angular 6 中测试返回语句
- windows - Windows 和 CMake 下的共享库:安装前未找到 DLL
- algorithm - 随机算法的概率放大