本文轉載自:http://blog.csdn.net/swibyn/article/details/52096321
Performing Common Central Role Tasks
central角色的實現
central 角色需要完成的幾件事情,如搜索,連接,與peripheral交互數據。
peripheral 角色同樣需要完成幾件事情,如,發布和廣播服務,響應讀,寫,訂閱請求
本章中,你將學習如何完成central端的功能。
1,創建central manager 對象
2,發現和連接正在廣播的peripheral
3,瀏覽peripheral的數據
4,發送讀和寫請求到peripheral設備
5,訂閱characteristic的值
下一章你將學習如何開發peripheral角色的功能
Starting Up a Central Manager
創建Central manager對象
myCentralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:nil];'
在這里self設置成central角色的代理。dispath queue設置為nil,意味著central事件將交由main queue處理。
創建central manager時,會觸發centralManagerDidUpdateState: 代理方法。你必須實現這個代理。
Discovering Peripheral Devices That Are Advertising
搜索正在發送廣播的peripheral
[myCentralManager scanForPeripheralsWithServices:nil options:nil];
注意:如果第一個參數設置成nil,那么centralmanager會返回所有被發現的peripherals,在實際應用中,你應該給他賦值 CBUUID 對象數組。這樣只有有廣播這些uuid服務的peripheral才會被返回,
一旦發現peripheral,將觸發
centralManager:didDiscoverPeripheral:advertisementData:RSSi:
代理方法,如果你想連接這個peripheral,請使用強引用變量引用它,這樣系統就不會釋放掉它。
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral
advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
NSLog(@"Discovered %@", peripheral.name);
self.discoveredPeripheral = peripheral;
...
如果你想連接多個設備,你可以使用NSArray來管理他們。不管什么情況,一旦你找到所有你想要的設備,你應該停止掃描以便節省電量。
[myCentralManager stopScan];
Connecting to a Peripheral Device After You’ve Discovered It
連接peripheral
[myCentralManager connectPeripheral:peripheral options:nil];
如果連接成功,則會觸發centralManager:didConnectPeripheral:代理方法,與之通訊之前,你需要為它設置代理
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
NSLog(@"Peripheral connected");
peripheral.delegate = self;
...
Discovering the Services of a Peripheral That You’re Connected To
查詢peripheral的服務
建立連接之后,就可以查詢數據,第一步就是查詢有哪些services。因為廣播包有大小限制,在廣播中可能沒有顯示全部的服務信息,這里你可以使用discoverServices: 來查詢所有的services。
[peripheral discoverServices:nil];
注意:實際開發中,你不應該傳值nil,因為這樣做會返回所有的services,包括那些你不需要的services,這樣做會浪費時間和電量。所以你應該傳遞你需要的uuids。
查找到所有的服務會觸發peripheral:didDiscoverServices:代理方法
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
for (CBService *service in peripheral.services) {
NSLog(@"Discovered service %@", service);
...
}
...
Discovering the Characteristics of a Service
查找characteristics
發現service之后,下一步就是查找characteristics
NSLog(@"Discovering characteristics for service %@", interestingService);
[peripheral discoverCharacteristics:nil forService:interestingService];
注意:實際開發中,不要傳nil,這樣做會返回所有的characteristics,包括那些你不感興趣的characteristics。這樣做即浪費時間又損耗電量。所以你應該傳你需要的uuids的值
查找到characteristics之后,會觸發peripheral:didDiscoverCharacteristicsForService:error:代理方法
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
for (CBCharacteristic *characteristic in service.characteristics) {
NSLog(@"Discovered characteristic %@", characteristic);
...
}
...
Retrieving the Value of a Characteristic
獲取數據
一個characteristic只包含一種信息數據。比如恒溫service下的溫度characteristic只包含當前溫度值,你可以通過讀取或訂閱來獲得這個值。
Reading the Value of a Characteristic
讀取characteristic的數據
NSLog(@"Reading value for characteristic %@", interestingCharacteristic);
[peripheral readValueForCharacteristic:interestingCharacteristic];
獲取到數據后peripheral調用peripheral:didUpdateValueForCharacteristic:error:代理方法
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
NSData *data = characteristic.value;
// parse the data as needed
...
注意:并不是所有的characteristic都是可讀的,你可以通過 characteristic的 proterties屬性是否包含CBCharacteristicPropertyRead 常量來判斷是否可讀。在讀一個不可讀的characteristic的數據值,會在代理方法的error參數中體現異常信息
Subscribing to a Characteristic’s Value
訂閱characteristic的值
雖然通過readValueForCharacteristic: 可以有效獲取靜態值,但如果值是動態改變的,則最好使用訂閱的方法。當值變化時,自動獲得通知。
設置訂閱
[peripheral setNotifyValue:YES forCharacteristic:interestingCharacteristic];
訂閱的時候peripheral會調用peripheral:didUpdateNotificationStateForCharacteristic:error: 代理方法。如果訂閱失敗了,也可以通過這個方法查詢失敗的原因
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
if (error) {
NSLog(@"Error changing notification state: %@",[error localizedDescription]);
}
注意:并不是所有的characteristics都可以訂閱,可以通過檢查characteristic的properties屬性是否包含CBCharacteristicPropertyNotify 或 CBCharacteristicPropertyIndicate常量來判斷是否可訂閱
Writing the Value of a Characteristic
寫數據
有時也是需要寫數據的,比如恒溫器,你需要設置目標溫度。如果characteristic是可寫的,那么你就可以調用writeValue:forCharacteristic:type: 方法來寫入數據。如下:
NSLog(@"Writing value for characteristic %@", interestingCharacteristic);
[peripheral writeValue:dataToWrite forCharacteristic:interestingCharacteristic type:CBCharacteristicWriteWithResponse];
當你寫數據時,你可以標明寫類型。上例中,寫類型是CBCharacteristicWriteWithResponse, 這種情況下,不管有沒有寫成功,peripheral都會通過代理通知你。你需要實現這個方法以便處理異常情況。
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
if (error) {
NSLog(@"Error writing characteristic value: %@",[error localizedDescription]);
}
...
如果你設置的寫類型是CBCharacteristicWriteWithoutResponse, 那么寫操作會以更有效的方式執行,但不保證寫成功,并且不會有報告。peripheral不會通知任何回調。
注意:characteristic可能只支持特定的寫類型,或不支持寫操作。你可以通過檢查properties屬性是否包含CBCharacteristicPropertyWriteWithoutResponse 或 CBCharacteristicPropertyWrite 來判斷。