IOS 鏈接多個藍牙設(shè)備,收發(fā)數(shù)據(jù)

這段時間一直在做關(guān)于藍牙的項目当纱,有點心得呛每,拿出來和大家分享下。希望對大家有幫助坡氯,廢話不多說晨横。直接上代碼

屏幕快照 2016-08-05 下午8.11.17.png

首先,我在ViewController這個類中主要做的是藍牙的搜索,鏈接箫柳,及斷開颓遏。在LinkViewController這個類中,設(shè)置藍牙外設(shè)的代理人滞时,打開訂閱的通道叁幢,給外設(shè)發(fā)數(shù)據(jù)。(我這個藍牙是一問一答模式)leftView和rightView分別是作為兩個藍牙的代理人坪稽,來設(shè)置寫入特征和訂閱特征并且接收藍牙數(shù)據(jù)

下面代碼中的全局實例對象cell僅是為了在tableView中展示的時候區(qū)別鏈接與未鏈接曼玩。
#import "ViewController.h"
#import <CoreBluetooth/CoreBluetooth.h>
#import "LinkViewController.h"

@interface ViewController ()<CBCentralManagerDelegate,UITableViewDelegate,UITableViewDataSource>
{
UITableViewCell *cell;
}

@property (nonatomic,strong ) CBCentralManager *manager;// 中心設(shè)備
@property (nonatomic,strong ) NSMutableArray   *devices;// 掃描到的外圍設(shè)備
@property (nonatomic, strong) NSMutableArray   *connectSuccess;//鏈接成功的的外設(shè)
@property (weak, nonatomic  ) IBOutlet UITableView      *tableView;

@end

在ViewDidLoad中對中心設(shè)備及可變數(shù)據(jù)進行初始化鳞骤。
- (void)viewDidLoad {
cell = [[UITableViewCell alloc] init];
[super viewDidLoad];
self.manager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
self.devices = [NSMutableArray array];
self.connectSuccess = [NSMutableArray array];
self.tableView.delegate = self;
self.tableView.dataSource = self;
}
下面代碼是掃描外設(shè)以及停止掃描
- (IBAction)startScan:(id)sender {
//掃描外設(shè)
[self.manager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey:@YES}];
//3秒后停止。(開啟掃描后會不停的掃描)
[self performSelector:@selector(stopScan) withObject:nil afterDelay:3];
}
/**
* 停止掃描
*/
-(void)stopScan{
[self.manager stopScan];
}
藍牙的代理(藍牙的狀態(tài)改變的代理黍判,掃描外設(shè)的代理豫尽,連接成功,失敗顷帖,以及斷開藍牙的代理)
#pragma mark - 藍牙的代理事件
//中心設(shè)備狀態(tài)改變的代理必須實現(xiàn)
- (void)centralManagerDidUpdateState: (CBCentralManager *)central
{
switch (central.state)
{
case CBCentralManagerStatePoweredOn:
// [self showInfo:@"藍牙已打開"];
break;
case CBCentralManagerStateUnknown:
// [self showInfo:@"藍牙 狀態(tài)位置"];
break;
case CBCentralManagerStatePoweredOff:
// [self showInfo:@"藍牙未打開"];
break;
case CBCentralManagerStateResetting:
// [self showInfo:@"藍牙初始化中"];
break;
case CBCentralManagerStateUnsupported:
// [self showInfo:@"藍牙不支持狀態(tài)"];
break;
case CBCentralManagerStateUnauthorized:
// [self showInfo:@"藍牙設(shè)備未授權(quán)"];
break;
default:
break;
}
}

/**
 *  掃描藍牙的代理
 *
 *  @param central           中心設(shè)備
 *  @param peripheral        掃描到的藍牙
 *  @param advertisementData 在ios中藍牙廣播信息中通常會包含以下4種類型的信息美旧。ios的藍牙通信協(xié)議中不接受其他類型的廣播信息。
                         因此需要注意的是贬墩,如果需要在掃描設(shè)備時榴嗅,通過藍牙設(shè)備的Mac地址來唯一辨別設(shè)備,那么需要與藍牙設(shè)備的硬件工程師溝通好:將所需要的Mac地址放到一下幾種類型的廣播信息中陶舞。
                         通常放到kCBAdvDataManufacturerData這個字段中嗽测。
        kCBAdvDataIsConnectable = 1;
        kCBAdvDataLocalName = XXXXXX;
        kCBAdvDataManufacturerData = <XXXXXXXX>;
        kCBAdvDataTxPowerLevel = 0;
 *  @param RSSI              信號強度
 */
