跳转至

智能家居能源管理:Solar + Battery 联动与峰谷调度

装太阳能板 + 储能电池后,最大的浪费不是发电不够,而是用错了时间。中午光伏发电最多,但家里没人,电被低价卖掉;晚上电价高峰,电池却没电了。这篇文章讲怎么让 HA 帮你做最优调度。

能源管理架构

┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│  Solar Panel│    │  Battery    │    │  Grid       │
│  (DC → AC)  │    │  (LiFePO4)  │    │  (AC 220V)  │
└──────┬──────┘    └──────┬──────┘    └──────┬──────┘
       │                  │                  │
       └──────────────────┼──────────────────┘
                          │
                   ┌──────▼──────┐
                   │  Power Meter │
                   │  (CT sensor) │
                   └──────┬──────┘
                          │
                   ┌──────▼──────┐
                   │  Home Assistant │
                   │  Energy Dashboard │
                   │  + Custom Automations │
                   └─────────────┘
                          │
                   ┌──────▼──────┐
                   │  Loads      │
                   │  (HVAC / EV / Water Heater) │
                   └─────────────┘

核心数据流: 1. Power Meter 采集实时功率(W) 2. HA 计算累计能量(kWh),区分 solar/battery/grid 来源 3. 调度逻辑根据电价时段和发电预测,决定何时充/放/卖电

第一步:硬件选型

方案 A:商业一体方案(最省事)

产品 价格 功能 集成方式
Tesla Powerwall ¥60,000+ 电池 + 逆变器一体 HA 有官方集成
BYD Battery-Box ¥30,000+ 模块化电池 Modbus TCP 集成
Huawei SUN2000 ¥25,000+ 逆变器 + 电池管理 Modbus RTU

方案 B:DIY 方案(性价比最高)

# ESPHome 功率监测
# 硬件:ESP32-C6 + ACS712 电流传感器 + LCD 屏
esphome:
  name: power-monitor
esp32:
  board: esp32-c6-devkitc-1
wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

# 电流传感器(ACS712-30A,3.3V 版本)
sensor:
  - platform: adc
    pin: GPIO3
    name: "AC Current"
    unit_of_measurement: "A"
    accuracy_decimals: 2
    filters:
      - calibrate_linear:
          - 0.0 -> 0.0
          - 1.65 -> 15.0   # 校准点:15A 时 ADC 读数为 1.65V
      - average:
          window_size: 10
          send_every: 10
          send_first_at: 1

  - platform: wifi_signal
    name: "Power Monitor WiFi"
    update_interval: 60s

# 在 HA 里通过 ESPHome integration 自动发现

推荐:预算有限选方案 B,Shelly 3EM(¥300)是最省心的商业方案,三相电监测,HA 原生集成。

第二步:HA Energy Dashboard 配置

# configuration.yaml
sensor:
  - platform: template
    sensors:
      # 太阳能发电功率
      solar_power:
        friendly_name: "Solar Power"
        unit_of_measurement: "W"
        value_template: "{{ states('sensor.shelly_3em_phase_a') | float + states('sensor.shelly_3em_phase_b') | float + states('sensor.shelly_3em_phase_c') | float }}"

      # 家用总功率
      home_power:
        friendly_name: "Home Power"
        unit_of_measurement: "W"
        value_template: "{{ states('sensor.power_monitor_ac_current') | float * 220 }}"

      # 电池电量(%)
      battery_level:
        device_class: battery
        unit_of_measurement: "%"
        value_template: "{{ states('sensor.battery_soc') | default(80) }}"

      # 电网功率(正=用电,负=卖电)
      grid_power:
        friendly_name: "Grid Power"
        unit_of_measurement: "W"
        value_template: "{{ (states('sensor.home_power') | float) - (states('sensor.solar_power') | float) - (states('sensor.battery_charge') | float) }}"
# 能源配置
energy:
  solar:
    component: shelly
    flow_energy_sensor: sensor.solar_power
    cost_per_kwh: 0.0   # 太阳能自发自用,边际成本≈0
  grid:
    component: utility_meter
    energy_source: grid
    tariff_source: sensor.electricity_price
  battery:
    component: generic
    charge_energy_sensor: sensor.battery_charge
    discharge_energy_sensor: sensor.battery_discharge

