Zendure - Plan énergétique - Modification via Home Assistant

Bonjour,

Mon problème

J’ai installé il y a quelques mois maintenant la solution Zendure avec Hyper 2000 et 4 batteries AB2000. Jusqu’à maintenant l’integration via MQTT me convenait tout à fait car mes batteries se chargeaient pendant la journée.

J’aimerais maintenant combiner deux modes énergétiques: Le soir, vers 22h si la charge des batteries est inférieure à 50%, j’active le mode « Attribution » jusqu’à 100% jusqu’à 6h ( Tempo ). S’il y a du soleil pendant la journée, j’aimerais changer vers le mode « Intelligent ».

Je n’arrive malheureusement pas à retrouver dans MQTT le champ qui contient le mode. Est ce que quelqu’un sait ? Est-il possible de récrire sur Zendure avec l’API existante ?

Ma configuration


[center]## System Information

version core-2024.9.2
installation_type Home Assistant OS
dev false
hassio true
docker true
user root
virtualenv false
python_version 3.12.4
os_name Linux
os_version 6.6.31-haos-raspi
arch aarch64
timezone Europe/Paris
config_dir /config
Home Assistant Community Store
GitHub API ok
GitHub Content ok
GitHub Web ok
HACS Data ok
GitHub API Calls Remaining 5000
Installed Version 2.0.1
Stage running
Available Repositories 1413
Downloaded Repositories 27
Home Assistant Cloud
logged_in true
subscription_expiration 4 mars 2025 à 01:00
relayer_connected true
relayer_region eu-central-1
remote_enabled true
remote_connected true
alexa_enabled true
google_enabled true
remote_server eu-central-1-6.ui.nabu.casa
certificate_status ready
instance_id 394d05695ec44bfa88316b6d9599dda6
can_reach_cert_server ok
can_reach_cloud_auth ok
can_reach_cloud ok
Home Assistant Supervisor
host_os Home Assistant OS 13.1
update_channel stable
supervisor_version supervisor-2024.09.1
agent_version 1.6.0
docker_version 26.1.4
disk_total 457.7 GB
disk_used 12.9 GB
healthy true
supported true
host_connectivity true
supervisor_connectivity true
ntp_synchronized true
virtualization
board rpi5-64
supervisor_api ok
version_api ok
installed_addons Advanced SSH & Web Terminal (19.0.0), Mosquitto broker (6.4.1), Zigbee2MQTT (1.40.1-1), Studio Code Server (5.15.0), SQLite Web (4.2.1), MQTT Explorer (browser-1.0.3), Spotify Connect (0.13.0)
Dashboards
dashboards 4
resources 17
views 7
mode storage
Recorder
oldest_recorder_run 18 septembre 2024 à 09:26
current_recorder_run 19 septembre 2024 à 15:49
estimated_db_size 289.04 MiB
database_engine sqlite
database_version 3.45.3
[/center] ___

Salut,

A défaut de connaitre l’info, tuu peux parcourir les éléments MQTT à sa recherche avec MQTT explorer, qui existe sous forme d’addon

Bonjour Pulpy-Luke,

Merci pour ton retour.

Avant de solliciter le forum, j’ai fait une analyse avec MQTT-explorer. Impossible de trouver la moindre information.

Nicolas

OK,

Dans ce cas, sauf à ce que quelqu’un avec le même matériel que toi passe (et sache), ça risque d’être assez long.
As-tu posé la question au SAV à tout hasard ?

Re,

oui j’ai parlé avec Zendure sur une nouvelle « feature » à ajouter dans l’application Zendure. Ils ont bien pris en compte ma demande mais ca ne serait pas de suite.

Je suis tout à fait conscient d’envoyer une bouteille à la mer mais je me suis dit que quelqu’un rencontrait peut être un besoin similaire.

Merci de ton retour.

Nicolas

Pour le moment, ce n’est pas accessible en MQTT.

Il y a que 3 switch qui remontent
image

Nous attendons tous avec impatience que Zendure ajout le pilotage du plan énergétique et du mode intelligent via MQTT.

Bonjour Olivr2s,

Ok j’ai la même chose, il va donc falloir s’armer de patience.

