👁 2389

家里装了一套 SunPower 光储一体机(光伏 + 电池 + 逆变器),厂家只给了个云端平台和手机 App——没有本地 API,没有 Modbus,没有 MQTT。数据 5 分钟才刷一次,想跟家里其他设备联动?没门。想在客厅电视上看实时发电?做梦。

那就自己干。目标很明确:把数据从云端拉到本地 Home Assistant,再做一个 TV 大屏看板挂在客厅电视上,随时扫一眼就知道发了多少电、用了多少电、电池还剩多少。

客厅电视实拍 — 大屏看板整体效果
客厅电视实拍 — 大屏看板整体效果

Phase 1:数据接入(5月20日前)

这是整个项目最难的部分。厂家没有公开 API 文档,一切靠抓包 + 逆向。

逆向云端 API

在厂商 Web 端打开 Chrome DevTools → Network,登录后观察所有 XHR 请求,发现三个关键接口:

  • webQueryDeviceEs — 设备列表
  • querySPDeviceLastData — 实时遥测(PV电压电流、电池SOC、电网功率等)
  • webQueryDeviceEnergyFlowEs — 能流数据(光伏→负载/电池/电网的功率分配)

每个请求都需要 SHA1 签名认证,混淆过的 JS 签名逻辑可以还原:排序拼接 + 前后 secret + SHA1。

import hashlib
def make_sign(params: dict, secret: str) -> str:
    query_str = '&'.join(f'{k}={v}' for k, v in sorted_items)

踩了一堆坑:

  • 签名算法不对:一开始以为简单 SHA1 拼接,结果 403。后来发现要加前后 secret,而且 key 必须按字母排序
  • 时间戳格式:秒级 Unix 时间戳,服务器对时间窗口有校验,本地时钟偏差超过 5 分钟就签名失败
  • Token 过期:登录 token 有效期有限,Bridge 脚本需要处理刷新逻辑

Bridge 同步脚本

写了一个 Python 脚本,跑在 Docker 容器里,每 120 秒轮询一次云端 API,通过 HA REST API 写入 sensor。28 个传感器覆盖光伏/负载/电池/电网/温度/能量统计等。

核心流程:拉数据 → 映射到 20+ HA sensor → POST /api/states/ → 梯形积分法本地累计 kWh → Git 同步持久化

又踩坑:厂商的”总发电量”偶尔跳变(固件升级/数据修正)。Docker 容器重建后本地累计数据会丢。方案:梯形积分法本地累计 + Git 同步持久化。


Phase 2:第一版拓扑图(5月20日)

这是最初的版本,一个纯桌面版的动态拓扑图:

  • SVG 画 5 个节点(光伏、逆变器、电池、负载、电网)
  • 3 条能流线,简单的虚线动画
  • HA REST API 60 秒轮询数据
  • 在电脑浏览器里看,还不错

局限: 没有大屏优化,字体太小电视上看不清;没有统计卡片,只有拓扑图;没有天气/预测/家电控制;能流方向逻辑简单,经常显示错误。

这个版本是后面所有迭代的起点,备份文件还留着。


Phase 3:TV 大屏版诞生(5月21日~22日)

从拓扑图演化成 TV 大屏看板:

  • 大字体、高对比度,3 米外可读
  • 4 大主卡片:☀️光伏发电 / ?家庭用电 / ?电池状态 / ⚡市电
  • 电池 SOC 进度条
  • 底部数据条:今日发电/年度/累计/收益
  • 60 秒自动轮询

踩坑继续:

  • ES6兼容:旧版 Android TV WebView 对 ES6 支持不好,async/await 和 fetch 全报错。做了兼容版,改用 XMLHttpRequest
  • HA /local/ 缓存:修改 HTML 后浏览器还是旧版。HA /local/ 路径返回 Cache-Control: max-age=2678400(31天缓存)
  • TV 乱码:UTF-8 被当 Latin-1 解码。HA 返回 Content-Type: text/html 无 charset,Android WebView 默认 Latin-1。patch HA static.py 加 charset=utf-8

