Swift中向BLE设备发送JSON指令并获取对应响应的方法
BLE设备指令发送问题:已连接但自定义JSON指令未生效
问题背景
我是BLE设备集成新手,已完成BLE设备连接代码且连接成功,现在需要发送自定义JSON指令从设备获取数据。设备与应用的指令交互格式如下:
应用→设备指令
{"cmd": "getBatteryLevel"} {"cmd":"setLight", "channel":"0", "brightness":100, "state":"ON"}
设备→应用成功响应
{"cmd": "getBatteryLevel", "response":100} {"cmd":"setLight", "channel":"0", "brightness":100, "state":"ON", "response":"OK"}
尝试的代码(未生效)
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { guard let characteristics = service.characteristics else { return } for characteristic in characteristics { if characteristic.properties.contains(.write) && !isValueWritten { // Save the characteristic for later use self.characteristic = characteristic guard let data = self.viewModel.setBLELightCommand() else { return print("Invalid data") } peripheral.writeValue(data, for: characteristic, type: .withResponse) } } } func convertJsonDictToData(_ dict:[String:Any])->Data?{ do { let jsonData = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted) // here "jsonData" is the dictionary encoded in JSON data guard let jsonString = String(data: jsonData, encoding: .utf8), let data = jsonString.data(using: .utf8) else { return nil } return data } catch { print(error.localizedDescription) return nil } } func setBLELightCommand()->Data?{ let setLightCommand = [ "cmd" : "setLight", "channel" : "0", "brightness" : "50", "state" : "ON" ] return convertJsonDictToData(setLightCommand) }
问题排查与解决方案
1. JSON数据类型不匹配
你发送的brightness是字符串类型("50"),但设备要求的是数字类型(如示例中的100),设备无法解析类型错误的指令,需修改为数字:
func setBLELightCommand()->Data?{ let setLightCommand = [ "cmd" : "setLight", "channel" : "0", "brightness" : 50, // 改为数字类型 "state" : "ON" ] return convertJsonDictToData(setLightCommand) }
2. JSON序列化冗余操作
convertJsonDictToData中存在不必要的转码步骤,直接返回JSON序列化后的Data即可,同时避免使用.prettyPrinted(设备通常需要紧凑的JSON格式):
func convertJsonDictToData(_ dict:[String:Any])->Data?{ do { return try JSONSerialization.data(withJSONObject: dict, options: []) } catch { print(error.localizedDescription) return nil } }
3. 特征值写入逻辑优化
- 确认目标特征:仅通过
.write属性判断特征可能不准确,需确认设备文档中指定的指令传输特征UUID,精准匹配特征。 - 标记写入状态:在写入成功回调中设置
isValueWritten = true,避免重复写入。 - 添加写入回调排查错误:实现写入结果回调,明确是否写入失败:
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) { if let error = error { print("写入失败:\(error.localizedDescription)") return } isValueWritten = true print("写入成功") // 订阅通知以接收设备响应 peripheral.setNotifyValue(true, for: characteristic) }
4. 监听设备响应
需订阅设备的通知特征,才能接收返回数据,实现响应处理回调:
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { guard let data = characteristic.value, error == nil else { print("接收数据失败:\(error?.localizedDescription ?? "未知错误")") return } if let jsonString = String(data: data, encoding: .utf8), let responseDict = try? JSONSerialization.jsonObject(with: data, options: []) as? [String:Any] { print("设备响应:\(jsonString)") // 根据response字段处理业务逻辑 if let response = responseDict["response"] { if response as? String == "OK" || response as? Int != nil { // 指令执行成功 } } } }
内容的提问来源于stack exchange,提问作者user3587934
相关产品推荐
相关产品推荐

