Modifying json outputs in Node-RED flows

Dear expert and more experienced coders,

I am trying to edit the MQTT-out of a new set of flows (set2) to basically follow the MQTT-out nodes of an existing set of flows (set1) so that the data from set2 could be uploaded to the same platform with a similar json string format.

In set1, the sensor data are extracted via OPC-UA servers, get converted from Boolean to int (1 or 0) and then put into a "msg.payload" json string as follows, for example:

msg.payload = {"id" : "4", "version": "1.0", "params": [{"deviceKey": "aBCdeFgHi", "measurepoints": {"sensor_object_present": msg.payload }, "time": Time}],"method": "integration.measurepoint.post"}

In set2, the different types of data are extracted individually from a SICK device (TDC-E) via http://hwmanager:8000/api/v1/device-info/AvailableMemory and then sent to Node-RED dashboard after formatting as follows, for example:

var AvailableMemory = msg.payload;
msg.payload = AvailableMemory;

//Write NODE status
node.status({ fill: "green", shape: "ring", text: "AvailableMemory: " + AvailableMemory + ""});

//Return message
return msg;

There is also an overall device-info node which extract all the sensor data, format them as follows and then send MQTT message to 192.168.0.100:9000 (the TDC-E router) or 194.152.206.247:1883 (according to the Node-RED example for TDC-E document).

// create new date object. (includes current time)
var now = new Date();

// convert current time to ISO format
//now.toISOString()

// Basic topic for TDC-E meta data
msg.topic = "VD0B8050E8D05CEA581E/S/";

if (msg.payload !== null && msg.payload !== '' ) {
    return [{ "payload": now.toISOString() + "|" + msg.payload.DeviceName + "|h|7",
              "topic":msg.topic+"TDC_E_DeviceName"
            },
            { "payload": now.toISOString() + "|" + msg.payload.ProductNumber + "|h|7",
              "topic":msg.topic+"TDC_E_ProductNumber"
            },
            { "payload": now.toISOString() + "|" + msg.payload.SerialNumber + "|h|7",
              "topic":msg.topic+"TDC_E_SerialNumber"
            }, 
            { "payload": now.toISOString() + "|" + msg.payload.IMEI + "|h|7",
              "topic":msg.topic+"TDC_E_IMEI"
            },
            { "payload": now.toISOString() + "|" + msg.payload.SystemVersion + "|h|7",
              "topic":msg.topic+"TDC_E_SystemVersion"
            }, 
            { "payload": now.toISOString() + "|" + msg.payload.AvailableMemory + "|h|7",
              "topic":msg.topic+"TDC_E_AvailableMemory"
            },
            { "payload": now.toISOString() + "|" + msg.payload.Cpu + "|h|7",
              "topic":msg.topic+"TDC_E_Cpu"
            },
            { "payload": now.toISOString() + "|" + msg.payload.EnvironmentTemperature + "|h|7",
              "topic":msg.topic+"TDC_E_ET"
            }]; 
    
} else {
    // ERROR
    // handle if variable could not be received
    node.warn("Error, receiving picoStratus value.");
}

A few questions:

  1. What could be the purpose of this Send MQTT Message node?
  2. How do I create a json string similar to that in set1 while keeping the existing json string? (Note: While the variable name is like "AvailableMemory", the same variable in the MQTT-out string is like "TDC_E_AvailableMemory".)

Many thanks for your help in advance.
A beginner Node-RED coder
Jo Tan

Admin edit - change block quotes to code blocks

Hi Jo, welcome to the forum. Please use the CODE button not the QUOTE button for code

1 Like

You dont. You create a JavaScript object & when it is transmitted to MQTT it is converted to JSON automatically.

e.g. creating JSON - ugly mess & hard to understand...

msg.payload = "{ \"value\": \"" + msg.payload + "\" }"; 

e.g. creating the save value as a JS Object...

msg.payload = { 
  "value":  msg.payload
}; 

So if you want to format data set2 into the same format as data set1 then something like...

msg.payload = {
  "id" : "4",  //<<set this to the value from your set2 data
  "version": "1.0",  //<<set this to the value from your set2 data
  "params": [
    {
      "deviceKey": "aBCdeFgHi",  //<<set this to the value from your set2 data
      "measurepoints": {
        "sensor_object_present": msg.payload  //<< set this to the value from your set2 data
      }, 
      "time":  Time 
    }
  ],
  "method": "integration.measurepoint.post" //<<set this to the value from your set2 data
}
return msg;

Thank you for the welcome. Noted about the CODE button.

Thank you, Steve, for your replies. Noted about your point wrt the messiness of json and of a Javascript object being converted to json once transmitted to MQTT.

Perhaps I didn't phrase my questions clearly enough.

I am confused by how the msg.payload in set2 concatenates now.toISOString(), a "|", variable name (e.g. AvailableMemory, "|h|7", "topic":msg.topic+"TDC_E_AvailableMemory".

And uncertain as to how to string it as
msg.payload = {"id" : "4", "version": "1.0", "params": [{"deviceKey": "aBCdeFgHi", "measurepoints": {"TDC_E_AvailableMemory": msg.payload }, "time": Time}],"method": "integration.measurepoint.post"}

A sticking point is that there are two variables used in set2: AvailableMemory and TDC_E_AvailableMemory (the one that I need for MQTT-out),

Another sticking point is that set2 seems to extract the device info twice: first individually and then collectively. Hmm... Perhaps the individual extraction is merely to output to the dashboard, and the collective extraction is for MQTT-out to 194.152.206.247:1833 (which seems to be an Aedes broker).

One more sticking point: set2 uses payload for each measurement point while set1 uses params for the device key and all the measurement points.

So if I want to convert set2 to set1 data structure, could I simply ignore the individual extractions and just modify the MQTT-out node to the online platform that we are using for set1? Or add a new MQTT-out node? Or...

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.