Merci pour le retour.

Nicolas

Bonjour,

J’ai pas ce matériel mais si ça sera disponible pour ton matériel, au besoin, voici comment j’ai crée mes automatisations qui vont dans ce sens :

  • La veille d’une journée Tempo « Rouge » :
    une notification active un scheduler pour recharger la batterie (et défini a 60% le niveau de la batterie a atteindre, mais on peut le changer via une slider dans HA )
automatisation EDF Tarif Rouge Notification
alias: EDF Tarif Rouge Notification
description: "Notification Alerte tempo : quand demain sera un tarifs rouge"
trigger:
  - platform: state
    entity_id:
      - sensor.edf_tempo_tomorrow
    from: unknown
    to: ROUGE
condition: []
action:
  - data:
      message: TTS
      data:
        ttl: 0
        priority: high
        tts_text: Attention Demain EDF tarif Rouge
    action: notify.mobile_app_xxx
  - data:
      title: EDF tarif Rouge
      message: Attention Demain EDF tarif Rouge
      data:
        ttl: 0
        priority: high
    action: notify.mobile_app_xxx

  - type: turn_on
    device_id: 61f41a9e351c76d19d5c30a7dbc7ef9e
    entity_id: a48f5d326bfb31c2efd2ee85362d94e4
    domain: switch
  - target:
      entity_id: number.battery_schedule_soc_limit
    data:
      value: "60"
    action: number.set_value
mode: single
  • a 22H ou a tout moment entre 22h & 6h, si on change le % de la batterie à atteindre, on change la vitesse de rechargement de la batterie (via une limite en intensité vers le circuit « DC »)
automatisation Charge la plus douce possible, pour arriver a X% de charge de la batterie
alias: Battery - Limite charge de la batterie en heure creuse
description: |
  Update number.battery_limit A value
  a 22h ou a chaque change de limit soc % entre 22h et 6
trigger:
  - platform: time
    at: "22:00:00"
  - platform: state
    entity_id:
      - number.battery_schedule_soc_limit
condition:
  - condition: state
    entity_id: switch.system_schedule_charge_hc
    state: "on"
  - condition: time
    after: "21:59:00"
    before: "05:59:00"
action:
  - action: number.set_value
    metadata: {}
    data:
      value: >-
        {# En prend le plut petit entre demain 6h- moins maintenant ET 8h #}{%
        if (now()| as_local).hour >= 22 %}{% set temp = ((now().replace(hour=5,
        minute=59, second=0, microsecond=0) + timedelta(days=1)) -
        now()).seconds /3600 %}{% elif (now()|as_local).hour < 6 %}{% set temp =
        (now().replace(hour=5, minute=59, second=0, microsecond=0) -
        now()).seconds /3600 %}{% else %}{% set temp = 7.98 %}{% endif %} {% set
        value = ((states('number.battery_schedule_soc_limit')
        | float(default=0) - states('sensor.battery_soc') |
        float(default=0) ) / 100 * 15 / temp ) /
        states('sensor.battery_voltage') | float(default=0) * 1000 %}{%
        if value > 100 %}100{% elif value > 0 %}{{ value | round + 1 }}{% endif
        %}
    target:
      entity_id: number.battery_charge_limit
mode: single
  • Si en Heure-creuse (hors veille d’un jour rouge), on a pas assez d’énergie dans la batterie pour passer la nuit, on recharge pas, mais on puisse sur le réseau pour le besoin de la maison (ça serait dommage de vider la batterie en Heure Creuse, puis de devoir utiliser le réseau en Heure Pleine car la batterie est vide) :

ps : a l’origine, ce qu’il y avait en condition était en trigger mais ça fessait beaucoup de check inutile a home assistant, …

automatisation Batterie Vide pour passer la nuit
alias: Batterie Vide pour passer la nuit
description: >-
  postulat : besoin de 300wh la nuit

  Si en Heure Creuse on a plus assez d’énergie pour passer la nuit, c'est mieux
  d'utiliser EDF pour la nuit (mais pas de recharger ) 
