bluetooth — низкоуровневый Bluetooth¶
Этот модуль предоставляет интерфейс к встроенному контроллеру Bluetooth. Он поддерживает Bluetooth Low Energy (BLE) в ролях Central, Peripheral, Broadcaster и Observer, а также GATT-сервер и клиент и каналы L2CAP, ориентированные на соединение. Устройство может одновременно работать в нескольких ролях. Также поддерживаются сопряжение (pairing) и привязка (bonding).
Этот API предназначен для соответствия низкоуровневому протоколу Bluetooth и предоставления строительных блоков для более высокоуровневых абстракций, таких как конкретные типы устройств.
Совет
Для большинства приложений предпочтительнее использовать более высокоуровневую библиотеку aioble, которая предоставляет основанную на asyncio обёртку вокруг этого модуля. См. aioble — асинхронный BLE.
class BLE¶
- class bluetooth.BLE¶
Возвращает синглтон-объект BLE.
Конфигурация
- active(active: bool | None = None, /) bool¶
Опционально изменяет активное состояние BLE-радио и возвращает текущее состояние.
Радио должно быть переведено в активное состояние перед использованием любых других методов этого класса.
- config(param: str, /) Any¶
- config(*, **kwargs: Any) None
Получает или задаёт значения конфигурации интерфейса BLE. Для получения значения имя параметра должно быть указано в виде строки в кавычках, и за один раз запрашивается только один параметр. Для задания значений используйте синтаксис с ключевыми словами, при этом за один раз можно задать один или несколько параметров.
В настоящее время поддерживаются следующие значения:
'mac': Текущий используемый адрес в зависимости от текущего режима адресации. Возвращает кортеж(addr_type, addr).См.
gap_scanдля получения подробностей о типе адреса.Это значение может быть запрошено только когда интерфейс в данный момент активен.
'addr_mode': Задаёт режим адресации. Значения:Значение
Имя
Поведение
0x00PUBLIC
Использовать публичный адрес контроллера.
0x01RANDOM
Использовать сгенерированный статический адрес.
0x02RPA
Использовать разрешаемые приватные адреса.
0x03NRPA
Использовать неразрешаемые приватные адреса.
По умолчанию интерфейс будет использовать адрес PUBLIC, если он доступен, в противном случае будет использован адрес RANDOM.
'gap_name': Получает/задаёт имя GAP-устройства, используемое сервисом Generic Access (UUID0x1800), характеристикой Device Name (UUID0x2a00). Его можно задавать в любое время и изменять несколько раз.'rxbuf': Получает/задаёт размер в байтах внутреннего буфера, используемого для хранения входящих событий. Этот буфер является глобальным для всего драйвера BLE и поэтому обрабатывает входящие данные для всех событий, включая все характеристики. Его увеличение позволяет лучше обрабатывать пакетные входящие данные (например, результаты сканирования) и принимать значения характеристик большего размера.'mtu': Получает/задаёт MTU, который будет использоваться во время обмена ATT MTU. Результирующий MTU будет минимумом из этого значения и MTU удалённого устройства. Обмен ATT MTU не происходит автоматически (если только удалённое устройство не инициирует его) и должен быть запущен вручную с помощьюgattc_exchange_mtu. Используйте событие_IRQ_MTU_EXCHANGED, чтобы узнать MTU для данного соединения.'bond': Задаёт, будет ли включена привязка (bonding) во время сопряжения. Когда включено, запросы на сопряжение будут устанавливать флаг «bond», и ключи будут сохраняться обоими устройствами.'mitm': Задаёт, требуется ли защита от MITM для сопряжения.'io': Задаёт возможности ввода/вывода (I/O) этого устройства.Доступны следующие варианты:
Константа
Значение
Возможность
_IO_CAPABILITY_DISPLAY_ONLY0
Только дисплей
_IO_CAPABILITY_DISPLAY_YESNO1
Дисплей с вводом да/нет
_IO_CAPABILITY_KEYBOARD_ONLY2
Только клавиатура
_IO_CAPABILITY_NO_INPUT_OUTPUT3
Нет ввода или вывода
_IO_CAPABILITY_KEYBOARD_DISPLAY4
Клавиатура и дисплей
'le_secure': Задаёт, требуется ли сопряжение «LE Secure». По умолчанию false (т. е. разрешается «Legacy Pairing»).
Обработка событий
- irq(handler: Callable[[int, Tuple], Any | None], /) None¶
Регистрирует функцию обратного вызова для событий от стека BLE. handler принимает два аргумента:
event(который будет одним из кодов ниже) иdata(который представляет собой специфичный для события кортеж значений).Примечание: В качестве оптимизации для предотвращения ненужных аллокаций записи
addr,adv_data,char_data,notify_dataиuuidв кортежах являются доступными только для чтения экземплярами memoryview, указывающими на внутренний кольцевой буфер модуляbluetooth, и действительны только во время вызова функции-обработчика IRQ. Если вашей программе нужно сохранить одно из этих значений для доступа после возврата из обработчика IRQ (например, сохранив его в экземпляре класса или глобальной переменной), то ей нужно сделать копию данных, используя либоbytes(), либоbluetooth.UUID(), например так:connected_addr = bytes(addr) # equivalently: adv_data, char_data, or notify_data matched_uuid = bluetooth.UUID(uuid)
Например, обработчик IRQ для результата сканирования может проверить
adv_data, чтобы решить, является ли это правильным устройством, и только затем скопировать данные адреса для использования в другом месте программы. А для вывода данных изнутри обработчика IRQ потребуетсяprint(bytes(addr)).Обработчик обычно выполняет диспетчеризацию по коду события и распаковывает специфичный для события кортеж полезной нагрузки:
def bt_irq(event, data): if event == _IRQ_CENTRAL_CONNECT: conn_handle, addr_type, addr = data ... elif event == _IRQ_SCAN_RESULT: addr_type, addr, adv_type, rssi, adv_data = data ...
Каждый код события, доставляемая им полезная нагрузка и краткое описание перечислены ниже. Для событий, у которых упоминается поле
status, значениеstatusравно0при успехе и зависящему от реализации ненулевому значению при неудаче.Константа
Значение
Событие
Кортеж полезной нагрузки
_IRQ_CENTRAL_CONNECT1
Центральное устройство подключилось к этому периферийному устройству.
(conn_handle, addr_type, addr)_IRQ_CENTRAL_DISCONNECT2
Центральное устройство отключилось от этого периферийного устройства.
(conn_handle, addr_type, addr)_IRQ_GATTS_WRITE3
Подключённый клиент произвёл запись в локальную характеристику или дескриптор. Используйте
gatts_readдля получения нового значения.(conn_handle, attr_handle)_IRQ_GATTS_READ_REQUEST4
Подключённый клиент выполнил чтение. Верните ненулевой код ошибки из таблицы ниже, чтобы запретить чтение, или
0/None, чтобы принять его.(conn_handle, attr_handle)_IRQ_SCAN_RESULT5
Во время активного сканирования был получен один рекламный (advertising) пакет.
(addr_type, addr, adv_type, rssi, adv_data)_IRQ_SCAN_DONE6
Текущее сканирование завершилось — либо потому что истекла настроенная продолжительность, либо потому что был вызван
gap_scan(None).()_IRQ_PERIPHERAL_CONNECT7
Ранее выполненный
gap_connectзавершился успешно.(conn_handle, addr_type, addr)_IRQ_PERIPHERAL_DISCONNECT8
Подключённое периферийное устройство отключилось.
(conn_handle, addr_type, addr)_IRQ_GATTC_SERVICE_RESULT9
Один сервис был найден с помощью
gattc_discover_services.(conn_handle, start_handle, end_handle, uuid)_IRQ_GATTC_SERVICE_DONE10
Обнаружение сервисов завершено.
(conn_handle, status)_IRQ_GATTC_CHARACTERISTIC_RESULT11
Одна характеристика была найдена с помощью
gattc_discover_characteristics.(conn_handle, end_handle, value_handle, properties, uuid)_IRQ_GATTC_CHARACTERISTIC_DONE12
Обнаружение характеристик завершено.
(conn_handle, status)_IRQ_GATTC_DESCRIPTOR_RESULT13
Один дескриптор был найден с помощью
gattc_discover_descriptors.(conn_handle, dsc_handle, uuid)_IRQ_GATTC_DESCRIPTOR_DONE14
Обнаружение дескрипторов завершено.
(conn_handle, status)_IRQ_GATTC_READ_RESULT15
Ранее выполненный
gattc_readвернул данные.(conn_handle, value_handle, char_data)_IRQ_GATTC_READ_DONE16
Ранее выполненный
gattc_readзавершился.(conn_handle, value_handle, status)_IRQ_GATTC_WRITE_DONE17
Ранее выполненный
gattc_writeбыл подтверждён.(conn_handle, value_handle, status)_IRQ_GATTC_NOTIFY18
Удалённый сервер отправил (неподтверждаемое) уведомление (notification).
(conn_handle, value_handle, notify_data)_IRQ_GATTC_INDICATE19
Удалённый сервер отправил (подтверждаемое) указание (indication).
(conn_handle, value_handle, notify_data)_IRQ_GATTS_INDICATE_DONE20
Ранее отправленное указание было подтверждено клиентом (или истёк его тайм-аут).
(conn_handle, value_handle, status)_IRQ_MTU_EXCHANGED21
Обмен ATT MTU завершён (инициированный любой из сторон).
(conn_handle, mtu)_IRQ_L2CAP_ACCEPT22
Удалённое устройство запросило L2CAP-соединение на PSM, который прослушивает это устройство. Верните ненулевое целое число, чтобы отклонить, или
0/None, чтобы принять.(conn_handle, cid, psm, our_mtu, peer_mtu)_IRQ_L2CAP_CONNECT23
L2CAP-канал теперь установлен — либо принятием входящего запроса, либо завершением исходящего
l2cap_connect.(conn_handle, cid, psm, our_mtu, peer_mtu)_IRQ_L2CAP_DISCONNECT24
L2CAP-канал был отключён.
statusравен0для чистого отключения или ненулевому значению, если исходящая попытка соединения не удалась.(conn_handle, cid, psm, status)_IRQ_L2CAP_RECV25
На L2CAP-канал поступили данные. Вызовите
l2cap_recvintoдля их чтения.(conn_handle, cid)_IRQ_L2CAP_SEND_READY26
Предыдущий вызов
l2cap_send, вернувшийFalse, опустошился, и канал снова готов. Ненулевойstatusозначает, что буфер передачи переполнился, и приложение должно повторно отправить данные.(conn_handle, cid, status)_IRQ_CONNECTION_UPDATE27
Удалённое устройство обновило параметры соединения (интервал, задержку, тайм-аут супервизии).
(conn_handle, conn_interval, conn_latency, supervision_timeout, status)_IRQ_ENCRYPTION_UPDATE28
Состояние шифрования соединения изменилось, обычно после завершения сопряжения или привязки.
(conn_handle, encrypted, authenticated, bonded, key_size)_IRQ_GET_SECRET29
Стек запрашивает сохранённый секрет привязки. Если
keyравенNone, вернитеindex-е по счёту сохранённое значение типаsec_type; в противном случае верните значение, связанное с заданным(sec_type, key). ВернитеNone, если ничего не сохранено.(sec_type, index, key)_IRQ_SET_SECRET30
Стек просит приложение сохранить секрет привязки в постоянном хранилище. Верните
Trueпосле сохранения.(sec_type, key, value)_IRQ_PASSKEY_ACTION31
В рамках сопряжения требуется действие с ключом доступа (passkey). Ответьте с помощью
gap_passkey; возможные действия см. в таблице действий с passkey ниже.(conn_handle, action, passkey)Для события
_IRQ_GATTS_READ_REQUESTдоступны следующие коды возврата:Константа
Значение
Значение
_GATTS_NO_ERROR0x00Принять чтение.
_GATTS_ERROR_READ_NOT_PERMITTED0x02Чтение не разрешено.
_GATTS_ERROR_WRITE_NOT_PERMITTED0x03Запись не разрешена.
_GATTS_ERROR_INSUFFICIENT_AUTHENTICATION0x05Клиент не аутентифицирован.
_GATTS_ERROR_INSUFFICIENT_AUTHORIZATION0x08Клиент не авторизован.
_GATTS_ERROR_INSUFFICIENT_ENCRYPTION0x0fКанал не зашифрован.
Для события
_IRQ_PASSKEY_ACTIONдоступны следующие действия:Константа
Значение
Значение
_PASSKEY_ACTION_NONE0
Действие не требуется.
_PASSKEY_ACTION_INPUT2
Предложить пользователю ввести ключ доступа, показанный на удалённом устройстве.
_PASSKEY_ACTION_DISPLAY3
Отобразить 6-значный ключ доступа для ввода на удалённом устройстве.
_PASSKEY_ACTION_NUMERIC_COMPARISON4
Подтвердить, что ключ доступа совпадает с тем, который показан на удалённом устройстве.
Для экономии места в прошивке эти константы не включены в модуль
bluetooth. Добавьте нужные вам из списков выше в свою программу.
Роль Broadcaster (рекламодатель)
- gap_advertise(interval_us: int | None, adv_data: bytes | None = None, *, resp_data: bytes | None = None, connectable: bool = True) None¶
Запускает рекламу (advertising) с указанным интервалом (в микросекундах). Этот интервал будет округлён вниз до ближайших 625 мкс. Чтобы остановить рекламу, установите interval_us в
None.adv_data и resp_data могут быть любого типа, реализующего протокол буфера (например,
bytes,bytearray,str). adv_data включается во все рассылки, а resp_data отправляется в ответ на активное сканирование.Примечание: если adv_data (или resp_data) равны
None, то будут повторно использованы данные, переданные при предыдущем вызовеgap_advertise. Это позволяет рекламодателю возобновить рекламу просто с помощьюgap_advertise(interval_us). Чтобы очистить рекламную полезную нагрузку, передайте пустойbytes, т. е.b''.
Роль Observer (сканер)
- gap_scan(duration_ms: int | None, interval_us: int = 1280000, window_us: int = 11250, active: bool = False, /) None¶
Выполняет операцию сканирования, длящуюся указанную продолжительность (в миллисекундах).
Для бесконечного сканирования установите duration_ms в
0.Чтобы остановить сканирование, установите duration_ms в
None.Используйте interval_us и window_us для опциональной настройки рабочего цикла. Сканер будет работать в течение window_us микросекунд каждые interval_us микросекунд в общей сложности duration_ms миллисекунд. Интервал и окно по умолчанию составляют 1,28 секунды и 11,25 миллисекунды соответственно (фоновое сканирование).
Для каждого результата сканирования будет вызвано событие
_IRQ_SCAN_RESULTс данными события(addr_type, addr, adv_type, rssi, adv_data).Значения
addr_typeуказывают на публичные или случайные адреса:Значение
Имя
Значение
0x00PUBLIC
Публичный адрес устройства.
0x01RANDOM
Случайный адрес (статический, RPA или NRPA; тип закодирован в самом адресе).
Значения
adv_typeсоответствуют спецификации Bluetooth:Значение
Имя
Значение
0x00ADV_IND
Подключаемая и сканируемая ненаправленная реклама.
0x01ADV_DIRECT_IND
Подключаемая направленная реклама.
0x02ADV_SCAN_IND
Сканируемая ненаправленная реклама.
0x03ADV_NONCONN_IND
Неподключаемая ненаправленная реклама.
0x04SCAN_RSP
Ответ на сканирование.
activeможно установить вTrue, если вы хотите получать ответы на сканирование в результатах.Когда сканирование останавливается (либо из-за завершения продолжительности, либо при явной остановке), будет вызвано событие
_IRQ_SCAN_DONE.
Роль Central
Центральное устройство может подключаться к периферийным устройствам, которые оно обнаружило с помощью роли Observer (см.
gap_scan), или к устройствам с известным адресом.- gap_connect(addr_type: int | None, addr: bytes | None = None, scan_duration_ms: int = 2000, min_conn_interval_us: int | None = None, max_conn_interval_us: int | None = None, /) None¶
Подключиться к периферийному устройству.
См.
gap_scanдля получения подробностей о типах адресов.Чтобы досрочно отменить незавершённую попытку соединения, вызовите
gap_connect(None).При успехе будет вызвано событие
_IRQ_PERIPHERAL_CONNECT. При отмене попытки соединения будет вызвано событие_IRQ_PERIPHERAL_DISCONNECT.Устройство будет ждать до scan_duration_ms, чтобы получить рекламную полезную нагрузку от устройства.
Интервал соединения можно настроить в микросекундах с помощью одного или обоих параметров min_conn_interval_us и max_conn_interval_us. В противном случае будет выбран интервал по умолчанию, обычно от 30000 до 50000 микросекунд. Более короткий интервал увеличит пропускную способность за счёт энергопотребления.
Роль Peripheral
Ожидается, что периферийное устройство отправляет подключаемую рекламу (см.
gap_advertise). Обычно оно действует как GATT-сервер, предварительно зарегистрировав сервисы и характеристики с помощьюgatts_register_services.Когда центральное устройство подключается, будет вызвано событие
_IRQ_CENTRAL_CONNECT.Роли Central и Peripheral
- gap_disconnect(conn_handle: int, /) bool¶
Разорвать соединение с указанным дескриптором соединения. Это может быть как центральное устройство, подключившееся к этому устройству (если оно действует как периферийное), так и периферийное устройство, к которому это устройство ранее подключилось (если оно действует как центральное).
При успехе будет вызвано событие
_IRQ_PERIPHERAL_DISCONNECTили_IRQ_CENTRAL_DISCONNECT.Возвращает
False, если дескриптор соединения не был подключён, иTrueв противном случае.
GATT-сервер
GATT-сервер имеет набор зарегистрированных сервисов. Каждый сервис может содержать характеристики, каждая из которых имеет значение. Характеристики также могут содержать дескрипторы, которые сами имеют значения.
Эти значения хранятся локально и доступны по их «дескриптору значения» (value handle), который генерируется во время регистрации сервиса. Их также может читать или записывать удалённое клиентское устройство. Кроме того, сервер может «уведомлять» (notify) о характеристике подключённого клиента через дескриптор соединения.
Устройство в роли Central или Peripheral может функционировать как GATT-сервер, однако в большинстве случаев чаще именно периферийное устройство будет действовать как сервер.
Характеристики и дескрипторы по умолчанию имеют максимальный размер 20 байт (ATT MTU по умолчанию в 23 байта минус 3-байтовый заголовок ATT; больший согласованный MTU сам по себе не увеличивает этот предел). Всё, что клиент в них записывает, будет усечено до этой длины. Однако любая локальная запись увеличит максимальный размер, поэтому, если вы хотите разрешить более крупные записи от клиента в данную характеристику, используйте
gatts_writeпосле регистрации, напримерgatts_write(char_handle, bytes(100)).- gatts_register_services(services_definition: Sequence[Sequence], /) Sequence[Sequence[int]]¶
Настраивает сервер с указанными сервисами, заменяя любые существующие сервисы.
services_definition — это список сервисов, где каждый сервис представляет собой кортеж из двух элементов, содержащий UUID и список характеристик.
Каждая характеристика — это кортеж из двух или трёх элементов, содержащий UUID, значение flags и опционально список дескрипторов.
Каждый дескриптор — это кортеж из двух элементов, содержащий UUID и значение flags.
flags представляют собой побитовую комбинацию (OR) флагов, определённых ниже. Они задают как поведение характеристики (или дескриптора), так и требования к безопасности и приватности.
Возвращаемое значение — это список (по одному элементу на сервис) кортежей (каждый элемент — это дескриптор значения). Дескрипторы характеристик и дескрипторов сведены в один кортеж в том порядке, в котором они определены.
В следующем примере регистрируются два сервиса (Heart Rate и Nordic UART):
bt = bluetooth.BLE() bt.active(True) # Heart Rate service: one Heart Rate Measurement characteristic. HR_SERVICE = ( bluetooth.UUID(0x180D), ( (bluetooth.UUID(0x2A37), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY), ), ) # Nordic UART service: a TX characteristic the client subscribes # to for notifications, and an RX characteristic it writes to. UART_SERVICE = ( bluetooth.UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E'), ( (bluetooth.UUID('6E400003-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY), (bluetooth.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_WRITE), ), ) ((hr,), (tx, rx)) = bt.gatts_register_services( (HR_SERVICE, UART_SERVICE), )
Три дескриптора значений (
hr,tx,rx) можно использовать сgatts_read,gatts_write,gatts_notifyиgatts_indicate.Примечание: Реклама должна быть остановлена перед регистрацией сервисов.
Доступные флаги для характеристик и дескрипторов:
Константа
Значение
Значение
_FLAG_BROADCAST0x0001О характеристике можно вещать (broadcast).
_FLAG_READ0x0002Клиент может читать значение.
_FLAG_WRITE_NO_RESPONSE0x0004Клиент может выполнять запись без ожидания ответа.
_FLAG_WRITE0x0008Клиент может выполнять запись с подтверждаемым ответом.
_FLAG_NOTIFY0x0010Сервер может отправлять уведомления (неподтверждаемые).
_FLAG_INDICATE0x0020Сервер может отправлять указания (подтверждаемые).
_FLAG_AUTHENTICATED_SIGNED_WRITE0x0040Клиент может выполнять подписанные записи.
_FLAG_AUX_WRITE0x0100Расширенные свойства: разрешены записи в очередь/надёжные записи.
_FLAG_READ_ENCRYPTED0x0200Чтение требует зашифрованного канала.
_FLAG_READ_AUTHENTICATED0x0400Чтение требует аутентифицированного (с защитой от MITM) канала.
_FLAG_READ_AUTHORIZED0x0800Чтение требует авторизации на уровне приложения.
_FLAG_WRITE_ENCRYPTED0x1000Запись требует зашифрованного канала.
_FLAG_WRITE_AUTHENTICATED0x2000Запись требует аутентифицированного (с защитой от MITM) канала.
_FLAG_WRITE_AUTHORIZED0x4000Запись требует авторизации на уровне приложения.
Как и в случае с константами событий выше, эти флаги не предоставляются модулем
bluetooth; скопируйте нужные вам в свою программу.
- gatts_read(value_handle: int, /) bytes¶
Читает локальное значение для этого дескриптора (которое было записано либо с помощью
gatts_write, либо удалённым клиентом).
- gatts_write(value_handle: int, data: bytes, send_update: bool = False, /) None¶
Записывает локальное значение для этого дескриптора, которое может быть прочитано клиентом.
Если send_update равно
True, то все подписанные клиенты будут уведомлены (или им будет отправлено указание, в зависимости от того, на что они подписаны и какие операции поддерживает характеристика) об этой записи.
- gatts_notify(conn_handle: int, value_handle: int, data: bytes | None = None, /) None¶
Отправляет запрос на уведомление подключённому клиенту.
Если data равно
None(по умолчанию), то будет отправлено текущее локальное значение (как установлено с помощьюgatts_write).В противном случае, если data не равно
None, то это значение отправляется клиенту в составе уведомления. Локальное значение не будет изменено.Примечание: Уведомление будет отправлено независимо от статуса подписки клиента на эту характеристику.
- gatts_indicate(conn_handle: int, value_handle: int, data: bytes | None = None, /) None¶
Отправляет запрос на указание подключённому клиенту.
Если data равно
None(по умолчанию), то будет отправлено текущее локальное значение (как установлено с помощьюgatts_write).В противном случае, если data не равно
None, то это значение отправляется клиенту в составе указания. Локальное значение не будет изменено.При подтверждении (или неудаче, например тайм-ауте) будет вызвано событие
_IRQ_GATTS_INDICATE_DONE.Примечание: Указание будет отправлено независимо от статуса подписки клиента на эту характеристику.
- gatts_set_buffer(value_handle: int, len: int, append: bool = False, /) None¶
Задаёт размер внутреннего буфера для значения в байтах. Это ограничит наибольшую возможную запись, которая может быть получена. По умолчанию 20 байт (ATT MTU по умолчанию в 23 минус 3-байтовый заголовок ATT).
Установка append в
Trueприведёт к тому, что все удалённые записи будут добавляться к текущему значению, а не заменять его. Таким образом можно буферизировать не более len байт. Когда вы используетеgatts_read, значение будет очищено после чтения. Эта функция полезна при реализации чего-то вроде Nordic UART Service.
GATT-клиент
GATT-клиент может обнаруживать и читать/записывать характеристики на удалённом GATT-сервере.
Чаще именно устройство в роли Central действует как GATT-клиент, однако периферийное устройство также может действовать как клиент, чтобы обнаружить информацию о центральном устройстве, которое к нему подключилось (например, прочитать имя устройства из сервиса device information).
- gattc_discover_services(conn_handle: int, uuid: UUID | None = None, /) None¶
Запросить у подключённого сервера его сервисы.
Опционально укажите uuid сервиса, чтобы запросить только этот сервис.
Для каждого обнаруженного сервиса будет вызвано событие
_IRQ_GATTC_SERVICE_RESULT, за которым по завершении последует_IRQ_GATTC_SERVICE_DONE.
- gattc_discover_characteristics(conn_handle: int, start_handle: int, end_handle: int, uuid: UUID | None = None, /) None¶
Запросить у подключённого сервера характеристики в указанном диапазоне.
Опционально укажите uuid характеристики, чтобы запросить только эту характеристику.
Передача
start_handle=1иend_handle=0xffffохватывает весь диапазон дескрипторов атрибутов GATT, поэтому эта комбинация фактически просматривает каждый сервис на удалённом устройстве.Для каждой обнаруженной характеристики будет вызвано событие
_IRQ_GATTC_CHARACTERISTIC_RESULT, за которым по завершении последует_IRQ_GATTC_CHARACTERISTIC_DONE.
- gattc_discover_descriptors(conn_handle: int, start_handle: int, end_handle: int, /) None¶
Запросить у подключённого сервера дескрипторы в указанном диапазоне.
Для каждого обнаруженного дескриптора будет вызвано событие
_IRQ_GATTC_DESCRIPTOR_RESULT, за которым по завершении последует_IRQ_GATTC_DESCRIPTOR_DONE.
- gattc_read(conn_handle: int, value_handle: int, /) None¶
Выполнить удалённое чтение на подключённом сервере для указанного дескриптора характеристики или дескриптора.
Когда значение будет доступно, будет вызвано событие
_IRQ_GATTC_READ_RESULT, за которым по завершении последует_IRQ_GATTC_READ_DONE.
- gattc_write(conn_handle: int, value_handle: int, data: bytes, mode: int = 0, /) None¶
Выполнить удалённую запись на подключённом сервере для указанного дескриптора характеристики или дескриптора.
Аргумент mode задаёт поведение записи, при этом в настоящее время поддерживаются следующие значения:
mode=0(по умолчанию) — это запись без ответа: запись будет отправлена удалённому серверу, но подтверждение не будет возвращено и событие не будет вызвано.mode=1— это запись с ответом: удалённому серверу предлагается отправить ответ/подтверждение того, что он получил данные.
Если от удалённого сервера получен ответ, будет вызвано событие
_IRQ_GATTC_WRITE_DONE.
- gattc_exchange_mtu(conn_handle: int, /) None¶
Инициировать обмен MTU с подключённым сервером, используя предпочтительный MTU, заданный с помощью
BLE.config(mtu=value).Событие
_IRQ_MTU_EXCHANGEDбудет вызвано по завершении обмена MTU.Обмен MTU обычно инициируется центральным устройством; NimBLE поддерживает обе роли.
L2CAP-каналы, ориентированные на соединение
Эта функция позволяет обмениваться данными между двумя BLE-устройствами способом, похожим на сокеты. После того как устройства соединены через GAP, любое устройство может прослушивать подключение другого на числовом PSM (Protocol/Service Multiplexer).
В каждый момент времени может быть активен только один L2CAP-канал (т. е. вы не можете подключаться во время прослушивания).
Активные L2CAP-каналы идентифицируются дескриптором соединения, на котором они были установлены, и CID (идентификатором канала).
Каналы, ориентированные на соединение, имеют встроенное управление потоком на основе кредитов. В отличие от ATT, где устройства согласуют общий MTU, и прослушивающее, и подключающееся устройство каждое задаёт независимый MTU, который ограничивает максимальный объём ещё не обработанных данных, которые удалённое устройство может отправить, прежде чем они будут полностью использованы в
l2cap_recvinto.- l2cap_listen(psm: int, mtu: int, /) None¶
Начать прослушивание входящих запросов на L2CAP-канал на указанном psm с локальным MTU, установленным в mtu.
Когда удалённое устройство инициирует соединение, будет вызвано событие
_IRQ_L2CAP_ACCEPT, которое даёт прослушивающему серверу возможность отклонить входящее соединение (вернув ненулевое целое число).После принятия соединения будет вызвано событие
_IRQ_L2CAP_CONNECT, позволяющее серверу получить идентификатор канала (CID), а также локальный и удалённый MTU.Примечание: В настоящее время остановить прослушивание невозможно.
- l2cap_connect(conn_handle: int, psm: int, mtu: int, /) None¶
Подключиться к прослушивающему узлу на указанном psm с локальным MTU, установленным в mtu.
При успешном соединении будет вызвано событие
_IRQ_L2CAP_CONNECT, позволяющее клиенту получить CID, а также локальный и удалённый (peer) MTU.Неуспешное соединение вызовет событие
_IRQ_L2CAP_DISCONNECTс ненулевым статусом.
- l2cap_disconnect(conn_handle: int, cid: int, /) None¶
Разорвать активный L2CAP-канал с указанными conn_handle и cid.
- l2cap_send(conn_handle: int, cid: int, buf: bytes, /) bool¶
Отправить указанный buf (который должен поддерживать протокол буфера) по L2CAP-каналу, идентифицируемому conn_handle и cid.
Буфер должен удовлетворять обоим ограничениям: он не должен превышать удалённый (peer) MTU и не должен превышать удвоенный локальный MTU.
Это вернёт
False, если канал теперь «застопорен» (stalled), что означает, чтоl2cap_sendне должен вызываться снова, пока не будет получено событие_IRQ_L2CAP_SEND_READY(которое произойдёт, когда удалённое устройство предоставит больше кредитов, обычно после того, как оно получит и обработает данные).
- l2cap_recvinto(conn_handle: int, cid: int, buf: Any | None, /) int¶
Получить данные от указанных conn_handle и cid в предоставленный buf (который должен поддерживать протокол буфера, например bytearray или memoryview).
Возвращает количество байт, прочитанных из канала.
Если buf равен
None, то возвращает количество доступных байт.Примечание: После получения события
_IRQ_L2CAP_RECVприложение должно продолжать вызыватьl2cap_recvinto, пока в приёмном буфере не останется доступных байт (обычно вплоть до размера удалённого (peer) MTU).Пока приёмный буфер не опустеет, удалённому устройству не будет предоставлено больше кредитов канала, и оно не сможет отправлять больше данных.
Сопряжение и привязка
Сопряжение (pairing) позволяет зашифровать и аутентифицировать соединение посредством обмена секретами (с опциональной защитой от MITM через аутентификацию по ключу доступа).
Привязка (bonding) — это процесс сохранения этих секретов в энергонезависимое хранилище. После привязки устройство способно разрешать разрешаемый приватный адрес (RPA) другого устройства на основе сохранённого ключа разрешения идентичности (IRK). Для поддержки привязки приложение должно реализовать события
_IRQ_GET_SECRETи_IRQ_SET_SECRET.- gap_pair(conn_handle: int, /) None¶
Инициировать сопряжение с удалённым устройством.
Перед вызовом этого метода убедитесь, что параметры конфигурации
io,mitm,le_secureиbondзаданы (черезconfig).При успешном сопряжении будет вызвано событие
_IRQ_ENCRYPTION_UPDATE.
- gap_passkey(conn_handle: int, action: int, passkey: int, /) None¶
Ответить на событие
_IRQ_PASSKEY_ACTIONдля указанных conn_handle и action. Значение passkey зависит от action (которое, в свою очередь, зависит от настроенной возможности ввода/вывода):Действие
Требуемый ответ passkey
_PASSKEY_ACTION_INPUTКлюч доступа, который пользователь считывает с удалённого устройства.
_PASSKEY_ACTION_DISPLAYЛокально сгенерированный случайный 6-значный ключ доступа, показанный пользователю.
_PASSKEY_ACTION_NUMERIC_COMPARISON1, чтобы принять ключ доступа, показанный в событии_IRQ_PASSKEY_ACTION, или0, чтобы отменить сопряжение.
class UUID¶
- class bluetooth.UUID(value: int | bytes | str, /)¶
Создаёт экземпляр UUID с указанным значением
value. Bluetooth использует три ширины UUID;UUIDпринимает любую из них:Ширина UUID
Принимаемые типы
valueПример
16-бит
intили 2-байтовый буфер (little-endian)UUID(0x2908)илиUUID(b'\x08\x29')32-бит
4-байтовый буфер (little-endian)
UUID(b'\x08\x29\x00\x00')128-бит
16-байтовый буфер или строка с дефисами
UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E')16- и 32-битные UUID обычно являются идентификаторами, выделенными SIG (см. присвоенные номера Bluetooth); 128-битные UUID обычно определяются производителем.