ESP32:能用QQ和蓝牙控制的空调遥控器
寝室是大学牲长期居住的地方,与家中不同的是,很多大学宿舍采用上床下桌方案,高昂的上下床成本带来了一系列问题,比如谁去关灯、谁去开门、谁去拿空调遥控器。除此之外,我们经常因为早八走得匆忙而忘记关闭空调,造成了不小的浪费。
懒惰是第一生产力,于是有了下面这个小项目,解放人类的同时还能为环保事业出一份力。
本文会包含项目部分实现细节,使用方法等。工程说明与解释可以移步GitHub仓库README文件查看。
项目仓库链接:https://github.com/HuXioAn/Dorm-Executor
目录
文章目录
- ESP32:能用QQ和蓝牙控制的空调遥控器
- 目录
- 功能演示
- 红外遥控
- 空调编码的抓取
- ESP32的RMT外设
- 程序实现
- 通信方案
- 蓝牙BLE
- WIFI+MQTT
- 利用QQ远程控制
- 通信模式切换逻辑的实现
- 总结
功能演示
红外遥控
控制空调的第一个难点是获得空调的红外编码。
空调编码的抓取
实不相瞒,这不是我第一次尝试红外控制空调,前几次都失败在红外编码上。使用各种单片机尝试网上不计其数的教程中给出的编码,空调却没有任何反应,有人说仅格力就有近40种空调编码格式,这无疑令人沮丧。
尝试无果后,我突然想到,最常见的遥控器虽然有调整编码的功能,但是绝大多数时候并不需要调整就能控制各种型号的空调,售价不到10元的遥控器又是怎么做到的?既然网上资料不靠谱,那就买一个遥控器用逻辑分析仪抓包看看(新买是因为原来这个不能拆)。
废了一些力将遥控器拆开,能明显的感觉到这款遥控器做工相当一般,仅使用单面板,不过能把功能实现并压低成本也是令人佩服。
![拆开后的遥控器](https://article-pic-pool.oss-cn-shanghai.aliyuncs.com/img/login_by_socket2/image-20220408230130565.png)
外接供电和分析仪探针之后,我们就可以对其进行抓包。
好家伙,抓出这么长的编码是没有想到的,网上的教程大多描述的是单个红框中的内容,然而遥控器却一次发送了三种编码。如果仔细查看会发现前两个红框中的编码几乎一模一样,仅有一位的差别,而第三个红框的内容与前两个框中的前半部分也非常相似。
我觉得这才是前面说提到的,遥控器总是能开箱即用的关键,如果有几十种编码,那么在民用家用空调产品上占据绝大多数的编码只有一两种,这种遥控器同时发送多种常用编码就能做到最大化覆盖产品。后面的实验中也印证了这一点,在我的程序里并没有第三个红框里的编码类型。
我将抓到的编码与网上教程进行对比,发现大部分的功能分布是相符的,仅有少部分,比如校验码、不同模式下温度的编码有些出入,在程序中能体现出来。
基于这些,我编写了红外编码生成等函数,可以在项目仓库的README中查看函数功能。更多抓包与编码细节不在这里呈现,如果有朋友需要编码的细节图片或者有任何疑问和建议麻烦移步公众号与我交流。
ESP32的RMT外设
一般来说,红外遥控器用38kHz信号进行载波,在网上很多的项目中可以使用单片机定时器来生成,但是ESP32提供了RMT外设。
将更多的工作交给硬件外设,能进一步简化软件逻辑实现。我们只需要设定好某一段电平的电平值与持续时间,RMT就会帮我们调制到设定的38KHz上面。减少大量不必要的外围电路或者软件等待。除此之外,RMT外设还可以用于控制WS2812等需要生成大量特定信号的场景。
程序实现
红外遥控序列可以用二进制来表示,再将1与0转换为对应的红外电平时间就可以发送给空调接收端,经过层层包装,形成了如下图的调用结构。
![调用流程](https://article-pic-pool.oss-cn-shanghai.aliyuncs.com/img/login_by_socket2/image-20220410210131649.png)
另外,为方便集成,另有remote_control
函数将所有流程包含,输入一定格式的字符串,自动完成所有的调用流程。
通信方案
通信方式无疑决定了产品的易用性、可用性,为了在寝室频繁断网断电的环境下维持最大的可用性,WIFI与BLE混合交替的控制方案是必要的。
蓝牙BLE
寝室在工作日实行11点断电、12点断网的策略,断电后路由器提供的WIFI也随之消失,此时BLE提供的近场通信能力就能基本满足室内的控制需求。
正如之前一篇文章《ESP32:蓝牙BLE控制M3508电机》中所述,蓝牙BLE非常适合传递少量控制信息。我大量复用了先前工程中的代码,只需要将关键业务处理部分更改为识别空调指令。BLE仅仅充当通信的途径,尽量的降低了与遥控服务的关系。
我们只要在GATT Profile的事件回调函数中ESP_GATTS_WRITE_EVT
事件处理部分添加对收到内容的识别,如果识别为控制指令,则将其发送至红外遥控任务队列。一直被读队列阻塞的发送任务就会进入运行态并开始解析指令等操作,完成红外遥控。
case ESP_GATTS_WRITE_EVT:{if (!param->write.is_prep){memcpy(data, param->write.value, param->write.len);data[19] = 0;xQueueSend(xQueue_IRremote, data, 100 / portTICK_PERIOD_MS);if (a_property & ESP_GATT_CHAR_PROP_BIT_NOTIFY){ //发送noticeesp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, gl_profile_tab[PROFILE_A_APP_ID].char_handle,strlen(data), (unsigned char *)data, false);}
//部分代码
不希望使用WIFI与MQTT的朋友可以查看仓库中仅包含BLE通信的工程。
WIFI+MQTT
我选择了WIFI与MQTT来实现远程操控,由于ESP32是不可能有公网IP的,我们需要具有公网IP的MQTT服务器帮我们完成消息的转发。我将MQTT Broker mosquitto
部署在一台云服务器上,同时为空调控制设立了对应的Topic。
WIFI与MQTT在ESP32上的使用是非常简单的,乐鑫官方给出了很多示例工程与库,这里不再赘述。部分难点在于两者的事件处理在突发情况下的切换逻辑与实现,这将在通信模式切换逻辑一节中提到。
利用QQ远程控制
选用WIFI+MQTT的远程操作方案又带来一个问题:客户端。近年来我们看到各大厂商纷纷布局的万物互联与智能家电平台,华为的智慧生活、小米的米家、苹果的HomeKit、开源的HomeAssistant部署在每个人的设备上。
同学的手机品牌各不相同,使用统一的接入平台不仅不现实、使用者学习成本也会直线上升。于是我想到了之前整活用的QQ机器人。
QQ作为国民软件之一,几乎每个大学生的手机都有安装,即时消息的实时性也能满足控制的需求,仅需开发小小的一个机器人插件即可。这样就形成了一个对于使用者与开发者成本都极低的客户端方案。
![控制关机](https://article-pic-pool.oss-cn-shanghai.aliyuncs.com/img/login_by_socket2/image-20220410223359981.png)
![提示功能](https://article-pic-pool.oss-cn-shanghai.aliyuncs.com/img/login_by_socket2/image-20220410223408954.png)
由于之前部署的QQ机器人在另一台云服务器上,所以在收到控制信息时,插件需要使用MQTT客户端连接到前文所说的MQTT服务端并发送控制信息。有关各类服务的选择可以阅读GitHub仓库README对应章节。
通信模式切换逻辑的实现
正如前面所说,宿舍电力、网络环境变化情况复杂,要使设备具有最大的可用性,就必须有应对外界事件的灵活处理策略。
在目前的设计中,WIFI+MQTT的优先级要高于蓝牙,在WIFI和MQTT服务可用时优先使用,只有在出现异常并重试数次失败后,才会进入蓝牙BLE模式。在蓝牙模式下,将会定时检查WIFI与MQTT是否可用,并在可用时立即切换。
上述的策略主要由任务函数mode_schedule_task
配合一个软件定时器、一个消息队列以及WIFI\MQTT\BLE事件处理回调的部分逻辑组成。其主要流程关系图如下:
很遗憾,一些程序上的处理细节没能在图中展现,可以查看工程代码或者与我交流讨论。
总结
总体实现过程还算顺利,在整合各项功能的过程中遇到的小问题也能比较快的解决掉。虽然目前能完整的实现各项功能,但仍有非常大的缺陷,比如配网目前还是硬写入,通信方面TLS与安全保护的缺失,低功耗方面还没能着手等一系列问题。我希望这会是一个长期演进的项目,不断地丰富和优化功能与安全性。
技术新人,水平有限。如果您有任何疑问与建议,请与我联系,万分感谢!
项目仓库地址:https://github.com/HuXioAn/Dorm-Executor
更多相关内容请见公众号: