Count messages // do something // reset // howt to simplify flow

I have a home assistant feature that does fail sometimes at the first command, so i wanted a flow that when this happens there are 3 retries before another action takes place (msg + restart application).

I've cobbled something together with info found on the forum, but i'm sure there are more simple ways of building this. Any input would be welcome.

[
    {
        "id": "a7c11995713d7dca",
        "type": "tab",
        "label": "Flow 2",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "f6f2ab575394f14f",
        "type": "inject",
        "z": "a7c11995713d7dca",
        "name": "",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "test",
        "payloadType": "str",
        "x": 370,
        "y": 340,
        "wires": [
            [
                "d83f8261fda92a3e"
            ]
        ]
    },
    {
        "id": "d83f8261fda92a3e",
        "type": "api-call-service",
        "z": "a7c11995713d7dca",
        "name": "action",
        "server": "43edf570.794d9c",
        "version": 5,
        "debugenabled": false,
        "domain": "switch",
        "service": "turn_off",
        "areaId": [],
        "deviceId": [],
        "entityId": [
            "switch.plugbeneden_wekkerd_5"
        ],
        "data": "",
        "dataType": "jsonata",
        "mergeContext": "",
        "mustacheAltTags": false,
        "outputProperties": [],
        "queue": "none",
        "x": 610,
        "y": 340,
        "wires": [
            [
                "55e53661163af3fc"
            ]
        ]
    },
    {
        "id": "d441858f37d90197",
        "type": "function",
        "z": "a7c11995713d7dca",
        "name": "count to 3 send close",
        "func": "\nlet msgCount = flow.get(\"msgCount\") || 0;//get remembered count\nlet sendMessage = false;\nlet countMessage = \"\";\nmsgCount++; //increment count\n\ncountMessage = \"Count of payload 1: \" + msgCount;\n\nif (msgCount >= 3)  {\n    msgCount = 0;//reset counter\n    sendMessage = true;//instruct code to send the msg\n    msg.topic = \"control\";\n    msg.payload = \"close\"; //set payload to a string of \"1\" as you requested\n}\n\nflow.set(\"msgCount\", msgCount); //remember count\nnode.status(countMessage);\nlet msgWithCount = { payload: countMessage };\n\nif(sendMessage) {\n    return [msg, msgWithCount];\n} else {\n    return [null, msgWithCount];\n}\n\n\n\n",
        "outputs": 2,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 680,
        "y": 460,
        "wires": [
            [
                "a51a482896d5908a",
                "e3994347eb9acb5b"
            ],
            [
                "011f256f4332d61f"
            ]
        ]
    },
    {
        "id": "a51a482896d5908a",
        "type": "gate",
        "z": "a7c11995713d7dca",
        "name": "",
        "controlTopic": "control",
        "defaultState": "open",
        "openCmd": "open",
        "closeCmd": "close",
        "toggleCmd": "toggle",
        "defaultCmd": "default",
        "statusCmd": "status",
        "persist": false,
        "storeName": "memory",
        "x": 1090,
        "y": 360,
        "wires": [
            [
                "d441858f37d90197"
            ]
        ]
    },
    {
        "id": "011f256f4332d61f",
        "type": "delay",
        "z": "a7c11995713d7dca",
        "name": "",
        "pauseType": "delay",
        "timeout": "3",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 360,
        "y": 400,
        "wires": [
            [
                "d83f8261fda92a3e"
            ]
        ]
    },
    {
        "id": "e3994347eb9acb5b",
        "type": "delay",
        "z": "a7c11995713d7dca",
        "name": "",
        "pauseType": "delay",
        "timeout": "5",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 1080,
        "y": 460,
        "wires": [
            [
                "76ec6703b51d4db9"
            ]
        ]
    },
    {
        "id": "76ec6703b51d4db9",
        "type": "change",
        "z": "a7c11995713d7dca",
        "name": "",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "open",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "topic",
                "pt": "msg",
                "to": "control",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 1280,
        "y": 460,
        "wires": [
            [
                "a51a482896d5908a",
                "fd43bb5041e3bf12"
            ]
        ]
    },
    {
        "id": "fd43bb5041e3bf12",
        "type": "change",
        "z": "a7c11995713d7dca",
        "name": "Msg",
        "rules": [
            {
                "t": "set",
                "p": "title",
                "pt": "msg",
                "to": "Rc35 day mode not activated",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "message1",
                "pt": "msg",
                "to": "Check ems!",
                "tot": "str",
                "dc": true
            },
            {
                "t": "set",
                "p": "message2",
                "pt": "msg",
                "to": "   ",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "message3",
                "pt": "msg",
                "to": "",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "sound",
                "pt": "msg",
                "to": "",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "critical",
                "pt": "msg",
                "to": "0",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "volume",
                "pt": "msg",
                "to": "1",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "target",
                "pt": "msg",
                "to": "mobile_app_davids_iphone",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 1510,
        "y": 460,
        "wires": [
            [
                "e3ebcd14fc372a41"
            ]
        ]
    },
    {
        "id": "e3ebcd14fc372a41",
        "type": "link out",
        "z": "a7c11995713d7dca",
        "name": "link out 161",
        "mode": "link",
        "links": [
            "6ee3f7c73fa6aab3"
        ],
        "x": 1635,
        "y": 460,
        "wires": []
    },
    {
        "id": "55e53661163af3fc",
        "type": "api-current-state",
        "z": "a7c11995713d7dca",
        "name": "control action on?",
        "server": "43edf570.794d9c",
        "version": 3,
        "outputs": 2,
        "halt_if": "on",
        "halt_if_type": "str",
        "halt_if_compare": "is",
        "entity_id": "switch.plugbeneden_wekkerd_5",
        "state_type": "str",
        "blockInputOverrides": false,
        "outputProperties": [],
        "for": "0",
        "forType": "num",
        "forUnits": "minutes",
        "override_topic": false,
        "state_location": "payload",
        "override_payload": "msg",
        "entity_location": "data",
        "override_data": "msg",
        "x": 810,
        "y": 320,
        "wires": [
            [
                "6bfe3823fd554214",
                "ae857c9227626769"
            ],
            [
                "a51a482896d5908a",
                "b9ee918c4adb69da"
            ]
        ]
    },
    {
        "id": "6bfe3823fd554214",
        "type": "debug",
        "z": "a7c11995713d7dca",
        "name": "All Ok = do something // set counter to 0",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 1180,
        "y": 280,
        "wires": []
    },
    {
        "id": "b9ee918c4adb69da",
        "type": "debug",
        "z": "a7c11995713d7dca",
        "name": "Not ok = repeat message 3 times // then other action",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 1220,
        "y": 320,
        "wires": []
    },
    {
        "id": "ae857c9227626769",
        "type": "function",
        "z": "a7c11995713d7dca",
        "name": "reset counter to 0 if all ok",
        "func": "var count = flow.get(\"msgCount\") || 0;\nflow.set(\"msgCount\", 0);\nmsg.payload = \"counter set to \" + count;\nreturn msg; ",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1130,
        "y": 240,
        "wires": [
            []
        ]
    },
    {
        "id": "a9facd51c3fa600b",
        "type": "inject",
        "z": "a7c11995713d7dca",
        "name": "reset counter",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 850,
        "y": 240,
        "wires": [
            [
                "ae857c9227626769"
            ]
        ]
    },
    {
        "id": "43edf570.794d9c",
        "type": "server",
        "name": "Home Assistant",
        "version": 5,
        "addon": false,
        "rejectUnauthorizedCerts": true,
        "ha_boolean": "y|yes|true|on|home|open",
        "connectionDelay": true,
        "cacheJson": true,
        "heartbeat": false,
        "heartbeatInterval": "30",
        "areaSelector": "friendlyName",
        "deviceSelector": "friendlyName",
        "entitySelector": "friendlyName",
        "statusSeparator": "at: ",
        "statusYear": "hidden",
        "statusMonth": "short",
        "statusDay": "numeric",
        "statusHourCycle": "h23",
        "statusTimeFormat": "h:m",
        "enableGlobalContextStore": true
    }
]

I see 3 loops in your flow, why is everything related to home assistant so overly complex ? That is how it appears to me at least.

that does fail sometimes at the first command

Shouldn't you figure out first why this happens in the first place?

Why not chain 3 "action" nodes to each other with a switch node in between ? (if else)

It's a "problem" with an ems-esp gateway that is known to "stall" if that happens i need to send some commands to get it up and running again. At the moment no other way round.

the overly complex part may be on my side, i'm slowly learning to understand node red and some code.

I'll look into your suggestion, thanks!

I've make a sketch of your proposal, but, im unclear howto
resend the message 3 times and the stop the loop.

Also do not know howto setup a switch node for this situation.

Sorry, but this node may be helpful for counting things happening.

Very simplistic, make a literal flow that performs the action 3 times, you can put a delay between them if needed:

and the switch nodes are configured something like (i dont know what payload the action nodes produce).

So if it is off, it goes to output 1, if it is on, it goes to output 2.
No complicated loops and counters and the flow is readable.

Thanks all for the input!

will get at it.