Last active
November 4, 2025 12:23
-
-
Save JohanAlvedal/56e06d6b7b62cf4a080bb04d0e5b015f to your computer and use it in GitHub Desktop.
Predbat Charging & Discharging Control (Huawei Solar)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # ============================= | |
| # 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 } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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
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.