这次把微雪 ESP32-S3-GEEK 做成了带屏幕的 Home Assistant 蓝牙代理:接收领普 ES5 普通款的人体存在广播,通过 Wi-Fi 送给 HA 解密,再实现“有人开挂灯、无人关挂灯”。GEEK 的屏幕同时显示存在状态、光照、网络和时钟,还能切换显示方向。本文按实际部署过程整理,配有原创示意图、产品介绍图和本次部署的设备实拍,图注分别说明。
适用范围:领普 ES5 普通款,米家型号 linp.sensor_occupy.es5b,HA 识别为 ES5BB;开发板为 ESP32-S3-GEEK。其他 ES5 变体、其他开发板需要自己开发适配。实测版本:ESPHome 2026.9.1、HA Container 2026.7.1、xiaomi-ble 1.11.0。

一、先弄清“蓝牙网关”在这里做什么
本文实现的是 ESPHome Bluetooth Proxy,不会让 GEEK 变成米家 App 中可添加的官方蓝牙网关。ES5 的状态通过加密广播发送,常规读取不需要持续 GATT 配对。GEEK 收到广播并转发给 HA,Xiaomi BLE 使用该设备的 bindkey 解密。
二、准备硬件和软件
- ESP32-S3-GEEK:本次板子实测 16 MB Flash、2 MB PSRAM,板载 ST7789 屏幕。
- 已在自己的米家账号绑定的领普 ES5 普通款。
- 可运行的 Home Assistant;本次使用路由器中的容器实例。
- 2.4 GHz Wi-Fi,且 HA 能访问 GEEK 的局域网地址和 TCP 6053 端口。
- 一台用于首次 USB 烧录的电脑,以及可选的米家显示器挂灯2。
硬件资料可参考 微雪官方文档。GEEK 内置屏幕接线已固定,不需要另外接杜邦线。


三、下载源码并填写私有配置
下载教程源码 ZIP。该包只包含可编辑源码和配置模板,个人 IP、Wi-Fi 密码、API key、BLE key等需自己添加。
解压后,复制 secrets.yaml.example 为 secrets.yaml,按包内说明下载思源黑体并保存为 fonts/ui.otf。Linux/macOS 可使用 Python 虚拟环境:
python3 -m venv .venv
source .venv/bin/activate
pip install "esphome==2026.9.1"
cp secrets.yaml.example secrets.yaml
python -c "import base64,secrets; print(base64.b64encode(secrets.token_bytes(32)).decode())"
把最后生成的一行填入 api_key。Windows 可使用 Python 虚拟环境对应的 Scripts 目录;USB 端口使用设备管理器看到的 COM 端口。不要把本文中的占位文字当成有效密钥。
wifi_ssid: "你的2.4GHz无线名称"
wifi_password: "你的无线密码"
api_key: "这里填新生成的Base64密钥"
ap_password: "至少8位的独立配网热点密码"
需要区分三种凭据:ESPHome API key 用于 HA 与 GEEK 通信;ES5 BLE bindkey 用于解密传感器广播;米家 Wi-Fi 设备的 Token 用于对应设备的接口认证。它们不能互相替代。BLE bindkey 是 32 位十六进制字符串,只应从自己的设备及账号获取。
使用 Xiaomi Cloud Tokens Extractor 获取 BLE KEY / Token
本次获取设备密钥使用的是 Xiaomi Cloud Tokens Extractor,作者为 Piotr Machowski。这是第三方开源工具,可读取自己小米账号下的设备 Token 和 BLE 加密密钥。作者项目主页与使用说明 · 下载页面。
Windows 可从作者页面下载 token_extractor.exe;Linux 或其他 Python 环境可下载源码,在工具目录创建虚拟环境,然后安装依赖并运行:
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python token_extractor.py
启动后会看到 Xiaomi Cloud Tokens Extractor 的标识,以及下面的登录方式选择:
Please select a way to log in:
p - using password
q - using QR code
p/q:
- 输入
p使用小米账号和密码登录,或输入q按提示扫码登录;账号须与绑定 ES5 的米家账号一致。 - 登录后选择设备所在的服务器地区。米家地区为中国大陆时选
cn;其他地区按实际情况选择。工具也支持留空查询可用地区。 - 在输出中找到“领普人体存在传感器ES5”,核对
MODEL: linp.sensor_occupy.es5b和自己的 MAC,避免拿错设备的密钥。 - 将这一条设备的 BLE KEY 填入 HA 的 Xiaomi BLE 手动密钥输入框;该字段就是本文说的 bindkey,应为 32 位十六进制字符串。
下面仅展示输出字段结构,所有凭据和设备标识均为占位内容,不能直接使用:
NAME: 领普人体存在传感器ES5
ID: <你的设备ID>
BLE KEY: <你的32位十六进制BLE密钥>
MAC: <你的ES5蓝牙MAC>
TOKEN: <工具返回的设备Token>
MODEL: linp.sensor_occupy.es5b
ES5 在 Xiaomi BLE 中填写 BLE KEY,不填写 TOKEN。米家显示器挂灯2等 Wi-Fi 设备的 Token 则用于支持该型号的 miIO/MIoT 接入方式;本文挂灯采用已有 Xiaomi Home 账号集成,不需要把 Token 填入 ES5 配置。若没有找到 BLE KEY,先核对账号、地区及设备绑定情况,不要用 Token 凑成密钥。工具输出包含可控制设备的凭据。
四、编译烧录蓝牙代理
源码中的核心配置如下,完整工程另外包含屏幕、按键和状态订阅:
esp32:
board: esp32-s3-devkitc-1
flash_size: 16MB
framework:
type: esp-idf
psram:
mode: quad
speed: 80MHz
api:
encryption:
key: !secret api_key
reboot_timeout: 0s
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
power_save_mode: NONE
esp32_ble_tracker:
scan_parameters:
active: false
bluetooth_proxy:
active: false
两个 active:false 的含义不同:扫描配置关闭主动扫描请求;代理配置关闭主动 GATT 连接能力。本文 ES5 状态读取使用广播即可,不意味着这种设置适合所有蓝牙设备。参考 ESPHome 蓝牙代理文档。
esphome compile geek.yaml
esphome upload geek.yaml --device /dev/ttyACM0
esphome logs geek.yaml --device /dev/ttyACM0
串口名称以本机为准;源码附带的 bash manage.sh 也可以完成同样操作。烧录看到写入校验通过后,还要观察设备启动和联网日志。
模板默认 DHCP,推荐在路由器按板子 MAC 保留地址。一次实际排查中,电脑开启有线网络共享,板子误拿到另一 DHCP 服务分配的网段,导致 Wi-Fi 已连接但 HA 无法访问。遇到这种情况,先检查实际 IP、网关和 DHCP 来源;不要直接复制别人的静态地址。
五、在 HA 添加 ESPHome 和 Xiaomi BLE
- 进入 HA“设置 → 设备与服务”,添加 ESPHome,填写 GEEK 的 IP、端口 6053,以及 secrets.yaml 中的 api_key。
- 确认 ESPHome 设备加载成功,蓝牙代理被 HA 识别。把 ES5 暂时放近一些,走动触发广播。
- 在发现的 Xiaomi BLE 设备中核对 ES5 的 MAC;也可手动添加 Xiaomi BLE。
- 选择手动输入蓝牙密钥,填写自己的 ES5 bindkey。密钥校验成功后才完成接入。
- 观察 Occupancy 存在状态,等待后续广播生成 Illuminance 光照实体。部分数据上报较慢,不要用 0 代替尚未收到的数据。
本次 HA 原生库识别到了 ES5BB,成功生成存在和光照实体。如果你的版本显示不支持,先核对具体型号及 Xiaomi BLE 官方支持说明,再按 HA 的正常升级流程处理。
验证时离开检测范围,等待传感器自己的无人延时结束,再回来走动。应能观察到真实 on → off → on。不要在开发者工具里写入模拟状态,然后把它当作硬件测试成功。
六、把 HA 状态回传到 GEEK 屏幕
在 HA 复制实际实体 ID,修改 geek.yaml 顶部的两个 substitutions,然后重新编译上传:
substitutions:
presence_entity: binary_sensor.你的ES5存在实体
illuminance_entity: sensor.你的ES5光照实体
screen.yaml 管布局、颜色、字体和背光;entities.yaml 管 HA 数据订阅与按键。屏幕使用 ESPHome 的 WAVESHARE-ESP32-S3-GEEK 模型:SCLK=12、MOSI=11、CS=10、DC=8、RESET=9、背光=7、BOOT=0。完整偏移和旋转配置已放在源码中。