Phase 4:功能大升级(5月31日~6月4日)

文件从 ~37KB 飙到 ~87KB,功能爆发式增长。用 Claude Code 大幅重构,加入大量新功能。

能流拓扑重写

  • 5 节点 SVG 拓扑重新设计:光伏→能源枢纽→罗府,电池和电网在下方
  • 动态虚线动画:有能流时流动,无能流时极淡
  • 线上标注:PV 线上方黄色标注电流电压,放电线下方粉色标注

踩了三个关键坑:

  • 能流线不显示:电池放电时线完全不可见!根因:setFlow() 函数只对 flowPv 和 flowLoad 调用了,对电池充放电和电网线没调用。flow-idle class 从未被移除,opacity=0.12
  • 充电线不亮:PV 发电 2700W、负载 700W、多出 2000W 在充电池,但充电线不亮!根因:battery_estimated_power 传感器充电时返回 0!充电功率在 pv_to_battery_power 传感器里。修复:优先用 pvToBat > 20,fallback 用 batV × batInA
  • 能量守恒:之前各线独立判断,可能出现逻辑矛盾。引入能量守恒公式:supplyW = PV + 电网取电 + 电池放电 = 负载 + 充电。实测验证 PV=2724, supply=2724, demand=2724 ✅

发电趋势图

Canvas 绘制 06:00-20:00 实际发电曲线(绿色实线)+ 预测曲线(黄色虚线),当前时间标记线,每 30 分钟数据点。

电池状态升级

SOC 百分比 + 进度条 + 电压/电流明细 + 环境光呼吸效果:

  • SOC>30% 绿光
  • 20-30% 黄光
  • <20% 红光闪烁

动态频率:SOC 越低闪烁越快 duration = max(0.5, SOC/100 × 3)

天气卡片

wttr.in API(Open-Meteo 在国内不稳定),当前温度 + 天气图标 + 7 日预报。

家电控制面板

从硬编码改为 HA API 自动发现,8 个设备 3 种控制类型:simple(空调风扇)、multi(灯光亮度色温)、complex(弹窗控制),过滤掉 LED 指示灯只保留真实可控设备,玻璃拟态弹窗效果。

语音播报

模式切换时语音提醒(Web Speech API),5 分钟冷却,10% 变化重置。

温度监控

  • 能源枢纽 = 入户开关温度
  • 罗府 = 房间温湿度
  • PV = 天气 + 10℃(白天发电>50W)/ 天气原值(夜间)

Phase 5:1080p 适配 + 全屏(6月5日)

文件:~87KB → ~109KB

纵向溢出问题

1080p 电视需要上下滚动才能看到底部数据。修复:

1. 紧凑布局:全面缩减 CSS 间距/padding/margin/font-size 约 30-40%

2. autoScale() 兜底:JS 检测内容高度超出视口时,transform: scale() 整体缩放(0.7~0.95)

3. body { height: 100vh; overflow: hidden } 强制一屏

踩坑:一度把 min-height:100vh 改成 height/overflow-y:auto 再改 overflow:hidden,中间过程把 flex 能流布局压死了。Fullscreen API 本身足够,不需要改 min-height。

全屏功能

  • 双击页面 → 进入全屏
  • 右上角 ⛶ 按钮 → 切换全屏
  • F 键快捷键
  • ESC 退出
  • 首次打开显示提示(4秒后消失)
TV 大屏实时效果 — 能流拓扑 + 发电趋势 + 电池状态
TV 大屏实时效果 — 能流拓扑 + 发电趋势 + 电池状态

Phase 6:Android APK(5月22日~6月4日)

从 WebView 壳到可用的 APK。

架构

MainActivity (Activity, 非 AppCompatActivity)
  └── WebView
       ├── settings: JavaScript=true, LOAD_NO_CACHE
       ├── usesCleartextTraffic=true
       ├── network_security_config.xml: 允许 HTTP
       └── URL: http://内网IP:8123/local/sunpower-tv.html?token=xxx

踩坑最多的一段:

  • Android 9 闪退:IPTV 盒子装 APK 后闪退。根因:AppCompatActivity 报 ClassNotFoundException: androidx.window.extensions。修复:改用 Activity,minSdk 从 28 降到 24
  • HTTP 明文禁止:Android 9 默认禁止 HTTP 明文请求,HA 是 HTTP。添加 network_security_config.xml 允许明文。之前天气能用是因为 wttr.in 是 HTTPS
  • WebView Token 注入时序:onPageFinished 注入 window.HA_TOKEN 太晚,JS 轮询已用空 token 请求,全部 401。最终方案:URL 带参数 ?token=xxx + iframe postMessage + 硬编码三重 fallback
  • 对话脱敏破坏 JS:Hermes redact_secrets: true 把 new URLSearchParams 变成 *** URLSearchParams,语法错误导致整个 IIFE 不执行。根因修复:redact_secrets 改为 false
APK 在 IPTV 盒子上运行 — 启动到数据加载
APK 在 IPTV 盒子上运行 — 启动到数据加载

构建信息

  • minSdk=24, targetSdk=34
  • Debug APK 大小:~14MB → 最终 ~1.5MB(去掉 AppCompat)
  • 不打包 HTML,加载 HA 服务器版本
  • HTML 更新无需重编 APK

Phase 7:收尾打磨(6月5日~6月6日)

6月5日整理了完整的开发日志,包含系统架构、28 个传感器映射、UI 模块详解、踩坑实录、部署方案、关键代码片段。

底部新增行:

  • ☀️今日发电量(黄色大字)
  • ?罗府日用量(橙色大字)

PWA 方案:生成 manifest.json、sw.js、icon-192/512.png,手机/平板也能安装为独立 App。

电池呼吸灯效果 — SOC 进度条 + 呼吸灯闪烁
电池呼吸灯效果 — SOC 进度条 + 呼吸灯闪烁

电池呼吸灯效果(视频版)


踩坑速查

整个项目从 API 逆向到 UI 开发到 APK 打包,踩了 15 个坑:

| # | 坑 | 解法 |

|—|—-|——|

| 1 | SHA1 签名不对 | 排序拼接 + 前后 secret + SHA1 |

| 2 | 时间戳偏差签名失败 | 秒级 Unix,确保本地时钟准确 |

| 3 | Token 过期 | Bridge 加刷新逻辑 |

| 4 | 累计电量跳变 | 梯形积分 + Git 同步到 Private Repo |

| 5 | ES6 在旧 WebView 报错 | 做 ES5 兼容版,用 XMLHttpRequest |

| 6 | HA /local/ 缓存 31 天 | meta no-cache + patch static.py + fetch no-store |

| 7 | TV 乱码 | patch HA static.py 加 charset=utf-8 |

| 8 | 能流线不显示 | setFlow() 对 5 条线统一调用 |

| 9 | 充电线不亮 | 新增 pv_to_battery_power 传感器,fallback 用 V×A |

| 10 | 能量守恒矛盾 | 引入守恒公式实时校验 |

| 11 | autoScale 压死能流布局 | 用 Fullscreen API,不改 min-height |

| 12 | Android 9 闪退 | AppCompatActivity → Activity + 允许 HTTP 明文 |

| 13 | WebView Token 注入时序 | URL参数 + postMessage + 硬编码三重 fallback |

| 14 | 对话脱敏破坏 JS | redact_secrets 改为 false |

| 15 | 1080p 纵向溢出 | CSS 紧凑布局 + autoScale() 兜底 + 100vh 一屏 |


关键代码

能量守恒核心逻辑,整个能流拓扑图的心脏:

// 充电功率:优先传感器,fallback V×A 估算
const chargeW = pvToBat > 20 ? pvToBat : (batInA > 0.5 ? Math.round(batV * batInA) : 0);
const batCharge = chargeW > 20;

// 放电功率
const dischargeW = bat2h > 20 ? bat2h : 0;
const batDis = dischargeW > 20;

// 电网取电
const gridImportW = gridV > 5 ? gridV : 0;

// 能量守恒校验
const supplyW = pv + gridImportW + dischargeW;
const demandW = load + chargeW;
// PV + 电网取电 + 电池放电 = 负载 + 充电 ✅

Token 三重 Fallback,确保各种场景都能认证:

// 1. 硬编码长效 token(独立访问)— 到期 2095 年
let TOKEN='***';

// 2. URL 参数(APK 场景)
const params = new URLSearchParams(location.search);
if (params.get('token')) TOKEN = params.get('token');

// 3. 父窗口 postMessage(HA iframe 场景)
window.addEventListener('message', e => {
  if (e.data?.type === 'auth-token') TOKEN = e.data.token;
});

部署方案

由于 HA Docker 容器无 SSH/Samba 写入权限,使用 shell_command.exec_command API 分块写入:

# base64 编码,分 4 块写入(每块 40000 字符)
for i in 0 1 2 3; do
  CHUNK=${CONTENT:$((i*40000)):40000}
  OP=$([ $i -eq 0 ] && echo ">" || echo ">>")
  curl -X POST "http://HA:8123/api/services/shell_command/exec_command" \\
    -H "Authorization: Bearer $TOKEN" \\
    -d "{\\"cmd\\":\\"echo '$CHUNK' | base64 -d $OP /config/www/sunpower-tv.html\\"}"
done
HA 部署配置 — shell_command 与自动化脚本
HA 部署配置 — shell_command 与自动化脚本

最终版功能清单

文件:sunpower-tv.html ~109KB / ~2364行

  • ☀️ 光伏发电实时功率 + PV1/PV2 电压电流明细
  • ? 家庭用电功率 + 负载率
  • ? 电池 SOC + 进度条 + 电压电流 + 环境光呼吸效果
  • ⚡ 市电状态 + 功率
  • ? 能流拓扑图(SVG 动态动画 + 线上标注)
  • ? 发电趋势图(Canvas 实际+预测曲线)
  • ?️ 天气卡片(wttr.in 7日预报)
  • ? 家电控制面板(HA 自动发现 8 设备)
  • ?️ 语音播报(模式切换提醒)
  • ? 统计栏(今日发电/年度/累计/收益/日用量)
  • ?️ 温度监控(逆变器/房间温湿度/PV温度)
  • ⛶ 全屏功能(双击/按钮/F键/ESC)
  • ? 10 秒轮询 + 断线自动恢复
  • ? Token 三重 fallback(硬编码/URL参数/postMessage)

成本

| 项目 | 成本 |

|——|——|

| HTML 单文件 | 0 — 纯前端,无服务器 |

| HA REST API | 0 — 本地轮询 |

| wttr.in 天气 | 0 — 免费开源 |

| 数据采集 Bridge | 0 — Docker 自建 |

| AI 开发(Claude Code + Hermes) | ~$100+ |

| 维护成本 | 0 — HTML 更新无需重编 APK |

长期可持续: Token 到期 2095 年,30 年内无需更新。HTML 更新直接覆盖 HA 文件。无外部依赖,纯本地运行。


技术栈

| 层级 | 技术 |

|——|——|

| 数据源 | 厂商云端 API(逆向,SHA1 签名认证) |

| Bridge | Python 3.12, Docker, 120s 轮询 |

| Home Assistant | Docker, 28+ REST sensor |

| UI 面板 | 原生 HTML/CSS/JS + SVG 动画 + Canvas 图表,零框架 |

| TV 展示 | Android WebView APK + PWA |

| 部署 | HA shell_command.exec_command 分块 base64 写入 |

| 持久化 | NAS SMB + Git 同步 |


文件清单

