Bon je vous avez dit que je débutais dans HA, mais c'est aussi le cas pour Node RED
Je suis en train de me faire une borne de charge pour mon VE avec un controleur Etek EKEPC2-S, si certains sont interessé, je pourrais ouvrir un autre post pour expliqué un peu le projet.
Ce controleur dispose d'une liaison RS485, on peut donc le piloter a distance et récupérer certaines infos.
Pour la partie Comm je passe par un petit module Ethernet/RS485 qui me permet d'interroger le controleur en Modbus TCP.
Ca fonctionne , comme je découvre les bloc dans node red c'est pas évident au début...
Maintenant je voudrais récupérer les valeur sous HA
Je me dis que ca serrait bien de créer du coup un device dans lequel j'aurais les sensors et quelques objet pour contrôler la borne.
Du coup est-ce que quelqu'un sait comment on pourrait faire ? (C'est a priori possible, mais je n'ai pas vue d'exemple)
KNX Partner Base / Avancé
Ma boite de MP est pleine, merci de créer un post si vous avez une question, cela profitera a tout le monde.
12/08/2024, 15:42:36 (Modification du message : 12/08/2024, 15:44:22 par NicNac.)
Je sais que ce n'est pas tout à fait l'endroit, mais, ne créerais tu pas un dossier HA vu que nous sommes je crois nombreux à utiliser Home Assistant où l'on pourrait y mettre nos découvertes et programmation non KNX.
Le dossier Configuration me semble pas réellement du KNX dans ton message. Même si je suis intéressé.
Citation :Je sais que ce n'est pas tout à fait l'endroit, mais, ne créerais tu pas un dossier HA vu que nous sommes je crois nombreux à utiliser Home Assistant où l'on pourrait y mettre nos découvertes et programmation non KNX.
Oui l'idée avait germé il y a quelques temps, mais je n'ai pas les droits pour le faire , faut que je relance qui de droit.
Citation :Le dossier Configuration me semble pas réellement du KNX dans ton message. Même si je suis intéressé.
J'ai pas trop compris le sens de ton message, si c'est l'emplacement du sujet. j'ai mis ici dans la partie supervision car NodeRED / MQTT / HA sont intimement lié et c'est l'endroit le plus judicieux actuellement pour ca.
KNX Partner Base / Avancé
Ma boite de MP est pleine, merci de créer un post si vous avez une question, cela profitera a tout le monde.
Autrement je ne voudrais pas m'attirer les foudres des administrateurs mais très bon forum francophone pour les questions vraiment HA: Hacf http://www.hacf.fr
Toutes les suggestion sont bonne, j'y avais jeté un coup d'oeil mais elle ne m'inspire pas cette intégration.
J'ai une table de 81 registres a lire.
J'effectue 2 requête de lecture uniquement pour lire cette table. Ce qui permet d'avoir un refresh ultra rapide avec très peu de requete de communication.
Avec cette intégration, je peux me tromper mais a vue de nez si je veux lire le mot 89 et le mot 91, j'aurais déjà 2 requetes.
Je suis en train de regarder si en passant par MQTT ca pourrait pas le faire. Car j'ai vue des sujets de création de device provenant de donnée plublié sur MQTT.
Bon maintenant je me heurte a un autre problème, j'ai pas pris option Javascript , ca existait pas dans mon cursus scolaire
Je publie facilement mes tableau sur MQTT, mais pour le moment mes topic comportent uniquement des index numériques
Faut que je trouve un moyen pour itéré le tableau et en fonction des index de nommer le topic
Voici la fonction NodeRED que j'utilise actuellement :
Code PHP :
// Input : msg.payload should be an arnay [442, e, 440 e, e ] // Define the base MQTT topic and starting index const baseTopic = "ETEK Chargeur 1"; // Replace with your base MQTT topic const startIndex = 0; // Replace with your desired starting index
// Iterate through the array and publish each value to a unique topic with a custom index const values = msg.payload; const topics = values.map((value, index) => `${baseTopic}/HR${startIndex + index}` );
const messages = values.map((value, index) => ({ topic: topics[index], payload: value.toString(), // Convert the value to a string })); return [messages] ;
(12/08/2024, 16:35:59)vincen a écrit : Autrement je ne voudrais pas m'attirer les foudres des administrateurs mais très bon forum francophone pour les questions vraiment HA: Hacf http://www.hacf.fr
Pas de soucis, le problème c'est que je pars de loin dans plein de domaine (HA/MQTT/NodeRED/Javascript... ) et qu'il me manque plein de base et que je commence pas forcément par les truc les plus simple.
KNX Partner Base / Avancé
Ma boite de MP est pleine, merci de créer un post si vous avez une question, cela profitera a tout le monde.
Citation :Je sais que ce n'est pas tout à fait l'endroit, mais, ne créerais tu pas un dossier HA vu que nous sommes je crois nombreux à utiliser Home Assistant où l'on pourrait y mettre nos découvertes et programmation non KNX.
Oui l'idée avait germé il y a quelques temps, mais je n'ai pas les droits pour le faire , faut que je relance qui de droit.
Citation :Le dossier Configuration me semble pas réellement du KNX dans ton message. Même si je suis intéressé.
J'ai pas trop compris le sens de ton message, si c'est l'emplacement du sujet. j'ai mis ici dans la partie supervision car NodeRED / MQTT / HA sont intimement lié et c'est l'endroit le plus judicieux actuellement pour ca.
Je voulais dire que l'on pourrait créer un répertoire spécifique Home Assitant différent de Logiciel libre(Link.....). Sinon toujours super le forum.
En parallèle de ce post, je suis en train de découvrir Modbus au travers de ma nouvelle installation photovoltaïque Huawei avec 2 onduleurs 10ktl M1 et une batterie Luna 15KwH. J'utilise l'intégration HA Huwei Solar, mais j'ai un décalage des valeurs d'énergie (en dehors des durées de mises à jour différentes) entre l'application FusionSolar de Huawei et les données transmises en Modbus par l'intégration Huwei Solar de HA.
Du coup j'aimerai trouver un utilitaire (si possible gratuit) pour interroger en Modbus directement les registres de Huawei afin de vérifier d'où viennent les discordances.
le module Modbus de HA serait-il la solution??
Où peut-être faut-il passer par les nodes de Node-Red.
A terme je pense utiliser le module KNX-Modbus de chez wiezhert, mais j'aimerai bien valider les données Modbus avant cela.
16/08/2024, 11:57:38 (Modification du message : 16/08/2024, 12:11:48 par richardpub.)
Je suis parti sur un piste avec open Modsim et la Vidéo. Je commence à voir des choses intéressantes, bien que pour l'instant en mode simulation.
Modsim semble fonctionner, par contre pas de connexion directe pour l'instant.
J'ai lancé Modbus sur Node-red mais je n'ai pas encore de lecture de ce qui se passe sur Modbus!!
il va falloir comprendre la notion de maitre et d'esclave!!
18/08/2024, 08:32:21 (Modification du message : 18/08/2024, 09:09:45 par filou59.)
Pour en revenir a mes moutons et donc au sujet principal.
Je suis en train d'opter pour la solution suivante : Creation d'un Device via MQTT
En gros voici comment ce décompose le truc :
1.[OK] Mon Device Modbus RTU : MaBornedeCharge (Branché en Ethernet avec un Adapateur EE11a Convertisseur Ethernet/RS485)
2.[OK]NodeRED : Interrogation du Module de charge via Liaison Modbus TCP.
3.[OK]NodeRED : Lecture des Registre de la Table Modbus
4.[TODO]NodeRED : Sauvegarde des Valeurs de Registre
5.[OK]NodeRED : Publication des Valeurs sur MQTT
6.[EnCours...]NodeRED : Surveillance MQTT (Subscriber)
6.[TODO]NodeRED : Ecriture des Registre de la Table Modbus (Sur Changement d'etat)
7.[EnCours...]HA : Creation d'un Device via fichier.yaml
Je sais pas comment faire :
8.Changer l'icone de mon Device (Là actuellement le Device a l'icone MQTT, ca m'énerve )
A la base le programe Lecture/Ecriture Modbus/MQTT pourrait être très simple.
Mais ... il y a un mais.
Lorsqu'on lit les valeurs sur le Modbus, si on les publies sur MQTT, deriere vue que l'on est abonné a un Topic qu'on veut aussi pouvoir ecrire, celui-ci nous génére un message, si je ferme les yeux, du coup ca déclenche une ecriture sur le modbus dans mon device.
Et ca il faut clairement éviter. Car on ne sait pas comment le device va gérer ca.
Si il est intelligent et que la valeur ne change pas il ne fera rien.
Dans le pire des cas ca fait une ecriture, et une écriture dans de la mémoire non volatile, suivant le type de mémoire et bien on peut rapidement cramer une puce. Certains fabriquants s'en sont déjà mordus les doigts.
Du coup il faut que je j'implémente un système d'ecriture "OnChange", je dois donc mémoriser la derniere valeur, et la comparer avec celle que je viens de recevoir.
Sur le papier c'est pas compliqué quand on connait bien un langage de prog, mais là je débute avec Node-RED et c'est pas forcément le truc le plus simple a faire pour débuter...
Du coup je me pose la question aussi de mon Publish vers MQTT, je peux éventuellement faire aussi pareil, un Publish OnChange ou un mix [OnChange ou OnDelay]
KNX Partner Base / Avancé
Ma boite de MP est pleine, merci de créer un post si vous avez une question, cela profitera a tout le monde.
21/08/2024, 15:18:31 (Modification du message : 21/08/2024, 15:19:18 par filou59.)
J'ai avancé (une peu lentement ) sur mon truc
1.[OK] Mon Device Modbus RTU : MaBornedeCharge (Branché en Ethernet avec un Adapateur EE11a Convertisseur Ethernet/RS485)
2.[OK]NodeRED : Lecture de Fichier CSV pour Charger le nom des Registre a Lire et leur Addresse
3.[OK]NodeRED : Interrogation du Module de charge via Liaison Modbus TCP.
4.[OK]NodeRED : Lecture des Registres de la Table Modbus
5.[OK]NodeRED : Sauvegarde des Valeurs de Registre dans Flow pour Comparaison Etat
6.[OK]NodeRED : Publication des Valeurs sur MQTT
7.[OK][/color]NodeRED : Surveillance MQTT (Subscriber)
8.[OK][/color]NodeRED : Ecriture des Registres de la Table Modbus (Sur Changement d'etat)
9.[EnCours...]HA : Creation d'un Device via fichier.yaml
Je sais pas comment faire :
8.Changer l'icone de mon Device (Là actuellement le Device a l'icone MQTT, ca m'énerve )
Je vais probablement intégrer la gestion de la charge directement dans NodeRED :
Mode de Charge : Instantané, Arret, Heure Creuse
Courant de Charge Maxi
Me reste après a voir comment fonctionne la régulation interne du controleur, car il peut adapter le courant de charge afin de ne pas dépasser un courant défini.
Ca ressemble a ca :
Bon au final je me suis retrouvé a faire pas mal de code en JS.
Pour une 1ere expérience, je suis content car j'y suis arrivé, mais non sans mal. Ca m'a pris pas mal de temps, pour différente raison, j'ai essayé de ne pas brulé les étapes en tentant d'apprendre et en commençant par les bases, mais quand on a un objectif d'application en tete on a vite tendance de prendre des raccourcis et d'aller droit au but.
J'ai donc fait un mix, un peu de base et qq raccourci
Beaucoup plus de temps donc que si j'avais ca directement dans mon automate WAGO.
KNX Partner Base / Avancé
Ma boite de MP est pleine, merci de créer un post si vous avez une question, cela profitera a tout le monde.
Il de la config dans L'environnement du Flow
Puis dans le BP de config
Ce flux nécessite normalement ca :
node-red-contrib-config
node-red-contrib-modbus
Si j'ai oublié une palette faite moi signe.
Code :
[{"id":"e6cc81bb1a8448d6","type":"tab","label":"Etek Modbus Array","disabled":false,"info":"","env":[{"name":"BASETOPIC","value":"ETEK_Borne_v5","type":"str"},{"name":"BASETOPIC_CMD","value":"ETEK_Borne_v4/cmnd/#","type":"str"},{"name":"STAT_TOPIC_DIR","value":"stat","type":"str"},{"name":"CMD_TOPIC_DIR","value":"cmnd","type":"str"}]},{"id":"84f321f0363d90e4","type":"group","z":"e6cc81bb1a8448d6","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["f8885cff676d7ee6","8c6ac4abd4a328c1","8d8597b1d87ddb58","7f2b930738fa68b6","a08f964816cfd9d4","b45d8b1d9be983a8","c50b5d1d4ba4d2c1"],"x":14,"y":499,"w":892,"h":202},{"id":"3232febd0ceac99d","type":"group","z":"e6cc81bb1a8448d6","name":"Disable","style":{"label":true,"color":"#ff0000"},"nodes":["1a4764f4.e619eb","380c5600.15f6fa","2739cc04.8cf06c","2d480aced01a8fa5","afa54b6ffd63ad40","ac9be6c17b8657ee","f8322fedf7e9f6c9","e99afac59d8e06af","517233ca62784742"],"x":14,"y":1019,"w":512,"h":382},{"id":"f649032686964af1","type":"group","z":"e6cc81bb1a8448d6","name":"","style":{"label":true},"nodes":["3ff7506e5ad0789c","be3b1c0048b672e5","2f6bc9d894bc0427","e1594cca2a7a0a37","09dd89bd0c2a40df","9492194fe0848524","98c5e3067de3010c","c904a7a5adc39119","c96b65adde138cc0","04ceca3d66c81c9a","0ef11b69d8d3f797","97ce823cd7b43492","81caa59d31738555","1bb49a267954922d","d56d60035690d41c","45a9e341dfa4ab56","b0041bd54123aecc","dae53049f2af714b"],"x":14,"y":159,"w":1112,"h":322},{"id":"78d43f17836ec011","type":"group","z":"e6cc81bb1a8448d6","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["c6b457795af6de41","ea1f48037a3dcf6b","fdf2322b9ae1cd47","5b232547fbfd20be"],"x":314,"y":19,"w":492,"h":122},{"id":"619fc7581fbfc0d3","type":"group","z":"e6cc81bb1a8448d6","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["65dbc8d5f97deae6","cc97bf6ee14d9e4e"],"x":14,"y":19,"w":272,"h":122},{"id":"b04f4bef237d1990","type":"group","z":"e6cc81bb1a8448d6","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["d92c65a4.566478","4e4829e3.eaeae8","b3b077c4f4020a03","ec2e03fa9fb04f11","327e3bdb553df041","4ae7a7804e28c4ef","bff8878355ae4279","bc234ce34d75c054","d3d99b7769fe85b9"],"x":14,"y":719,"w":1072,"h":242},{"id":"3ff7506e5ad0789c","type":"debug","z":"e6cc81bb1a8448d6","g":"f649032686964af1","name":"Tableau de Valeurs Recu","active":true,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":970,"y":260,"wires":[]},{"id":"380c5600.15f6fa","type":"switch","z":"e6cc81bb1a8448d6","d":true,"g":"3232febd0ceac99d","name":"","property":"payload","propertyType":"msg","rules":[{"t":"jsonata_exp","v":"($count(payload))=40","vt":"jsonata"},{"t":"jsonata_exp","v":"($count(payload))=41","vt":"jsonata"}],"checkall":"false","repair":false,"outputs":2,"x":90,"y":1160,"wires":[["1a4764f4.e619eb"],["2739cc04.8cf06c"]]},{"id":"1a4764f4.e619eb","type":"debug","z":"e6cc81bb1a8448d6","d":true,"g":"3232febd0ceac99d","name":"Reponse Pool1[40]","active":false,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":290,"y":1060,"wires":[]},{"id":"2739cc04.8cf06c","type":"debug","z":"e6cc81bb1a8448d6","d":true,"g":"3232febd0ceac99d","name":"Reponse Pool2[41]","active":false,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":290,"y":1120,"wires":[]},{"id":"be3b1c0048b672e5","type":"debug","z":"e6cc81bb1a8448d6","g":"f649032686964af1","name":"Taille Tableau Recu","active":true,"tosidebar":false,"console":false,"tostatus":true,"complete":"($count(payload))","targetType":"jsonata","statusVal":"($count(payload))","statusType":"auto","x":930,"y":200,"wires":[]},{"id":"2f6bc9d894bc0427","type":"comment","z":"e6cc81bb1a8448d6","g":"f649032686964af1","name":"Lecture de Toute la Table du Controleur ETEK","info":"","x":220,"y":200,"wires":[]},{"id":"65dbc8d5f97deae6","type":"comment","z":"e6cc81bb1a8448d6","g":"619fc7581fbfc0d3","name":"Reset/Init Config Variable : ","info":"","x":150,"y":60,"wires":[]},{"id":"2d480aced01a8fa5","type":"function","z":"e6cc81bb1a8448d6","d":true,"g":"3232febd0ceac99d","name":"fct PrepareData1toMQTT v2","func":"// Input : msg.payload should be an arnay [442, e, 440 e, e ]\n// Define the base MQTT topic and starting index\nconst baseTopic = \"ETEK Chargeur v2\"; // Replace with your base MQTT topic\nconst ListTopics = [\n\t\"R86_OV_protection_value\", \n\t\"R87_UV_protection_value\", \n\t\"R88_Current_protection_value\",\n\t\"R89_Remote_start & stop\", \n\t\"R90_kWH_meter_voltage_A_phase_address\",\n\t\"R91_kWH_meter_voltage_B_phase_address\",\n\t\"R92_kWH_meter_voltage_C_phase_address\",\n\t\"R93_kWH_meter_current_address\",\n\t\"R94_kWH_meter_power_address\",\n\t\"R95_kWH_meter_electricity_using_address\",\n\t\"R96_DLB_using_kWH_meter_address\",\n\t\"R97_Spare\",\n\t\"R98_Spare\",\n\t\"R99_Spare\",\n\t\"R100_Device_address_No\",\n\t\"R101_DLB_resume_work_current_value\",\n\t\"R102_DLB_protection_current\",\n\t\"R103_Ref_current_value\",\n\t\"R104_Ref_current_AD_value\",\n\t\"R105_Spare\",\n\t\"R106_Spare\",\n\t\"R107_Spare\",\n\t\"R108_Spare\",\n\t\"R109_Charger_PWM_Max_value\",\n\t\"R110_RCMU_function_choose\",\n\t\"R111_RFID_function_choose_\",\n\t\"R112_Lock_function_choose_\",\n\t\"R113_Cable_Socket_version_choose\", \n\t\"R114_DLB_function_choose\",\n\t\"R115_PID_control_parameter_KP\",\n\t\"R116_PID_control_parameter_KI\",\n\t\"R117_PID_control_parameter_KD\",\n\t\"R118_Controller_ID_number\",\n\t\"R119_Controller_ID_number\",\n\t\"R120_Temperature_correction\",\n\t\"R121_Temperature_correction\",\n\t\"R122_Overtemperature_protection_value_of_stop\",\n\t\"R123_Overtemperature_protection_value_of_start\",\n\t\"R124_Frequency_correction\",\n\t\"R125_Duty_cycle_correction\"]\n\nconst startIndex = 0; // Replace with your desired starting index\n\n// Iterate through the array and publish each value to a unique topic with a custom index\nconst values = msg.payload;\nconst topics = values.map((value, index) => `${baseTopic}/${ListTopics[index]}` );\n\nconst messages = values.map((value, index) => ({\n\ttopic: topics[index],\n\tpayload: value.toString(), // Convert the value to a string\n}));\nreturn [messages] ;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":320,"y":1200,"wires":[[]]},{"id":"afa54b6ffd63ad40","type":"function","z":"e6cc81bb1a8448d6","d":true,"g":"3232febd0ceac99d","name":"fct PrepareData1toMQTT v1","func":"// Input : msg.payload should be an arnay [442, e, 440 e, e ]\n// Define the base MQTT topic and starting index\nconst baseTopic = \"ETEK Chargeur v1\"; // Replace with your base MQTT topic\nconst startIndex = 0; // Replace with your desired starting index\n\n// Iterate through the array and publish each value to a unique topic with a custom index\nconst values = msg.payload;\nconst topics = values.map((value, index) => `${baseTopic}/HR${startIndex + index}` );\n\nconst messages = values.map((value, index) => ({\n topic: topics[index],\n payload: value.toString(), // Convert the value to a string\n}));\nreturn [messages] ;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":320,"y":1160,"wires":[[]]},{"id":"e1594cca2a7a0a37","type":"debug","z":"e6cc81bb1a8448d6","g":"f649032686964af1","name":"Read Sortie Bas (msg.value=array)","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":900,"y":360,"wires":[]},{"id":"09dd89bd0c2a40df","type":"debug","z":"e6cc81bb1a8448d6","g":"f649032686964af1","name":"Read Sortie Haut (msg.payload=array)","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":930,"y":320,"wires":[]},{"id":"9492194fe0848524","type":"inject","z":"e6cc81bb1a8448d6","g":"f649032686964af1","name":"1 Cycle","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":110,"y":240,"wires":[["04ceca3d66c81c9a"]]},{"id":"98c5e3067de3010c","type":"function","z":"e6cc81bb1a8448d6","g":"f649032686964af1","name":"fct2 ModbusValuetoMQTT v6","func":"/* ----------------------------------------------------------------------------\nDescription : Genere les Messages MQTT a partir des Valeurs Modbus\n\n-Charge la liste des Topic en fonction du Pool Actif\n-Filtre Les Topic envoyé vers MQTT \n\t-SR : Single Read (16bits)\n\t-SW : Single Write (16bits)\n\t-XX / Rien ou Autre : Disable\n-Genere le Topic MQTT en fonction de la list des Topic \n-Affecte la Valeur au topic\n\n----------------------------------------------------------------------------\nChangelog :\nv6 : \n-Utilisation des Variable d'environnement\n-Publication vers MQTT en mode Retain si Activé\n---------------------------------------------------------------------------- */\n\n//Lecture des Variable d'environnement du Flow\nconst sBaseTopic=env.get(\"BASETOPIC\");\t\t\t\t// ETEK_Borne_v4\nconst sStatTopicDir = env.get(\"STAT_TOPIC_DIR\");\t// stat\nconst sCmdTopicDir = env.get(\"CMD_TOPIC_DIR\");\t\t// cmnd\n\n\nconst bSendSRasRetain=flow.get('bSendSRasRetain');\nconst bSendSWasRetain=flow.get('bSendSWasRetain');\n\n//List des Topics a Envoyer sur MQTT\nlet aListTopics;\n// Recupere Le Pool Actif (Saved in fct1)\nlet sThisPool = msg.topic;\nswitch (sThisPool) {\n\tcase 'Pool1':\n\t\taListTopics=flow.get('aListTopicsPool1');\n\tbreak;\n\tcase 'Pool2':\n\t\taListTopics=flow.get('aListTopicsPool2');\n\tbreak;\n\tdefault:\n\t\tnode.status({fill:\"red\",shape:\"ring\",text:\"Nom de Pool Incorrect : msg.topic[\" + msg.topic + \"]\"});\n\t\treturn null;\t\t\t\n}\n\nlet values = msg.payload;\nlet messages = {};\n\nlet count = 0;\t//Nb de Message Envoyé vers MQTT\n\n// Si les Tailles sont différentes, on change le Status de la fct\nif (aListTopics.length===values.length) {\n\tlet result = values.reduce(function(result, field, index) {\n\t\tresult[aListTopics[index]] = field;\n\n\t\tlet sThisTopic = `${sBaseTopic}/${sStatTopicDir}/${aListTopics[index]}`;\n\t\tif (aListTopics[index].substring(0,2)===\"SR\" || aListTopics[index].substring(0,2)===\"SW\"){\t\t\t\n\t\t\tcount=count+1;\n\t\t\tmessages.topic=sThisTopic;\n\t\t\tmessages.payload=field.toString();\n\t\t\t/*\n\t\t\tif (aListTopics[index].substring(0,2)===\"SR\" && bSendSRasRetain) { messages.retain = true;} \n\t\t\telse if (aListTopics[index].substring(0,2)===\"SW\" && bSendSRasRetain) { messages.retain = true;} \n\t\t\telse {messages.retain = false;}\n\t\t\t*/\n\t\t\tnode.send(messages);\t\n\t\t}\t\t\t \n\t\treturn result;\n\t}, {})\n\n\tflow.set('aLastModbus',result);\n\tnode.status({fill:\"green\",shape:\"dot\",text:\"Read=\" + values.length + \" ,Send2MQTT=\" + count});\n} else {\n\t//Erreur : Nb de Topic <> Nb de Valeur\n\tnode.status({fill:\"red\",shape:\"ring\",text:\"Nb Valeur Recu=[\" + values.length + \"]<> Tableau Defini[\" + aListTopics.length + \"]\"});\n\treturn null;\t\n}","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":240,"y":440,"wires":[["97ce823cd7b43492","c904a7a5adc39119"]],"info":"v5 : \r\n-Combine Tableau (Key+Valeur) pour retrouver Comparer les Valeur avant Ecrire\r\n-Enregistre les Valeur lu dans : flow.set('aLastModbus',result);\r\n\r\nTODO :\r\nLire le Tableau de Key depuis un Fichier plutot que d'avoir ca en Variable"},{"id":"c904a7a5adc39119","type":"mqtt out","z":"e6cc81bb1a8448d6","g":"f649032686964af1","name":"Publish Modbus2MQTT","topic":"","qos":"0","retain":"false","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"56f17224.5234f4","x":530,"y":440,"wires":[]},{"id":"f8885cff676d7ee6","type":"debug","z":"e6cc81bb1a8448d6","g":"84f321f0363d90e4","name":"debug fct MQTT Decoder","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":750,"y":600,"wires":[]},{"id":"ac9be6c17b8657ee","type":"function","z":"e6cc81bb1a8448d6","d":true,"g":"3232febd0ceac99d","name":"fct v4","func":"const baseTopic = \"ETEK_Borne_v4\";\nconst SensorTopic = \"stat\";\nconst CmdTopic = \"cmnd\";\n\n//List des Topic a Envoyer sur MQTT\nvar ListTopics = [\n\t\"SR86_OV_protection_value\", \n\t\"SR87_UV_protection_value\", \n\t\"SR88_Current_protection_value\",\n\t\"SW89_Remote_start_stop\",\n\t\"XX90_JenVeuxPas\"];\n\nvar values = msg.payload;\nvar messages = {};\n//msg.payload = ListTopics;\n//msg.newrows = ListTopics;\n\nvar count = 0;\n\nvar result = values.reduce(function(result, field, index) {\n\tresult[ListTopics[index]] = field;\n\treturn result;\n}, {})\n\nflow.set('aLastModbus',result);\n\nvalues.forEach((value, index) => {\n\tvar ThisTopic = `${baseTopic}/${ListTopics[index]}`;\n\t//const ThisTopic = topics[index];\n\tif (ListTopics[index].substring(0,2)===\"SR\" || ListTopics[index].substring(0,2)===\"SW\"){\n\t\tcount=count+1;\n\t\tmessages.topic=ThisTopic;\n\t\tmessages.payload=value.toString();\n\n\t\tnode.send(messages);\n\t}\n});\n\nnode.status({fill:\"green\",shape:\"dot\",text:\"Read=\" + values.length + \" ,Send2MQTT=\" +count});\n\n//msg.aCurrentValuewKey=result;\n\n//return msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":250,"y":1280,"wires":[[]]},{"id":"f8322fedf7e9f6c9","type":"function","z":"e6cc81bb1a8448d6","d":true,"g":"3232febd0ceac99d","name":"fct PrepareData1toMQTT v3","func":"// Input : msg.payload should be an arnay [26500,16500,120,2,65535,65535,65535,65535,65535,65535,65535,0,0,0,255,3500,4500,10000,1270,0,0,0,0,9000,3,3,1,1,1,10,80,1,0,0,1024,65456,850,1000,0,0]\n// Define the base MQTT topic and starting index\nconst baseTopic = \"ETEK Chargeur v3\"; // Replace with your base MQTT topic\nconst ListTopics = [\n\t\"R86_OV_protection_value\", \n\t\"E87_UV_protection_value\", \n\t\"R88_Current_protection_value\",\n\t\"E89_Remote_start_stop\",\n\t\"XX\"]\n\n// Iterate through the array and publish each value to a unique topic with a custom index\nconst values = msg.payload;\nconst messages = [];\nvar LenValues = values.length;\n// Si les Tailles sont différentes, on change le Status de la fct\nif (ListTopics.length === LenValues) {\n\t//On a le même Nombre de Valeur que de Topic\n\tnode.status({fill:\"green\",shape:\"dot\",text:\"OK\"});\n\tvalues.forEach((value, index) => {\n\t\tconst ThisTopic = `${baseTopic}/${ListTopics[index]}`;\n\t\t//const ThisTopic = topics[index];\n\t\tif (ListTopics[index].substring(0,1)===\"E\" ){\n\t\t\tmessages.push({\n\t\t\t\ttopic: ThisTopic,\n\t\t\t\tpayload: value.toString()});\n\t\t}\n\t});\n\treturn [messages];\n} else {\n\t//Erreur : Nb de Topic <> Nb de Valeur\n\tnode.status({ fill: \"red\", shape: \"ring\", text: \"Nb Valeur Recu=[\" + LenValues + \"]<> Tableau Defini[\" + ListTopics.length + \"]\"});\n\treturn null;\t\n}\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":320,"y":1240,"wires":[[]]},{"id":"8c6ac4abd4a328c1","type":"mqtt in","z":"e6cc81bb1a8448d6","g":"84f321f0363d90e4","name":"MQTT Subscrib Cmd","topic":"$(BASETOPIC_CMD)","qos":"2","datatype":"auto-detect","broker":"56f17224.5234f4","nl":false,"rap":true,"rh":0,"inputs":0,"x":140,"y":600,"wires":[["7f2b930738fa68b6","a08f964816cfd9d4"]]},{"id":"8d8597b1d87ddb58","type":"debug","z":"e6cc81bb1a8448d6","g":"84f321f0363d90e4","name":"debug complete msg","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":740,"y":540,"wires":[]},{"id":"7f2b930738fa68b6","type":"function","z":"e6cc81bb1a8448d6","g":"84f321f0363d90e4","name":"MQTT Decoder and Modbus Encoder","func":"/* ----------------------------------------------------------------------------\nDescription : Recupere les Publish From MQTT et Envoi vers Modbus si Changement de Valeur \n\nTODO : A Paufiner en cas d'echec de certains test\n---------------------------------------------------------------------------- */\n\nconst bDefaultWriteIfNoLastValue=false; // Action a Faire si Ancienne Value Non Dispo (Ne Doit pas Arriver)\n\n// Example input message\n// msg.topic:ETEK_Borne_v4/cmnd/SW89_Remote_start_stop\n// msg.payload: 2\n\n//var sBaseTopic=flow.get('sBaseTopic') || \"\";\n//Lecture des Variable d'environnement du Flow\nconst sBaseTopic=env.get(\"BASETOPIC\");\t\t\t\t// ETEK_Borne_v4\nconst sStatTopicDir = env.get(\"STAT_TOPIC_DIR\");\t// stat\nconst sCmdTopicDir = env.get(\"CMD_TOPIC_DIR\");\t\t// cmnd\n\nlet sRegNumber = \"\";\n// Check if the topic matches the expected format for Holding Registers\nif (msg.topic.startsWith(sBaseTopic +\"/\" + sCmdTopicDir)) {\n // Find Register Type \n let PosTypeReg = msg.topic.indexOf(\"SW\");\n \n if (PosTypeReg > 0) {\n //Recherche \"_\" après le Type Registre\n let PosEndAddr = msg.topic.indexOf(\"_\",PosTypeReg);\n if (PosEndAddr>0) {\n sRegNumber = msg.topic.substring(PosTypeReg+2,PosEndAddr);\n //node.status({fill:\"green\",shape:\"ring\",text:\"RegNumber=[\" + sRegNumber + \"], PosTypeReg= [\" + PosTypeReg + \"], PosEndAddr= [\" + PosEndAddr + \"]\"});\n }\n } \n // GetRegisterName\n let LenFullTopic = msg.topic.length;\n let LenRegisterName= (LenFullTopic-PosTypeReg);\n let sRegisterName = msg.topic.substring(PosTypeReg,LenFullTopic);\n // Extract the value from the payload\n let value = msg.payload;\n // Convert String to Int\n let iRegNumber = parseInt(sRegNumber,10);\n\n //Compare ActualValue with aLastModbus\n\n // Load Tableau des Dernieres Valeur si il existe\n let aLastModbus=flow.get('aLastModbus') || {};\n\n let bMbWriteNeeded = false; //Est-ce qu'il faut Faire un Write ?\n\n let aLastModbusSize=Object.keys(aLastModbus).length; \n if (aLastModbusSize>0) {\n //La variable aLastModbus exist et contient au moins 1 Valeur\n\n let bLastValueExist=aLastModbus.hasOwnProperty(sRegisterName);\n if (bLastValueExist) {\n // On a déjà Stocké une Valeur, on la Compare pour savoir si il faut faire un ModbusWrite \n if (aLastModbus[sRegisterName] != value) {\n //Si la Derniere Valeur est Différente on fait un MB Write\n bMbWriteNeeded=true;\n node.status({ fill: \"green\", shape: \"dot\", text: \"Size of aLastModbus=\" + aLastModbusSize + \" ,RegName=\" + sRegisterName + \" ,Last=\" + aLastModbus[sRegisterName] + \"!= Current=\" + value + \", LastValueExist=\" + bLastValueExist});\n }\n } else {\n // On a pas d'ancienne valeur\n bMbWriteNeeded=bDefaultWriteIfNoLastValue; \n }\n } else {\n node.status({fill:\"red\",shape:\"ring\",text:\"La variable aLastModbus N'existe pas\"});\n }\n\n // Construct the message for the Modbus write node\n msg.payload = {\n value: value, // Wrap the value in an array\n 'fc': 6, // Function Code 16 (write multiple registers)\n 'unitid': flow.get('iUnitID'), // Modbus slave ID, adjust as necessary\n 'address': iRegNumber, // Register number\n 'quantity': 1, // Quantity is always 1\n 'PosTypeReg': PosTypeReg,\n 'LenFullTopic': LenFullTopic,\n 'LenRegisterName': LenRegisterName,\n 'sRegisterName': sRegisterName,\n aLastModbus: aLastModbus,\n 'aLastModbusSize': aLastModbusSize\n };\n //node.status({fill:\"green\",shape:\"ring\",text:\"RegNumber=[\" + sRegNumber + \"], Valeur = [\" + value + \"]\"});\n} else {\n // If the topic doesn't match any expected format, log an error and return null\n node.error(\"Invalid topic format. Expected format: '\" + sBaseTopic + \"/cmnd/SW<number>'\");\n return null; // Abort further processing\n}\n\n// Output the message\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":450,"y":600,"wires":[["8d8597b1d87ddb58","f8885cff676d7ee6","b45d8b1d9be983a8"]]},{"id":"b45d8b1d9be983a8","type":"modbus-flex-write","z":"e6cc81bb1a8448d6","g":"84f321f0363d90e4","name":"","showStatusActivities":false,"showErrors":false,"showWarnings":true,"server":"ecdc236fcc845883","emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":730,"y":660,"wires":[[],[]]},{"id":"a08f964816cfd9d4","type":"debug","z":"e6cc81bb1a8448d6","g":"84f321f0363d90e4","name":"Subscriber MQTT debug payload ","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload ","targetType":"msg","statusVal":"","statusType":"auto","x":440,"y":540,"wires":[]},{"id":"cc97bf6ee14d9e4e","type":"config","z":"e6cc81bb1a8448d6","g":"619fc7581fbfc0d3","name":"","properties":[{"p":"iUnitID","pt":"flow","to":"1","tot":"num"},{"p":"iCurrentPoolNumber","pt":"flow","to":"1","tot":"num"},{"p":"bEnableAutoRepeat","pt":"flow","to":"true","tot":"bool"},{"p":"iNumberOfPool","pt":"flow","to":"2","tot":"num"},{"p":"bSendSRasRetain","pt":"flow","to":"false","tot":"bool"},{"p":"bSendSWasRetain","pt":"flow","to":"true","tot":"bool"},{"p":"bEnableAutoChangePool","pt":"flow","to":"true","tot":"bool"}],"active":true,"x":110,"y":100,"wires":[]},{"id":"c96b65adde138cc0","type":"modbus-flex-getter","z":"e6cc81bb1a8448d6","g":"f649032686964af1","name":"","showStatusActivities":false,"showErrors":false,"showWarnings":true,"logIOActivities":false,"server":"ecdc236fcc845883","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":660,"y":240,"wires":[["be3b1c0048b672e5","09dd89bd0c2a40df","81caa59d31738555","3ff7506e5ad0789c"],["e1594cca2a7a0a37"]]},{"id":"04ceca3d66c81c9a","type":"function","z":"e6cc81bb1a8448d6","g":"f649032686964af1","name":"fct1 Select Pool1 or Pool2","func":"/* ----------------------------------------------------------------------------\nDescription : Defini la Requete Modbus en fonction du N° Pool Actif\n\n-Défini l'adresse de début\n-Défini la quantité de Mot a lire\n\nLe N° du Pool actif est récupéré dans la variable : iCurrentPoollNumber (flow)\n---------------------------------------------------------------------------- */\n\nlet iAddress=0; //Address Modbus\nlet iQuantity=0; //Nd de Mot a Lire\nlet iCurrentPoolNumber=flow.get('iCurrentPoolNumber'); //N° du Pool\n\nswitch (iCurrentPoolNumber) {\n case 1:\n // Pool N°1\n iAddress=86;\n iQuantity=40;\n break;\n case 2:\n // Pool N°2\n iAddress=126;\n iQuantity=41;\n break;\n default:\n //Error\n node.status({fill: \"red\", shape: \"ring\", text: \"Error Pool undedined\"});\n return null;\n};\n\nmsg.payload = { \n value: msg.payload, \n 'fc': 3, \n 'unitid': flow.get('iUnitID'), \n 'address': iAddress , \n 'quantity': iQuantity,\n 'iCurrentPoollNumber' :iCurrentPoolNumber\n};\nnode.status({\n fill: \"green\", shape: \"dot\", \n text: \"Pool N°\" + iCurrentPoolNumber + \n \" ,FC:3, unitid=\" + flow.get('iUnitID') +\n \" ,address=\" + iAddress +\n \" ,quantity=\" + iQuantity\n });\n\n//Défini le Pool actif (Utilisé par fct2) pr Savoir d'ou Vient la Reponse\nmsg.topic = \"Pool\" + iCurrentPoolNumber;\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":330,"y":240,"wires":[["0ef11b69d8d3f797","c96b65adde138cc0"]]},{"id":"0ef11b69d8d3f797","type":"debug","z":"e6cc81bb1a8448d6","g":"f649032686964af1","name":"debug fct1","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":710,"y":200,"wires":[]},{"id":"97ce823cd7b43492","type":"debug","z":"e6cc81bb1a8448d6","g":"f649032686964af1","name":"fct2 PublishModbus2MQTT","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":540,"y":400,"wires":[]},{"id":"81caa59d31738555","type":"link out","z":"e6cc81bb1a8448d6","g":"f649032686964af1","name":"link out MbRead","mode":"link","links":["d56d60035690d41c"],"x":825,"y":280,"wires":[]},{"id":"1bb49a267954922d","type":"function","z":"e6cc81bb1a8448d6","g":"f649032686964af1","name":"fct3 AutoRepeat Pool (& NextPool)","func":"/* ----------------------------------------------------------------------------\nDescription : Ative le Pool Suivant / Declenche le Cycle Suivant si AutoRepeat=true\n\n---------------------------------------------------------------------------- */\n\n//Bascule sur le Pool Suivant\nlet iCurrentPoolNumber=flow.get('iCurrentPoolNumber');\nlet iNumberOfPool=flow.get('iNumberOfPool');\n\n//Changement Automatique de Pool (False: Pour le Debuggage)\nlet bEnableAutoChangePool=flow.get('bEnableAutoChangePool');\nif (bEnableAutoChangePool) {\niCurrentPoolNumber=iCurrentPoolNumber+1;\nif (iCurrentPoolNumber>iNumberOfPool) {\n iCurrentPoolNumber=1;\n}\nflow.set('iCurrentPoolNumber',iCurrentPoolNumber);\n}\n\n//Lance le Prochain Cycle si bEnableAutoRepeat=true\nlet bEnableAutoRepeat=flow.get('bEnableAutoRepeat');\nif (bEnableAutoRepeat) {\n node.status({fill: \"green\", shape: \"dot\", text: \"AutoRepeat=ON, NextPool=\"+iCurrentPoolNumber + \",NbPool=\"+ iNumberOfPool});\n return msg;\n} else {\n //node.status({fill: \"grey\", shape: \"ring\", text: \"AutoRepeat=OFF\"});\n node.status({fill: \"grey\", shape: \"dot\", text: \"AutoRepeat=OFF, NextPool=\"+iCurrentPoolNumber + \",NbPool=\"+ iNumberOfPool});\n return null;\n}\n\n\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":260,"y":360,"wires":[["dae53049f2af714b"]]},{"id":"d56d60035690d41c","type":"link in","z":"e6cc81bb1a8448d6","g":"f649032686964af1","name":"link in fct3 AutoRepeat","links":["81caa59d31738555"],"x":65,"y":360,"wires":[["1bb49a267954922d","98c5e3067de3010c"]]},{"id":"c50b5d1d4ba4d2c1","type":"comment","z":"e6cc81bb1a8448d6","g":"84f321f0363d90e4","name":"Modbus Write OnChange","info":"A la reception d'un Publish depuis MQTT\n\nDecodage du Registre\nWrite OnChange vers Modbus","x":150,"y":540,"wires":[]},{"id":"c6b457795af6de41","type":"inject","z":"e6cc81bb1a8448d6","g":"78d43f17836ec011","name":"Set Pool N°1","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"1","payloadType":"num","x":430,"y":60,"wires":[["ea1f48037a3dcf6b"]]},{"id":"ea1f48037a3dcf6b","type":"change","z":"e6cc81bb1a8448d6","g":"78d43f17836ec011","name":"","rules":[{"t":"set","p":"iCurrentPoolNumber","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":660,"y":100,"wires":[[]]},{"id":"fdf2322b9ae1cd47","type":"inject","z":"e6cc81bb1a8448d6","g":"78d43f17836ec011","name":"Set Pool N°2","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"2","payloadType":"num","x":430,"y":100,"wires":[["ea1f48037a3dcf6b"]]},{"id":"5b232547fbfd20be","type":"comment","z":"e6cc81bb1a8448d6","g":"78d43f17836ec011","name":"Manu Set Pool Number","info":"","x":640,"y":60,"wires":[]},{"id":"d92c65a4.566478","type":"inject","z":"e6cc81bb1a8448d6","g":"b04f4bef237d1990","name":"Init","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":"2","topic":"","payload":"","payloadType":"date","x":110,"y":800,"wires":[["4e4829e3.eaeae8"]]},{"id":"4e4829e3.eaeae8","type":"file in","z":"e6cc81bb1a8448d6","g":"b04f4bef237d1990","name":"","filename":"C:\\Users\\Pierre\\.node-red/TableEKEPC2 - Pool1.csv","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"utf8","allProps":false,"x":380,"y":800,"wires":[["ec2e03fa9fb04f11","4ae7a7804e28c4ef"]]},{"id":"b3b077c4f4020a03","type":"comment","z":"e6cc81bb1a8448d6","g":"b04f4bef237d1990","name":"Read CSV File (Pool1 & 2)","info":"","x":150,"y":760,"wires":[]},{"id":"ec2e03fa9fb04f11","type":"debug","z":"e6cc81bb1a8448d6","g":"b04f4bef237d1990","name":"debug Read CSV File","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":740,"y":760,"wires":[]},{"id":"4ae7a7804e28c4ef","type":"function","z":"e6cc81bb1a8448d6","g":"b04f4bef237d1990","name":"fct0 CSV to Array","func":"/* ---------------------------------------------------------------\nDescription : Converti le Contenu du Fichier CSV dans un Array\n\nOutput 1: Permet de lancer la Lecture du Pool N°2\nOutput 2: Permet de lancer le 1er Cycle de Lecture sur le Modbus\n--------------------------------------------------------------- */\n\n// Load CSV File Result to String\nlet str = msg.payload;\n\n// Load String (with Separator \\n) to Array\nlet aListTopics = str.split(\"\\n\");\n\nmsg.payload ={value:aListTopics};\nif (msg.filename.indexOf(\"Pool1\")>0) {\n\t//Read Pool1\n\tflow.set('aListTopicsPool1',aListTopics);\n node.status({fill: \"green\", shape: \"dot\", text: \"Read OK Pool1\"});\n\t\n\treturn [msg,null];\n} else if (msg.filename.indexOf(\"Pool2\")>0) {\n\tflow.set('aListTopicsPool2',aListTopics);\n node.status({fill: \"green\", shape: \"dot\", text: \"Read OK Pool2\"});\n\treturn [null,msg];\n} else {\n\tnode.status({fill: \"red\", shape: \"dot\", text: \"Error Read\"});\n\treturn [null,null];\n}\n\n","outputs":2,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":710,"y":840,"wires":[["bff8878355ae4279","327e3bdb553df041"],["bc234ce34d75c054","bff8878355ae4279"]]},{"id":"bff8878355ae4279","type":"debug","z":"e6cc81bb1a8448d6","g":"b04f4bef237d1990","name":"debug CSV to Array","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":940,"y":800,"wires":[]},{"id":"327e3bdb553df041","type":"file in","z":"e6cc81bb1a8448d6","g":"b04f4bef237d1990","name":"","filename":"C:\\Users\\Pierre\\.node-red/TableEKEPC2 - Pool2.csv","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"utf8","allProps":false,"x":380,"y":840,"wires":[["4ae7a7804e28c4ef","ec2e03fa9fb04f11"]]},{"id":"bc234ce34d75c054","type":"link out","z":"e6cc81bb1a8448d6","g":"b04f4bef237d1990","name":"link out fct0 CSV to Array","mode":"link","links":["45a9e341dfa4ab56"],"x":865,"y":840,"wires":[]},{"id":"45a9e341dfa4ab56","type":"link in","z":"e6cc81bb1a8448d6","g":"f649032686964af1","name":"link in fct0 CSV to Array","links":["bc234ce34d75c054"],"x":385,"y":300,"wires":[["04ceca3d66c81c9a"]]},{"id":"b0041bd54123aecc","type":"comment","z":"e6cc81bb1a8448d6","g":"f649032686964af1","name":"Start Cycle after ofLoad CSVFile (On Init)","info":"","x":200,"y":300,"wires":[]},{"id":"dae53049f2af714b","type":"delay","z":"e6cc81bb1a8448d6","g":"f649032686964af1","name":"","pauseType":"delay","timeout":"1000","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":500,"y":340,"wires":[["04ceca3d66c81c9a"]]},{"id":"e99afac59d8e06af","type":"function","z":"e6cc81bb1a8448d6","d":true,"g":"3232febd0ceac99d","name":"fct Load Array of Topic (Tst)","func":"//Input from Modbus Flex Getter Ouput1\n\nlet aCurrentListOfTopic;\nlet sThisPool = msg.topic;\nswitch (sThisPool) {\n\tcase 'Pool1':\n\t\taCurrentListOfTopic=flow.get('aListTopicsPool1');\n\tbreak;\n\tcase 'Pool2':\n\t\taCurrentListOfTopic=flow.get('aListTopicsPool2');\n\tbreak;\n}\n\nmsg.payload = {\n value: msg.payload, // Wrap the value in an array\n aCurrentListOfTopic: aCurrentListOfTopic\n}\n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":320,"y":1320,"wires":[["517233ca62784742"]]},{"id":"517233ca62784742","type":"debug","z":"e6cc81bb1a8448d6","d":true,"g":"3232febd0ceac99d","name":"debug fct Load Array of Topic","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":350,"y":1360,"wires":[]},{"id":"d3d99b7769fe85b9","type":"comment","z":"e6cc81bb1a8448d6","g":"b04f4bef237d1990","name":"Les Fichiers CSV doivent être au format Linux (LF)","info":"**Le format Windows CR LF n'est pas géré**","x":370,"y":920,"wires":[],"icon":"node-red/alert.svg"},{"id":"56f17224.5234f4","type":"mqtt-broker","name":"MQTT Pierre 192.168.20.5","broker":"192.168.20.5","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"autoUnsubscribe":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""},{"id":"ecdc236fcc845883","type":"modbus-client","name":"MB Slave P17","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"127.0.0.1","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"0x3A","unit_id":"1","commandDelay":"1","clientTimeout":"1000","reconnectOnTimeout":true,"reconnectTimeout":"2000","parallelUnitIdsAllowed":true,"showErrors":false,"showWarnings":true,"showLogs":true}]
KNX Partner Base / Avancé
Ma boite de MP est pleine, merci de créer un post si vous avez une question, cela profitera a tout le monde.
Je n'arrive pas à installer les nodes : Flows stopped due to missing node types.
ioBroker out
ioBroker in
config
Faut-il passer par npm?? Je ne les trouve pas dans la palette pour les installer.
Sinon comme toi je cherche à rester simple avant d'aller plus loin.
Pour l'instant, je reste bloqué pour me connecter en Modbus à mon Dongle des onduleurs Huawei.
Je cherche à simplifier la connexion maximum en pouvoir interroger les adresses des enregistrements modbus défini par Huawei.
C'est un conteneur LXC avec uniquement Node-red. Comme j'étais planté, J'ai restauré le dernière sauvegarde fiable et là, le CT à disparu de proxmox. Jamais eu cela!!
Quand tu dis planté, c'est Node-RED qui était planté je supose ?
Pas le LXC ?
Si tu crées un Flow et qu'il provoque une erreur lors du déploiement, NodeRed va planter en permanence.
Dans ce cas il faut le lancer en mode secours : "SAFE MODE"
Node-RED redevient accessible mais les noeuds ne sont pas déployé.
Auparavant il vaut mieux consulté les log pour voir d'ou vient lerreur, pour ensuite corriger ou supprimer le truc qui bloque.
Ensuite on relancer Node RED en mode normal.
KNX Partner Base / Avancé
Ma boite de MP est pleine, merci de créer un post si vous avez une question, cela profitera a tout le monde.
Malheureusement c'est le conteneur qui après restauration (qui s'est mise en erreur en cours de route) de la dernière version stable a planté, et a disparu de de mes conteneurs disponibles.
Heureusement pas trop de chose dedans juste des versions de test de modbus et de KNX Ultimate