tfohlmeister/berbel-remote
GitHub: tfohlmeister/berbel-remote
基于 ESP32 的 BLE 遥控器模拟器,通过逆向工程 Berbel 抽油烟机协议并桥接 MQTT,实现 Home Assistant 智能家居集成。
Stars: 11 | Forks: 3
# Berbel BFB 6bT - BLE 遥控器模拟器
[](https://github.com/tfohlmeister/berbel-remote/actions/workflows/test.yml)
基于 ESP32 的 **Berbel BFB 6bT** 遥控器(货号 1090045)模拟器,通过 MQTT 实现完整的 Home Assistant 集成。已通过 Berbel Skyline Frame 抽油烟机测试,但 BFB 6bT 遥控器同样兼容其他 Berbel 抽油烟机。
## 功能特性
- **BLE 遥控模拟** - 完整模拟原版 Berbel BFB 6bT 遥控器
- **Home Assistant 集成** - 通过 MQTT 自动发现自动创建实体
- **实时状态解码** - 读取来自抽油烟机的 9 字节状态数据包(灯光、风扇、位置、延时运行)
- **OTA 更新** - 通过 ArduinoOTA 进行无线固件更新
- **NimBLE 协议栈** - 相比 Arduino BLE (Bluedroid) 节省了约 100KB 的堆内存,为 WiFi + MQTT 留出了空间
## 兼容的抽油烟机
BFB 6bT 遥控器适用于配备了 **berbel Connect 2.0**,且生产日期在 **2020 年 11 月**之后的 Berbel 抽油烟机。只要支持原版遥控器的抽油烟机,本模拟器应该都能兼容。
**岛式抽油烟机:** Skyline Frame, Skyline Edge, Skyline Curve, Skyline Sound, Skyline Light, Skyline Round, Ergoline, Glassline, Blockline, Smartline
**壁挂式抽油烟机:** Glassline, Blockline, Smartline
**紧凑型抽油烟机:** Ergoline, Glassline, Formline, Smartline
**内置式抽油烟机(2021 年 4 月起):** Glassline, Firstline, Firstline Touch, Firstline Unseen
**风机模块(2021 年 4 月起):** Firstline
## 硬件要求
- ESP32 开发板(任何带有 BLE + WiFi 的型号)
- 兼容的 Berbel 厨房抽油烟机(见上述列表)
- MQTT broker(例如 Mosquitto)
- Home Assistant(可选,用于智能家居控制)
## 快速开始
1. **克隆并配置:**
git clone https://github.com/tfohlmeister/berbel-remote.git
cd berbel-remote/BerbelRemote
cp src/config.example.h src/config.h
2. **编辑 `src/config.h`**,填入您的 WiFi 和 MQTT 凭证。如果您的抽油烟机没有伸缩罩(升降功能),请将 `HOOD_HAS_COVER` 设置为 `false`,以禁用 Position、Hochfahren、Herunterfahren 和 Cover State 实体。
3. **构建并烧录:**
pio run -t upload # USB(首次烧录)
pio run -e ota -t upload # OTA(后续更新)
4. **与抽油烟机配对:**
- 使抽油烟机进入配对模式(在 Skyline Frame 上:同时按住机身上的电源键和灯光键 5 秒钟;其他型号可能有所不同)
- ESP32 将自动连接
- 连接成功后,板载 LED 将停止闪烁
5. **监控:**
pio device monitor
## Home Assistant 实体
所有实体均通过 MQTT 自动发现自动创建。
| 实体 | 类型 | 描述 |
|--------|------|-------------|
| Oberlicht | Light | 上部/氛围灯开关 |
| Unterlicht | Light | 炉灶照明灯开关 |
| Lufter | Select | 风扇速度:Aus, Stufe 1-3, Power |
| Ausschalten | Button | 关闭电源(启动延时运行计时器) |
| Nachlauf | Switch | 切换延时运行计时器 |
| Position | Select | Oben(收回) / Unten(展开) *(仅限 `HOOD_HAS_COVER`)* |
| Hochfahren | Button | 无条件上升 *(仅限 `HOOD_HAS_COVER`)* |
| Herunterfahren | Button | 无条件下降 *(仅限 `HOOD_HAS_COVER`)* |
| BLE Verbindung | Binary Sensor | BLE 连接状态(诊断) |
| Cover State | Sensor | 盖板位置:up/moving up/moving down/down(诊断) *(仅限 `HOOD_HAS_COVER`)* |
| Status Raw | Sensor | 用于调试的原始 9 字节十六进制数据(诊断) |
## 按键代码
BFB 6bT 遥控器上全部 13 个按键的完整映射关系,附带 Berbel 手册中的官方功能名称。
| 代码 | 遥控器标签 | 官方功能(Berbel 手册) |
|------|-------------|-----------------------------------|
| 0x01 | Power | EIN/AUS |
| 0x02 | Fan 1 | Leistungsstufe 1 |
| 0x03 | Fan 2 | Leistungsstufe 2 |
| 0x04 | Fan 3 | Leistungsstufe 3 |
| 0x05 | Fan P | Leistungsstufe POWER |
| 0x06 | Cooktop Light | Kochfeld-Beleuchtung |
| 0x07 | Sync | Synchronisation |
| 0x08 | Recirculation | Umluftbetrieb / Kontrollanzeige Filter |
| 0x09 | Raise | Liftfunktion "Heben" |
| 0x0A | Effect Light | Effektbeleuchtung |
| 0x0B | Multi | Multifunktionstaste |
| 0x0C | Afterrun | Nachlauffunktion |
| 0x0D | Lower | Liftfunktion "Senken" |
协议:在特征值 `f004f002-...-berbel` 上进行 2 字节通知。按下:`[code, 0x00]`,松开:`[0x00, 0x00]`。
## 抽油烟机状态字节
抽油烟机会在特征值 `f004f001-...-berbel` 上发送 9 字节的状态数据包。所有值均基于位掩码。
| 字节 | 掩码 | 含义 |
|------|------|---------|
| [0] | 0x10 | Fan Stufe 1 |
| [1] | 0x01 | Fan Stufe 2 |
| [1] | 0x10 | Fan Stufe 3 |
| [2] | 0x09 | Fan Power |
| [2] | 0x10 | Oberlicht(上部灯) |
| [4] | 0x10 | Unterlicht(炉灶灯) |
| [4] | 0x01 | 盖板正在上升(收回) *(仅限 `HOOD_HAS_COVER`)* |
| [5] | 0x90 | Nachlauf(延时运行计时器已激活) |
| [6] | 0x01 | 盖板正在下降(展开) *(仅限 `HOOD_HAS_COVER`)* |
在连接时会发送同步数据包(所有字节均为 `0x11`),应将其忽略。
## BLE 协议摘要
### MAC 地址 OUI 过滤
抽油烟机仅接受来自具有 Texas Instruments OUI 的设备的连接:
- `88:01:F9:xx:xx:xx`
- `30:AF:7E:xx:xx:xx`
ESP32 的 MAC 地址会在 BLE 初始化之前被伪装:
```
uint8_t ti_mac[6] = {0x88, 0x01, 0xF9, 0xAA, 0xBB, 0xCC};
esp_base_mac_addr_set(ti_mac); // BEFORE NimBLEDevice::init()
```
### 配对
- 传统配对(无安全连接)
- Just Works(无输入,无输出)
- 仅 LTK(无 IRK,无 CSRK)
- 抽油烟机作为 Central(发起配对)
### GATT 服务顺序
必须严格按照此顺序创建服务(抽油烟机会进行验证):
1. Device Information (0x180A)
2. Battery Service (0x180F)
3. HID Service (0x1812)
4. Berbel Custom Service (`f004f000-...-berbel`)
### 广播
仅使用带有 Flags + Service Data 的原始 `ADV_IND`。没有设备名称,没有 HID UUID,没有外观。Service Data 的值必须为 `0x01`(活动状态)。
## 逆向工程过程
1. 使用 **nRF52840 Dongle** 作为嗅探器,结合 **Wireshark/nRF Sniffer 插件**,捕获了原装遥控器与抽油烟机之间的 BLE 通信流量
2. 分析了广播数据、GATT 服务结构和 SMP 配对交换过程
3. 通过反复试验发现了 MAC OUI 过滤机制(带有 Espressif OUI 的 ESP32 会被静默拒绝)
4. 通过按下每个按键并记录通知,映射了全部 13 个按键代码
5. 通过系统地切换每个功能,解码了 9 字节的抽油烟机状态数据包
6. 使用另一个遥控器(不同的 TI OUI,但协议完全相同)确认了这些发现
有关完整的协议文档,包括 GATT 服务表、广播数据以及 Wireshark 分析命令,请参阅 [REVERSE_ENGINEERING.md](REVERSE_ENGINEERING.md)。
## 项目结构
```
berbel-remote/
├── BerbelRemote/ # ESP32 firmware (PlatformIO)
│ ├── src/
│ │ ├── main.cpp # Firmware: BLE/WiFi/MQTT wiring
│ │ ├── berbel_protocol.h # Pure protocol logic (unit-tested)
│ │ ├── config.example.h # WiFi/MQTT config template
│ │ └── config.h # Your credentials (gitignored)
│ ├── test/
│ │ └── test_protocol/ # Host-side unit tests (Unity)
│ └── platformio.ini # Build configuration
├── .github/workflows/test.yml # CI: unit tests + firmware build
├── REVERSE_ENGINEERING.md # Full protocol documentation
├── berbel_button_map.json # Button code mapping (machine-readable)
├── LICENSE # MIT License
└── README.md
```
## 测试
逆向工程得出的协议逻辑(状态解码、风扇/盖板状态、JSON
解析)位于 `src/berbel_protocol.h` 中,作为无依赖函数存在,因此
可以在没有 ESP32 的情况下在主机上进行单元测试:
```
cd BerbelRemote
pio test -e native
```
CI 会在每次推送时运行这些测试以及完整的固件编译检查(参见
顶部的测试徽章)。硬件 I/O(BLE、WiFi、MQTT、OTA)在
设备上进行测试,而不是在 CI 中。
## 许可证
本项目采用 [MIT 许可证](LICENSE) 授权。
## 免责声明
这是一个基于私人逆向工程工作的非官方社区项目。它与 **berbel Ablufttechnik GmbH** 没有任何形式的附属、认可或关联关系。
所有商标,包括 "Berbel",均属于其各自的所有者,此处使用它们仅用于描述兼容性。
对于您的硬件可能受到的任何损坏,作者不承担任何责任。使用风险由您自己承担。
标签:ESP32, Home Assistant, 智能家居, 物联网, 蓝牙低功耗