/mnt/ax6600/Ai-home/homeassistant/www/
├── sunpower-tv.html              # TV 大屏版 (~109KB)
├── sunpower-tv-dev-log.md        # 开发全记录
├── manifest.json                  # PWA 配置
├── sw.js                          # Service Worker
├── icon-192.png / icon-512.png   # PWA 图标

/mnt/ax6600/Ai-home/homeassistant/
├── sunpower-webview-v20260605.apk  # Android TV 版 (1.5MB)

HA 配置:
├── configuration.yaml              # shell_command.exec_command
├── automations.yaml                # Patch Cache + Charset on Startup
└── scripts/patch_cache.sh          # 启动时 patch

从”看数据”到”用数据”:光储空调能源自动化

上篇把数据从云端拉到了本地 HA,做了个 TV 大屏看板——能”看”了。但光看不够,得用起来。

我家在南方,夏天光伏满载一小时能发 8kWh,两组拆车电池组大概 20 多度电。问题来了:白天发电多到用不完,晚上几台空调一起开又不够用。电池中午就充满,下午光伏功率下降后开始吃电池,到晚上空调全开时电量根本撑不住。

所以我想做一套能源感知自动化——让 HA 根据发电功率、电池 SOC、房间温度、天气预报,自动决定什么时候开空调、开几台、什么时候关。不是简单的”温度到了就开”,而是发电多就多用,发电少就少用,电池不够就停。


硬件改造:空调和一体机都要”本地化”

空调:拆掉原厂 WiFi 模块,换 ESP8266

家里几台科龙空调(海信旗下,同协议),原厂 WiFi 模块是 AIH-411,APP 早就废了。科龙/海信空调的通信口是半双工 RS485,不是普通 UART——所以需要加一个 MAX485 转换模块。

每台空调的改造清单:

| 物品 | 价格 | 用途 |

|——|——|——|

| ESP-01S (ESP8266) | ¥3-5 | WiFi 通信 |

| MAX485 模块 | ¥2-3 | RS485 半双工转换 |

| 杜邦线 4 根 | ¥0.5 | 接空调 4 针口 |

单台成本 ¥6-12,比买原厂替换模块(¥9.9)还便宜,而且直接接入 HA,不依赖任何云。

接线方式——空调 4 针接口定义:

| 针位 | 信号 | 接到 |

|——|——|——|

| 1 | TX (A+) | MAX485 A |

| 2 | GND | GND |

| 3 | RX (B-) | MAX485 B |

| 4 | 5V | MAX485 VCC + ESP 供电 |

> 注意:5V 口输出约 4.8V,带 ESP32 不够,但 ESP8266+MAX485 功耗低,实测稳定运行。

ESPHome 已有海信/科龙空调组件(基于 pio2398/W4G2 项目),支持开关机、模式切换、温度设定、室内温湿度、盘管温度、显示屏控制。配置十几行 YAML,刷进去 HA 自动发现。

太阳能一体机:RS485 直读,替代云端

之前用 DessMonitor 云端集成(120s 轮询,5-7 分钟延迟),现在改用 ESP32-S3 + MAX485 直读 Modbus,延迟降到秒级,还能控制逆变器参数。

一体机改造清单:

| 物品 | 价格 | 用途 |

|——|——|——|

| ESP32-S3 | ¥15-20 | 双串口,一路 RS485 读一体机 |

| MAX485 模块 | ¥2-3 | RS485 转换 |

一块 ESP32-S3 + MAX485 就能读德业 12K 一体机全部数据——光伏功率/电压/电流、电池 SOC/温度/功率、电网三相、负载功率、日/累计发电量,还能控制最大充放电电流、卖电开关等 40+ 传感器和开关。

电池组级别数据(SOC/电压/电流/功率/温度)通过一体机就能拿到——德业 BOS-G48V200-A 均衡板走 CAN2.0 连一体机,Modbus 寄存器里都有。但16 电芯电压、压差、均衡状态这些电芯级细节,一体机拿不到。

电池 BMS:电芯级监控