第三步:峰谷调度自动化

基础版:定时充放电

# 谷电时段充电(00:00-08:00)
alias: "谷电充电"
triggers:
  - trigger: time
    at: "00:00:00"
conditions:
  - condition: numeric_state
    entity_id: sensor.battery_level
    below: 80
actions:
  - action: input_boolean.turn_on
    target:
      entity_id: input_boolean.battery_charge_mode
  - delay: "08:00:00"
  - action: input_boolean.turn_off
    target:
      entity_id: input_boolean.battery_charge_mode

# 尖峰时段放电(10:00-14:00, 18:00-22:00)
alias: "尖峰放电"
triggers:
  - trigger: time
    at: "10:00:00"
  - trigger: time
    at: "18:00:00"
conditions:
  - condition: numeric_state
    entity_id: sensor.battery_level
    above: 30
actions:
  - action: input_boolean.turn_on
    target:
      entity_id: input_boolean.battery_discharge_mode

进阶版:动态电价响应

# 使用外部电价 API(如当地电网公开 API)
# 每 30 分钟刷新一次电价
alias: "电价监控与动态调度"
triggers:
  - trigger: time_pattern
    minutes: "/30"
conditions:
  - condition: template
    value_template: >
      {{ states('sensor.current_price') | float > 0.6 }}
actions:
  - choose:
      - conditions:
          - condition: numeric_state
            entity_id: sensor.battery_level
            above: 50
        sequence:
          - action: homeassistant.turn_on
            target:
              entity_id: switch.battery_discharge
          - action: notify.mobile_app
            data:
              message: "电价高峰,电池开始放电"
      - conditions:
          - condition: numeric_state
            entity_id: sensor.battery_level
            below: 30
        sequence:
          - action: homeassistant.turn_off
            target:
              entity_id: switch.battery_discharge
          - action: notify.mobile_app
            data:
              message: "电池低电量,切回电网供电"
# 电价数据源(示例:用 REST sensor 拉取当地电价)
sensor:
  - platform: rest
    name: "current_price"
    resource: "https://api.grid.cn/pricing/realtime"
    value_template: "{{ value_json.price }}"
    unit_of_measurement: "元/kWh"
    scan_interval: 1800
    headers:
      Authorization: "Bearer YOUR_API_KEY"

三个真实配置案例

案例一:光伏自发自用最大化

场景:屋顶 5kW 太阳能板,10kWh 电池,家里白天有人。

策略:中午发电高峰期,优先给电池充电 + 供家电使用,剩余电量卖电网。晚上用电池供电。

# 自发自用调度
alias: "光伏自发自用优化"
triggers:
  - trigger: time_pattern
    minutes: "/5"   # 每 5 分钟检查
conditions:
  - condition: template
    value_template: "{{ states('sensor.solar_power') | float > 500 }}"
actions:
  - choose:
      - conditions:
          - condition: numeric_state
            entity_id: sensor.battery_level
            below: 90
        sequence:
          - action: switch.turn_on
            target:
              entity_id: switch.charger
      - conditions:
          - condition: numeric_state
            entity_id: sensor.battery_level
            above: 90
        sequence:
          - action: switch.turn_off
            target:
              entity_id: switch.charger
          - action: input_number.set_value
            target:
              entity_id: input_number.grid_export_limit
            data:
              value: "{{ (states('sensor.solar_power') | float) - 200 }}"

结果:自用率从 40% 提升到 75%,每月减少购电费用约 180 元。

案例二:EV 充电时段优化

场景:家里有电动车,充电桩功率 7kW,需要在谷电时段充电。

# EV 充电时段优化
alias: "EV 谷电充电"
triggers:
  - trigger: time
    at: "23:00:00"
conditions:
  - condition: state
    entity_id: binary_sensor.ev_plugged_in
    state: "on"
  - condition: numeric_state
    entity_id: sensor.battery_level
    above: 20
actions:
  - action: switch.turn_on
    target:
      entity_id: switch.ev_charger
  - delay: "06:00:00"
  - action: switch.turn_off
    target:
      entity_id: switch.ev_charger

注意:如果电池电量低(< 20%),优先给家用电池充电,EV 推迟到次日 00:00。

