How to work with multiple inputs and saved vars

Hi,

I have an Ikea 'volume button' what I use for my sonos. This works.
The only annoying thing: when I adjust the volume with something else then the Ikea button, you have a volume 'jump' the next time you use the button again because I have no feedback.
This feedback is no problem for me the ask, but then I'm stuck, I will have to different inputs on my function and I really don't manage to combine them.

So 'flow' 1 works. I receive data from the pushbutton over MQTT and I increase or decrease the volume in my function

But now, I want to 'sync' this volume when I have an action on 'flow' 2.
You can see the commented code in my function and you will understand where I would like to go to, but this does not work. I also tried with the join function, but I get stuck every time.

Who can help me with this? The goal is that every time there is an action on 2, my internal variable volume is updated and saved... not return msg at that moment.

[
    {
        "id": "2183bd54719bd6df",
        "type": "mqtt in",
        "z": "9a5ec889a62524d2",
        "name": "zigbee2mqtt/volumeknop_bureau",
        "topic": "zigbee2mqtt/volumeknop_bureau",
        "qos": "2",
        "datatype": "json",
        "broker": "ac0ebf430a1bb8e8",
        "nl": false,
        "rap": true,
        "rh": 0,
        "inputs": 0,
        "x": 550,
        "y": 1540,
        "wires": [
            [
                "b9352ec6d93f4ecc"
            ]
        ]
    },
    {
        "id": "7a52b6c58e35def1",
        "type": "harmonyws-observer",
        "z": "9a5ec889a62524d2",
        "name": "Harmony Observer",
        "server": "4c96c05d6c530ab5",
        "startup": true,
        "toContext": false,
        "context": "global",
        "contextKeyActivity": "activity",
        "contextKeyAutomation": "automation",
        "x": 110,
        "y": 1480,
        "wires": [
            [
                "10b5d4a54ab907ed"
            ]
        ]
    },
    {
        "id": "6446a526e7c456fa",
        "type": "sonos-universal",
        "z": "9a5ec889a62524d2",
        "confignode": "88e9fa70.4a53e8",
        "command": "player.set.volume",
        "state": "",
        "stateType": "str",
        "avoidCheckPlayerAvailability": false,
        "name": "Set_Volume",
        "x": 1075,
        "y": 1520,
        "wires": [
            []
        ],
        "l": false
    },
    {
        "id": "b9352ec6d93f4ecc",
        "type": "function",
        "z": "9a5ec889a62524d2",
        "name": "Sonos volume",
        "func": "var x = msg.payload.action;\n//var start_volume = msg.payload.volume ;\nvar volume=context.get('volume') || 0;\n\n//if (start_volume != volume) {\n//    volume = start_volume;\n //   context.set('volume',volume);\n //   }\n\nif (x== \"rotate_right\") {\n    volume +=2;\n     if (volume >= 30) {\n        volume = 30;\n    }\n    msg.payload= volume;\n    context.set('volume',volume);\n    return [msg, null];\n    }\n\nif (x== \"rotate_left\") {\n    volume -=2;\n    if (volume <= 0) {\n        volume = 0;\n    }\n    msg.payload= volume;\n    context.set('volume',volume);\n    return [msg, null];\n    }\n \n //next if is not in use at the moment\nif (x== \"play_pause\") {\n    msg.payload = 'Pushed';\n    return [null, msg];\n    }\n\n\n",
        "outputs": 2,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 840,
        "y": 1540,
        "wires": [
            [
                "6446a526e7c456fa",
                "e14a7d6d57d4749b"
            ],
            [
                "6de6e7cfa5a7aec3"
            ]
        ]
    },
    {
        "id": "10b5d4a54ab907ed",
        "type": "sonos-universal",
        "z": "9a5ec889a62524d2",
        "confignode": "88e9fa70.4a53e8",
        "command": "player.get.volume",
        "state": "",
        "stateType": "str",
        "avoidCheckPlayerAvailability": false,
        "name": "",
        "x": 330,
        "y": 1480,
        "wires": [
            [
                "2958fc72007e716c"
            ]
        ]
    },
    {
        "id": "2958fc72007e716c",
        "type": "change",
        "z": "9a5ec889a62524d2",
        "name": "",
        "rules": [
            {
                "t": "move",
                "p": "payload",
                "pt": "msg",
                "to": "payload.volume",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 550,
        "y": 1480,
        "wires": [
            [
                "b9352ec6d93f4ecc",
                "6a500c68d45bda7a"
            ]
        ]
    },
    {
        "id": "e14a7d6d57d4749b",
        "type": "debug",
        "z": "9a5ec889a62524d2",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 1140,
        "y": 1460,
        "wires": []
    },
    {
        "id": "6de6e7cfa5a7aec3",
        "type": "debug",
        "z": "9a5ec889a62524d2",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 1060,
        "y": 1660,
        "wires": []
    },
    {
        "id": "6a500c68d45bda7a",
        "type": "debug",
        "z": "9a5ec889a62524d2",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 820,
        "y": 1440,
        "wires": []
    },
    {
        "id": "ac0ebf430a1bb8e8",
        "type": "mqtt-broker",
        "name": "Mqtt",
        "broker": "192.168.0.71",
        "port": "1883",
        "clientid": "",
        "autoConnect": true,
        "usetls": false,
        "protocolVersion": "4",
        "keepalive": "60",
        "cleansession": true,
        "birthTopic": "",
        "birthQos": "0",
        "birthPayload": "",
        "birthMsg": {},
        "closeTopic": "",
        "closeQos": "0",
        "closePayload": "",
        "closeMsg": {},
        "willTopic": "",
        "willQos": "0",
        "willPayload": "",
        "willMsg": {},
        "sessionExpiry": ""
    },
    {
        "id": "4c96c05d6c530ab5",
        "type": "harmonyws-server",
        "name": "Woonkamer",
        "ip": "192.168.0.80",
        "debug": false
    },
    {
        "id": "88e9fa70.4a53e8",
        "type": "sonos-config",
        "name": "Sonos_IP",
        "serialnum": "",
        "ipaddress": "192.168.0.111"
    }
]

I don't use those nodes, or hardware, but I suggest that when your Get Volume node sees that there has been an external change, that you send that to MQTT. Then your MQTT In node will pick it up and all should be well. Be careful that you do not get an infinite loop via MQTT though. Whether you need to do anything to avoid that depends on how whether, when you press the volume button, that causes an input from the get volume node, which would then go to MQTT, causing another button event and so on.

I would save the volume to a flow variable and test it against the incoming volume. Here is a sample using injects in place of the 'harmony Observer' and 'player get volume' nodes:

[{"id":"b9e3165a2d04a559","type":"inject","z":"48dc7d4315c5f4fc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":310,"y":220,"wires":[["e0eccb5cec454216"]]},{"id":"e0eccb5cec454216","type":"change","z":"48dc7d4315c5f4fc","name":"Initilize flow.volume to 0","rules":[{"t":"set","p":"volume","pt":"flow","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":550,"y":220,"wires":[[]]},{"id":"2183bd54719bd6df","type":"mqtt in","z":"48dc7d4315c5f4fc","d":true,"name":"zigbee2mqtt/volumeknop_bureau","topic":"zigbee2mqtt/volumeknop_bureau","qos":"2","datatype":"json","broker":"ac0ebf430a1bb8e8","nl":false,"rap":true,"rh":0,"inputs":0,"x":550,"y":500,"wires":[["b9352ec6d93f4ecc"]]},{"id":"b9352ec6d93f4ecc","type":"function","z":"48dc7d4315c5f4fc","name":"Sonos volume","func":"var x = msg.payload.action;\n//var start_volume = msg.payload.volume ;\nvar volume=context.get('volume') || 0;\n\n//if (start_volume != volume) {\n//    volume = start_volume;\n //   context.set('volume',volume);\n //   }\n\nif (x== \"rotate_right\") {\n    volume +=2;\n     if (volume >= 30) {\n        volume = 30;\n    }\n    msg.payload= volume;\n    context.set('volume',volume);\n    return [msg, null];\n    }\n\nif (x== \"rotate_left\") {\n    volume -=2;\n    if (volume <= 0) {\n        volume = 0;\n    }\n    msg.payload= volume;\n    context.set('volume',volume);\n    return [msg, null];\n    }\n \n //next if is not in use at the moment\nif (x== \"play_pause\") {\n    msg.payload = 'Pushed';\n    return [null, msg];\n    }\n\n\n","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":840,"y":500,"wires":[["e14a7d6d57d4749b"],["6de6e7cfa5a7aec3"]]},{"id":"2958fc72007e716c","type":"change","z":"48dc7d4315c5f4fc","name":"","rules":[{"t":"set","p":"volume","pt":"flow","to":"payload.volume","tot":"msg","dc":true},{"t":"move","p":"payload","pt":"msg","to":"payload.volume","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":520,"y":420,"wires":[["b9352ec6d93f4ecc","6a500c68d45bda7a"]]},{"id":"e14a7d6d57d4749b","type":"debug","z":"48dc7d4315c5f4fc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1140,"y":420,"wires":[]},{"id":"6de6e7cfa5a7aec3","type":"debug","z":"48dc7d4315c5f4fc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1060,"y":620,"wires":[]},{"id":"6a500c68d45bda7a","type":"debug","z":"48dc7d4315c5f4fc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":820,"y":400,"wires":[]},{"id":"59b32a7f74e1f686","type":"inject","z":"48dc7d4315c5f4fc","name":"5","props":[{"p":"payload.volume","v":"5","vt":"num"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":130,"y":360,"wires":[["2f1372212345c107"]]},{"id":"ef6958d390d6d580","type":"inject","z":"48dc7d4315c5f4fc","name":"7","props":[{"p":"payload.volume","v":"7","vt":"num"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":130,"y":440,"wires":[["2f1372212345c107"]]},{"id":"2f1372212345c107","type":"switch","z":"48dc7d4315c5f4fc","name":"","property":"payload.volume","propertyType":"msg","rules":[{"t":"neq","v":"volume","vt":"flow"}],"checkall":"false","repair":false,"outputs":1,"x":350,"y":420,"wires":[["2958fc72007e716c"]]},{"id":"ac0ebf430a1bb8e8","type":"mqtt-broker","name":"Mqtt","broker":"192.168.0.71","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"sessionExpiry":""}]

each input is checked against the flow.volume. If it is different it is passed on and replaces the existing flow.volume. It it is the same, nothing is passed on.

Thanks both,
I do understand where you both would like to get to and I easily thought, well, just change the payload of the 'external' to the same type of payload as my mqtt message. Seems simple, but I don't even get there to create an object exactly the same...

Let's forget this, and let me ask my question a little bit different.
I'll build up from scratch:

  1. My MQTT is giving me this object:

{"action":"rotate_right","battery":87,"brightness":244,"linkquality":6,"rate":195,"update":{"state":"available"},"update_available":true}

  1. All I check in my function is the action, to count up the volume, or count down the volume
var x = msg.payload.action;
var volume=context.get('volume') || 0;

if (x== "rotate_right") {
    volume +=2;
     if (volume >= 30) {
        volume = 30;
    }
    msg.payload= volume;
    context.set('volume',volume);
    return [msg, null];
    }

if (x== "rotate_left") {
    volume -=2;
    if (volume <= 0) {
        volume = 0;
    }
    msg.payload= volume;
    context.set('volume',volume);
    return [msg, null];
    }
  1. But now I want also to preset the volume from another type of message, that just is a number.
    I think, if I 'switch' this into an object that also has "action" and then a value, I can easily add another 'if' statement in my function, without getting an error that a message has arrived without an action as now.
    image

This is my new 'test' code: (ps: how to you guys get this in one line? or do you really erase all the enters)

[
    {
        "id": "2183bd54719bd6df",
        "type": "mqtt in",
        "z": "9a5ec889a62524d2",
        "name": "zigbee2mqtt/volumeknop_bureau",
        "topic": "zigbee2mqtt/volumeknop_bureau",
        "qos": "2",
        "datatype": "json",
        "broker": "ac0ebf430a1bb8e8",
        "nl": false,
        "rap": true,
        "rh": 0,
        "inputs": 0,
        "x": 470,
        "y": 2060,
        "wires": [
            [
                "212daa51e58ac6ab",
                "8ed1884f55597cd6"
            ]
        ]
    },
    {
        "id": "212daa51e58ac6ab",
        "type": "function",
        "z": "9a5ec889a62524d2",
        "name": "Sonos volume",
        "func": "var x = msg.payload.action;\nvar volume=context.get('volume') || 0;\n\nif (x== \"rotate_right\") {\n    volume +=2;\n     if (volume >= 30) {\n        volume = 30;\n    }\n    msg.payload= volume;\n    context.set('volume',volume);\n    return [msg, null];\n    }\n\nif (x== \"rotate_left\") {\n    volume -=2;\n    if (volume <= 0) {\n        volume = 0;\n    }\n    msg.payload= volume;\n    context.set('volume',volume);\n    return [msg, null];\n    }\n \n //next if is not in use at the moment\nif (x== \"play_pause\") {\n    msg.payload = 'Pushed';\n    return [null, msg];\n    }\n\n\n",
        "outputs": 2,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 780,
        "y": 2060,
        "wires": [
            [
                "ad51d69f048aa0d5"
            ],
            []
        ]
    },
    {
        "id": "ad51d69f048aa0d5",
        "type": "debug",
        "z": "9a5ec889a62524d2",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 1160,
        "y": 2040,
        "wires": []
    },
    {
        "id": "f75ac6624caf2b2a",
        "type": "inject",
        "z": "9a5ec889a62524d2",
        "name": "6",
        "props": [
            {
                "p": "init",
                "v": "6",
                "vt": "num"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "x": 530,
        "y": 1940,
        "wires": [
            [
                "212daa51e58ac6ab"
            ]
        ]
    },
    {
        "id": "ba8a9755593e76b1",
        "type": "inject",
        "z": "9a5ec889a62524d2",
        "name": "8",
        "props": [
            {
                "p": "init",
                "v": "8",
                "vt": "num"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "x": 530,
        "y": 1980,
        "wires": [
            [
                "212daa51e58ac6ab"
            ]
        ]
    },
    {
        "id": "8ed1884f55597cd6",
        "type": "debug",
        "z": "9a5ec889a62524d2",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 740,
        "y": 2220,
        "wires": []
    },
    {
        "id": "ac0ebf430a1bb8e8",
        "type": "mqtt-broker",
        "name": "Mqtt",
        "broker": "192.168.0.71",
        "port": "1883",
        "clientid": "",
        "autoConnect": true,
        "usetls": false,
        "protocolVersion": "4",
        "keepalive": "60",
        "cleansession": true,
        "birthTopic": "",
        "birthQos": "0",
        "birthPayload": "",
        "birthMsg": {},
        "closeTopic": "",
        "closeQos": "0",
        "closePayload": "",
        "closeMsg": {},
        "willTopic": "",
        "willQos": "0",
        "willPayload": "",
        "willMsg": {},
        "sessionExpiry": ""
    }
]

What to add here, to make a new object with an 'action' and a 'volume' part, so my function will be happy?

It should be something like this, but my 'action' is not returned...

[
    {
        "id": "233bed1ce073dcf7",
        "type": "debug",
        "z": "9a5ec889a62524d2",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 610,
        "y": 1780,
        "wires": []
    },
    {
        "id": "f75ac6624caf2b2a",
        "type": "inject",
        "z": "9a5ec889a62524d2",
        "name": "6",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "6",
        "payloadType": "num",
        "x": 350,
        "y": 1840,
        "wires": [
            [
                "ed30d28f9d45e893",
                "233bed1ce073dcf7"
            ]
        ]
    },
    {
        "id": "ba8a9755593e76b1",
        "type": "inject",
        "z": "9a5ec889a62524d2",
        "name": "8",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "8",
        "payloadType": "num",
        "x": 350,
        "y": 1880,
        "wires": [
            [
                "ed30d28f9d45e893"
            ]
        ]
    },
    {
        "id": "ed30d28f9d45e893",
        "type": "function",
        "z": "9a5ec889a62524d2",
        "name": "",
        "func": "var x =msg.payload;\n\nmsg.volume = x;\nmsg.action = \"init volume\";\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 610,
        "y": 1880,
        "wires": [
            [
                "d9ccd3623bda57cb"
            ]
        ]
    },
    {
        "id": "d9ccd3623bda57cb",
        "type": "debug",
        "z": "9a5ec889a62524d2",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 830,
        "y": 1880,
        "wires": []
    }
]

In the function node msg.payload is expected to be an object but your injects are just sending msg.init so when the function node runs the first statement:
var x = msg.payload.action;
there is no msg.payload.action in the msg that has been received. So you need to send a msg that contains an object. Also, if the msg coming from mqtt doesn't contain msg.init you are going to have an issue too.

It has to do with a setting in the settings.js file:

    /** By default, the flow JSON will be formatted over multiple lines making
     * it easier to compare changes when using version control.
     * To disable pretty-printing of the JSON set the following property to false.
     */

    flowFilePretty: false,

Basically, it should be this:

[
    {
        "id": "2183bd54719bd6df",
        "type": "mqtt in",
        "z": "9a5ec889a62524d2",
        "name": "zigbee2mqtt/volumeknop_bureau",
        "topic": "zigbee2mqtt/volumeknop_bureau",
        "qos": "2",
        "datatype": "json",
        "broker": "ac0ebf430a1bb8e8",
        "nl": false,
        "rap": true,
        "rh": 0,
        "inputs": 0,
        "x": 470,
        "y": 2060,
        "wires": [
            [
                "212daa51e58ac6ab",
                "c0ac8b56191f26fd"
            ]
        ]
    },
    {
        "id": "212daa51e58ac6ab",
        "type": "function",
        "z": "9a5ec889a62524d2",
        "name": "Sonos volume",
        "func": "var x = msg.payload.action;\nvar volume=context.get('volume') || 0;\n\nif (x== \"init_volume\") {\n    volume = msg.volume;\n    context.set('volume',volume);\n    }\n\nif (x== \"rotate_right\") {\n    volume +=2;\n     if (volume >= 30) {\n        volume = 30;\n    }\n    msg.payload= volume;\n    context.set('volume',volume);\n    return [msg, null];\n    }\n\nif (x== \"rotate_left\") {\n    volume -=2;\n    if (volume <= 0) {\n        volume = 0;\n    }\n    msg.payload= volume;\n    context.set('volume',volume);\n    return [msg, null];\n    }\n \n //next if is not in use at the moment\nif (x== \"play_pause\") {\n    msg.payload = 'Pushed';\n    return [null, msg];\n    }\n\n\n",
        "outputs": 2,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 820,
        "y": 2060,
        "wires": [
            [
                "ad51d69f048aa0d5"
            ],
            []
        ]
    },
    {
        "id": "ad51d69f048aa0d5",
        "type": "debug",
        "z": "9a5ec889a62524d2",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 1050,
        "y": 2060,
        "wires": []
    },
    {
        "id": "f75ac6624caf2b2a",
        "type": "inject",
        "z": "9a5ec889a62524d2",
        "name": "6",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "6",
        "payloadType": "num",
        "x": 370,
        "y": 1920,
        "wires": [
            [
                "ed30d28f9d45e893"
            ]
        ]
    },
    {
        "id": "ba8a9755593e76b1",
        "type": "inject",
        "z": "9a5ec889a62524d2",
        "name": "8",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "8",
        "payloadType": "num",
        "x": 370,
        "y": 1960,
        "wires": [
            [
                "ed30d28f9d45e893"
            ]
        ]
    },
    {
        "id": "ed30d28f9d45e893",
        "type": "function",
        "z": "9a5ec889a62524d2",
        "name": "",
        "func": "var x = msg.payload;\n\nmsg.volume = x;\nmsg.action = \"init_volume\";\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 580,
        "y": 1940,
        "wires": [
            [
                "212daa51e58ac6ab",
                "765feb21eb6d9a00"
            ]
        ]
    },
    {
        "id": "c0ac8b56191f26fd",
        "type": "debug",
        "z": "9a5ec889a62524d2",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 810,
        "y": 2120,
        "wires": []
    },
    {
        "id": "765feb21eb6d9a00",
        "type": "debug",
        "z": "9a5ec889a62524d2",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 840,
        "y": 1960,
        "wires": []
    },
    {
        "id": "ac0ebf430a1bb8e8",
        "type": "mqtt-broker",
        "name": "Mqtt",
        "broker": "192.168.0.71",
        "port": "1883",
        "clientid": "",
        "autoConnect": true,
        "usetls": false,
        "protocolVersion": "4",
        "keepalive": "60",
        "cleansession": true,
        "birthTopic": "",
        "birthQos": "0",
        "birthPayload": "",
        "birthMsg": {},
        "closeTopic": "",
        "closeQos": "0",
        "closePayload": "",
        "closeMsg": {},
        "willTopic": "",
        "willQos": "0",
        "willPayload": "",
        "willMsg": {},
        "sessionExpiry": ""
    }
]

But, offcourse, it does not work. And I think it's because my MQTT message has the structure msg.PAYLOAD.action and my function just gives an msg.action

image

First I thought, just add the word 'payload' extra in my function, but that gives error's...

I feel stupid with all these basic questions, but I'm a PLC programmer using Structured Text. Nodered with payloads, different structures, combined with java is really a struggle for me to combine.

Sorry for the delay, I needed to get out for a walk before it got much warmer.

First off it's not Java it's JavaScript two different things. Secondly msg's are sent from node to node by the wires. a msg is an object and objects can have multiple different properties. If you change the debug node you have connected to the mqtt-in node, to display the complete msg object you will see what it is comprised of. You can copy (more abuot this below) the contents of the payload and put it in an inject node for testing.

Note, any msg going to the function node will have to contain anything you are testing in the function node. So if you add a new property to the inject node and test it in the function node then the msg's coming from the mqtt-in node better have the same property added to it.

In your function to add an action you have:

var x = msg.payload;

msg.volume = x;
msg.action = "init_volume";

return msg;

But in the 'Sonos volume' function the first line is:

var x = msg.payload.action;

but there is no msg.payload.action just a msg.action. You need to change msg.action = "init_volume"; to msg.payload.action = "init_volume"; but don't forget msg's coming via mqtt will also need that added in and you need to add vaolume to the mqtt incoming msg so it's reference will be msg.payload.volume.

---- canned replies to help you ----

I recommend watching this playlist: Node-RED Essentials. The videos are done by the developers of node-red. They're nice & short and to the point. You will understand a whole lot more in about 1 hour. A small investment for a lot of gain.

There’s a great page in the docs (Working with messages : Node-RED) that will explain how to use the debug panel to find the right path to any data item.

Pay particular attention to the part about the buttons that appear under your mouse pointer when you over hover a debug message property in the sidebar.

BX00Cy7yHi

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

You should also take a JavaScript tutorial. Here is a link to one: JavaScript Tutorial

no sorry for the delay... this is not a job, but an open forum :wink:
I appreciate your patience.

Although I do understand what you are sayin, it was not working by just adding the word 'payload'.

I changed everything, and moved/filtered some important 'things'. Finally I have this and this works .

[
    {
        "id": "7a52b6c58e35def1",
        "type": "harmonyws-observer",
        "z": "9a5ec889a62524d2",
        "name": "Harmony Observer",
        "server": "4c96c05d6c530ab5",
        "startup": true,
        "toContext": false,
        "context": "global",
        "contextKeyActivity": "activity",
        "contextKeyAutomation": "automation",
        "x": 110,
        "y": 1320,
        "wires": [
            [
                "10b5d4a54ab907ed"
            ]
        ]
    },
    {
        "id": "6446a526e7c456fa",
        "type": "sonos-universal",
        "z": "9a5ec889a62524d2",
        "confignode": "88e9fa70.4a53e8",
        "command": "player.set.volume",
        "state": "",
        "stateType": "str",
        "avoidCheckPlayerAvailability": false,
        "name": "Set_Volume",
        "x": 1150,
        "y": 1380,
        "wires": [
            []
        ]
    },
    {
        "id": "10b5d4a54ab907ed",
        "type": "sonos-universal",
        "z": "9a5ec889a62524d2",
        "confignode": "88e9fa70.4a53e8",
        "command": "player.get.volume",
        "state": "",
        "stateType": "str",
        "avoidCheckPlayerAvailability": false,
        "name": "Get_Volume",
        "x": 330,
        "y": 1320,
        "wires": [
            [
                "0bd076aa7ea2c93a"
            ]
        ]
    },
    {
        "id": "4c8391320bf1c703",
        "type": "inject",
        "z": "9a5ec889a62524d2",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payloadType": "date",
        "x": 150,
        "y": 1280,
        "wires": [
            [
                "10b5d4a54ab907ed"
            ]
        ]
    },
    {
        "id": "b12104bd8eeceb0f",
        "type": "mqtt in",
        "z": "9a5ec889a62524d2",
        "name": "zigbee2mqtt/volumeknop_bureau",
        "topic": "zigbee2mqtt/volumeknop_bureau",
        "qos": "2",
        "datatype": "json",
        "broker": "ac0ebf430a1bb8e8",
        "nl": false,
        "rap": true,
        "rh": 0,
        "inputs": 0,
        "x": 290,
        "y": 1380,
        "wires": [
            [
                "067d069d0dc98cf9"
            ]
        ]
    },
    {
        "id": "feecbda41247d1a1",
        "type": "function",
        "z": "9a5ec889a62524d2",
        "name": "Sonos volume",
        "func": "var x = msg.action;\nvar volume=context.get('volume') || 0;\n\nif (x== \"init_volume\") {\n    volume = msg.volume;\n    context.set('volume',volume);\n    }\n\nif (x== \"rotate_right\") {\n    volume +=2;\n     if (volume >= 45) {\n        volume = 45;\n    }\n    msg.payload= volume;\n    context.set('volume',volume);\n    return [msg, null];\n    }\n\nif (x== \"rotate_left\") {\n    volume -=2;\n    if (volume <= 0) {\n        volume = 0;\n    }\n    msg.payload= volume;\n    context.set('volume',volume);\n    return [msg, null];\n    }\n \n //next if is not in use at the moment\nif (x== \"play_pause\") {\n    msg.payload = 'Pushed';\n    return [null, msg];\n    }\n\n\n",
        "outputs": 2,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 940,
        "y": 1380,
        "wires": [
            [
                "6446a526e7c456fa",
                "00406b14dbf0ee06"
            ],
            []
        ]
    },
    {
        "id": "98a7e59c1d6851a3",
        "type": "function",
        "z": "9a5ec889a62524d2",
        "name": "Add msg.action",
        "func": "\nmsg.action = \"init_volume\";\n\nreturn msg",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 740,
        "y": 1320,
        "wires": [
            [
                "feecbda41247d1a1"
            ]
        ]
    },
    {
        "id": "0bd076aa7ea2c93a",
        "type": "change",
        "z": "9a5ec889a62524d2",
        "name": "msg.volume",
        "rules": [
            {
                "t": "move",
                "p": "payload",
                "pt": "msg",
                "to": "volume",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 550,
        "y": 1320,
        "wires": [
            [
                "98a7e59c1d6851a3"
            ]
        ]
    },
    {
        "id": "067d069d0dc98cf9",
        "type": "change",
        "z": "9a5ec889a62524d2",
        "name": "msg.action",
        "rules": [
            {
                "t": "move",
                "p": "payload.action",
                "pt": "msg",
                "to": "action",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 550,
        "y": 1380,
        "wires": [
            [
                "feecbda41247d1a1"
            ]
        ]
    },
    {
        "id": "00406b14dbf0ee06",
        "type": "debug",
        "z": "9a5ec889a62524d2",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 1200,
        "y": 1280,
        "wires": []
    },
    {
        "id": "4c96c05d6c530ab5",
        "type": "harmonyws-server",
        "name": "Woonkamer",
        "ip": "192.168.0.80",
        "debug": false
    },
    {
        "id": "88e9fa70.4a53e8",
        "type": "sonos-config",
        "name": "Sonos_IP",
        "serialnum": "",
        "ipaddress": "192.168.0.111"
    },
    {
        "id": "ac0ebf430a1bb8e8",
        "type": "mqtt-broker",
        "name": "Mqtt",
        "broker": "192.168.0.71",
        "port": "1883",
        "clientid": "",
        "autoConnect": true,
        "usetls": false,
        "protocolVersion": "4",
        "keepalive": "60",
        "cleansession": true,
        "birthTopic": "",
        "birthQos": "0",
        "birthPayload": "",
        "birthMsg": {},
        "closeTopic": "",
        "closeQos": "0",
        "closePayload": "",
        "closeMsg": {},
        "willTopic": "",
        "willQos": "0",
        "willPayload": "",
        "willMsg": {},
        "sessionExpiry": ""
    }
]

Now I'm going to look for a function that can inform me if the sonos his volume has been changed. Because now I'm looking to my harmony, but that is only valid if we use the remote to change the volume. I need to get the info from the source itself. Or I can do a polling every 60 seconds with the get_volume, that will probably also be accurate.

I'm going trough all the info here above, I use node red for some time and manage every time to make what I need, but I want to have it in my fingers and really understand it. In PLC this would have taken me 30 second, now 3 days I believe :stuck_out_tongue:

But how long did it first take you to do things with PLC? Or ride a bike or anything, learning takes some time. When I first sarted with Node-red it took me forever too :grin:

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.