在开发智能蓝牙移动app中,我们需要进行ota功能的开发;
具体操作流程记录一下:
一.在发送设备进入到OTA模式的地方进行第一步操作:
//ota升级
let ins: UInt8 = 0xFF
let len: UInt8 = 4
let data: [UInt8] = [0x5A,0xA5,0x67,0x76]
let packet = self.allExpanded.buildInstructionPacket(ins: ins, len: len, data: data)
- buildInstructionPacket方法是根据指令格式构建数据包
func buildInstructionPacket(ins: UInt8, len: UInt8, data: [UInt8]) -> Data {
var packet = Data()
packet.append(ins)
packet.append(len)
packet.append(contentsOf: data)
let crc = packet.reduce(0, { $0 &+ $1 }) & 0xFF ^ 0xFF
packet.append(UInt8(crc))
return packet
}
二:发送构建好的数据包到蓝牙
- packet就是上面构建好的数据包,发送此命令给底层设备
- self.model?.mSendotacharater是需要发送进入OTA的UUID
- self.model?.mPeripheral是服务
BleManager.shared.writeValue(packet, self.model?.mSendotacharater, self.model?.mPeripheral)
三,此时就是蓝牙管理数据层,调用发送写入方法;
//写入蓝牙数据
func writeValue(_ value:Data?, _ character:CBCharacteristic?, _ periperal:CBPeripheral?){
if value != nil && character != nil && periperal != nil {
writeataValue(value!, for: character, periperalData: periperal)
}
}
- value就是BleManager.shared.writeValue发送过来的构建好的数据
- writeataValue是蓝牙写入方法,如下
func writeataValue(_ value:Data, for characteristic: CBCharacteristic?, periperalData periperal: CBPeripheral?){
let data:Data = value
if (characteristic?.properties.rawValue)! & CBCharacteristicProperties.writeWithoutResponse.rawValue != 0 {
periperal?.writeValue(data, for: characteristic!, type: .withoutResponse)
} else {
periperal?.writeValue(data, for: characteristic!, type: .withResponse)
}
}
好了,数据发送到设备,进入ota模式就成功了;
以下是两个方法:
1.调用服务成功后,获取到特征值
//调取服务成功,读取特征值
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
if error != nil {
if let error = error {
print("发现蓝牙特征出现错误,错误原因:\(error)")
}
} else {
for character in service.characteristics ?? [] {
print("==character== ",character.uuid)
// 重新设计制作 2023/6/27 13:46
if character.uuid == RECEIVE_DATA_UUID {
for model in successList {
// 当前的peripheral 相等
if model.mPeripheral == peripheral{
model.readTempCharater = character
//peripheral.discoverDescriptors(for: character)
//peripheral.readValue(for: character)
peripheral.setNotifyValue(true, for: character)
// 打开通知代码
//peripherals(peripheral: peripheral, didDiscoverCharacteristicsForService: service, error: error as NSError?)
}
}
}
// Ota
else if character.uuid == SEND_OTA_UUID {
for model in successList {
if model.mPeripheral == peripheral {
model.mSendotacharater = character
//开启通知
peripheral.setNotifyValue(true, for: character)
}
}
}else if character.uuid == RECEIVE_FILE_UUID{
for model in successList {
if model.mPeripheral == peripheral {
//开启通知
peripheral.setNotifyValue(true, for: character)
}
}
}
}
}
}
2.在外设中查询服务,打开通知服务CCCD
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
if error != nil {
if let error = error {
print("扫描服务出现错误,错误原因:\(error)")
}
} else {
for service in peripheral.services ?? [] {
print("服务UUID为...:\(service.uuid)");
peripheral.discoverCharacteristics(nil, for: service)
if service.uuid == CBUUID(string: "FFF2") {
// 发现目标服务,设置通知和温度采样间隔
//peripheral.setNotifyValue(true, for: service.characteristics?.first!)
//setTemperatureSamplingInterval(interval: 0x02)
enableNotification(peripheral) // 调用enableNotification()方法
}
}
}
}
// 打开通知服务CCCD
func enableNotification(_ peripheral: CBPeripheral) {
// 将CCCD的值设置为1,表示打开通知服务
let value: [UInt8] = [0x01, 0x00]
let cccd = CBUUID(string: "2902")
let characteristic = peripheral.services?.first?.characteristics?.first(where: { $0.uuid == cccd })
peripheral.writeValue(Data(value), for: characteristic!, type: .withResponse)
}