重新读这份 ESP8266 固件时,我先改掉了旧稿里一句看起来很顺的话:页面拿到 200,不等于空调确认了状态。代码没有提供这样的回执。
2025 年 7 月 15 日的固定提交里,控制链路很短。ESP8266 自己开一个 Wi-Fi 热点,浏览器提交 HTTP 请求,处理函数更新几项本地变量,再调用红外发送函数。源码能说明调用顺序,不能让各层结果互相作证。
请求在代码里怎样走向发送函数
固件使用 AP 模式,地址固定为 192.168.4.1。DNSServer 将连入热点后的域名请求指向本地页面,ESP8266WebServer 提供页面与控制路由。loop() 里只处理 Web 客户端和下一条 DNS 请求,没有云端账号,也没有 MQTT 或家庭路由器配网。
页面上的开关、温度、模式、风速和睡眠按钮分别请求 /power、/temp_up、/temp_down、/mode、/speed 与 /sleep。处理函数通常先修改变量,再调用 sendMideaCode() 或关机发送函数,最后把 buildStateString() 的结果放进 HTTP 响应。
从源码顺序只能确认:正常处理路径在返回响应前包含发送函数调用,响应内容取自固件记录的状态。仅凭源码,无法知道一次真实请求是否走到该处,也无法确认红外发射管是否正确接线、脉冲是否从硬件发出,或空调是否识别并执行了这组时序。空调到开发板之间没有反向数据通道。
页面显示的是本地记录
buildStateString() 把开关、温度索引、模式索引、风速索引和睡眠标记拼成一串文本。浏览器收到文本后更新界面,所以屏幕展示的是 ESP8266 当前记住的设置。
这份记录有用。它能说明某次请求改变了哪几个变量,也让排查可以沿着浏览器、路由、状态、编码和发送函数逐段进行。但它不是空调的读数。有人使用实体遥控器改了温度,开发板并不知道,页面仍会停在原来的值。
/timer 更能说明两者的差别。这个路由连接的是 handleNotImplemented(),函数没有实现定时动作,却照样返回 200 和当前状态。这个反例把三层结果分开:HTTP 是否返回、固件是否调用发送函数、目标设备是否实际响应。三项不能互相代替。
三个字节怎样变成两帧时序
仓库把美的协议整理成 A、B、C 三个字节。A 使用固定用户码 0xB2;B 从风速表中选择,睡眠模式则暂时使用单独的字节;C 由温度表和模式表按位与得到。关机没有复用普通组合,而是使用 0xB2, 0x7B, 0xE0 这组负载。
generateMideaCode() 会依次编码字节及其反码,生成两帧原始时序。sendMideaCode() 再调用 sendRaw(..., 38)。这里的 38 是代码选择的载波频率参数,双帧也是固定实现的一部分。文章能确认的是这些数组、运算和函数调用,不能由此补出目标空调上的成功率。
睡眠字节 0xCE 在源码注释里带着一条警告:它是占位值,README 要求用实体遥控器重新捕获真实指令后替换。在捕获和复测完成前,页面上的“睡眠”按钮不能证明睡眠模式已经可用。
代码里还有几个空位
当前路线图里的定时、MQTT、断电状态保存和更多品牌型号都没有完成。仓库存在 GitHub Pages workflow,但 CNAME 仍是示例域名;配置文件存在,也不能替代一次公开部署验收。
主循环、路由和协议表已经给出一条可以阅读的程序路径。固定材料里没有目标型号、供电与接线、各按钮的实机结果、睡眠码捕获,也没有空调无响应时的串口或红外接收证据。因此这里只能写“代码调用了发送函数”,不能写“设备已经完成控制”。
这次修订只把 200 放回它实际能证明的位置。实机材料仍然缺失,页面本地状态与空调动作是否一致暂不下结论。