Combine different Input-Node in a Function Node

Hello,

I'm new to the forum and have little experience with NodeRed. I'm working on the topic right now. I currently have a problem.
I would like to send an e-mail, SMS or a WhatsApp message when the trigger node (5 seconds delay) becomes active and the "device presense check" is at 1 and the value of an MQTT message (float) is less than a certain value.

NodeRed_01|690x204

In the first step I wanted to combine the first two nodes with an AND. Didn't work for me, because the AND node probably doesn't get the status of the "DPC" at the time of the trigger (5 seconds) --> Status unknown!

How can I access the status of the other two nodes as soon as the trigger comes and start another action (function node?)?

Best regards, Christoph

Your flow

The three nodes Device Presence Check, mqtt and trigger don't retain a value which the function can consult. Instead a mesage passes from them to the function and is then gone.

So your flow has to save the most recent message from Device Presence Check and mqtt.

Probably the easiest way is to set flow level context variables like this
Suggested variation


Your function nodes can access these like this
let devicepresence = flow.get('devicepresencecheck')
then you can use this variable in your comparison.

An alternative is to use a Join node to combine all three inputs into a single message. It's probably better but I think not as intuitive.

ps The red triangle suggests that your mqtt node is not set up correctly.

1 Like

You can also save the values of the different nodes in the context of the function node and ten compare the values,

Cany ou give me an example for a code of a function node?

Personally I would use a Join node rather than context. See this article in the cookbook for an example of how to join messages into one object.

In a function node - you have your own context - so to keep it easy - I used as context variable name the msg.topic which is topic1, topic2, topic3

If you click on your function node - you can directly see the context variables, which are stored with your function node, when you open your context menu.

So in the debug window you can see how the payload increases with each inject node:

With
context.set (<name>,<value>);

you can store a value, with
context.get (<name>);

you can retrieve your stored value back.

Here is the code of a function node:

context.set(msg.topic, msg.payload);
var valueOfTopic1 = context.get('topic1')||"";
var valueOfTopic2 = context.get('topic2')||"";
var valueOfTopic3 = context.get('topic3')||"";

msg.payload = { topic1: valueOfTopic1,
            topic2: valueOfTopic2,
            topic3: valueOfTopic3 }
return msg;

And here is the flow to test by yourself:

Zusammenfassung
[
    {
        "id": "49aae2568a4a87e0",
        "type": "inject",
        "z": "ebe8134f6b5af26c",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "topic1",
        "payload": "This is a string in topic1",
        "payloadType": "str",
        "x": 600,
        "y": 960,
        "wires": [
            [
                "365882932ba6ac11"
            ]
        ]
    },
    {
        "id": "2572f6e462c6dcc1",
        "type": "inject",
        "z": "ebe8134f6b5af26c",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "topic2",
        "payload": "198745",
        "payloadType": "num",
        "x": 650,
        "y": 1020,
        "wires": [
            [
                "365882932ba6ac11"
            ]
        ]
    },
    {
        "id": "84716c3a07f97e9e",
        "type": "inject",
        "z": "ebe8134f6b5af26c",
        "name": "topic3: An Object",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "topic3",
        "payload": "{\"type\":\"object\",\"name\":\"MyObject\"}",
        "payloadType": "json",
        "x": 640,
        "y": 1080,
        "wires": [
            [
                "365882932ba6ac11"
            ]
        ]
    },
    {
        "id": "365882932ba6ac11",
        "type": "function",
        "z": "ebe8134f6b5af26c",
        "name": "",
        "func": "context.set(msg.topic, msg.payload);\nvar valueOfTopic1 = context.get('topic1')||\"\";\nvar valueOfTopic2 = context.get('topic2')||\"\";\nvar valueOfTopic3 = context.get('topic3')||\"\";\n\nmsg.payload = { topic1: valueOfTopic1,\n            topic2: valueOfTopic2,\n            topic3: valueOfTopic3 }\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 870,
        "y": 1020,
        "wires": [
            [
                "ad257cf107d542c7"
            ]
        ]
    },
    {
        "id": "ad257cf107d542c7",
        "type": "debug",
        "z": "ebe8134f6b5af26c",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 1080,
        "y": 1020,
        "wires": []
    }
]

So in your case - you need to identify the msg object from which node it comes (best is using msg.topic, if there is none - set one with a change node), then you can store the payload with a specific name in the context of your function node - and then you can retrieve the value whenever you need it in your code.

So in my example you can compare the values of the different nodes:

if (valueOfTopic1 === 'hello' && valueOfTopic2 === 7) {
        // ... do something
       msg.payload = "Finally a match!";
}

I am not a friend of function nodes as well - as this contradicts the concept to visualize a program flow. So you can place a complete flow into a function node.

Nevertheless - if someone want to know how it works - I see no problem to explain. There are always more than one way to solve a problem.

But in general I agree with you - and I avoid using function nodes whenever I can.

Particularly when the function node just replicates a core node's operation.

OK - you can do something in addition, i.e. check if all nodes deliver true or something else. Here a context is useful or an internal counter. I am also not a friend of additional nodes when the same result can be achieved with the core nodes. In addition if I look to the posts here, I see 50% of the posts implemented with function nodes - which can be achieved with core nodes as well.

So there are several ways to implement things - and if someone asks for a specific solution, I will provide this solution and then it makes no sense to tell him there are other solutions. In my opinion @Node4Home has 3 ways (join, flow variable or function node) to implement a solution and he/she has the choice now.

I would have a look at this video showing how to kick a whatsapp when an node-red event happens... and how to receive on node-red a response back.

Have a look at the flow code if you need it, it's attached on video description.
:smiley:

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