找回密码
 立即注册

微信扫码登录

搜索
查看: 178|回复: 3

[教程系列] 再次折腾极米投影仪(M1)接入homekit

[复制链接]

19

主题

203

回帖

1947

积分

论坛技术达人

积分
1947
金钱
1725
HASS币
10
发表于 3 天前 | 显示全部楼层 |阅读模式
本帖最后由 lhy741059930 于 2025-8-21 22:43 编辑

OK,这是我第N次折腾极米的投影仪(接入Homekit),记录一下

硬件:苹果手机1台,安卓手机一台,ESP32 S3 zero (之前用剩下的,如果是买的话,应该ESP32 C3 更加便宜)吐槽一下,这玩意儿真不耐玩。 不知道怎么就不能通过串口读取数据,反复验证应该是坏了,不过功能正常。
软件(APP):Si Connect(苹果),EFR Connect(安卓)其实俩软件应该是同一个东西。一个手机应该就能搞定,我以前是用两个手机搞得。这次直接用了。 Arduino 就不用说了,必须要的。

1. 首先就是打开苹果上的
Si Connect 然后搜索,同时不停按极米遥控器的开关。会扫描到下面的这个广播信息。在有数据的时候赶紧截屏。
e25bc36555da2eebad4c590f8d9689fc.jpg

2.接着打开安卓的EFR Connect  到Configure页面 新增一个广播,并如图设置参数。当然参数应该是你用Si Connect获取到的,而不是直接抄我这个(当然如果你是M1,也许可以),新增打开广播开关,就应该可以看到投影机开机了。
07ec72f91a475b6ba49189d5a61f9f64.jpg     88f7610f5ecc001e5f3374f454dc063a.jpg

3.接下来,打开你的Arduino创建一个新项目,把代码放进去,根据你的wifi和mqtt修改一下参数,并选择好开发板,烧录进去。
#include "BLEDevice.h"
#include "BLEAdvertising.h"
#include "BLEServer.h"
#include <WiFi.h>
#include <PubSubClient.h>

BLEAdvertising* pAdvertising;
BLEServer* pServer;

// WiFi和MQTT配置
const char* ssid = "";     // 请替换为你的WiFi名称
const char* password = "."; // 请替换为你的WiFi密码
const char* mqtt_server = ""; // 请替换为你的MQTT服务器地址
const char* mqtt_username = "";       // MQTT用户名
const char* mqtt_password = "";  // MQTT密码
const char* mqtt_topic = "XGIMI/Power/set";      // MQTT主题

WiFiClient espClient;
PubSubClient client(espClient);

// 蓝牙控制变量
bool bleInitialized = false;
int broadcastCount = 0;
const int maxBroadcasts = 5;
const int broadcastInterval = 500; // 500ms间隔
unsigned long lastBroadcastTime = 0;

void setup() {
  Serial.begin(115200);
  delay(1000);
  
  // 连接WiFi
  setupWiFi();
  
  // 设置MQTT
  client.setServer(mqtt_server, 1883);
  client.setCallback(mqttCallback);
  
  Serial.println("系统初始化完成,等待MQTT消息...");
}

void setupAdvertising() {
  // 设置广播功率 (使用可用的功率等级)
  BLEDevice::setPower(ESP_PWR_LVL_N9); // 使用-9dBm,最接近-8dBm
  
  // 设置设备名称
  pAdvertising->setAppearance(0x03C0); // HID设备外观
  
  // 添加服务UUID 0x1812 (Human Interface Device)
  BLEUUID serviceUUID("1812");
  pAdvertising->addServiceUUID(serviceUUID);

  // 制造商数据内容 (从图片中的十六进制数据)
  uint8_t mfgData[] = {
    0x46, 0x00, // Company Code (Little Endian): 0x0046
    0x47, 0x80, 0x17, 0xB2, 0xC1, 0x84, 0x18, 0xFF, 
    0xFF, 0xFF, 0x30, 0x43, 0x52, 0x4B, 0x54, 0x4D
  };
  
  // 转换为Arduino String类型
  String manufacturerData = "";
  for (int i = 0; i < sizeof(mfgData); i++) {
    manufacturerData += (char)mfgData[i];
  }
  
  // 设置制造商数据
  BLEAdvertisementData advData;
  advData.setManufacturerData(manufacturerData);
  advData.setName("New adv");  
  advData.setCompleteServices(serviceUUID);
  advData.setFlags(0x06); // General Discoverable + BR/EDR Not Supported
  
  pAdvertising->setAdvertisementData(advData);
  
  // 设置广播参数 - 针对ESP32-S3优化
  pAdvertising->setMinInterval(160); // 100ms (160 * 0.625ms)
  pAdvertising->setMaxInterval(240); // 150ms
  pAdvertising->setScanResponse(true);
  
}

