我把国家电网数据塞进了 Home Assistant

我把国家电网数据塞进了 Home Assistant

前几天翻自己的项目记录,看到一个挺适合写成博客的东西:把国家电网的用电数据接进 Home Assistant。

这事的动机很简单。家里已经有 HA 了,温湿度、灯、插座、NAS、路由器状态都能看,唯独电费和用电量还停留在手机 App 里。每次想知道这个月用了多少电、余额还剩多少,都得打开网上国网。对一个已经习惯把东西接进仪表盘的人来说,这种割裂感很别扭。

所以就有了这个小项目:SGCC Home Assistant Bridge。它基于 ARC-MX/sgcc_electricity_new 二开,把 95598 / 网上国网里的余额、日用电、月度电费、年度用电、峰平谷尖分时电量,整理后发布到 Home Assistant。

从“能抓到”到“能一直用”

一开始想得挺轻松:网页能登录,页面上有数据,那 Selenium 抓一下不就完了。

真做起来才发现,国家电网这类站点很烦。登录态会过期,验证码会跳出来,页面上有些数据是前端状态里算出来的,还有一些历史范围取决于当时页面自然加载了多少。今天能抓到,不代表明天凌晨还能抓到;本机跑通,也不代表丢进 Docker、HAOS Add-on 里还能跑通。

后来项目的形态就慢慢变了。它不再像一个“爬虫脚本”,更像一个小型家庭服务:

定时任务
  -> 打开持久浏览器
  -> 检查登录态
  -> 必要时走账号密码和验证码
  -> 读取页面/Vue 状态
  -> 解析成统一数据
  -> 写 SQLite
  -> 发布到 MQTT / Home Assistant

这里最关键的一步是 SQLite。

以前写这种小工具,很容易把数据库当缓存:有就读,没有就重新抓。但用电数据接进 HA 后,它会出现在图表、自动化和长期历史里。网页临时炸一下,HA 不该立刻变成一堆 unavailable;MQTT 重启一下,也不该逼着我重新登录国网页面。

所以我把 SQLite 当成本地事实库用。每次抓取有没有开始、有没有成功、失败原因是什么、这次拿到了哪些日/月/年数据、最后发布给 HA 的值是什么,都落到库里。这样排障的时候不用对着几百行日志猜,也能把旧数据安全重发给 HA。

Home Assistant 里长什么样

接入方式后来也改了一轮。

最偷懒的办法是直接调用 HA 的 REST API 写 sensor.xxx 状态。这个办法很快,能看到数值,但它不像一个真正的设备。实体注册、设备归属、重启恢复这些体验都比较粗糙。

现在主路径走 MQTT Discovery。配置好 broker 以后,HA 里会自动出现一个类似“国网电费 ****1234”的设备,下面挂一组传感器:

  • 电费余额、预付费余额、应交金额;
  • 最近日用电;
  • 月度用电和月度电费;
  • 年度用电和年度电费;
  • 峰、平、谷、尖分时电量;
  • 最近抓取状态和时间。

Lovelace 里再配一个简单页面,就能看到余额卡片、日用电曲线、月度用电柱状图。到这一步,手机 App 里的数据才算真正进入了家里的仪表盘。

验证比开发更折磨

这个项目最容易翻车的地方其实是“看起来成功”。

比如 HA 里已经有国网实体了,传感器也有数值。直觉上会觉得 Add-on 跑通了。后来仔细查 MQTT 才发现,broker 里有 retained topic,HA 可以从旧的 retained 消息恢复实体。也就是说,实体存在只能证明“HA 现在有数据”,不能证明“刚才那轮 Add-on 真登录成功并发布了新数据”。

这类误判很坑人。后来每次验证都得拆开看:

  • Add-on 能不能安装;
  • 容器能不能启动;
  • 能不能打开国网页登录页;
  • 多模态接口有没有返回验证码坐标;
  • 点击验证码后有没有真的通过;
  • 有没有完成账号登录;
  • 本轮有没有写入新数据;
  • 新数据是不是从本轮发布到 MQTT 的。

最近一次 HAOS Add-on 测试就是个反例。安装、启动、网络、LLM 接口都正常,模型也返回了验证码点击坐标;但点击后验证码没过,随后二维码 fallback 超时。HA 里虽然还能看到国网实体和旧数据,但那不能算本轮真实抓取成功。

这件事提醒我,开源项目文档宁可保守一点。Add-on 安装启动通过,就写安装启动通过;真实账号抓取没完整证明,就别写成完整通过。否则别人照着文档复现,一失败就会怀疑自己哪里填错了。

国内镜像这种小事也很影响体验

项目现在同时发 GHCR 和阿里云 ACR。

这听起来像发布流程里的边角料,但对国内 Home Assistant 用户很现实。GitHub 页面能打开,不代表镜像能顺利拉下来。一个项目如果第一步卡在 docker pull,后面写再多教程都没意义。

所以 GitHub Actions 现在会在 main 分支发布 GHCR 镜像,也同步推到阿里云 ACR。国内用户可以直接把 image: 换成 ACR 地址。HAOS Add-on 目前还是 GitHub 仓库入口,如果以后要照顾完全小白的国内链路,再补 Gitee 元数据仓库会更顺。

写完之后的感觉

这个项目没有什么惊天动地的技术。浏览器、SQLite、MQTT、Home Assistant,都是很常见的东西。

但它挺像我喜欢的那类个人项目:从一个小不爽开始,慢慢磨成每天能用的基础设施。中间真正花时间的地方,也不在“怎么抓网页”这种标题党问题上,而是在那些很琐碎的边缘:登录态复用、验证码失败、旧数据干扰验证、容器里的网络、HAOS Add-on 的配置、国内镜像、脱敏截图、错误现场。

最后得到的东西也很朴素:打开 Home Assistant,就能看到家里这个月用了多少电,余额还剩多少,昨晚空调大概吃掉了多少度。

对我来说,这种反馈已经够爽了。

下一步大概会继续磨验证码点击。至少要把每轮验证码截图、模型坐标、实际点击点都保存下来,做成 overlay,别再靠日志里几个坐标猜偏移。等 Add-on 的真实抓取链路也稳定后,这个项目就可以更放心地推荐给别人用了。