CoreBluetooth For Central (6)

CoreBluetooth For Central (6)

Explore >> BLE Device’s Services

Explore Services From Device

前半段了解如何連線至BLE週邊,接下來要看看BLE週邊提供什麼樣的服務類型,服務(Service)類型中會提供屬性(Characteristics),透過屬性(Characteristics)才能真正的與BLE週邊溝通,結構如官網的圖片:

所以我們要在已線連成功之後尋訪該週邊能提供什麼樣的服務(Service)類型,其中服務類型可以從Bluetooth協會中來了解已經被定義的類型,已經被定義的就能由規範好的溝通方式與週邊溝通,像0x180DUUID則是心跳表所代表的服務類型。 當你得知服務類型時,就能從規範中理解與服務溝通時會提供很多溝通管道,而這個溝通管道叫做Characteristics,這個有屬性觀念,會有唯讀寫入通知讀寫,當然它有一堆UUID碼當做溝通的識別碼,現在我們要先來列舉週邊提供什麼樣的服務(Service)。

連線成功後,CoreBluetooth會引發centralManager:didConnectPeripheral:告知已經連線成功,此時我們需要利用CoreBluetooth Framework開始進行Service的尋訪:

//-----------start-----------
-(void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
    NSLog(@"Connect To Peripheral with name: %@\nwith UUID:%@\n",peripheral.name,peripheral.identifier.UUIDString);

    peripheral.delegate=self;//連線成功後會回傳CBPeripheral,並邊要設定Delegate才能對後續的操作有所反應
    [peripheral discoverServices:nil];//一定要執行"discoverService"功能去尋找可用的Service

}
//------------end------------

連線成功取得Peripheral後,必需要立即設定Delegate,之後尋訪Service後才能有所反應,現在要執行尋訪Service的Method:

//-----------start-----------
    [peripheral discoverServices:nil]; //沒有指定要尋訪的Service UUID時,傳入nil
//------------end------------

接下來CoreBluetooth會開始動作,有反應時會引發peripheral:didDiscoverServices: Delegate,在Delegate發生時我們也要利用它來尋訪Characteristics,如此才能再引發peripheral:didDiscoverCharacteristicsForService:得知已能使用的Characteristics,下面範例會將Service的UUID內容印出,同時也執行尋訪Characteristics的功能(還未處理該Delegate):

//-----------start-----------
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
    NSLog(@"didDiscoverServices:\n");
    if( peripheral.identifier == NULL  ) return; // zach ios6 added
    if (!error) {
        NSLog(@"====%@\n",peripheral.name);
        NSLog(@"=========== %ld of service for UUID %@ ===========\n",peripheral.services.count,peripheral.identifier.UUIDString);

        for (CBService *p in peripheral.services){
            NSLog(@"Service found with UUID: %@\n", p.UUID);
            [peripheral discoverCharacteristics:nil forService:p];
        }

    }
    else {
        NSLog(@"Service discovery was unsuccessfull !\n");
    }

}
//------------end------------

上面程式內容會將Service類別印出來,不過在實作前需要有BLE週邊,範例使用的是Polar H7心跳表來當連線的週邊,如果再配合CoreBluetooth For Central (4)所學到的內容,將centralManager:didDiscoverPeripheral:advertisementData:RSSI:內容修改一下,讓程式當抓到Polar H7週邊時自動進行連線:

//-----------start-----------
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {

    NSLog(@"peripheral\n%@\n",peripheral);
    NSLog(@"advertisementData\n%@\n",advertisementData);
    NSLog(@"RSSI\n%@\n",RSSI);

    NSString *localName = [advertisementData objectForKey:CBAdvertisementDataLocalNameKey];

    NSLog(@"localName:%@",localName);
    //if ([peripheral.name length] && [peripheral.name rangeOfString:@"DannySimpleBLE"].location != NSNotFound) {
    if ([localName length] && [localName rangeOfString:@"Polar"].location != NSNotFound) {
        //抓到週邊後就立即停子Scan
        [CM stopScan];
        NSLog(@"stopScan");
        connectPeripheral = peripheral;
        [CM connectPeripheral:peripheral options:nil];
        NSLog(@"connect to %@",peripheral.name);
    }

}
//------------end------------

執行結果如下:

