Skip to content

Работа термометров в Home Assistant c Bluetooth LE Long Range. #297

@pvvx

Description

@pvvx

Предварительное описание решения.

Для примера можно взять:
Low-cost Realtek RTL8761BU BT adapter

image

USB ID 0bda:8771 Realtek Semiconductor Corp. Bluetooth Radio

Сurrent version of Linux fw on RTL8761BU supports Bluetooth Core ver 5.4:

# hciconfig hci2 version
hci2:   Type: Primary  Bus: USB
        BD Address: 8C:88:2B:00:E7:EA  ACL MTU: 1021:6  SCO MTU: 255:12
        HCI Version:  (0xd)  Revision: 0xddd5
        LMP Version:  (0xd)  Subversion: 0xc761
        Manufacturer: Realtek Semiconductor Corporation (93)

Для работы HA c LE Long Range в интеграции “Bluetooth” желательно установить последнюю версию bluez и добавить в файле /lib/systemd/system/bluetooth.service
ExecStart=/usr/local/libexec/bluetooth/bluetoothd --experimental

Из-за неверной инициализации адаптеров BT5.+ в Bluez, перед запуском Home Assistant необходимо переключить BT адаптер на работу в режим Bluetoch 5.0:
hcitool -i hci1 cmd 08 31 03 05 05
или во всех режимах PHY 1M/2M/Coded:
hcitool -i hci1 cmd 08 31 03 07 07
Номер hciN - свой.
Проверить переключение возможно в btmon (log btmon):

@ RAW Open: hcitool (privileged) version 2.22
< HCI Command: LE Set Default PHY (0x08|0x0031) plen 3
        All PHYs preference: 0x03
          No TX PHY preference
          No RX PHY preference
        TX PHYs preference: 0x07
          LE 1M
          LE 2M
          LE Coded
        RX PHYs preference: 0x07
          LE 1M
          LE 2M
          LE Coded
> HCI Event: Command Complete (0x0e) plen 4
      LE Set Default PHY (0x08|0x0031) ncmd 2
        Status: Success (0x00)

В итоге, в интеграции "BTHome" получаем успешный прием термометров со стандартной рекламой и работающих в LE Long Range:

image

Если адаптер будет работать неустойчиво, тогда HA может его переинициализировать и настройка на работу в Coded PHY (Long Range) собьется. Ожидать официальной поддержки в интеграции “Bluetooth” нет никакой возможности. Выбранный автором API “Bleak” не позволяет управлять PHY адаптера и не предвидится никакой поддержки BLUETOOTH SPECIFICATION Version 5.0 от 2016 года.

BLUETOOTH SPECIFICATION Version 5.0 | Vol 1, Part C page 291
Core Specification Change History
9 CHANGES FROM v4.2 TO 5.0
9.1 NEW FEATURES
Several new features are introduced in the Bluetooth Core Specification 5.0
Release. The major areas of improvement are:
• Slot Availability Mask (SAM)
• 2 Msym/s PHY for LE
• LE Long Range
• High Duty Cycle Non-Connectable Advertising
• LE Advertising Extensions
• LE Channel Selection Algorithm #2 

Проверить адаптер на совместимость возможно с помощью команд:

# btmgmt phy
Supported phys: BR1M1SLOT BR1M3SLOT BR1M5SLOT EDR2M1SLOT EDR2M3SLOT EDR2M5SLOT EDR3M1SLOT EDR3M3SLOT EDR3M5SLOT LE1MTX LE1MRX LE2MTX LE2MRX LECODEDTX LECODEDRX
Configurable phys: BR1M3SLOT BR1M5SLOT EDR2M1SLOT EDR2M3SLOT EDR2M5SLOT EDR3M1SLOT EDR3M3SLOT EDR3M5SLOT LE2MTX LE2MRX LECODEDTX LECODEDRX
Selected phys: BR1M1SLOT BR1M3SLOT BR1M5SLOT EDR2M1SLOT EDR2M3SLOT EDR2M5SLOT EDR3M1SLOT EDR3M3SLOT EDR3M5SLOT LECODEDTX LECODEDRX

# hciconfig -a
hci0:   Type: Primary  Bus: USB
        BD Address: 8C:88:2B:00:E7:EA  ACL MTU: 1021:6  SCO MTU: 255:12
        UP RUNNING
        RX bytes:6245694 acl:0 sco:0 events:46360 errors:0
        TX bytes:33016 acl:0 sco:0 commands:222 errors:0
        Features: 0xff 0xff 0xff 0xfe 0xdb 0xfd 0x7b 0x87
        Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3
        Link policy: RSWITCH HOLD SNIFF PARK
        Link mode: PERIPHERAL ACCEPT
        Name: 'nanopi-r5s'
        Class: 0x400000
        Service Classes: Telephony
        Device Class: Miscellaneous,
        HCI Version:  (0xd)  Revision: 0xddd5
        LMP Version:  (0xd)  Subversion: 0xc761
        Manufacturer: Realtek Semiconductor Corporation (93)

