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为范例继续了解如何与它来进行沟通。

范例程式