Adding Certain data tags to a data received by a sensor

Hello Everyone,

I am receiving a data from a sensor with a certain data tags {Device}. {Events} but I would like to change this data tags to match this format: {line}.{unit/system/function}.{device/function}[.{device/function}[...]].property

should I add a certain node on node-RED that could make this possible or is there another possible solution?

type or paste code here

It is a little unclear what you expect the output to be, but I guess you want to unflatten the object named properties into nested properties.

In a function node, try feeding your message through this.

msg.payload = unflatten(msg.payload)
return msg

function unflatten(data) {
  const result = {}
  for (let i in data) {
    const keys = i.split('.')
    keys.reduce(function(r, e, j) {
      return r[e] || (r[e] = isNaN(Number(keys[j + 1])) ? (keys.length - 1 == j ? data[i] : {}) : [])
    }, result)
  }
  return result
}

Note: Untested

I think this is context of this topic

Perhaps OP should explain what he wants to do with the data (purpose) and why it needs to be in a non-standard format.

This data should be sent to a cloud. the cloud can receive the data in a certain format otherwise, it will not be stored that's why I want to add a certain data tags

No, the problem is not with flatten or unflatten data but I have the data in certain data tags but I would like to add other data tags to make this data receivable on the cloud, which is using a certain data tags.

I want to the receivable data to have this format {line}.{unit/system/function}.{device/function}[.{device/function}[...]].property

start with line number, the function, then unit and so on, which means I would like to add at least five data tags.

But for the current receivable data, I can only receive the device name and the event, which are two data tags only.

For the other data tags should I add a separable node to add this information automatically from the receivable sensor data? or what exactly should I do here that's my question

You have shown us what the data coming in looks like. Now, instead of using words to describe what you want, show us exactly what you want to get out when that data comes in. Then perhaps we will understand.

Okay the incoming data now are
TempHumi.Range: 0

I want it to be like this

Line_1.Celsius.Temp.TempHumi.Range: 0
which comply with this format:
{line}.{unit/system/function}.{device/function}[.{device/function}[...]].property

Assuming that is in an variable myVar, then to get what you want in msg.payload all you need is
msg.payload = {Line_1: {Celsius: {Temp: myVar}}}

This Iis more clear now the next step is to include this formatting syntax in a fonction node that will do it automatically.
This function will receive the object.
For each key, it will get the value in a variable and the key in another variable.
Then you have to write the rule that will add the additional keys depending of the exiting key to match the syntax of your cloud solution.
You can then bend each reforfomated information as a separate message using a node.send() function inside the loop.
If needed I can share later some function code example.
For each msg you send by the node,send() you have perhaps to define the msg.topic depending on the node you use to publish to the cloud.
This can be done outside of the function node with a change node or directly in the function node if the topic also depends on some conditions.
Another good practice can be to add a delay node that could limit the rate of message send to the cloud server.
I have personally no experience in this part, I only save my data to an influxDB staying locally on my machine..

Pierre RUWET

I think it is worth explaining why we had a lot of difficulty understanding what you wanted. You asked about adding tags to data, tags is not a work that has meaning in javascript but I assumed that you meant adding keys to an object. If fact what you want to do is put the input object inside another object (Temp) inside another (Celcius) inside another (Line 1) in yet another object.

It is not clear from your last post whether you need further help.

Thank you so much for your answer. If you have an example it would be nice to share it because the merging process between the data received directly from sensor and node-function that adding this data tags automatically is not clear, I have tried to do something like this, but it did not work,

I need further help about how to merge and automate the process. I am receiving the data directly from the sensor with a certain data tags, but I want to add more data tags and convert them as I have mentioned earlier in this post. therefore, the problem is related to how to make this function and how to automate the process.

I can only repeat what I said before. Show us the input data and exactly what you want to get out.

Why are you still calling them tags? I explained earlier that you are talking about embedding data in objects. Unless the requirement has changed.

I want to declare something thing. The incoming data are coming directly from a sensor in the following format

