BLE 客户端
ble_client 组件用于连接蓝牙低功耗设备,以便查询和控制它们。该组件本身不暴露任何传感器或输出组件,而只是管理与其他组件的连接。
WARNING
ESP32 上的 BLE 软件栈会消耗设备上相当多的 RAM。
如果您的设备配置中包含太多额外组件,很可能会发生崩溃。 内存密集型组件,如 Voice Assistant 和其他音频组件,最有可能引起问题。
NOTE
由于 ESP32 BLE 协议栈的限制,最多支持三个设备。如果您希望连接更多设备,请使用额外的 ESP32 开发板。
此组件支持需要 6 位 PIN 码用于身份验证的设备。
目前,已连接客户端的设备无法被基于 Esp32 Ble Tracker 的其他组件支持,因为它们监听只由没有活动连接的设备发送的广播。
尽管有上面最后一点,ble_client 组件仍需要 esp32_ble_tracker 组件来发现可用的客户端设备。
esp32_ble_tracker:
ble_client: - mac_address: XX:XX:XX:XX:XX:XX id: itag_black auto_connect: true- mac_address (必填, MAC Address):要连接的 BLE 设备的 MAC 地址。
- auto_connect (可选, boolean):如果为 true,当设备被 Esp32 Ble Tracker 发现时将自动连接。默认为 true。
- id (必填, ID):用于代码生成以及供依赖组件引用的 ID。
自动化:
-
on_connect (可选, 自动化):当客户端连接到设备时执行的自动化。请参阅
on_connect。 -
on_disconnect (可选, 自动化):当客户端断开与设备的连接时执行的自动化。请参阅
on_disconnect。 -
on_passkey_request (可选, 自动化):用于输入另一个 BLE 设备所需的验证密钥的自动化。请参阅
on_passkey_request。 -
on_passkey_notification (可选, 自动化):用于向用户显示验证密钥的自动化。请参阅
on_passkey_notification。 -
on_numeric_comparison_request (可选, 自动化):用于比较两个 BLE 设备上显示的验证密钥的自动化。请参阅
on_numeric_comparison_request。
BLE 客户端自动化
Section titled “BLE 客户端自动化”on_connect
Section titled “on_connect”当客户端连接到 BLE 设备时触发此自动化。
ble_client: - mac_address: XX:XX:XX:XX:XX:XX id: ble_itag on_connect: then: - lambda: |- ESP_LOGD("ble_client_lambda", "Connected to BLE device");on_disconnect
Section titled “on_disconnect”当客户端断开与 BLE 设备的连接时触发此自动化。
ble_client: - mac_address: XX:XX:XX:XX:XX:XX id: ble_itag on_disconnect: then: - lambda: |- ESP_LOGD("ble_client_lambda", "Disconnected from BLE device");on_passkey_request
Section titled “on_passkey_request”当 BLE 设备请求验证密钥进行身份验证时触发此自动化。
ble_client: - mac_address: XX:XX:XX:XX:XX:XX id: ble_itag on_passkey_request: then: - ble_client.passkey_reply: id: ble_itag passkey: 123456on_passkey_notification
Section titled “on_passkey_notification”当从 BLE 设备收到验证密钥时触发此自动化。
ble_client: - mac_address: XX:XX:XX:XX:XX:XX id: ble_itag on_passkey_notification: then: - logger.log: format: "Enter this passkey on your BLE device: %06d" args: [ passkey ]on_numeric_comparison_request
Section titled “on_numeric_comparison_request”当 BLE 设备请求进行数字比较时触发此自动化。
ble_client: - mac_address: XX:XX:XX:XX:XX:XX id: ble_itag on_numeric_comparison_request: then: - logger.log: format: "Compare this passkey with the one on your BLE device: %06d" args: [ passkey ] - ble_client.numeric_comparison_reply: id: ble_itag accept: Trueble_client.connect Action
Section titled “ble_client.connect Action”此操作仅对 auto_connect: false 的设备有用,允许从自动化内部建立连接。连接后,可以使用其他操作,如 ble_write。这在对 BLE 服务器只需要偶尔交互时很有用,因此不需要保持持续连接。
以下示例每小时更新一次小米 MHO-C303 时钟的时间。请注意,在连接尝试期间必须停止 BLE 跟踪器,并在之后重新启动。如果跟踪器设置了 continuous: false,则不需要这样做。在此示例场景中,还有另一个 BLE 设备确实需要扫描器保持开启,因此在连接期间需要停止和启动扫描。
ble_client: - id: ble_clock mac_address: XX:XX:XX:XX:XX:XX auto_connect: false - id: other_device mac_address: XX:XX:XX:XX:XX:XX
interval: - interval: 60min then: - esp32_ble_tracker.stop_scan: - ble_client.connect: ble_clock - ble_client.ble_write: id: ble_clock service_uuid: EBE0CCB0-7A0A-4B0C-8A1A-6FF2997DA3A6 characteristic_uuid: EBE0CCB7-7A0A-4B0C-8A1A-6FF2997DA3A6 value: !lambda |- uint32_t t = id(sntp_time).now().timestamp + ESPTime::timezone_offset(); return {(uint8_t)t, (uint8_t)(t >> 8), (uint8_t)(t >> 16), (uint8_t)(t >> 24), 0}; - ble_client.disconnect: ble_clock - esp32_ble_tracker.start_scan:connect 操作之后的任何操作都只在连接成功后才继续执行。如果连接失败,自动化块中的后续操作将不会执行。如果扫描已停止,应考虑这一点——可能需要另一种机制来重新启动扫描。
ble_client.disconnect Action
Section titled “ble_client.disconnect Action”此操作断开使用 ble_client.connect 操作连接的设备。断开连接完成后,自动化块序列的执行将继续。
ble_client.ble_write Action
Section titled “ble_client.ble_write Action”此操作触发对指定 BLE 特性的写入。写入以尽力而为的方式进行尝试,并且只有在 ble_client 的连接已建立且外设公开了预期的 BLE 服务和特性的情况下才会成功。写入完成后,自动化块序列的执行将继续。写入失败将不会停止后续操作的执行(例如,这允许执行断开连接。)
示例用法:
ble_client: - mac_address: XX:XX:XX:XX:XX:XX id: my_ble_client
switch: - platform: template name: "My Switch" turn_on_action: - ble_client.ble_write: id: my_ble_client service_uuid: F61E3BE9-2826-A81B-970A-4D4DECFABBAE characteristic_uuid: 6490FAFE-0734-732C-8705-91B653A081FC # List of bytes to write. value: [0x01, 0xab, 0xff] - ble_client.ble_write: id: my_ble_client service_uuid: F61E3BE9-2826-A81B-970A-4D4DECFABBAE characteristic_uuid: 6490FAFE-0734-732C-8705-91B653A081FC # A lambda returning an std::vector<uint8_t>. value: !lambda |- return {0x13, 0x37};- id (必填, ID):关联 BLE 客户端的 ID。
- service_uuid (必填, UUID):要写入的服务的 UUID。
- characteristic_uuid (必填, UUID):要写入的服务特性的 UUID。
- value (必填, bytes 列表, 可模板化):要写入的值。
ble_client.passkey_reply Action
Section titled “ble_client.passkey_reply Action”此操作使用指定的 passkey 触发身份验证尝试。
示例用法:
on_...: then: - ble_client.passkey_reply: id: my_ble_client passkey: 123456ble_client.numeric_comparison_reply Action
Section titled “ble_client.numeric_comparison_reply Action”此操作在数字比较后触发身份验证尝试。
示例用法:
on_...: then: - ble_client.numeric_comparison_reply: id: my_ble_client accept: Trueble_client.remove_bond Action
Section titled “ble_client.remove_bond Action”此操作从安全数据库中移除设备并管理取消配对。
示例用法:
ble_client: - mac_address: XX:XX:XX:XX:XX:XX id: my_ble_client on_connect: then: - ble_client.remove_bond: id: my_ble_client- id (必填, ID):关联 BLE 客户端的 ID。
BLE 概述
Section titled “BLE 概述”本节简要概述蓝牙 LE 架构,以帮助理解此组件及相关组件。网上有很多更详细的参考资料。
BLE 使用服务器和客户端的概念。简而言之,服务器实现在提供服务的设备上,通常是诸如心脏监测器、标签、气象站等设备。客户端连接到服务器并使用其服务。客户端通常是手机上的应用,或者在 ESPHome 的情况下,是 ESP32 设备。
当客户端连接到服务器时,客户端会查询服务器提供的服务。服务在服务器上公开类别的功能。这些可能是定义明确且受支持的服务,例如电池电量服务、设备信息或心率。也可能是为该设备专门设计的自定义服务。例如,廉价 iTag 上的按钮使用自定义服务。
每个服务然后定义一个或多个特征,这些特征通常是该服务的离散值。例如,对于环境传感器服务,公开的特征包括风速、湿度和降雨量。根据它们的功能,这些特征可能只读或可读写。
一个特征还可以公开一个或多个描述符,这些描述符携带有关该特征的更多信息。这可能是单位、有效范围以及是否启用通知(见下文)等内容。
BLE 还支持通知。客户端持续轮询更新可能会消耗大量电力,这对于设计为低功耗的协议来说是不可取的。相反,服务器可以仅在更新发生变化时将更新推送给客户端。根据其用途和设计,特征可能允许发送通知。然后,客户端可以通过设置该特征的配置描述符来启用通知。
每个服务、特征和描述符都由一个唯一标识符(UUID)标识,长度可能在 16 到 128 位之间。客户端通常会根据 UUID 来识别设备的功能。
一旦连接建立,使用完整的 UUID 引用每个服务/特征/描述符将占用小小的(约 23 字节)数据包的相当大一部分。因此,特征和描述符还提供了一个小的 2 字节句柄(别名)来最大限度地增加可用数据空间。
虽然该组件可以连接到大多数 BLE 设备,但只有通过依赖组件才能获得有用的功能,例如 Ble Client。有关设置特定设备的详细信息,请参阅这些组件的文档。
要使用 ble_client 组件,您需要启用 Esp32 Ble Tracker 组件。这还将允许您发现设备的 MAC 地址。
当您发现设备的 MAC 地址后,可以将其添加到 ble_client 配置块中。
然后,如果您构建并上传此配置,ESP 将侦听该设备,并在发现它时尝试连接。然后,该组件将查询设备的所有可用服务和特性并显示在日志中:
[18:24:56][D][ble_client:043]: Found device at MAC address [XX:XX:XX:XX:XX:XX][18:24:56][I][ble_client:072]: Attempting BLE connection to XX:XX:XX:XX:XX:XX[18:24:56][I][ble_client:097]: [XX:XX:XX:XX:XX:XX] ESP_GATTC_OPEN_EVT[18:24:57][I][ble_client:143]: Service UUID: 0x1800[18:24:57][I][ble_client:144]: start_handle: 0x1 end_handle: 0x5[18:24:57][I][ble_client:305]: characteristic 0x2A00, handle 0x3, properties 0x2[18:24:57][I][ble_client:305]: characteristic 0x2A01, handle 0x5, properties 0x2[18:24:57][I][ble_client:143]: Service UUID: 0x1801[18:24:57][I][ble_client:144]: start_handle: 0x6 end_handle: 0x6[18:24:57][I][ble_client:143]: Service UUID: 0x180A[18:24:57][I][ble_client:144]: start_handle: 0x7 end_handle: 0x19[18:24:57][I][ble_client:305]: characteristic 0x2A29, handle 0x9, properties 0x2[18:24:57][I][ble_client:305]: characteristic 0x2A24, handle 0xb, properties 0x2[18:24:57][I][ble_client:305]: characteristic 0x2A25, handle 0xd, properties 0x2[18:24:57][I][ble_client:305]: characteristic 0x2A27, handle 0xf, properties 0x2[18:24:57][I][ble_client:305]: characteristic 0x2A26, handle 0x11, properties 0x2[18:24:57][I][ble_client:305]: characteristic 0x2A28, handle 0x13, properties 0x2[18:24:57][I][ble_client:305]: characteristic 0x2A23, handle 0x15, properties 0x2[18:24:57][I][ble_client:305]: characteristic 0x2A2A, handle 0x17, properties 0x2[18:24:57][I][ble_client:305]: characteristic 0x2A50, handle 0x19, properties 0x2[18:24:57][I][ble_client:143]: Service UUID: F000FFC0045140-00B0-0000-0000-000000[18:24:57][I][ble_client:144]: start_handle: 0x1a end_handle: 0x22[18:24:57][I][ble_client:305]: characteristic F000FFC1045140-00B0-0000-0000-000000, handle 0x1c, properties 0x1c[18:24:57][I][ble_client:343]: descriptor 0x2902, handle 0x1d[18:24:57][I][ble_client:343]: descriptor 0x2901, handle 0x1e[18:24:57][I][ble_client:305]: characteristic F000FFC2045140-00B0-0000-0000-000000, handle 0x20, properties 0x1c[18:24:57][I][ble_client:343]: descriptor 0x2902, handle 0x21[18:24:57][I][ble_client:343]: descriptor 0x2901, handle 0x22[18:24:57][I][ble_client:143]: Service UUID: 0xFFE0[18:24:57][I][ble_client:144]: start_handle: 0x23 end_handle: 0x26[18:24:57][I][ble_client:305]: characteristic 0xFFE1, handle 0x25, properties 0x10[18:24:57][I][ble_client:343]: descriptor 0x2902, handle 0x26[18:24:57][I][ble_client:143]: Service UUID: 0x1802[18:24:57][I][ble_client:144]: start_handle: 0x27 end_handle: 0x29[18:24:57][I][ble_client:305]: characteristic 0x2A06, handle 0x29, properties 0x4发现的服务随后可用于启用和配置其他 ESPHome 组件,例如服务 UUID 0xFFE0 用于 iTag 式钥匙串按钮事件,由 Ble Client 组件使用。
Passkey 示例
Section titled “Passkey 示例”使用固定验证密钥的安全连接:
esp32_ble: io_capability: keyboard_only
esp32_ble_tracker:
ble_client: - mac_address: XX:XX:XX:XX:XX:XX id: pvvx_ble_display on_passkey_request: then: - logger.log: "Authenticating with passkey" - ble_client.passkey_reply: id: pvvx_ble_display passkey: 123456使用动态生成的验证密钥的安全连接:
api: actions: - action: passkey_reply variables: passkey: int then: - logger.log: "Authenticating with passkey" - ble_client.passkey_reply: id: my_ble_client passkey: !lambda return passkey; - action: numeric_comparison_reply variables: accept: bool then: - logger.log: "Authenticating with numeric comparison" - ble_client.numeric_comparison_reply: id: my_ble_client accept: !lambda return accept;
esp32_ble: io_capability: keyboard_display
esp32_ble_tracker:
ble_client: - mac_address: XX:XX:XX:XX:XX:XX id: my_ble_client on_passkey_request: then: - logger.log: "Enter the passkey displayed on your BLE device" - logger.log: " Go to https://my.home-assistant.io/redirect/developer_services/ and select passkey_reply" on_passkey_notification: then: - logger.log: format: "Enter this passkey on your BLE device: %06d" args: [ passkey ] on_numeric_comparison_request: then: - logger.log: format: "Compare this passkey with the one on your BLE device: %06d" args: [ passkey ] - logger.log: " Go to https://my.home-assistant.io/redirect/developer_services/ and select numeric_comparison_reply" on_connect: then: - logger.log: "Connected"