案例三:电价套利自动交易

场景:当地分时电价,尖峰 1.2 元/kWh,谷电 0.3 元/kWh,价差 0.9 元。

# 电价套利决策
alias: "电价套利调度"
triggers:
  - trigger: state
    entity_id: sensor.electricity_price
conditions:
  - condition: template
    value_template: >
      {% set price = states('sensor.electricity_price') | float %}
      {{ price > 0.8 or price < 0.3 }}
actions:
  - choose:
      - conditions:
          - condition: template
            value_template: "{{ states('sensor.electricity_price') | float > 0.8 }}"
        sequence:
          # 高价时段:电池放电
          - action: switch.turn_on
            target:
              entity_id: switch.battery_discharge
          - action: notify.mobile_app
            data:
              message: "电价 ¥{{ states('sensor.electricity_price') }},电池放电中"
      - conditions:
          - condition: template
            value_template: "{{ states('sensor.electricity_price') | float < 0.3 }}"
        sequence:
          # 低价时段:电池充电
          - action: switch.turn_off
            target:
              entity_id: switch.battery_discharge
          - action: switch.turn_on
            target:
              entity_id: switch.battery_charge
          - action: notify.mobile_app
            data:
              message: "电价 ¥{{ states('sensor.electricity_price') }},电池充电中"

收益计算:假设每天完成 1 次充放电循环(10kWh),日收益 9 元,月收益 270 元,年收益 3240 元。电池循环寿命 6000 次,约 16 年,ROI 合理。

3 个真实翻车案例

案例一:电价 API 返回格式变化导致调度失效

现象:某天早上发现 EV 在电价高峰时段还在充电,浪费了钱。

根因:电价 API 返回字段从 price 变成了 current_price,HA sensor 读到 null,condition 判断失败。

# 排查
ha core logs | grep -i "rest\|price"
# 看到 AttributeError: 'NoneType' object has no attribute 'get'

修复:加默认值和错误处理。

sensor:
  - platform: rest
    name: "current_price"
    resource: "https://api.grid.cn/pricing/realtime"
    value_template: "{{ value_json.current_price | default(0.5) }}"

预防:给电价 sensor 加 availability_template,null 时标记为 unavailable,让自动化跳过执行。

案例二:电池过放保护失效

现象:电池放电到 5%,HA 没有自动停止,电池损坏。

根因:低电量保护 condition 写在了错误的 entity 上,实际用的是 sensor.battery_level(百分比),但 condition 判断的是 sensor.battery_voltage(电压)。

# ❌ 错误:entity 不匹配
conditions:
  - condition: numeric_state
    entity_id: sensor.battery_voltage   # 这个是电压,单位 V
    below: 48                            # 以为是百分比

# ✅ 正确
conditions:
  - condition: numeric_state
    entity_id: sensor.battery_level     # SOC 百分比
    below: 20

预防:每个 condition 都要在 dev-tools/template 里验证返回值,不要凭感觉写 entity_id。

案例三:调度冲突——两个自动化同时反向操作

现象:电池一会儿充一会儿放,耗电比预期多。

根因:两个自动化都监听了同一个 trigger,但没有互斥锁。 - 自动化 A:电价 > 0.8 时放电 - 自动化 B:太阳能 > 2kW 时充电

中午太阳能发电多、电价也高时,两个自动化同时触发,互相打架。

修复:用 input_boolean 做互斥锁。

# 充放电互斥
alias: "充放电互斥锁"
triggers:
  - trigger: state
    entity_id: input_boolean.battery_charge_mode
    to: "on"
conditions:
  - condition: state
    entity_id: input_boolean.battery_discharge_mode
    state: "on"
actions:
  - action: input_boolean.turn_off
    target:
      entity_id: input_boolean.battery_discharge_mode

总结

能源管理的核心不是设备多先进,而是调度逻辑是否匹配你的电价结构和用电习惯。DIY 方案成本低但需要花时间调参;商业方案省心但扩展性差。

我的判断:家庭用户选 Shelly 3EM + HA Energy Dashboard + 自定义自动化,性价比最高。需要大规模储能或商业场景,考虑华为/比亚迪一体方案。无论选哪个,先装一个功率监测 sensor,没有数据就做不了优化。

延伸阅读