Я новичок в использовании 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, которое рекламирует свои услуги, поэтому он должен быть в выходных данных. Скорее всего, это не официальное устройство TrikThom. Поиск в Google этого имени приводит к веб-сайту, который автоматически перенаправляет на Harmony.energy, я понятия не имею, как они связаны или что означает 51212.
51212
— идентификатор компании TrikThom
. Чтобы проверить это, используйте документ Назначенные номера. Чтобы получить шестнадцатеричное значение: int(51212).to_bytes(2, "little")
= 0x0cc8
. Может быть, использование manufacturer_data
— это лучшее, что вы сможете сделать с этим устройством?
И есть библиотека Python, которая поможет с поиском: github.com/koenvervloesem/bluetooth-numbers . Хотя версия PyPI немного отстает main
. github.com/koenvervloesem/bluetooth-numbers/issues/51
Хорошо, хорошая идея, я собирался реализовать это, хотя похоже, что идентификатор производителя полуслучайный: ca0c 310000000000 ca0c 310000000000 bc0c 310000000000 cc0c 310000000000 bc0c 310000000000 c60c 310000000000
Во-первых, это ключ, во-вторых, данные производителя_данных, возвращаемые для устройства. (Да, должно присутствовать только одно устройство, диапазон кажется достаточно коротким, чтобы любое другое устройство могло находиться на расстоянии прикосновения, и я фильтрую по local_name). Думаю, я мог бы какое-то время собирать сообщения, если есть какая-то закономерность. Или выполните поиск по данным, а не по идентификатору.
Придется перечитать даташит, но на первый взгляд я не увидел в рекламных данных ничего об идентификаторе производителя: wch-ic.com/products/CH9141.html
Спецификация BLE (раздел 1.4.2 CSS v10) требует, чтобы первые два байта поля данных производителя после длины были идентификатором компании (CIC), но не существует механизма, обеспечивающего это, и не каждое устройство будет делать это правильно. . (Однажды я работал над устройством, которое случайно использовало BRADDR, которых у нас не было из-за опечатки… всякое бывает…) Поэтому, если вы видите здесь меняющиеся значения, я ожидаю, что это просто данные, и устройство не соответствует спецификациям. . («Кодекс — это скорее то, что вы называете… руководящими принципами». :D)
Это устройство просто объявляет DIS, который рекламирует почти каждое устройство, и оно нарушает спецификацию, используя неназначенные 16-битные идентификаторы служб. Они выбрали 0xFFF0 и 0xFFE0, и я думаю, просто надеюсь, что они ни с кем не столкнутся… Это не очень надежно, хотя, если у них очень короткая дальность, которую вы описываете, я уверен, что им это почти всегда сходит с рук, именно поэтому они сделали это вместо того, чтобы платить сборы, необходимые для получения собственных идентификаторов. Но это не особо идентифицирует устройство. Надеюсь, есть что-то еще (возможно, что-то в службе информации об устройстве), которое действительно определит, что это правильное устройство. «Приседать на двух легко выбираемых идентификаторах услуг» — не лучший способ убедиться в этом.
Обычно при поиске такого устройства вы просматриваете его рекламу, чтобы узнать, является ли это именно то устройство, которое вам нужно, а затем подключаетесь, чтобы проверить те устройства, которые возможны. После подключения идентификатор CBPeripheral будет довольно стабильным (я видел, как они менялись, но это редко), так что вы сможете использовать его в будущем.
Этот вид эвристического многоэтапного подхода очень распространен. Я делал это еще тогда, когда контролировал прошивку устройства и мог поместить в рекламный пакет все, что хотел.
«Разве устройство BLE не должно рекламировать предоставляемые им услуги?» Абсолютно нет. И многие устройства BLE не рекламируют (и не могут) рекламировать все предоставляемые ими услуги из-за рекламного пространства. Из того, что вы здесь обсуждали, не очевидно, рекламирует ли это конкретное устройство свои услуги или нет, или это проблема с вашим скриптом
discover.py
. Какие службы вы пытаетесь сканировать? (Похоже, это реклама TrikThom, учитывая 51212 в mfgdata? Не могли бы вы использовать этот факт? Я плохо знаю это конкретное устройство.)