node Red -> MQTT

  • bloody27370
  • Auteur du sujet
  • Hors Ligne
  • Nouveau membre
  • Nouveau membre
Plus d'informations
16 Aoû 2023 20:58 #1 par bloody27370
node Red -> MQTT a été créé par bloody27370
Bonjour,

Je cherche à récupérer toutes les secondes certaines valeurs du M'Sun PV pour les utiliser dans ma domotique. J'ai eu l'idée peut être un peu bête d'utiliser Node RED pour convertir le XML status en MQTT. Pour qu'ensuite je puisse utiliser les valeurs dans ma domotique sans charger le processeur de la domotique à gérer les scénario d'analyse du XML.

Ma connaissance de Node Red est très limité car je le découvre aujourd'hui. Après plusieurs heures à chercher en m'aidant un peu de chatGPT je sèche. Et MQTT je l'utilise depuis quelques mois mais j'essaye d'apprendre encore son fonctionnement.
Je vous joint une capture de mon Node pour comprendre.

1) un timestamp à la seconde pour l'actualisation en continue => fonctionnel
2) http request avec le lien "http://mon-ip/status.xml" => fonctionnel
3) un node xml pour convertir le XML en JSON. Cela me donne le JSON suivant :
{
  "xml": {
    "rtcc": [
      "22:41:58 ME"
    ],
    "paramSys": [
      "22:41:58;16/08/2023;On;01:00;0,0;MS_PV2_2;5.0.1;0000220;102e;102c;00:00;00:00"
    ],
    "inAns": [
      "493,0;-3,3; 0; 0;228,2;0,0;0,0;0,0; 0; 0; 0; 0; 0; 0; 0; 0;"
    ],
    "survMm": [
      "0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;"
    ],
    "cmdPos": [
      "a;a;0;0;0;0;0;1;"
    ],
    "outStat": [
      "0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;"
    ],
    "cptVals": [
      "24c67;fffff15d;fffdeded;fe80e657;0;0;0;0;"
    ],
    "chOutVal": [
      "0;0;0;ff;:0,0;0,0;0,0;0,0;"
    ]
  }
}

4) Ensuite et c'est là que je pense être ma première erreur, je voulais le convertir, j'ai essayé avec ChatGPT, mais rien n'a l'air de fonctionner. Une de ses propositions est :
var inAnsData = msg.payload.xml.inAns[0];
var cptValsData = msg.payload.xml.cptVals[0];
var outStatData = msg.payload.xml.outStat[0];
var cmdPosData = msg.payload.xml.cmdPos[0];

// Traitement des données de inAns
var inAnsValues = inAnsData.split(';');
// ... Traitez les données de inAns comme vous le faisiez dans la fonction PHP

// Traitement des données de cptVals
var cptValsValues = cptValsData.split(';');
// ... Traitez les données de cptVals comme vous le faisiez dans la fonction PHP

// Traitement des données de outStat
var outStatValues = outStatData.split(';');
// ... Traitez les données de outStat comme vous le faisiez dans la fonction PHP

// Traitement des données de cmdPos
var cmdPosValues = cmdPosData.split(';');
// ... Traitez les données de cmdPos comme vous le faisiez dans la fonction PHP

Pour finir j'ai le MQTT Out, j'ai bien renseigné mon brocker et il s'y connecte mais je ne sais pas quoi mettre en payload

Si vous avez d'autres solution je suis preneur ...

En l'occurence je n'ai que 5 infos qu'il m'intéresse de récupérer en gras ci-dessous :

