Чтение GATT-характеристик Bluetooth устройства
Привет, хабраюзеры! Работая над своей ANE библиотекой для работы с Bluetooth LE в AIR приложении для iOS+OSX, обнаружил что помимо ваших собственных сервисов и характеристик для обмена информацией, у bluetooth-устройств есть стандартные. Статья о том, как считывать информацию с этих характеристик. Скажу сразу я не большой знаток bluetooth и всего что с ним связано, и для мне все это в новинку :) Поехали…
Сканируя сервисы и характеристики своего macbook, увидел следующие сервисы: UUID: 180A — Device Information UUID: D0611E78-BBB4–4591-A5F8–487910AE4366 — Continuity … Сервис Continuity Сервис Continuity служит для передачи данных между связанными Apple устройствами, подробнее здесь: www.apple.com/ru/ios/whats-new/continuity/. Если будет время разобраться в формате передаваемых данных — напишу об этом отдельный пост.Сервис 180A (Device Information) Рассмотрим сервис 180A — информация об устройстве. Этот сервис является часть GATT-профиля. Открываем страницу GATT-сервисов, находим сервис по идентификатору 180A. В списке доступных указаны различные характеристики: Manufacturer Name String Model Number String … и еще много всего Конкретно мое устройство показало только две доступные характеристики: UUID: 2A29 — Manufacturer Name String UUID: 2A24 — Model Number String Открываем страницу GATT-характеристик, находим там нужную характеристику по uuid, например 2A29. В описании сказано что характеристика имеет одно единственное поле и оно имеет формат utf8s: Это значит что прочитать значение в AIR приложении можно следующим способом: var bytes: ByteArray = …; var string: String = bytes.readUTFBytes (bytes.bytesAvailable); В моем случае я получил значения: 2A29 — Apple Inc 2A24 — MacBookPro10,2 С этими характеристиками было все просто, идем дальше. Попробуем теперь сканировать iOS устройство и заглянуть какие данные оно предоставляет. Мой iPhone показал мне следующие сервисы: UUID: 180F UUID: 1805 UUID: 7905F431-B5CE-4E99-A40F-4B1E122D00D0 … Сервис 7905F431-B5CE-4E99-A40F-4B1E122D00D0, это сервис центра уведомлений Apple, подробнее здесь: developer.apple.com/library/ios/documentation/CoreBluetooth/Reference/AppleNotificationCenterServiceSpecification/Specification/Specification.html. Будет время, попробую разобраться в формате данных и напишу отдельный пост по работе с bluetooth-сервисами устройств Apple.
Сервис 180F (Battery Service) Сервис 180F — это информация о заряде батареи. Этот сервис имеет одну единственную характеристику 2A19, в описании которой сказано что характеристика имеет одно единственное поле формата uint8: Прочитать эту информацию в AIR приложении можно так: var bytes: ByteArray = …; var level: int = bytes.readByte (); Получим значение от 0 до 100, соответствующее уровню заряда батареи устройства.Сервис 1805 (Current Time Service) Как видим из описания сервиса 1805 — это информация о текущем времени. Мое iOS устройство показало только две характеристики у этого сервиса: UUID: 2A0F — Local Time Information UUID: 2A2B — Current Time Характеристика 2A0F (Local Time Information) Характеристика 2A0F имеет два поля: Открываем описание первого поля Time Zone и видим что оно содержит в себе одно поле формата sint8.
Второе поле у сервиса 2A0F это Daylight Saving Time — информация о переходе на летнее время, формат: uint8.
Итак, чтобы прочитать характеристику 2A0F в AIR приложении используем следующий код:
var bytes: ByteArray = …;
var timeZoneValue: int = bytes.readByte (); // считываем Time Zone
var dstValue: int = bytes.readUnsignedByte (); // считываем Daylight Saving Time
В моем случае я получил значения:
TimeZone: 12
Daylight Saving Time: 0
Значение 12 в поле TimeZone соответствует временной зоне UTC+3:00, согласно XML файлу: Список временных зон в XML
cкачать который можно в описании поля Time Zone нажав кнопку Download / View напротив имени поля.Характеристика 2A2B (Current Time) Характеристика 2A2B представляет текущее время на устройстве, и она имеет многоуровневую вложенность полей, ознакомиться с описаниями и форматами которых вы можете самостоятельно. Я приведу только код, для считывания полной информации о текущем времени устройства: var bytes: ByteArray = …; bytes.endian = Endian.LITTLE_ENDIAN; // var year: int = b.readUnsignedShort (); // год var month: int = b.readUnsignedByte (); // месяц (начинается с 1) var day: int = b.readUnsignedByte (); // день (начинается с 1) var hours: int = b.readUnsignedByte (); // часы var minutes: int = b.readUnsignedByte (); // минуты var seconds: int = b.readUnsignedByte (); // секунды // var dayOfWeek: int = b.readUnsignedByte (); // день недели (начинается с 0) var fraction: int = b.readUnsignedByte (); // миллисекунды var adjustReason: int = b.readUnsignedByte (); // ??? Здесь есть несколько важных моментов.Первое: в примечаниях всех GATT спецификаций сказано:
The fields in the above table are in the order of LSO to MSO. Where LSO = Least Significant Octet and MSO = Most Significant Octet. Это значит что в ByteArray первым идет младший байт, в AIR это можно указать с помощью свойства endian: bytes.endian = Endian.LITTLE_ENDIAN; Второе: поле fraction, как следует из описания — это 1/256я секунды, т.е. чтобы получить миллисекунды пишем код:
var milliseconds: int = Math.floor (fraction/256×1000); И третье: я так и не разобрался что такое Adjust Reason. Кто знает — поделитесь информацией :).
GATT сервисы GATT характеристики Видео, демонстрирующие чтение GATT-характеристик с OSX и iOS устройств в AIR приложении ANE библиотека для работы с Bluetooth в AIR приложении. Там же есть готовые iOS и OSX приложения для сканирования сервисов и получения информации с имеющихся характеристик