534 lines
15 KiB
Objective-C
Executable File
534 lines
15 KiB
Objective-C
Executable File
//
|
|
// 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
|