Устройства-фильтры Bluetooth Low Energy на основе сервисов

Я новичок в использовании BLE/Bluetooth. Я пытаюсь связаться с устройством с поддержкой BLE, которое использует мост CH9141K BLE-последовательный порт. Мое хост-приложение успешно взаимодействует с устройством, используя мрачную библиотеку для Python.

До сих пор я связывался с устройством напрямую, подключаясь через MAC или локальное имя (или uuid в MacOS), и все работало нормально.

Теперь я хочу выполнить поиск устройств, поскольку вполне вероятно, что пользователь не знает MAC или локальное имя устройства. (MacOS скрывает MAC, и локальное имя можно изменить.)

python3 discover.py (пример из безрадостной упаковки) сообщает об этом:

AdvertisementData(local_name='device ', manufacturer_data = {51212: b'1\x00\x00\x00\x00\x00'}, tx_power=0, rssi=-53)

Я немного запутался: разве устройство BLE не должно рекламировать предоставляемые им услуги? Я сравнил это с примером из библиотеки MicroPython aioble (temp_sensor.py), которая возвращает service_uuids для предоставляемых ею сервисов.

Мой план состоял в том, чтобы сначала как можно эффективнее обнаружить устройства CH9141K, а затем прослушать каждое из них, если они вернут пакет данных, действительный для устройства, которое я ищу.

Если я использую service_explorer.py (опять же, из мрачных примеров), я получаю:

