On and off random for 2 Relays alternating

Hi
I am trying to send to mqtt a random on and off for two relays.
I tried to work with delay random delay. But this succeeds me only once and then stopped.
I want to send random on and off as long as an action is active, for example, a switch is pressed and sends a HIGH signal to Node Red at mqtt until the switch goes LOW.
The time should be between 1 and 10 seconds for Relay 1 on and 10 to 20 seconds for off then 1 to 10 seconds for Relay 2 on nd 10 to 20 seconds for off . After that its starts up again with new random times
My flow has become huge, but without function. It was only on and off once,
So I deleted the flow and don't quite know how to start over.
Does anyone have a start idea for me?
PS it is for our cat, a motor turns right, stop, left, stop ... and spins a string with a PingPong ball
(one esp with two relays and one 5V motor with power bank)

Try this

[{"id":"fad11015.7984b","type":"inject","z":"c791cbc0.84f648","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"1","payloadType":"num","x":110,"y":420,"wires":[["fb28ca81.e16f18","2ebc1b8e.1a0274"]]},{"id":"fb28ca81.e16f18","type":"change","z":"c791cbc0.84f648","name":"","rules":[{"t":"set","p":"run","pt":"flow","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":320,"y":420,"wires":[[]]},{"id":"2ebc1b8e.1a0274","type":"switch","z":"c791cbc0.84f648","name":"","property":"run","propertyType":"flow","rules":[{"t":"true"}],"checkall":"true","repair":false,"outputs":1,"x":120,"y":560,"wires":[["fa90369e.a1fc5","7e8b7956.9d387"]]},{"id":"fa90369e.a1fc5","type":"delay","z":"c791cbc0.84f648","name":"","pauseType":"random","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"10","randomUnits":"seconds","drop":false,"x":280,"y":540,"wires":[["c772d719.50d3f"]]},{"id":"7e8b7956.9d387","type":"delay","z":"c791cbc0.84f648","name":"","pauseType":"random","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"10","randomLast":"20","randomUnits":"seconds","drop":false,"x":280,"y":580,"wires":[["aeef98a5.998688"]]},{"id":"662e7912.c9006","type":"change","z":"c791cbc0.84f648","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"off","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":680,"wires":[["fc4dc31.4f2734","2ebc1b8e.1a0274"]]},{"id":"c772d719.50d3f","type":"change","z":"c791cbc0.84f648","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"on","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":460,"y":540,"wires":[["9f49d03c.0a3c08"]]},{"id":"aeef98a5.998688","type":"change","z":"c791cbc0.84f648","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"off","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":460,"y":580,"wires":[["9f49d03c.0a3c08","429b5b71.3e758c"]]},{"id":"4fb70ce.a38cff4","type":"delay","z":"c791cbc0.84f648","name":"","pauseType":"random","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"10","randomLast":"20","randomUnits":"seconds","drop":false,"x":300,"y":680,"wires":[["662e7912.c9006"]]},{"id":"fc4dc31.4f2734","type":"debug","z":"c791cbc0.84f648","name":"relay 2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":660,"y":640,"wires":[]},{"id":"9f49d03c.0a3c08","type":"debug","z":"c791cbc0.84f648","name":"relay 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":650,"y":540,"wires":[]},{"id":"429b5b71.3e758c","type":"change","z":"c791cbc0.84f648","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"1","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":120,"y":660,"wires":[["40cc56a9.d3527","4fb70ce.a38cff4"]]},{"id":"19d6f4f7.01733b","type":"change","z":"c791cbc0.84f648","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"on","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":640,"wires":[["fc4dc31.4f2734"]]},{"id":"40cc56a9.d3527","type":"delay","z":"c791cbc0.84f648","name":"","pauseType":"random","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"10","randomUnits":"seconds","drop":false,"x":300,"y":640,"wires":[["19d6f4f7.01733b"]]}]

Here's one using Javascript timers