trigger:
  - platform: time
    at: "22:00:00"
  - platform: time
    at: "23:00:00"
  - platform: time
    at: "00:00:00"
  - platform: time
    at: "01:00:00"
  - platform: time
    at: "02:00:00"
  - platform: time
    at: "03:00:00"
  - platform: time
    at: "04:00:00"
  - platform: time
    at: "05:00:00"
condition:
  - alias: Si puissance requise pour passer la nuit est > puissance batterie restante
    condition: template
    value_template: >-
      {% if (now()| as_local).hour >= 22 or (now()|as_local).hour < 6 %}
        {% set duree = ( ( state_attr("sun.sun", "next_rising")| as_datetime | as_local ) + timedelta(hours=1) - now()).seconds /3600 %}
      {% else %}
        {% set duree = 0 %}
      {% endif %} {% if ( (duree * 0.3 ) + 0.5 ) | round(2) > ( (
      states('sensor.battery_soc') | float (default=0) -
      states('number.min_soc') | float (default=0) )* 14.5 /
      100 ) | round (1) %} true {% else %} false {% endif %}
action:
  - action: notify.mobile_app_sm_a346e
    metadata: {}
    data:
      title: Cerbo Schedule Charge HC minimal
      message: >-
        {% if (now()| as_local).hour >= 22 or (now()|as_local).hour < 6 %}   {%
        set duree = ( ( state_attr("sun.sun", "next_rising")| as_datetime |
        as_local ) + timedelta(hours=1) - now()).seconds /3600 %} {% else %}  
        {% set duree = 0 %} {% endif %} duree restant pour passer la nuit : {{
        duree | round(2) }}h puissance requise : {{ ( (duree * 0.3 ) + 0.5 ) |
        round(2) }}Kwh batterie restante : {{ ( (
        states('sensor.battery_soc') | float (default=0) -
        states('number.min_soc') | float (default=0) )* 14.5 /
        100 ) | round (1) }}Kwh
  - action: number.set_value
    metadata: {}
    data:
      value: "{{ states('number.min_soc') | int (default=0) +1 }}"
    target:
      entity_id: number.battery_schedule_2_soc_limit
    alias: Limit Schedule 2 limit SOC = Min SOC +1
  - action: number.set_value
    metadata: {}
    data:
      value: "1"
    target:
      entity_id: number.battery_charge_limit
    alias: >-
      mettre a 1A la vitesse de rechargement, pour pas recharge mais prendre d
      EDF pour ac-out
  - action: switch.turn_on
    data: {}
    target:
      entity_id: switch.system_schedule_2_activer
  - action: input_datetime.set_datetime
    data_template:
      entity_id: input_datetime.schedule_2_duree
      time: >
        {% if (now()| as_local).hour >= 22 or (now()|as_local).hour < 6 %}   {%
        set duree = ( ( state_attr("sun.sun", "next_rising")| as_datetime |
        as_local ) + timedelta(hours=1) - now()).seconds /3600 %} {% else %}  
        {% set duree = 0 %} {% endif %} {% set dure = duree * 0.3 + 0.5 %} {%
        set requise = ( (duree * 0.3 ) + 0.5 ) | round(2) %} {% set restant = (
        ( states('sensor.battery_soc') | float (default=0) -
        states('number.min_soc') | float (default=0) )* 14.5 /
        100 ) | round (1) %} {% if restant < requise %}   {{ ( ( ( (requise -
        restant ) / 0.3 *3600 )+ 900 ) | int | as_datetime).time() }} {% else
        %}   {{ ( ( 0 ) | int | as_datetime).time() }} {% endif %}
    alias: Defini Duree du Schedule 2
  - action: input_datetime.set_datetime
    data_template:
      entity_id: input_datetime.schedule_2_heure_de_demarrage
      time: >
        {{ (now().replace(second=0, microsecond=0) +
        timedelta(minutes=5)).strftime("%H:%M:%S") }}
    alias: Defini Start du Schedule 2
mode: single

ps: 14.5, c’est la puissance de la batterie en Kwh (hardcoder dans les automatisations) , à changer suivant la configuration de chaque un.

ps2: j’ai une autre automatisation qui a 6h, reset la valeur de la limite en intensité vers le circuit DC et déactive le schedule mais elle est facile et n’a pas d’intérêt dans l’exemple ici.

