Параметры низкоэнергетического подключения Bluetooth для Android, iOS и Win8
Я искал все необходимые параметры соединения Bluetooth, которые будут работать на всех трех операционных платформах. Я использую профиль HOGP (Bluetooth over HID GATT) для этого проекта.
Мой проект представляет собой встроенную систему, написанную мной с модулем BLE, в которой я контролирую следующие параметры для соединения.
- Интервал подключения Min
- Интервал подключения Макс.
- Slave Latency
- Тайм-аут надзора
- Интервал рекламы Мин.
- Интервал рекламы Макс.
Мои целевые устройства для подключения будут поддерживать соединения с Android >= 4.3, iOS7 и >= Win 8.1.
Apple была достаточно любезна, чтобы предоставить документ с соответствующими параметрами на стр. 22 в приведенной ниже ссылке. Я не смог найти информацию об Android и Win 8.
https://developer.apple.com/hardwaredrivers/bluetoothdesignguidelines.pdf
Мои текущие рабочие настройки для iOS7 полностью протестированы с двунаправленной связью с бесплатным LightBlue следующим образом. Мой встроенный код и хост-программное обеспечение для iOS7 работает.
- Интервал подключения Min 30ms
- Интервал подключения Макс. 56.25мс
- Slave Latency 3
- Тайм-аут контроля 5000 мс
Я нашел из другой страницы, что андроид, по-видимому, работает с интервалом соединения 7.5ms из следующих ссылок.
К сожалению, второе требование от спецификации iOS от Apple заключается в том, что "Interval Min ≥ 20 ms".
Я не понимаю эти диапазоны или как они интерпретируются? Если я установил интервал min на 7,5 мс для Android, это не значит, что явные требования к ядам? Как я могу удовлетворить обе системы, а также Win8, если это возможно?
Я понимаю, что подчиненное устройство предлагает предлагаемую настройку между min и max, а ведущий (смартфон) предупреждает пользователя о фактическом выбранном значении в этом диапазоне.
Я высоко оценил любую помощь в этом вопросе и надеюсь, что этот пост может принести пользу другим, учитывая довольно новую и неполную базу знаний для BLE.
Спасибо заранее!
Ответы
Ответ 1
Во-первых, интервал подключения определяет временное окно, в течение которого оба устройства используют одну и ту же частоту для передачи данных. Всего имеется 37 каналов данных, а подключенные устройства через них проходят через каждый интервал соединения.
Таким образом, оба устройства должны согласовывать точные значения этих параметров с самого начала, чтобы быть в синхронизации, то есть подключены.
Во-вторых, когда соединение установлено, главный (или Центральный) отправляет параметры соединения, которые он поддерживает. Другое устройство (или периферийное) просто слепо принимает их. iOS по умолчанию устанавливает интервал подключения до 30 мс. После установления соединения периферийное устройство может запросить обновление параметров соединения, указав значения min и max в соответствии с рекомендациями, которые Apple предоставила вам. Принимающая часть, читающая iOS в этом случае, выберет все, что она найдет для нее между [min; max], и отправит ответ обратно с точными значениями, которые он выбрал. Он также может отклонить запрос, если значения не соответствуют рекомендациям.
Наконец, 7.5ms - это минимальная длина интервала соединения, определенного спецификацией Bluetooth. Максимальное значение - 4 с. Чем ниже, тем выше пропускная способность, но более высокая потребляемая мощность. И наоборот в более высоких значениях. Наилучшее значение зависит от конкретного приложения. Учитывая, что вы работаете с профилем HID, я предполагаю, что для вас важна латентность.
iOS говорит, что поддерживает интервалы подключения до 20 мс (хотя мне было трудно это сделать несколько раз), но в вашем случае (HID-профиль) они также допускают 11,25 мс.
Надеюсь, что это поможет.
Ответ 2
Чтобы изменить параметры на Android (запросив от Central to Peripheral), вы можете сделать что-то вроде этого:
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/
Ответ 3
Я считаю, что эта характеристика предназначена только для предоставления информации центральному устройству. Вот почему он обычно доступен только для чтения (для меня и для cxphong). Ответ Бингена не работает повсеместно, и я не уверен, что он должен работать таким образом. Кто-нибудь действительно получил его для работы на определенном устройстве?
Похоже, что Android и iOS не обращаются к информации в этой характеристике только для чтения, и поэтому я не уверен, что она очень полезна.
Что работает для меня, описано ниже, для периферийных устройств Cypress и Android. Аналогичный подход должен работать с другими устройствами.
- На периферии определить предпочтительные параметры соединения в параметрах структуры CYBLE_GAP_CONN_UPDATE_PARAM_T.
- После подключения GATT в обработчике событий CYBLE_EVT_GATT_CONNECT_IND (например) вызовите CyBle_L2capLeConnectionParamUpdateRequest (connHandle, & params).
На центральной стороне нечего делать. После того, как он получит запрос, он начнет обновление параметра немного позже.
Приветствия,
Дэвид