Привет, читатели!
Работая над своей ANE библиотекой для работы с Bluetooth LE в AIR приложении для iOS+OSX, обнаружил что помимо ваших собственных сервисов и характеристик для обмена информацией, у bluetooth-устройств есть стандартные. Статья о том, как считывать информацию с этих характеристик. Скажу сразу я не большой знаток bluetooth и всего что с ним связано, и для мне все это в новинку :) Поехали…
Сервисы и характеристики OSX устройства
Сканируя сервисы и характеристики своего 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 устройства
Попробуем теперь сканировать 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 version="1.0" encoding="UTF-8"?>
<!-- Copyright 2011 Bluetooth SIG, Inc. All rights reserved. -->
<Characteristic xsi:noNamespaceSchemaLocation="http://schemas.bluetooth.org/Documents/characteristic.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Time Zone" type="org.bluetooth.characteristic.time_zone" uuid="2A0E">
<InformativeText>
</InformativeText>
<Value>
<Field name="Time Zone">
<Requirement>Mandatory</Requirement>
<Format>sint8</Format>
<Minimum>-48</Minimum>
<Maximum>56</Maximum>
<Enumerations>
<Enumeration key="-48" value="UTC-12:00" />
<Enumeration key="-44" value="UTC-11:00" />
<Enumeration key="-40" value="UTC-10:00" />
<Enumeration key="-38" value="UTC-9:30" />
<Enumeration key="-36" value="UTC-9:00" />
<Enumeration key="-32" value="UTC-8:00" />
<Enumeration key="-28" value="UTC-7:00" />
<Enumeration key="-24" value="UTC-6:00" />
<Enumeration key="-20" value="UTC-5:00" />
<Enumeration key="-18" value="UTC-4:30" />
<Enumeration key="-16" value="UTC-4:00" />
<Enumeration key="-14" value="UTC-3:30" />
<Enumeration key="-12" value="UTC-3:00" />
<Enumeration key="-8" value="UTC-2:00" />
<Enumeration key="-4" value="UTC-1:00" />
<Enumeration key="0" value="UTC+0:00" />
<Enumeration key="4" value="UTC+1:00" />
<Enumeration key="8" value="UTC+2:00" />
<Enumeration key="12" value="UTC+3:00" />
<Enumeration key="14" value="UTC+3:30" />
<Enumeration key="16" value="UTC+4:00" />
<Enumeration key="18" value="UTC+4:30" />
<Enumeration key="20" value="UTC+5:00" />
<Enumeration key="22" value="UTC+5:30" />
<Enumeration key="23" value="UTC+5:45" />
<Enumeration key="24" value="UTC+6:00" />
<Enumeration key="26" value="UTC+6:30" />
<Enumeration key="28" value="UTC+7:00" />
<Enumeration key="32" value="UTC+8:00" />
<Enumeration key="35" value="UTC+8:45" />
<Enumeration key="36" value="UTC+9:00" />
<Enumeration key="38" value="UTC+9:30" />
<Enumeration key="40" value="UTC+10:00" />
<Enumeration key="42" value="UTC+10:30" />
<Enumeration key="44" value="UTC+11:00" />
<Enumeration key="46" value="UTC+11:30" />
<Enumeration key="48" value="UTC+12:00" />
<Enumeration key="51" value="UTC+12:45" />
<Enumeration key="52" value="UTC+13:00" />
<Enumeration key="56" value="UTC+14:00" />
</Enumerations>
<AdditionalValues>
<Enumeration key="-128" value="time zone offset is not known"/>
</AdditionalValues>
</Field>
</Value>
</Characteristic>
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 приложения для сканирования сервисов и получения информации с имеющихся характеристик
Автор: FlashPress