TempHumi.Range: 0
TempHumi.Status: 0
TempHumi.Event: 0
TempHumi.SenVal: 32875
Accelerometer.X-Axis.SenEvent: 0
Accelerometer.X-Axis.OAVelocity: 44
Accelerometer.X-Axis.Peakmg: 7
Accelerometer.X-Axis.RMSmg: 5
Accelerometer.Y-Axis.SenEvent: 0
Accelerometer.Y-Axis.OAVelocity: 19
Accelerometer.Y-Axis.Peakmg: 5
Accelerometer.Y-Axis.RMSmg: 4
Accelerometer.Z-Axis.SenEvent: 0
Accelerometer.Z-Axis.OAVelocity: 15
Accelerometer.Z-Axis.Peakmg: 9
Accelerometer.Z-Axis.RMSmg: 7
Accelerometer.LogIndex: 0
Accelerometer.Timestamp: 1552546760
Device.Events: 0
Device.PowerSrc: 1
Device.BatteryVolt: 0
Device.Time: 1552546760

this is the message payload shows, calling them data tags might not be wrong but I want to embed, whatever you call it, those other things like the line number, device name and more.

what I want to get

"Line_1.HA20.Temperature.Temperature.TempHumi.Range": 0,
"Line_1.HA20.Temperature.Temperature.TempHumi.Status": 0,
"Line_1.HA20.Temperature.Temperature.TempHumi.Event": 0

But I want this process to happen automatically with the incoming data every 10 seconds and to be done with all the other incoming data. My problem is how to write a function on node red to automate this process and merge it with the incoming data.

I am not sure if you got my point here or not

It is effectively the same answer as I gave last time, though you seem to have changed the object names. If the values are in an object in msg.payload then
msg.payload = {Line_1: {HA20: {Temperature: {Temperature: msg.payload}}}}}

Having thought some more, I am not sure whether my solution is correct. You did not say I was wrong when I said that you wanted the incoming data to be added into hierarchical objects, and since, presumably, you tested my previous solution then that is what you want.
However, it is possible that this is not what you want and what you want is for the data to be changed so that the property names are strings such as "Line_1.HA20.Temperature.Temperature.TempHumi.Range". Do you understand the difference between those two and if so then which do you want?

You said that you need to send the data to the cloud. Do you have a link to the docs for that api?

I have not tried your last answer but I am thinking about how to write the conversion function in general. Because now I am thinking about converting the raw JSON data directly, I do not know should I use JSON parse to convert the data into the wanted format?

object
TempHumi: object
Range: 0
Status: 0
Event: 0
SenVal: 25875
Accelerometer: object
X-Axis: object
SenEvent: 0
OAVelocity: 6
Peakmg: 5
RMSmg: 4
Y-Axis: object
SenEvent: 0
OAVelocity: 4
Peakmg: 5
RMSmg: 4
Z-Axis: object
SenEvent: 0
OAVelocity: 5
Peakmg: 5
RMSmg: 4
LogIndex: 0
Timestamp: 1552536020
Device: object
Events: 0
PowerSrc: 1
BatteryVolt: 0
Time: 1552536021

what do you think?

For your question, I cannot give you a direct link to data related to the cloud as the access is restricted.

In order to know how to change it you must answer the question I asked. Do you want an object with keys of the form "Line_1.HA20.Temperature.Temperature.TempHumi.Range" or do you want nested objects Line_1, containing HA20 etc?

What you have shown is not JSON (which is always a string), it is a javascript object. What I have been suggesting is how to convert that javascript object directly to the form you want, once we know what you want.

This post should help to clarify the difference between Javascript objects and JSON.

[Edit] Removed a question as I see you have already answered it.

I want an object with keys of the form "Line_1.HA20.Temperature.Temperature.TempHumi.Range" not a nested one.

Is this what you are after?