短按 BOOT 切换蓝牙接收、存在状态、网络信息、时钟四页;双击循环旋转;长按一秒切换背光。HA 的 ES5 GEEK 配置区域提供 Screen Rotation,支持 0°、90°、180°、270°,横竖屏分别适配。修改后等待最多 5 秒写入 Flash,再断电;运行时四方向切换及重启恢复已做设备日志验证。
本次已经验证状态能从 HA 回传至固件,下方实拍展示了竖屏运行效果;照片不代替对全部方向和按键操作的现场验证。后续加中文文字时,记得将新字符加入对应字号的 glyphs。

七、联动米家显示器挂灯2
先确保挂灯在 HA 中已经是可控制的 light 实体。本次通过现有 Xiaomi Home 集成更新设备列表,添加 xiaomi.light.bar2,并分别验证开灯、关灯及设备状态读回。Xiaomi Home 的 auto 模式不等于已证明完全离线控制;本文没有做断网测试。
下面是可粘贴进 HA 单条自动化 YAML 编辑器的基础规则。将所有占位实体名称替换成自己的实体 ID;这里只控制开关,不覆盖亮度或色温。
alias: ES5 人来开灯人走关灯
triggers:
- trigger: state
entity_id: binary_sensor.你的ES5存在实体
to: "on"
- trigger: state
entity_id: binary_sensor.你的ES5存在实体
to: "off"
conditions: []
actions:
- choose:
- conditions:
- condition: state
entity_id: binary_sensor.你的ES5存在实体
state: "on"
sequence:
- action: light.turn_on
target:
entity_id: light.你的挂灯实体
- conditions:
- condition: state
entity_id: binary_sensor.你的ES5存在实体
state: "off"
sequence:
- action: light.turn_off
target:
entity_id: light.你的挂灯实体
mode: restart
规则只响应 on/off,unknown 和 unavailable 不会被当作无人。关灯时机以 ES5 自身的无人判断为准;本次没有再叠加等待。如果希望手动关灯后持续保持关闭,可另外设计“自动模式”开关,不宜简单高频强制同步灯光。实际部署还可加入 HA 启动及灯恢复在线时的状态同步。
资料与下载
教程源码托管于 Gitee,可进入仓库下载 ZIP,或使用 git clone https://gitee.com/qianmonai/es5-geek-home-assistant.git 获取。
教程源码(Gitee 仓库) · 微雪硬件文档 · ESPHome Bluetooth Proxy · MIPI SPI 屏幕驱动 · HA Xiaomi BLE · 小米官方 HA 集成






