You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 06:15:14