现在很多电视的遥控器配备的都是蓝牙遥控器,所以无法使用红外信号来控制电视的开机。
前面的文章用树莓派配合hdmi-cec实现了电视的开机,但是电视有线外接了一个树莓派,多少有点难看,那么是否有更好的办法无线实现电视的开机操作呢?
之前在瀚思彼岸论坛有看到坛友利用此方法实现了极米的开机,按照此方法成功将家里的夏普电视成功接入到Homeassistant实现控制电视的开关机,并且之前抓包过夏普电视的app可以通过发送tcp包控制电视关机。
我家里的电视是夏普LCD-70MY6150A电视,如果有和我用的同型号的同学可以直接抄作业。
准备工作
- 准备一台ios设备, 下载安装 bluetooth smart scanner app
- 把电视或者投影仪关机
- 不停的按遥控器上的开机按键,这时在bluetooth smart scanner 上可以找到遥控器发射的ble advertisement信号
- 在上面的信号中, 找到manufactorer data
- 可以通过EFR connect这个安卓app发送蓝牙广播来验证能否使用上面的manufactorer data唤起电视或者投影
- 如果电视或者投影能成功开机,那么就说明成功了。
接下来就是如何让ESP32实现这个模拟发送这个蓝牙广播让Homeassistant来控制实现电视的开机
附上Arduino的代码
#include <ESP32BleAdvertise.h>
#include <WiFi.h>
#include <PubSubClient.h>
// WiFi 设置
const char* ssid = "wifi";
const char* password = "12345678";
// MQTT 设置
const char* mqtt_server = "192.168.199.100";
const char* mqtt_user = "mqtt";
const char* mqtt_password = "password";
const char* mqtt_topic = "homeassistant/switch/tv_switch/state";
const char* mqtt_command_topic = "homeassistant/switch/tv_switch/set";
// TCP 设置
const char* target_ip = "192.168.199.50";
const int target_port = 9688; // 目标端口号
const char* turn_off_msg = "SPRC#DIRK#19#1#2#1|22#";//发送TCP包来关闭电视
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);
SimpleBLE bleadv;
bool currentState = false; // 开关当前状态
void setup_wifi() {
delay(10);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void callback(char* topic, byte* payload, unsigned int length) {
String message;
for (unsigned int i = 0; i < length; i++) {
message += (char)payload[i];
}
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
Serial.println(message);
if (String(topic) == mqtt_command_topic) {
if (message == "ON") {
//发送蓝牙开机指令
currentState = true;
turnon();
// bleadv.begin(); //初始化蓝牙名
// uint8_t data[] = { 0x46, 0x00, 0x2E, 0x5F, 0xDF, 0xED, 0x84, 0x20, 0x70, 0xFF, 0xFF, 0xFF, 0xFF, 0x53, 0x48, 0x41, 0x52, 0x50 }; //蓝牙广播内容
// bleadv.advertise(data, 18);
// delay(5000);
// bleadv.end();
} else if (message == "OFF") {
send_tcp_message(turn_off_msg);
currentState = false;
}
}
}
void send_tcp_message(const char* message) {
WiFiClient client;
if (!client.connect(target_ip, target_port)) {
Serial.println("Connection to target IP failed");
return;
}
client.print(message);
client.stop();
}
bool check_tcp_status() {
WiFiClient client;
if (!client.connect(target_ip, target_port)) {
return false;
}
client.stop();
return true;
}
void reconnect() {
while (!mqttClient.connected()) {
Serial.print("Attempting MQTT connection...");
if (mqttClient.connect("ESP32Client", mqtt_user, mqtt_password)) {
Serial.println("connected");
mqttClient.subscribe(mqtt_command_topic);
} else {
Serial.print("failed, rc=");
Serial.print(mqttClient.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void turnon(){
if(currentState){
bleadv.begin(); //初始化蓝牙名
uint8_t data[] = { 0x46, 0x00, 0x2E, 0x5F, 0xDF, 0xED, 0x84, 0x20, 0x70, 0xFF, 0xFF, 0xFF, 0xFF, 0x53, 0x48, 0x41, 0x52, 0x50 }; //蓝牙广播内容
bleadv.advertise(data, 18);
}else{
bleadv.end();
}
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
setup_wifi();
mqttClient.setServer(mqtt_server, 1883);
mqttClient.setCallback(callback);
}
void loop() {
// put your main code here, to run repeatedly:
if (!mqttClient.connected()) {
reconnect();
}
mqttClient.loop();
static unsigned long last_check = 0;
if (millis() - last_check > 5000) { // 每5秒检查一次
last_check = millis();
bool status = check_tcp_status();
mqttClient.publish(mqtt_topic, status ? "ON" : "OFF");
if(status&¤tState){//如果电视现在是开机状态,并且广播还在发送中,取消发送
currentState=false;
}
turnon();
}
}
上面用到的蓝牙库的地址:https://github.com/peterk54/ESP32BLESimpleAdvertiser
在写入esp32s的时候遇到容量不足的问题
Sketch uses 1648605 bytes (125%) of program storage space. Maximum is 1310720 bytes.
Global variables use 57980 bytes (17%) of dynamic memory, leaving 269700 bytes for local variables. Maximum is 327680 bytes.
Sketch too big; see https://support.arduino.cc/hc/en-us/articles/360013825179 for tips on reducing it.
text section exceeds available space in board
Compilation error: text section exceeds available space in board
解决办法:Arduino IDE: Tools -> Partition Scheme:change "Default" to "Huge APP(3MB No OTA)"
把上面的代码编译写入ESP32后,最后在Homeassistant里的configuration.yaml配置这个mqtt开关
mqtt:
- switch:
name: "tv power"
state_topic: "homeassistant/switch/tv_switch/state"
command_topic: "homeassistant/switch/tv_switch/set"
qos: 0
retain: true
大功告成!
本文地址:https://www.blear.cn/article/esp32-bluetooth-tv-power
转载时请以链接形式注明出处
评论