『瀚思彼岸』» 智能家居技术论坛

 找回密码
 立即注册
楼主: fentensoft

[经验分享] 当贝投影仪通过ESP32接入HA方案,代码已开源

[复制链接]

1

主题

41

帖子

476

积分

中级会员

Rank: 3Rank: 3

积分
476
金钱
435
HASS币
0
发表于 2023-12-19 19:34:33 | 显示全部楼层
shenmirenQUQ 发表于 2023-12-19 18:12
极米z6x,看大佬的帖子,https://bbs.hassbian.com/thread-16308-1-1.html,
实现了抓包用 安卓手机发送蓝 ...

我的刚好也是极米,ESP32用esphome是实现不了蓝牙广播的,只有用Arduino刷,以下是代码,开机就发送一次广播,收到MQTT消息为22也发送一次,可以整合进HA里
#include <Arduino.h>
#include <NimBLEDevice.h>
#include <NimBLEAdvertisedDevice.h>
#include "NimBLEEddystoneURL.h"
#include "NimBLEEddystoneTLM.h"
#include "NimBLEBeacon.h"
#include <WiFi.h>
#include <PubSubClient.h>

const char *ssid = "k";
const char *password = "passwd";
const char *mqtt_server = "192.168.1.62";
const char *topic = "ble/open";
const char *mqtt_username = "idummy";
const char *mqtt_password = "passwd";

WiFiClient espClient;
PubSubClient client(espClient);
const int blueLedPin = 2;

BLEAdvertising *pAdvertising;
bool mqttMessageReceived = false;

