Home Assistant - Zendure automation MQTT and QCELLs

YAML

alias: __Zendure_New_Automation v4
description: ""
triggers:
  - trigger: time_pattern
    seconds: /30
conditions: []
actions:
  - sequence: []
  - alias: HP ou HC ?
    choose:
      - conditions:
          - condition: state
            entity_id: sensor.linky_current_price
            state:
              - HEURE PLEINE
        sequence:
          - alias: Etat de QCELLS
            choose:
              - conditions:
                  - condition: state
                    entity_id: sensor.qcells_etat
                    state:
                      - Standby
                sequence:
                  - alias: >-
                      Si il est à -10% (vide) alors on compense si nécessaire
                      avec SF2400
                    choose:
                      - conditions:
                          - condition: and
                            conditions:
                              - type: is_battery_level
                                condition: device
                                device_id: afda895cc1812b99521eb78710326b89
                                entity_id: f25a2fe7b99ed232a00fd0c82cb205e2
                                domain: sensor
                                below: 11
                              - condition: numeric_state
                                entity_id: sensor.te31njn8n387601_l3_p
                                above: 50
                        sequence:
                          - sequence:
                              - if:
                                  - condition: device
                                    device_id: a9bed78637a3d4199888177480ba0f4b
                                    domain: select
                                    entity_id: faa8306ea0f42cc0b510209a0e408c8e
                                    type: selected_option
                                    option: Input mode
                                then:
                                  - device_id: a9bed78637a3d4199888177480ba0f4b
                                    domain: select
                                    entity_id: faa8306ea0f42cc0b510209a0e408c8e
                                    type: select_option
                                    option: Output mode
                                alias: >-
                                  SF2400 - Changement d'état IN to Out si
                                  necessaire
                              - action: number.set_value
                                target:
                                  entity_id: number.eeb4aep1p032084_outputlimit
                                data:
                                  value: >
                                    {% set current =
                                    states('sensor.te31njn8n387601_l3_p') |
                                    float(0) %} {% set output =
                                    states('number.eeb4aep1p032084_outputlimit')
                                    | float(0) %}

                                    {% if -50 <= current <= 50 %}
                                      {{ output | round(0) }}

                                    {% else %}
                                      {% set delta = 0.7 * current %}
                                      {% set cible = output + delta %}
                                      {% set result = cible - 50 if cible > 0 else cible %}
                                      {{ [result, 900] | min | round(0) }}
                                    {% endif %}
                          - sequence:
                              - if:
                                  - condition: device
                                    device_id: a9bed78637a3d4199888177480ba0f4b
                                    domain: select
                                    entity_id: faa8306ea0f42cc0b510209a0e408c8e
                                    type: selected_option
                                    option: Input mode
                                then:
                                  - device_id: a9bed78637a3d4199888177480ba0f4b
                                    domain: select
                                    entity_id: faa8306ea0f42cc0b510209a0e408c8e
                                    type: select_option
                                    option: Output mode
                                alias: >-
                                  SF2400 - Changement d'état IN to Out si
                                  necessaire
                              - action: number.set_value
                                target:
                                  entity_id: number.eeb4aep1p032084_outputlimit
                                data:
                                  value: >
                                    {% set current =
                                    states('sensor.te31njn8n387601_l3_p') |
                                    float(0) %} {% set output =
                                    states('number.eeb4aep1p032084_outputlimit')
                                    | float(0) %}

                                    {% if -50 <= current <= 50 %}
                                      {{ output | round(0) }}

                                    {% else %}
                                      {% set delta = 0.7 * current %}
                                      {% set cible = output + delta %}
                                      {% set result = cible - 50 if cible > 0 else cible %}
                                      {{ [result, 900] | min | round(0) }}
                                    {% endif %}
                            enabled: false
                        alias: Si 3CT > 50W, on compense avec xW pour arriver à 50W
                      - conditions:
                          - condition: numeric_state
                            entity_id: sensor.te31njn8n387601_l3_p
                            below: -200
                          - type: is_battery_level
                            condition: device
                            device_id: afda895cc1812b99521eb78710326b89
                            entity_id: f25a2fe7b99ed232a00fd0c82cb205e2
                            domain: sensor
                            above: 90
                            alias: QCELLs > 90%
                        sequence:
                          - alias: >-
                              On demarre la charge de SF2400 avec 0.3 de ce
                              qu'on inject en trop
                            sequence:
                              - device_id: a9bed78637a3d4199888177480ba0f4b
                                domain: select
                                entity_id: faa8306ea0f42cc0b510209a0e408c8e
                                type: select_option
                                option: Input mode
                              - device_id: a9bed78637a3d4199888177480ba0f4b
                                domain: number
                                entity_id: f2984ee0e6ebcf40e208c5a0d56b90d8
                                type: set_value
                                value: 0
                              - action: number.set_value
                                target:
                                  entity_id: number.eeb4aep1p032084_inputlimit
                                data:
                                  value: >
                                    {% set current =
                                    states('sensor.te31njn8n387601_l3_p') |
                                    float(0) %} {% set input =
                                    states('number.eeb4aep1p032084_inputlimit')
                                    | float(0) %}

                                    {% if -50 <= current <= 50 %}
                                      {{ input | round(0) }}

                                    {% else %}
                                      {% set current = current * -1 %}
                                      {% set delta = 0.3 * current %}
                                      {% set cible = input + delta %}
                                      {% set result = cible - 50 if cible > 0 else cible %}
                                      {{ [result, 900] | min | round(0) }}
                                    {% endif %}
                              - device_id: a9bed78637a3d4199888177480ba0f4b
                                domain: number
                                entity_id: 446540682f8a0142e01a5f8a2272926d
                                type: set_value
                                value: 200
                                enabled: false
                        alias: QCELLs full
                alias: QCELLS en Standby
              - conditions:
                  - condition: state
                    entity_id: sensor.qcells_etat
                    state:
                      - En charge
                sequence:
                  - alias: Si surplus de production
                    choose:
                      - conditions:
                          - condition: and
                            conditions:
                              - condition: numeric_state
                                entity_id: sensor.qcells_inverter_production_2
                                below: 20
                              - type: is_power
                                condition: device
                                device_id: 181b299767530862f68a9d7f84c40146
                                entity_id: 04b888d40622ee63c389a1da5046b77f
                                domain: sensor
                                below: -50
                        sequence:
                          - alias: Faut-il lancer la charge du SF2400 ?
                            choose:
                              - conditions:
                                  - condition: device
                                    device_id: a9bed78637a3d4199888177480ba0f4b
                                    domain: select
                                    entity_id: faa8306ea0f42cc0b510209a0e408c8e
                                    type: selected_option
                                    option: Output mode
                                sequence:
                                  - target:
                                      entity_id: number.eeb4aep1p032084_outputlimit
                                    data:
                                      value: >
                                        {% set current =
                                        states('sensor.te31njn8n387601_l3_p') |
                                        float %} {% set output =
                                        states('number.eeb4aep1p032084_outputlimit')
                                        | float %}

                                        {% if -50 <= current <= 50 %}
                                          {{ output | round(0) }}

                                        {% else %}
                                          {% set surplus = current * -1 %}
                                          {% set delta = 0.7 * surplus %}
                                          {{ (output - delta) | round(0) }}
                                        {% endif %}
                                    action: number.set_value
                                alias: >-
                                  SF2400 est-il en output, auquel ca il faut
                                  réduire son injection
                              - conditions: []
                                sequence:
                                  - sequence:
                                      - alias: >-
                                          SF2400 - Changement d'état OUT to IN si
                                          necessaire
                                        if:
                                          - condition: device
                                            device_id: a9bed78637a3d4199888177480ba0f4b
                                            domain: select
                                            entity_id: faa8306ea0f42cc0b510209a0e408c8e
                                            type: selected_option
                                            option: Output mode
                                        then:
                                          - device_id: a9bed78637a3d4199888177480ba0f4b
                                            domain: select
                                            entity_id: faa8306ea0f42cc0b510209a0e408c8e
                                            type: select_option
                                            option: Input mode
                                      - target:
                                          entity_id: number.eeb4aep1p032084_inputlimit
                                        data:
                                          value: >
                                            {% set current =
                                            states('sensor.te31njn8n387601_l3_p') |
                                            float %} {% set input =
                                            states('number.eeb4aep1p032084_inputlimit')
                                            | float %}

                                            {% if -50 <= current <= 50 %}
                                              {{ input | round(0) }}

                                            {% else %}
                                              {% set surplus = current * -1 %}
                                              {% set delta = 0.7 * surplus %}
                                              {{ (input + delta) | round(0) }}
                                            {% endif %}
                                        action: number.set_value
                        alias: 3CT negatif < -50W vérification sur QCELLS inject
                      - conditions:
                          - condition: or
                            conditions:
                              - condition: and
                                conditions:
                                  - condition: numeric_state
                                    entity_id: sensor.qcells_inverter_production_2
                                    below: 10
                                  - condition: device
                                    device_id: a9bed78637a3d4199888177480ba0f4b
                                    domain: select
                                    entity_id: faa8306ea0f42cc0b510209a0e408c8e
                                    type: selected_option
                                    option: Output mode
                              - condition: and
                                conditions:
                                  - condition: numeric_state
                                    entity_id: sensor.qcells_inverter_production_2
                                    below: sensor.qcells_production_solaire
                                enabled: false
                        sequence:
                          - target:
                              entity_id: number.eeb4aep1p032084_outputlimit
                            data:
                              value: >
                                {% set current =
                                states('sensor.te31njn8n387601_l3_p') | float
                                %}  {% set output =
                                states('number.eeb4aep1p032084_outputlimit') |
                                float %} {% set qcell =
                                states('sensor.qcells_inverter_production_2') |
                                float %}

                                {% if qcell <= 10 %}
                                  {{ output | round(0) }}

                                {% else %}
                                  {% set surplus = current * -1 %}
                                  {% set delta = 0.1 * output %}
                                  {{ (output - delta) | round(0) }}
                                {% endif %}
                            action: number.set_value
                alias: QCELLS en Charge
              - conditions:
                  - condition: state
                    entity_id: sensor.qcells_etat
                    state:
                      - En décharge
                sequence:
                  - choose:
                      - conditions:
                          - alias: >-
                              QCELLs à plus de 90%, on réduit la charge de
                              SF2400 si en charge
                            condition: and
                            conditions:
                              - condition: and
                                conditions: []
                              - condition: numeric_state
                                entity_id: sensor.qcells_batterie_level
                                above: 90
                              - condition: device
                                device_id: a9bed78637a3d4199888177480ba0f4b
                                domain: select
                                entity_id: faa8306ea0f42cc0b510209a0e408c8e
                                type: selected_option
                                option: Input mode
                        sequence:
                          - action: number.set_value
                            target:
                              entity_id: number.eeb4aep1p032084_inputlimit
                            data:
                              value: >
                                {% set current =
                                states('sensor.te31njn8n387601_l3_p') | float(0)
                                %} 

                                {% set input =
                                states('number.eeb4aep1p032084_inputlimit') |
                                float(0) %}

                                {% if -50 <= current <= 50 %}
                                  {{ input | round(0) }}

                                {% else %}
                                  {% set delta = 0.7 * current * -1 %}
                                  {% set cible = input - delta %}
                                  {% set result = cible - 50 if cible > 0 else cible %}
                                  {{ [result, 900] | min | round(0) }}
                                {% endif %}
                      - conditions:
                          - condition: numeric_state
                            entity_id: sensor.te31njn8n387601_l3_p
                            above: 50
                          - type: is_power
                            condition: device
                            device_id: afda895cc1812b99521eb78710326b89
                            entity_id: ef2eee2418adb0259f2f29dbd7ed8206
                            domain: sensor
                            above: 1900
                        sequence:
                          - sequence:
                              - if:
                                  - condition: device
                                    device_id: a9bed78637a3d4199888177480ba0f4b
                                    domain: select
                                    entity_id: faa8306ea0f42cc0b510209a0e408c8e
                                    type: selected_option
                                    option: Input mode
                                then:
                                  - device_id: a9bed78637a3d4199888177480ba0f4b
                                    domain: select
                                    entity_id: faa8306ea0f42cc0b510209a0e408c8e
                                    type: select_option
                                    option: Output mode
                                alias: >-
                                  SF2400 - Changement d'état IN to Out si
                                  necessaire
                              - action: number.set_value
                                target:
                                  entity_id: number.eeb4aep1p032084_outputlimit
                                data:
                                  value: >
                                    {% set current =
                                    states('sensor.te31njn8n387601_l3_p') |
                                    float(0) %} {% set output =
                                    states('number.eeb4aep1p032084_outputlimit')
                                    | float(0) %}

                                    {% if -50 <= current <= 50 %}
                                      {{ output | round(0) }}

                                    {% else %}
                                      {% set delta = 0.7 * current %}
                                      {% set cible = output + delta %}
                                      {% set result = cible - 50 if cible > 0 else cible %}
                                      {{ [result, 900] | min | round(0) }}
                                    {% endif %}
                        alias: >-
                          Qcells en Décharge mais on tire toujours de l'EDF, on
                          compense avec SF2400
                      - conditions:
                          - type: is_power
                            condition: device
                            device_id: a9bed78637a3d4199888177480ba0f4b
                            entity_id: b220a07315cd6e8c253e8c771528fd3e
                            domain: sensor
                            above: 50
                        sequence:
                          - sequence:
                              - action: number.set_value
                                target:
                                  entity_id: number.eeb4aep1p032084_outputlimit
                                data:
                                  value: >
                                    {% set current =
                                    states('sensor.te31njn8n387601_l3_p') |
                                    float(0) %} 

                                    {% set output =
                                    states('number.eeb4aep1p032084_outputlimit')
                                    | float(0) %}


                                    {% set delta = 0.3 * output %}

                                    {% set cible = output - delta %}

                                    {% set result = cible - 50 if cible > 0 else
                                    cible %}


                                    {% if -50 <= result <= 50 %}
                                      {{ output | round(0) }}

                                    {% else %}
                                      {{ [result, 900] | min | round(0) }}
                                    {% endif %}
                        alias: QCELLs est en Decharge mais SF aussi, on reduit SF
                alias: QCELLS en Decharge
        alias: Si HP
      - conditions:
          - condition: state
            entity_id: sensor.linky_current_price
            state:
              - HEURE CREUSE
        sequence:
          - alias: Faut-il lancer la charge du SF2400 ?
            choose:
              - conditions:
                  - condition: state
                    entity_id: sensor.qcells_etat
                    state:
                      - En décharge
                sequence:
                  - sequence:
                      - target:
                          entity_id: number.eeb4aep1p032084_inputlimit
                        data:
                          value: "0"
                        action: number.set_value
                alias: >-
                  QCELLs est en Décharge alors mettre le SF2400 en input mais à
                  0W !
              - conditions:
                  - condition: and
                    conditions:
                      - condition: state
                        entity_id: sensor.qcells_etat
                        state:
                          - Standby
                        alias: Si Qcells est Standby
                      - condition: numeric_state
                        entity_id: sensor.qcells_batterie_level
                        below: 11
                        alias: Si QCells < 11%
                      - type: is_battery_level
                        condition: device
                        device_id: a9bed78637a3d4199888177480ba0f4b
                        entity_id: 23f1ec717c4dcf6732d11bfaac92d296
                        domain: sensor
                        below: 35
                        alias: Si SF2400 < 35%
                sequence:
                  - sequence:
                      - alias: SF2400 - Changement d'état OUT to IN si necessaire
                        if:
                          - condition: device
                            device_id: a9bed78637a3d4199888177480ba0f4b
                            domain: select
                            entity_id: faa8306ea0f42cc0b510209a0e408c8e
                            type: selected_option
                            option: Output mode
                        then:
                          - device_id: a9bed78637a3d4199888177480ba0f4b
                            domain: select
                            entity_id: faa8306ea0f42cc0b510209a0e408c8e
                            type: select_option
                            option: Input mode
                      - target:
                          entity_id: number.eeb4aep1p032084_inputlimit
                        data:
                          value: "900"
                        action: number.set_value
                      - if:
                          - condition: numeric_state
                            entity_id: number.eeb4aep1p032084_inputlimit
                            below: 800
                        then:
                          - device_id: a9bed78637a3d4199888177480ba0f4b
                            domain: number
                            entity_id: 446540682f8a0142e01a5f8a2272926d
                            type: set_value
                            value: 900
                alias: Charge SF2400 Si Qcells vide et SF2400 <35%
              - conditions:
                  - type: is_battery_level
                    condition: device
                    device_id: a9bed78637a3d4199888177480ba0f4b
                    entity_id: 23f1ec717c4dcf6732d11bfaac92d296
                    domain: sensor
                    above: 89
                sequence:
                  - sequence:
                      - alias: SF2400 - Changement d'état IN to OUT si necessaire
                        if:
                          - condition: device
                            device_id: a9bed78637a3d4199888177480ba0f4b
                            domain: select
                            entity_id: faa8306ea0f42cc0b510209a0e408c8e
                            type: selected_option
                            option: Input mode
                        then:
                          - device_id: a9bed78637a3d4199888177480ba0f4b
                            domain: select
                            entity_id: faa8306ea0f42cc0b510209a0e408c8e
                            type: select_option
                            option: Output mode
                      - target:
                          entity_id: number.eeb4aep1p032084_outputlimit
                        data:
                          value: "300"
                        action: number.set_value
                alias: SF2400 est à >=90%
              - conditions:
                  - condition: and
                    conditions:
                      - condition: device
                        device_id: a9bed78637a3d4199888177480ba0f4b
                        domain: select
                        entity_id: faa8306ea0f42cc0b510209a0e408c8e
                        type: selected_option
                        option: Output mode
                        alias: "SF2400 Mode : output"
                      - type: is_battery_level
                        condition: device
                        device_id: a9bed78637a3d4199888177480ba0f4b
                        entity_id: 23f1ec717c4dcf6732d11bfaac92d296
                        domain: sensor
                        below: 41
                        alias: SF2400 Bat <=41%
                    alias: SF2400 <=41% et AC Output
                sequence:
                  - sequence:
                      - target:
                          entity_id: number.eeb4aep1p032084_outputlimit
                        data:
                          value: "0"
                        action: number.set_value
                        alias: "SF2400 Stop decharge : Output 0W"
                    alias: Stop decharge SF2400
                alias: SF2400 est à <=40% et si il etait en décharge, on stop
        alias: Si HC