[{"id":"907c981aa2131e77","type":"inject","z":"ac631a6e.90e038","name":"Go","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":190,"y":80,"wires":[["211ea9f3804323ec"]]},{"id":"211ea9f3804323ec","type":"function","z":"ac631a6e.90e038","name":"Simulate sensor data","func":"msg.payload = {};\nmsg.payload.TempHumi = {Range: 0,\nStatus: 0,\nEvent: 0,\nSenVal: 32875};\nmsg.payload.Accelerometer = {\n'X - Axis.SenEvent': 0,\n'X - Axis.OAVelocity': 44,\n'X - Axis.Peakmg': 7,\n'X - Axis.RMSmg': 5,\n'Y - Axis.SenEvent': 0,\n'Y - Axis.OAVelocity': 19,\n'Y - Axis.Peakmg': 5,\n'Y - Axis.RMSmg': 4,\n'Z - Axis.SenEvent': 0,\n'Z - Axis.OAVelocity': 15,\n'Z - Axis.Peakmg': 9,\n'Z - Axis.RMSmg': 7,\n'LogIndex': 0,\n'Timestamp': 1552546760,\n};\nmsg.payload.Device = {\n'Events': 0,\n'PowerSrc': 1,\n'BatteryVolt': 0,\n'Time': 1552546760,\n};\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":360,"y":80,"wires":[["8bdd3ac75b98ed1b","148b68a0480bfaa0","e3f1ea911685f42a"]]},{"id":"8bdd3ac75b98ed1b","type":"debug","z":"ac631a6e.90e038","name":"Input Data","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":570,"y":40,"wires":[]},{"id":"e3f1ea911685f42a","type":"function","z":"ac631a6e.90e038","name":"Reformat","func":"let newmsg = {};\nnewmsg.payload = {\n    'Line_1.HA20.Temperature.Temperature.TempHumi':  msg.payload.TempHumi\n};\nreturn newmsg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":560,"y":120,"wires":[["4f538ec80ab7c63c"]]},{"id":"4f538ec80ab7c63c","type":"debug","z":"ac631a6e.90e038","name":"Output data","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":730,"y":120,"wires":[]}]

Untitled 3

Or this:
Untitled 4

[{"id":"907c981aa2131e77","type":"inject","z":"ac631a6e.90e038","name":"Go","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":190,"y":80,"wires":[["211ea9f3804323ec"]]},{"id":"211ea9f3804323ec","type":"function","z":"ac631a6e.90e038","name":"Simulate sensor data","func":"msg.payload = {};\nmsg.payload.TempHumi = {Range: 0,\nStatus: 0,\nEvent: 0,\nSenVal: 32875};\nmsg.payload.Accelerometer = {\n'X - Axis.SenEvent': 0,\n'X - Axis.OAVelocity': 44,\n'X - Axis.Peakmg': 7,\n'X - Axis.RMSmg': 5,\n'Y - Axis.SenEvent': 0,\n'Y - Axis.OAVelocity': 19,\n'Y - Axis.Peakmg': 5,\n'Y - Axis.RMSmg': 4,\n'Z - Axis.SenEvent': 0,\n'Z - Axis.OAVelocity': 15,\n'Z - Axis.Peakmg': 9,\n'Z - Axis.RMSmg': 7,\n'LogIndex': 0,\n'Timestamp': 1552546760,\n};\nmsg.payload.Device = {\n'Events': 0,\n'PowerSrc': 1,\n'BatteryVolt': 0,\n'Time': 1552546760,\n};\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":360,"y":80,"wires":[["e3f1ea911685f42a","b71c382c3d074795"]]},{"id":"b71c382c3d074795","type":"function","z":"ac631a6e.90e038","name":"Reformat","func":"let newmsg = {};\nnewmsg.payload = {\n    'Line_1.HA20.Temperature.Temperature.TempHumi.Range':  msg.payload.TempHumi.Range,\n    'Line_1.HA20.Temperature.Temperature.TempHumi.Status': msg.payload.TempHumi.Status,\n    'Line_1.HA20.Temperature.Temperature.TempHumi.Event': msg.payload.TempHumi.Event,\n    'Line_1.HA20.Temperature.Temperature.TempHumi.SenVal': msg.payload.TempHumi.SenVal,\n};\nreturn newmsg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":560,"y":160,"wires":[["4f538ec80ab7c63c"]]},{"id":"4f538ec80ab7c63c","type":"debug","z":"ac631a6e.90e038","name":"Output data","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":730,"y":160,"wires":[]}]

In my humble opinion, the dots embedded in long strings for the name of message properties is bound to cause difficulties or confusion further down the line, much better to have nested objects.

1 Like