// // Bluetooth.m // BluetoothDemo // // Created by mac on 17/3/9. // Copyright © 2017年 . All rights reserved. // #import "BluetoothFireBoltt.h" #import "L2DataParseFireBoltt.h" #import #import "NSString+methods.h" #import "BLETools.h" #import "BLEConstFireBoltt.h" #import "BLEBaseBlFireBoltt.h" #import "FireBoltt-Swift.h" #import #import "User_Http.h" NSString *kFLT_BLE_FOUND = @"FLT_BLE_FOUND"; //发现设备 NSString *kFLT_BLE_PAIRED = @"FLT_BLE_PAIRED"; //BLE已配对 NSString *kFLT_BLE_CONNECTED = @"FLT_BLE_CONNECTED"; //BLE已连接 NSString *kFLT_BLE_DISCONNECTED = @"FLT_BLE_DISCONNECTED"; //BLE断开连接 NSString *FLT_BLE_SERVICE = @"AE00"; //服务号 NSString *FLT_BLE_RCSP_W = @"AE01"; //命令“写”通道 NSString *FLT_BLE_RCSP_R = @"AE02"; //命令“读”通道 // 超时间隔 #define TimeOutNumber 5 // 连接延时 #define ConnectPeripheralTimerName @"Bluetooth_ConnectPeripheralTimerName" #define ConnectPeripheralTimerName2 @"Bluetooth_ConnectPeripheralTimerName2" @interface BluetoothFireBoltt () //CLLocationManagerDelegate @property (nonatomic, strong) CBPeripheralManager *peripheralManager; /** 蓝牙请求计数 */ @property (nonatomic, assign) NSInteger timeNumber; /** 是否正在执行 */ @property (nonatomic, assign) BOOL isExecuting; /** 超时定时器 */ @property (nonatomic, strong) NSTimer *checkoutTimer; /** 当前执行的命令 */ @property (nonatomic, strong) BlueToothItemFireBoltt *currenItem; /** 当前接收的数据 */ @property (nonatomic, strong) NSMutableData *currenData; /** 总数据包 */ @property (nonatomic, strong) NSMutableData *totalData; /** crc校验是否成功 */ @property (nonatomic, assign) BOOL isCrc; /** 防止手表多次调用特征值变化 */ @property (nonatomic, assign) BOOL isChangeCharacteristic; /** 重连外设 */ @property (nonatomic, strong) CBPeripheral *reconnectPeripheral; /** 是否DFU扫描 */ @property (nonatomic, assign) BOOL isDFUScan; //@property (nonatomic ,strong) CLLocationManager *locationManager; // //@property (nonatomic ,strong) CLBeaconRegion *beaconRegion; /** */ @property (nonatomic, assign) BOOL is_JL; /// 手表表盘资源文件 @property (nonatomic ,strong) NSArray *mWatchList; /// 是否正在升级 @property (nonatomic ,assign) BOOL isOtaUpdate; /// <#arguments#> @property (nonatomic ,strong) NSString *mOtaPath; @property (nonatomic ,strong) NSString *otaString; @end @implementation BluetoothFireBoltt + (nullable instancetype)shareInstance { static BluetoothFireBoltt *share = nil; static dispatch_once_t oneToken; dispatch_once(&oneToken, ^{ share = [[self alloc] init]; }); return share; } - (id)init { self = [super init]; if (self) { self.isIndependentOff = NO; self.bleRequestSid = 0; self.bluetoothItems = [NSMutableArray array]; self.currenData = [NSMutableData new]; self.totalData = [NSMutableData new]; self.cMgr = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:@{CBCentralManagerOptionRestoreIdentifierKey: @"myCentralManagerIdentifier"}]; self.isChangeCharacteristic = NO; self.is_JL = NO; self.mAssist = [[JL_Assist alloc] init]; self.mAssist.mNeedPaired = YES; //是否需要握手配对 self.mAssist.mPairKey = nil; //配对秘钥 self.mAssist.mService = FLT_BLE_SERVICE; //服务号 self.mAssist.mRcsp_W = FLT_BLE_RCSP_W; //特征「写」 self.mAssist.mRcsp_R = FLT_BLE_RCSP_R; //特征「读」 // 监听时间改变 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(timeDidChanged) name:UIApplicationSignificantTimeChangeNotification object:nil]; } return self; } /** 实时同步时间到设备 */ - (void)timeDidChanged{ if ([[BluetoothFireBoltt shareInstance] isConnected]) { // 延迟请求,防止时制切换未反应 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [[[BLEBaseBlFireBoltt alloc] init] setIngTimeWithBleCmdTypeFB:BleCMD_setIngTime]; }); } // 更改了时间通知主要界面刷新界面,1为时间标示 [[NSNotificationCenter defaultCenter] postNotificationName:SycnDatas object:@(1)]; } /** 扫描外设Peripherals @param serviceUUIDs 过滤的服务UUID @param isDFU 是否DFU升级使用 */ - (void)scanForPeripheralsWithdiscoverServices:(nullable NSArray *)serviceUUIDs IsDFU:(BOOL)isDFU { // 停止扫描 [self cancelScan]; self.isDFUScan = isDFU; // 获取系统已配对的手环平台设备,存在则加入 NSMutableArray *connectedArray = [self getPairedConnectedArray]; for (BLEModelFireBoltt *bleModel in connectedArray) { [self.delegate onDiscoverToPeripheralsBleModel:bleModel]; } // DFU模式不使用uuid的筛选扫描 if (isDFU || [[NSUserDefaults standardUserDefaults] objectForKey:DFUMASString]) { NSDictionary *options= [NSDictionary dictionaryWithObject:@NO forKey:CBCentralManagerScanOptionAllowDuplicatesKey]; [self.cMgr scanForPeripheralsWithServices:nil options:options]; return; } NSArray *uuids = @[[CBUUID UUIDWithString:BraceletServicesUUID]]; NSDictionary *scanForPeripheralsWithOptions = @{CBCentralManagerScanOptionAllowDuplicatesKey:@YES}; [self.cMgr scanForPeripheralsWithServices:uuids options:scanForPeripheralsWithOptions]; } #pragma mark - coreBlueTooth --系统代理 - (void)centralManagerDidUpdateState:(CBCentralManager *)central { self.state = central.state; [self.mAssist assistUpdateState:central.state]; if (central.state == CBManagerStatePoweredOn) { // 蓝牙开始重连 [self startAndStopReconnect:YES]; } else if (central.state == CBManagerStatePoweredOff) { [[NSNotificationCenter defaultCenter] postNotificationName:BluetoothNotificationAtPowerOff object:@"PowerOff"]; CGFloat systemVision = DEVICEVERSION; if (systemVision <10 || systemVision >= 11) { if (self.isConnected) { // 连接断开发出通知 self.isConnected = NO; [[NSNotificationCenter defaultCenter] postNotificationName:BluetoothNotificationAtDisconnect object:nil]; // 清空所有 self.writecharacteristic = nil; // 断开连接后处理,当前队列若存在则清空并且停止定时器 if (self.bluetoothItems.count) { [self.bluetoothItems removeAllObjects]; [self.checkoutTimer invalidate]; self.timeNumber = 0; _executing = NO; } } } [self startAndStopReconnect: NO]; } } //搜索蓝牙设备 - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI { NSLog(@"[蓝牙通讯] 搜索到了设备:%@ \n设备UUID:%@ \n advertisementData:%@",peripheral.name, peripheral.identifier.UUIDString, advertisementData); NSString *ble_name = advertisementData[@"kCBAdvDataLocalName"]; NSString *MACString = [[NSString alloc] init]; NSData *manufacturerData = advertisementData[@"kCBAdvDataManufacturerData"]; if (manufacturerData && manufacturerData.length >= 8) { NSData *MACData = [advertisementData[@"kCBAdvDataManufacturerData"] subdataWithRange:NSMakeRange(2, 6)]; MACString = [BluetoothToolFireBoltt getPositiveSequenceMacWithData:MACData]; } BLEModelFireBoltt *bleModel = [[BLEModelFireBoltt alloc] initWithCentral:central Peripheral:peripheral AdvertisementData:advertisementData RSSI:RSSI UUIDString:peripheral.identifier.UUIDString MACString:MACString]; // 未完成升级设备 || 需要重连的设备 if ((self.isDFUScan && [peripheral.name isEqual:@"DfuTarg"]) || [bleModel.MACString isEqualToString:[UserDefaultsManagerFrieBoltt getLocalDeviceMacID]]) { __weak typeof(self) weakSelf = self; [GCDTimer.ocShareInstance scheduledDispatchTimerWithTimerName:ConnectPeripheralTimerName2 timeInterval:self.reconnectTime queue:dispatch_get_main_queue() repeats:false immediately:false action:^{ [weakSelf connectedWithBleModel:bleModel]; weakSelf.reconnectTime = 0; }]; } if (self.delegate && [self.delegate respondsToSelector:@selector(onDiscoverToPeripheralsBleModel:)]) { [self.delegate onDiscoverToPeripheralsBleModel:bleModel]; } // ota升级过程,回连使用 if (manufacturerData != nil && self.is_JL) //if ([JL_BLEAction otaBleMacAddress:self.lastBleMacAddress isEqualToCBAdvDataManufacturerData:manufacturerData]) { // self.is_JL = NO; [self connectedWithBleModel:bleModel]; } } // 蓝牙状态的保存和恢复,进入后台和重新启动有关 - (void)centralManager:(CBCentralManager *)central willRestoreState:(NSDictionary *)dict { } // 已经连接外设 - (void) centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral { NSLog(@"[蓝牙通讯] BLE Connected ---> Device %@", peripheral.name); peripheral.delegate = self; [peripheral discoverServices:nil]; [self cancelScan]; // [peripheral discoverServices:[NSArray arrayWithObject:[CBUUID UUIDWithString:ServicesUUID]]];//再去发现服务 // 若是Dfu模式外设则在此处发出连接成功的通知 if ([peripheral.name rangeOfString:@"DfuTarg"].location != NSNotFound) { NSLog(@"DFUl连接成功!!!!"); self.isConnected = YES; [[NSNotificationCenter defaultCenter] postNotificationName:BluetoothNotificationAtDFUConnectSuccess object:nil]; } } // 连接外设失败 - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error { NSLog(@"[蓝牙通讯] 设备:%@--连接失败",peripheral.name); //if (self.isIndependentOff) [SVProgressHUD showInfoWithStatus:NSLocalizedString(@"连接失败", nil)]; // 连接失败发出通知 [[NSNotificationCenter defaultCenter] postNotificationName:BluetoothNotificationAtConnectFail object:peripheral.name]; self.isConnected = NO; //self.isRay = NO; } // 已经断开连接 - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error { NSLog(@"[蓝牙通讯] 设备:%@--断开连接",peripheral.name); /*--- JLSDK ADD ---*/ [self.mAssist assistDisconnectPeripheral:peripheral]; // 连接断开发出通知 self.isConnected = NO; //self.isRay = NO; [[NSNotificationCenter defaultCenter] postNotificationName:BluetoothNotificationAtDisconnect object:peripheral.name]; // 清空所有 self.writecharacteristic = nil; // 断开连接后处理,当前队列若存在则清空并且停止定时器 if (self.bluetoothItems.count) { [self.bluetoothItems removeAllObjects]; [self.checkoutTimer invalidate]; self.timeNumber = 0; _executing = NO; } //if (!self.isIndependentOff) [self startAndStopReconnect:YES]; } // characteristic订阅状态改变 - (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error { NSLog(@"[蓝牙通讯] //characteristic订阅状态改变的block---- %@",characteristic.value); // 判断是否监听设备广播通知成功 -->成功才发送连接成功通知 if (characteristic.isNotifying && [characteristic.UUID isEqual:[CBUUID UUIDWithString:NotifycharacteristicUUIDString]]) { NSLog(@"[蓝牙通讯] 连接成功!!!!!!"); // 连接成功保存UUID,做重连使用 [[NSUserDefaults standardUserDefaults] setObject:peripheral.identifier.UUIDString forKey:AutomaticReconnectionDevice]; // 订阅了读数据才发出连接成功通知 self.isConnected = YES; self.reconnectPeripheral = peripheral; [[NSNotificationCenter defaultCenter] postNotificationName:BluetoothNotificationAtConnectSuccess object:self.currenModel]; } [self jlTimeClose]; self.is_JL = NO; __weak typeof(self) weakSelf = self; [self.mAssist assistUpdateCharacteristic:characteristic Peripheral:peripheral Result:^(BOOL isPaired) { if (isPaired == YES) { [[NSUserDefaults standardUserDefaults] setObject:peripheral.identifier.UUIDString forKey:AutomaticReconnectionDevice]; NSLog(@"[蓝牙通讯] 配对成功"); self.reconnectPeripheral = peripheral; [JL_Tools post:kFLT_BLE_PAIRED Object:peripheral]; JL_EntityM *entity = [[JL_EntityM alloc] init]; [entity setBlePeripheral:peripheral]; self.mAssist.mCmdManager.mEntity = entity; weakSelf.lastBleMacAddress = nil; [JL_Tools delay:0.5 Task:^{ [self getInfo]; }]; } else { [weakSelf.cMgr cancelPeripheralConnection:peripheral]; } }]; } //外设传来数据 - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error { // NSLog(@" 设备发过来的 characteristic name:%@ value is:%@",characteristic.UUID,characteristic.value); /*--- JLSDK ADD ---*/ [self.mAssist assistUpdateValueForCharacteristic:characteristic]; if (characteristic.value.length && [characteristic.UUID isEqual:[CBUUID UUIDWithString:NotifycharacteristicUUIDString]]) { // 接收到的数据处理 [self handleReceiveData:[characteristic value]]; } // FRQ OTA是否存在数据 if (characteristic.value.length && [characteristic.UUID isEqual:[CBUUID UUIDWithString:kFRQReadCharacteristicUUID]]) { [[NSNotificationCenter defaultCenter] postNotificationName:FRQReadCharacteristicUUIDNotify object:characteristic.value]; } if (self.delegate && [self.delegate respondsToSelector:@selector(OnReadValueForCharacteristic:characteristicsL:)]) { [self.delegate OnReadValueForCharacteristic:peripheral characteristicsL:characteristic]; } } //发现服务 - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error { if (error) { NSLog(@"Err: Discovered services fail."); return; } for (CBService *service in peripheral.services) { NSLog(@"[蓝牙通讯] BLE Service ---> %@", service.UUID.UUIDString); [peripheral discoverCharacteristics:nil forService:service]; } if (self.delegate && [self.delegate respondsToSelector:@selector(onDiscoverServices:)]) { [self.delegate onDiscoverServices:peripheral]; } } //发现特征值 - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error { [self.mAssist assistDiscoverCharacteristicsForService:service Peripheral:peripheral]; if (IsDelegate(self, OnDiscoverCharacteristics:Service:)) { [self.delegate OnDiscoverCharacteristics:peripheral Service:service]; } if ([service.UUID isEqual:[CBUUID UUIDWithString:ServicesUUID]]) { for (CBCharacteristic *characteristic in service.characteristics ) { if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:NotifycharacteristicUUIDString]]) { [peripheral setNotifyValue:true forCharacteristic:characteristic]; } if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:WirtecharacteristicUUIDString]]) { self.writecharacteristic = characteristic; } } } // FRQ OTA if ([service.UUID isEqual:[CBUUID UUIDWithString:kFRQServiceUUID]]) { for (CBCharacteristic *characteristic in service.characteristics ) { if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kFRQReadCharacteristicUUID]]) { [peripheral setNotifyValue:true forCharacteristic:characteristic]; } if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kFRQWriteCharacteristicUUID]]) { self.frqOTAwritecharacteristic = characteristic; } } } } //写入值的监听 - (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error { NSLog(@"写入成功"); } /** 停止扫描 */ - (void)cancelScan { [self.cMgr stopScan]; } //-(void)centralManager:(CBCentralManager *)central connectionEventDidOccur:(CBConnectionEvent)event // forPeripheral:(CBPeripheral *)peripheral //{ // if (event == CBConnectionEventPeerConnected) // { // NSLog(@"---> 系统界面,已连接设备:%@",peripheral.name); // if (peripheral.name.length > 0) { // [self connectBLE:peripheral]; // } // } // // if (event == CBConnectionEventPeerDisconnected) { // NSLog(@"---> 系统界面,断开设备:%@",peripheral.name); // } //} //-(void)connectBLE:(CBPeripheral*)peripheral //{ // self.reconnectPeripheral = peripheral; // [self.reconnectPeripheral setDelegate:self]; // // [self.cMgr connectPeripheral:self.reconnectPeripheral // options:@{CBConnectPeripheralOptionNotifyOnDisconnectionKey:@(YES), // CBConnectPeripheralOptionNotifyOnConnectionKey:@(YES) // }]; // [self.cMgr stopScan]; // // NSLog(@"BLE Connecting... Name ---> %@ UUID:%@",peripheral.name,peripheral.identifier.UUIDString); //} /** 连接设备 @param bleModel ble模型 */ - (void)connectedWithBleModel:(BLEModelFireBoltt *)bleModel { self.currenModel = bleModel; self.reconnectPeripheral = bleModel.peripheral; // 连接设备 NSLog(@"BLE Connecting... Name ---> %@", bleModel.peripheral.name); [bleModel.peripheral setDelegate:self]; //[self.cMgr connectPeripheral:bleModel.peripheral options:@{CBConnectPeripheralOptionNotifyOnDisconnectionKey:@(YES)}]; if (@available(iOS 13.0, *)) { [self.cMgr connectPeripheral:bleModel.peripheral options:@{CBConnectPeripheralOptionNotifyOnDisconnectionKey:@(YES),CBConnectPeripheralOptionEnableTransportBridgingKey:@(YES)}]; } else { [self.cMgr connectPeripheral:bleModel.peripheral options:@{CBConnectPeripheralOptionNotifyOnDisconnectionKey:@(YES)}]; } // 停止扫描 [self cancelScan]; } /// 断开当前连接的设备 /// @param isUnbind 是否解绑 - (void)disConnectedCurrenDevice:(BOOL)isUnbind { if (isUnbind) { [[NSUserDefaults standardUserDefaults] removeObjectForKey:AutomaticReconnectionDevice]; } // 调用则立刻设置为断开 self.isConnected = NO; // 存在设备则断开 if (self.reconnectPeripheral) { [self.cMgr cancelPeripheralConnection:self.reconnectPeripheral]; if (isUnbind) { self.reconnectPeripheral = nil; self.currenModel = nil; } } } /** 蓝牙设备重连 @param isStart 开启停止 */ - (void)startAndStopReconnect:(BOOL)isStart { if (!isStart || self.state != CBManagerStatePoweredOn) { // 取消重连 if (self.reconnectPeripheral) { [self.cMgr cancelPeripheralConnection:self.reconnectPeripheral]; } return; } // 获取本地设备 NSString *reconnectionUUIDSrting = [[NSUserDefaults standardUserDefaults] objectForKey:AutomaticReconnectionDevice]; if (!reconnectionUUIDSrting) { return; } // 重连系统已配对设备 NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:reconnectionUUIDSrting]; NSArray *systemPeripherals = [self.cMgr retrievePeripheralsWithIdentifiers:@[uuid]]; if (systemPeripherals.count) { CBPeripheral *peripheral = systemPeripherals.firstObject; BLEModelFireBoltt *bleModel = [[BLEModelFireBoltt alloc] initWithCentral:self.cMgr Peripheral:peripheral AdvertisementData:0 RSSI:[NSNumber numberWithInteger:0] UUIDString:peripheral.identifier.UUIDString MACString:nil]; self.currenModel = bleModel; self.reconnectPeripheral = peripheral; __weak typeof(self) weakSelf = self; [GCDTimer.ocShareInstance scheduledDispatchTimerWithTimerName:ConnectPeripheralTimerName timeInterval:self.reconnectTime queue:dispatch_get_main_queue() repeats:false immediately:false action:^{ weakSelf.reconnectPeripheral.delegate = self; [weakSelf.cMgr connectPeripheral:weakSelf.reconnectPeripheral options:@{CBConnectPeripheralOptionNotifyOnDisconnectionKey:@(YES), CBConnectPeripheralOptionNotifyOnConnectionKey:@(YES), CBConnectPeripheralOptionNotifyOnNotificationKey:@(YES)}]; weakSelf.reconnectTime = 0; [self cancelScan]; }]; } // 扫描设备 [self scanForPeripheralsWithdiscoverServices:nil IsDFU:true]; } //========== 处理蓝牙指令 ========== // /** 写入数据 @param bleItem 蓝牙命令模型 */ - (void)writeWithBleItem:(BlueToothItemFireBoltt *)bleItem { if (self.isConnected) { [self.bluetoothItems addObject:bleItem]; [self loopRequest]; return; } // 代理超时返回 if (IsDelegate(bleItem.dataSource, bluetoothManager:sequenceID:didTimeOutWithData:cmdId:)) { [bleItem.dataSource bluetoothManager:self sequenceID:bleItem.sid didTimeOutWithData:nil cmdId:bleItem.cmd]; } } /// 清空指令队列 - (void)removeCmdItem { // 当前队列若存在则清空并且停止定时器 if (self.bluetoothItems.count) { [self.bluetoothItems removeAllObjects]; [self.checkoutTimer invalidate]; self.timeNumber = 0; _executing = NO; } } - (void)firmwareCompleteResetDelegate { self.cMgr.delegate = self; } /** 循环串行 执行蓝牙请求(先进先出) */ - (void)loopRequest { if (_bluetoothItems.count > 0 && _executing == NO) { BlueToothItemFireBoltt *bleItem = _bluetoothItems.firstObject; if (!bleItem.isExecuting) { self.currenItem = bleItem; // 分包发送数据 [self handleWithByteBuffer:self.currenItem.byteBuffer]; bleItem.isExecuting = YES; _executing = YES; // 定时器开启 3秒超时 self.timeNumber = 0; CGFloat timeOut = 1.0; NSTimer *checkoutTimer = [NSTimer scheduledTimerWithTimeInterval:timeOut target:self selector:@selector(clickTimeout:) userInfo:nil repeats:YES]; self.checkoutTimer = checkoutTimer; NSLog(@"[蓝牙通讯] 发送了蓝牙指令 %@ 序号是 %ld 指令是 %ld",bleItem.byteBuffer,bleItem.sid,bleItem.cmd); } } } /** 超时处理,进入此方法则重发 */ - (void)clickTimeout:(NSTimer *)timer { self.timeNumber++; NSLog(@"[蓝牙通讯] 超时了,第 %ld 秒",self.timeNumber); // 超时五秒后重发 if (self.timeNumber > TimeOutNumber) { // 重发三次 if (self.currenItem.requestCount < 2) { self.timeNumber = 0; NSLog(@"[蓝牙通讯] 重新发送了 %ld",self.currenItem.requestCount); self.currenItem.requestCount++; // 重新发送时置空数据包 self.currenData = [NSMutableData new]; self.totalData = [NSMutableData new]; // 分包发送数据 [self handleWithByteBuffer:self.currenItem.byteBuffer]; }else { // 超时隐藏提示框 [SVProgressHUD dismiss]; // [SVProgressHUD showInfoWithStatus:NSLocalizedString(@"请求超时", nil)]; // // 超时断开设备 // [self disConnectedCurrenDevice:false]; // 代理超时返回 if (IsDelegate(self.currenItem.dataSource, bluetoothManager:sequenceID:didTimeOutWithData:cmdId:)) { [self.currenItem.dataSource bluetoothManager:self sequenceID:self.currenItem.sid didTimeOutWithData:nil cmdId:self.currenItem.cmd]; } // 超时处理 [self completeAndTimeouthandleWithItem:self.currenItem]; } } } /** 分包数据发送处理 */ - (void)handleWithByteBuffer:(NSMutableData *)byteBuffer { // 发送时默认回调数据校验成功 self.isCrc = YES; // 大于20字节则分包发送 if (byteBuffer.length > 20) { NSInteger count = byteBuffer.length / 20; for (int i = 0; i <= count; i++) { NSData *data = [[NSData alloc] init]; if (i < count) { data = [byteBuffer subdataWithRange:NSMakeRange(i * 20, 20)]; } else if (byteBuffer.length % 20) { // 最后不足20字节的数据 data = [byteBuffer subdataWithRange:NSMakeRange(i * 20, byteBuffer.length % 20)]; } if (data) { if (self.writecharacteristic) { // 写入数据 [self.reconnectPeripheral writeValue:data forCharacteristic:self.writecharacteristic type:CBCharacteristicWriteWithoutResponse]; // NSLog(@"写入数据 %@",data); } } } } else { if (self.writecharacteristic) { // 写入数据 [self.reconnectPeripheral writeValue:byteBuffer forCharacteristic:self.writecharacteristic type:CBCharacteristicWriteWithoutResponse]; //NSLog(@"写入数据 %@",byteBuffer); } } // for (int i = 0; i < byteBuffer.length; i += 20) // { // // 预加 最大包长度,如果依然小于总数据长度,可以取最大包数据大小 // if ((i + 20) < byteBuffer.length) // { // NSString *rangeStr = [NSString stringWithFormat:@"%i,%i", i, 20]; // NSData *subData = [byteBuffer subdataWithRange:NSRangeFromString(rangeStr)]; // NSLog(@"%@",subData); // if (self.writecharacteristic) // { // // 写入数据 // [self.reconnectPeripheral writeValue:subData forCharacteristic:self.writecharacteristic type:CBCharacteristicWriteWithoutResponse]; // NSLog(@"写入数据 %@",subData); // } // //根据接收模块的处理能力做相应延时 // usleep(20 * 1000); // } // else { // if (self.writecharacteristic) // { // // 写入数据 // [self.reconnectPeripheral writeValue:byteBuffer forCharacteristic:self.writecharacteristic type:CBCharacteristicWriteWithoutResponse]; // NSLog(@"写入数据 %@",byteBuffer); // } // usleep(20 * 1000); // } // } } /** 任务完成 || 超时 处理 @param item 当前蓝牙命令 */ - (void)completeAndTimeouthandleWithItem:(BlueToothItemFireBoltt *)item { [self.checkoutTimer invalidate]; _executing = NO; self.currenData = [NSMutableData new]; self.totalData = [NSMutableData new]; [self.bluetoothItems removeObject:item]; [self loopRequest]; } /** 根据序号查找当前队列是否存在 */ - (BlueToothItemFireBoltt *)requestItemFromIndex:(int)index { for (BlueToothItemFireBoltt *item in _bluetoothItems) { if (item.sid == index) { return item; } } return nil; } /** 处理收到的数据 @param data 返回的数据 */ #pragma mark ---- 处理收到的数据 - (void)handleReceiveData:(NSData *)data { NSLog(@"[蓝牙通讯] 接收到的数据------%@",data); // 如果存在队列 收到数据则重新计算超时 if (_bluetoothItems.count) { self.timeNumber = 0; } // 处理命令后的返回数据 [self.currenData appendData:data]; // 判断数据是否完整 Byte *currentDataBytes = (Byte *)[self.currenData bytes]; int contenLenght = (currentDataBytes[2] & 0xff) << 8 | (currentDataBytes[3] & 0xff); int actualLenght = (int)self.currenData.length - 8; // NSLog(@"现在的数据------ %@",self.currenData); // NSLog(@"应该有的长度------ %d 现在的长度-------- %d",contenLenght,actualLenght); //Byte *buffer = (Byte *)[self.currenData bytes]; // 接收到的数据包完整 if (contenLenght == actualLenght) { // 判断序号是否存在当前队列 int sid = (currentDataBytes[6] & 0xff) << 8 | (currentDataBytes[7] & 0xff); BlueToothItemFireBoltt *item = [self requestItemFromIndex:sid]; if (item) { // 判断err,1:成功 0:失败 BOOL err = [self checkDataWithData:self.currenData ByteIndex:1 bitIndex:2]; if (err) { // 大于200bytes字节的数据不做CRC处理 if (contenLenght <= 200) { // CRC校验(失败则返回重发) if (![BluetoothToolFireBoltt checkCRCWithData:self.currenData]) { self.isCrc = NO; } } // 判断是否有后续数据包返回 1:有 0:无 BOOL isData = [self checkDataWithData:self.currenData ByteIndex:1 bitIndex:1]; if (!isData && !self.isCrc) { // 不存在后续数据并且数据检验失败直接重发 return; } if (isData) { // 还有后续数据则将当前完整数据包以分隔符拼接 [self.totalData appendData:self.currenData]; self.currenData = [NSMutableData new]; [self.totalData appendData:[DataSeparator dataUsingEncoding:NSUTF8StringEncoding]]; return; }else{ // 拼接最后完整数据包 [self.totalData appendData:self.currenData]; // 代理返回成功数据 if (item.cmd == BleCMD_syncHealth) NSLog(@"909090"); if (IsDelegate(item.dataSource, bluetoothManager:sequenceID:didCompleteWithData:cmdId:)) { [self.currenItem.dataSource bluetoothManager:self sequenceID:item.sid didCompleteWithData:self.totalData cmdId:item.cmd]; } // 当前数据处理完成 [self completeAndTimeouthandleWithItem:item]; } } }else { // 不存在此队列(设备主动发送过来的数据) [self handleDeviceControlWithData:self.currenData]; self.currenData = [NSMutableData new]; } }else { // 数据不完整返回拼接 return; } } /** 处理设备发送过来的指令(找手机,拍照功能,实时数据) */ - (void)handleDeviceControlWithData:(NSMutableData *)data { NSLog(@"处理设备发送过的指令 ------- %@",data); // 检查是否为指令 if (((Byte*)([data bytes]))[0] == 0xCB) { // 判断err是否正确 BOOL err = [self checkDataWithData:data ByteIndex:1 bitIndex:2]; if (err) { Byte key = ((Byte*)([data bytes]))[10]; BleCMD_FireBoltt blecmd = 0; switch (key) { case 0x46: //!< 拍照开关 0X46 { blecmd = BleCMD_cameraSwitch; } break; case 0x47: //!< 拍照 0X47 { blecmd = BleCMD_cameraON; } break; case 0x48: //!< 退出拍照 0X48 { blecmd = BleCMD_cameraOFF; } break; case 0x51: //!< 查找手机 0X51 { blecmd = BleCMD_findPhone; } break; case 0xB4: //!< 实时计步,心率,血压,血氧-> 同步实时数据 case 0xB3: case 0xB6: case 0xB7: case 0xB8: { blecmd = BleCMD_realTimesync; } break; case 0x01: //!< 抬手亮屏设置 { blecmd = BleCMD_gesturesControl; } break; case 0xA5: //!< 辅助运动,的运动数据 { //blecmd = BleCMD_sportModelData; blecmd = BleCMD_syncHealth; } break; case 0x41: //!< 电量 { blecmd = BleCMD_batteryBack; } break; default: break; } // 将设备控制的指令类型通知出去 if (blecmd) { if (blecmd == BleCMD_realTimesync) [BLEBaseBlFireBoltt.shareInstance readProfileWithBleCmdTypeFB:BleCMD_readProfile]; // 处理设备端发来的实时 if (blecmd == BleCMD_realTimesync || blecmd == BleCMD_syncHealth) { [self handleDeviceDataCMD:blecmd Data:data]; return; } // 回复设备发出通知 [self checkCRCHandleWithData:data confirm:YES]; [[NSNotificationCenter defaultCenter] postNotificationName:DeviceControlNotification object:@(blecmd) userInfo:@{@"data": data}]; return; } } else { [self checkCRCHandleWithData:data confirm:NO];// 回复设备发出通知 } } else { return; // 非请求返回的数据也不是设备发送过来的数据不处理 } } /** 处理设备的运动状态 */ - (void)handleSportStateWithData:(NSMutableData *)data { // Byte *buffer = (Byte *)[data bytes]; // int sportState = buffer[13]; // // UserGlobal *userGlobal = [UserGlobal ocShareInstance]; // if (!userGlobal.locationAide) { // userGlobal.locationAide = [[LocationAide alloc]init]; // } // if (sportState == 1) {//运动结束 // [userGlobal.locationAide stopLocation]; // } else {//运动开始 // [userGlobal.locationAide stratLocation]; // userGlobal.locationAide.gpsSignalBlock = ^(NSInteger signal) { // [[[BLEBaseBl alloc] init] GPSSignalStrengthWithBleCmdType:BleCMD_GPSSignalStrength dialType:signal]; // NSLog(@"signal = %ld",(long)signal); // }; // } } /** 处理设备发送过来的数据 */ - (void)handleDeviceDataCMD:(BleCMD_FireBoltt)blecmd Data:(NSMutableData *)data { NSDictionary *dict = [L2DataParseFireBoltt L2_ParseData:data type:blecmd]; BleCMD_FireBoltt reportCMD = [dict[@"DataType"] integerValue]; [[NSNotificationCenter defaultCenter] postNotificationName:DeviceReportRealTimeHealthData object:@(reportCMD) userInfo:dict]; if (blecmd == BleCMD_syncHealth) { NSLog(@"实时运动数据:%@",dict[@"SPORT"]); if (dict[@"SPORT"]) { // if (IsDelegate(self.currenItem.dataSource, bluetoothManager:sequenceID:didCompleteWithData:cmdId:)) { // [self.currenItem.dataSource bluetoothManager:self sequenceID:self.currenItem.sid didCompleteWithData:data cmdId:BleCMD_syncHealth]; // } [BluetoothService.ocShareInstance finishedHandleWithData:dict cmd:BleCMD_syncHealth]; } } } /** 检查data中某个字节中的某位的值 1:YES 0:NO @param data 数据包 @param byteIndex 字节的下标 @param bitIndex 位的下标(从左到又) */ - (BOOL)checkDataWithData:(NSMutableData *)data ByteIndex:(NSInteger)byteIndex bitIndex:(NSInteger)bitIndex { int num = ((Byte*)([data bytes]))[byteIndex]; UInt8 confirm = (UInt8)num; confirm = confirm << bitIndex; confirm = confirm >> 7; return confirm; } /** CRC校验成功或失败后回复设备端 */ - (void)checkCRCHandleWithData:(NSMutableData *)data confirm:(BOOL)confirm { if(data.length <=12) { //l1层就有13个字节了。不够长的数据是垃圾数据 return; } Byte byte = confirm == YES ? [BluetoothToolFireBoltt stitchWithErr:1 Ack:1 Vision:0] : [BluetoothToolFireBoltt stitchWithErr:0 Ack:1 Vision:0]; // 替换L1层第二个字节 [data replaceBytesInRange:NSMakeRange(1, 1) withBytes:&byte length:1]; // 替换长度为不带参数的5 Byte buffer[2]; buffer[0] = 5 >> 8; buffer[1] = 5 & 0xff; [data replaceBytesInRange:NSMakeRange(2, 2) withBytes:buffer length:2]; Byte dataLength[2]; dataLength[0] = 0; dataLength[1] = 0; [data replaceBytesInRange:NSMakeRange(11, 2) withBytes:dataLength length:2]; // NSLog(@"发送给设备端的确认码--------%@ 是否正确:%d",[data subdataWithRange:NSMakeRange(0, 13)],confirm); // 发送L1层确认码给设备端 [self.reconnectPeripheral writeValue:[data subdataWithRange:NSMakeRange(0, 13)] forCharacteristic:self.writecharacteristic type:CBCharacteristicWriteWithoutResponse]; } /** 获取系统已配对的设备 */ - (NSMutableArray *)getPairedConnectedArray { NSMutableArray *connectedArray = [[NSMutableArray alloc] init]; NSArray *braceletDeviceArr = [self.cMgr retrieveConnectedPeripheralsWithServices:@[[CBUUID UUIDWithString:ServicesUUID]]]; for (NSInteger i = 0; i < braceletDeviceArr.count; i ++) { CBPeripheral *peripheral = braceletDeviceArr[i]; BLEModelFireBoltt *bleModel = [[BLEModelFireBoltt alloc] initWithCentral:self.cMgr Peripheral:peripheral AdvertisementData:0 RSSI:[NSNumber numberWithInteger:0] UUIDString:peripheral.identifier.UUIDString MACString:nil]; bleModel.isPaired = YES; [connectedArray addObject:bleModel]; } return connectedArray; } #pragma mark 杰里升级 /// 打开表盘文件 - (void)openDialFile { [DialManager openDialFileSystemWithCmdManager:self.mAssist.mCmdManager withResult:^(DialOperateType type, float progress) { if (type == DialOperateTypeUnnecessary) { NSLog(@"已开启!"); } if (type == DialOperateTypeFail || type == DialOperateTypeCmdFail) { NSLog(@"获取失败!"); } if (type == DialOperateTypeSuccess) { NSLog(@"获取成功!"); } }]; } -(void)getInfo { [self.mAssist.mCmdManager cmdTargetFeatureResult:^(JL_CMDStatus status, uint8_t sn, NSData * _Nullable data) { JLModel_Device *model = [self.mAssist.mCmdManager outputDeviceModel]; if (status == JL_CMDStatusSuccess) { JL_OtaStatus upSt = model.otaStatus; self.mOtaPath = [[NSUserDefaults standardUserDefaults] objectForKey:@"OTAPATH"]; if (upSt == JL_OtaStatusForce) { NSLog(@"---> 进入强制升级."); //[JL_Tools delay:5 Task:^{ [self onUpdateOTA]; //}]; return; }else{ if (model.otaHeadset == JL_OtaHeadsetYES) { NSLog(@"---> 进入强制升级: OTA另一只耳机."); // [DFUITools showText:@"需要强制升级!" onView:self.view delay:1.0]; // [JL_Tools post:@"kJL_OTA_CONNECT" Object:nil]; // [JL_Tools delay:5 Task:^{ [self onUpdateOTA]; //}]; return; } } NSLog(@"---> 设备正常使用..."); [self openDialFile]; [JL_Tools mainTask:^{ //[DFUITools showText:@"设备正常使用" onView:self.view delay:1.0]; /*--- 获取公共信息 ---*/ [self.mAssist.mCmdManager cmdGetSystemInfo:JL_FunctionCodeCOMMON Result:nil]; }]; }else{ NSLog(@"---> ERROR:设备信息获取错误!"); } }]; } #pragma mark - OTA升级监听超时定时器(也可不监听超时) static NSTimer *otaTimer = nil; static int otaTimeout= 0; static NSTimer *jlTimer = nil; - (void)otaTimeCheck { otaTimeout = 0; if (otaTimer == nil) { otaTimer = [JL_Tools timingStart:@selector(otaTimeAdd) target:self Time:1.0]; } } #pragma mark 关闭超时检测 - (void)otaTimeClose { [JL_Tools timingStop:otaTimer]; otaTimeout = 0; otaTimer = nil; } - (void)otaTimeAdd { otaTimeout++; if (otaTimeout == 10) { [self otaTimeClose]; NSLog(@"OTA ---> 超时了!!!"); [SVProgressHUD showErrorWithStatus:@"升级超时"]; } } ///////////////////////////////////////// - (void)ljTimeCheck { if (jlTimer == nil) { jlTimer = [JL_Tools timingStart:@selector(scanForPeripherals) target:self Time:1.0]; } } - (void)scanForPeripherals { [self scanForPeripheralsWithdiscoverServices:nil IsDFU:YES]; } - (void)jlTimeClose { [JL_Tools timingStop:jlTimer]; jlTimer = nil; } - (void)otaFuncWithFilePaths:(NSString *)otaFilePath { [[NSUserDefaults standardUserDefaults] setObject:otaFilePath forKey:@"OTAPATH"]; self.mOtaPath = otaFilePath; NSString *lastZip = [[self.mOtaPath lastPathComponent] stringByReplacingOccurrencesOfString:@".zip" withString:@""]; NSString *lastPath = [JL_Tools listPath:NSDocumentDirectory MiddlePath:lastZip File:@""]; [JL_Tools removePath:lastPath]; // [self.mTimer threadContinue]; NSArray *zipArr = [FatfsObject unzipFileAtPath:self.mOtaPath toDestination:lastPath]; if (zipArr.count == 0) { [SVProgressHUD showErrorWithStatus:@"文件解压出错"]; return; } if (zipArr.count > 1) { [DialManager listFile:^(DialOperateType type, NSArray * _Nullable array) { if (type == DialOperateTypeSuccess && array.count > 0) { self.mWatchList = array; [JL_Tools subTask:^{ [self onUpdateResource:^{ [self onUpdateOTA]; }]; }]; } }]; } else { /*--- 只需要【OTA升级】 ---*/ [JL_Tools mainTask:^{ [self onUpdateOTA]; }]; } } - (void)onUpdateOTA { NSData *otaData = [self outputDataOfOtaPath:self.mOtaPath]; __weak typeof(self) weakSelf = self; [self.mAssist.mCmdManager.mOTAManager cmdOTAData:otaData Result:^(JL_OTAResult result, float progress) { if (result == JL_OTAResultUpgrading || result == JL_OTAResultPreparing) { NSString *txt = [NSString stringWithFormat:@"%.1f%%",progress*100.0f]; if (result == JL_OTAResultPreparing) { NSLog(@"JL-校验文件中 %@",txt); [SVProgressHUD showWithStatus:[NSString stringWithFormat:@"%@ %@",NSLocalizedString(@"校验文件", nil),txt]]; } if (result == JL_OTAResultUpgrading) { NSLog(@"JL-正在升级 %@",txt); [SVProgressHUD showWithStatus:[NSString stringWithFormat:@"%@ %@",NSLocalizedString(@"正在升级", nil),txt]]; } [self otaTimeCheck];//增加超时检测 } else if (result == JL_OTAResultPrepared) { NSLog(@"JL----> 检验文件【完成】"); [self otaTimeCheck];//增加超时检测 } else if (result == JL_OTAResultReconnect) { NSLog(@"JL----> OTA正在回连设备... "); [self startAndStopReconnect:YES]; [self otaTimeCheck];//关闭超时检测 } else if (result == JL_OTAResultReconnectWithMacAddr) { [SVProgressHUD dismiss]; [SVProgressHUD showWithStatus:NSLocalizedString(@"正在重新连接", nil)]; JLModel_Device *model = [self.mAssist.mCmdManager outputDeviceModel]; NSLog(@"JL----> OTA正在通过Mac Addr方式回连设备... \n%@",model); //[self startAndStopReconnect:YES]; self.lastBleMacAddress = model.bleAddr; self.is_JL = YES; [self ljTimeCheck]; [self otaTimeCheck];//关闭超时检测 } else if (result == JL_OTAResultReboot) { [SVProgressHUD dismiss]; //[SVProgressHUD showWithStatus:NSLocalizedString(@"设备重启,正在回连", nil)]; NSLog(@"JL---->设备重启."); [self otaTimeClose];//关闭超时检测 } else if (result == JL_OTAResultSuccess || result == JL_OTAResultFail) { if ([weakSelf.jl_delegate respondsToSelector:@selector(otaProgressWithOtaResult:withProgress:)]) { [weakSelf.jl_delegate otaProgressWithOtaResult:result withProgress:progress]; } } else { [SVProgressHUD showErrorWithStatus:NSLocalizedString(@"发生错误,升级失败", nil)]; // 其余错误码详细 Command+点击JL_OTAResult 查看说明 NSLog(@"JL-ota update result: %d", result); } }]; } - (void)startScanBLE { NSLog(@"BLE ---> startScanBLE."); if (self.cMgr) { if (self.cMgr.state == CBManagerStatePoweredOn) { [self.cMgr scanForPeripheralsWithServices:nil options:nil]; } else { __weak typeof(self) weakSelf = self; dispatch_after(0.5, dispatch_get_main_queue(), ^{ if (weakSelf.cMgr.state == CBManagerStatePoweredOn) { [weakSelf.cMgr scanForPeripheralsWithServices:nil options:nil]; } }); } } } - (NSData*)outputDataOfOtaPath:(NSString*)path { NSString *folderName = [[path lastPathComponent] stringByReplacingOccurrencesOfString:@".zip" withString:@""]; NSString *zipPath = [JL_Tools listPath:NSDocumentDirectory MiddlePath:folderName File:@""]; [FatfsObject unzipFileAtPath:path toDestination:zipPath]; NSArray *zipArray = [JL_Tools subPaths:zipPath]; for (NSString *name in zipArray) { if ([name hasSuffix:@".ufw"]) { NSString *otaPath = [JL_Tools listPath:NSDocumentDirectory MiddlePath:folderName File:name]; NSLog(@"---->Start OTA:%@ ",otaPath); NSData *otaData = [[NSData alloc] initWithContentsOfFile:otaPath]; return otaData; } else { } } return nil; } typedef void(^OTA_VIEW_BK)(void); -(void)onUpdateResource:(OTA_VIEW_BK __nullable)result { self.isOtaUpdate = YES; JL_ManagerM *mCmdManager = self.mAssist.mCmdManager; /*--- 更新资源标志 ---*/ [mCmdManager.mFlashManager cmdWatchUpdateResource]; /*--- 展示手表更新资源UI ---*/ NSLog(@"--->Fats Update UI.(OTA)"); __block uint8_t m_flag = 0; [mCmdManager.mFlashManager cmdUpdateResourceFlashFlag:JL_FlashOperateFlagStart Result:^(uint8_t flag) { m_flag = flag; }]; if (m_flag != 0) { [JL_Tools mainTask:^{ //[DFUITools showText:@"升级请求失败!" onView:self.view delay:1.0]; [SVProgressHUD showErrorWithStatus:NSLocalizedString(@"升级请求失败!", nil)]; }]; self.isOtaUpdate = NO; return; } [DialManager updateResourcePath:self.mOtaPath List:self.mWatchList Result:^(DialUpdateResult updateResult, NSArray * _Nullable array, NSInteger index, float progress){ [JL_Tools mainTask:^{ if (updateResult == DialUpdateResultReplace) { [self otaTimeCheck];//增加超时检测 NSString *fileName = array[index]; [SVProgressHUD showWithStatus:[NSString stringWithFormat:@"正在更新表盘:%@(%d/%lu)\n%.1f%%", fileName,(int)index+1,(unsigned long)array.count,progress*100.0]]; return; } if (updateResult == DialUpdateResultAdd) { [self otaTimeCheck];//增加超时检测 NSString *fileName = array[index]; [SVProgressHUD showWithStatus:[NSString stringWithFormat:@"正在传输新表盘%@(%d/%lu)\n%.1f%%", fileName,(int)index+1,(unsigned long)array.count,progress*100.0]]; return; } if (updateResult == DialUpdateResultFinished) self.otaString = @"资源更新完成"; if (updateResult == DialUpdateResultNewest) self.otaString = @"资源已是最新"; if (updateResult == DialUpdateResultInvalid) self.otaString = @"无效资源文件"; if (updateResult == DialUpdateResultEmpty) self.otaString = @"资源文件为空"; if (updateResult == DialUpdateResultNoSpace) self.otaString = @"资源升级空间不足"; if (updateResult == DialUpdateResultZipError) self.otaString = @"ZIP资源文件错误"; [SVProgressHUD showErrorWithStatus:self.otaString]; // [JL_Tools delay:1.0 Task:^{ // [SVProgressHUD showErrorWithStatus:NSLocalizedString(self.otaString, nil)]; // if (result) result(); // }]; }]; }]; } - (void)downloadZipUrl:(NSString *)url updatePath:(NSString *)path { [[User_Http shareInstance] downloadUrl:url Path:path Result:^(float progress, JLHTTP_Result result) { [JL_Tools mainTask:^{ //self.updateTxt.text = kJL_TXT("下载固件"); if (result == JLHTTP_ResultDownload) { // self.progressTxt.text = [NSString stringWithFormat:@"%.1f%%",progress*100.0]; // self.progressView.progress = progress; //[DFUITools showTransparentHUDOnWindowWithLabel:[NSString stringWithFormat:@"%.1f%%",progress*100.0]]; [SVProgressHUD showWithStatus:[NSString stringWithFormat:@"%@ %.1f%%",NSLocalizedString(@"下载中", nil),progress*100.0]]; } if (result == JLHTTP_ResultSuccess) { /*--- 现在完直接升级 ---*/ [self otaFuncWithFilePaths:path]; } if (result == JLHTTP_ResultFail) { [SVProgressHUD showErrorWithStatus:@"下载失败"]; } }]; }]; } @end