mode: single

Présentation

Le but de ce process est le suivant :

Je vais essayer d'expliquer en détail ce que j'ai souhaité faire...

Mon installation :
- Solution QCells G1 avec 5.5kw en batterie et 2400Wc (installation toiture historique)
- Solution Zendure SolarFlow 800 avec 2 x 500Wc (Installation toiture Veranda)
- Solution Zendure SolarFlow 800 avec 2x 450Wc (Installation toiture Abris Bois)
- Solution Zendure SolarFlow 2400 Pro avec 4 x 450Wc (Future installation toiture Garage)

Pourquoi une si "grosse installation" ?

Habitant dans le sud (Aix en Provence), il est parfois nécessaire en été de se rafraichir... la climatisation de la maison (5 clims) et la piscine peuvent vite devenir un gouffre !
De même l'hiver, il est pas rare de devoir chauffer un peu !

Quand j'ai emménagé dans la maison, la première période (Aout 2023 - Aout 2024) a été un test, pas de clim et pas d'optimisation de la piscine
Résultat : 7.428kWh de consommés (HP 4.293kWh / HC 3.135kWh) : 1849€ TTC pour l'année, soit 154€ mensuel...

L'année suivante Aout 2024 - Aout 2025), 7.286kWh ( HP 3.942kWh / HC 3.344kWh) : 1772€ pour l'année, soit 148€ mensuel...
Cette seconde année a été marqué par le fait que j'ai optimisé un peu la piscine (variateur de pompe), qu'on a installé la Clim dans la maison, mais surtout que j'ai ajoutée un kit SF800, ce qui nous a pas réduis la conso, mais a rendu la maison plus confortable !
Bref c'était pas foufou...

