Skip to content

Instantly share code, notes, and snippets.

@JohanAlvedal
Last active November 4, 2025 12:23
Show Gist options
  • Select an option

  • Save JohanAlvedal/56e06d6b7b62cf4a080bb04d0e5b015f to your computer and use it in GitHub Desktop.

Select an option

Save JohanAlvedal/56e06d6b7b62cf4a080bb04d0e5b015f to your computer and use it in GitHub Desktop.
Predbat Charging & Discharging Control (Huawei Solar)
# =============================
# Blueprint — Predbat Charging & Discharging Control (Huawei Solar)
# =============================
blueprint:
name: Predbat Charging & Discharging Control (Huawei Solar) — basic
description: |
Blueprint som styr laddning/urladdning med dag/natt-fönster, hold charging och
car charging slot.
Antaganden (Predbat-standard):
• predbat.status
• binary_sensor.predbat_charging
• binary_sensor.predbat_exporting
• predbat.best_charge_limit (fallback: predbat.charge_limit)
• predbat.best_export_limit
• switch.predbat_set_read_only
• binary_sensor.predbat_car_charging_slot
Huawei Solar:
• number.*battery_maximum_charging_power
• number.*battery_maximum_discharging_power
• huawei_solar.forcible_charge_soc
• huawei_solar.forcible_discharge_soc
• huawei_solar.forcible_discharge
• huawei_solar.stop_forcible_charge
domain: automation
input:
# Device-id
battery_device_id:
name: Huawei battery device_id (Connected Energy Storage)
selector:
text: {}
# SoC sensor
soc_sensor:
name: Battery SoC sensor
selector:
entity:
domain: sensor
# Number entities
number_charging_power:
name: Number — battery_maximum_charging_power
selector:
entity:
domain: number
number_discharging_power:
name: Number — battery_maximum_discharging_power
selector:
entity:
domain: number
# Time windows & powers
day_start:
name: Day window start
selector: { time: {} }
default: "06:00:00"
day_end:
name: Day window end
selector: { time: {} }
default: "23:30:00"
day_charge_power:
name: Day — charging (W)
default: 4500
selector: { number: { min: 0, max: 5000, step: 100 } }
day_car_charge_power:
name: Day (car slot ON) — charging (W)
default: 2500
selector: { number: { min: 0, max: 5000, step: 100 } }
night_charge_power:
name: Night — charging (W)
default: 5000
selector: { number: { min: 0, max: 5000, step: 100 } }
night_car_charge_power:
name: Night (car slot ON) — charging (W)
default: 2500
selector: { number: { min: 0, max: 5000, step: 100 } }
discharge_power:
name: Discharging (W)
default: 5000
selector: { number: { min: 0, max: 5000, step: 100 } }
mode: restart
max_exceeded: silent
trigger:
- platform: state
entity_id: binary_sensor.predbat_exporting
to: "on"
for: "00:00:03"
- platform: state
entity_id: binary_sensor.predbat_charging
to: "on"
for: "00:00:03"
- platform: state
entity_id: predbat.best_charge_limit
for: "00:00:03"
- platform: state
entity_id: predbat.charge_limit
for: "00:00:03"
- platform: state
entity_id: predbat.status
for: "00:00:03"
condition:
- condition: state
entity_id: switch.predbat_set_read_only
state: "off"
action:
- alias: Charging / Export
choose:
# ----- CHARGING -----
- conditions:
- condition: state
entity_id: predbat.status
state: "Charging"
- condition: state
entity_id: binary_sensor.predbat_charging
state: "on"
sequence:
- alias: Day window
if:
- condition: time
after: !input day_start
before: !input day_end
then:
- choose:
- conditions:
- condition: state
entity_id: binary_sensor.predbat_car_charging_slot
state: "on"
sequence:
- service: huawei_solar.forcible_charge_soc
data:
target_soc: >-
{% set v1 = states('predbat.best_charge_limit')|int(0) %}
{% set v2 = states('predbat.charge_limit')|int(0) %}
{% set v = v1 if v1>0 else v2 %}
{{ 12 if v < 12 else v }}
power: !input day_car_charge_power
device_id: !input battery_device_id
- service: number.set_value
entity_id: !input number_charging_power
data: { value: !input day_car_charge_power }
- service: number.set_value
entity_id: !input number_discharging_power
data: { value: 0 }
default:
- service: huawei_solar.forcible_charge_soc
data:
target_soc: >-
{% set v1 = states('predbat.best_charge_limit')|int(0) %}
{% set v2 = states('predbat.charge_limit')|int(0) %}
{% set v = v1 if v1>0 else v2 %}
{{ 12 if v < 12 else v }}
power: !input day_charge_power
device_id: !input battery_device_id
- service: number.set_value
entity_id: !input number_charging_power
data: { value: !input day_charge_power }
- service: number.set_value
entity_id: !input number_discharging_power
data: { value: 0 }
- alias: Night window
if:
- condition: or
conditions:
- condition: time
before: !input day_start
- condition: time
after: !input day_end
then:
- choose:
- conditions:
- condition: state
entity_id: binary_sensor.predbat_car_charging_slot
state: "on"
sequence:
- service: huawei_solar.forcible_charge_soc
data:
target_soc: >-
{% set v1 = states('predbat.best_charge_limit')|int(0) %}
{% set v2 = states('predbat.charge_limit')|int(0) %}
{% set v = v1 if v1>0 else v2 %}
{{ 12 if v < 12 else v }}
power: !input night_car_charge_power
device_id: !input battery_device_id
- service: number.set_value
entity_id: !input number_charging_power
data: { value: !input night_car_charge_power }
- service: number.set_value
entity_id: !input number_discharging_power
data: { value: 0 }
default:
- service: huawei_solar.forcible_charge_soc
data:
target_soc: >-
{% set v1 = states('predbat.best_charge_limit')|int(0) %}
{% set v2 = states('predbat.charge_limit')|int(0) %}
{% set v = v1 if v1>0 else v2 %}
{{ 12 if v < 12 else v }}
power: !input night_charge_power
device_id: !input battery_device_id
- service: number.set_value
entity_id: !input number_charging_power
data: { value: !input night_charge_power }
- service: number.set_value
entity_id: !input number_discharging_power
data: { value: 0 }
# ----- EXPORT / DISCHARGING -----
- conditions:
- condition: state
entity_id: binary_sensor.predbat_charging
state: "off"
- condition: state
entity_id: binary_sensor.predbat_exporting
state: "on"
sequence:
- service: huawei_solar.forcible_discharge_soc
data:
target_soc: >-
{% set v = states('predbat.best_export_limit')|int(0) %}
{{ 12 if v < 12 else v }}
power: !input discharge_power
device_id: !input battery_device_id
- service: number.set_value
entity_id: !input number_discharging_power
data: { value: !input discharge_power }
- alias: STOP / HOLD / FREEZE / DEMAND
choose:
- conditions:
- condition: state
entity_id: predbat.status
state: "Hold for Car"
sequence:
- service: huawei_solar.stop_forcible_charge
data: { device_id: !input battery_device_id }
- service: number.set_value
entity_id: !input number_charging_power
data: { value: 0 }
- service: number.set_value
entity_id: !input number_discharging_power
data: { value: 0 }
- conditions:
- condition: or
conditions:
- condition: state
entity_id: predbat.status
state: "Hold exporting"
- condition: state
entity_id: predbat.status
state: "Freeze exporting"
sequence:
- service: huawei_solar.stop_forcible_charge
data: { device_id: !input battery_device_id }
- service: number.set_value
entity_id: !input number_charging_power
data: { value: !input discharge_power }
- service: number.set_value
entity_id: !input number_discharging_power
data: { value: !input discharge_power }
# ---- HOLD/FREEZE CHARGING = SAMMA EFFEKT SOM ORD. CHARGING (dag/natt + ev. car-slot)
- conditions:
- condition: or
conditions:
- condition: state
entity_id: predbat.status
state: "Hold charging"
- condition: state
entity_id: predbat.status
state: "Freeze charging"
sequence:
- service: huawei_solar.stop_forcible_charge
data: { device_id: !input battery_device_id }
- alias: Hold power följer dag/natt & car-slot
choose:
- conditions:
- condition: time
after: !input day_start
before: !input day_end
sequence:
- choose:
- conditions:
- condition: state
entity_id: binary_sensor.predbat_car_charging_slot
state: "on"
sequence:
- service: number.set_value
entity_id: !input number_charging_power
data: { value: !input day_car_charge_power }
default:
- service: number.set_value
entity_id: !input number_charging_power
data: { value: !input day_charge_power }
- conditions:
- condition: or
conditions:
- condition: time
before: !input day_start
- condition: time
after: !input day_end
sequence:
- choose:
- conditions:
- condition: state
entity_id: binary_sensor.predbat_car_charging_slot
state: "on"
sequence:
- service: number.set_value
entity_id: !input number_charging_power
data: { value: !input night_car_charge_power }
default:
- service: number.set_value
entity_id: !input number_charging_power
data: { value: !input night_charge_power }
- service: number.set_value
entity_id: !input number_discharging_power
data: { value: 0 }
- conditions:
- condition: state
entity_id: predbat.status
state: "Demand"
sequence:
- service: huawei_solar.stop_forcible_charge
data: { device_id: !input battery_device_id }
- service: number.set_value
entity_id: !input number_charging_power
data: { value: !input discharge_power }
- service: number.set_value
entity_id: !input number_discharging_power
data: { value: !input discharge_power }
@martinold
Copy link

Blueprint imported and testing.

Huawei hardware:
Inverter - SUN2000-5KTL-L1
Batteries - LUNA2000-5KW-C0 x 4 (20Kwh)
Panels - 16 x 400w Eurener (6400w)

Rates:
Tariff is Octopus IOG

  • Import peak rate £0.28
  • Import off-peak rate £0.07
  • Export rate £0.15

Location is the Midlands, UK
The car charger is wired separately, and no automation is required.
Nordpool is not necessary on the IOG tariff

HA integrations installed:
PredBat
Solcast
Huawei Solar
Octopus Energy

Thank you for the work. I could not get Bradbat to control the Huawei inverter, so I have been using my own automation.
I will feed back on the results.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment