成年欧美1314www色,亚洲+激情+专区,最爽无遮挡行房视频,中文字幕av无码一区二区三区电影,亚洲国产成人久久精品大牛影视

廣州藍牙APP開發(fā)

文章分類:APP行業(yè)動態(tài) 發(fā)布時間:2017-08-12 原文作者:Shi Yongfeng 閱讀( )

    之前公司在做一個iOS藍牙項目,在開發(fā)的過程中簡單整理了一些與之相關的基礎知識,在這里廣州iOS APP開發(fā)公司奕環(huán)科技小編分享一下iOS藍牙APP開發(fā),藍牙中心設備的實現(xiàn)及藍牙外設的實現(xiàn)。整理包括以下內容:

1、iOS藍牙開發(fā)的關鍵詞

2、藍牙的簡單介紹

3、CoreBluetooth框架

4、實現(xiàn)iOS藍牙外設(Demo)

5、實現(xiàn)iOS藍牙中心設備(Demo)

點擊查看Demo的運行gif圖,中心設備可以從外設讀取數(shù)據(jù),也可以向外設寫入數(shù)據(jù)。外設也可以向中心設備發(fā)送數(shù)據(jù)。

PS:需要使用真機測試。

iOS的藍牙開發(fā)是圍繞著CoreBluetooth框架來實現(xiàn)的。

下面先從iOS藍牙開發(fā)的基本概念說起

中心設備:就是用來掃描周圍藍牙硬件的設備,比如通過你手機的藍牙來掃描并連接智能手環(huán),這時候你的手機就是中心設備。

外設:被掃描的設備。比如當你用手機的藍牙掃描連接智能手環(huán)的時候,智能手環(huán)就是外設。

廣播:就是外設不停的散播藍牙信號,讓中心設備可以掃描到。

服務(services):外設廣播和運行的時候會有服務,可以理解成一個功能模塊,中心設備可以讀取服務。外設可以有多個服務。

特征(characteristic):在服務中的一個單位,一個服務可以有多個特征,特征會有一個value,一般讀寫的數(shù)據(jù)就是這個value。

UUID:區(qū)分不同的服務和特征,可以理解為服務和特征的身份證。我們可以用UUID來挑選需要的服務和特征。

下面進入iOS藍牙開發(fā)的主要部分,中心設備的實現(xiàn),這也是手機App通常擔任的角色。

實現(xiàn)iOS藍牙中心設備(Demo)

1、同外設開發(fā)一樣,首先要導入CoreBluetooth框架。

#import <CoreBluetooth/CoreBluetooth.h>

2、遵守的協(xié)議與外設開發(fā)不同,中心設備的開發(fā)需要遵循如下兩個協(xié)議。

@interface ViewController () <CBCentralManagerDelegate,CBPeripheralDelegate>

3、創(chuàng)建中心管理器并用屬性強引用,創(chuàng)建的時候也會設置代理和選擇線程。

@property (nonatomic, strong) CBCentralManager *centralManager;

// 創(chuàng)建中心設備管理器,會回調centralManagerDidUpdateState

self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];

4、當創(chuàng)建中心管理對象的時候,會回調如下方法用來判斷中心設備的藍牙狀態(tài)。當藍牙狀態(tài)沒問題的時候,可以根據(jù)外設服務的UUID來掃描需要的外設。所以自然而然的就想到了要定義與外設UUID相同的宏。

/** 判斷手機藍牙狀態(tài) */

#define SERVICE_UUID @"CDD1"

#define CHARACTERISTIC_UUID @"CDD2"

- (void)centralManagerDidUpdateState:(CBCentralManager *)central {

// 藍牙可用,開始掃描外設

if (central.state == CBManagerStatePoweredOn) {

NSLog(@"藍牙可用");

// 根據(jù)SERVICE_UUID來掃描外設,如果不設置SERVICE_UUID,則掃描所有藍牙設備

[central scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:SERVICE_UUID]] options:nil];

}

if(central.state==CBCentralManagerStateUnsupported) {

NSLog(@"該設備不支持藍牙");

}

if (central.state==CBCentralManagerStatePoweredOff) {

NSLog(@"藍牙已關閉");

}

}

5、當掃描到外設之后,就會回調下面這個方法,可以在這個方法中繼續(xù)設置篩選條件,例如根據(jù)外設名字的前綴來選擇,如果符合條件就進行連接。

/** 發(fā)現(xiàn)符合要求的外設,回調 */

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI {

// 對外設對象進行強引用

self.peripheral = peripheral;

// if ([peripheral.name hasPrefix:@"WH"]) {

// // 可以根據(jù)外設名字來過濾外設

// [central connectPeripheral:peripheral options:nil];

// }

// 連接外設

[central connectPeripheral:peripheral options:nil];

}

7、當連接成功的時候,就會來到下面這個方法。為了省電,當連接上外設之后,就讓中心設備停止掃描,并且別忘記設置連接上的外設的代理。在這個方法里根據(jù)UUID進行服務的查找。

/** 連接成功 */

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{

// 可以停止掃描

[self.centralManager stopScan];

// 設置代理

peripheral.delegate = self;

// 根據(jù)UUID來尋找服務

[peripheral discoverServices:@[[CBUUID UUIDWithString:SERVICE_UUID]]];

NSLog(@"連接成功");

}

8、連接失敗和斷開連接也有各自的回調方法。在斷開連接的時候,我們可以設置自動重連,根據(jù)項目需求來自定義里面的代碼。

/** 連接失敗的回調 */

-(void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {

NSLog(@"連接失敗");

}

/** 斷開連接 */

- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error {

NSLog(@"斷開連接");

// 斷開連接可以設置重新連接

[central connectPeripheral:peripheral options:nil];

}

9、下面開始處理代理方法。

最開始就是發(fā)現(xiàn)服務的方法。這個方法里可以遍歷服務,找到需要的服務。由于上面做的外設只有一個服務,所以我這里直接取服務中的最后一個lastObject就行了。

找到服務之后,連貫的動作繼續(xù)根據(jù)特征的UUID尋找服務中的特征。

/** 發(fā)現(xiàn)服務 */

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {

// 遍歷出外設中所有的服務

for (CBService *service in peripheral.services) {

NSLog(@"所有的服務:%@",service);

}

// 這里僅有一個服務,所以直接獲取

CBService *service = peripheral.services.lastObject;

// 根據(jù)UUID尋找服務中的特征

[peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:CHARACTERISTIC_UUID]] forService:service];

}

10、下面這個方法里做的事情不少。

當發(fā)現(xiàn)特征之后,與服務一樣可以遍歷特征,根據(jù)外設開發(fā)人員給的文檔找出不同特征,做出相應的操作。

我的外設只設置了一個特征,所以也是直接通過lastObject拿到特征。

再重復一遍,一般開發(fā)中可以設置兩個特征,一個用來發(fā)送數(shù)據(jù),一個用來接收中心設備寫過來的數(shù)據(jù)。

這里用一個屬性引用特征,是為了后面通過這個特征向外設寫入數(shù)據(jù)或發(fā)送指令。

readValueForCharacteristic方法是直接讀一次這個特征上的數(shù)據(jù)。

/** 發(fā)現(xiàn)特征回調 */

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {

// 遍歷出所需要的特征

for (CBCharacteristic *characteristic in service.characteristics) {

NSLog(@"所有特征:%@", characteristic);

// 從外設開發(fā)人員那里拿到不同特征的UUID,不同特征做不同事情,比如有讀取數(shù)據(jù)的特征,也有寫入數(shù)據(jù)的特征

}

// 這里只獲取一個特征,寫入數(shù)據(jù)的時候需要用到這個特征

self.characteristic = service.characteristics.lastObject;

// 直接讀取這個特征數(shù)據(jù),會調用didUpdateValueForCharacteristic

[peripheral readValueForCharacteristic:self.characteristic];

// 訂閱通知

[peripheral setNotifyValue:YES forCharacteristic:self.characteristic];

}

setNotifyValue:(BOOL)enabled forCharacteristic:(CBCharacteristic *)characteristic方法是對這個特征進行訂閱,訂閱成功之后,就可以監(jiān)控外設中這個特征值得變化了。

11、當訂閱的狀態(tài)發(fā)生改變的時候,下面的方法就派上用場了。

/** 訂閱狀態(tài)的改變 */

-(void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {

if (error) {

NSLog(@"訂閱失敗");

NSLog(@"%@",error);

}

if (characteristic.isNotifying) {

NSLog(@"訂閱成功");

} else {

NSLog(@"取消訂閱");

}

}

12、外設可以發(fā)送數(shù)據(jù)給中心設備,中心設備也可以從外設讀取數(shù)據(jù),當發(fā)生這些事情的時候,就會回調這個方法。通過特種中的value屬性拿到原始數(shù)據(jù),然后根據(jù)需求解析數(shù)據(jù)。

/** 接收到數(shù)據(jù)回調 */

- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {

// 拿到外設發(fā)送過來的數(shù)據(jù)

NSData *data = characteristic.value;

self.textField.text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

}

13、中心設備可以向外設寫入數(shù)據(jù),也可以向外設發(fā)送請求或指令,當需要進行這些操作的時候該怎么辦呢。

  • 首先把要寫入的數(shù)據(jù)轉化為NSData格式,然后根據(jù)上面拿到的寫入數(shù)據(jù)的特征,運用方法writeValue:(NSData )data forCharacteristic:(CBCharacteristic )characteristic type:(CBCharacteristicWriteType)type來進行數(shù)據(jù)的寫入。

  • 當寫入數(shù)據(jù)的時候,系統(tǒng)也會回調這個方法peripheral:(CBPeripheral )peripheral didWriteValueForCharacteristic:(nonnull CBCharacteristic )characteristic error:(nullable NSError *)error 。

/** 寫入數(shù)據(jù) */

- (IBAction)didClickPost:(id)sender {

// 用NSData類型來寫入

NSData *data = [self.textField.text dataUsingEncoding:NSUTF8StringEncoding];

// 根據(jù)上面的特征self.characteristic來寫入數(shù)據(jù)

[self.peripheral writeValue:data forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];

}

/** 寫入數(shù)據(jù)回調 */

- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(nonnull CBCharacteristic *)characteristic error:(nullable NSError *)error {

NSLog(@"寫入成功");

}

14、中心設備如何主動從外設讀取數(shù)據(jù)呢。

  • 用正在連接的外設對象來調用readValueForCharacteristic方法,并且把將要讀取數(shù)據(jù)的特征作為參數(shù),這樣就可以主動拿一次數(shù)據(jù)了。

去到第12步的回調方法中,在特征的value屬性中拿到這次的數(shù)據(jù)。

/** 讀取數(shù)據(jù) */

- (IBAction)didClickGet:(id)sender {

[self.peripheral readValueForCharacteristic:self.characteristic];

}

 
原文來自:Shi Yongfeng