1. 程式人生 > >IOS 藍芽裝置斷開時間內進行自動連結

IOS 藍芽裝置斷開時間內進行自動連結

一: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斷開的次數,進行邏輯處理和功能需求的最終目的。

如果對您有所幫助,或者不懂之處可以留言,若有寫的不對之處,歡迎志同道合的朋友一起學習,一起進步,謝謝您的閱讀,別忘了點贊呀!