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

iOS BLE开发:CBPeripheralManager传输图片数据及updateValue方法问题

实现BLE图片数据传输(基于CBPeripheralManager.updateValue)

嘿,我来帮你搞定这个BLE图片传输的问题!你已经有了PeripheralManager的状态回调,接下来咱们一步步实现图片数据的分片发送逻辑:

1. 先准备BLE服务和可通知特征

首先得创建一个BLE服务,以及一个支持**通知(Notify)**的特征——因为图片数据通常比较大,用通知模式来推送分片数据是最合适的。在你的peripheralManagerDidUpdateState里补充.poweredOn的分支:

func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
    switch peripheral.state {
    case .unknown:
        print("central.state is .unknown")
    case .resetting:
        print("central.state is .resetting")
    case .unsupported:
        print("central.state is .unsupported")
    case .unauthorized:
        print("central.state is .unauthorized")
    case .poweredOff:
        print("central.state is .poweredOff...")
    case .poweredOn:
        // 当BLE开启时,创建服务和特征
        let imageServiceUUID = CBUUID(string: "YOUR_CUSTOM_SERVICE_UUID")
        let imageCharacteristicUUID = CBUUID(string: "YOUR_CUSTOM_CHARACTERISTIC_UUID")
        
        // 创建可通知的特征,属性设为Notify,权限设为可读
        let imageCharacteristic = CBMutableCharacteristic(
            type: imageCharacteristicUUID,
            properties: .notify,
            value: nil,
            permissions: .readable
        )
        
        // 创建服务并添加特征
        let imageService = CBMutableService(type: imageServiceUUID, primary: true)
        imageService.characteristics = [imageCharacteristic]
        
        // 添加服务到PeripheralManager
        peripheral.add(imageService)
        
        // 开始广播服务
        peripheral.startAdvertising([CBAdvertisementDataServiceUUIDsKey: [imageServiceUUID]])
        print("BLE开启,已启动服务广播")
    @unknown default:
        print("未知状态")
    }
}

2. 处理图片数据的分片

BLE的MTU(最大传输单元)默认是20字节(实际可用数据是17字节,因为ATT层有3字节头部),所以需要把图片Data切成多个小分片:

// 全局或类成员变量,存储分片数据和当前发送索引
var imageDataChunks: [Data] = []
var currentChunkIndex = 0
var targetCharacteristic: CBMutableCharacteristic?
var peripheralManager: CBPeripheralManager! // 确保你已经初始化了这个实例

// 拆分图片数据的方法
func splitImageData(_ imageData: Data) {
    let mtuSize = peripheralManager.maximumWriteValueLength(for: .withoutResponse)
    // 实际可用的分片大小:MTU减去ATT头的3字节
    let chunkSize = mtuSize - 3
    
    // 按chunkSize拆分数据
    imageDataChunks.removeAll()
    for i in stride(from: 0, to: imageData.count, by: chunkSize) {
        let endIndex = min(i + chunkSize, imageData.count)
        let chunk = imageData[i..<endIndex]
        imageDataChunks.append(chunk)
    }
    currentChunkIndex = 0
    print("图片已拆分为\(imageDataChunks.count)个分片")
}

3. 用updateValue发送分片数据

当中心设备订阅了你的特征后,就可以开始发送分片。首先要监听特征的订阅事件:

func peripheralManager(_ peripheral: CBPeripheralManager, central: CBCentral, didSubscribeTo characteristic: CBCharacteristic) {
    print("中心设备已订阅特征,开始发送图片分片")
    targetCharacteristic = characteristic as? CBMutableCharacteristic
    // 假设你已经把图片转成了Data,这里用示例图片做演示
    if let imageData = UIImage(named: "yourImageName")?.pngData() {
        splitImageData(imageData)
        // 发送第一个分片
        sendNextChunk()
    }
}

// 发送下一个分片的方法
func sendNextChunk() {
    guard let characteristic = targetCharacteristic, currentChunkIndex < imageDataChunks.count else {
        print("所有分片已发送完成")
        return
    }
    
    let chunk = imageDataChunks[currentChunkIndex]
    // 调用updateValue发送数据,第二个参数是目标特征
    let success = peripheralManager.updateValue(chunk, for: characteristic, onSubscribedCentrals: nil)
    
    if success {
        currentChunkIndex += 1
        print("已发送第\(currentChunkIndex)/\(imageDataChunks.count)个分片")
        // 继续发送下一个(如果队列没满的话)
        sendNextChunk()
    } else {
        print("当前发送队列已满,等待回调继续")
    }
}

4. 处理发送队列满的情况

当updateValue返回false时,说明BLE发送队列已满,需要等待系统回调后再继续发送:

func peripheralManagerIsReadyToUpdateSubscribers(_ peripheral: CBPeripheralManager) {
    print("发送队列已就绪,继续发送分片")
    sendNextChunk()
}

关键注意点

  • MTU协商:如果想提升传输效率,可以和中心设备协商更大的MTU,这样能减少分片数量(最大MTU可达512字节)。
  • 数据校验:建议在每个分片里加入分片索引、总片数等标识信息,让中心设备能正确拼接数据,避免丢片或顺序错乱。
  • 异常处理:要处理中心设备取消订阅、连接断开等情况,及时停止发送并清理分片数据。

内容的提问来源于stack exchange,提问作者ironRoei

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:39:25