2024-08-21 17:31:21,970 __main__ INFO: connecting to device...
2024-08-21 17:31:23,641 __main__ INFO: connected
2024-08-21 17:31:23,641 __main__ INFO: [Service] 0000180a-0000-1000-8000-00805f9b34fb (Handle: 14): Device Information
2024-08-21 17:31:23,686 __main__ INFO:   [Characteristic] 00002a23-0000-1000-8000-00805f9b34fb (Handle: 15): System ID (read), Value: bytearray(b'\x13\xdey\x00\x00\x10S\\')
2024-08-21 17:31:23,716 __main__ INFO:   [Characteristic] 00002a24-0000-1000-8000-00805f9b34fb (Handle: 17): Model Number String (read), Value: bytearray(b'CH9141')
2024-08-21 17:31:23,746 __main__ INFO:   [Characteristic] 00002a25-0000-1000-8000-00805f9b34fb (Handle: 19): Serial Number String (read), Value: bytearray(b'190420000000')
2024-08-21 17:31:23,791 __main__ INFO:   [Characteristic] 00002a26-0000-1000-8000-00805f9b34fb (Handle: 21): Firmware Revision String (read), Value: bytearray(b'VER1.0')
2024-08-21 17:31:23,821 __main__ INFO:   [Characteristic] 00002a27-0000-1000-8000-00805f9b34fb (Handle: 23): Hardware Revision String (read), Value: bytearray(b'VER1.0')
2024-08-21 17:31:23,851 __main__ INFO:   [Characteristic] 00002a28-0000-1000-8000-00805f9b34fb (Handle: 25): Software Revision String (read), Value: bytearray(b'VER1.0')
2024-08-21 17:31:23,895 __main__ INFO:   [Characteristic] 00002a29-0000-1000-8000-00805f9b34fb (Handle: 27): Manufacturer Name String (read), Value: bytearray(b'WCH')
2024-08-21 17:31:23,925 __main__ INFO:   [Characteristic] 00002a50-0000-1000-8000-00805f9b34fb (Handle: 29): PnP ID (read), Value: bytearray(b'\x019\x07\x00\x00\x10\x01')
2024-08-21 17:31:23,938 __main__ INFO: [Service] 0000fff0-0000-1000-8000-00805f9b34fb (Handle: 31): Vendor specific
2024-08-21 17:31:24,001 __main__ INFO:   [Characteristic] 0000fff1-0000-1000-8000-00805f9b34fb (Handle: 32): Vendor specific (read,notify), Value: bytearray(b'')
2024-08-21 17:31:24,031 __main__ INFO:     [Descriptor] 00002902-0000-1000-8000-00805f9b34fb (Handle: 34): Client Characteristic Configuration, Value: bytearray(b'')
2024-08-21 17:31:24,061 __main__ INFO:     [Descriptor] 00002901-0000-1000-8000-00805f9b34fb (Handle: 35): Characteristic User Description, Value: bytearray(b'UART DATA')
2024-08-21 17:31:24,061 __main__ INFO:   [Characteristic] 0000fff2-0000-1000-8000-00805f9b34fb (Handle: 36): Vendor specific (write-without-response,write), Max write w/o rsp size: 197
2024-08-21 17:31:24,121 __main__ INFO:     [Descriptor] 00002901-0000-1000-8000-00805f9b34fb (Handle: 38): Characteristic User Description, Value: bytearray(b'BLE DATA')
2024-08-21 17:31:24,151 __main__ INFO:   [Characteristic] 0000fff3-0000-1000-8000-00805f9b34fb (Handle: 39): Vendor specific (read,write,notify), Value: bytearray(b'')
2024-08-21 17:31:24,181 __main__ INFO:     [Descriptor] 00002902-0000-1000-8000-00805f9b34fb (Handle: 41): Client Characteristic Configuration, Value: bytearray(b'')
2024-08-21 17:31:24,211 __main__ INFO:     [Descriptor] 00002901-0000-1000-8000-00805f9b34fb (Handle: 42): Characteristic User Description, Value: bytearray(b'BLE CONFIG')
2024-08-21 17:31:24,211 __main__ INFO: [Service] 0000ffe0-0000-1000-8000-00805f9b34fb (Handle: 43): Vendor specific
2024-08-21 17:31:24,211 __main__ INFO:   [Characteristic] 0000ffe1-0000-1000-8000-00805f9b34fb (Handle: 44): Vendor specific (notify)
2024-08-21 17:31:24,241 __main__ INFO:     [Descriptor] 00002902-0000-1000-8000-00805f9b34fb (Handle: 46): Client Characteristic Configuration, Value: bytearray(b'')
2024-08-21 17:31:24,271 __main__ INFO:     [Descriptor] 00002901-0000-1000-8000-00805f9b34fb (Handle: 47): Characteristic User Description, Value: bytearray(b'UART DATA')
2024-08-21 17:31:24,271 __main__ INFO:   [Characteristic] 0000ffe2-0000-1000-8000-00805f9b34fb (Handle: 48): Vendor specific (write-without-response,write), Max write w/o rsp size: 197
2024-08-21 17:31:24,301 __main__ INFO:     [Descriptor] 00002901-0000-1000-8000-00805f9b34fb (Handle: 50): Characteristic User Description, Value: bytearray(b'BLE DATA')
2024-08-21 17:31:24,301 __main__ INFO: disconnecting...
2024-08-21 17:31:24,303 __main__ INFO: disconnected

...хотя это подключается к устройству для перебора сервисов.

Итак, вопрос в том, как мне эффективно фильтровать устройства, предоставляющие определенные услуги, или допустимо подключаться ко всем обнаруженным устройствам для быстрого просмотра? Или есть опция, которой мне не хватает в BLE/Bleak? Мне нужно как минимум знать, что я имею дело с устройством CH9141, наверное, лучше посмотреть, что оно также предоставляет сервис 0xFFF0. Оба из них легко найти после подключения.

«Разве устройство BLE не должно рекламировать предоставляемые им услуги?» Абсолютно нет. И многие устройства BLE не рекламируют (и не могут) рекламировать все предоставляемые ими услуги из-за рекламного пространства. Из того, что вы здесь обсуждали, не очевидно, рекламирует ли это конкретное устройство свои услуги или нет, или это проблема с вашим скриптом discover.py. Какие службы вы пытаетесь сканировать? (Похоже, это реклама TrikThom, учитывая 51212 в mfgdata? Не могли бы вы использовать этот факт? Я плохо знаю это конкретное устройство.)

