藍牙OTA升級。把OTA升級的大概步驟記錄下,邏輯上OTA升級和常規(guī)發(fā)送數(shù)據(jù)是一樣的,只是OTA固件包相對較大,所以需要將數(shù)據(jù)分割發(fā)送,每次發(fā)送20byte,在此需注意的是需要每次記錄已發(fā)送的數(shù)據(jù)長度。
藍牙掃描連接就不提了,這里從點擊升級按鈕開始
/*
點擊升級按鈕獲取到固件文件的路徑 并執(zhí)行bluetoothManager 中的Update方法
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *publicDocumentsDir = [pathsobjectAtIndex:0];
NSString *Path = [publicDocumentsDirstringByAppendingPathComponent:tagartStr];
NSURL *fileURL = [NSURLURLWithString:[NSStringstringWithFormat:@"file://%@",Path]];
fileStr ; 傳入的固件路徑轉(zhuǎn)為的URL
step 自定義的一個int屬性 用來判斷執(zhí)行的步驟
Nextstep 自定義的一個int屬性,用來記錄所執(zhí)行的步驟
block size ;定義的每輪發(fā)送數(shù)據(jù)的大小
用到的所有的UUID 由藍牙工程師的協(xié)議給定
expectedValue 有藍牙協(xié)議寫定,寫入數(shù)據(jù)后外設(shè)會返回相應(yīng)的值,用此判斷下一執(zhí)行步驟
*/
- (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];
}
//最重要的步驟:按照藍牙回調(diào)的值執(zhí)行相應(yīng)步驟和寫入數(shù)據(jù)- (void)doStep {
switch (step) {
case 1: {
step = 0;
expectedValue =0x00;
nextStep =2;
//memoryType:藍牙協(xié)議定義的類型 memoryBank:藍牙協(xié)議定義
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: {
//固件數(shù)據(jù)打包
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; //每次發(fā)送數(shù)據(jù)的大小
blockStartByte =0; //用于累加數(shù)據(jù)值
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; //藍牙協(xié)議給定,根據(jù)回調(diào)判斷用
nextStep =5;
int dataLength = (int) [fileDatalength];
int chunkStartByte =0;
//判斷已發(fā)送的數(shù)據(jù)長度
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;
}
}
//這里是向藍牙寫入數(shù)據(jù)
[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;
//發(fā)送文件尾
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 回調(diào)#PRagma mark 寫數(shù)據(jù)后回調(diào)
- (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 {
//這里重啟設(shè)備
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
}
新聞熱點
疑難解答
圖片精選