找回密码
 立即注册

微信扫码登录

搜索
查看: 100|回复: 3

[进阶教程] 美的等蓝牙遥控器接入HomeAssistant

[复制链接]

1

主题

8

回帖

136

积分

注册会员

积分
136
金钱
127
HASS币
0
发表于 6 小时前 | 显示全部楼层 |阅读模式
众所周知,美的很难接入HA,特别是非智能款,提供了一个蓝牙遥控器,不支持WIFI

这类设备支持小程序《美的照明》,可以尝试是否能控制,如果能控制继续看下面教程。
教程不限于美的蓝牙遥控器,其他遥控器也可以尝试,如投影仪的
需求: 安卓手机,HA,ESP32
1. SI Connect 安卓端抓广播包
将手机靠近蓝牙遥控器,打开SCAN扫描
此时快速按蓝牙遥控器的按键,确保能搜到
主要看信号,贴上去一般-30dBm左右,出现后快速截图保存,因为蓝牙遥控器发送数据后会快速休眠
6ea0b1359447f56516dccea70eec7a8f.jpg
2.测试
先新增
3559a7d70b6d5212f614afc2e1235c4e.jpg
然后按照图片输入数据,点ADD Data Type,输入刚刚截图保存的数据
ecdde9d5ac0ba6c1d69bdd30925edf16_720.jpg
保存后回到主页,按下开启广播开关,如果灯有反应,继续下一步接入HA
3.ESPHOME接入
下面是参考代码,注意先把厂商ID改为截图里面的,然后刷入即可,代码加入了日志功能,会监听灯的状态反馈,方便加入双向状态同步(可选),其他开关可以自己用AI加入

esphome:
  name: ble-broadcast
  friendly_name: BLE_BroadCast

esp32:
  board: esp32dev
  framework:
    type: esp-idf

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "123"

ota:
  - platform: esphome
    password: "123"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Ble-Broadcast Fallback Hotspot"
    password: "123"

captive_portal:
   
sensor:
  - platform: internal_temperature
    name: "Internal Temperature"
   
bluetooth_proxy:
  active: true


# ========== BLE 发送部分 ==========
esp32_ble:

esp32_ble_server:
  id: ble_server
  manufacturer: "MyDevice"
  manufacturer_data: [0xA8, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

# ========== BLE 接收部分 ==========
esp32_ble_tracker:
  scan_parameters:
    interval: 300ms
    window: 150ms
    active: false
  on_ble_manufacturer_data_advertise:
    - manufacturer_id: "06A8"
      then:
        - lambda: |-
            if (x.size() != 24) return;
            
            // 只监听灯的状态广播: x[1] = 0x51
            if (x[1] != 0x51) return;
            
            // 验证是目标灯的特征
            if (x[0] != 0x81 || x[2] != 0x01 || x[3] != 0x65 || x[4] != 0x30 || x[5] != 0x57) {
              return;
            }
            
            // 用静态数组保存上一次的数据,用于去重
            static uint8_t last_data[24] = {0};
            static bool first_run = true;
            
            // 比较是否与上次数据相同
            bool same_as_last = true;
            if (first_run) {
              same_as_last = false;
              first_run = false;
            } else {
              for (int i = 0; i < 24; i++) {
                if (x != last_data) {
                  same_as_last = false;
                  break;
                }
              }
            }
            
            // 只有数据变化时才打印和处理
            if (!same_as_last) {
              // 保存当前数据
              for (int i = 0; i < 24; i++) {
                last_data = x;
              }
              
              // 打印完整数据
              ESP_LOGI("灯数据", "------- 数据变化 -------");
              ESP_LOGI("灯数据", "[0-7]   %02X %02X %02X %02X %02X %02X %02X %02X",
                x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7]);
              ESP_LOGI("灯数据", "[8-15]  %02X %02X %02X %02X %02X %02X %02X %02X",
                x[8], x[9], x[10], x[11], x[12], x[13], x[14], x[15]);
              ESP_LOGI("灯数据", "[16-23] %02X %02X %02X %02X %02X %02X %02X %02X",
                x[16], x[17], x[18], x[19], x[20], x[21], x[22], x[23]);
              ESP_LOGI("灯数据", "------------------------");
              
              // 正在发送时不更新状态
              if (id(is_sending)) {
                ESP_LOGD("灯数据", "正在发送中,跳过状态更新");
                return;
              }
              
              // x[11] = 0x01 是开, x[11] = 0x00 是关
              bool light_is_on = (x[11] == 0x01);
              
              if (light_is_on && !id(liangba_switch).state) {
                ESP_LOGI("凉霸", "状态变化: 开启");
                id(liangba_switch).publish_state(true);
              } else if (!light_is_on && id(liangba_switch).state) {
                ESP_LOGI("凉霸", "状态变化: 关闭");
                id(liangba_switch).publish_state(false);
              }
            }
# ========== 全局变量 ==========
globals:
  - id: is_sending
    type: bool
    initial_value: 'false'

# ========== 清空广播脚本 ==========
script:
  - id: clear_broadcast
    then:
      - delay: 500ms
      - lambda: |-
          std::vector<uint8_t> empty = {
            0xA8, 0x06,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
          };
          id(ble_server).set_manufacturer_data(empty);
      - delay: 500ms
      - globals.set:
          id: is_sending
          value: 'false'

# ========== 主开关 ==========
switch:
  - platform: template
    name: "凉霸"
    id: liangba_switch
    optimistic: false
    restore_mode: RESTORE_DEFAULT_OFF
   
    turn_on_action:
      - globals.set:
          id: is_sending
          value: 'true'
      - lambda: |-
          std::vector<uint8_t> mfr_data = {
            0xA8, 0x06,
            0x81, 0x0F, 0x30, 0xDC, 0x00, 0x73, 0x75, 0x55,
            0x76, 0x64, 0x12, 0x7C, 0xF5, 0x55, 0x76, 0xEC,
            0xC8, 0xE3, 0x35, 0x14, 0xC9, 0x94, 0xB8, 0xFE
          };
          id(ble_server).set_manufacturer_data(mfr_data);
          ESP_LOGI("凉霸", "发送开启指令");
      - script.execute: clear_broadcast
   
    turn_off_action:
      - globals.set:
          id: is_sending
          value: 'true'
      - lambda: |-
          std::vector<uint8_t> mfr_data = {
            0xA8, 0x06,
            0x81, 0x0F, 0x70, 0xDC, 0x00, 0x73, 0x75, 0x55,
            0x76, 0x00, 0x36, 0xFB, 0xC8, 0xE9, 0xCA, 0xEF,
            0xCB, 0x85, 0x23, 0xB0, 0x50, 0x2A, 0x52, 0xA3
          };
          id(ble_server).set_manufacturer_data(mfr_data);
          ESP_LOGI("凉霸", "发送关闭指令");
      - script.execute: clear_broadcast






回复

使用道具 举报

64

主题

656

回帖

5118

积分

论坛元老

积分
5118
金钱
4393
HASS币
20
发表于 6 小时前 | 显示全部楼层
大佬请教一下
esp32是监听到的还是不停扫描的呢?
回复

使用道具 举报

ZDZX 手机认证

6

主题

144

回帖

985

积分

高级会员

积分
985
金钱
835
HASS币
0
发表于 5 小时前 | 显示全部楼层
有道理啊,为了节约功耗蓝牙遥控器更倾向于做广播而不是做统信,这就回家试试
回复

使用道具 举报

195

主题

3033

回帖

9937

积分

元老级技术达人

积分
9937
金钱
6694
HASS币
80
发表于 4 小时前 | 显示全部楼层
我家里的电视遥控器是蓝牙的,只实现了开机,其他不只知道怎么复制,然后用esp32发送,
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Hassbian ( 晋ICP备17001384号-1 )

GMT+8, 2026-2-4 19:55 , Processed in 0.076620 second(s), 10 queries , MemCached On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表