iOS的藍(lán)牙框架是支持藍(lán)牙4.0協(xié)議的婉刀。
理解iOS CoreBluetooth兩個(gè)很重要的概念脊另,Central 和 Periperal Devices
這兩個(gè)概念可以用傳統(tǒng)的模式client-server來(lái)理解嗅钻,central意思是中心粤剧,其作用類(lèi)似server,periperal就是外設(shè)奕污,一般攜帶有數(shù)據(jù),我們需要去其中獲取數(shù)據(jù)按厘,下圖是蘋(píng)果官網(wǎng)的例子医吊,peripheral是心跳儀,按期作用逮京,我們?nèi)ミ@個(gè)外設(shè)中取心跳數(shù)據(jù)遮咖,則心跳儀的作用就類(lèi)似server了,我們的手機(jī)去心跳儀中獲取數(shù)據(jù)造虏,類(lèi)似client御吞。
Peripheral如何讓central知道它的存在呢? peripheral.比如上圖的心跳儀,通過(guò)不斷廣播自己的存在,并且在廣播過(guò)程中附帶廣告包(advertising packet),這樣你就發(fā)現(xiàn)了這個(gè)設(shè)備漓藕,并且獲取到它提供的服務(wù)陶珠。
介紹完這些概念,我們來(lái)看看實(shí)際代碼應(yīng)該如何填寫(xiě).這里對(duì)于我的藍(lán)牙小票機(jī)來(lái)編寫(xiě)的享钞,因?yàn)槲乙獙?duì)藍(lán)牙小票機(jī)器進(jìn)行寫(xiě)操作揍诽,手機(jī)是搜索peripharal的,所以手機(jī)為central,小票機(jī)為peripharal栗竖。
首先導(dǎo)入這個(gè)框架
-
該框架有主要有幾個(gè)類(lèi)值得我們注意,CBCentralManager暑脆,也就是我們之前提到的Central,可以用來(lái)發(fā)現(xiàn)外設(shè)的。
#import@interface ViewController () @property (nonatomic, retain) CBCentralManager *centralManager; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil]; }
上面代碼這里我們創(chuàng)建了一個(gè)CBCentralManager,用來(lái)發(fā)現(xiàn)外設(shè)狐肢,當(dāng)創(chuàng)建成功添吗,CBCentralManager會(huì)回調(diào)代理說(shuō)創(chuàng)建成功了,如下面代碼
/*
Invoked whenever the central manager's state is updated.
*/
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
NSString * state = nil;
switch ([central state])
{
case CBCentralManagerStateUnsupported:
state = @"The platform/hardware doesn't support Bluetooth Low Energy.";
break;
case CBCentralManagerStateUnauthorized:
state = @"The app is not authorized to use Bluetooth Low Energy.";
break;
case CBCentralManagerStatePoweredOff:
state = @"Bluetooth is currently powered off.";
break;
case CBCentralManagerStatePoweredOn:
state = @"work";
break;
case CBCentralManagerStateUnknown:
default:
;
}
NSLog(@"Central manager state: %@", state);
}
上面的代碼如果這個(gè)時(shí)候如果是CBCentralManagerStatePoweredOn份名,代表藍(lán)牙可用碟联。一定要在該方法回調(diào)后去開(kāi)啟掃描外設(shè),否則無(wú)反應(yīng).
-
現(xiàn)在可以連接掃描外設(shè)了
- (IBAction)scan:(id)sender { [self.centralManager scanForPeripheralsWithServices:nil options:nil]; }
上面代碼我創(chuàng)建了一個(gè)按鈕來(lái)掃描僵腺,就不上對(duì)應(yīng)的xib圖片了.
這個(gè)方法如果傳入的事nil,代表掃描所有外設(shè)鲤孵。
- (IBAction)scan:(id)sender {
[self.centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:@"FFE0"]] options:nil];
}
如果你只想搜索有提供對(duì)應(yīng)的服務(wù)號(hào)的外設(shè)(去peripharal 的advertising packet里匹配服務(wù)號(hào),傳入一個(gè)數(shù)組進(jìn)入辰如,對(duì)象為CBUUID,也就是Service的唯一標(biāo)識(shí)符普监。一般我們搜索過(guò)一個(gè)nil的就會(huì)知道我們要的服務(wù)好是什么樣子的了,之后編程就可以直接使用這個(gè)已知的服務(wù)好琉兜。除非你的藍(lán)牙設(shè)備的廠家更改服務(wù)號(hào)凯正,不過(guò)幾乎不可能。
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
static int i = 0;
NSString *str = [NSString stringWithFormat:@"Did discover peripheral. peripheral: %@ rssi: %@, UUID: %@ advertisementData: %@ ", peripheral, RSSI, peripheral.UUID, advertisementData];
NSLog(@"%@",str);
[self.discoverdPeriparals addObject:peripheral];
}
當(dāng)你發(fā)現(xiàn)了一個(gè)設(shè)備呕童,該方法會(huì)回調(diào)漆际。peripheral代表你發(fā)現(xiàn)的設(shè)備,advertisementData時(shí)廣告數(shù)據(jù)夺饲,rssi代表著信號(hào)強(qiáng)度.
從廣播數(shù)據(jù)中可以看到一個(gè)服務(wù)UUIDs,因?yàn)閺V播數(shù)據(jù)有數(shù)量大小限制奸汇,數(shù)據(jù)比較少。不過(guò)目前我們只是發(fā)現(xiàn)了這個(gè)設(shè)備往声,假設(shè)該設(shè)備已經(jīng)是我們感興趣的設(shè)備擂找,你可以通過(guò)[self.centralManager stopScan]來(lái)停止掃描,也可以繼續(xù)掃描浩销。
-
連接發(fā)現(xiàn)的外設(shè)
- (IBAction)connect:(id)sender {
[self.centralManager connectPeripheral: [self.discoverdPeriparals firstObject] options:nil];
}
假設(shè)第一個(gè)是我們需要的外設(shè)贯涎,連接它。/* Invoked whenever a connection is succesfully created with the peripheral. Discover available services on the peripheral */ - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral { NSLog(@"Did connect to peripheral: %@", peripheral); peripheral.delegate = self; [central stopScan]; [peripheral discoverServices:nil]; }
當(dāng)連接成功后調(diào)用該方法慢洋。這個(gè)時(shí)候我們?cè)O(shè)置該peripheral的代理我們自己塘雳,讓peripheral給我們返回所有服務(wù)陆盘。
[peripheral discoverServices:@[[CBUUID UUIDWithString:@"FFE0"]]];
這個(gè)方法也是傳入nil返回所有服務(wù),如果是傳入特定的服務(wù)id,只返回該服務(wù) 這里我們傳入nil來(lái)返回所有服務(wù)
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
if (error)
{
NSLog(@"Discovered services for %@ with error: %@", peripheral.name, [error localizedDescription]);
return;
}
for (CBService *service in peripheral.services)
{
NSLog(@"Service found with UUID: %@", service.UUID);
if ([service.UUID isEqual:[CBUUID UUIDWithString:@"FFE0"]])
{
[peripheral discoverCharacteristics:nil forService:service];
}
}
}
這里看到返回了兩個(gè)服務(wù)败明,因?yàn)樾枰狥FE0,所以讓該服務(wù)返回對(duì)應(yīng)的characteristics.
[peripheral discoverCharacteristics:nil forService:service];
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
if (error)
{
NSLog(@"Discovered characteristics for %@ with error: %@", service.UUID, [error localizedDescription]);
return;
}
for (CBCharacteristic * characteristic in service.characteristics)
{
DLog(@"%@",characteristic);
if( [characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FFE1"]])
{
self.p = peripheral;
self.c = characteristic;
//read
//[testPeripheral readValueForCharacteristic:characteristic];
NSLog(@"Found a Device Manufacturer Name Characteristic - Read manufacturer name");
}
}
}
上面的方法是找到FEE0服務(wù)的所有特征隘马,這里的只有一個(gè),也就藍(lán)牙小票機(jī)FFE0寫(xiě)服務(wù)的寫(xiě)特征. 獲取到該特征妻顶。進(jìn)行寫(xiě)服務(wù)酸员,具體的log就不寫(xiě)了
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSString *RStr = @"2764";
NSMutableString *str = [NSMutableString new];
[str appendFormat:@"%c", 28];
[str appendFormat:@"%c", 33];
[str appendFormat:@"%c", 8];
[self.p writeValue:[str dataUsingEncoding:CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000)] forCharacteristic:self.c type:CBCharacteristicWriteWithResponse];
RStr = @"吳彥祖 你好呀!!!\n\n\n\n\n\n\n\n";
[self.p writeValue:[RStr dataUsingEncoding:CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000)] forCharacteristic:self.c type:CBCharacteristicWriteWithResponse];
}
這里我對(duì)藍(lán)牙小票機(jī)提供的寫(xiě)特征進(jìn)行寫(xiě)服務(wù)。成功.
補(bǔ)充: 如果該特征是可以讀特征讳嘱,你可以對(duì)該特征進(jìn)行訂閱幔嗦。
[peripheral setNotifyValue:YES forCharacteristic:interestingCharacteristic];
該方法回調(diào)peripheral:didUpdateValueForCharacteristic:error:
方法
當(dāng)你訂閱成功后,如果數(shù)據(jù)有更新沥潭,則回調(diào)該方法邀泉。 你就可以去讀取你想要的數(shù)據(jù)了。
如果想要了解更多叛氨,建議查看iOS官方文檔提供的CoreBluetooth programming guid呼渣。