上一篇文章我們講了iOS開發(fā)的理論知識,下面我們就從代碼開始講解。
1.CoreBluetooth.framework導(dǎo)入
1.在General->TARGETS->Linked Framworks and Libraries中點(diǎn)擊添加并選擇CoreBluetooth.framework導(dǎo)入症杏。
2.在代碼中導(dǎo)入CoreBluetooth.framework Swift:import CoreBluetooth Objective-C:#import
3.聲明協(xié)議:使用CoreBluetooth需要支持CBCentralManagerDelegate(需要藍(lán)牙管理者mgr 管理者可以掃描外圍設(shè)備), CBPeripheralDelegate協(xié)議(mgr掃描到外設(shè)桨踪,與外設(shè)進(jìn)行連接斷開連接信息交流等一系列反饋回調(diào)),即前面所說的中心設(shè)備和外圍設(shè)備缅叠,并實(shí)現(xiàn)相應(yīng)方法
2.建立一個Central Manager實(shí)例進(jìn)行藍(lán)牙管理
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
一旦設(shè)置代理在運(yùn)行程序的時候,就會調(diào)用協(xié)議里一個必須要完成的方法:
這個方法是查看中心設(shè)備是否打開藍(lán)牙虏冻。
#pragma mark - 只要中心管理者初始化 就會觸發(fā)此代理方法 判斷手機(jī)藍(lán)牙狀態(tài)
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
switch (central.state)
{
// PoweredOff
case CBCentralManagerStatePoweredOff:
break;
// PoweredOn
case CBCentralManagerStatePoweredOn: //藍(lán)牙已開啟
// 搜索外設(shè)
[self.centralManager scanForPeripheralsWithServices:nil options:self.centralManagerOptionDic];
break;
// Resetting
case CBCentralManagerStateResetting:
break;
// Unsupported
case CBCentralManagerStateUnsupported: //不支持藍(lán)牙
break;
// Unauthorized
case CBCentralManagerStateUnauthorized:
break;
// Unknown state
case CBCentralManagerStateUnknown:
break;
default:
break;
}
}
[manager scanForPeripheralsWithServices:nil options:nil];
第一個參數(shù)那里表示掃描帶有相關(guān)服務(wù)的外部設(shè)備肤粱,例如填寫@[[CBUUIDUUIDWithString:@"需要連接的外部設(shè)備的服務(wù)的UUID"]],即表示帶有需要連接的外部設(shè)備的服務(wù)的UUID的外部設(shè)備厨相,nil表示掃描全部設(shè)備领曼;
options處以后細(xì)講,暫時可以寫一個@{CBCentralManagerScanOptionAllowDuplicatesKey :@YES}這樣的參數(shù)蛮穿,YES表示會讓中心設(shè)備不斷地監(jiān)聽外部設(shè)備的消息庶骄,NO就是不能。
3.掃描周邊的藍(lán)牙設(shè)備
// 1.中心管理者 2.外設(shè) 3.外設(shè)攜帶的數(shù)據(jù) 4.外設(shè)發(fā)出的藍(lán)牙信號強(qiáng)度
- (void)centralManager:(CBCentralManager *)central
didDiscoverPeripheral:(CBPeripheral *)peripheral
advertisementData:(NSDictionary *)advertisementData
RSSI:(NSNumber *)RSSI
{
/*
peripheral = <CBPeripheral: 0x166668f0 identifier = C69010E7-EB75-E078-FFB4-421B4B951341, Name = "OBand-75", state = disconnected>, advertisementData = {
kCBAdvDataChannel = 38;
kCBAdvDataIsConnectable = 1;
kCBAdvDataLocalName = OBand;
kCBAdvDataManufacturerData = <4c69616e 0e060678 a5043853 75>;
kCBAdvDataServiceUUIDs = (
FEE7
);
kCBAdvDataTxPowerLevel = 0;
}, RSSI = -55
*/
if ([peripheral.name hasPrefix:@"OBand"]) {
[self.centralManager stopScan];
// 在此處對我們的 advertisementData(外設(shè)攜帶的廣播數(shù)據(jù)) 進(jìn)行一些處理
// 標(biāo)記我們的外設(shè),讓他的生命周期 = vc
self.peripheral = peripheral;
// 發(fā)現(xiàn)完之后就是進(jìn)行連接
[self.centralManager connectPeripheral:self.peripheral options:nil];
NSLog(@"%s, line = %d", __FUNCTION__, __LINE__);
}
}
4.連接外圍設(shè)備
// 中心管理者連接外設(shè)成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
NSLog(@"%s, line = %d, %@=連接成功", __FUNCTION__, __LINE__, peripheral.name);
// 連接成功之后,可以進(jìn)行服務(wù)和特征的發(fā)現(xiàn)
// 設(shè)置外設(shè)的代理
self.peripheral.delegate = self;
// 外設(shè)發(fā)現(xiàn)服務(wù),傳nil代表不過濾
// 這里會觸發(fā)外設(shè)的代理方法 - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
[self.peripheral discoverServices:nil];
}
// 連接失敗
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(nullableNSError *)error;(連接失敿酢)
// 丟失連接
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
NSLog(@"%s, line = %d, %@=斷開連接", __FUNCTION__, __LINE__, peripheral.name);
}
5.獲得外圍設(shè)備的服務(wù) & 6.獲得服務(wù)的特征
#pragma mark - CBPeripheralDelegate
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(nullable NSError *)error{
if (error)
{
NSLog(@"error:%@",error.localizedDescription);
return ;
}
for (CBService *service in peripheral.services)
{
NSLog(@"Discovered service %@", service);
[peripheral discoverCharacteristics:nil forService:service];
}
}
當(dāng)我們掃描到特征的時候单刁,就會跳入發(fā)現(xiàn)特征的協(xié)議方法里去:
// 發(fā)現(xiàn)外設(shè)服務(wù)里的特征的時候調(diào)用的代理方法(這個是比較重要的方法,你在這里可以通過事先知道UUID找到你需要的特征府适,訂閱特征幻碱,或者這里寫入數(shù)據(jù)給特征也可以)
- (void)peripheral:(CBPeripheral *)peripheral
didDiscoverCharacteristicsForService:(CBService *)service
error:(nullable NSError *)error
{
if (error) {
NSLog(@"error:%@",error.localizedDescription);
return ;
}
NSLog(@"%s, line = %d", __FUNCTION__, __LINE__);
// 下面的36F6和36F5根據(jù)需求自己定義
for (CBCharacteristic *characteristic in service.characteristics)
{
if ([[[characteristic UUID] UUIDString] isEqualToString:@"36F6"])
{
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
else if([[[characteristic UUID] UUIDString] isEqualToString:@"36F5"] )
{
// 記錄要之后每次要寫入的特征
writeCBCharacteristic = characteristic;
}
}
}
7.給外圍設(shè)備發(fā)送數(shù)據(jù)(也就是寫入數(shù)據(jù)到藍(lán)牙)
發(fā)送數(shù)據(jù)只需要在指定的service和characteristic組合下發(fā)送即可,如果是以CBCharacteristicWriteWithResponse模式發(fā)送细溅,發(fā)送完后還會調(diào)用
CBPeripheralDelegate的peripheral:(CBPeripheral *) didWriteValueForCharacteristic:(CBCharacteristic *) error:(NSError *)褥傍,實(shí)現(xiàn)該協(xié)議方法可判斷發(fā)送是否成功。
以CBCharacteristicWriteWithoutResponse模式則不會有回調(diào)喇聊。
[connectPeripheral writeValue:data forCharacteristic:writeCBCharacteristic type:CBCharacteristicWriteWithResponse];
//第一個參數(shù)是已連接的藍(lán)牙設(shè)備 恍风;第二個參數(shù)是要寫入到哪個特征; 第三個參數(shù)是通過此響應(yīng)記錄是否成功寫入
- (void)peripheral:(CBPeripheral *)peripheral
didWriteValueForCharacteristic:(CBCharacteristic *)characteristic
error:(nullable NSError *)error
{
if (error)
{
NSLog(@"error:%@, %@",error.localizedDescription, characteristic);
return ;
}
if (!(characteristic.properties & CBCharacteristicPropertyNotify))
{
[peripheral readValueForCharacteristic:characteristic];
}
}
8.從外圍設(shè)備讀數(shù)據(jù)
// 更新特征的value的時候會調(diào)用 (凡是從藍(lán)牙傳過來的數(shù)據(jù)都要經(jīng)過這個回調(diào)誓篱,簡單的說這個方法就是你拿數(shù)據(jù)的唯一方法) 你可以判斷是否修改密碼成功, 獲取電量信息等, 以及getToken(以我工程藍(lán)牙鎖為例子)
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
NSLog(@"%s, line = %d", __FUNCTION__, __LINE__);
if (characteristic == @"你要的特征的UUID或者是你已經(jīng)找到的特征") {
//characteristic.value就是你要的數(shù)據(jù), 類型是NSData, 二進(jìn)制數(shù)據(jù)
}
}
// 如果有寫特征將notift設(shè)置為yes之后: [peripheral setNotifyValue:YES forCharacteristic:c]朋贬,訂閱的通知消息會走下面這個接口
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{}
以上內(nèi)容有寫的不對的地方,請大家指出窜骄,有理解不了的地方可以同我交流锦募。