IOS 藍芽裝置斷開時間內進行自動連結
阿新 • • 發佈:2018-11-02
一:IOS Ble藍芽裝置自動連結藍芽的功能需求
二: 主要分為以下幾個邏輯點:
1.把主藍芽列表MAC地址儲存到詳情介面
2.把連結成功的服務(peripheral)列表呼叫如:self.deviceModel.peripheral = peripheral;
3.當裝置關閉斷開的時候,進行時間的運算,判斷處理是否進行自動連結
1.裝置的藍芽列表總介面
DeviceViewController.h
#import <UIKit/UIKit.h> #import "BaseTableViewController.h" #import "DeviceCell.h" #import "DeviceView.h" #import "DeviceModel.h" #import "BlueUtil.h" #import "CommonDefaults.h" #import "BTAlertController.h" #import "BlueTempViewController.h" #import "OtaViewController.h" //#import "WJProgress.h" @interface DeviceViewController : BaseTableViewController //空白布局檔案 @property(strong,nonatomic) DeviceView *deviceView; //藍芽列表 @property (nonatomic,strong) NSMutableArray *deviceList; @property(strong,nonatomic) DeviceModel *deviceModel; // 掃描到的外圍裝置 //@property (nonatomic,strong ) NSMutableArray <CBPeripheral*>*peripheralList; @property (nonatomic,strong ) NSMutableArray *peripheralList; //獲取裝置定時器 @property(strong,nonatomic) NSTimer *deviceTimer; @property(strong,nonatomic) BlueUtil *bleUtil; @property(strong,nonatomic) CommonDefaults *cmDefaults; @end
二:藍芽列表總介面
DeviceViewController.m
// // DeviceViewController.m // BWProject // // Created by rnd on 2018/6/28. // Copyright © 2018年 Radiance Instruments Ltd. All rights reserved. // #import "DeviceViewController.h" //藍芽的的兩個代理 @interface DeviceViewController ()<UITableViewDelegate,UITableViewDataSource> @end @implementation DeviceViewController - (void)viewDidLoad { [super viewDidLoad]; //定義函式initData [self initData]; } //導航欄中間對齊 - (void)customContentView{ UIColor *commonBlue = [self.commonUtil stringToColor:@"#333333"]; [self.navigationController.navigationBar setBarTintColor:commonBlue]; self.navigationController.navigationBar.tintColor = [UIColor whiteColor]; self.navigationItem.title = @"BLE"; //建立下啦重新整理 NSString *dropscan = NSLocalizedString(@"dropscan", nil); UIRefreshControl *rc = [[UIRefreshControl alloc] init]; rc.attributedTitle = [[NSAttributedString alloc] initWithString:dropscan]; [rc addTarget:self action:@selector(redreshTableView) forControlEvents:UIControlEventValueChanged]; self.refreshControl = rc; } -(void)initData{ //藍芽裝置類 self.bleUtil = [BlueUtil sharedManager]; [self getDeviceModel]; [self getDeviceList]; [self getPeripheralList]; self.tableView.delegate = self; self.tableView.dataSource = self; //小技巧,用了之後不會出現多餘的Cell UIView *view = [[UIView alloc] init]; self.tableView.tableFooterView = view; //裝置定時器時間,如果等於null就每隔2秒鐘掃描一次 if(_deviceTimer==nil){ _deviceTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(deviceTime) userInfo:nil repeats:YES]; } } /* 程式載入的時候呼叫 */ - (void)viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated]; if(_deviceList.count>0&&_peripheralList.count>0){ //可變陣列物件 [_deviceList removeAllObjects]; [_peripheralList removeAllObjects]; //重新載入資料 [self.tableView reloadData]; } if (self.refreshControl.refreshing) { //TODO: 已經在重新整理資料了 //NSLog(@"12233"); } else { NSLog(@"y is %f",self.tableView.contentOffset.y); if (self.tableView.contentOffset.y == -64.0) { [UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^(void){ self.tableView.contentOffset = CGPointMake(0, -self.refreshControl.frame.size.height); } completion:^(BOOL finished){ [self.refreshControl beginRefreshing]; [self.refreshControl sendActionsForControlEvents:UIControlEventValueChanged]; }]; } } } //裝置佈局檔案 -(DeviceView *)getDeviceView{ if(self.deviceView==nil){ self.deviceView = [[DeviceView alloc] init]; } return self.deviceView; } //裝置藍芽列表初始化 -(NSMutableArray*)getDeviceList{ if(self.deviceList==nil){ self.deviceList=[NSMutableArray array]; } return self.deviceList; } //外圍藍芽裝置初始化 -(NSMutableArray*)getPeripheralList{ if(self.peripheralList==nil){ self.peripheralList = [NSMutableArray array]; } return self.peripheralList; } -(DeviceModel*)getDeviceModel{ if(self.deviceModel==nil){ self.deviceModel = [[DeviceModel alloc] init]; } return self.deviceModel; } //獲取裝置連線的資料 -(void)deviceTime{ self.deviceList = [self.bleUtil getDeviceLists]; self.peripheralList = [self.bleUtil getPeriperalLists]; if(self.deviceList.count>0){ [self.tableView reloadData]; } } //tableview的行數 #pragma mark tableView -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return self.deviceList.count; } -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *cellIdentifiter = @"DeviceCellIdentifiter"; DeviceCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifiter]; if (cell == nil) { cell = [[DeviceCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifiter]; } //藍芽列表行數是否大於0 if([self.deviceList count]>0){ NSUInteger row = [indexPath row]; if(row<self.deviceList.count){ _deviceModel = [_deviceList objectAtIndex:indexPath.row]; cell.mDeviceNameLb.text = self.deviceModel.deviceName; cell.mDeviceAddreLb.text = self.deviceModel.deviceAddre; } } return cell; } #pragma tableView的點選事件 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *cellIdentifiter = @"DeviceCellIdentifiter"; DeviceCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifiter]; if (cell == nil) { cell = [[DeviceCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifiter]; } if(self.deviceList.count>0){ NSString *contentTips = @"Connect Tips"; NSString *multiple = @"Cancel"; NSString *single = @"Connect"; //該方法響應列表中行的點選事件 NSString *
[email protected]""; //indexPath.row得到選中的行號,提取出在陣列中的內容。 BTAlertController *alertController = [BTAlertController alertControllerWithTitle:contentTips message:bleSelected preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *noAction = [UIAlertAction actionWithTitle:multiple style:UIAlertActionStyleCancel handler:^(UIAlertAction *action){ }]; UIAlertAction *yesAction = [UIAlertAction actionWithTitle:single style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){ //連線第一個掃描到的外設 NSUInteger row = [indexPath row]; int rows =(int)row; self.deviceModel = [self.deviceList objectAtIndex:indexPath.row]; //[self.cmDefaults saveMacAdder:self.deviceModel.deviceAddre]; //儲存地址 [[CommonDefaults shared] saveMacAdder:self.deviceModel.deviceAddre]; //如果是為OTA的話 if([self.deviceModel.deviceName containsString:@"update"]){ [[BlueUtil sharedManager] contentBlue:rows]; OtaViewController *otaView = [[OtaViewController alloc] init]; otaView.title = @"OTA UpGrade"; [self.navigationController pushViewController:otaView animated:YES]; }else{ //連線藍芽 [[BlueUtil sharedManager] contentBlue:rows]; BlueTempViewController *bluetempView = [[BlueTempViewController alloc] init]; bluetempView.title = @"Temperature"; [self.navigationController pushViewController:bluetempView animated:YES]; } }]; [alertController addAction:noAction]; [alertController addAction:yesAction]; [self presentViewController:alertController animated:true completion:nil]; } } //定義列的高度 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return 90; } //讀取重新整理TableView -(void)redreshTableView{ if(self.refreshControl.refreshing){ self.refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:@"Refresh"]; if(_deviceList!=nil&&_deviceList.count>0){ [_deviceList removeAllObjects]; } if(_peripheralList.count>0&&_peripheralList!=nil){ [_peripheralList removeAllObjects]; } //掃描藍芽 [self.bleUtil startScan]; [self.refreshControl endRefreshing]; self.refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:@"Down Refresh"]; //掃描 [self.tableView reloadData]; } } //用完之後需要關閉掉 -(void)viewDidDisappear:(BOOL)animated{ [super viewDidDisappear:animated]; [[BlueUtil sharedManager] stopScan]; } @end
三:藍芽服務介面:
#import <Foundation/Foundation.h>
#import <CoreBluetooth/CoreBluetooth.h>
#import "DeviceModel.h"
#import "Constants.h"
#import "BlueTempModel.h"
#import "BWTmpDB.h"
#import "TmpModel.h"
#import "MBProgressHUD.h"
#import "CommonUtil.h"
@interface BlueUtil : NSObject
+ (id)sharedManager;
//顏色轉換
@property(nonatomic,strong) CommonUtil *comUtil;
//藍芽的裝置搜尋顯示在列表中
@property (nonatomic, strong) NSMutableArray <CBPeripheral*>*periperals;// 掃描到的外圍裝置
//連線peripheral
@property(nonatomic,strong) CBPeripheral *peripheral;
//中心管理者
@property (nonatomic, strong) CBCentralManager *centerManager;
//裝置列表
@property(nonatomic,strong) NSMutableArray *deviceList;
@property(nonatomic,strong) BlueTempModel *blueTempModel;
@property(strong,nonatomic) NSMutableArray *tempList;
//所有的charater
@property(nonatomic,strong)CBCharacteristic *readtempcharaterone;
//讀取高低溫報警值
@property(nonatomic,strong)CBCharacteristic *readalarmcharaterone;
@property(nonatomic,strong)CBCharacteristic *readalarmcharatertwo;
@property(nonatomic,strong)CBCharacteristic *readalarmcharaterthree;
@property(nonatomic,strong)CBCharacteristic *readalarmcharaterfour;
//OTA
@property(nonatomic,strong)CBCharacteristic *sendotacharateristic;
//傳送資料進行OTA升級
@property(nonatomic,strong) CBCharacteristic *sendupcharateristic;
//讀取單位
@property(nonatomic,strong)CBCharacteristic *readtempunit;
//報警靜音
@property(nonatomic,strong) CBCharacteristic *sendmuteswitch;
//自動連結
@property(nonatomic,strong) CBCharacteristic *sendzidswitch;
//裝置資訊
@property(nonatomic,strong)CBCharacteristic *readdeviceinfo;
//設定路由器賬號密碼
@property(nonatomic,strong)CBCharacteristic *sendsetarouter;
//傳輸時間間隔
@property(nonatomic,strong) CBCharacteristic *sendupdatetime;
//裝置名字
@property(nonatomic,strong) CBCharacteristic *senddevicename;
//設定伺服器地址埠
@property(nonatomic,strong) CBCharacteristic *sendsevername;
//裝置
@property (nonatomic,strong) DeviceModel *deviceModel;
//dalao
@property(strong,nonatomic) MBProgressHUD *hud;
-(NSMutableArray *)getDeviceLists;
-(NSMutableArray *)getPeriperalLists;
-(void)contentBlue:(int) row;
-(void)startScan;
-(void)stopScan;
//斷開藍芽
-(void)disContentBle;
-(void)writeUpdateOTA:(NSString*)value;
-(void)writeBlueOTA:(NSString *)value;
-(void)wirteBlueOTAData:(NSData *)value;
//寫入溫度單位資料
-(void)writeUnitData:(NSString *)value;
//寫入靜音開關資料
-(void)writeMuteData:(NSString*)value;
//寫入自動連結列表
-(void)contentAutoBlue:(CBPeripheral*)peripheral;
-(void)writeAlarmData:(NSString *)value codes:(NSString *)code;
//寫入arouter值
-(void)sendARouterData:(NSString*)value;
//寫入更新時間值
-(void)sendUpdateData:(NSString*)value;
//寫入裝置名字
-(void)sendNameData:(NSString*)value;
//寫入伺服器地址埠值
-(void)sendIPPortData:(NSString*)value;
@end
BlueUtil.m
#import "BlueUtil.h"
@interface BlueUtil()<CBCentralManagerDelegate,CBPeripheralDelegate>
@end
@implementation BlueUtil
+ (id)sharedManager {
static BlueUtil *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
-(id)init{
self = [super init];
if(self){
[self getCBCentralManager];//中心管理者
self.centerManager.delegate = self;
[self getPeriperals];//連結
[self getDeviceList];
[self getDeviceModel];
//[self getBlueTempModel];
[self gettempList];
[self getComUtil];
}
return self;
}
-(CommonUtil *)getComUtil{
if(self.comUtil==nil){
self.comUtil = [[CommonUtil alloc] init];
}
return self.comUtil;
}
//管理中心者
-(CBCentralManager*)getCBCentralManager{
if(self.centerManager==nil){
self.centerManager = [[CBCentralManager alloc] init];
}
return self.centerManager;
}
//連結的藍芽
-(NSMutableArray *)getPeriperals{
if(self.periperals==nil){
self.periperals = [NSMutableArray array];
}
return self.periperals;
}
//獲取裝置列表
-(NSMutableArray *)getDeviceList{
if(self.deviceList==nil){
self.deviceList = [NSMutableArray array];
}
return self.deviceList;
}
//獲取裝置名稱,地址樣式
-(DeviceModel*)getDeviceModel{
if(self.deviceModel==nil){
self.deviceModel = [[DeviceModel alloc] init];
}
return self.deviceModel;
}
//獲取最大,最小溫度狀態,報警狀態
-(BlueTempModel *)getBlueTempModel{
if(self.blueTempModel==nil){
self.blueTempModel = [[BlueTempModel alloc] init];
}
return self.blueTempModel;
}
//獲取實時溫度的列表資料
-(NSMutableArray *)gettempList{
if(self.tempList==nil){
self.tempList = [NSMutableArray array];
}
return self.tempList;
}
/*
* 獲取裝置的list
*/
-(NSMutableArray *)getDeviceLists{
return self.deviceList;
}
/*
* 獲取裝置的periperals
*/
-(NSMutableArray *)getPeriperalLists{
return self.periperals;
}
#pragma 藍芽代理 ---
//程式執行後,會自動呼叫的檢查藍芽的方法 並掃描藍芽的方法
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
if (@available(iOS 10.0, *)) {
if ([central state] == CBManagerStatePoweredOff) {
NSLog(@"CoreBluetooth BLE hardware is powered off");
}
else if ([central state] == CBManagerStatePoweredOn) {
NSLog(@"CoreBluetooth BLE hardware is powered on and ready");
[self startScan];
}
else if ([central state] == CBManagerStateUnauthorized) {
NSLog(@"CoreBluetooth BLE state is unauthorized");
}
else if ([central state] == CBManagerStateUnknown) {
NSLog(@"CoreBluetooth BLE state is unknown");
}
else if ([central state] == CBManagerStateUnsupported) {
NSLog(@"CoreBluetooth BLE hardware is unsupported on this platform");
}
} else {
// Fallback on earlier versions
}
}
/*
* 程式執行的時候開始掃描
*/
-(void)startScan{
if(self.periperals.count>0){
[self.periperals removeAllObjects];
}
if(self.deviceList.count>0){
[self.deviceList removeAllObjects];
}
//利用中心裝置掃描外部裝置
[self.centerManager scanForPeripheralsWithServices:nil options:nil];
}
/*
* 停止掃描
*/
-(void)stopScan{
[self.centerManager stopScan];
}
/*
* 連線藍芽裝置給外部呼叫的方法
* 傳入的是相對應的行數
*/
-(void)contentBlue:(int) row{
[self.centerManager connectPeripheral:self.periperals[row] options:nil];
}
//斷開藍芽
-(void)disContentBle{
//關鍵的斷開藍芽 通知也要停止掉
if(self.peripheral!=nil){
if(self.readtempcharaterone!=nil){
[self.peripheral setNotifyValue:NO forCharacteristic:self.readtempcharaterone];
}
[self disconnectPeripheral:self.peripheral];
}
}
//連結外設的列表
- (void) disconnectPeripheral:(CBPeripheral*)peripheral
{
[self.centerManager cancelPeripheralConnection:peripheral];
}
//中心裝置獲取外圍裝置的列表
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSS{
//NSString *deviceName;
if (![self.periperals containsObject:peripheral]){
NSArray *keys = [advertisementData allKeys];
for(int i=0;i<[keys count];i++){
id key = [keys objectAtIndex:i];
NSString *keyName = (NSString *) key;
NSData *value = [advertisementData objectForKey: key];
if([keyName isEqualToString:@"kCBAdvDataLocalName"]){
NSString *aStr= (NSString*)value;
NSLog(@"astr is %@",aStr);
self.deviceModel = [[DeviceModel alloc] init];
self.deviceModel.deviceName = aStr;
self.deviceModel.peripheral = peripheral;
[self.periperals addObject:peripheral];
[self.deviceList addObject:self.deviceModel];
}
if([keyName isEqualToString:@"kCBAdvDataManufacturerData"]){
NSLog(@"value is %@",value);
NSString *result = [self convertDataToHexStr:value];
NSLog(@"reslut is %@",result);
if(result!=nil&&result.length>4){
NSString *d = [result substringFromIndex:4];
NSLog(@"D IS %@",d);
NSString *upper = [result uppercaseString];
self.deviceModel.deviceAddre = [NSString stringWithFormat:@"S/N:%@",upper];
}
}
}
}
}
//連線成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
if(peripheral!=nil){
//停止掃描 這個用於自動連線的時候
[self.centerManager stopScan];
peripheral.delegate = self;
//再去掃描服務
[peripheral discoverServices:nil];
}
}
//連線失敗
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error{
NSLog(@"連線失敗,失敗原因:%@",error);
NSString *disContentBlue = @"discontentblue";
NSDictionary *blueDiscontent = [NSDictionary dictionaryWithObject:disContentBlue forKey:@"disconnect"];
//傳送廣播 連線失敗
[[NSNotificationCenter defaultCenter] postNotificationName:@"disNofiction" object:nil userInfo:blueDiscontent];
}
//斷開連線
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
NSLog(@"斷開連線22");
NSString *disContentBlue = @"discontentblue";
NSDictionary *blueDiscontent = [NSDictionary dictionaryWithObject:disContentBlue forKey:@"disconnect"];
//傳送廣播 連線失敗
[self.hud hideAnimated:YES];
[[NSNotificationCenter defaultCenter] postNotificationName:@"disNofiction" object:nil userInfo:blueDiscontent];
}
#pragma mark - CBPeripheralDelegate
//只要掃描到服務就會呼叫,其中的外設就是服務所在的外設
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
if (error){
NSLog(@"掃描服務出現錯誤,錯誤原因:%@",error);
}else{
//獲取外設中所掃描到的服務
for (CBService *service in peripheral.services){
//把所有的service打印出來
//從需要的服務中查詢需要的特徵
//從peripheral的services中掃描特徵
[peripheral discoverCharacteristics:nil forService:service];
}
}
}
//只要掃描到特徵就會呼叫,其中的外設和服務就是特徵所在的外設和服務
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(nonnull CBService *)service error:(nullable NSError *)error{
if (error){
NSLog(@"掃描特徵出現錯誤,錯誤原因:%@",error);
}else{
for (CBCharacteristic *characteristic in service.characteristics){
NSLog(@"characteristic is %@",characteristic.UUID);
//傳送資料到OTA
if([characteristic.UUID isEqual:BW_PROJECT_UPDATE_OTA]){
self.peripheral = peripheral;
self.sendupcharateristic = characteristic;
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
//OTA升級
else if([characteristic.UUID isEqual:BW_PROJECT_OTA_DATA]){
self.peripheral = peripheral;
self.sendotacharateristic = characteristic;
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
//所有探頭的溫度資料
else if([characteristic.UUID isEqual:BW_PROJECT_TEMP_ONE]){
self.readtempcharaterone = characteristic;
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
//第一個報警值
else if([characteristic.UUID isEqual:BW_PROJECT_ALARM_ONE]){
self.readalarmcharaterone = characteristic;
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
//第二個報警值
else if([characteristic.UUID isEqual:BW_PROJECT_ALARM_TWO]){
self.readalarmcharatertwo = characteristic;
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
//第三個報警值
else if([characteristic.UUID isEqual:BW_PROJECT_ALARM_THREE]){
self.readalarmcharaterthree = characteristic;
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
//第四個報警值
else if([characteristic.UUID isEqual:BW_PROJECT_ALARM_FOUR]){
self.readalarmcharaterfour = characteristic;
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
//溫度單位
else if([characteristic.UUID isEqual:BW_PROJECT_TEMP_UNIT]){
self.readtempunit = characteristic;
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
//報警靜音 此過程只能傳送資料 並無讀取資料的功能
else if([characteristic.UUID isEqual:BW_PROJECT_MUTE_SWITCH]){
self.sendmuteswitch = characteristic;
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
//裝置資訊
else if([characteristic.UUID isEqual:BW_PROJECT_DEVICE_INFO])
{
self.readdeviceinfo = characteristic;
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
//設定路由器
else if([characteristic.UUID isEqual:BW_PROJECT_AROUTER_DATA]){
self.sendsetarouter = characteristic;
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
//傳送時間間隔
else if([characteristic.UUID isEqual:BW_PROJECT_UPDATE_TIME]){
self.sendupdatetime = characteristic;
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
//修改裝置名字
else if([characteristic.UUID isEqual:BW_PROJECT_DEVICE_NAME]){
self.senddevicename = characteristic;
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
//修改裝置IP和埠號
else if([characteristic.UUID isEqual:BW_PROJECT_ADDERPORT_DATA]){
self.sendsevername = characteristic;
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
}
}
}
//設定通知
-(void)notifyCharacteristic:(CBPeripheral *)peripheral
characteristic:(CBCharacteristic *)characteristic{
//設定通知,資料通知會進入:didUpdateValueForCharacteristic方法
NSLog(@"發現通知!");
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
[self.centerManager stopScan];
}
//取消通知
-(void)cancelNotifyCharacteristic:(CBPeripheral *)peripheral
characteristic:(CBCharacteristic *)characteristic{
[peripheral setNotifyValue:NO forCharacteristic:characteristic];
}
//接受解析資料
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{ //第一個探頭
if(characteristic==self.readtempcharaterone){
NSString *tempdata = [self getTempTMWData:characteristic];
NSArray *data = [tempdata componentsSeparatedByString:@","];
NSDictionary *tempDict = [NSDictionary dictionaryWithObject:data forKey:@"tempData"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"tempNofiction" object:nil userInfo:tempDict];
}
else if(characteristic==self.readalarmcharaterone){
NSString *alarmdata = [self getTempTMWData:characteristic];
if(alarmdata!=nil){
NSArray *data = [alarmdata componentsSeparatedByString:@","];
NSDictionary *alarmDict = [NSDictionary dictionaryWithObject:data forKey:@"alarmDataOne"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"alarmNofictionOne" object:nil userInfo:alarmDict];
}
}
else if(characteristic==self.readalarmcharatertwo){
NSString *alarmdata = [self getTempTMWData:characteristic];
if(alarmdata!=nil){
NSArray *data = [alarmdata componentsSeparatedByString:@","];
NSDictionary *alarmDict = [NSDictionary dictionaryWithObject:data forKey:@"alarmDataTwo"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"alarmNofictionTwo" object:nil userInfo:alarmDict];
}
}
else if(characteristic==self.readalarmcharaterthree){
NSString *alarmdata = [self getTempTMWData:characteristic];
if(alarmdata!=nil){
NSArray *data = [alarmdata componentsSeparatedByString:@","];
NSDictionary *alarmDict = [NSDictionary dictionaryWithObject:data forKey:@"alarmDataThree"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"alarmNofictionThree" object:nil userInfo:alarmDict];
}
}
else if(characteristic==self.readalarmcharaterfour){
NSString *alarmdata = [self getTempTMWData:characteristic];
if(alarmdata!=nil){
NSArray *data = [alarmdata componentsSeparatedByString:@","];
NSDictionary *alarmDict = [NSDictionary dictionaryWithObject:data forKey:@"alarmDataFour"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"alarmNofictionFour" object:nil userInfo:alarmDict];
}
}
//如果讀取到溫度的單位
else if(characteristic==self.readtempunit){
NSString *tempunit = [self getTempTMWData:characteristic];//1
NSDictionary *tempDict = [NSDictionary dictionaryWithObject:tempunit forKey:@"tempUnit"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"tempUnitNofiction" object:nil userInfo:tempDict];
}
//讀取裝置資訊
else if(characteristic==self.readdeviceinfo){
NSString *deviceinfo = [self getTempTMWData:characteristic];
if(deviceinfo!=nil){
NSArray *data = [deviceinfo componentsSeparatedByString:@","];
if([data count]>0){
if([data count]>4){
NSLog(@"astr is %@",data[4]);
}
}
NSDictionary *deviceinfoDict = [NSDictionary dictionaryWithObject:data forKey:@"deviceInfo"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"deviceInfoNofiction" object:nil userInfo:deviceinfoDict];
}
}
//OTA升級的時候
else if(characteristic==self.sendotacharateristic){
//接受資料處理
NSString *data = [self getOTAData:characteristic];
if(data!=nil){
//傳送所有資料 要在清單中註冊該廣播
NSDictionary *otaDict = [NSDictionary dictionaryWithObject:data forKey:@"otaData"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"otaNofiction" object:nil userInfo:otaDict];
}
}
}
-(NSString *)getOTAData:(CBCharacteristic *)characteristic{
NSData *data = characteristic.value;
return [self convertDataToHexStr:data];
}
-(NSString *)convertDataToHexStr:(NSData *)data
{
if (!data || [data length] == 0) {
return @"";
}
NSMutableString *string = [[NSMutableString alloc] initWithCapacity:[data length]];
[data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) {
unsigned char *dataBytes = (unsigned char*)bytes;
for (NSInteger i = 0; i < byteRange.length; i++) {
NSString *hexStr = [NSString stringWithFormat:@"%x", (dataBytes[i]) & 0xff];
if ([hexStr length] == 2) {
[string appendString:hexStr];
} else {
[string appendFormat:@"0%@", hexStr];
}
}
}];
return string;
}
//解析溫度資料
-(NSString *)getTempTMWData:(CBCharacteristic *)characteristic{
NSData *data = characteristic.value;
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
/*
寫入資料區塊
*/
-(void)writeUpdateOTA:(NSString*)value{
if(self.sendupcharateristic!=nil){
NSData *data = [value dataUsingEncoding:NSUTF8StringEncoding];
NSLog(@"data is:%@",data);
[self writeOTA:data forCharacteristic:self.sendupcharateristic];
}
}
-(void)writeBlueOTA:(NSString *)value{
NSMutableData *data = [self.comUtil dataFromHexString:[value stringByReplacingOccurrencesOfString:@"0x" withString:@""]];
NSLog(@"data is:%@",data);
[self writeOTA:data forCharacteristic:self.sendotacharateristic];
}
-(void)wirteBlueOTAData:(NSData *)value{
[self writeOTA:value forCharacteristic:self.sendotacharateristic];
}
//寫入報警值
-(void)writeAlarmData:(NSString *)value codes:(NSString *)code{
if([code isEqual:@"one"]){
if(self.readalarmcharaterone!=nil){
[self writeTempData:value forCharacteristic:self.readalarmcharaterone];
}
}else if([code isEqual:@"two"]){
if(self.readalarmcharatertwo!=nil){
[self writeTempData:value forCharacteristic:self.readalarmcharatertwo];
}
}else if([code isEqual:@"three"]){
if(self.readalarmcharaterthree!=nil){
[self writeTempData:value forCharacteristic:self.readalarmcharaterthree];
}
}else if([code isEqual:@"four"]){
if(self.readalarmcharaterfour!=nil){
[self writeTempData:value forCharacteristic:self.readalarmcharaterfour];
}
}
}
//寫入溫度單位資料
-(void)writeUnitData:(NSString *)value{
if(self.readtempunit!=nil){
[self writeTempData:value forCharacteristic:self.readtempunit];
}
}
//寫入靜音開關資料
-(void)writeMuteData:(NSString*)value{
if(self.sendmuteswitch!=nil){
[self writeTempData:value forCharacteristic:self.sendmuteswitch];
}
}
//寫入Arouter值
-(void)sendARouterData:(NSString*)value{
if(self.sendsetarouter!=nil){
[self writeTempData:value forCharacteristic:self.sendsetarouter];
}
}
//寫入更新時間值
-(void)sendUpdateData:(NSString*)value{
if(self.sendupdatetime!=nil){
[self writeTempData:value forCharacteristic:self.sendupdatetime];
}
}
//寫入DeviceName值
-(void)sendNameData:(NSString*)value{
if(self.senddevicename!=nil){
[self writeTempData:value forCharacteristic:self.senddevicename];
}
}
//
//寫入IP/PORT值
-(void)sendIPPortData:(NSString*)value{
if(self.sendsevername!=nil){
[self writeTempData:value forCharacteristic:self.sendsevername];
}
}
//寫入自動連結列表資料
-(void)contentAutoBlue:(CBPeripheral*)peripheral{
[self.centerManager connectPeripheral:peripheral options:nil];
}
//寫入資料
-(void)writeTempData:(NSString *)value forCharacteristic:(CBCharacteristic *)characteristic
{
NSData *data = [value dataUsingEncoding:NSUTF8StringEncoding];
if(characteristic.properties & CBCharacteristicPropertyWriteWithoutResponse)
{
[self.peripheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse];
}else
{
[self.peripheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];
}
}
//寫入OTA的區塊
-(void)writeOTA:(NSData *)value forCharacteristic:(CBCharacteristic *)characteristic
{
//is no write bluetooth data
if(self.sendotacharateristic.properties & CBCharacteristicPropertyWriteWithoutResponse)
{
//send phone on bluetooth data
[self.peripheral writeValue:value forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse];
}else
{
[self.peripheral writeValue:value forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];
}
NSLog(@"已經向外設%@的特徵值%@寫入資料",_peripheral.name,characteristic.description);
}
@end
四:藍芽詳情介面:
BlueTempViewController.h
#import <UIKit/UIKit.h>
#import "BaseViewController.h"
#import "DeviceViewController.h"
#import <CoreBluetooth/CoreBluetooth.h>
#import "BlueTempCell.h"
#import "BlueTempView.h"
#import "BlueTempModel.h"
#import "BlueUtil.h"
#import "BleChartController.h"
#import "MBProgressHUD.h"
#import "SettingController.h"
#import "CommonDefaults.h"
#import "AFNetReqest.h"
#import "Download.h"
#import <AudioToolbox/AudioToolbox.h>
@protocol DownloadModelDelegate <NSObject>
@end
@interface BlueTempViewController : BaseViewController
//@property (nonatomic, strong) NSMutableArray <CBPeripheral*>*periperals;// 掃描到的外圍裝置
@property(strong,nonatomic) CommonDefaults *cmDefaults;
@property(strong,nonatomic) BlueTempView *btView;
@property(strong,nonatomic) BlueTempModel *blueTempModel;
@property(strong,nonatomic) NSMutableArray *tempList;
@property(nonatomic,strong) NSMutableArray *deviceList;//定義列表
@property(nonatomic,strong) NSMutableArray <CBPeripheral*>*peripheralList;//連結的列表
//-(NSMutableArray *)getDeviceLists;
//
//-(NSMutableArray *)getPeriperalLists;
//連線peripheral
@property(nonatomic,strong) CBPeripheral *peripheral;
@property(nonatomic,assign) int cdata;
@property(nonatomic,strong) NSString *oneHigh;
@property(nonatomic,strong) NSString *oneLow;
@property(nonatomic,strong) NSString *twoHigh;
@property(nonatomic,strong) NSString *twoLow;
@property(nonatomic,strong) NSString *threeHigh;
@property(nonatomic,strong) NSString *threeLow;
@property(nonatomic,strong) NSString *fourHigh;
@property(nonatomic,strong) NSString *fourLow;
@property (nonatomic,assign) BOOL isAutoCon;
@property(assign,nonatomic) BOOL isSaveOnce;
@property (nonatomic,strong) NSTimer * deviceTimer;
@property (nonatomic,assign) int times;
//溫度單位
@property(nonatomic,strong) NSString *tmpUnit;
//報警狀態1
@property(nonatomic,strong) NSString *alamOneText;
//報警狀態2
@property(nonatomic,strong) NSString *alamTwoText;
//報警狀態3
@property(nonatomic,strong) NSString *alamThreeText;
//報警狀態4
@property(nonatomic,strong) NSString *alamFourText;
//溫度狀態1
@property(nonatomic,strong) NSString *tempOne;
//溫度狀態2
@property(nonatomic,strong) NSString *tempTwo;
//溫度狀態3
@property(nonatomic,strong) NSString *tempThree;
//溫度狀態4
@property(nonatomic,strong) NSString *tempFour;
//裝置探頭名稱1
@property(nonatomic,strong) NSString *probeOneName;
//裝置探頭名稱2
@property(nonatomic,strong) NSString *probeTwoName;
//裝置探頭名稱3
@property(nonatomic,strong) NSString *probeThreeName;
//裝置探頭名稱4
@property(nonatomic,strong) NSString *probeFourName;
//最大溫度1
@property(nonatomic,strong) NSString *maxOne;
//最小溫度1
@property(nonatomic,strong) NSString *minOne;
//最大溫度2
@property(nonatomic,strong) NSString *maxTwo;
//最小溫度2
@property(nonatomic,strong) NSString *minTwo;
//最大溫度3
@property(nonatomic,strong) NSString *maxThree;
//最小溫度3
@property(nonatomic,strong) NSString *minThree;
//最大溫度4
@property(nonatomic,strong) NSString *maxFour;
//最小溫度4
@property(nonatomic,strong) NSString *minFour;
//裝置序列號
@property(nonatomic,strong) NSString *deviceNo;
//韌體升級判斷邏輯
@property(nonatomic,strong) NSString *deviceInfo;
@property(strong,nonatomic) NSTimer *highTimer;
@property(strong,nonatomic) NSString *highTimerdata;
//獲取當前的時間
@property (strong,nonatomic) NSDate *currentDate;
//時間格式化
@property(strong,nonatomic) NSDateFormatter *dateformatter;
@property(nonatomic) long ctime;
@property(strong,nonatomic) MBProgressHUD *hud;
@property(strong,nonatomic) NSString *salNumber;
@property(strong,nonatomic) NSString *arr;
@property(nonatomic,assign) id<DownloadModelDelegate> delegate;
@property(nonatomic,strong) Download *download;
//新增Model
@property(strong,nonatomic) BlueTempModel *bleModel;
@property(strong,nonatomic) NSString *stringdate;
//中心管理者
@property (nonatomic, strong) CBCentralManager *centerManager;
@end
BlueTempViewController.m
//重寫返回
- (void)onBackClick{
self.isAutoCon = FALSE;
NSString *tips = @"DisConnect Tips";
NSString *cancel = @"Cancel";
NSString *ok = @"OK";
BTAlertController *alertController = [BTAlertController alertControllerWithTitle:tips message:@"Do you want to give up Bluetooth connected" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *noAction = [UIAlertAction actionWithTitle:cancel style:UIAlertActionStyleCancel handler:^(UIAlertAction *action){
}];
UIAlertAction *yesAction = [UIAlertAction actionWithTitle:ok style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){
//斷開藍芽 結束升級
[[BlueUtil sharedManager] disContentBle];
[self.navigationController popViewControllerAnimated:YES];
}];
[alertController addAction:noAction];
[alertController addAction:yesAction];
[self presentViewController:alertController animated:true completion:nil];
}
/*
斷開藍芽的時候傳送廣播
*/
-(void)disContentBle:(NSNotification*)notification{
self.isAutoCon = TRUE;
//當接受到藍芽退出的指令之後 不斷開介面 需要重新去連線介面
if(self.deviceTimer==nil){
self.deviceTimer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(deviceTime) userInfo:nil repeats:YES];
}
}
//自動連線藍芽程式碼
-(void)deviceTime{
//自定加1
self.times++;
NSString *mac = [[CommonDefaults shared] getMacAdder];
self.deviceList = [[BlueUtil sharedManager] getDeviceLists];
self.peripheralList = [[BlueUtil sharedManager] getPeriperalLists];
//如果不為空的時候
if(mac!=nil&&self.isAutoCon){
for(int i=0;i<self.deviceList.count;i++){
DeviceModel *data = [self.deviceList objectAtIndex:i];
if([data.deviceAddre isEqual:mac]){
[[BlueUtil sharedManager] contentAutoBlue:data.peripheral];
}
}
}
if(self.times>=5){
NSLog(@"大於了20。。%@",self.deviceTimer);
NSLog(@"大於了20.。%d",self.times);
if(self.deviceTimer!=nil){
[self.deviceTimer invalidate];
self.deviceTimer = nil;
}
self.isAutoCon = FALSE;
UIViewController *target = nil;
for (UIViewController * controller in self.navigationController.viewControllers) {
//遍歷
if ([controller isKindOfClass:[DeviceViewController class]]) {
//這裡判斷是否為你想要跳轉的頁面
target = controller;
}
}
if (target) {
[self.navigationController popToViewController:target animated:YES]; //跳轉
}
}else{
NSLog(@"DDD-HHH-LLL%@",self.deviceTimer);
NSLog(@"DDD-HHH-LLL%d",self.times);
}
}
五:相關藍芽列表的服務呼叫
-(BlueTempModel*)getBleTempModel{
if(self.bleModel==nil){
self.bleModel = [[BlueTempModel alloc] init];
}
return self.bleModel;
}
-(CommonDefaults*)getCmDefaults{
if(self.cmDefaults==nil){
self.cmDefaults = [[CommonDefaults alloc] init];
}
return self.cmDefaults;
}
-(BlueTempView *)getBlueTempView{
if(self.btView==nil){
self.btView = [[BlueTempView alloc] init];
}
return self.btView;
}
-(BlueTempModel *)getBlueTempModel{
if(self.blueTempModel==nil){
self.blueTempModel = [[BlueTempModel alloc] init];
}
return self.blueTempModel;
}
-(NSMutableArray *)gettempList{
if(self.tempList==nil){
self.tempList = [NSMutableArray array];
}
return self.tempList;
}
-(NSMutableArray*)getDeviceList{
if(self.deviceList==nil){
self.deviceList=[NSMutableArray array];
}
return self.deviceList;
}
-(NSMutableArray*)getPeripheralList{
if(self.peripheralList==nil){
self.peripheralList = [NSMutableArray array];
}
return self.peripheralList;
}
這篇博文總結了藍芽自動連結的相關知識,判斷到當裝置斷開之後,一定時間範圍內,如果裝置再次開啟,App移動應用端將依舊連結,繼續讀取/寫入相關資料,如果超出時間範圍內,則進行返回退出連結介面,需要用times斷開的次數,進行邏輯處理和功能需求的最終目的。
如果對您有所幫助,或者不懂之處可以留言,若有寫的不對之處,歡迎志同道合的朋友一起學習,一起進步,謝謝您的閱讀,別忘了點贊呀!