Add an element to dropdown list when a specific event occurs

Hi guys,

I want to be able to add elements dynamically to a drop-down list following a specific topic received.

I have multiple devices on a network that are added or removed from the network over time. It can be due to maintenance or student adding devices to the network.

When a device is booted, it sends a MQTT message with the topic "device-ID/hello" with the following payload

{
  "dateTime": "2022-06-14 11:31:36",
  "runningSince": "2022-06-14 11:13:59",
  "deviceType": "BIOREACTOR",
  "deviceName": "BIOREACT-CC83",
  "ip": "192.168.1.146"
}

Currently, in my development, I'm filling the ddl manually, but this will get quickly unmanageable when my students will plug or unplug there device.

firefox_QJ8VdjQQGO

For now, I just want to fill a drop-down list the deviceName as soon as it received the "hello" topic. How can I do that?

you need to store the incoming payloads in context and then use the stored values to create msg.options
e.g.

[{"id":"322498fb.179d68","type":"change","z":"bf9e1e33.030598","name":"","rules":[{"t":"set","p":"hello_mqtt","pt":"flow","to":"$append(\t    [$flowContext(\"hello_mqtt\")][deviceName != $$.payload.deviceName],\t    [$$.payload]\t)\t","tot":"jsonata"},{"t":"set","p":"options","pt":"msg","to":"[$flowContext(\"hello_mqtt\").deviceName]","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":340,"y":2180,"wires":[["c692b223.af45e","5c45cfe5.8c7838"]]},{"id":"f967ae4a.d3929","type":"inject","z":"bf9e1e33.030598","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"device-ID/hello","payload":"{   \"dateTime\": \"2022-06-14 11:31:36\",   \"runningSince\": \"2022-06-14 11:13:59\",   \"deviceType\": \"BIOREACTOR\",   \"deviceName\": \"BIOREACT-CC83\",   \"ip\": \"192.168.1.146\" }","payloadType":"json","x":140,"y":2180,"wires":[["322498fb.179d68"]]},{"id":"c692b223.af45e","type":"ui_dropdown","z":"bf9e1e33.030598","name":"","label":"hello","tooltip":"","place":"Select option","group":"2d4fe667.28f8ba","order":9,"width":0,"height":0,"passthru":true,"multiple":false,"options":[],"payload":"","topic":"topic","topicType":"msg","className":"","x":260,"y":2240,"wires":[[]]},{"id":"5c45cfe5.8c7838","type":"debug","z":"bf9e1e33.030598","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":580,"y":2220,"wires":[]},{"id":"2d4fe667.28f8ba","type":"ui_group","name":"demo","tab":"1caa8458.b17814","order":1,"disp":true,"width":"12","collapse":false},{"id":"1caa8458.b17814","type":"ui_tab","name":"Demo","icon":"dashboard","order":1,"disabled":false,"hidden":false}]

when they log off, you will need to remove from storage and recreate msg.options

I'm currently filtering the data from function node.

This is the code in the function node, but it does not work.

var varName = 'deviceList';

if (!global.get(varName)) {
    global.set(varName, new Map()); // Init
    node.warn("New global 'deviceList' created.");
}

var devices = global.get(varName);

if (msg.payload.deviceName) {
    var dev = msg.payload.deviceName;
    var devId = dev.slice(-4);

    
    if (!devices.has(dev)) {
        devices.set(dev, devId);
    }
    
}

let msgDbg = `Nb devices : ${devices.size}\n`;

let result = []
const iter = devices.entries();


for (let i = 0; i < devices.size; i++) {
    let keyValue = {} ;
    let value = iter.next().value;
    
    keyValue[value[0]] = value[1];
    
    result[i] = keyValue;
    
    msgDbg += `${value[0]} : ${value[1]}\n`
}

// node.warn(msgDbg)

msg.payload = result;
msg.options = result; // Not working either.
return msg;

@E1cid I've never used the change node. What is the meaning of "hello_mqtt" in the change node? Which node receives it?

I have copied your change node in my flow, but there's no change in the DDL.

hello_mqtt is just the context store variable name.

here is a funcntion and change node that do the exact same thing

[{"id":"19eb38d0.8f604f","type":"inject","z":"bf9e1e33.030598","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"device-ID/hello","payload":"{   \"dateTime\": \"2022-06-14 11:31:36\",   \"runningSince\": \"2022-06-14 11:13:59\",   \"deviceType\": \"BIOREACTOR\",   \"deviceName\": \"BIOREACT-CC83\",   \"ip\": \"192.168.1.146\" }","payloadType":"json","x":190,"y":2040,"wires":[["d97c8291.c0987"]]},{"id":"d97c8291.c0987","type":"function","z":"bf9e1e33.030598","name":"","func":"const varName = 'deviceList';\n\nlet devices = global.get(varName) || [];\n\nif (msg.payload.deviceName) {\n    const dev = msg.payload.deviceName;\n    const devId = dev.slice(-4);\n\n    \n    if (!(devices.find(obj => obj[dev] === devId))) {\n        devices.push({[dev]:devId})\n        global.set(varName, devices);\n    }\n    \n}\n\n\nmsg.options = devices; // Not working either.\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":360,"y":2100,"wires":[["5c45cfe5.8c7838"]]},{"id":"7c5a92bc.37419c","type":"inject","z":"bf9e1e33.030598","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"device-ID/hello","payload":"{\"dateTime\":\"2022-06-14 11:31:36\",\"runningSince\":\"2022-06-14 11:13:59\",\"deviceType\":\"BIOREACTOR\",\"deviceName\":\"BIOREACT-CC99\",\"ip\":\"192.168.1.146\"}","payloadType":"json","x":190,"y":2080,"wires":[["d97c8291.c0987"]]},{"id":"5c45cfe5.8c7838","type":"debug","z":"bf9e1e33.030598","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":580,"y":2220,"wires":[]},{"id":"322498fb.179d68","type":"change","z":"bf9e1e33.030598","name":"","rules":[{"t":"set","p":"deviceList","pt":"global","to":"$append(\t    [$globalContext(\"deviceList\")][$$.payload.deviceName != $substring($$.payload.deviceName,-4)],\t    [{$$.payload.deviceName: $substring($$.payload.deviceName,-4)}]\t)\t","tot":"jsonata"},{"t":"set","p":"options","pt":"msg","to":"deviceList","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":340,"y":2180,"wires":[["5c45cfe5.8c7838","c692b223.af45e"]]},{"id":"f967ae4a.d3929","type":"inject","z":"bf9e1e33.030598","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"device-ID/hello","payload":"{   \"dateTime\": \"2022-06-14 11:31:36\",   \"runningSince\": \"2022-06-14 11:13:59\",   \"deviceType\": \"BIOREACTOR\",   \"deviceName\": \"BIOREACT-CC83\",   \"ip\": \"192.168.1.146\" }","payloadType":"json","x":110,"y":2140,"wires":[["322498fb.179d68"]]},{"id":"28e1e28b.ddeb56","type":"inject","z":"bf9e1e33.030598","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"device-ID/hello","payload":"{\"dateTime\":\"2022-06-14 11:31:36\",\"runningSince\":\"2022-06-14 11:13:59\",\"deviceType\":\"BIOREACTOR\",\"deviceName\":\"BIOREACT-CC99\",\"ip\":\"192.168.1.146\"}","payloadType":"json","x":110,"y":2180,"wires":[["322498fb.179d68"]]},{"id":"c692b223.af45e","type":"ui_dropdown","z":"bf9e1e33.030598","name":"","label":"hello","tooltip":"","place":"Select option","group":"2d4fe667.28f8ba","order":9,"width":0,"height":0,"passthru":true,"multiple":false,"options":[],"payload":"","topic":"topic","topicType":"msg","className":"","x":260,"y":2240,"wires":[[]]},{"id":"7754ef38.46cf48","type":"inject","z":"bf9e1e33.030598","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":140,"y":2300,"wires":[["4322b51a.2a7b14"]]},{"id":"4322b51a.2a7b14","type":"change","z":"bf9e1e33.030598","name":"","rules":[{"t":"delete","p":"deviceList","pt":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":380,"y":2300,"wires":[[]]},{"id":"2d4fe667.28f8ba","type":"ui_group","name":"demo","tab":"1caa8458.b17814","order":1,"disp":true,"width":"12","collapse":false},{"id":"1caa8458.b17814","type":"ui_tab","name":"Demo","icon":"dashboard","order":1,"disabled":false,"hidden":false}]
1 Like

Your function is more elegant than mine. Thanks!

As a C-style developer, I really need to get to JS.