"inAns": [
"493,0;-3,3; 0; 0;228,2;0,0;0,0;0,0; 0; 0; 0; 0; 0; 0; 0; 0;"

cptVals": [
"24c67;fffff15d;fffdeded;fe80e657;0;0;0;0;"
Pièces jointes :
Les utilisateur(s) suivant ont remercié: ilco

Connexion ou Créer un compte pour participer à la conversation.

  • bloody27370
  • Auteur du sujet
  • Hors Ligne
  • Nouveau membre
  • Nouveau membre
Plus d'informations
17 Aoû 2023 09:01 #2 par bloody27370
Réponse de bloody27370 sur le sujet node Red -> MQTT
Je me réponds à moi même, après avoir été guidé sur le forum Jeedom.

Voici la solution que m'a donné chatGPT et qui fonctionne pour récupérer les deux premières valeurs de InAns qui m'intéresse.
// Récupérer le message JSON d'entrée
var inputJSON = msg.payload;

// Extraire l'objet "inAns"
var inAnsArray = inputJSON.xml.inAns;

// Join des éléments de l'array et remplacement des virgules par des points
var inAnsString = inAnsArray.join('').replace(/,/g, '.');

// Séparer les valeurs par des points-virgules et prendre les 2 premières
var numericValues = inAnsString.split(';').slice(0, 2).map(item => parseFloat(item));

// Créer l'objet de sortie avec les valeurs numériques
var outputObj = { "inAns": numericValues };

// Envoyer l'objet de sortie
msg.payload = outputObj;
return msg;

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
11 Fév 2024 12:55 - 11 Fév 2024 13:53 #3 par ilco
Réponse de ilco sur le sujet node Red -> MQTT
Salut,

J’ai un peu complété le code avec l’envoi de toutes les infos sur un topic msunpv/data. J’ai converti la valeur des compteurs avec le fameux complément a 2 pour avoir les nombres negatifs!
[{"id":"5c1f49a2f0842fa0","type":"function","z":"999280016ff24882","name":"function 1","func":"// Récupérer le message JSON d'entrée\nvar inputJSON = msg.payload;\n\n// Extraire l'objet \"inAns\"\n\nvar inRTCC = inputJSON.xml.rtcc;\nvar inParamSys = inputJSON.xml.paramSys;\nvar inAnsArray = inputJSON.xml.inAns;\nvar inSurvMm = inputJSON.xml.survMm;\nvar inCmdPos = inputJSON.xml.cmdPos;\nvar inOutStat = inputJSON.xml.outStat;\nvar inCptVals = inputJSON.xml.cptVals;\nvar inChOutVal = inputJSON.xml.chOutVal;\n\n\nvar RTCCStringValues = inRTCC.join('').split(' ');\nvar ParamSysStringValues = inParamSys.join('').split(';');\n\n// Join des éléments de l'array et remplacement des virgules par des points\nvar ansStringValues = inAnsArray.join('').replace(/,/g, '.').replace(/\\;$/,'');\n// Séparer les valeurs par des points-virgules et prendre les 2 premières\nvar ansNumericValues = ansStringValues.split(';').map(item => parseFloat(item));\n\nvar SurvMmStringValues = inSurvMm.join('').replace(/\\;$/, '').split(';').map(item => parseInt(item));\nvar CmdPosStringValues = inCmdPos.join('').replace(/\\;$/, '').split(';').map(item => parseInt(item));\nvar OutStatStringValues = inOutStat.join('').replace(/\\;$/, '').split(';').map(item => parseInt(item));\nvar CptValsNumericValues = inCptVals.join('').replace(/\\;$/, '').split(';').map(item => hexToInt(item));\nvar ChOutValStringValues = inChOutVal.join('').replace(/\\;$/, '').split(';');\n\n// Créer l'objet de sortie avec les valeurs numériques\nvar outputObj = {\"RTCC\": RTCCStringValues, \"ParamSys\": ParamSysStringValues, \"inAns\": ansNumericValues, \"SurvMm\": SurvMmStringValues, \"CmdPos\": CmdPosStringValues, \"OutStat\": OutStatStringValues, \"CptVals\": CptValsNumericValues, \"ChOutVal\": ChOutValStringValues};\n\n// Envoyer l'objet de sortie\nmsg.payload = outputObj;\nreturn msg;\n\nfunction hexToInt(hex) {\n    if (hex.length % 2 != 0) {\n        hex = \"0\" + hex;\n    }\n    var num = parseInt(hex, 16);\n    var maxVal = Math.pow(2, hex.length / 2 * 8);\n    if (num > maxVal / 2 - 1) {\n        num = num - maxVal\n    }\n    return num;\n}","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":700,"y":500,"wires":[["7d266cee5180b2e6","e1cf2e08bb917aa2"]]}]

Il me manque encore la partie de « surveille un topic msunpv/data pour envoyer les commandes POST » et modifier le routeur. Je ne sais pas trop quelle strategie adopter…
Dernière édition: 11 Fév 2024 13:53 par ilco.

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
10 Mar 2024 14:25 #4 par ilco
Réponse de ilco sur le sujet node Red -> MQTT
Et voila enfin avec la commande qui fonctionne !! Si je publie sur topic msunpv/cmd/cmd1 un 2 ca met le ballon en auto en envoyant la bonne commande sur index.xml, si c'est 1 un en manu, et 0 ben OFF :)
[{"id":"999280016ff24882","type":"tab","label":"MSunPV","disabled":false,"info":"","env":[]},{"id":"03b797d2b3224219","type":"inject","z":"999280016ff24882","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"3","crontab":"","once":true,"onceDelay":"90","topic":"","payload":"","payloadType":"date","x":150,"y":220,"wires":[["2709667b90776444"]]},{"id":"2709667b90776444","type":"http request","z":"999280016ff24882","name":"","method":"GET","ret":"txt","paytoqs":"ignore","url":"http://192.168.1.139/status.xml","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":310,"y":220,"wires":[["b6f1891b2e985037"]]},{"id":"b6f1891b2e985037","type":"xml","z":"999280016ff24882","name":"","property":"payload","attr":"","chr":"","x":450,"y":220,"wires":[["5c1f49a2f0842fa0","90c320ffa0d9e270"]]},{"id":"7d266cee5180b2e6","type":"debug","z":"999280016ff24882","name":"debug 11","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":780,"y":220,"wires":[]},{"id":"5c1f49a2f0842fa0","type":"function","z":"999280016ff24882","name":"function 1","func":"// Récupérer le message JSON d'entrée\nvar inputJSON = msg.payload;\n\n// Extraire l'objet \"inAns\"\n\nvar inRTCC = inputJSON.xml.rtcc;\nvar inParamSys = inputJSON.xml.paramSys;\nvar inAnsArray = inputJSON.xml.inAns;\nvar inSurvMm = inputJSON.xml.survMm;\nvar inCmdPos = inputJSON.xml.cmdPos;\nvar inOutStat = inputJSON.xml.outStat;\nvar inCptVals = inputJSON.xml.cptVals;\nvar inChOutVal = inputJSON.xml.chOutVal;\n\n\nvar RTCCStringValues = inRTCC.join('').split(' ');\nvar ParamSysStringValues = inParamSys.join('').split(';');\n\n// Join des éléments de l'array et remplacement des virgules par des points\nvar ansStringValues = inAnsArray.join('').replace(/,/g, '.').replace(/\\;$/,'');\n// Séparer les valeurs par des points-virgules et prendre les 2 premières\nvar ansNumericValues = ansStringValues.split(';').map(item => parseFloat(item));\n\nvar SurvMmStringValues = inSurvMm.join('').replace(/\\;$/, '').split(';').map(item => parseInt(item));\nvar CmdPosNumericValues = inCmdPos.join('').replace(/\\;$/, '').split(';').map(item => hexToInt(item));\nvar OutStatStringValues = inOutStat.join('').replace(/\\;$/, '').split(';').map(item => parseInt(item));\nvar CptValsNumericValues = inCptVals.join('').replace(/\\;$/, '').split(';').map(item => hexToInt(item));\nvar ChOutValStringValues = inChOutVal.join('').replace(/\\;$/, '').split(';');\n\nlet cmd1;\nlet cmd2;\n\nswitch (CmdPosNumericValues[0]) {\n    case 0:\n        cmd1 = 0; //off\n        cmd2 = 0;\n        break;\n    case 1:\n        cmd1 = 1; //manu\n        cmd2 = 0;\n        break;\n    case 2:\n        cmd1 = 2; //auto\n        cmd2 = 0;\n        break;\n    case 4:\n        cmd1 = 0;\n        cmd2 = 1;\n        break;\n    case 5:\n        cmd1 = 1;\n        cmd2 = 1;\n        break;\n    case 6:\n        cmd1 = 2;\n        cmd2 = 1;\n        break;\n    case 8:\n        cmd1 = 0;\n        cmd2 = 2;\n        break;\n    case 9:\n        cmd1 = 1;\n        cmd2 = 2;\n        break;\n    case 10:\n        cmd1 = 2;\n        cmd2 = 2;\n        break;\n    default:\n        cmd1 = 0; //off\n        cmd2 = 0;\n        console.log(`Error`);\n}\n\nvar CmdPosValues = [cmd1, cmd2, CmdPosNumericValues[7]];\n\n// Créer l'objet de sortie avec les valeurs numériques\nvar outputObj = { \"RTCC\": RTCCStringValues, \"ParamSys\": ParamSysStringValues, \"inAns\": ansNumericValues, \"SurvMm\": SurvMmStringValues, \"CmdPos\": CmdPosValues, \"OutStat\": OutStatStringValues, \"CptVals\": CptValsNumericValues, \"ChOutVal\": ChOutValStringValues };\n\n\n// Envoyer l'objet de sortie\nmsg.payload = outputObj;\nreturn msg;\n\nfunction hexToInt(hex) {\n    if (hex.length % 2 != 0) {\n        hex = \"0\" + hex;\n    }\n    var num = parseInt(hex, 16);\n    var maxVal = Math.pow(2, hex.length / 2 * 8);\n    if (num > maxVal / 2 - 1) {\n        num = num - maxVal\n    }\n    return num;\n}","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":620,"y":220,"wires":[["7d266cee5180b2e6","e1cf2e08bb917aa2","2ddc9ea8d81ba2a9"]]},{"id":"90c320ffa0d9e270","type":"debug","z":"999280016ff24882","name":"debug 12","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":620,"y":160,"wires":[]},{"id":"9c980b5856077a0e","type":"mqtt out","z":"999280016ff24882","name":"","topic":"","qos":"0","retain":"false","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"c6b88f19.cc3fb","x":990,"y":280,"wires":[]},{"id":"362f878fc7372f25","type":"mqtt in","z":"999280016ff24882","name":"","topic":"msunpv/cmd/#","qos":"2","datatype":"json","broker":"c6b88f19.cc3fb","nl":false,"rap":true,"rh":0,"inputs":0,"x":120,"y":580,"wires":[["0b881a8881ba03fa"]]},{"id":"e1cf2e08bb917aa2","type":"change","z":"999280016ff24882","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"msunpv/data","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":810,"y":280,"wires":[["9c980b5856077a0e"]]},{"id":"c1e7b1f4288a8051","type":"debug","z":"999280016ff24882","name":"debug 13","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1000,"y":580,"wires":[]},{"id":"95ece56e027bbfa5","type":"http request","z":"999280016ff24882","name":"","method":"POST","ret":"txt","paytoqs":"ignore","url":"http://192.168.1.139/index.xml","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":670,"y":580,"wires":[["5f580393ab3426ff"]]},{"id":"13737083e0019043","type":"function","z":"999280016ff24882","name":"SETTING REQUEST","func":"msg.headers = {};\nmsg.headers = {\n    'Content-Type': 'application/x-www-form-urlencoded'\n};\n\nvar cmd1 = newOrOld(msg.payload['msunpv/cmd/cmd1'], msg.payload.current[0]);\nvar cmd2 = newOrOld(msg.payload['msunpv/cmd/cmd2'], msg.payload.current[1]);\n\nvar cmd;\n\nswitch (cmd1 + 4 * cmd2) {\n    case 1: case 2: case 4: case 5: case 6: case 8: case 9: case 10: //send 10 and not a (even while receiving a)\n        cmd = cmd1 + 4 * cmd2;\n        break;\n    default:\n        cmd = 2;\n}\n\nlet test;\n\nswitch (newOrOld(msg.payload['msunpv/cmd/test'], msg.payload.current[2])) {\n    case 1: case 2: case 4: case 8:\n        test = newOrOld(msg.payload['msunpv/cmd/test'], msg.payload.current[2]);\n        break;\n    default:\n        test = 2;\n}\n\nmsg.payload = 'parS=' + cmd + ';0;0;0;0;0;0;' + test + ';';\n\nreturn msg;\n\nfunction newOrOld(nnew, old) {\n    if (nnew === undefined) {\n        return old;\n    }\n    return nnew;\n}","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":480,"y":580,"wires":[["95ece56e027bbfa5","0cfee7360b6fdae2"]]},{"id":"2ddc9ea8d81ba2a9","type":"function","z":"999280016ff24882","name":"extract current cmd","func":"msg.payload = msg.payload.CmdPos;\nmsg.topic = \"current\";\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":190,"y":440,"wires":[["0b881a8881ba03fa"]]},{"id":"0b881a8881ba03fa","type":"join","z":"999280016ff24882","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":300,"y":580,"wires":[["13737083e0019043","d18ecd3c0e10bea4"]]},{"id":"5f580393ab3426ff","type":"xml","z":"999280016ff24882","name":"","property":"payload","attr":"","chr":"","x":850,"y":580,"wires":[["c1e7b1f4288a8051"]]},{"id":"0cfee7360b6fdae2","type":"debug","z":"999280016ff24882","name":"debug 14","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":700,"y":440,"wires":[]},{"id":"d18ecd3c0e10bea4","type":"debug","z":"999280016ff24882","name":"debug 15","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":460,"y":440,"wires":[]},{"id":"c6b88f19.cc3fb","type":"mqtt-broker","name":"Mosquitto","broker":"192.168.1.27","port":"1883","clientid":"16","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"autoUnsubscribe":true,"birthTopic":"Node-red-router","birthQos":"2","birthRetain":"false","birthPayload":"1","birthMsg":{},"closeTopic":"Node-red-router","closeQos":"2","closeRetain":"false","closePayload":"0","closeMsg":{},"willTopic":"Node-red-router","willQos":"2","willPayload":"0","willMsg":{},"userProps":"","sessionExpiry":""}]

Connexion ou Créer un compte pour participer à la conversation.

Propulsé par Kunena