New user with newbie interpetation problems

Hi everybody,

I'm in this forum for more than a month getting information and solving my problems, but now I stuck with a string problem.
I'm using version 1.2.6 of node red in a raspberry Pi 3B+.
I found a flow for my APC UPS, and I'm getting the data from the apcupsd, but the info comes in a big string of info, and I can't get what I need.
This is the string:

APC      : 001,043,1001DATE     : 2021-01-27 09:52:47 -0100  HOSTNAME : DreamVERSION  : 3.14.14 (31 May 2016) debianUPSNAME  : APCCABLE    : USB CableDRIVER   : USB UPS DriverUPSMODE  : Stand AloneSTARTTIME: 2021-01-24 11:42:55 -0100  MODEL    : Smart-UPS 1000 STATUS   : ONLINE LINEV    : 244.8 VoltsLOADPCT  : 0.0 PercentBCHARGE  : 100.0 PercentTIMELEFT : 291.0 MinutesMBATTCHG : 5 PercentMINTIMEL : 3 MinutesMAXTIME  : 0 SecondsOUTPUTV  : 244.8 VoltsSENSE    : HighDWAKE    : -1 SecondsDSHUTD   : 180 SecondsLOTRANS  : 208.0 VoltsHITRANS  : 253.0 VoltsRETPCT   : 0.0 PercentITEMP    : 28.3 CALARMDEL : 30 SecondsBATTV    : 27.5 VoltsLINEFREQ : 50.0 HzLASTXFER : No transfers since turnonNUMXFERS : 0TONBATT  : 0 SecondsCUMONBATT: 0 SecondsXOFFBATT : N/ASELFTEST : NOSTESTI   : 14 daysSTATFLAG : 0x05000008MANDATE  : 2004-10-18SERIALNO : AS0443230286BATTDATE : 2004-10-18NOMOUTV  : 220 VoltsNOMBATTV : 24.0 VoltsFIRMWARE : 600.3.I USB FW:1.5END APC  : 202...

The flow that I'm using is this one (not mine), but adapted to me:

[{"id":"ff997979.d294b8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"73db5098.7513c","type":"exec","z":"ff997979.d294b8","command":"/sbin/apcaccess","addpay":false,"append":"","useSpawn":"","timer":"","name":"apcaccess","x":350,"y":140,"wires":[["dca40517.33c468","b4aed1aa.aec878"],[],[]]},{"id":"a3de16ec.d1803","type":"inject","z":"ff997979.d294b8","name":"every 10 seconds","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"10","crontab":"","once":true,"onceDelay":"","topic":"","payload":"","payloadType":"str","x":177,"y":139,"wires":[["73db5098.7513c"]]},{"id":"dca40517.33c468","type":"function","z":"ff997979.d294b8","name":"Parse apcaccess data","func":"var wanted = ['upsname', 'serialno', 'status', 'linev', 'linefreq', 'loadpct', 'battv', 'bcharge', 'timeleft', 'itemp', 'xonbatt', 'xoffbatt'];\nvar lines = msg.payload.trim().split(\"\\n\");\nvar outputMsgs = [];\nvar mqtttopic = 'home/common/ups/APC';\n\n// loop over every line\nlines.forEach(function (line) {\n    // assign values\n    var stats = line.split(' : ');\n    var label = stats[0].toLowerCase();\n    var value = stats[1];\n\n    // remove surrounding spaces\n    label = label.replace(/(^\\s+|\\s+$)/g, '');\n    context.curValues = context.curValues || {};\n    context.curValues[label] = context.curValues[label] || 0;\n\n    // if found as wanted value, store it\n    if (wanted.indexOf(label) > -1) {\n        value = value.replace(/(^\\s+|\\s+$)/g, '');\n        if (context.curValues[label] != value) {\n            outputMsgs.push({topic:mqtttopic + '/' + label, payload:value});\n            context.curValues[label] = value;\n        }\n    }\n});\n\nreturn [ outputMsgs ];","outputs":1,"noerr":0,"initialize":"","finalize":"","x":560,"y":120,"wires":[["be0d6ac0.c1f378","d4ecacc3.36cc68"]]},{"id":"be0d6ac0.c1f378","type":"mqtt out","z":"ff997979.d294b8","name":"","topic":"APC","qos":"2","retain":"","broker":"1425f6c7.b9ea79","x":750,"y":120,"wires":[]},{"id":"d4ecacc3.36cc68","type":"debug","z":"ff997979.d294b8","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":770,"y":180,"wires":[]},{"id":"b4aed1aa.aec878","type":"debug","z":"ff997979.d294b8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":450,"y":220,"wires":[]},{"id":"cb1c6661.c219d","type":"function","z":"ff997979.d294b8","name":"UPS_Load","func":"msg.payload = Number(msg.payload.ups_load);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":750,"y":280,"wires":[[]]},{"id":"bd434a78.e3c448","type":"function","z":"ff997979.d294b8","name":"Battery Status","func":"var Vbats = msg.payload.battery_voltage;\n\nvar Vbat = Vbats.replace(\"_\",\".\");\n\nmsg.payload = Number(Vbat);\n\nreturn msg;","outputs":1,"noerr":0,"x":740,"y":360,"wires":[[]]},{"id":"c3d3cefd.564dd8","type":"function","z":"ff997979.d294b8","name":"V IN","func":"var Vins = msg.payload.input_voltage;\n\nvar Vin = Vins.replace(\"_\",\".\");\n\nmsg.payload = Number(Vin);\nreturn msg;","outputs":1,"noerr":0,"x":770,"y":600,"wires":[[]]},{"id":"42e0e523.4e45f4","type":"function","z":"ff997979.d294b8","name":"Bat Runtime","func":"msg.payload = Number(msg.payload.battery_runtime);\nreturn msg;","outputs":1,"noerr":0,"x":750,"y":440,"wires":[[]]},{"id":"fbdb99d8.a26208","type":"function","z":"ff997979.d294b8","name":"Bat Charge","func":"var Vcharges = msg.payload.battery_charge;\n\nvar Vcharge = Vcharges.replace(\"_\",\".\");\n\nmsg.payload = Number(Vcharge);\n\n\nreturn msg;","outputs":1,"noerr":0,"x":750,"y":520,"wires":[[]]},{"id":"1425f6c7.b9ea79","type":"mqtt-broker","name":"MQTT","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":false,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""}]

So I would like to use the info of the UPS_Load, Battery Status, Bat. Runtime, Bat Charge and V In, but I'm not getting there.
I already tried other ways to get there, but without any success.
I know, that this is easy for the majority of the users, but I'm stuck here...

Thanks in advance,

Tete

Is there really no divider or anything between the 1 and the D? Can you feed it exactly as you get it into a debug node and post a screenshot please?

This is what I'm getting:

Thanks,

Tete

That is better, there are new line characters there that can be split on. Though it isn't always obvious what exactly to split on (\n or \r)
Try this in a function node

function addProperty(obj, str) {
    const split = str.split(":")
    obj[split[0].trim()] = split[1].trim()
    return obj
}
msg.payload = msg.payload.split("\n").reduce( addProperty, {})
return msg;

and see what you get.

Other error:

Tete

Hi your original string example had no newlines and was truncated, so i did this