Enfin cette troisième année Aout 2025 - Aout 2026, même si elle n'est pas fini, a été l'occasion de refaire un abris à bois et donc d'installer un second kit SF800 en guise de toiture en novembre 2025 !

Et à partir de ce moment, c'est devenu intéressant, on a tiré un peu moins d'EDF sur l'hiver, mais surtout, j'arrivais à charger le QCells a plus de 50%, ce qui était une bonne chose car avant ce n'était pas possible.

Depuis fin février et l'ajout d'une batterie AB2000, avec les beaux jours, cela c'est confirmé c'était intéressant.

Enfin depuis avril, les jours ensoleillés, le QCells se charge à plus de 80% et de temps à autre, je donne quelques kWh à EDF gratuitement.

L'idée était donc d'éviter de trop donner tout en essayer d'optimiser encore...

Ainsi depuis début mai, j'ai ajouter un kit SF2400 Pro avec 4 x 450Wc.

A ce jour, je suis à 4.425kWh (HP 1.192 / HC 2.513kWh)

Voici le tableau sur ces 3 an :

  2023 - 2024 2024 - 2025 2025 - 2026
  HP HC HP HC HP HC
juillet  142 128 274 294 248 299
aout 375 257 399 309 284 285
septembre 331 227 286 223 171 184
octobre  548 274 296 267 246 280
novembre  566 309 470 358 322 329
décembre  768 513 589 392 426 443
janvier  529 350 432 283 230 326
février  195 209 348 283 127 277
mars  185 182 265 219 53 211
avril  113 106 196 190 53 178
mai  299 319 153 228    
juin  242 261 234 298    
  4293 3135 3942 3344 2160 2812
  7428 7286 4972