Rob Napier 27.08.2024 02:27

Я использовал тот же сценарий с отдельным устройством BLE, которое рекламирует свои услуги, поэтому он должен быть в выходных данных. Скорее всего, это не официальное устройство TrikThom. Поиск в Google этого имени приводит к веб-сайту, который автоматически перенаправляет на Harmony.energy, я понятия не имею, как они связаны или что означает 51212.

user1387 27.08.2024 08:44
51212 — идентификатор компании TrikThom. Чтобы проверить это, используйте документ Назначенные номера. Чтобы получить шестнадцатеричное значение: int(51212).to_bytes(2, "little") = 0x0cc8. Может быть, использование manufacturer_data — это лучшее, что вы сможете сделать с этим устройством?
ukBaz 27.08.2024 11:26

И есть библиотека Python, которая поможет с поиском: github.com/koenvervloesem/bluetooth-numbers . Хотя версия PyPI немного отстает main. github.com/koenvervloesem/bluetooth-numbers/issues/51

ukBaz 27.08.2024 11:55

Хорошо, хорошая идея, я собирался реализовать это, хотя похоже, что идентификатор производителя полуслучайный: ca0c 310000000000 ca0c 310000000000 bc0c 310000000000 cc0c 310000000000 bc0c 310000000000 c60c 310000000000 Во-первых, это ключ, во-вторых, данные производителя_данных, возвращаемые для устройства. (Да, должно присутствовать только одно устройство, диапазон кажется достаточно коротким, чтобы любое другое устройство могло находиться на расстоянии прикосновения, и я фильтрую по local_name). Думаю, я мог бы какое-то время собирать сообщения, если есть какая-то закономерность. Или выполните поиск по данным, а не по идентификатору.

user1387 27.08.2024 14:09

Придется перечитать даташит, но на первый взгляд я не увидел в рекламных данных ничего об идентификаторе производителя: wch-ic.com/products/CH9141.html

user1387 27.08.2024 14:12

Спецификация BLE (раздел 1.4.2 CSS v10) требует, чтобы первые два байта поля данных производителя после длины были идентификатором компании (CIC), но не существует механизма, обеспечивающего это, и не каждое устройство будет делать это правильно. . (Однажды я работал над устройством, которое случайно использовало BRADDR, которых у нас не было из-за опечатки… всякое бывает…) Поэтому, если вы видите здесь меняющиеся значения, я ожидаю, что это просто данные, и устройство не соответствует спецификациям. . («Кодекс — это скорее то, что вы называете… руководящими принципами». :D)

Rob Napier 27.08.2024 15:25
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
7
53
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это устройство просто объявляет DIS, который рекламирует почти каждое устройство, и оно нарушает спецификацию, используя неназначенные 16-битные идентификаторы служб. Они выбрали 0xFFF0 и 0xFFE0, и я думаю, просто надеюсь, что они ни с кем не столкнутся… Это не очень надежно, хотя, если у них очень короткая дальность, которую вы описываете, я уверен, что им это почти всегда сходит с рук, именно поэтому они сделали это вместо того, чтобы платить сборы, необходимые для получения собственных идентификаторов. Но это не особо идентифицирует устройство. Надеюсь, есть что-то еще (возможно, что-то в службе информации об устройстве), которое действительно определит, что это правильное устройство. «Приседать на двух легко выбираемых идентификаторах услуг» — не лучший способ убедиться в этом.

Обычно при поиске такого устройства вы просматриваете его рекламу, чтобы узнать, является ли это именно то устройство, которое вам нужно, а затем подключаетесь, чтобы проверить те устройства, которые возможны. После подключения идентификатор CBPeripheral будет довольно стабильным (я видел, как они менялись, но это редко), так что вы сможете использовать его в будущем.

Этот вид эвристического многоэтапного подхода очень распространен. Я делал это еще тогда, когда контролировал прошивку устройства и мог поместить в рекламный пакет все, что хотел.

Другие вопросы по теме