[{"id":"6b24e166.a7bb58","type":"inject","z":"a2d9cfcc.919dd8","name":"every 10 seconds","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":"","topic":"","payload":"","payloadType":"str","x":140,"y":100,"wires":[["d116d6e9.3d4f08"]]},{"id":"d116d6e9.3d4f08","type":"exec","z":"a2d9cfcc.919dd8","command":"/sbin/apcaccess","addpay":false,"append":"","useSpawn":"","timer":"","name":"apcaccess","x":350,"y":140,"wires":[["d989cc8.1ea653","28470eeb.44571a"],[],[]]},{"id":"d989cc8.1ea653","type":"function","z":"a2d9cfcc.919dd8","name":"Parse apcaccess data","func":"var wanted = [\"LINEV\",\"BCHARGE\"];\nvar hold =msg.payload;\nmsg.payload ={};\nvar mqtttopic = 'home/common/ups/APC';\n// loop over every wanted value\nwanted.forEach((patt) => {\n    let regx = new RegExp( patt+\"\\\\s*:\\\\s*\\\\d+\", \"g\");\n    regx = hold.match(regx);\nmsg.payload[patt]=regx[0].split(\":\")[1].trim();\n});\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":620,"y":120,"wires":[["defeffa2.acad18"]]},{"id":"28470eeb.44571a","type":"debug","z":"a2d9cfcc.919dd8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":450,"y":220,"wires":[]},{"id":"defeffa2.acad18","type":"debug","z":"a2d9cfcc.919dd8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":770,"y":180,"wires":[]},{"id":"b1cc23c4.15fe6","type":"inject","z":"a2d9cfcc.919dd8","name":"test","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"APC      : 001,043,1001DATE     : 2021-01-27 09:52:47 -0100  HOSTNAME : DreamVERSION  : 3.14.14 (31 May 2016) debianUPSNAME  : APCCABLE    : USB CableDRIVER   : USB UPS DriverUPSMODE  : Stand AloneSTARTTIME: 2021-01-24 11:42:55 -0100  MODEL    : Smart-UPS 1000 STATUS   : ONLINE LINEV    : 244.8 VoltsLOADPCT  : 0.0 PercentBCHARGE  : 100.0 PercentTIMELEFT : 291.0 MinutesMBATTCHG : 5 PercentMINTIMEL : 3 MinutesMAXTIME  : 0 SecondsOUTPUTV  : 244.8 VoltsSENSE    : HighDWAKE    : -1 SecondsDSHUTD   : 180 SecondsLOTRANS  : 208.0 VoltsHITRANS  : 253.0 VoltsRETPCT   : 0.0 PercentITEMP    : 28.3 CALARMDEL : 30 SecondsBATTV    : 27.5 VoltsLINEFREQ : 50.0 HzLASTXFER : No transfers since turnonNUMXFERS : 0TONBATT  : 0 SecondsCUMONBATT: 0 SecondsXOFFBATT : N/ASELFTEST : NOSTESTI   : 14 daysSTATFLAG : 0x05000008MANDATE  : 2004-10-18SERIALNO : AS0443230286BATTDATE : 2004-10-18NOMOUTV  : 220 VoltsNOMBATTV : 24.0 VoltsFIRMWARE : 600.3.I USB FW:1.5END APC  : 202...","payloadType":"str","x":430,"y":80,"wires":[["d989cc8.1ea653"]]}]

if you can provide a correct and full string i could do better.

YES!
Yours it's working!


Now I'm going to try to get the other values and see if I can get everything working.
Many thanks!

Tete

Interesting, first check that this gives an array with each element being of the form name : value

msg.payload = msg.payload.split("\n")
return msg;

If it does then try

function addProperty(obj, str) {
    const split = str.split(":")
    if (split.length >= 2) {
        obj[split[0].trim()] = split[1].trim()
    } else if (split.length === 1) {
        obj[split[0].trim()] = ""
    } else {
        obj[str] = "unsplitable"
    }
    return obj
}
msg.payload = msg.payload.split("\n").reduce( addProperty, {})
return msg;

I would be interested in knowing the issue with my solution if you had a couple of minutes to try what I asked.

Hi Colin,

Yours is working also, and I have to thank you also!

All the best,

Tete

Good, thanks. I haven't used Array.reduce() previously but I thought this looked like exactly the sort of problem that it should be able to crack.