适用于Android,iOS和Win8的蓝牙低功耗连接参数

时间:2014-03-19 17:58:55

标签: android ios7 bluetooth bluetooth-lowenergy android-bluetooth

我一直在寻找所有这三个操作平台所需的蓝牙连接参数。我在这个项目中使用HOGP(Bluetooth over HID GATT)配置文件。

我的项目是我自己用BLE模块编写的嵌入式系统,我可以控制以下连接参数。

  1. 连接间隔最小
  2. 连接间隔最大
  3. Slave Latency
  4. 监督超时
  5. 广告间隔敏感
  6. 广告Interval Max
  7. 我要连接的目标设备将满足与Android> = 4.3,iOS7和> = Win 8.1的连接。

    Apple非常友好地在下面的链接中提供了包含相应参数的文档。我无法找到有关Android和Win 8的任何信息。

    https://developer.apple.com/hardwaredrivers/bluetoothdesignguidelines.pdf

    iOS7的当前工作设置完全通过与免费软件lightBlue的双向通信测试如下。我的iOS7嵌入式代码和主机软件可以使用。

    1. 连接间隔最小30毫秒
    2. 连接间隔最大56.25ms
    3. Slave Latency 3
    4. 监督超时5000毫秒
    5. 我从另一个堆栈溢出页面发现,据称android可以通过以下链接在7.5ms连接间隔上工作。

      1. Android BLE Connection time interval
      2. http://processors.wiki.ti.com/index.php/Bluetooth_SensorTag?DCMP=lprf-stdroid&HQS=lprf-stdroid-pr-wiki1#Supported_Android_devices
      3. 不幸的是,Apple iOS规范的第二个要求是" IntervalMin≥20ms"。

        我不理解这些范围或如何解释它们?如果我将Interval min设置为7.5ms for Android不会使苹果要求无效吗?如果可能的话,我怎样才能满足两个系统和Win8?

        我的理解是从设备在最小值和最大值之间提供建议设置,主设备(智能手机)提醒用户该范围内的实际选定值。

        我对这个问题有任何帮助,并希望这篇文章可以让其他人考虑到BLE相当新的和不完整的知识基础。

        提前致谢!

3 个答案:

答案 0 :(得分:13)

首先,连接间隔定义了一个时间窗口,在此期间两个设备使用相同的频率来传输数据。总共有37个数据通道,连接的设备每个连接间隔跳过它们。

因此,两个设备必须从一开始就这些参数的精确值达成一致,以便同步,即连接。

其次,当建立连接时,主(或中央)发送它支持的连接参数。另一个设备(或外围设备)只是盲目地接受它们。 iOS默认情况下将连接间隔设置为30毫秒。建立连接后,外设可以根据Apple提供的指南,通过定义最小值和最大值来请求更新连接参数。接收部分,在这种情况下读取iOS,将在[min; max]之间选择最适合它的任何内容,并将发送回具有它已选择的精确值的响应。如果值不符合指南,它也可以拒绝请求。

最后,7.5ms是蓝牙规范定义的连接间隔的最小长度。最大值为4秒。它越低,带宽越高,但功耗越高。与较高值相反。最佳值取决于具体应用。考虑到您使用HID配置文件,我认为延迟对您很重要。

iOS表示它支持低至20毫秒的连接间隔(虽然我发现很难实现这一点),但在您的情况下(HID配置文件),它们也允许11.25毫秒。

希望有所帮助。

答案 1 :(得分:4)

要修改Android中的参数(从中心到外围请求),您可以执行以下操作:

private String CONN_SERVICE_UUID = "00001800-0000-1000-8000-00805f9b34fb";
private static final UUID CONN_CHARACTERISTIC_UUID = UUID.fromString("00002a04-0000-1000-8000-00805F9B34FB");
private static final int CONN_INTERVAL = 0x0006;
private static final int SUPERVISION_TIMEOUT = 0x000A;
private void findServiceForConnectionParams(List<BluetoothGattService> gattServices){
    BluetoothGattService connGattService = filterServices(gattServices, CONN_SERVICE_UUID);
    if (connGattService != null) {
        setConnectionInterval(connGattService);
    }
}
private void setConnectionInterval(BluetoothGattService gattService) {
    if (gattService == null) {
        Log.e(TAG, "setConnectionInterval. Gatt service is null!");
        return;
    }
    BluetoothGattCharacteristic connCharacteristic = 
            gattService.getCharacteristic(CONN_CHARACTERISTIC_UUID);
    if (connCharacteristic != null) {
        byte[] value = { (byte) (CONN_INTERVAL & 0x00FF), // gets LSB of 2 byte value
                (byte) ((CONN_INTERVAL & 0xFF00) >> 8), // gets MSB of 2 byte value
                (byte) (CONN_INTERVAL & 0x00FF),
                (byte) ((CONN_INTERVAL & 0xFF00) >> 8),
                0, 0,
                (byte) (SUPERVISION_TIMEOUT & 0x00FF),
                (byte) ((SUPERVISION_TIMEOUT & 0xFF00) >> 8)
        };
        connCharacteristic.setValue(value);
        boolean status = mBluetoothGatt.writeCharacteristic(connCharacteristic);
        Log.d(TAG, "setConnectionInterval. Change connection interval result: " + status);
    } else {
        Log.e(TAG, "setConnectionInterval. Connection characteristic is null!");
    }

}
private BluetoothGattService filterServices(List<BluetoothGattService> gattServices, String targetUuid) {
    for(BluetoothGattService gattService : gattServices){
        String serviceUUID = gattService.getUuid().toString();
        Log.i(TAG, "serviceUUID: " + serviceUUID);

        if(serviceUUID.equals(targetUuid)){
            Log.i(TAG, "serviceUUID matches! UUID: " + serviceUUID + " Type: " + gattService.getType());
            // no needed, just to check which characteristics are offered
            for(BluetoothGattCharacteristic characteristic : gattService.getCharacteristics()) {
                Log.i(TAG, "serviceUUID characteristics: " + characteristic.getUuid().toString());
            }
            return gattService;
        }
    }
    return null;
}

我必须说,虽然使用Android 5设备作为外围设备和中央设备,但它不起作用,因为Generic Acces Service(0x1800)在我的设备中没有提供特性连接参数的特性0x2a04。它只提供0x2a00(设备名称)和0x2a01(外观)。 参考文献:

http://www.cumulations.com/blogs/7/Doing-firmware-upgrade-over-BLE-in-Android

https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.peripheral_preferred_connection_parameters.xml

https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.generic_access.xml

https://farwestab.wordpress.com/2011/02/05/some-tips-on-android-and-bluetooth/

答案 2 :(得分:0)

我认为此特性仅用于向中央设备提供信息。这就是为什么它通常是只读的(对我来说,和cxphong)。宾根的回答并不普遍,我不确定它是否意味着以这种方式工作。有人真的让它在特定的设备上工作吗?

Android和iOS似乎没有查阅此只读特性中的信息,因此我不确定它是否非常有用。

对于赛普拉斯外设和Android中心,下面介绍了对我有用的功能。类似的方法应该适用于其他设备。

  1. 在外围设备上,在CYBLE_GAP_CONN_UPDATE_PARAM_T结构中定义首选连接参数&#34;参数&#34;。
  2. 在GATT连接之后,在CYBLE_EVT_GATT_CONNECT_IND事件处理程序(例如)中,调用CyBle_L2capLeConnectionParamUpdateRequest(connHandle,&amp; params)。
  3. 在中央一侧,无所事事。收到请求后,它会稍后启动参数更新。

    干杯,

    大卫