How can I get the value and not override it again when starting the timer?

Hey!

I may or may not have a rather simple question which I'm a bit stuck on though.
I want to achive a counter, which starts at 5, counts down, if it gets to 0 starts at 5 again and so on.

Now the problem I've is that I'm always setting the value to 0 when starting the timer.
How is it possible to get the value? As I have to declare it somewhere at least.

You could use a function node containing

let value = context.get("value") || 0
if (value <= 0) {
  value = 5
} else {
  value -= 1
}
context.set("value", value)
msg.payload = value
return msg

If you don't want to do it that way then select all the nodes in your flow, export it, and paste it here so we can have a look. When pasting here use the </> at the top of the forum entry window.

[
    {
        "id": "cc95aeca32ce2b12",
        "type": "inject",
        "z": "5d0182bc24cb8af1",
        "name": "timer 10 sec / set value to 0",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "value",
                "v": "0",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 400,
        "y": 1320,
        "wires": [
            [
                "790473c21614a766",
                "bb016360fc96c295"
            ]
        ]
    },
    {
        "id": "790473c21614a766",
        "type": "switch",
        "z": "5d0182bc24cb8af1",
        "name": "value <= 0",
        "property": "value",
        "propertyType": "msg",
        "rules": [
            {
                "t": "lte",
                "v": "0",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 1,
        "x": 670,
        "y": 1260,
        "wires": [
            [
                "ac80c7f88c40c752"
            ]
        ]
    },
    {
        "id": "bb016360fc96c295",
        "type": "switch",
        "z": "5d0182bc24cb8af1",
        "name": "value > 0",
        "property": "value",
        "propertyType": "msg",
        "rules": [
            {
                "t": "gt",
                "v": "0",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 1,
        "x": 660,
        "y": 1440,
        "wires": [
            [
                "4255125a0820bde2"
            ]
        ]
    },
    {
        "id": "856637291ac1484a",
        "type": "debug",
        "z": "5d0182bc24cb8af1",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "value",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 1300,
        "y": 1260,
        "wires": []
    },
    {
        "id": "4255125a0820bde2",
        "type": "function",
        "z": "5d0182bc24cb8af1",
        "name": "value -1",
        "func": "msg.value = msg.value - 1;\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 860,
        "y": 1440,
        "wires": [
            [
                "856637291ac1484a"
            ]
        ]
    },
    {
        "id": "ac80c7f88c40c752",
        "type": "function",
        "z": "5d0182bc24cb8af1",
        "name": "set value to 5",
        "func": "msg.value = 5;\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 930,
        "y": 1260,
        "wires": [
            [
                "856637291ac1484a"
            ]
        ]
    }
]

Thank you! There you go.

You are not saving msg.value in the context, so it is not remembered from one pass to the next. If you look in the function I suggested you will see it is saving it in the node's context so it is available when the next value arrives. For other ways of saving context see Working with context : Node-RED

Thank you! I just solved it like this:

[
    {
        "id": "1fb0dec6ddaa11c1",
        "type": "inject",
        "z": "1b12c10.509463f",
        "name": "timer 10 sec / set value to 0",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "2",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 180,
        "y": 440,
        "wires": [
            [
                "bcbcb32a35d54d5d"
            ]
        ]
    },
    {
        "id": "e331649be74fcc42",
        "type": "switch",
        "z": "1b12c10.509463f",
        "name": "value <= 0",
        "property": "value",
        "propertyType": "msg",
        "rules": [
            {
                "t": "lte",
                "v": "0",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 1,
        "x": 630,
        "y": 380,
        "wires": [
            [
                "f19dfab3736ae2c8"
            ]
        ]
    },
    {
        "id": "bf9305738917358e",
        "type": "switch",
        "z": "1b12c10.509463f",
        "name": "value > 0",
        "property": "value",
        "propertyType": "msg",
        "rules": [
            {
                "t": "gt",
                "v": "0",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 1,
        "x": 520,
        "y": 620,
        "wires": [
            [
                "b29850a155842ee1"
            ]
        ]
    },
    {
        "id": "fa4116889a32f8cf",
        "type": "debug",
        "z": "1b12c10.509463f",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "value",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 1080,
        "y": 380,
        "wires": []
    },
    {
        "id": "bcbcb32a35d54d5d",
        "type": "function",
        "z": "1b12c10.509463f",
        "name": "get value",
        "func": "msg.value = flow.get(\"test\",\"store\");\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 420,
        "y": 440,
        "wires": [
            [
                "e331649be74fcc42",
                "bf9305738917358e"
            ]
        ]
    },
    {
        "id": "f19dfab3736ae2c8",
        "type": "function",
        "z": "1b12c10.509463f",
        "name": "set value to 5",
        "func": "flow.set(\"test\", msg.value = 5, \"store\");\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 810,
        "y": 380,
        "wires": [
            [
                "fa4116889a32f8cf"
            ]
        ]
    },
    {
        "id": "b29850a155842ee1",
        "type": "function",
        "z": "1b12c10.509463f",
        "name": "-1",
        "func": "flow.set(\"test\", msg.value = msg.value - 1, \"store\");\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 770,
        "y": 540,
        "wires": [
            [
                "fa4116889a32f8cf"
            ]
        ]
    }
]

As a matter of interest, why don't you like the function I posted that does it all in one go?

I just simplified my problem a lot in here. I'm working with a few subflows.
Basically what I'm trying to do is go seperate ways.

It goes way1 so to speak, if the given value is 0, calculates everything and returns a bunch of values with a timer. Then way2 activates which repeats for the given time.

Simplified example would be:
Machine is inactive (timer = 0), we start the calculation, tell it what to do and then it runs for the given time. Each minute I then decrement the timer and once the timer runs out, it calculates new things to do and starts again for a random amount of time.

To put it short: I'm just emulating a machine. :slight_smile:

OK. That makes sense.
I think there are a couple of issues with your flow.
In the Switch you are testing against the strings instead of numbers, which means it will be doing alphanumeric tests of the characters rather than testing numbers. I think if you changed the limit to 10 then it would stop working, as "2" is greater "10".

Your two switch nodes can be combined into 1 with two outputs.

image

Thank you for that!

Isn't "msg.value = 5" a number? Or am I getting something mixed up here with the setters and getters?

Here you are comparing to the character "0" not the number 0

image

Should be

image

Also this is rather unusual code, which could cause confusion. Did you intentionally write it like that, even though it could be confusing?

flow.set("test", msg.value = msg.value - 1, "store");

Oh! I didn't even notice that, thank you.

And yeah. I now changed it to:

flow.set("timer", msg.value = msg.value - 1)

Not sure if that is any better though.

That is perfectly legal javascript. The code msg.value = msg.value-1 calculates msg.value-1 and sets msg.value to the result of the subtraction. Because, in javascript the result of an assignment is also the value of the left hand side of that assignment, then this value is also passed to the function flow.set().

Personally I avoid using that construct as it is more commonly used as something like
flow.set("timer", value1 == value2)
which compares value1 to value2 giving true or false, and that is what is passed to the function.

So myself I would have used
msg.value = msg.value - 1
flow.set( "timer", msg.value )
just because I find it easier to understand. As I said there is nothing wrong with your syntax though.

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