Automatisme Arrosage avec Node Red

Ben oui, mais tu en es là …

1 « J'aime »

Pas de problème. Quand je fais un truc, j’aime bien comprendre.
Faire un copier/coller d’un truc tout fait sans comprendre ce que l’on fait, ce n’est pas mon choix.
Et comme tout ou presque, Node Red, jsonata,… et HA d’ailleurs, ça demande un investissement en temps assez significatif.
Je peux te donner la solution, mais à part résoudre ce cas-là précis, ça ne sert à rien.
L’exemple que j’ai donné devrais mettre sur la piste. Pas d’arriver au but.

1 « J'aime »

Pas de problème non plus pour moi, c’est toi qui a raison. Mais quand on a 36 choses à faire en même temps, il faut bien faire des choix pour le temps à y consacrer.
Disons que cette galère passagère est mal tombée, j’y reviendrai plus tard…
Merci encore pour ton aide,
patrickp78

J’ai quand même du mal à comprendre la démarche.
Apriori tu n’as pas tellement de temps à consacrer à ce problème, tu as donc encore moins le temps d’apprendre et de rentrer dans les détails… mais tu t’obstine avec NR alors que tout le monde te dis que ça serait plus simple et plus vite fait avec les automatisations HA.
C’est quoi la raison exact de cette acharnement ? (qui de l’extérieur semble bien injustifié)

1 « J'aime »

Vu de l’extérieur, cela peut sembler être de l’acharnement effectivement. Disons plutôt que j’aime bien arriver à mes fins avec un peu d’obstination malgré tout, un peu trop peut-être, mais ça fonctionne la plupart du temps et c’est extrêmement enrichissant.
Si ce n’était pas le cas, jamais, avec votre aide à tous, je n’aurais avancé en domotique comme je l’ai fait. C’est un peu aussi le but du forum, non ?

Pour en revenir à notre sujet, il se trouve que très vite je me suis pris d’affection pour Node Red et son enchaînement de fonctions très graphiques. Mises à part une cinquantaine d’entrées HA effectivement plus faciles à créer que dans Node Red, 98% de mes automatismes sont faits avec Node Red. Je ne vais donc pas l’abandonner aussi facilement ! :rofl:

C’est donc par réflexe que j’ai posté mon problème sous l’étiquette Node Red. Pour autant, je n’ai aucune action chez eux et s’il faut leur faire quelques infidélités passagères, pourquoi pas ?
Obstiné, mais pas obtus ! :wink:

Cordialement,
patrickp78

Je ne comprends pas bien l’histoire des deux jours, l’information humidité n’est pas suffisante ?
Tu stockes la date du dernier arrosage j’imagine ?
J’ai un flux Node Red qui fait la différence entre la date de validité de mon certificat SSL et la date du jour pour lancer une action Let’s encrypt si < 15j.

Pas le temps là mais si ça peut t’aider dis moi :wink:

Bob

Merci pour le coup de main !
Je ne suis pas certain de la sonde d’humidité qui n’est pas placée au meilleur endroit (liaison bluetooth vers esp32 wifi). Du coup, je ne veux pas au départ que l’arrosage puisse se mettre en route toutes les nuits, je préfère acheter du whisky que de la flotte :joy:
Et puis mieux vaut un bon arrosage espacé plutôt que quotidien.
Je verrai comment optimiser ça plus tard…

Avec la doc de @golfvert et ton exemple, je vais essayer de décortiquer tout cela tranquillement ligne par ligne pour bien piger.
En attendant, le principe c’est bien de stocker la date du dernier arrosage et de le comparer chaque nuit à 4:00 du matin à la date en cours.
Et si la différence est supérieure à 2 jours, l’arrosage se met en route.
Pour les autres paramètres (%HR, pluie, présence…) je n’ai pas de problème. Des pros comme vous auraient surement fait mieux mais ça fonctionne déjà très bien en manuel, reste à finaliser l’automatique.
Cordialement,
patrickp78

Les noeuds:


Expiration certificat:

Expir:

Date:

Jour:

DiffDate, je l’ai déjà mis dans le message précédent.
Commuter:

Je ne fais pas d’explication de code hein :wink:

EDIT: les sorties de dates dans debug:

  1. Expiration certificat
  2. Expiration certificat (timestamp)
  3. Date du jour (timestamp)
  4. Différence de date en jours

Bon arrosage @patrickp78 :wink:
Bob

1 « J'aime »

Merci @Bob pour toutes ces infos !
Je vais digérer tout ça dès que possible.

Ce n’est sans doute pas très académique, je vous l’accorde, mais ça me permet d’avancer…
Pour info j’ai coupé le flux d’allumage pour avoir une différence entre les deux flux.

