11.5. Соединения¶
Как только центральное устройство выбирает периферийное устройство из потока рекламных пакетов и отправляет ему connect request, обе стороны выходят из режима рекламы / сканирования и переходят в режим соединения. Теперь радиомодуль планирует свою активность на каналах данных канального уровня, псевдослучайно перескакивая между ними по последовательности, согласованной во время установления соединения. Всё, что находится выше канального уровня – GATT, безопасность, L2CAP – работает поверх соединения, которое устанавливается здесь.
11.5.1. Событие соединения¶
Два устройства в BLE-соединении не передают данные непрерывно. Они согласуют connection interval, и при каждом интервале обе стороны пробуждают радиомодуль, обмениваются всеми пакетами из очереди, подтверждают полученное и снова засыпают. Каждый такой обмен называется connection event.
Радиомодуль на каждой стороне активен только во время кратких событий соединения, всё остальное время он спит. Периферийное устройство может пропускать события при использовании peripheral latency.¶
Числа, управляющие этим, согласуются во время установления соединения, и канальный уровень обеспечивает их соблюдение. Они видны приложению как со стороны запроса в виде регулируемых параметров, так и в виде итоговых значений, сообщаемых обратно.
Connection interval. От 7,5 мс до 4 с, с шагом 1,25 мс. Центральное устройство выбирает значение, запрошенное периферийным устройством, если запрос не является необоснованным. Более короткие интервалы доставляют данные с меньшей задержкой ценой большей радиоактивности; более длинные экономят энергию, но делают каждый цикл обмена медленнее.
Peripheral latency. Неотрицательное целое число N. Периферийному устройству разрешено пропускать до N событий соединения, когда ему нечего отправлять, и снова засыпать вместо того, чтобы пробуждать радиомодуль для пустого обмена. Полезно для датчиков, которые пробуждаются для отчёта раз в секунду, но хотят иметь низкий отзывчивый connection interval для редких немедленных сообщений.
Supervision timeout. От 100 мс до 32 с. Если одна из сторон ничего не слышит от другой в течение этого времени, соединение объявляется потерянным, и обе стороны возвращаются к рекламе / сканированию. Тайм-аут должен быть больше, чем
connection_interval * (1 + peripheral_latency)– канальный уровень отклоняет значения, нарушающие это правило.
aioble.Device.connect() принимает min_conn_interval_us и max_conn_interval_us, чтобы центральное устройство могло запросить определённый диапазон; фактическое значение, на котором остановился радиомодуль, можно прочитать через конфигурацию канального уровня после установления соединения.
11.5.2. Что означают «центральное» и «периферийное» внутри соединения¶
Роли, установленные во время рекламы, сохраняются после установления соединения:
Центральное устройство управляет таймингом – оно владеет ведущей стороной последовательности перескоков и событиями соединения.
Периферийное устройство реактивно. Оно может запросить изменение параметров соединения (например, более медленный интервал для экономии энергии), но центральное устройство решает, принять ли его.
Роли не зависят от того, кто размещает базу данных GATT, что является отдельной осью. По соглашению периферийное устройство является также GATT-сервером, а центральное устройство – GATT-клиентом, но BLE позволяет любой стороне размещать GATT-сервисы. Камеры почти всегда следуют этому соглашению: периферийное устройство + сервер для приложений типа «камера публикует данные», центральное устройство + клиент для приложений типа «камера читает с датчика».
11.5.3. Максимальный размер передаваемого блока (MTU)¶
Канальный уровень по умолчанию переносит короткие пакеты – 27 байт полезной нагрузки, из которых только 23 доступны для GATT. Этого достаточно для небольшого показания или короткой команды, но крайне мало для чего-либо многобайтового. Обе стороны могут согласовать увеличение этого значения вплоть до предела, поддерживаемого прошивкой радиомодуля (обычно несколько сотен байт на современных контроллерах).
API aioble управляет согласованием через aioble.DeviceConnection.exchange_mtu(), а результат становится доступным в атрибуте mtu. Бо́льшие значения MTU означают меньше циклов обмена для любого значения больше ~20 байт ценой небольшого расхода памяти буфера.
11.5.4. Время жизни¶
Соединение длится до тех пор, пока не произойдёт одно из следующего:
одна из сторон вызывает
disconnect(),срабатывает supervision timeout (выход за пределы диапазона, выключенный радиомодуль, сбой партнёра), или
явный сбой канального уровня (несоответствие шифрования, отклонение сопряжения).
Когда соединение разрывается, каждая операция GATT, поставленная в очередь или выполняемая на нём, вызывает aioble.DeviceDisconnectedError, и все блоки async with connection, в которых находится приложение, корректно завершаются. Периферийное устройство обычно реагирует возвратом к aioble.advertise() и ожиданием следующего центрального устройства; центральное устройство реагирует либо повторным сканированием, либо передачей информации о разрыве соединения приложению.
Время жизни – одна из причин, по которой aioble полезен. Синхронному BLE API пришлось бы предоставлять функции обратного вызова для разрыва соединения и маски событий; версия на asyncio превращает разрывы в исключения внутри сопрограммы, которая ожидала операцию, для чего и предназначена очистка async with.