void callback(char *topic, byte *payload, unsigned int length)
{
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  
  // Print payload
  for (int i = 0; i < length; i++)
  {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  // 将 payload 转换为字符串
  String receivedMessage = "";
  for (int i = 0; i < length; i++)
  {
    receivedMessage += (char)payload[i];
  }

  // 检查 payload 内容是否为 "22"
  if (receivedMessage == "22") {
    Serial.println("Received message is '22'. Sending BLE broadcast.");
    publishBLE();
  }
}

void onBLEDataReceived(const char *data)
{
  Serial.print("Received BLE data: ");
  Serial.println(data);
}

void setup()
{
  Serial.begin(115200);
  connectWiFi();
  setupBLE();

  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void loop()
{
  if (WiFi.status() != WL_CONNECTED)
  {
    connectWiFi();
  }

  if (!client.connected())
  {
    reconnect();
  }

  client.loop();

  delay(1000);
}

void connectWiFi()
{
  Serial.println("Connecting to WiFi");
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(1000);
    Serial.println("Connecting...");
  }
  Serial.println("Connected to WiFi");
}

void setupBLE()
{
  NimBLEDevice::init("MyESP32");
  NimBLEServer *pServer = NimBLEDevice::createServer();
  pAdvertising = pServer->getAdvertising();

  NimBLEAdvertisementData advertisementData;
  advertisementData.setFlags(0x06);
  advertisementData.setManufacturerData({0x46, 0x00, 0x08, 0x36, 0xc9, 0x54, 0xa4, 0x23, 0x60, 0xFF, 0xFF, 0xFF, 0x30, 0x43, 0x52, 0x4B, 0x54, 0x4D});

  pAdvertising->setAdvertisementData(advertisementData);
  pAdvertising->start();
  delay(1000);
  pAdvertising->stop();
}

void reconnect()
{
  while (!client.connected())
  {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("ESP32Client", mqtt_username, mqtt_password))
    {
      Serial.println("connected");
      client.subscribe(topic);
      mqttMessageReceived = false; // Reset the flag when reconnecting
    }
    else
    {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

void publishBLE()
{

  Serial.println("publishBLE: " + String(mqttMessageReceived));
  String bleData = "okokokok6";
  NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
  NimBLEAdvertisementData advertisementData;
  advertisementData.setFlags(0x06);
  advertisementData.setManufacturerData({0x46, 0x00, 0x08, 0x36, 0xc9, 0x54, 0xa4, 0x23, 0x60, 0xFF, 0xFF, 0xFF, 0x30, 0x43, 0x52, 0x4B, 0x54, 0x4D});
  pAdvertising->setAdvertisementData(advertisementData);
  pAdvertising->start();
  delay(1000);
  pAdvertising->stop();
  client.publish(topic, bleData.c_str());

}
回复

使用道具 举报

109

主题

1580

帖子

4992

积分

元老级技术达人

积分
4992
金钱
3407
HASS币
30
发表于 2023-12-19 20:17:45 | 显示全部楼层
idummy 发表于 2023-12-19 19:34
我的刚好也是极米,ESP32用esphome是实现不了蓝牙广播的,只有用Arduino刷,以下是代码,开机就发送一次 ...

我也是极米,能不能步骤稍微写下,
回复

使用道具 举报

1

主题

41

帖子

476

积分

中级会员

Rank: 3Rank: 3

积分
476
金钱
435
HASS币
0
发表于 2023-12-19 21:41:24 来自手机 | 显示全部楼层
参照https://bbs.hassbian.com/thread-16308-1-1.html拿到广播数据,有二处,在我的代码内相应按照格式更改你的广播数据,比如我的极米rs pro广播数据<46000836 c954a423 60ffffff 3043524b 544d>,更改wifi 及mqtt设置,mqtt订阅/ble/open 数据22,用arduino刷进esp32即可
回复

使用道具 举报

55

主题

621

帖子

3804

积分

论坛元老

Rank: 8Rank: 8

积分
3804
金钱
3178
HASS币
20
发表于 2023-12-20 01:14:50 | 显示全部楼层
idummy 发表于 2023-12-19 19:34
我的刚好也是极米,ESP32用esphome是实现不了蓝牙广播的,只有用Arduino刷,以下是代码,开机就发送一次 ...

我修改你的代码 适用于当贝就  关闭使用adb命令关机
#include <Arduino.h>
#include <NimBLEDevice.h>
#include <NimBLEAdvertisedDevice.h>
#include "NimBLEEddystoneURL.h"
#include "NimBLEEddystoneTLM.h"
#include "NimBLEBeacon.h"
#include <WiFi.h>
#include <PubSubClient.h>

const char *ssid = "JDCwifi_404";
const char *password = "adminadmin";
const char *mqtt_server = "192.168.68.149";
const char *topic = "ble/open";
const char *mqtt_username = "mqtt";
const char *mqtt_password = "mqttt";

WiFiClient espClient;
PubSubClient client(espClient);
const int blueLedPin = 2;

BLEAdvertising *pAdvertising;
bool mqttMessageReceived = false;

void callback(char *topic, byte *payload, unsigned int length)
{
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  
  // Print payload
  for (int i = 0; i < length; i++)
  {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  // 将 payload 转换为字符串
  String receivedMessage = "";
  for (int i = 0; i < length; i++)
  {
    receivedMessage += (char)payload[i];
  }

  // 检查 payload 内容是否为 "22"
  if (receivedMessage == "22") {
    Serial.println("Received message is '22'. Sending BLE broadcast.");
    publishBLE();
  }
}

void onBLEDataReceived(const char *data)
{
  Serial.print("Received BLE data: ");
  Serial.println(data);
}

void setup()
{
  Serial.begin(115200);
  connectWiFi();
  setupBLE();

  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void loop()
{
  if (WiFi.status() != WL_CONNECTED)
  {
    connectWiFi();
  }

  if (!client.connected())
  {
    reconnect();
  }

  client.loop();

  delay(1000);
}

void connectWiFi()
{
  Serial.println("Connecting to WiFi");
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(1000);
    Serial.println("Connecting...");
  }
  Serial.println("Connected to WiFi");
}

void setupBLE()
{
  NimBLEDevice::init("MyESP32");
  NimBLEServer *pServer = NimBLEDevice::createServer();
  pAdvertising = pServer->getAdvertising();

  NimBLEAdvertisementData advertisementData;
  advertisementData.setFlags(0x06);
  advertisementData.setManufacturerData({0x46, 0x00, 0x7c, 0x9f, 0x73, 0x3d, 0x04, 0xc8, 0x38, 0xff, 0xff, 0xff, 0xff});

  pAdvertising->setAdvertisementData(advertisementData);
  pAdvertising->start();
  delay(1000);
  pAdvertising->stop();
}

void reconnect()
{
  while (!client.connected())
  {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("ESP32Client", mqtt_username, mqtt_password))
    {
      Serial.println("connected");
      client.subscribe(topic);
      mqttMessageReceived = false; // Reset the flag when reconnecting
    }
    else
    {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

void publishBLE()
{

  Serial.println("publishBLE: " + String(mqttMessageReceived));
  String bleData = "okokokok6";
  NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
  NimBLEAdvertisementData advertisementData;
  advertisementData.setFlags(0x06);
  advertisementData.setManufacturerData({0x46, 0x00, 0x7c, 0x9f, 0x73, 0x3d, 0x04, 0xc8, 0x38, 0xff, 0xff, 0xff, 0xff});
  pAdvertising->setAdvertisementData(advertisementData);
  pAdvertising->start();
  delay(1000);
  pAdvertising->stop();
  client.publish(topic, bleData.c_str());

}
回复

使用道具 举报

55

主题

621

帖子

3804

积分

论坛元老

Rank: 8Rank: 8

积分
3804
金钱
3178
HASS币
20
发表于 2023-12-20 01:18:59 | 显示全部楼层
adb关机 adb shell reboot -p
回复

使用道具 举报

4

主题

224

帖子

1302

积分

金牌会员

Rank: 6Rank: 6

积分
1302
金钱
1078
HASS币
0
发表于 2023-12-25 15:58:06 | 显示全部楼层
我的明基来电开机,关机用的是红外
回复

使用道具 举报

0

主题

4

帖子

60

积分

注册会员

Rank: 2

积分
60
金钱
56
HASS币
0
发表于 2024-1-16 17:07:59 | 显示全部楼层
ManufacturerData 这串实际上是投影仪的蓝牙地址 大小端反转下
回复

使用道具 举报

4

主题

70

帖子

459

积分

中级会员

Rank: 3Rank: 3

积分
459
金钱
389
HASS币
0
发表于 2024-1-17 13:01:44 | 显示全部楼层
有esp32 yaml抄作业吗?想蓝牙控制电视盒子开关机
回复

使用道具 举报

0

主题

16

帖子

110

积分

注册会员

Rank: 2

积分
110
金钱
94
HASS币
0
发表于 2024-1-18 15:38:59 | 显示全部楼层
真是个好文章,解开了我长久以来的疑问,当贝投影的遥控器是怎么开机的,没发觉它的遥控器有红外发射装置
不知道纯靠python能不能发Manufacturer Data包让投影开机
回复

使用道具 举报

1

主题

7

帖子

64

积分

注册会员

Rank: 2

积分
64
金钱
57
HASS币
0
发表于 2024-1-18 15:56:06 | 显示全部楼层
我也是当贝F3 AIR  眼睛看懂了 脑子还没懂
回复

使用道具 举报

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

本版积分规则

Archiver|手机版|小黑屋|Hassbian

GMT+8, 2024-4-27 22:35 , Processed in 0.055858 second(s), 30 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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