Merci beaucoup Roumano.

J’utilisais ce même principe avec mes batteries EcoFlow. Je te remercie pour tout, je vais lire ton code il y a certainement des parties à réutiliser.

Merci encore.

Nicolas

Bonjour à tous, je jete un pavé dans la marre mais si il est possible de piloter en local via HA le Hyper et tous les produits Zendure. Cependant ca nécessite du développement sourcing + coding. Quelqu’un a réussi à piloter le switch pour le AC entre la recharge AC de la batterie et la décharge AC de la batterie ? Il ne me manque plus que cela pour avoir un pilotage complet

PS : quelqu’un sait à quoi servent les switch : « acSwitch », « masterSwitch » ?

J’ai trouvé une autre piste qui permet de récupérer via mqtt les sensor et switch pour le Hyper 2000 qui est celle-ci:

ça utile IoBroker pour faire comme si on utilisait l’appli Android avec plus d’informations en retour et d’autres possibilité de pilotage.

Je viens tout juste de tester avec un Orange Pi PC+ qu’il me restait dans un coin, sur lequel j’ai installé un système Debian, puis IoBroker dessus.

Une fois IoBroker d’installé et fait les premières configurations de démarrage, il faut installer l’adaptateur MQTT
image
et le configurer comme l’exemple du Wiki du Github

Après on installe l’adaptateur Zendure
image
et on le configure avec l’identifiant et mot de passe de son appli Zendure Android.
Attention, la connexion au compte Zendure déconnecte celle de l’appli Android (1 seule connection à la fois). Pour pouvoir garder un accès sur son téléphone Android, il faut créer un autre compte Zendure et faire un partage à se second compte, puis utiliser le second compte sur son appli Android.

Si les 2 adaptateurs son bien configurés, on devrait avoir tout en vert dans le panneau de contrôle des instances.

Pour vérifier que le MQTT de IoBroker diffuse bien, un petit tour dans MQTTExplorer…
image
Et il devrait il y avoir ça…

Par rapport à la méthode du MQTT du serveur EU de Zendure, les informations notamment de puissances s’actualisent beaucoup plus vite, et il y a plus d’informations et controls.

Pour pouvoir récupérer dans Home Assistant les infos MQTT de IoBroker, il faut ajouter dans Mosquitto un fichier de configuration pour MQTT externe et redémarrer Mosquitto.
image

Si tout va bien (pas d’erreur dans les logs de Mosquitto, et connected au MQTT de IoBroker),
Il va être possible de récupérer les informations de MQTT.
Pour cela il faut rajouter dans la config yaml de mqtt les sensors et switch que l’on souhaite.
image

Pour avoir ça dans HA

J’ai pas encore tout récupéré et testé, mais on peut changer la puissance de sortie à la demande, même sans désactiver le mode intelligent. Je dois tester encore le reste des control.

Sinon le dev de l’adaptateurs Zendure sur IoBroker à l’air assez actif, ce qui est bien pour la suite…

Sur les partie que tu veut pouvoir interagir plus finement (dans certains cas), utilise select, ou le plus utile: number

  - name: "Schedule 2 Durée"
    unique_id: ...
    min: 0
    max: 86340
    step: 60
    mode: slider
    command_topic: "..."
    command_template: >
      {"value": {{ value }} }
    state_topic: "..."
    value_template: >
      {{value_json.value | round(0) }}

Si tu fait comme ça, tu peut interagir sur ton matériel via une action input_datetime.set_datetime ( ou number.set_value )

  - action: number.set_value
    metadata: {}
    data:
      value: '{{ state_attr(''input_datetime.yyyyy'',''timestamp'')
        }}'
    target:
      entity_id: number.xxx

Un grand merci Olivr2s. Je vais tester tout ca ce jour, je vous ferais un retour et peut être un petit bout de doc pour permettre à d’autres d’en profiter.

Oui, c’est prévu d’utiliser select ou number pour optimiser les contrôles avec HA.
C’est tout frais et il faut que je pose maintenant ce que je vais faire avec tout ça…

1 « J'aime »

Merci, cela fonctionne parfaitement