void loop() {
  // 保持MQTT连接
  if (!client.connected()) {
    reconnectMQTT();
  }
  client.loop();
  
  // 处理蓝牙广播
  handleBLEBroadcast();
  
  delay(100); // 短暂延时
}

// WiFi连接设置
void setupWiFi() {
  WiFi.begin(ssid, password);
  Serial.print("连接WiFi");
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  Serial.println();
  Serial.println("WiFi连接成功!");
  Serial.print("IP地址: ");
  Serial.println(WiFi.localIP());
}

// MQTT重连
void reconnectMQTT() {
  while (!client.connected()) {
    Serial.print("尝试MQTT连接...");
    
    if (client.connect("ESP32Client", mqtt_username, mqtt_password)) {
      Serial.println("MQTT连接成功!");
      // 订阅主题
      client.subscribe(mqtt_topic);
      Serial.println("已订阅主题: " + String(mqtt_topic));
    } else {
      Serial.print("连接失败, rc=");
      Serial.print(client.state());
      Serial.println(" 5秒后重试");
      delay(5000);
    }
  }
}

// MQTT消息回调
void mqttCallback(char* topic, byte* payload, unsigned int length) {
  String message = "";
  for (int i = 0; i < length; i++) {
    message += (char)payload[i];
  }
  
  Serial.println("收到MQTT消息: [" + String(topic) + "] " + message);
  
  // 检查是否为"open"消息
  if (message == "open") {
    Serial.println("收到开启指令,准备启动蓝牙广播...");
    startBLEBroadcastSequence();
  }
}

// 启动蓝牙广播序列
void startBLEBroadcastSequence() {
  if (!bleInitialized) {
    Serial.println("初始化蓝牙设备...");
    
    // 初始化BLE设备
    BLEDevice::init("New adv");
    // 创建BLE服务器
    pServer = BLEDevice::createServer();
    // 获取广播对象
    pAdvertising = BLEDevice::getAdvertising();
    
    // 设置广播参数
    setupAdvertising();
    
    bleInitialized = true;
    Serial.println("蓝牙初始化完成");
  }
  
  // 重置广播计数
  broadcastCount = 0;
  lastBroadcastTime = millis();
  
  // 开始第一次广播
  BLEDevice::startAdvertising();
  broadcastCount = 1;
  Serial.println("开始蓝牙广播 (" + String(broadcastCount) + "/" + String(maxBroadcasts) + ")");
}

// 处理蓝牙广播逻辑
void handleBLEBroadcast() {
  if (broadcastCount > 0 && broadcastCount < maxBroadcasts) {
    if (millis() - lastBroadcastTime >= broadcastInterval) {
      // 停止当前广播
      BLEDevice::getAdvertising()->stop();
      delay(50); // 短暂延时
      
      // 开始下一次广播
      BLEDevice::startAdvertising();
      broadcastCount++;
      lastBroadcastTime = millis();
      
      Serial.println("蓝牙广播 (" + String(broadcastCount) + "/" + String(maxBroadcasts) + ")");
    }
  } else if (broadcastCount >= maxBroadcasts) {
    // 完成所有广播,关闭蓝牙
    if (bleInitialized) {
      Serial.println("广播完成,关闭蓝牙以节省功耗...");
      BLEDevice::getAdvertising()->stop();
      BLEDevice::deinit();
      bleInitialized = false;
      broadcastCount = 0;
      Serial.println("蓝牙已关闭,系统进入低功耗模式");
    }
  }
}
[size=0.8em]
image.png
image.png

flows.json

14.18 KB, 下载次数: 0

评分

参与人数 1金钱 +12 收起 理由
隔壁的王叔叔 + 12 高手,这是高手!

查看全部评分

回复

使用道具 举报

19

主题

203

回帖

1947

积分

论坛技术达人

积分
1947
金钱
1725
HASS币
10
 楼主| 发表于 3 天前 | 显示全部楼层
很奇怪发布的时候缺失了一些内容。  不过导入这个流程就一目了然了。
回复

使用道具 举报

14

主题

1623

回帖

5350

积分

论坛元老

积分
5350
金钱
3713
HASS币
0
发表于 前天 00:14 | 显示全部楼层
感谢楼主分享
回复

使用道具 举报

188

主题

2813

回帖

9452

积分

元老级技术达人

积分
9452
金钱
6436
HASS币
80
发表于 前天 00:19 | 显示全部楼层
除了开机键,其他的功能是adb命令吗,还是也是蓝牙数据包发送
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-8-24 10:27 , Processed in 0.064565 second(s), 6 queries , MemCached On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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