Il fallait donc un petit chef d'orchestre pour gerer tout ca, HEMS n'etant pas capable d'avoir une vision d'ensemble et surtout de s'adapter au cas particulier.

Ainsi est né cet automatisme sous HA...

 

Fonctionnement

Ce script se base sur plusieurs éléments et tourne toute les 30 secondes.

Dans mon cas, les heures creuses sont de 20h50 à 4h50.

Dans un premier temps il vérifie si on est en heure pleine ou en heure creuse.

Si on est en HC, il va avoir 4 options :

Maintenant les HP !

Je me base en priorité sur l'état de mon QCells !
Il peut avoir 3 etats : Standby, en Charge, en Décharge

StandBy : c'est quand il est complètement vide ou complètement chargé
en Charge : il se charge avec le surplus de ses PV qu'il n'injecte pas
en Décharge : il balance ce que les PV produisent + sa batterie si nécessaire, dans la limite des 3500W

Il surveille ce que je tire d'EDF et compense de façon autonome et non pilotable !

J'ai pas le chois c'est comme ca...

Donc en StandBy :
Je demande au SF2400 de venir compenser uniquement si le QCells est vide.

En Décharge, 3 options :
- QCells est à plus de 90% alors je réduis ma charge sur le SF2400.
- QCells est en décharge mais on tire encore de l'EDF, alors SF2400 vient aider le QCells
- QCells est en décharge mais aussi SF2400, alors on va essayer d'adapter l'injection de SF2400 pour toujours privilégier une décharge de QCells

En Charge, 2 options :
- QCells se charge mais SF2400 injecte, alors on réduit l'injection de SF2400 au maximum
- QCells se charge mais on injecte encore vers EDF, on vient forcer la charge de SF2400 avec le surplus.

Ce qu'il va manquer maintenant c'est de limiter l'injection vers EDF si tout est full.

Au plus fort, il peut arriver d'envoyer 3000W vers EDF ce qui n'est pas supposer arriver...