//掃描到的藍牙設(shè)備添加到devices數(shù)組中,刷新列表
-(void)centralManager:(CBCentralManager *)central
didDiscoverPeripheral:(CBPeripheral *)peripheral
advertisementData:(NSDictionary<NSString *,id> *)advertisementData
             RSSI:(NSNumber *)RSSI{

if (![self.devices containsObject:peripheral]) {
    [self.devices addObject:peripheral];
    [self.tableView reloadData];
    NSLog(@"發(fā)現(xiàn)外圍設(shè)備:%@---RSSI:%@---advertisementData:%@",peripheral,RSSI,advertisementData);
}
}

在表格的點擊代理中去連接外設(shè)

-(void)tableView:(UITableView *)tableView       didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[self.manager connectPeripheral:self.devices[indexPath.row] options:nil];
cell = [tableView cellForRowAtIndexPath:indexPath];
}

藍牙連接的代理

/**
 *  藍牙連接成功時候的代理
 *
 *  @param central    中心設(shè)備
 *  @param peripheral 當前連接的設(shè)備
 */
-(void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
NSLog(@"%@名字的藍牙連接成功",peripheral.name);
cell.detailTextLabel.text = @"已連接";
[self.connectSuccess addObject:peripheral];
}
/**
 *  藍牙鏈接失敗的代理
 *
 *  @param central    中心設(shè)備
 *  @param peripheral 當前連接的外設(shè)
 *  @param error      錯誤信息
 */
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error;{
   NSLog(@"%@名字的藍牙連接失敗",peripheral.name); 
}

cell左劃斷開藍牙連接肿孵,這里的cell.detailTextLabel.text在連接成功唠粥,和斷開成功的時候進行設(shè)置,區(qū)分停做。

-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell2 = [tableView cellForRowAtIndexPath:indexPath];
if ([cell2.detailTextLabel.text isEqualToString:@"已連接"]) {
    return YES;
}
return NO;
}

- (NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath{
cell = [tableView cellForRowAtIndexPath:indexPath];

UITableViewRowAction *disconnect = [UITableViewRowAction rowActionWithStyle:1 title:@"斷開連接" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
    //斷開藍牙連接
    CBPeripheral *peripheral = self.devices[indexPath.row];
    [self.manager cancelPeripheralConnection:peripheral];
    [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
}];
return @[disconnect];
}

藍牙斷開連接的代理

/**
 *  藍牙斷開連接的代理
 *
 *  @param central    中心設(shè)備
 *  @param peripheral 當前需要斷開連接的外設(shè)
 *  @param error      錯誤信息
 */
-(void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
NSLog(@"%@名字的藍牙斷開鏈接",peripheral.name);
cell.detailTextLabel.text = @"";
for (CBPeripheral *p in self.connectSuccess) {
    if ([p.identifier.UUIDString isEqualToString:peripheral.identifier.UUIDString]) {
        [self.connectSuccess removeObject:p];
    }
}
}

以上就是藍牙的掃描晤愧,連接,斷開

最后跳轉(zhuǎn)到LinkViewController頁面蛉腌,并且把連接成功的外設(shè)傳遞過去官份,這里我就不把外設(shè)一一對應(yīng)了。
#pragma mark - 跳轉(zhuǎn)
- (IBAction)gotoLink:(id)sender {
LinkViewController *link = [[LinkViewController alloc] init];
if (self.connectSuccess.count > 0) {
for (int i = 0; i < self.connectSuccess.count; i++) {
CBPeripheral *p = self.connectSuccess[i];
if (i == 0) {
link.leftperipheral = p;
}
if (i == 1) {
link.rightperipheral = p;
}
}
[self.navigationController pushViewController:link animated:YES];
}
}

這里我們將進行的是藍牙的收發(fā)數(shù)據(jù)

leftView和rightView分別對應(yīng)一個藍牙的代理人眉抬。這里我就展示一個贯吓。另外一個也是同樣的操作

leftView.h文件中懈凹。textView只是用來展示接收到的藍牙數(shù)據(jù)蜀变,mutStr存放接收到藍牙數(shù)據(jù)
#import <UIKit/UIKit.h>
#import <CoreBluetooth/CoreBluetooth.h>
@interface leftView : UIView<CBPeripheralDelegate>
@property (nonatomic, strong) UITextView *textView;
@property (nonatomic, strong) CBCharacteristic *leftNotiC, *leftWriteC;
@property (nonatomic, strong) NSMutableString *mutStr;
@end
leftView.m文件

#import "leftView.h"
//這里是和硬件工程師溝通好訂閱與寫入的服務(wù)通道
#define leftNotiService @"FFE0"
#define leftWriteService @"FFE5"

@implementation leftView
//重寫init方法
-(instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
    self.mutStr = [NSMutableString string];
    [self addTextView];
}
return self;
}
//添加textView
-(void)addTextView{
self.textView = [[UITextView alloc] initWithFrame:self.bounds];
self.textView.backgroundColor = [UIColor lightGrayColor];
[self addSubview:self.textView];
}


