Améliorer l'affichage du pourcentage de batterie des capteurs zigbee Xiaomi/Aqara avec node red

Bonjour,

J’utilise beaucoup de capteurs zigbee Xiaomi/Aqara dans mon installation via zigbee2mqtt.
la plupart du temps le niveau de batterie des capteurs restent à 100% pendant des mois/années.

Après quelques recherches, j’ai trouvé une solution assez simple pour avoir une indication un peu plus proche du niveau réel de la batterie.

En bref,

  • Nous allons récupérer le voltage renvoyé par le capteur,
  • Calculer le pourcentage en fonction de cette valeur,
  • Créer une nouvelle entité qui affichera le nouveau pourcentage de batterie du capteur.

Cette entité pourra être utilisée dans une carte lovelace ou une automatisation, une notification en cas de batterie faible par exemple.

Tout d’abord, il faudra activer l’entité « voltage » sur les capteurs concernés.
Cette entité est assez souvent désactivée de base (en tout cas sur zigbee2mqtt).
Pour ça, il suffit d’aller dans les paramètres, appareils, cliquer sur l’entité à activer, paramètres avancés, cocher « activer » puis valider en cliquant sur mise à jour.
Pour prendre en compte les modifications, il faut REDEMARRER HOME ASSISTANT

activer entite voltage

Une fois que nos entités voltages sont activées, on peut commencer.

Le flow node red est assez simple.

[{"id":"dde87b8ae3fac06c","type":"tab","label":"Batterie","disabled":false,"info":"","env":[]},{"id":"fa63d7d64e0be27f","type":"inject","z":"dde87b8ae3fac06c","name":"Tous les lundis 8h","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"00 08 * * 1","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":170,"y":120,"wires":[["23cade183fba7f56"]]},{"id":"2e66d4e31e6d7b54","type":"function","z":"dde87b8ae3fac06c","name":"Calcul de la batterie","func":"percentage = toPercentage(msg.payload, 2800, 3200, true);\n\nfunction toPercentage(value, min, max, log=false) {\n    if (value > max) {\n        value = max;\n    } else if (value < min) {\n        value = min;\n    }\n\n    const normalised = (value - min) / (max - min);\n    let percentage;\n    if (log == true) {\n        percentage = normalised === 0 ? 0 : normalised * (1 - Math.log( normalised ));\n    } else {\n        percentage = normalised;\n    }\n    msg.payload = Math.round(percentage * 100);\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":620,"y":120,"wires":[["abdec2e93262d12e"]]},{"id":"23cade183fba7f56","type":"api-current-state","z":"dde87b8ae3fac06c","name":"Etat Switch Salon","server":"ec865156.c67db","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.salon_switch_voltage","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":390,"y":120,"wires":[["2e66d4e31e6d7b54"]]},{"id":"abdec2e93262d12e","type":"ha-entity","z":"dde87b8ae3fac06c","name":"Batterie Switch Salon","server":"ec865156.c67db","version":2,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"salon_switch_batterie"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:battery-50"},{"property":"unit_of_measurement","value":"%"},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"state":"payload","stateType":"msg","attributes":[],"resend":true,"outputLocation":"payload","outputLocationType":"none","inputOverride":"allow","outputOnStateChange":false,"outputPayload":"","outputPayloadType":"str","x":860,"y":120,"wires":[[]]},{"id":"ec865156.c67db","type":"server","name":"Home Assistant","version":2,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":30}]

J’ai d’abord mis un noeud « Timestamp » qui va activer le flow une fois par semaine.
Je préfère ne pas le faire trop souvent pour ne pas vider la batterie des capteurs.

Ensuite un noeud « current state » qui va simplement vérifier la valeur de l’entité « voltage » du capteur.

le noeud « fonction » va récupérer la valeur voltage puis calculer un pourcentage en fonction d’une valeur minimum et maximum que l’on peut modifier en fonction du capteur.

Voilà le code a mettre dans le noeud « fonction » :

percentage = toPercentage(msg.payload, 2800, 3200, true);

function toPercentage(value, min, max, log=false) {
    if (value > max) {
        value = max;
    } else if (value < min) {
        value = min;
    }

    const normalised = (value - min) / (max - min);
    let percentage;
    if (log == true) {
        percentage = normalised === 0 ? 0 : normalised * (1 - Math.log( normalised ));
    } else {
        percentage = normalised;
    }
    msg.payload = Math.round(percentage * 100);
}
return msg;

J’utilise 2800mV comme valeur minimum et 3200mV comme valeur maximum (dans la première ligne).
Si ces valeurs ne donne pas de bons résultats pour vos capteurs, il est possible de les modifier.

Enfin, le dernier noeud est un noeud « entity ». Comme son nom l’indique, il va créer une nouvelle entité dans HA avec le pourcentage de batterie que l’on a calculé juste avant.

Dans la partie Home Assistant Config, on donne un nom a notre entité.
j’ai utilisé le même nom que l’entité originale mais j’ai mis « batterie » à la fin a la place de « battery » pour ne pas les confondre.
On peut choisir une icone et on indique quelle est l’unité de mesure (ici le %)

Pour se faire une idée, voila la batterie de mon interrupteur du salon donnée par zigbee2mqtt :
batterie z2m

La batterie a plus d’un an ça m’étonnerait beaucoup qu’elle soit toujours à 100%.

Dans la nouvelle entité, la valeur me semble plus juste.
batterie entité

Pour plusieurs capteurs, ça donne ça:

C’est pas super joli mais pour moi c’est utile :wink:

Si vous voulez en savoir un peu plus sur la remontée et le calcul des infos de batterie, j’ai trouvé la plupart des infos dans cette discussion. Il y a pas mal d’infos intéressantes pour un peu mieux comprendre comment ça fonctionne (an anglais).
https://github.com/Koenkk/zigbee2mqtt/issues/8499

4 « J'aime »

Salut,

De mon coté, j’ai regardé, mais à priori, tous les appareils ne remontent pas le voltage sous z2m.
Donc difficile à généraliser

Juste pour le fun, l’équivalent sans NR est faisable dans un template sensor, ou du decluttering

{%- set min=2800 -%}
{%- set max=3200 -%}
{%- set value=state_attr('monsensor','voltage') -%}
{%- set normalised = (value - min) / (max - min)  %}
{{ normalised*100|round(0,2) }}%

4 « J'aime »

Oui c’est pour ça que j’ai précisé Xiaomi/Aqara
Je ne sais pas si tous les capteurs de la marque remontent l’information « voltage » en tout cas tous les miens le font.

Quant à ton code, il est beaucoup plus simple, et clair que celui que j’ai récupéré. Merci beaucoup.

J’ai perdu le peu de notions de JS que j’avais après 6 ans a ne pas pratiquer.
(J’étais déjà pas très doué a la base) :sweat_smile:

1 « J'aime »