Flow set "array error" using mqtt topic

Hi.

I am trying to save a thermostat mode to a flow variable using the msg.topic but it does not work as expected.

Flow:

Result:

How can i save it based on the MQTT adress without getting all those array enteries as well?

This is my example flow:

[{"id":"d8f143e9.eb063","type":"function","z":"82add03.b9a433","name":"","func":"//Get adress and build flow variable name \nvar address = msg.topic.split(\"/\")[2];\nvar newname = \"hdl.fh.\" + address + \".textmode\"\n\n//Save msg to flow variable\nflow.set (newname, msg.payload)\n\n//Debug\nmsg.address = address\nmsg.newname = newname\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":360,"y":120,"wires":[["ca252047.e559a"]]},{"id":"ca252047.e559a","type":"debug","z":"82add03.b9a433","name":"2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":530,"y":120,"wires":[]},{"id":"dbbd3792.f6fd88","type":"inject","z":"82add03.b9a433","name":"Test input msg: Normal","props":[{"p":"topic","vt":"str"},{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"hdl/fh/1.106/textmode/set","payload":"normal","payloadType":"str","x":140,"y":80,"wires":[["d8f143e9.eb063","2bfddbe0.c8dea4"]]},{"id":"de39039.e93a9","type":"inject","z":"82add03.b9a433","name":"Test input msg: Day","props":[{"p":"topic","vt":"str"},{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"hdl/fh/1.106/textmode/set","payload":"day","payloadType":"str","x":130,"y":140,"wires":[["d8f143e9.eb063","2bfddbe0.c8dea4"]]},{"id":"2bfddbe0.c8dea4","type":"debug","z":"82add03.b9a433","name":"1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":350,"y":200,"wires":[]}]

It's flow.set("newname", msg.payload)
With quotes around the variable name, same with flow.get

You issue is the numbers in the path are being interpreted as array elements

You will need to DIY this one...

const data = {
    hdl: flow.get("hdl") || {}
}

//Get adress and build flow variable name 
const address = msg.topic.split("/")[2];
const newname = "hdl.fh." + address + ".textmode";
const value = msg.payload;


setValue(data, newname, value);
flow.set("hdl", data.hdl);

//Debug
msg.address = address
msg.newname = newname

return msg;


/**
* @param {object} obj
* @param {string} path
* @param {any} value
*/
function setValue(obj, path, value) {
    var a = path.split('.')
    var o = obj
    while (a.length - 1) {
        var n = a.shift()
        if (!(n in o)) o[n] = {}
        o = o[n]
    }
    o[a[0]] = value
}

image

1 Like

Thanks that worked great. I would never be able to get that working alone, and still dont understand how that code works.

In simple terms, the setValue splits hdl.fh.1.106.textmode by "." into an array then loops through them setting the object obj parameters, creating a new object where none exists & on the last element, setting the value.