两块拆车电池组配的是极空 JK-PB 16S 280Ah BMS,负责电芯均衡、过充过放保护。一体机只看得到电池组整体 SOC 和功率,看不到每颗电芯的健康状况——压差大了不处理,轻则容量缩水,重则提前报废。

所以又加了一路 ESP32 + RS485 直读 BMS,独立于一体机的 Modbus 总线,16 电芯电压、温度、均衡状态、告警全拿到,还带个 GC9A01A 圆屏本地显示。数据同步入 HA,看板和自动化都能用电芯级数据。

接线要点:RS485 接 BMS 独立的监控口(A 对 A、B 对 B),不要接到逆变器正在用的总线,也不要接 BMS 的并联通信 485P 口。详细接线、ESPHome 配置、圆屏固件、MQTT 方案等见 ESP32 接极空 JK-PB BMS:RS485+圆屏+BLE 接入 Home Assistant。


能源自动化策略:发电驱动,温度触发

核心逻辑

不是”温度到了就开空调”这么简单。真正的逻辑是:

发电功率 > 负载 + 充电功率?
  ├─ 是 → 还有余力,可以开更多电器
  └─ 否 → 发电不够了,开始减负载

电池 SOC < 20%?
  ├─ 是 → 关闭非必要负载(空调优先关)
  └─ 否 → 维持当前状态

天气预报:明天阴雨?
  ├─ 是 → 今天少放电,保留电量
  └─ 否 → 正常使用

空调启动策略:错峰不叠加

几台空调不能同时启动——压缩机启动电流是运行电流的 5-8 倍,3 台同时启动会瞬间拉垮逆变器。策略是:

1. 温度触发:房间温度 ≥ 33°C 进入"待启动"队列

2. 错峰启动:每台间隔 2 分钟依次启动,避免启动电流叠加

3. 功率匹配:已启动空调的总功率 + 当前负载接近发电功率时,不再启动新的

4. 温度回落:温度降到 26°C 以下且发电功率仍充足,保持运行;发电功率下降时优先关温度最低房间的空调

其他大电器联动

农村还有水泵抽水塔、洒水淋菜——这些也是大功率电器,但不像空调那么急迫。策略:

  • 白天发电高峰(10:00-15:00):优先启动水泵抽水,充满水塔
  • 光伏余量判断:发电功率 - 当前负载 > 水泵功率 → 启动水泵
  • 天气联动:HA 集成了本地天气,预报明天有雨 → 今天不淋菜,省电

HA 自动化配置

传感器输入

| 数据源 | 传感器 | 用途 |

|--------|--------|------|

| ESP32-S3 (RS485) | 光伏实时功率 | 判断发电余量 |

| ESP32-S3 (RS485) | 电池 SOC | 判断储能余量 |

| ESP32-S3 (RS485) | 负载总功率 | 判断当前用电 |

| ESP8266 × N (空调) | 各房间温度 | 触发空调启停 |

| HA 天气集成 | 天气预报 | 提前调整策略 |

| HA 天气集成 | 室外温度 | 辅助判断制冷需求 |

自动化示例

automation:
  - id: ac_staggered_start
    alias: "空调错峰启动控制"
    trigger:
      - platform: numeric_state
        entity_id: sensor.living_room_temperature
        above: 33
      - platform: numeric_state
        entity_id: sensor.bedroom_temperature
        above: 33
    condition:
      - condition: numeric_state
        entity_id: sensor.deye_battery_soc
        above: 20
      - condition: template
        value_template: >
          {{ (states('sensor.deye_pv_power')|float - 
              states('sensor.deye_load_power')|float) > 800 }}
    action:
      - service: script.ac_queue_start
        data:
          rooms: >
            {{ expand('group.ac_rooms') 
               | selectattr('state','eq','待启动')
               | map(attribute='entity_id') | list }}

功率平衡脚本