Установка вариантов PHY в btmgmt работает не совсем корректно (в некоторых вариантах имеются ошибки). Но и с помощью этой программы возможно установить необходимые PHY.

Для этого необходимо:

  1. Вывести текущие установки PHY:
# btmgmt -i 1 phy
Supported phys: BR1M1SLOT BR1M3SLOT BR1M5SLOT EDR2M1SLOT EDR2M3SLOT EDR2M5SLOT EDR3M1SLOT EDR3M3SLOT EDR3M5SLOT LE1MTX LE1MRX LE2MTX LE2MRX LECODEDTX LECODEDRX
Configurable phys: BR1M3SLOT BR1M5SLOT EDR2M1SLOT EDR2M3SLOT EDR2M5SLOT EDR3M1SLOT EDR3M3SLOT EDR3M5SLOT LE2MTX LE2MRX LECODEDTX LECODEDRX
Selected phys: BR1M1SLOT BR1M3SLOT BR1M5SLOT EDR2M1SLOT EDR2M3SLOT EDR2M5SLOT EDR3M1SLOT EDR3M3SLOT EDR3M5SLOT LE1MTX LE1MRX
  1. К вариантам 'Selected phys' добавить опции ‘LECODEDTX’ и ‘LECODEDRX’:
# btmgmt -i 1 phy BR1M1SLOT BR1M3SLOT BR1M5SLOT EDR2M1SLOT EDR2M3SLOT EDR2M5SLOT EDR3M1SLOT EDR3M3SLOT EDR3M5SLOT LE1MTX LE1MRX LECODEDTX LECODEDRX
PHY Configuration successfully set

Для установки PHY через API в bluez смотреть /doc/mgmt-api.txt.

Set PHY Configuration Command
=============================

	Command Code:		0x0045
	Controller Index:	<controller id>
	Command Parameters: 	Selected_PHYs (4 Octet)
	Return Parameters:

	This command is used to set the default PHY to the controller.

	This will be stored and used for all the subsequent scanning
	and connection initiation.

	The list of supported PHYs can be retrieved via the
	Get PHY Configuration command. Selecting unsupported or
	deselecting default PHYs will result in an Invalid Parameter
	error.

	This can be called at any point to change the Selected PHYs.

	Refer Get PHY Configuration command for PHYs parameter.

	This command generates a Command Complete event on success
	or a Command Status event on failure.

	Possible errors:	Invalid Parameters
				Invalid Index

Или через hci_send_cmd(). Пример для Python (неполный и не совсем корректный):

import os
import sys
import struct
import bluetooth._bluetooth as _bt

OGF_LE_CTL = 0x08
OCF_SET_DEFAULT_PHY = 0x0031

def set_hci_phy(hci_sock, phy):
    # save current filter
    old_filter = hci_sock.getsockopt(_bt.SOL_HCI, _bt.HCI_FILTER, 14)
    # Setup socket filter to receive only events related to the
    # write_inquiry_mode command
    flt = _bt.hci_filter_new()
    _bt.hci_filter_set_ptype(flt, _bt.HCI_EVENT_PKT)
    _bt.hci_filter_set_event(flt, _bt.EVT_CMD_COMPLETE);
    _bt.hci_filter_set_opcode(flt, _bt.cmd_opcode_pack(OGF_LE_CTL, OCF_SET_DEFAULT_PHY))
    hci_sock.setsockopt( _bt.SOL_HCI, _bt.HCI_FILTER, flt )
    #< HCI Command: ogf 0x08, ocf 0x0031, plen 3 [ 03 05 05 ]
    _bt.hci_send_cmd(hci_sock, OGF_LE_CTL, OCF_SET_DEFAULT_PHY, phy)
    #> HCI Event: 0x0e plen 4 02 31 20 00
    pkt = hci_sock.recv(255)
    status = struct.unpack("xxxxxxB", pkt)[0]
    print(status)
    # restore old filter
    hci_sock.setsockopt( _bt.SOL_HCI, _bt.HCI_FILTER, old_filter )
    return status

if __name__ == "__main__":
    dev_id = 1
    hci_sock = _bt.hci_open_dev(dev_id)
    status = set_hci_phy(hci_sock, struct.pack("<BBB", 3, 5, 5))
    _bt.hci_close_dev(dev_id)

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentation

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions