這段時間一直在做關(guān)于藍牙的項目当纱,有點心得呛每,拿出來和大家分享下。希望對大家有幫助坡氯,廢話不多說晨横。直接上代碼
首先,我在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攻城獅杂腰。如果喜歡請不吝點擊下喜歡。
這是本人第一次寫文章椅文,如有哪里不對請給我寶貴的意見喂很。