Splitting data from msg.payload

Hi All
I'm trying to get values from Victron Ve.Direct USB device, but I have troubles spitting the informations to value I can use in the Node-Red Dashboard.
From the Ve.Direct USB i'm getting following informations:

19.8.2019 09.42.12node: c2380c6b.cc0f6
msg : Object
object
payload: "PPV→7↵"
port: "/dev/ttyUSB0"
_msgid: "5e429aaf.e37ec4"

19.8.2019 09.42.12node: c2380c6b.cc0f6
msg : Object
object
payload: "VPV→35790↵"
port: "/dev/ttyUSB0"
_msgid: "1e90e921.a16f47"

How do I separete the values between the arrow and the broken arrow?
I've searched google and node-red forum for informations, but came short every time.

The arrows you are seeing is whitespace being displayed. The arrow at the end is a carriage return, followed by a linefeed. Also seen as \r\n. The first arrow I believe is a tab, or \t when displayed as a string. You could do a search for splitting on whitespace, but you will need some more afterwards:


That's where you start to split the string, but as you will see the second value, the one that you need still has the whitespace on the end. So you will need to trim that off: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim

Hi Afelix
And thanks for the quick reply. I've been looking at the split() method and it makes good sence, but I can not figure out how to use it in practice. I'm not very familiar with coding. I've done this once, but at that time I was able to use a function-node. The only problem is that it is now 4 years ago and I can not remember how I did it...
/Benjamin

Okay, then I'll spoil you with the solution, with an explanation on the how (I'm sick and bored and that's the excuse I'll use for it today :P):
What you're going to need is a function node, after your serial node. From what I remember from seeing this node, there is a configuration option that lets you trim off the whitespace, by selecting the return type or something like that. If it's there, select carriage return line feed or enter \r\n if it is an input. If it's not present there, you will have to add it to the function node as well. As for the code, let me show you the input message again, but simplified:

msg = {
    payload: "PPV\t7\r\n"
}
msg = { 
    payload: "VPV\t35790\r\n"
}

These are the two messages you posted in the first post. For the first one you would like the value 7 as output, for the second 35790. In the current shape, the msg.payload is a string. Meaning you can call the split() method on it directly. The separator you want to split it on is the tab part of the whitespace, that is the horizontal arrow. In a string that tab is displayed as \t. So to split you take msg.payload.split('\t') and now you have an array with in the first item the VPV or PPV string, and in the second the value followed by the ending whitespace. To get rid of that whitespace, you take the value and call .trim() on it. You could also flip those around, first calling .trim() to get rid of the whitespace at the start and end, then on the result from that split on the tab in the middle.

var stripped = msg.payload.trim();
var values = stripped.split('\t');
// As you are only appear to be interested in the value, 
// use [1] to access the actual value. The array is zero-indexed, meaning
// that the first item is [0], and the second is thus [1].
msg.payload = values[1];
return msg;

If you put that in a function node, it gives you the value, but still as a string. If you need it as a number, you have three options, more or less:

  1. for a whole number, an integer: msg.payload = parseInt(msg.payload, 10); // 10 as in base 10, a decimal number
  2. for a decimal number, or rather a floating point: msg.payload = parseFloat(msg.payload);
  3. if you don't know if it's a decimal or whole number, or if you want it to fail if there's still text in it: msg.payload = Number(msg.payload); If it has any text in it that makes it's unable to get a number, you will get NaN instead: Not a Number.

Hi Afelix
Thank you so much for using your time on this matter! I've read your post and understand where we are going, but when I'm making a function-node with the msg.payload.strip i'm getting the following information:
"TypeError: msg.payload.strip is not a function"

/Benjamin

Hm... I don't have access to node-red myself at the moment, but for the sake of keeping this in line with the rest of the topics on the forums, can you upload your flow in here, in between backticks? (use the </> button in the post editor to get those in). I'm able to more or less read those flow files without importing them into Node-RED, but can you for my ease add a screenshot of the flow too? I'm mostly interested in seeing how you connected the Ve.Direct USB to the function node, and beyond. With your first message in mind, it should work if the payload is a string (which it appears to be), and the function node is connected at the same place as your debug node is/was.

[{"id":"9c7ec065.ac87f","type":"tab","label":"Flow 3","disabled":false,"info":""},{"id":"514e458a.70e90c","type":"serial in","z":"9c7ec065.ac87f","name":"","serial":"856714ce.8bf378","x":260,"y":20,"wires":[["d6405849.355788"]]},{"id":"19cf282.a4962d8","type":"debug","z":"9c7ec065.ac87f","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":500,"y":140,"wires":[]},{"id":"d6405849.355788","type":"function","z":"9c7ec065.ac87f","name":"","func":"var stripped = msg.payload.trim();\nvar values = msg.payload.strip('\\t');","outputs":1,"noerr":0,"x":280,"y":220,"wires":[["19cf282.a4962d8"]]},{"id":"856714ce.8bf378","type":"serial-port","z":"","serialport":"/dev/ttyUSB0","serialbaud":"19200","databits":"8","parity":"none","stopbits":"1","waitfor":"","newline":"\\n","bin":"false","out":"char","addchar":"","responsetimeout":"10000"}]

screen2

