SunPower 光储接入 Home Assistant:逆向云端 API + androidTV 大屏监控
把一个「只看云」的太阳能一体机逆向接入本地 HA,再做自定义大屏挂到 Android TV。那个平台的不暴露了避免他们去改了数据规则后面不好抓,不过后期应该着手上 RS485 直接读取一体机实时的数据流和电池的保护板信息,后期。。...
背景
家里装了 SunPower 光储一体机(光伏 + 电池 + 逆变器),厂家只给 DM 云端平台和手机 App——没有本地 API,没有 Modbus,没有 MQTT。一体机 WiFi 推数据到,约 5 分钟一次刷新很慢。
问题是:
云端数据延迟高、刷新慢
跟家里其他智能设备没法联动
客厅电视上看不到实时发电 / 用电 / 电池状态
数据不在自己手里
目标:把数据拉到本地 Home Assistant,做自定义大屏面板,挂 Android TV(顺手 Claude 也做了个 androidTV 的 app) 当监控屏和前几期用androidTV 做监视器使用 ,APP 直接安装在
整体架构
☀️ 光伏阵列 → ⚡ SunPower 一体机 → 🔋 电池 / ⌁ 电网 / 🏠 负载
│
│ WiFi (~5min)
▼
☁️ DessMonitor 云端
(web.dessmonitor.com)
│
│ HTTPS + SHA1 签名
▼
🐍 DessMonitor Bridge (Docker)
(dessmonitor_to_ha.py, 120s 轮询)
│
│ REST API
▼
🏠 Home Assistant
(20+ sensor.dessmonitor_*)
│
│ /local/*.html
▼
🎨 自定义 UI 面板
├── sunpower-topology.html (动态拓扑)
├── sunpower-tv.html (TV 大屏)
└── sunpower-tv-legacy.html (兼容版)
│
▼
📺 Android TV (WebView APK)
第一步:逆向 DM 云端 API
这是整个项目最难的环节。厂家没公开 API 文档,一切靠抓包 + 逆向。
抓包
在 DM Web 端打开 Chrome DevTools → Network,登录后观察 XHR 请求,发现关键接口:
webQueryDeviceEs— 设备列表querySPDeviceLastData— 实时遥测(PV 电压电流、电池 SOC、电网功率等)webQueryDeviceEnergyFlowEs— 能流数据(光伏→负载 / 电池 / 电网的功率分配)
SHA1 签名认证
最大坑点:每个请求都要带 sign 参数(SHA1 哈希)。Web 端 JS 混淆过,但核心签名逻辑可以还原:
import hashlib
def make_sign(params: dict, secret: str) -> str:
sorted_items = sorted(params.items(), key=lambda x: x[0])
query_str = '&'.join(f'{k}={v}' for k, v in sorted_items)
sign_str = secret + query_str + secret
return hashlib.sha1(sign_str.encode()).hexdigest()
踩坑:
签名算法不是简单拼接,要加前后 secret(类似支付宝风格),key 必须字母排序
时间戳是秒级 Unix,本地时钟偏差 >5min 就签名失败
Token 会过期,Bridge 需要处理刷新逻辑
不同固件版本 JSON 结构可能不同,要做防御性解析
第二步:Bridge 同步脚本
dessmonitor_to_ha.py 跑在 Docker 里,120s 轮询 DessMonitor API,通过 HA REST API 写入 sensor。
核心流程:拉数据 → 映射到 20+ HA sensor → POST /api/states/<entity_id> → 梯形积分法本地累计 kWh → Git 同步持久化
踩坑:
HA REST sensor 默认是「拉」模式,但我们从外部「推」进去——用 Long-lived Access Token 认证
DessMonitor 的「总发电量」偶尔跳变(固件升级 / 数据修正),本地累计用梯形积分法 + Git 同步到 GitHub Private Repo 防丢
120s 轮询 vs 5min 云端更新,大部分拿到的是缓存,但偶尔能拿到更及时的能流数据
Docker 部署:
dessmonitor-bridge:
image: python:3.12-slim
volumes:
- ./dessmonitor_to_ha.py:/app/main.py
- ./ha-data:/app/ha-data
environment:
- DESSMONITOR_USERNAME=xxx
- DESSMONITOR_PASSWORD=xxx
- HA_URL=http://192.168.9.x:8123
- HA_TOKEN=xxx
command: python /app/main.py
restart: unless-stopped
第三步:HA Sensor 配置
Bridge 直接 POST /api/states/sensor.dessmonitor_xxx,HA 自动创建 entity。关键 sensor:
PV1/PV2 功率、电压(W, V)
电池 SOC、功率(W)
电网功率(W,负数 = 馈网)
负载功率(W)
今日 / 累计发电(kWh)
能流分配:光伏→负载、光伏→电池、电池→负载等
第四步:自定义 UI 面板
最有趣的部分。HA 的 www/local/ 目录可以放自定义 HTML,通过 http://HA_IP:8123/local/xxx.html 访问。
动态拓扑图
用 SVG 画动态能流拓扑图,实时显示光伏→一体机→电池 / 电网 / 负载的功率流向,能流线用 SVG 动画,功率越大线越粗越快。
TV 大屏
为客厅 Android TV 设计:大字体、高对比度,3 米外可读,60s 自动刷新。
兼容版
旧版 Android TV WebView 不支持 ES6,用 XMLHttpRequest 替代 async/await + fetch。
踩坑:
HA
/local/缓存问题——URL 加?v=timestamp强制刷新SMB 挂载 ≠ HA www——NAS 上改文件,HA 可能不会立即生效,要手动复制到 HA 真实 www 目录
CORS 限制——必须通过 HA 域名 /IP 访问
第五步:Android TV APK
极简 WebView 壳,全屏加载 HA 上的 TV 大屏 HTML。需要设置 setUseWideViewPort 和 FLAG_KEEP_SCREEN_ON 解决缩放和息屏问题。
成品截图


APP 的记录不是很准顺便集成一个在里面

踩坑速查
SHA1 签名 → 排序拼接 + 前后 secret + SHA1
时间戳偏差 → 秒级 Unix,确保本地时钟准确
Token 过期 → Bridge 加刷新逻辑
数据字段不固定 →
.get()+ 默认值HA REST Sensor 写入 → Bridge 主动 POST + Long-lived Token
累计电量丢 → 梯形积分 + Git 同步到 Private Repo
轮询 vs 云端更新 → 120s 间隔,接受大部分是缓存
HA /local/ 缓存 → URL 加
?v=timestampSMB ≠ HA www → 手动复制到 HA 真实目录
CORS 限制 → 始终通过 HA 域名 /IP 访问
Android TV 缩放 →
setUseWideViewPort+ initial scale屏幕常亮 →
FLAG_KEEP_SCREEN_ON
技术栈
数据源:DessMonitor 云端 API(逆向,SHA1 签名)
Bridge:Python 3.12, Docker, requests, hashlib
Home Assistant:Docker (host network), 20+ REST sensor
UI 面板:原生 HTML/CSS/JS + SVG 动画,无框架
TV 展示:Android TV APK (WebView 壘)
持久化:GitHub Private Repo
反思与展望
数据主权:所有数据落地本地 HA + Git,不再依赖可能跳变的云端数值
延迟:一体机→云端→Bridge→HA 约 5-7 分钟,厂家开放本地 Modbus/TCP 可做到秒级
UI 演进:从 Hermes 写的初版到 Claude 重新设计,UI 经历多轮迭代,每次踩「覆盖 /www」的坑
未来:加历史数据图表(Grafana + InfluxDB),自动化策略(SOC 低时关非必要负载)
by 数码罗记 · godsun.pro