首页 > 系统 > iOS > 正文

iOS 蓝牙外设OTA升级记录

2019-11-09 17:17:57
字体:
来源:转载
供稿:网友

蓝牙OTA升级。把OTA升级的大概步骤记录下,逻辑上OTA升级和常规发送数据是一样的,只是OTA固件包相对较大,所以需要将数据分割发送,每次发送20byte,在此需注意的是需要每次记录已发送的数据长度。

蓝牙扫描连接就不提了,这里从点击升级按钮开始

/*

点击升级按钮获取到固件文件的路径 并执行bluetoothManager  中的Update方法

 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);

    NSString *publicDocumentsDir = [pathsobjectAtIndex:0];

    NSString *Path = [publicDocumentsDirstringByAppendingPathComponent:tagartStr];

    NSURL *fileURL = [NSURLURLWithString:[NSStringstringWithFormat:@"file://%@",Path]];

fileStr ; 传入的固件路径转为的URL

step  自定义的一个int属性 用来判断执行的步骤

Nextstep 自定义的一个int属性,用来记录所执行的步骤

block size ;定义的每轮发送数据的大小

用到的所有的UUID 由蓝牙工程师的协议给定

expectedValue 有蓝牙协议写定,写入数据后外设会返回相应的值,用此判断下一执行步骤

 */

- (void)OTAupdate:(NSURL *)fileStr{

    CBService *service = [selffindServiceFromUUID:[selfIntToCBUUID:OTA_SERVICE_UUID]p:_peripheral];

        if (!service) {

        NSLog(@"Could not find service");

        return;

    }

    CBCharacteristic *characteristic = [selffindCharacteristicFromUUID:[CBUUIDUUIDWithString:OTA_SERV_STATUS_UUID]service:service];

    if (!characteristic) {

        NSLog(@"Could not find characteristic");

        return;

    }

   //重新订阅通知

    [_peripheral setNotifyValue:YESforCharacteristic:characteristic];

    

    

    fileData = [[NSDatadataWithContentsOfURL:fileStr] mutableCopy];

    step = 1;

    blockSize = 240;

    [self doStep];

    

    

}

//最重要的步骤:按照蓝牙回调的值执行相应步骤和写入数据

- (void)doStep {

        switch (step) {

        case 1: {

            step = 0;

            expectedValue =0x00;

            nextStep =2;

     //memoryType:蓝牙协议定义的类型 memoryBank:蓝牙协议定义

            int _memDevData = (memoryType <<24) | (memoryBank &0xFF);

            NSData *memDevData = [NSDatadataWithBytes:&_memDevData length:sizeof(int)];

    //写入文件头

            [self writeValue:[selfIntToCBUUID:OTA_SERVICE_UUID]characteristicUUID:[CBUUIDUUIDWithString:OTA_MEM_DEV_UUID]p:_peripheraldata:memDevData];

            break;

        }

            

        case 2: {

            int _memInfoData;

            _memInfoData = (spiMISOAddress <<24) | (spiMOSIAddress <<16) | (spiCSAddress <<8) | spiSCKAddress;

            NSData *memInfoData = [NSDatadataWithBytes:&_memInfoData length:sizeof(int)];

            step = 3;

            [self writeValue:[selfIntToCBUUID:OTA_SERVICE_UUID]characteristicUUID:[CBUUIDUUIDWithString:OTA_GPIO_MAP_UUID]p:self.peripheraldata:memInfoData];

             break;

        }

        case 3: {

          //固件数据打包

            uint8_t crc_code =0;

            const char *bytes = [fileDatabytes];

            for (int i =0; i < [fileDatalength]; i++) {

                crc_code ^= bytes[i];

            }

            

            [fileData appendBytes:&crc_code length:sizeof(uint8_t)];

             chunkSize =20; //每次发送数据的大小

            blockStartByte =0; //用于累加数据值

            step = 4;

            [self doStep];

     

            

            break;

        }

        case 4: {

            NSData *patchLengthData = [NSDatadataWithBytes:&blockSizelength:sizeof(UInt16)];

            step = 5;

            [self writeValue:[selfIntToCBUUID:OTA_SERVICE_UUID]characteristicUUID:[CBUUIDUUIDWithString:OTA_PATCH_LEN_UUID]p:self.peripheraldata:patchLengthData];

            break;

        }

        case 5: {

            step = 0;

            expectedValue =0x00; //蓝牙协议给定,根据回调判断用

            nextStep =5;

            int dataLength = (int) [fileDatalength];

            int chunkStartByte =0;

      //判断已发送的数据长度

            while (chunkStartByte <blockSize) {

                int bytesRemaining =blockSize - chunkStartByte;

                if (bytesRemaining <chunkSize) {

                    chunkSize = bytesRemaining;

                }

                char bytes[chunkSize];

                [fileDatagetBytes:bytes range:NSMakeRange(blockStartByte + chunkStartByte,chunkSize)];

                NSData *byteData = [NSDatadataWithBytes:&bytes length:sizeof(char)*chunkSize];

                

                chunkStartByte += chunkSize;

                if (chunkStartByte >=blockSize) {

                    blockStartByte +=blockSize;

                    

                    int bytesRemaining = dataLength -blockStartByte;

                    

                    if (bytesRemaining ==0) {

                        nextStep =6;

                        

                    } elseif (bytesRemaining < blockSize) {

                        blockSize = bytesRemaining;

                        nextStep =4; 

                    }

                }

          //这里是向蓝牙写入数据

                [self writeValue:[selfIntToCBUUID:OTA_SERVICE_UUID]characteristicUUID:[CBUUIDUUIDWithString:OTA_PATCH_DATA_UUID]p:self.peripheraldata:byteData andResponseType:CBCharacteristicWriteWithoutResponse];

               

            }

            

            break;

        }

        case 6: {

            step = 0;

            expectedValue =0x00;

            nextStep =7;

           //发送文件尾

            int suotaEnd =0xFE000000;

            NSData *suotaEndData = [NSDatadataWithBytes:&suotaEnd length:sizeof(int)];

            [self writeValue:[selfIntToCBUUID:OTA_SERVICE_UUID]characteristicUUID:[CBUUIDUUIDWithString:OTA_MEM_DEV_UUID]p:_peripheraldata:suotaEndData];

            break;

        }

        case 7: {

            UIAlertView *alert = [[UIAlertViewalloc] initWithTitle:@"Device has been updated"message:@"Do you wish to reboot the device?"delegate:selfcancelButtonTitle:@"No"otherButtonTitles:@"Yes, reboot",nil];

            [alert setTag:1];

            [alert show];

            break;

        }

        case 8: {

            break;

        }

    }

}

//==========coreBluetooth 回调

#PRagma mark 写数据后回调

- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic  error:(NSError *)error {

    NSLog(@"写入成功===%zd",step);

    if (step &&step != 7) {

        [self doStep];

    }

}

if ([characteristic.UUIDisEqual:[CBUUIDUUIDWithString:OTA_SERV_STATUS_UUID]]) {

        char value;

        [characteristic.valuegetBytes:&value length:sizeof(char)];

        if (expectedValue !=0) {

            if (value ==expectedValue) {

                step =nextStep;

                expectedValue =0; 

                [self doStep];

            } else {

                UIAlertView *alertView = [[UIAlertViewalloc] initWithTitle:@"Error"message:@"hehe"delegate:nilcancelButtonTitle:@"OK"otherButtonTitles:nil];

                [alertView show];

                

                expectedValue =0; // Reset

            }

        }

    }

//**********  用到的一些方法

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {

  //这里重启设备

    if (alertView.tag ==1) {

        if (buttonIndex != alertView.cancelButtonIndex) {

            // Send reboot signal to device

            step = 8;

            int suotaEnd =0xFD000000;

            NSData *suotaEndData = [NSDatadataWithBytes:&suotaEnd length:sizeof(int)];

            [self writeValue:[selfIntToCBUUID:OTA_SERVICE_UUID]characteristicUUID:[CBUUIDUUIDWithString:OTA_MEM_DEV_UUID]p:_peripheraldata:suotaEndData];

        }

    }

}

- (void) writeValue:(CBUUID*)serviceUUID characteristicUUID:(CBUUID*)characteristicUUID p:(CBPeripheral *)p data:(NSData *)data {

    

    CBService *service = [selffindServiceFromUUID:serviceUUID p:p];

    if (!service) {

        NSLog(@"Could not find service");

        return;

    }

    CBCharacteristic *characteristic = [selffindCharacteristicFromUUID:characteristicUUIDservice:service];

    if (!characteristic) {

        NSLog(@"Could not find characteristic");

        return;

    }

    [_peripheral writeValue:data forCharacteristic:characteristictype:CBCharacteristicWriteWithResponse];

   

}

- (void) writeValue:(CBUUID*)serviceUUID characteristicUUID:(CBUUID*)characteristicUUID p:(CBPeripheral *)p data:(NSData *)data andResponseType:(CBCharacteristicWriteType)responseType

{

    CBService *service = [selffindServiceFromUUID:serviceUUID p:p];

    if (!service) {

        NSLog(@"Could not find service ");

        return;

    }

    CBCharacteristic *characteristic = [selffindCharacteristicFromUUID:characteristicUUIDservice:service];

    if (!characteristic) {

        NSLog(@"Could not find characteristic");

        return;

    }

    [p writeValue:dataforCharacteristic:characteristic type:responseType];

}

- (CBService *) findServiceFromUUID:(CBUUID *)UUID p:(CBPeripheral *)p {

    for(int i =0; i < p.services.count; i++) {

        CBService *s = [p.servicesobjectAtIndex:i];

        if ([selfcompareCBUUID:s.UUIDUUID2:UUID]) return s;

    }

    return nil;//Service not found on this peripheral

}

-(int) compareCBUUID:(CBUUID *) UUID1 UUID2:(CBUUID *)UUID2 {

    char b1[16];

    char b2[16];

    [UUID1.data getBytes:b1];

    [UUID2.data getBytes:b2];

    if (memcmp(b1, b2, UUID1.data.length) ==0)return1;

    else return0;

}

-(CBUUID *) IntToCBUUID:(UInt16)UUID {

    

    UInt16 cz = [selfswap:UUID];

    NSData *cdz = [[NSDataalloc] initWithBytes:(char *)&czlength:2];

    CBUUID *cuz = [CBUUIDUUIDWithData:cdz];

    return cuz;

}

-(UInt16) CBUUIDToInt:(CBUUID *) UUID {

    char b1[16];

    [UUID.data getBytes:b1];

    return ((b1[0] <<8) | b1[1]);

}

- (UInt16) swap:(UInt16)s {

    UInt16 temp = s <<8;

    temp |= (s >> 8);

    return temp;

}

-(CBCharacteristic *) findCharacteristicFromUUID:(CBUUID *)UUID service:(CBService*)service {

    for(int i=0; i < service.characteristics.count; i++) {

        CBCharacteristic *c = [service.characteristicsobjectAtIndex:i];

        if ([selfcompareCBUUID:c.UUIDUUID2:UUID]) return c;

    }

    return nil;//Characteristic not found on this service

}


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表