2015-01-26 17:14:29.554 BluetoothLE-Explore[8404:6929832] UpdateState:PoweredOn
2015-01-26 17:14:30.511 BluetoothLE-Explore[8404:6929832] Scan And Connect
2015-01-26 17:14:30.578 BluetoothLE-Explore[8404:6929832] peripheral
<CBPeripheral: 0x14d807b0, identifier = 8DC3DD90-0C17-1AB9-90FE-E9130DD07B81, name = Polar H7 000607, state = disconnected>
2015-01-26 17:14:30.580 BluetoothLE-Explore[8404:6929832] advertisementData
{
    kCBAdvDataIsConnectable = 1;
    kCBAdvDataManufacturerData = <6b00031c 00>;
    kCBAdvDataServiceUUIDs =     (
        "Heart Rate"
    );
    kCBAdvDataTxPowerLevel = 0;
}
2015-01-26 17:14:30.580 BluetoothLE-Explore[8404:6929832] RSSI
-64
2015-01-26 17:14:30.581 BluetoothLE-Explore[8404:6929832] localName:(null)
2015-01-26 17:14:30.581 BluetoothLE-Explore[8404:6929832] peripheral
<CBPeripheral: 0x14e3cea0, identifier = 8DC3DD90-0C17-1AB9-90FE-E9130DD07B81, name = Polar H7 000607, state = disconnected>
2015-01-26 17:14:30.582 BluetoothLE-Explore[8404:6929832] advertisementData
{
    kCBAdvDataIsConnectable = 1;
    kCBAdvDataLocalName = "Polar H7 000607";
    kCBAdvDataManufacturerData = <6b00031c 00>;
    kCBAdvDataServiceUUIDs =     (
        "Heart Rate"
    );
    kCBAdvDataTxPowerLevel = 0;
}
2015-01-26 17:14:30.582 BluetoothLE-Explore[8404:6929832] RSSI
-64
2015-01-26 17:14:30.583 BluetoothLE-Explore[8404:6929832] localName:Polar H7 000607
2015-01-26 17:14:30.583 BluetoothLE-Explore[8404:6929832] stopScan
2015-01-26 17:14:30.584 BluetoothLE-Explore[8404:6929832] connect to Polar H7 000607
2015-01-26 17:14:30.683 BluetoothLE-Explore[8404:6929832] connected
2015-01-26 17:14:30.683 BluetoothLE-Explore[8404:6929832] Connect To Peripheral with name: Polar H7 000607
with UUID:8DC3DD90-0C17-1AB9-90FE-E9130DD07B81
2015-01-26 17:14:31.120 BluetoothLE-Explore[8404:6929832] didDiscoverServices:
2015-01-26 17:14:31.121 BluetoothLE-Explore[8404:6929832] ====Polar H7 000607
2015-01-26 17:14:31.121 BluetoothLE-Explore[8404:6929832] =========== 4 of service for UUID 8DC3DD90-0C17-1AB9-90FE-E9130DD07B81 ===========
2015-01-26 17:14:31.122 BluetoothLE-Explore[8404:6929832] Service found with UUID: Heart Rate
2015-01-26 17:14:31.123 BluetoothLE-Explore[8404:6929832] Service found with UUID: Device Information
2015-01-26 17:14:31.123 BluetoothLE-Explore[8404:6929832] Service found with UUID: Battery
2015-01-26 17:14:31.124 BluetoothLE-Explore[8404:6929832] Service found with UUID: 6217FF49-AC7B-547E-EECF-016A06970BA9

從執行結果看到Service found with UUID:...顯示有蠻多Service提供,其中Heart Rate這項是可以取得目前心跳的資訊,接下來再承上面的範例,再加上將每個Service中的Characteristics屬性列出來,如果你要這麼做,就要處理引發peripheral:didDiscoverCharacteristicsForService的內容,架構如下:

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

:
:
:

}
//------------end------------

加上處理的程式,程式將每個Service中包含的Characteristics屬性列出來:

//-----------start-----------
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
    CBService *s = [peripheral.services objectAtIndex:(peripheral.services.count - 1)];
    //NSLog(@"=========== Service UUID %s ===========\n",[NSUUID UUID] ini);
    if (!error) {
        NSLog(@"=========== %d Characteristics of %@ service ",service.characteristics.count,service.UUID);
        //以下針對service提供的Characteristics一一尋訪並列出
        for(CBCharacteristic *c in service.characteristics){

            NSLog(@" %@ \n",c.UUID);
            //  CBService *s = [peripheral.services objectAtIndex:(peripheral.services.count - 1)];
            if(service.UUID == NULL || s.UUID == NULL) return; // zach ios6 added

        }
        NSLog(@"=== Finished set notification ===\n");

    }
    else {
        NSLog(@"Characteristic discorvery unsuccessfull !\n");

    }


}
//------------end------------

執行結果如下:

2015-01-26 17:39:42.464 BluetoothLE-Explore[8424:6934992] UpdateState:PoweredOn
2015-01-26 17:39:44.112 BluetoothLE-Explore[8424:6934992] Scan And Connect
2015-01-26 17:39:48.112 BluetoothLE-Explore[8424:6934992] stopScan
2015-01-26 17:39:48.113 BluetoothLE-Explore[8424:6934992] connectPeripheral == NULL
2015-01-26 17:39:54.913 BluetoothLE-Explore[8424:6934992] Scan And Connect
2015-01-26 17:39:54.935 BluetoothLE-Explore[8424:6934992] peripheral
<CBPeripheral: 0x16d4de10, identifier = 8DC3DD90-0C17-1AB9-90FE-E9130DD07B81, name = Polar H7 000607, state = disconnected>
2015-01-26 17:39:54.936 BluetoothLE-Explore[8424:6934992] advertisementData
{
    kCBAdvDataIsConnectable = 1;
    kCBAdvDataLocalName = "Polar H7 000607";
    kCBAdvDataManufacturerData = <6b000300 00>;
    kCBAdvDataServiceUUIDs =     (
        "Heart Rate"
    );
    kCBAdvDataTxPowerLevel = 0;
}
2015-01-26 17:39:54.937 BluetoothLE-Explore[8424:6934992] RSSI
-57
2015-01-26 17:39:54.937 BluetoothLE-Explore[8424:6934992] localName:Polar H7 000607
2015-01-26 17:39:54.938 BluetoothLE-Explore[8424:6934992] stopScan
2015-01-26 17:39:54.938 BluetoothLE-Explore[8424:6934992] connect to Polar H7 000607
2015-01-26 17:39:55.025 BluetoothLE-Explore[8424:6934992] connected
2015-01-26 17:39:55.025 BluetoothLE-Explore[8424:6934992] Connect To Peripheral with name: Polar H7 000607
with UUID:8DC3DD90-0C17-1AB9-90FE-E9130DD07B81
2015-01-26 17:39:55.407 BluetoothLE-Explore[8424:6934992] didDiscoverServices:
2015-01-26 17:39:55.408 BluetoothLE-Explore[8424:6934992] ====Polar H7 000607
2015-01-26 17:39:55.408 BluetoothLE-Explore[8424:6934992] =========== 4 of service for UUID 8DC3DD90-0C17-1AB9-90FE-E9130DD07B81 ===========
2015-01-26 17:39:55.409 BluetoothLE-Explore[8424:6934992] Service found with UUID: Heart Rate
2015-01-26 17:39:55.410 BluetoothLE-Explore[8424:6934992] Service found with UUID: Device Information
2015-01-26 17:39:55.410 BluetoothLE-Explore[8424:6934992] Service found with UUID: Battery
2015-01-26 17:39:55.411 BluetoothLE-Explore[8424:6934992] Service found with UUID: 6217FF49-AC7B-547E-EECF-016A06970BA9
2015-01-26 17:39:55.527 BluetoothLE-Explore[8424:6934992] =========== 2 Characteristics of Heart Rate service 
2015-01-26 17:39:55.528 BluetoothLE-Explore[8424:6934992]  2A37 
2015-01-26 17:39:55.529 BluetoothLE-Explore[8424:6934992]  2A38 
2015-01-26 17:39:55.529 BluetoothLE-Explore[8424:6934992] === Finished set notification ===
2015-01-26 17:39:55.768 BluetoothLE-Explore[8424:6934992] =========== 7 Characteristics of Device Information service 
2015-01-26 17:39:55.769 BluetoothLE-Explore[8424:6934992]  System ID 
2015-01-26 17:39:55.769 BluetoothLE-Explore[8424:6934992]  Model Number String 
2015-01-26 17:39:55.769 BluetoothLE-Explore[8424:6934992]  Serial Number String 
2015-01-26 17:39:55.770 BluetoothLE-Explore[8424:6934992]  Firmware Revision String 
2015-01-26 17:39:55.770 BluetoothLE-Explore[8424:6934992]  Hardware Revision String 
2015-01-26 17:39:55.770 BluetoothLE-Explore[8424:6934992]  Software Revision String 
2015-01-26 17:39:55.771 BluetoothLE-Explore[8424:6934992]  Manufacturer Name String 
2015-01-26 17:39:55.771 BluetoothLE-Explore[8424:6934992] === Finished set notification ===
2015-01-26 17:39:55.887 BluetoothLE-Explore[8424:6934992] =========== 1 Characteristics of Battery service 
2015-01-26 17:39:55.888 BluetoothLE-Explore[8424:6934992]  Battery Level 
2015-01-26 17:39:55.888 BluetoothLE-Explore[8424:6934992] === Finished set notification ===
2015-01-26 17:39:56.007 BluetoothLE-Explore[8424:6934992] =========== 1 Characteristics of 6217FF49-AC7B-547E-EECF-016A06970BA9 service 
2015-01-26 17:39:56.008 BluetoothLE-Explore[8424:6934992]  6217FF4A-B07D-5DEB-261E-2586752D942E 
2015-01-26 17:39:56.008 BluetoothLE-Explore[8424:6934992] === Finished set notification ===

Heart Rate service來說明,它提供了2A372A38的屬性,從Bluetooth Characteristics查詢到:

AssignedNumber Specification Name
2A38 Body Sensor Location
2A37 Heart Rate Measurement

2A38來設定目前心跳表的所在位置,2A37則是讀取心跳的資料,其中有一些細節過程依照規格的表示方式去做讀、寫取得資訊與設定就能取得Polar H7提供的心跳資料。

不管如何要先知道Service的類型後再去尋得Characteristic的屬性,在CoreBluetooth使用上這兩種是互相配合使用的,後面的介紹中仍然會以Polar H7為範例繼續了解如何與它來進行溝通。

範例程式