[{"id":"af0a9d8da81b8c4c","type":"inject","z":"54efb553244c241f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":230,"y":960,"wires":[["8c3cb7d2479c90df"]]},{"id":"8c3cb7d2479c90df","type":"function","z":"54efb553244c241f","name":"Timers","func":"\nfunction run() {\n\n     node.status({ fill: \"yellow\", shape: \"dot\", text: \"Waiting\" });\n\n    let direction = [\"left\", \"right\"]\n\n    let randomDirection = direction[(Math.random() > 0.5) ? 1 : 0]\n    let delayOn = Math.random() * 10 + 1\n    let delayOff = Math.random() * 20\n\n\n    // delay on\n\n    flow.set(\"timer\", setTimeout(() => {\n\n        node.status({ fill: \"green\", shape: \"dot\", text: \"Running\" });\n\n        node.send({\n            payload: {\n                direction: randomDirection,\n                action: \"on\",\n                delayOn: delayOn\n\n            }\n        })\n\n        // execute stop timer\n        setTimeout(() => {\n\n            node.send({\n                payload: {\n                    direction: randomDirection,\n                    action: \"off\",\n                    delayOff: delayOff\n                }\n            })\n\n            node.status({ fill: \"red\", shape: \"dot\", text: \"Stopped\" });\n            if (flow.get(\"timer\")) run() // run again\n\n\n        }, delayOff * 1000)\n\n    }, delayOn * 1000))\n\n}\n\n\n\nif (msg.payload === true) {\n    // execute run timer\n    run()\n}\n\nelse {\n\n    flow.set(\"timer\", undefined)\n    node.status({ fill: \"red\", shape: \"dot\", text: \"Stopped\" });\n    // immediate off for both relays\n    node.send({ payload: { direction: \"left\", action: \"off\" } })\n    node.send({ payload: { direction: \"right\", action: \"off\" } })\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":430,"y":1000,"wires":[["8d9da4ca014bd9f3"]]},{"id":"e2c946ec0c352dac","type":"debug","z":"54efb553244c241f","name":"left","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":790,"y":960,"wires":[]},{"id":"8d9da4ca014bd9f3","type":"switch","z":"54efb553244c241f","name":"","property":"payload.direction","propertyType":"msg","rules":[{"t":"eq","v":"left","vt":"str"},{"t":"eq","v":"right","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":610,"y":1000,"wires":[["e2c946ec0c352dac"],["01a8e7444a092f54"]]},{"id":"01a8e7444a092f54","type":"debug","z":"54efb553244c241f","name":"right","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":790,"y":1040,"wires":[]},{"id":"533c94c062da7e24","type":"inject","z":"54efb553244c241f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"false","payloadType":"bool","x":230,"y":1040,"wires":[["8c3cb7d2479c90df"]]}]

You can create random numbers and then assign them to msg.delay.

Here some examples how to create random numbers with change nodes.

[
    {
        "id": "cf9437a2.6f4e28",
        "type": "change",
        "z": "6e170384.60c96c",
        "name": "random 0 bis 1",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "$random()\t",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 2840,
        "y": 4740,
        "wires": [
            [
                "1e12a8ad.6d58c7"
            ]
        ]
    },
    {
        "id": "1e12a8ad.6d58c7",
        "type": "debug",
        "z": "6e170384.60c96c",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 3040,
        "y": 4740,
        "wires": []
    },
    {
        "id": "93e67048.2221f",
        "type": "comment",
        "z": "6e170384.60c96c",
        "name": "Generiere Zufallszahl - Random Number",
        "info": "",
        "x": 2610,
        "y": 4700,
        "wires": []
    },
    {
        "id": "37082ffe.cf76e",
        "type": "inject",
        "z": "6e170384.60c96c",
        "name": "",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "true",
        "payloadType": "bool",
        "x": 2590,
        "y": 4800,
        "wires": [
            [
                "cf9437a2.6f4e28",
                "549fc585.2111bc",
                "5d41aaf4.bd9054"
            ]
        ]
    },
    {
        "id": "549fc585.2111bc",
        "type": "change",
        "z": "6e170384.60c96c",
        "name": "random posivtive Integer",
        "rules": [
            {
                "t": "set",
                "p": "range",
                "pt": "msg",
                "to": "100",
                "tot": "num"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "$round($random()*range, 0)\t",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 2870,
        "y": 4800,
        "wires": [
            [
                "80b2b15c.ca261"
            ]
        ]
    },
    {
        "id": "80b2b15c.ca261",
        "type": "debug",
        "z": "6e170384.60c96c",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 3130,
        "y": 4800,
        "wires": []
    },
    {
        "id": "5d41aaf4.bd9054",
        "type": "change",
        "z": "6e170384.60c96c",
        "name": "random posivtive  & negative Integer ",
        "rules": [
            {
                "t": "set",
                "p": "range",
                "pt": "msg",
                "to": "200",
                "tot": "num"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "$round(($random()-0.5)*range, 0)\t",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 2860,
        "y": 4860,
        "wires": [
            [
                "edfdace1.58a73"
            ]
        ]
    },
    {
        "id": "edfdace1.58a73",
        "type": "debug",
        "z": "6e170384.60c96c",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 3130,
        "y": 4860,
        "wires": []
    }
]

or you use the random number function within the delay nodes - as posted from @E1cid

WAU!
I have thought much too complicated. I would never have come up with this solution.
@UnborN
I find your solution super minimalistic and clear.
Most part of the function I have understood.
But I have a question about line 6 and 7:

let direction = ["left", "right"]
    let randomDirection = direction[(Math.random() > 0.5) ? 1 : 0]

My programming knowledge is not sufficient for this.
You write random direction, but it always comes out left right.
I think random would be a great addition, I never dreamed that far.
Can you explain line 7 to me?
@ ALL
I thank all the others for the ideas. That shows that many roads brings you to Rome, mine woud be the detour over the moon and i can arrived some time, but never so perfect as with you.
Thanks for this

1 Like

Line 6 sets up a new array (direction) which contains "left" and "right" - so direction[0] is "left" and direction[1] is "right".
Line 7 then sets randomDirection to one of those values... this is decided by the so-called ternary expression in the . the general form of a ternary expression is

some test   ?  result if test is true :  result if test is false ; 

so in this case the test is is Math.random() greater than 0.5 ... if so then return 1 - which then means direction[1] which is "right", otherwise return 0 - which then becomes "left".

Another way to do it without the ternary test would be

let randomDirection = direction[ Math.round(Math.random() ) ]

which uses the .round function to round the random number between 0 and 1 to either 0 (rounded down) or 1 (rounded up)... but yet another road to Rome :slight_smile:

Or then again - maybe without the array... but with the ternary

let randomDirection = (Math.random() > 0.5) ? "right" : "left";
2 Likes

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