#pragma mark - 外圍設(shè)備服務(wù)的代理
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{

for (CBService *s in peripheral.services) {
    NSLog(@"%@",[s.UUID UUIDString]);
    if ([[s.UUID UUIDString] isEqualToString:@"FFE0"]) {
        [peripheral discoverCharacteristics:nil forService:s];
    }
    if ([[s.UUID UUIDString] isEqualToString:@"FFE5"]) {
        [peripheral discoverCharacteristics:nil forService:s];
    }
}
}
#pragma mark 2. 外圍設(shè)備 掃描到服務(wù)下有哪些特征
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(nonnull CBService *)service error:(nullable NSError *)error
{
if ([[service.UUID UUIDString] isEqualToString:@"FFE0"]) {
    //這里也需要個硬件工程師溝通好。
    self.leftNotiC = service.characteristics[0];
}
if ([[service.UUID UUIDString] isEqualToString:@"FFE5"]) {
    self.leftWriteC = service.characteristics[0];
}
}

#pragma mark 3.接收外圍設(shè)備的數(shù)據(jù)(這里就能接到藍牙發(fā)送過來的數(shù)據(jù)介评,具體協(xié)議就要看你們是怎么定義的)
-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
NSData *testData           = characteristic.value;
Byte *testByte             = (Byte *)[testData bytes];
NSMutableArray *midArray   = [NSMutableArray array];
for(int i                  = 0;i<[testData length];i++){
    [midArray addObject:[NSString stringWithFormat:@"%d",testByte[i]]];
    }

for (NSString *str in midArray) {
    [_mutStr appendString:str];
    [_mutStr appendString:@","];
}
self.textView.text = self.mutStr;

}
LinkViewController.m文件中

- (void)viewDidLoad {
[super viewDidLoad];
[self setUI];
//發(fā)現(xiàn)左邊外設(shè)的服務(wù) (運行到這個方法會進入leftView.m文件中的外圍設(shè)備服務(wù)的代理)
[self.leftperipheral discoverServices:nil];
//發(fā)現(xiàn)右邊外設(shè)的服務(wù)
[self.rightperipheral discoverServices:nil];
}
-(void)setUI{
self.l = [[leftView alloc] initWithFrame:CGRectMake(0, 64, [UIScreen mainScreen].bounds.size.width, 200)];
[self.view addSubview:_l];
//設(shè)置代理人库北。這個很重要
self.leftperipheral.delegate = _l;

self.r = [[rightView alloc] initWithFrame:CGRectMake(0, 284, [UIScreen mainScreen].bounds.size.width, 200)];
[self.view addSubview:_r];
//設(shè)置代理人。這個很重要
self.rightperipheral.delegate = _r;
}
- (IBAction)writeData:(id)sender {
//打開通道
[self.leftperipheral setNotifyValue:YES forCharacteristic:_l.leftNotiC];
[self.leftperipheral writeValue:[self hexToBytes:@"a55a03010003"] forCharacteristic:_l.leftWriteC type:1];
//打開通道
[self.rightperipheral setNotifyValue:YES forCharacteristic:_r.rightNotiC];
[self.rightperipheral writeValue:[self hexToBytes:@"a55a03010003"] forCharacteristic:_r.rightWriteC type:1];
//這里我們的工程師定義為 給外設(shè)發(fā)送@"a55a03010003"的字節(jié)數(shù)組们陆。藍牙就會給我發(fā)送對應(yīng)的數(shù)據(jù)寒瓦。
_l.mutStr = [NSMutableString string];
_r.mutStr = [NSMutableString string];
}

