// // PPDeviceManager.m // PaoPao // // Created by lvwang2002 on 14/12/11. // Copyright (c) 2014年 paopao. All rights reserved. // #import "ENBLEDeviceManager.h" #import "NSArray+LinqExtensions.h" @implementation ENBLEDeviceManager{ CBCentralManager *_centralManager; NSMutableArray *_supportMacs; NSArray *_searchedPeripherals; //搜索到得mac设备 NSArray *_connectedPeripherals; //链接到得设备 NSDictionary *_deviceInfo; BOOL _isScan; NSTimer *_timer; dispatch_queue_t _scanQueue; dispatch_queue_t _centerQueue; dispatch_queue_t _postQueue; NSArray *_supportDeviceServerUDID; NSArray *_supportDeviceNames; NSMutableArray *_holdDevices; NSArray *bleDevices; ENSearchedType _searchedType; NSTimer *_searchedDeviceTimer; NSTimer *_updateSearchedDeviceTimer; CBPeripheral *_peripheral; } #pragma mark #pragma mark centerBlueManagere Delegate -(instancetype)init{ self = [super init]; if (self) { _supportMacs = [[NSMutableArray alloc]initWithCapacity:20]; _searchedPeripherals = [[NSArray alloc] init]; _connectedPeripherals = [[NSArray alloc] init]; // _supportDeviceServerUDID = @[]; _supportDeviceNames = @[@"BLE-",@"iGate",@"ENUO_",@"Glucose",@"INVS300",@"RBP",@"ClinkBlood",@"O",@"TH-",@"ENUO-G"]; _holdDevices =[[NSMutableArray alloc] initWithCapacity:20]; _isScan = NO; _searchedType = ENSearchedAllType; _BTStatus = ENBTPreparedStatus; _postQueue = dispatch_queue_create("com.device.post.bleCenter", NULL); [ENDLog share].isDisplayLog = true; _searchedDeviceTimer =[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(searchedDevices) userInfo:nil repeats:YES]; _updateSearchedDeviceTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(upgradeSearchedDevices) userInfo:nil repeats:YES]; } return self; } +(instancetype)shareDeviceManager{ static ENBLEDeviceManager *deviceManager; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ deviceManager = [[ENBLEDeviceManager alloc] init]; [deviceManager run]; }); return deviceManager; } -(void)run{ _centerQueue = dispatch_queue_create("com.device.bleCenter", NULL); _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:_centerQueue]; } -(BLEDevice *)getDeviceWithUUID:(NSUUID *)uuid{ NSArray *devices = [_holdDevices linq_where:^BOOL(id item) { return [[item getUUID] isEqual:uuid]; }]; if(devices.count == 0){ return nil; } return devices[0]; } - (void)centralManagerDidUpdateState:(CBCentralManager *)central{ switch (central.state) { case CBCentralManagerStatePoweredOff:{ NSLog(@"CoreBluetooth BLE hardware is Powered off"); self.BTStatus = ENBTPowerOffStatus; [self poweroffHand]; dispatch_async(dispatch_get_main_queue(), ^{ if([self.deviceManagerDelegate respondsToSelector:@selector(didUpdateBTStatus:)]){ [self.deviceManagerDelegate didUpdateBTStatus:ENBTPowerOffStatus]; }; }); } break; case CBCentralManagerStatePoweredOn:{ NSLog(@"CoreBluetooth BLE hardware is Powered on and ready"); self.BTStatus = ENBTPowerOnStatus; dispatch_async(dispatch_get_main_queue(), ^{ if([self.deviceManagerDelegate respondsToSelector:@selector(didUpdateBTStatus:)]){ [self.deviceManagerDelegate didUpdateBTStatus:ENBTPowerOnStatus]; }; }); } break; case CBCentralManagerStateResetting: NSLog(@"CoreBluetooth BLE hardware is resetting"); break; case CBCentralManagerStateUnauthorized: NSLog(@"CoreBluetooth BLE state is unauthorized"); break; case CBCentralManagerStateUnknown: NSLog(@"CoreBluetooth BLE state is unknown"); break; case CBCentralManagerStateUnsupported: NSLog(@"CoreBluetooth BLE hardware is unsupported on this platform"); break; default: break; } } - (void)centralManager:(CBCentralManager *)central willRestoreState:(NSDictionary *)dict{ NSLog(@"willRestoreState :%@",dict); } - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{ if(!_isScan){ NSLog(@"已经停止扫描"); return; } NSString *deviceName = peripheral.name; BOOL isSupport = [_supportDeviceNames linq_any:^BOOL(id item) { return [deviceName hasPrefix:item]; }]; if(!isSupport){ // [[ENDLog share] log:@"搜索到不支持设备"]; return; } //判断是否是指定的设备 BOOL isConnectedType = [self isSearchedTypeWithDeviceName:deviceName]; if(!isConnectedType){ return; } ENLog(@"device name:"); ENLog(deviceName); NSUUID *uuid = peripheral.identifier; BLEDevice *device = [self getBleDevice:uuid]; BOOL isNewly = YES; if (device == nil) { NSString *scanContent =[NSString stringWithFormat:@"Did discover peripheral. peripheral: %@ rssi: %@, UUID: %@ advertisementData: %@ ", peripheral, RSSI, peripheral.identifier, advertisementData]; ENLog(scanContent); //如果为空,则说明还没有接受管控,直接加入到管控列表. device = [[BLEDevice alloc] initWithPeripheral:peripheral CentralManager:_centralManager DeviceManager:self]; device.advertisementData = advertisementData; peripheral.delegate = device; [_holdDevices addObject:device]; }else{ isNewly = NO; } device.searchDate = [NSDate date]; //刷新设备发现时间 dispatch_async(dispatch_get_main_queue(), ^{ if([_deviceManagerDelegate respondsToSelector:@selector(didDiscoverDevice:IsNewly:)]){ [_deviceManagerDelegate didDiscoverDevice:device IsNewly:isNewly]; } }); } - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{ //告知外部连接成功 dispatch_async(dispatch_get_main_queue(), ^{ BLEDevice *device = [self getBleDevice:peripheral.identifier]; [device setConnectStatus:DeviceConnectedStatus]; if([_deviceManagerDelegate respondsToSelector:@selector(didConnectedDevice:)]){ [_deviceManagerDelegate didConnectedDevice:device]; } [device setConnectedDevice]; }); [peripheral discoverServices:nil]; //请求一次读取信号强度 [peripheral performSelector:@selector(readRSSI) withObject:nil afterDelay:1]; } - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{ //断开连接后,在连接设备中去掉该项,可以重新开始扫描. ENLog(@"设备断开连接"); BLEDevice *device = [self getBleDevice:peripheral.identifier]; peripheral.delegate = nil; if(device == nil){ ENLog(@"断开设备已经从存储数组中删除"); return; } @try { [_holdDevices removeObject:device]; } @catch (NSException *exception) { ENLog(@"删除不存在设备,报错"); } device.connectStatus = DeviceDisconnectedStatus; dispatch_async(dispatch_get_main_queue(), ^{ if([device.deviceDelegate respondsToSelector:@selector(didDisconnectDevice:)]){ [device.deviceDelegate didDisconnectDevice:device]; } }); } - (NSString *)getHexStringWithValue:(int)values{ NSString *newHexStr = [NSString stringWithFormat:@"%x",values&0xff]; if([newHexStr length]==1) newHexStr = [NSString stringWithFormat:@"0%@",newHexStr]; else newHexStr = [NSString stringWithFormat:@"%@",newHexStr]; newHexStr = [NSString stringWithFormat:@"0x%@",newHexStr]; return newHexStr ; } /** 开始扫描 */ -(void)startScan{ //如果不为空的话,直接开始扫描就可以,为空的 if(_scanQueue){ _isScan = YES; return; } _isScan = YES; _scanQueue = dispatch_queue_create("com.device.scanqueue", NULL); dispatch_async(_scanQueue, ^{ while (1) { if(!_isScan){ [NSThread sleepForTimeInterval:0.5]; continue; } dispatch_async(dispatch_get_main_queue(), ^{ ENLog(@"enable scan"); [_centralManager scanForPeripheralsWithServices:nil options:nil]; }); [NSThread sleepForTimeInterval:2.5]; dispatch_async(dispatch_get_main_queue(), ^{ ENLog(@"disable scan"); [_centralManager stopScan]; }); [NSThread sleepForTimeInterval:0.5]; } }); } /** 停止扫描 */ -(void)stopScan{ [_centralManager stopScan]; _isScan = NO; } -(void)emptySearchedPeripherals{ _searchedPeripherals = [[NSArray alloc]init]; } //蓝牙关断处理方法. -(void)poweroffHand{ ENLog(@"设备断开连接"); _isScan = NO; for (BLEDevice *device in _holdDevices) { [device disconnect]; dispatch_async(dispatch_get_main_queue(), ^{ if([device.deviceDelegate respondsToSelector:@selector(didDisconnectDevice:)]){ [device.deviceDelegate didDisconnectDevice:device]; } }); } _holdDevices = [[NSMutableArray alloc] initWithCapacity:20]; } /** 根据指定的设备得到 */ -(BLEDevice *)getBleDevice:(NSUUID *)uuid{ NSArray *devices = [_holdDevices linq_where:^BOOL(id item) { BLEDevice *device = item; return [device.getUUID isEqual:uuid]; }]; if([devices count]<=0){ return nil; }else{ return devices[0]; } }; /** 处理错误 */ -(void)uhoh:(BLEDevice *)device{ [_holdDevices removeObject:device]; [device disconnect]; } /** 判断是否有设备连接 */ -(BOOL)hasDeviceConnectedWithType:(ENSearchedType)type{ NSArray *connectedDevices = [_holdDevices linq_where:^BOOL(id item) { BLEDevice *device = (BLEDevice *)item; if(type == ENSearchedKetoneType){ NSString *deviceName = [device getDeviceName]; return (device.connectStatus == DeviceConnectedStatus && [deviceName hasPrefix:@"BLE-ENUO"]) || (device.connectStatus == DeviceConnectedStatus && [deviceName hasPrefix:@"ENUO-G"]) || (device.connectStatus == DeviceConnectedStatus && type == ENSearchedAllType); }else{ ENSearchedType deviceType = [self getDeviceTypeWithDeviceName:[device getDeviceName]]; return ((device.connectStatus == DeviceConnectedStatus && type == deviceType) || (device.connectStatus == DeviceConnectedStatus && type == ENSearchedAllType)); } }]; return (connectedDevices.count > 0); } /** 判断是否有设备正在连接 */ -(BOOL)hasDeviceConnectingWithType:(ENSearchedType)type{ NSArray *connectingDevices = [_holdDevices linq_where:^BOOL(id item) { BLEDevice *device = (BLEDevice *)item; if(type == ENSearchedKetoneType){ NSString *deviceName = [device getDeviceName]; return (device.connectStatus == DeviceConnectingStatus &&[deviceName hasPrefix:@"BLE-ENUO"]) || (device.connectStatus == DeviceConnectingStatus &&[deviceName hasPrefix:@"ENUO-G"]) || (device.connectStatus == DeviceConnectingStatus && type == ENSearchedAllType); }else{ ENSearchedType deviceType = [self getDeviceTypeWithDeviceName:[device getDeviceName]]; return ((device.connectStatus == DeviceConnectingStatus && type == deviceType) || (device.connectStatus == DeviceConnectingStatus && type == ENSearchedAllType)); } }]; return (connectingDevices.count > 0); } /** 指定类型连接 */ -(void)setSearchedDeviceType:(ENSearchedType)searchedDeviceType{ _searchedType = searchedDeviceType; } /** 判断设备是否是指定的设备 */ -(BOOL)isSearchedTypeWithDeviceName:(NSString *)deviceName{ if(_searchedType == ENSearchedAllType){ return true; }else if(_searchedType == ENSearchedGlucoType) { if([deviceName hasPrefix:@"Glucose"] || [deviceName hasPrefix:@"BLE-ENUO"] || [deviceName hasPrefix:@"ENUO-G"]){ return true; }else{ return false; } }else if(_searchedType == ENSearchedBPType){ if([deviceName hasPrefix:@"RBP"] || [deviceName hasPrefix:@"ClinkBlood"]){ return true; }else{ return false; } }else if(_searchedType == ENSearchedCholesterolType ){ if([deviceName hasPrefix:@"iGate"]){ return true; }else{ return false; } }else if(_searchedType == ENSearchedKetoneType){ if([deviceName hasPrefix:@"BLE-ENUO"]){ return true; }else{ return false; } } return false; } -(NSArray *)getSearchedDevices{ return [_holdDevices copy]; } -(void)postUpdateDeviceList{ dispatch_async(dispatch_get_main_queue(), ^{ [self searchedDevices]; }); } /** 更新界面 */ -(void)searchedDevices{ dispatch_async(dispatch_get_main_queue(), ^{ if([self.deviceManagerDelegate respondsToSelector:@selector(didUpdateSearchedDevices:)]){ NSArray *typeDevices = [_holdDevices linq_where:^BOOL(id item) { BLEDevice *device = (BLEDevice *)item; ENSearchedType type = [self getDeviceTypeWithDeviceName:[device getDeviceName]]; return ((_searchedType == ENSearchedAllType) || (_searchedType == type)); }]; [self.deviceManagerDelegate didUpdateSearchedDevices:typeDevices]; } }); } /** 更新搜索列表的内容 */ -(void)upgradeSearchedDevices{ // ENLog(@"1S刷新扫描设备列表"); NSArray *updateDevices = [_holdDevices linq_where:^BOOL(id item) { BLEDevice *device = (BLEDevice *)item; if((fabs([device.searchDate timeIntervalSinceDate:[NSDate date]])>=10.0) && device.connectStatus == DeviceSearchedStatus){ return NO; }else{ return YES; } }]; NSString *log =[NSString stringWithFormat:@"update device count:%lu",(unsigned long)updateDevices.count]; //ENLog(log); _holdDevices = [updateDevices mutableCopy]; } /** 设置是否输出 */ -(void)setIsShowLog:(BOOL)isShow{ [ENDLog share].isDisplayLog = isShow; } /** 当前连接的设备 */ -(BLEDevice *)getCurrentConnectedDeviceWithType:(ENSearchedType)type{ NSArray *connectedDevices = [_holdDevices linq_where:^BOOL(id item) { BLEDevice *device = (BLEDevice *)item; ENSearchedType deviceType = [self getDeviceTypeWithDeviceName:[device getDeviceName]]; return ((device.connectStatus == DeviceConnectedStatus && type == deviceType) || (device.connectStatus == DeviceConnectedStatus && type == ENSearchedAllType)); }]; return connectedDevices.count>0?[connectedDevices firstObject]:nil; } /** 根据名字获取类型 ,不包括血酮 */ -(ENSearchedType)getDeviceTypeWithDeviceName:(NSString *)deviceName{ if([deviceName hasPrefix:@"Glucose"] || [deviceName hasPrefix:@"BLE-ENUO"] || [deviceName hasPrefix:@"ENUO-G"]){ return ENSearchedGlucoType; }else if([deviceName hasPrefix:@"RBP"] || [deviceName hasPrefix:@"ClinkBlood"]){ return ENSearchedBPType; }else if([deviceName hasPrefix:@"iGate"]){ return ENSearchedCholesterolType; } return ENSearchedAllType; } /** 删除设备 */ -(void)removeDevice:(BLEDevice *)device{ @try { [_holdDevices removeObject:device]; } @catch (NSException *exception) { } @finally { } } /** 断开连接 */ -(void)disconnectAllDevices{ for(BLEDevice *device in _holdDevices){ [device disconnect]; } } -(dispatch_queue_t)getPostQueue{ return _postQueue; } @end