记
开发日志
特效预览
特效优化预览站 · 非正式博客——本页只演示效果,不动真站。 其中 搜索、点赞、智能助手 为演示态(见各组件旁的「演示」标记),目录、摘要卡、洞察图谱、代码块为可直接落地的交互演示。
← 返回预览首页

查了两个月的配对:最后发现是 80 端口被网页占了

大金固件
文章摘要

家庭 App 能发现、点配对永远「不可连接」,网页后台却一直好用。嫌疑排了一长串,最后定案的是一行谁都没动过的库默认值。

约 3 分钟 · 1318 字 · 5 节 · 标签 大金固件
  1. 症状 — 家庭 App 能发现、配对永远「不可连接」,网页后台却一切正常
  2. 排查长征 — 数据库警告、配对残留、身份密钥、广播字段、网络侧逐项排除
  3. 关键证据 — 配对期间 HAP 服务零入站——手机根本没连进来
  4. 终局 — HAP 与网页后台同抢 80 端口,先绑定者赢
  5. 修复与同批欠账 — setPortNum(55555) 挪离 80,顺手补徽章、曲线、指示灯

症状

大金传感器自研固件(基于 HomeSpan)接苹果 HomeKit:家庭 App 里能发现这台设备,点配对,永远回一句「配件不可连接」。与此同时,设备自己的网页后台一直稳定可用,传感器读数全活。

发现得到、连不上、设备不像是坏的——这个组合,后来查了将近两个月。

排查长征:每条都是真试过的

  • 数据库校验警告:审计发现温度服务误放了一个规范明令禁止的特征,设备开机日志里那条 Warnings=1 就是它。修掉(2.1.1),警告清零——配对仍败。
  • 配对残留与码:后台加了配对管理:清残留、查控制器计数(0)、网页重设配对码——仍败。
  • 身份密钥写坏:恢复出厂、换全新身份重新配网——仍败。
  • 广播字段验尸:mDNS 广播逐字段核对 HAP 规范——地址、待配对标志、协议版本、类别全合规;也没有 IPv6 地址捣乱(一度是头号嫌疑)。
  • 网络侧:跨频段路径、家庭中枢状态、新建测试家庭、重启手机——逐项排除。
  • 生产商字段:拿同款硬件的成功案例逐项对表,设备信息六项齐全,没漏。

关键证据:手机压根没连进来

一版诊断固件留下了决定性的一条:配对尝试期间,设备 HAP 服务的日志零入站。

也就是说,失败发生在配对协议开始之前——手机根本没有连上 HAP 的监听口。此前所有围绕「配对协议本身」的努力,方向就错了。

终局:一行没人动过的默认值

2.2.8 的全量审计里,第一次有人去核对广播中 SRV 记录指向的端口到底归谁——此前几轮审计核过文本字段,唯独漏了端口归属:

  • HomeSpan 库的默认设置里,HAP 服务监听 80 端口。这是上游库的出厂默认,多年来原样继承,我方代码从未改过口;
  • 设备的网页后台,监听的也是 80。

两个服务抢同一个端口,先绑定者赢,失败一方不会有任何报错日志;而网页服务在启动时序上系统性地抢先。于是真相是:手机按广播连到 80 端口,敲配对的门——接走它的是网页服务,配对请求只换来一个 404。iOS 报「不可连接」,HAP 侧日志一片空白,网页后台「长年可用」。全部症状,一朝自洽。

修复与同批欠账(2.2.9)

修复只有一行:homeSpan.setPortNum(55555),把 HAP 挪离 80;网页保持 80,用户习惯零影响;配网模式的门户本来就独立,不受扰。

同版顺手补齐审计里发现的其他欠账:

  • 状态徽章:CO₂、甲醛、TVOC 三张卡此前根本没有状态徽章,这次补齐(阈值与固件既有分级同源,甲醛线用国标 0.08 mg/m³);
  • 历史曲线:存储样本从 8 字节扩到 12 字节,补上甲醛、TVOC 两列,曲线页签和 CSV 导出同步;
  • 三路指示灯分路:机身三盏灯改为 CO₂ / PM2.5 / TVOC 各独占一盏(此前甲醛与 TVOC 共用一盏,分不出谁超标),外加 Home Assistant 多一个 eCO2 实体。

体积账照旧 tight:成品 1,834,928 B,距分区上限只剩 80 B。2.2.9 已出包,待刷入做根因的最后验证。

这案子最值钱的教训:查不出的故障,先查最「理所当然」的那一层——端口、地址、归属,往往比协议本身更容易出错,也最容易被所有人默认「肯定没问题」。

演示代码块

下面两段代码不是正文,是用来演示代码块特效的(取自本博客自己的构建流程):语言标签、行号、复制按钮;超 12 行的默认折叠,点「展开」看全文。

shell演示代码
# 博客日常:加文章 -> 重新生成 -> 部署
python3 build.py
python3 deploy.py
# 预览站同款流程(新项目)
python3 build_preview.py
python3 deploy_preview.py
python演示代码
import re

def toc_sections(body_html):
    """从文章 HTML 里抽 h2 章节,供目录面板用。"""
    heads = []
    def _pick(m):
        text = re.sub(r"<[^>]+>", "", m.group(1))
        heads.append(text)
        return '<h2 id="sec-%d">%s</h2>' % (len(heads), m.group(1))
    body = re.sub(r"<h2>(.*?)</h2>", _pick, body_html)
    return body, heads

if __name__ == "__main__":
    html_out, sections = toc_sections(article_body)
    print("%d 节:%s" % (len(sections), " / ".join(sections)))
点赞计数只存本机(演示,无后端)

本篇目录

站内助手演示 · 未接后端
演示模式:我没有接后端,只会回这一句。正式版会接站内搜索与文章摘要;现在可以试试左侧目录、代码块复制和右侧搜索(演示)。