//字符串改為字節(jié)數(shù)組,需要轉(zhuǎn)換的字符串也是與硬件工程師溝通好的
- (NSData *)hexToBytes:(NSString *)str{
NSMutableData* data = [NSMutableData data];
int idx;
for (idx = 0; idx+2 <= str.length; idx+=2) {
    NSRange range = NSMakeRange(idx, 2);
    NSString* hexStr = [str substringWithRange:range];
    NSScanner* scanner = [NSScanner scannerWithString:hexStr];
    unsigned int intValue;
    [scanner scanHexInt:&intValue];
    [data appendBytes:&intValue length:1];
}
return data;
}

以上就是IOS 鏈接兩個設(shè)備的操作坪仇。希望可以幫助到剛接觸到藍牙的IOS攻城獅杂腰。如果喜歡請不吝點擊下喜歡。
這是本人第一次寫文章椅文,如有哪里不對請給我寶貴的意見喂很。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末惜颇,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子少辣,更是在濱河造成了極大的恐慌凌摄,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件漓帅,死亡現(xiàn)場離奇詭異锨亏,居然都是意外死亡,警方通過查閱死者的電腦和手機忙干,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門器予,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人豪直,你說我怎么就攤上這事劣摇。” “怎么了弓乙?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵末融,是天一觀的道長。 經(jīng)常有香客問我暇韧,道長勾习,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任懈玻,我火速辦了婚禮巧婶,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘涂乌。我一直安慰自己艺栈,他們只是感情好,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布湾盒。 她就那樣靜靜地躺著湿右,像睡著了一般。 火紅的嫁衣襯著肌膚如雪罚勾。 梳的紋絲不亂的頭發(fā)上毅人,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機與錄音尖殃,去河邊找鬼丈莺。 笑死,一個胖子當著我的面吹牛送丰,可吹牛的內(nèi)容都是我干的缔俄。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼俐载!你這毒婦竟也來了铐懊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤瞎疼,失蹤者是張志新(化名)和其女友劉穎科乎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體贼急,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡茅茂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了太抓。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片空闲。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖走敌,靈堂內(nèi)的尸體忽然破棺而出碴倾,到底是詐尸還是另有隱情,我是刑警寧澤掉丽,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布跌榔,位于F島的核電站,受9級特大地震影響捶障,放射性物質(zhì)發(fā)生泄漏僧须。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一项炼、第九天 我趴在偏房一處隱蔽的房頂上張望担平。 院中可真熱鬧,春花似錦锭部、人聲如沸暂论。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽取胎。三九已至,卻和暖如春蹋砚,著一層夾襖步出監(jiān)牢的瞬間扼菠,已是汗流浹背摄杂。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工坝咐, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人析恢。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓墨坚,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子泽篮,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 原文:http://www.myexception.cn/operating-system/2052286.htm...
    KYM1988閱讀 1,944評論 2 2
  • 備注:下面說到的內(nèi)容都基于藍牙4.0標準以上输玷,主要以實踐為主蘸秘。 ~ CoreBluetooth.framework...
    未_漆小七閱讀 1,617評論 1 8
  • 藍牙 藍牙的波段為2400-2483.5MHz(包括防護頻帶)。這是全球范圍內(nèi)無需取得執(zhí)照(但定不是無管制的)的工...
    蘇永茂閱讀 6,147評論 0 11
  • 本文主要以藍牙4.0做介紹,因為現(xiàn)在iOS能用的藍牙也就是只僅僅4.0的設(shè)備 用的庫就是core bluetoot...
    暮雨飛煙閱讀 840評論 0 2
  • 每天打給妻子的電話,基本上是努爾接聽侠畔。昨晚突發(fā)奇想,十點估計她睡著了星瘾,再打坐桩,妻子順利接聽。 今晨及塘,想到白天給努爾打...
    兩個女兒的爸爸閱讀 690評論 7 2