Pourquoi la soustraction ne se fait-elle pas dans la fonction alors que je récupère bien des millisecondes dans chaque flux ?
Est-ce une erreur de syntaxe ou est-ce que les timestamp dans le flux ne sont pas reconnus comme des nombres ?
Merci pour votre aide,


Bonjour @patrickp78
Tu pourrais partager l’export de ton flow stp ?

Bob

Le voici

[{"id":"96d348d3b7b51f80","type":"cronplus","z":"17a31d0eba8efa0c","name":"Eclairage ttes les 2 min","outputField":"payload","timeZone":"","persistDynamic":false,"commandResponseMsgOutput":"output1","outputs":1,"options":[{"name":"schedule1","topic":"topic1","payloadType":"default","payload":"","expressionType":"cron","expression":"0 */2 * * * * *","location":"","offset":"0","solarType":"all","solarEvents":"sunrise,sunset"}],"x":170,"y":200,"wires":[["21eb9fbb5be830f5","91d6d83a9167ad07","cda5111a99401062"]]},{"id":"f2219af863b7da78","type":"api-call-service","z":"17a31d0eba8efa0c","name":"OFF Appliques Bureau","server":"f1388c55.bbcd1","version":7,"debugenabled":false,"action":"light.turn_off","floorId":[],"areaId":[],"deviceId":[],"entityId":["light.appliques_bureau"],"labelId":[],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","blockInputOverrides":false,"domain":"light","service":"turn_off","x":1140,"y":300,"wires":[[]]},{"id":"cda5111a99401062","type":"api-call-service","z":"17a31d0eba8efa0c","name":"ON Appliques Bureau","server":"f1388c55.bbcd1","version":7,"debugenabled":false,"action":"light.turn_on","floorId":[],"areaId":[],"deviceId":[],"entityId":["light.appliques_bureau"],"labelId":[],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","blockInputOverrides":false,"domain":"light","service":"turn_on","x":640,"y":200,"wires":[["4baf9dc46d79fa3a","c2a36e8e21e3da54","0e14c0d0bd293e59"]]},{"id":"4baf9dc46d79fa3a","type":"delay","z":"17a31d0eba8efa0c","name":"","pauseType":"delay","timeout":"15","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":920,"y":300,"wires":[["f2219af863b7da78"]]},{"id":"c2a36e8e21e3da54","type":"change","z":"17a31d0eba8efa0c","name":"","rules":[{"t":"set","p":"last_allumage","pt":"flow","to":"payload.triggerTimestamp","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":950,"y":220,"wires":[[]]},{"id":"113ab559994803a4","type":"debug","z":"17a31d0eba8efa0c","name":"debug 17","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":620,"y":280,"wires":[]},{"id":"91d6d83a9167ad07","type":"function","z":"17a31d0eba8efa0c","name":"function 4","func":"let HreNew = flow.new_allumage;\nlet HreOld = flow.old_allumage;\nmsg.payload = HreNew - HreOld;\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":420,"y":280,"wires":[["113ab559994803a4"]]},{"id":"21eb9fbb5be830f5","type":"change","z":"17a31d0eba8efa0c","name":"","rules":[{"t":"set","p":"new_allumage","pt":"flow","to":"payload.triggerTimestamp","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":470,"y":140,"wires":[[]]},{"id":"0e14c0d0bd293e59","type":"debug","z":"17a31d0eba8efa0c","name":"debug 7","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":900,"y":160,"wires":[]},{"id":"f1388c55.bbcd1","type":"server","name":"Home Assistant RBT","addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"","connectionDelay":false,"cacheJson":false,"heartbeat":false,"heartbeatInterval":"","statusSeparator":"","enableGlobalContextStore":false}]

Ok, je regarde en arrivant chez moi.
Bob

1 « J'aime »

J’ai beau retourner le problème dans tous les sens, je ne comprends pas pourquoi l’opération ne se fait pas !
J’ai pourtant simplifié le flux au maximum :

  • Inject toutes les 2 minutes = payload ok en millisecondes
  • flow.last_allumage = en millisecondes
  • function 4 = payload - flow.last_allumage = résultat NaN !!!

Avec payload - 50, ça marche
Avec flow.last_allumage - 50 = résultat NaN !
C’est donc le flow en millisecondes qui n’est pas reconnu comme nombre, allez savoir pourquoi, alors que si on clique sur le flow, il affiche bien l’heure en clair, ce sont donc bien des millisecondes, donc un nombre…
Je vais voir s’il ne faut pas lui préciser le format millisecondes quelque part.
Merci pour votre aide,
patrickp78

[{"id":"ab434c9a3ddf494b","type":"inject","z":"17a31d0eba8efa0c","name":"Toutes les 2 min","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"120","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":170,"y":180,"wires":[["113ab559994803a4","91d6d83a9167ad07"]]},{"id":"113ab559994803a4","type":"debug","z":"17a31d0eba8efa0c","name":"debug 17","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":400,"y":240,"wires":[]},{"id":"91d6d83a9167ad07","type":"function","z":"17a31d0eba8efa0c","name":"function 4","func":"msg.payload = msg.payload - flow.last_allumage;\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":400,"y":180,"wires":[["d9193ed3b79834e8","827acb8b57e6fef4"]]},{"id":"d9193ed3b79834e8","type":"switch","z":"17a31d0eba8efa0c","name":"","property":"payload","propertyType":"msg","rules":[{"t":"gte","v":"240000","vt":"num"},{"t":"lt","v":"240000","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":610,"y":180,"wires":[["cda5111a99401062","7a6ed4334f585048"],["c641e2fb3fa96aca"]]},{"id":"827acb8b57e6fef4","type":"debug","z":"17a31d0eba8efa0c","name":"debug 18","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":600,"y":240,"wires":[]},{"id":"cda5111a99401062","type":"api-call-service","z":"17a31d0eba8efa0c","name":"ON Appliques Bureau","server":"f1388c55.bbcd1","version":7,"debugenabled":false,"action":"light.turn_on","floorId":[],"areaId":[],"deviceId":[],"entityId":["light.appliques_bureau"],"labelId":[],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","blockInputOverrides":false,"domain":"light","service":"turn_on","x":860,"y":140,"wires":[["4baf9dc46d79fa3a","0e14c0d0bd293e59","c2a36e8e21e3da54"]]},{"id":"c641e2fb3fa96aca","type":"debug","z":"17a31d0eba8efa0c","name":"debug 16","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":820,"y":280,"wires":[]},{"id":"7a6ed4334f585048","type":"debug","z":"17a31d0eba8efa0c","name":"debug 20","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":820,"y":200,"wires":[]},{"id":"4baf9dc46d79fa3a","type":"delay","z":"17a31d0eba8efa0c","name":"","pauseType":"delay","timeout":"15","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":1120,"y":140,"wires":[["f2219af863b7da78"]]},{"id":"0e14c0d0bd293e59","type":"debug","z":"17a31d0eba8efa0c","name":"debug 7","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1120,"y":200,"wires":[]},{"id":"c2a36e8e21e3da54","type":"change","z":"17a31d0eba8efa0c","name":"","rules":[{"t":"set","p":"last_allumage","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1170,"y":80,"wires":[[]]},{"id":"f2219af863b7da78","type":"api-call-service","z":"17a31d0eba8efa0c","name":"OFF Appliques Bureau","server":"f1388c55.bbcd1","version":7,"debugenabled":false,"action":"light.turn_off","floorId":[],"areaId":[],"deviceId":[],"entityId":["light.appliques_bureau"],"labelId":[],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","blockInputOverrides":false,"domain":"light","service":"turn_off","x":1340,"y":140,"wires":[[]]},{"id":"f1388c55.bbcd1","type":"server","name":"Home Assistant RBT","addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"","connectionDelay":false,"cacheJson":false,"heartbeat":false,"heartbeatInterval":"","statusSeparator":"","enableGlobalContextStore":false}]

Bonjour,
pas sur ma machine donc je ne peux pas importer pour voir.
Tu fais ton calcul dans quel noeud ?
Si c’est « function 4 », alors c’est certainement qu’il ne dispose pas des deux infos, c’est pour cela que je passe par des global dans l’exemple que j’avais donné.

Bob

Si, si, il a bien les deux infos, mais je me suis aperçu que le flow.last_allumage qui affiche bien des millisecondes affiche aussi des jours, heures, minutes quand on clique dessus. Je pense donc qu’il faut préciser dans la fonction qu’il doit lire des millisecondes.
Voici le contenu de ma fonction 4 (ne pas tenir compte de la 2)

Plus le temps ce matin, je ne pourrais voir ça que ce soir,
Merci pour ton aide,

Bonjour @patrickp78
Je te propose un flow basé sur des global.

Pour conserver les variables global, flow ou context dans Node-RED sur Home Assistant, même après un redémarrage, tu dois activer la persistance du contexte.

Donc dans cet exemple j’ai pris le dernier changement de ma lampe marine (pour toi ce serait donc la fin du dernier arrosage sur une vanne ou je ne sais quoi).

Pour tester tu as juste à importer le flow et remplacer Lampe Marine par ton entité arrosage.

[{"id":"dbea5f3f3f2d4190","type":"tab","label":"Flux 1","disabled":false,"info":"","env":[]},{"id":"7756affa704fb4b8","type":"debug","z":"dbea5f3f3f2d4190","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":770,"y":200,"wires":[]},{"id":"0adec348a1076f06","type":"function","z":"dbea5f3f3f2d4190","name":"Jour","func":"msg.payload = msg.payload /1000 ;\nmsg.payload = parseFloat(msg.payload).toFixed(0);\nmsg.payload = Number(msg.payload);\nglobal.set('datejour', msg.payload);\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":570,"y":200,"wires":[["7756affa704fb4b8"]]},{"id":"81196c7c033e4f1f","type":"function","z":"dbea5f3f3f2d4190","name":"DiffDate","func":"var datejour = global.get('datejour');\nvar lastOnDate = global.get('lastOnDate');\nvar tempsval =  datejour - lastOnDate;\ntempsval = ((tempsval /3600) /24);\ntempsval = parseFloat(tempsval).toFixed(0);\nmsg.payload = Number(tempsval);\nglobal.set('datenewexpir', msg.payload);\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":440,"y":140,"wires":[["8ee0a403f6df497a"]]},{"id":"7fd42899a359e63d","type":"inject","z":"dbea5f3f3f2d4190","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payloadType":"date","x":210,"y":140,"wires":[["b131be350e4664d9","81196c7c033e4f1f"]]},{"id":"b131be350e4664d9","type":"ui_date_picker","z":"dbea5f3f3f2d4190","name":"","label":"date","group":"3c1c6a94b059fb77","order":2,"width":0,"height":0,"passthru":true,"topic":"topic","topicType":"msg","className":"","x":430,"y":200,"wires":[["0adec348a1076f06"]]},{"id":"8ee0a403f6df497a","type":"debug","z":"dbea5f3f3f2d4190","name":"debug 23","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":760,"y":140,"wires":[]},{"id":"56c1cf9535553e2e","type":"server-state-changed","z":"dbea5f3f3f2d4190","name":"Lampe Marine","server":"443ff1c5.63d78","version":6,"outputs":1,"exposeAsEntityConfig":"","entities":{"entity":["light.lampe_marine"],"substring":[],"regex":[]},"outputInitially":false,"stateType":"str","ifState":"","ifStateType":"str","ifStateOperator":"is","outputOnlyOnStateChange":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":190,"y":60,"wires":[["852b3c2602b2e612","81196c7c033e4f1f"]]},{"id":"6c05704a4fe2ab65","type":"debug","z":"dbea5f3f3f2d4190","name":"debug 26","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":760,"y":60,"wires":[]},{"id":"852b3c2602b2e612","type":"function","z":"dbea5f3f3f2d4190","name":"function 3","func":"let dateOn = new Date().toISOString();\nmsg.payload = dateOn.substring(0,dateOn.length -5);\nmsg.payload = Date.parse(msg.payload) /1000;\nglobal.set('lastOnDate', msg.payload);\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":440,"y":60,"wires":[["6c05704a4fe2ab65","81196c7c033e4f1f"]]},{"id":"3c1c6a94b059fb77","type":"ui_group","name":"Utilities","tab":"7a0a419fb6a93b55","order":3,"disp":true,"width":"6","collapse":false},{"id":"443ff1c5.63d78","type":"server","name":"Home Assistant Bruno","version":5,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":"30","areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true},{"id":"7a0a419fb6a93b55","type":"ui_tab","name":"Arbeitszimmer","icon":"dashboard","order":3}]

Le calcul est en jour, si tu le veux en heure je te laisse voir :wink:
Je te laisse aussi voir pour le déclenchement, cron ou autre.

Bob

Je vois pas en quoi le fait d’utiliser des variables globales plutôt que des variables de flow changera quoi que ce soit ?
Il ne me semble pas que le problème soit lié à la portée des variables…

Par contre pour récuperer une variable de flow, dans ma version de NR on fait

flow.get("ma_variable");

et non pas

flow.ma_variable;

Je ne suis pas spécialiste de NodeRed @Forhorse, j’ai juste quelques flow qui fonctionnent donc je partage le peu que je connais, ce que je propose fonctionne chez moi, après @patrickp78 en fera ce qu’il veut.
Merci pour la syntaxe, je testerai à l’occasion.
Compliqué l’arrosage :rofl:
Bonne soirée
Bob

Je ne suis pas un spécialiste non plus… loin de là !