script:
  ac_queue_start:
    alias: "空调排队启动"
    mode: queued
    fields:
      rooms:
        description: "待启动房间列表"
    sequence:
      - repeat:
          for_each: "{{ rooms }}"
          sequence:
            - condition: template
              value_template: >
                {{ (states('sensor.deye_pv_power')|float - 
                    states('sensor.deye_load_power')|float) > 800 }}
            - service: climate.turn_on
              target:
                entity_id: "{{ repeat.item }}"
            - delay:
                minutes: 2

最终系统架构

☀️ 光伏 3.84kW → 德业 12K 一体机 → ? 2×拆车电池组(20+kWh)
                    ↓ RS485/Modbus
              ESP32-S3 + MAX485
                    ↓ WiFi
              Home Assistant (192.168.9.242)
              ├─ 光伏/电池/电网 40+ 传感器(秒级刷新)
              ├─ BMS 电芯级监控(16 电芯电压/压差/均衡/告警)
              ├─ 天气集成(本地预报)
              ├─ 能源自动化引擎
              │   ├─ 空调错峰启动
              │   ├─ 水泵/淋菜调度
              │   └─ 功率平衡控制
              └─ TV 大屏看板

? 电池 BMS
  └─ ESP32+RS485 直读 JK-PB → HA 16 电芯传感器 + GC9A01A 圆屏

? 各房间科龙空调
  ├─ 客厅 → ESP8266+MAX485 → HA climate 实体
  ├─ 主卧 → ESP8266+MAX485 → HA climate 实体
  └─ 次卧 → ESP8266+MAX485 → HA climate 实体

? 水泵/淋菜
  └─ 智能开关 → HA switch 实体

改造成本汇总

| 项目 | 数量 | 单价 | 小计 |

|------|------|------|------|

| ESP-01S (空调用) | 3 | ¥5 | ¥15 |

| MAX485 模块 (空调用) | 3 | ¥3 | ¥9 |

| ESP32-S3 (一体机用) | 1 | ¥18 | ¥18 |

| MAX485 模块 (一体机用) | 1 | ¥3 | ¥3 |

| ESP32 (BMS 用) | 1 | ¥15 | ¥15 |

| MAX485 模块 (BMS 用) | 1 | ¥3 | ¥3 |

| 杜邦线/跳线 | 若干 | - | ¥5 |

| 总计 | | | ¥68 |

68 块钱,把 3 台空调 + 1 台光储一体机 + 电池 BMS 全部本地化接入 HA,实现发电驱动的能源自动化。比买任何商业能源管理系统都便宜,而且完全自主可控。


踩坑预警

1. 海信/科龙空调 RS485 是半双工——必须用 MAX485 而不是直连 UART,flow_control_pin 必须配

2. 空调 5V 供电能力有限——4.8V 带 ESP8266+MAX485 刚好,别加其他外设

3. 压缩机启动电流——3 台空调绝对不能同时启动,2 分钟间隔是最低要求

4. Modbus 寄存器地址因固件版本不同——德业一体机不同固件版本寄存器可能偏移,先读一下确认

5. 天气 API 限流——HA 天气集成默认刷新间隔够用,别改太频繁


回顾

从一个 37KB 的简单拓扑图,到 109KB 的全功能 TV 大屏监控看板,这个项目经历了:

1. 数据接入(逆向 API + Bridge) — 最难,花了最多时间

2. 基础 UI(拓扑图 + 卡片) — 桌面版能用

3. TV 适配(大字体 + 一屏显示) — 1080p 溢出问题折腾了好几轮

4. 功能爆发(能流动画 + 趋势图 + 家电控制 + 天气) — Claude Code 贡献最大

5. APK 打包(Android 9 兼容 + HTTP 明文 + Token 注入) — 踩坑最多

6. 收尾打磨(日用量 + 全屏 + PWA) — 小改动但体验提升明显

从"看数据"到"用数据",这才是智能家居的真正意义——不是手机远程开个灯,而是让系统根据发电、储能、天气、温度自动做决策。50 块钱的硬件改造,换来的是整个光储系统的智能化闭环。


*by 数码罗记 · godsun.pro*