Communication Node Red et Jmqtt

Bonjour,

Je cherche à récupérer toutes les secondes certaines valeurs de mon routeur 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 Jeedom sans charger le processeur à 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;"
    ]
  }
}

A cette étape si je l’envoi en MQTT cela envoi bien un payload mais dans JMQTT cela me génère des objets mais par exemple pour InAns je vais avoir toutes les valeurs entre guillemet et non pas une valeur par ;

Je veux donc avant d’envoyer le Payload essayer de le remettre en forme, et c’est là que malgré ChatGPT je n’arrive pas à remettre en forme. Il me propose d’ajouter une fonction avec un bout de code mais cela ne fonctionne pas.

Exemple de code proposé :

[{
    "id": "48306d0f.6ed00c",
    "type": "function",
    "z": "ec8a665f.07e6d8",
    "name": "Transform JSON",
    "func": "const inputJSON = msg.payload;\nconst inAns = inputJSON.xml.inAns[0].split(';');\nconst result = {\n    \"xml\": {}\n};\n\ninAns.forEach((value, index) => {\n    result.xml[`inAns${index + 1}`] = [value.trim()];\n});\n\nmsg.payload = result;\nreturn msg;",
    "outputs": 1,
    "noerr": 0,
    "initialize": "",
    "finalize": "",
    "x": 430,
    "y": 240,
    "wires": [
        ["c2513cf4.fbaa18"]
    ]
}, {
    "id": "c2513cf4.fbaa18",
    "type": "debug",
    "z": "ec8a665f.07e6d8",
    "name": "",
    "active": true,
    "tosidebar": true,
    "console": false,
    "tostatus": false,
    "complete": "false",
    "statusVal": "",
    "statusType": "auto",
    "x": 770,
    "y": 240,
    "wires": []
}, {
    "id": "ab1dcb2c.9cfed8",
    "type": "inject",
    "z": "ec8a665f.07e6d8",
    "name": "Sample JSON",
    "props": [{
        "p": "payload"
    }],
    "repeat": "",
    "crontab": "",
    "once": false,
    "onceDelay": 0.1,
    "topic": "",
    "payload": {
        "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;"]
        }
    },
    "op": "payload",
    "x": 240,
    "y": 240,
    "wires": [
        ["48306d0f.6ed00c"]
    ]
}]

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; »

Et dernière difficulté pour les données dans cptVals je dois les traduire de l’hexadecimal vers le décimal

Salut

Dans la partie array de ton json, les valeurs devraient être séparée par des , et non des ;

Cela doit géner le traitement ultérieur. A voir si tu peux avoir ses valeurs selon le format US pour éviter ce type de souci.

Antoine

Non malheureusement je ne peux pas toucher au format du XML.
chatGPT me propose ce code pour remplacer les ; par des , (et avant remplacer les , par des . dans mes valeurs numériques)

// Fonction récursive pour parcourir et modifier les valeurs du JSON
function replaceCommasAndSemicolons(obj) {
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            var value = obj[key];
            
            if (Array.isArray(value)) {
                obj[key] = value.map(item => {
                    if (typeof item === 'string') {
                        return item.replace(/,/g, '.').replace(/;/g, ',');
                    } else if (typeof item === 'object') {
                        return replaceCommasAndSemicolons(item);
                    }
                    return item;
                });
            } else if (typeof value === 'string') {
                obj[key] = value.replace(/,/g, '.').replace(/;/g, ',');
            } else if (typeof value === 'object') {
                obj[key] = replaceCommasAndSemicolons(value);
            }
        }
    }
    return obj;
}

// Récupérer le message JSON d'entrée
var inputJSON = msg.payload;

// Appeler la fonction récursive pour modifier le JSON
var modifiedJSON = replaceCommasAndSemicolons(inputJSON);

// Envoyer le JSON modifié
msg.payload = modifiedJSON;
return msg;

Cependant cela n’est pas mieux interpréter par jmqtt j’ai l’impression. Voici une capture d’écran :

Et maintenant enleve les " en debut et fin de liste. Ce qui est entre " est considéré comme un string. Sans, tu auras un array de valeur numérique.
Si tu as des valeurs string, elles doivent etre entre des ".

Antoine

Hello all,

Il y a pleins de très bonnes suggestions dans ce fil !
Par contre, si comme tu le dis @Bloody76320, tu n’as pas besoin de toutes les informations et que la fréquence de publication est très importante, je te recommande de filtrer les messages qui t’intéressent directement dans nodered et de les publier dans des topics différents afin de minimiser le temps de traitement côté Jeedom.

Bad

Suite à tes très bonne idées, j’ai demandé à ChatGpt de faire cela. Alors après une heure de recherche, cela ne fonctionnait pas. J’ai donc fais comme le propose @Bad je me suis focus sur les 2 valeurs qui sont pour moi le plus important c’est les deux premiers InAns (Puissance net instantané, et Puissance de prod des panneaux solaires".

ChatGpt m’a proposé le code suivant

// 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;

Cela fonctionne, j’ai bien le JSON en arrivant sur JMQTT

1 « J'aime »

Merci pour votre aide. ChatGPT est top, mais sans vos infos, j’aurais jamais pu le guider vers la réponse.

1 « J'aime »

Ce sujet a été automatiquement fermé après 24 heures suivant le dernier commentaire. Aucune réponse n’est permise dorénavant.