Okay yes I think I see it now. As the first screenshot shows, msg.payload is indeed a string. I made a typo in the sample code I gave you, while still explaining it more or less correctly. My primary language is Python, and in python the str.trim is called strip. Which it is not in JavaScript. But it looks a lot like split, so that’s what it should have been.
I’m seeing another small mistake in my sample code now which I’ll fix in a moment, as I’m seeing it repeated in your flow. Sorry for that, I’m sick in bed for a reason I guess :woman_facepalming:
The first step should be the trim, getting the whitespace off. That you store in a variable with a name of your choice, like stripped. Next you call the split function on that new variable, so you call it on the output of the trim() function. Next you set msg.payload to the value you got, and return msg. Which I forgot in the sample as well. I’m now going up to fix the sample :slight_smile:

.strip doesn't exist in javascript.

var values = msg.payload.replace('\\t','')

uuugh no - we need the \t to sPlit on not sTrip...

var values = msg.payload.trim().split('\t');    // trim off the crlf first then split into parts   
msg.payload = values[1];  // replace payload with the reading we want
msg.topic = values[0];      // set the topic in case we need to tell them apart later
return msg;

Eh yes, as I wrote just above it this was a typo on my side in the example code, you can still see it before the edited version.

Good point, I hadn’t thought of that yet.

Hi Everybody!
Thanks a lot for your help! I have really learned alot. For the next users with same or similar problem, here is my solution:

[{"id":"a75dd19f.913c7","type":"tab","label":"Dashbaord","disabled":false,"info":""},{"id":"cd5e91e.6b7ec7","type":"ui_gauge","z":"a75dd19f.913c7","name":"","group":"217b64fe.56738c","order":0,"width":0,"height":0,"gtype":"gage","title":"RPM","label":"RPM","format":"{{value}}","min":0,"max":"30","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","x":540,"y":80,"wires":[]},{"id":"6bdbd65d.30be88","type":"ui_gauge","z":"a75dd19f.913c7","name":"","group":"d0696258.14086","order":0,"width":0,"height":0,"gtype":"gage","title":"VOLTAGE","label":"V","format":"{{value}}","min":0,"max":"25","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","x":880,"y":100,"wires":[]},{"id":"19b562a.07f519d","type":"ui_gauge","z":"a75dd19f.913c7","name":"","group":"8913023.3aa7e","order":0,"width":0,"height":0,"gtype":"gage","title":"LOAD","label":"W","format":"{{value}}","min":0,"max":"150","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","x":1160,"y":100,"wires":[]},{"id":"77ecd1df.ce72a","type":"serial in","z":"a75dd19f.913c7","name":"","serial":"856714ce.8bf378","x":290,"y":180,"wires":[["def09dfc.5e55f"]]},{"id":"5702ff0a.d4faf","type":"debug","z":"a75dd19f.913c7","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":550,"y":300,"wires":[]},{"id":"def09dfc.5e55f","type":"function","z":"a75dd19f.913c7","name":"","func":"var values = msg.payload.trim().split('\\t');    // trim off the crlf first then split into parts   \nmsg.payload = values[1];  // replace payload with the reading we want\nmsg.topic = values[0];      // set the topic in case we need to tell them apart later\nreturn msg;","outputs":1,"noerr":0,"x":310,"y":380,"wires":[["8734261e.04cc18"]]},{"id":"8734261e.04cc18","type":"switch","z":"a75dd19f.913c7","name":"","property":"topic","propertyType":"msg","rules":[{"t":"cont","v":"PPV","vt":"str"},{"t":"cont","v":"VPV","vt":"str"},{"t":"eq","v":"V","vt":"str"}],"checkall":"true","repair":false,"outputs":3,"x":510,"y":460,"wires":[["19b562a.07f519d"],["46b987d0.2f09d8"],["3cdf414d.815b4e"]]},{"id":"3cdf414d.815b4e","type":"function","z":"a75dd19f.913c7","name":"","func":"msg.payload = msg.payload / 1000;\nreturn msg;","outputs":1,"noerr":0,"x":840,"y":440,"wires":[["6bdbd65d.30be88"]]},{"id":"46b987d0.2f09d8","type":"function","z":"a75dd19f.913c7","name":"","func":"msg.payload = msg.payload / 5000;\nreturn msg;","outputs":1,"noerr":0,"x":850,"y":340,"wires":[["5702ff0a.d4faf","cd5e91e.6b7ec7"]]},{"id":"217b64fe.56738c","type":"ui_group","z":"","name":"Left","tab":"380049d1.c1cf56","order":1,"disp":false,"width":"6","collapse":false},{"id":"d0696258.14086","type":"ui_group","z":"","name":"Mid","tab":"380049d1.c1cf56","order":2,"disp":false,"width":"6","collapse":false},{"id":"8913023.3aa7e","type":"ui_group","z":"","name":"Right","tab":"380049d1.c1cf56","order":3,"disp":false,"width":"6","collapse":false},{"id":"856714ce.8bf378","type":"serial-port","z":"","serialport":"/dev/ttyUSB0","serialbaud":"19200","databits":"8","parity":"none","stopbits":"1","waitfor":"","newline":"\\n","bin":"false","out":"char","addchar":"","responsetimeout":"10000"},{"id":"380049d1.c1cf56","type":"ui_tab","z":"","name":"Dashboard","icon":"dashboard","order":1,"disabled":false,"hidden":false}]