"Art" of the sequence, a Node-RED retrospective

I needed a motion lighting flow that respected manually controlling the lights. Along with usual time of day, illuminance filters. I wasn't being very successful, so Googling around I found an example from a HA user. It uses a node called a finite state machine. It takes a little bit to understand if you are not a programmer, but it's not that conceptually difficult. Basically the flow chooses a path based on triggers, current state, and future state. There's a lot more at the original reddit post.

Flow JSON:

Summary
[
{
    "id": "cd2e24c3.24164",
    "type": "state-machine",
    "z": "32054f7b.6f13c",
    "name": "",
    "triggerProperty": "payload",
    "triggerPropertyType": "msg",
    "stateProperty": "payload",
    "statePropertyType": "msg",
    "outputStateChangeOnly": true,
    "throwException": false,
    "states": [
        "switch",
        "motion-detected",
        "motion-on",
        "motion-off",
        "off",
        "on"
    ],
    "transitions": [
        {
            "name": "motion",
            "from": "off",
            "to": "motion-detected"
        },
        {
            "name": "motion",
            "from": "motion-on",
            "to": "motion-on"
        },
        {
            "name": "off",
            "from": "*",
            "to": "off"
        },
        {
            "name": "on",
            "from": "*",
            "to": "on"
        },
        {
            "name": "switch",
            "from": "off",
            "to": "switch"
        },
        {
            "name": "switch",
            "from": "on",
            "to": "switch"
        },
        {
            "name": "switch",
            "from": "switch",
            "to": "switch"
        },
        {
            "name": "switch",
            "from": "motion-on",
            "to": "switch"
        },
        {
            "name": "motion-on",
            "from": "motion-detected",
            "to": "motion-on"
        },
        {
            "name": "motion-off",
            "from": "motion-on",
            "to": "motion-off"
        }
    ],
    "x": 460,
    "y": 360,
    "wires": [
        [
            "e4bc4a4c.a41c88",
            "360cbf98.e378a8",
            "56259156.cacac",
            "3abe544f.9780ec"
        ]
    ]
},
{
    "id": "2e7249fe.b79626",
    "type": "change",
    "z": "32054f7b.6f13c",
    "name": "switch",
    "rules": [
        {
            "t": "set",
            "p": "payload",
            "pt": "msg",
            "to": "switch",
            "tot": "str"
        }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 270,
    "y": 400,
    "wires": [
        [
            "cd2e24c3.24164"
        ]
    ]
},
{
    "id": "81b55db6.ac465",
    "type": "change",
    "z": "32054f7b.6f13c",
    "name": "motion",
    "rules": [
        {
            "t": "set",
            "p": "payload",
            "pt": "msg",
            "to": "motion",
            "tot": "str"
        }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 270,
    "y": 360,
    "wires": [
        [
            "cd2e24c3.24164"
        ]
    ]
},
{
    "id": "e0147903.1a0668",
    "type": "stoptimer",
    "z": "32054f7b.6f13c",
    "duration": "2",
    "units": "Minute",
    "payloadtype": "num",
    "payloadval": "0",
    "name": "pause detection",
    "x": 860,
    "y": 540,
    "wires": [
        [
            "9d1eb16.c4c095"
        ],
        []
    ]
},
{
    "id": "18468b2f.edbca5",
    "type": "change",
    "z": "32054f7b.6f13c",
    "name": "stop",
    "rules": [
        {
            "t": "set",
            "p": "payload",
            "pt": "msg",
            "to": "stop",
            "tot": "str"
        }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 830,
    "y": 480,
    "wires": [
        [
            "786d7e71.4c4598"
        ]
    ]
},
{
    "id": "70df8219.d66544",
    "type": "change",
    "z": "32054f7b.6f13c",
    "name": "motion-on",
    "rules": [
        {
            "t": "set",
            "p": "payload",
            "pt": "msg",
            "to": "motion-on",
            "tot": "str"
        }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 1250,
    "y": 300,
    "wires": [
        [
            "81434535.f6326"
        ]
    ]
},
{
    "id": "9fdf23ab.1043a8",
    "type": "change",
    "z": "32054f7b.6f13c",
    "name": "motion-off",
    "rules": [
        {
            "t": "set",
            "p": "payload",
            "pt": "msg",
            "to": "motion-off",
            "tot": "str"
        }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 1250,
    "y": 360,
    "wires": [
        [
            "81434535.f6326"
        ]
    ]
},
{
    "id": "b0621693.6aa238",
    "type": "stoptimer",
    "z": "32054f7b.6f13c",
    "duration": "1",
    "units": "Second",
    "payloadtype": "num",
    "payloadval": "0",
    "name": "pause",
    "x": 1030,
    "y": 420,
    "wires": [
        [
            "9d1eb16.c4c095"
        ],
        []
    ]
},
{
    "id": "da08aec3.d749a",
    "type": "stoptimer",
    "z": "32054f7b.6f13c",
    "duration": "1",
    "units": "Second",
    "payloadtype": "num",
    "payloadval": "0",
    "name": "pause",
    "x": 1030,
    "y": 300,
    "wires": [
        [
            "70df8219.d66544"
        ],
        []
    ]
},
{
    "id": "1f3745d7.2e5fa2",
    "type": "inject",
    "z": "32054f7b.6f13c",
    "name": "steady-state",
    "topic": "",
    "payload": "stop",
    "payloadType": "str",
    "repeat": "",
    "crontab": "",
    "once": true,
    "onceDelay": 0.1,
    "x": 1070,
    "y": 620,
    "wires": [
        [
            "e0147903.1a0668",
            "9d1eb16.c4c095"
        ]
    ]
},
{
    "id": "e7869b10.0f8bf",
    "type": "inject",
    "z": "32054f7b.6f13c",
    "name": "",
    "topic": "",
    "payload": "simulate",
    "payloadType": "str",
    "repeat": "",
    "crontab": "",
    "once": false,
    "onceDelay": 0.1,
    "x": 100,
    "y": 340,
    "wires": [
        [
            "81b55db6.ac465"
        ]
    ]
},
{
    "id": "e4bc4a4c.a41c88",
    "type": "switch",
    "z": "32054f7b.6f13c",
    "name": "motion-detected",
    "property": "payload",
    "propertyType": "msg",
    "rules": [
        {
            "t": "eq",
            "v": "motion-detected",
            "vt": "str"
        }
    ],
    "checkall": "true",
    "repair": false,
    "outputs": 1,
    "x": 690,
    "y": 300,
    "wires": [
        [
            "76ef38e1.e0c138"
        ]
    ]
},
{
    "id": "360cbf98.e378a8",
    "type": "switch",
    "z": "32054f7b.6f13c",
    "name": "motion-on",
    "property": "payload",
    "propertyType": "msg",
    "rules": [
        {
            "t": "eq",
            "v": "motion-on",
            "vt": "str"
        }
    ],
    "checkall": "true",
    "repair": false,
    "outputs": 1,
    "x": 670,
    "y": 360,
    "wires": [
        [
            "786d7e71.4c4598"
        ]
    ]
},
{
    "id": "b1cbc49a.9cd008",
    "type": "link in",
    "z": "32054f7b.6f13c",
    "name": "kitchen state machine",
    "links": [
        "81434535.f6326"
    ],
    "x": 355,
    "y": 300,
    "wires": [
        [
            "cd2e24c3.24164"
        ]
    ]
},
{
    "id": "81434535.f6326",
    "type": "link out",
    "z": "32054f7b.6f13c",
    "name": "kitchen state machine",
    "links": [
        "b1cbc49a.9cd008"
    ],
    "x": 1455,
    "y": 320,
    "wires": []
},
{
    "id": "56259156.cacac",
    "type": "switch",
    "z": "32054f7b.6f13c",
    "name": "switch",
    "property": "payload",
    "propertyType": "msg",
    "rules": [
        {
            "t": "eq",
            "v": "switch",
            "vt": "str"
        }
    ],
    "checkall": "true",
    "repair": false,
    "outputs": 1,
    "x": 650,
    "y": 480,
    "wires": [
        [
            "18468b2f.edbca5",
            "e0147903.1a0668"
        ]
    ]
},
{
    "id": "3abe544f.9780ec",
    "type": "switch",
    "z": "32054f7b.6f13c",
    "name": "motion-off",
    "property": "payload",
    "propertyType": "msg",
    "rules": [
        {
            "t": "eq",
            "v": "motion-off",
            "vt": "str"
        }
    ],
    "checkall": "true",
    "repair": false,
    "outputs": 1,
    "x": 670,
    "y": 420,
    "wires": [
        [
            "e4033469.c56598"
        ]
    ]
},
{
    "id": "786d7e71.4c4598",
    "type": "stoptimer",
    "z": "32054f7b.6f13c",
    "duration": "2",
    "units": "Minute",
    "payloadtype": "num",
    "payloadval": "0",
    "name": "",
    "x": 1060,
    "y": 360,
    "wires": [
        [
            "9fdf23ab.1043a8"
        ],
        []
    ]
},
{
    "id": "b7009f7c.1475a8",
    "type": "hubitat device",
    "z": "32054f7b.6f13c",
    "name": "Motion Sensor",
    "server": "d0c8b8e.6894848",
    "deviceId": "2695",
    "attribute": "motion",
    "sendEvent": true,
    "x": 100,
    "y": 40,
    "wires": [
        [
            "a10c31d7.2a55a8"
        ]
    ]
},
{
    "id": "8b7bf52b.866948",
    "type": "hubitat device",
    "z": "32054f7b.6f13c",
    "name": "DR Lights",
    "server": "d0c8b8e.6894848",
    "deviceId": "7",
    "attribute": "switch",
    "sendEvent": true,
    "x": 80,
    "y": 420,
    "wires": [
        [
            "2e7249fe.b79626"
        ]
    ]
},
{
    "id": "76ef38e1.e0c138",
    "type": "hubitat command",
    "z": "32054f7b.6f13c",
    "name": "DR Lights On",
    "server": "d0c8b8e.6894848",
    "deviceId": "7",
    "command": "on",
    "commandArgs": "",
    "x": 880,
    "y": 300,
    "wires": [
        [
            "da08aec3.d749a"
        ]
    ]
},
{
    "id": "e4033469.c56598",
    "type": "hubitat command",
    "z": "32054f7b.6f13c",
    "name": "DR Lights Off",
    "server": "d0c8b8e.6894848",
    "deviceId": "7",
    "command": "off",
    "commandArgs": "",
    "x": 880,
    "y": 420,
    "wires": [
        [
            "b0621693.6aa238"
        ]
    ]
},
{
    "id": "9d1eb16.c4c095",
    "type": "hubitat device",
    "z": "32054f7b.6f13c",
    "name": "DR Lights",
    "server": "d0c8b8e.6894848",
    "deviceId": "7",
    "attribute": "switch",
    "sendEvent": false,
    "x": 1240,
    "y": 440,
    "wires": [
        [
            "e12d195c.ce2e9"
        ]
    ]
},
{
    "id": "e12d195c.ce2e9",
    "type": "change",
    "z": "32054f7b.6f13c",
    "name": "DR Lights State",
    "rules": [
        {
            "t": "set",
            "p": "payload",
            "pt": "msg",
            "to": "payload.value",
            "tot": "msg"
        }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 1340,
    "y": 500,
    "wires": [
        [
            "81434535.f6326"
        ]
    ]
},
{
    "id": "e64c4e31.36aaf8",
    "type": "time-range-switch",
    "z": "32054f7b.6f13c",
    "name": "",
    "lat": "",
    "lon": "",
    "startTime": "06:00",
    "endTime": "22:00",
    "startOffset": 0,
    "endOffset": 0,
    "x": 300,
    "y": 140,
    "wires": [
        [
            "aec70c57.f1e2d8"
        ],
        []
    ]
},
{
    "id": "afbbd0dd.bb8b38",
    "type": "hubitat device",
    "z": "32054f7b.6f13c",
    "name": "Lux - Back Entrance",
    "server": "d0c8b8e.6894848",
    "deviceId": "1579",
    "attribute": "illuminance",
    "sendEvent": false,
    "x": 320,
    "y": 200,
    "wires": [
        [
            "ec312867.891898"
        ]
    ]
},
{
    "id": "3b7e53e0.d21554",
    "type": "change",
    "z": "32054f7b.6f13c",
    "name": "Lux Blocked?",
    "rules": [
        {
            "t": "set",
            "p": "lux_block",
            "pt": "flow",
            "to": "0",
            "tot": "num"
        }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 660,
    "y": 200,
    "wires": [
        [
            "d768f4ca.32357"
        ]
    ]
},
{
    "id": "aec70c57.f1e2d8",
    "type": "switch",
    "z": "32054f7b.6f13c",
    "name": "",
    "property": "payload",
    "propertyType": "msg",
    "rules": [
        {
            "t": "nempty"
        }
    ],
    "checkall": "true",
    "repair": false,
    "outputs": 1,
    "x": 490,
    "y": 140,
    "wires": [
        [
            "aa9f4f85.57da7"
        ]
    ]
},
{
    "id": "aa9f4f85.57da7",
    "type": "change",
    "z": "32054f7b.6f13c",
    "name": "Time Blocked?",
    "rules": [
        {
            "t": "set",
            "p": "time_block",
            "pt": "flow",
            "to": "0",
            "tot": "num"
        }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 660,
    "y": 140,
    "wires": [
        [
            "d768f4ca.32357"
        ]
    ]
},
{
    "id": "ec312867.891898",
    "type": "switch",
    "z": "32054f7b.6f13c",
    "name": "",
    "property": "payload.value",
    "propertyType": "msg",
    "rules": [
        {
            "t": "lt",
            "v": "43",
            "vt": "num"
        }
    ],
    "checkall": "true",
    "repair": false,
    "outputs": 1,
    "x": 490,
    "y": 200,
    "wires": [
        [
            "3b7e53e0.d21554"
        ]
    ]
},
{
    "id": "d768f4ca.32357",
    "type": "function",
    "z": "32054f7b.6f13c",
    "name": "Blocked?",
    "func": "var a= flow.get('time_block')\nvar b= flow.get('lux_block')\nmsg.payload = a+b\nreturn msg;",
    "outputs": 1,
    "noerr": 0,
    "x": 860,
    "y": 160,
    "wires": [
        [
            "1c635c36.ad33ec"
        ]
    ]
},
{
    "id": "a10c31d7.2a55a8",
    "type": "switch",
    "z": "32054f7b.6f13c",
    "name": "Active?",
    "property": "payload.value",
    "propertyType": "msg",
    "rules": [
        {
            "t": "eq",
            "v": "active",
            "vt": "str"
        }
    ],
    "checkall": "true",
    "repair": false,
    "outputs": 1,
    "x": 280,
    "y": 40,
    "wires": [
        [
            "e64c4e31.36aaf8",
            "afbbd0dd.bb8b38"
        ]
    ]
},
{
    "id": "1c635c36.ad33ec",
    "type": "switch",
    "z": "32054f7b.6f13c",
    "name": "Blocked =0",
    "property": "payload",
    "propertyType": "msg",
    "rules": [
        {
            "t": "eq",
            "v": "0",
            "vt": "num"
        }
    ],
    "checkall": "true",
    "repair": false,
    "outputs": 1,
    "x": 1010,
    "y": 160,
    "wires": [
        [
            "81b55db6.ac465"
        ]
    ]
},
{
    "id": "4ccc06b2.f00188",
    "type": "comment",
    "z": "32054f7b.6f13c",
    "name": "Check filters",
    "info": "",
    "x": 90,
    "y": 120,
    "wires": []
},
{
    "id": "1578ab31.0d2b6d",
    "type": "comment",
    "z": "32054f7b.6f13c",
    "name": "Control the lights",
    "info": "",
    "x": 100,
    "y": 280,
    "wires": []
},
{
    "id": "d0c8b8e.6894848",
    "type": "hubitat config",
    "z": "",
    "name": "Hubitat",
    "usetls": false,
    "host": "192.168.1.17",
    "port": "80",
    "token": "e5653e7e-56a0-43fc-8e19-96a6d9f22711",
    "appId": "2834",
    "nodeRedServer": "http://192.168.1.10:1882",
    "webhookPath": "/hubitat/webhook"
}]
2 Likes

So that is cool - thx for the state machine node! Have to check it out.

Also for your function node.. try this one instead (function nodes are not efficient due to the way they sandbox) or recreate using core nodes.

1 Like

One more... so this is my simple motion disable.. for my use-case. I use a virtual switch in HE that enables or disables the timeout then control via external sequences like timers etc that enable/disable. Thanks to the NR for HE updates I can now test for physical switch and set disable as needed.

I call this the "stick"... :grinning: - which at the present time of the screenshot the motion detect is disabled due to a time constraint.

  • Armada

This one is receiving all of the data from an EcoWitt GW1000 for the sensors on the outdoors PWS, add-on temp/humidity sensors around the house, PM 2.5 sensors, soil moisture sensors, etc. Each has a debug to enable disable to validate a message is being received and then passed to RBE to prevent duplicate noise finally passed to MQTT which is then used elsewhere. Not complex at all. Just a whole lot of sensors!

2 Likes

Nice! That reminds me I have a bunch of moisture sensors lying around just waiting for some love.... mmmmm more projects to add to the list. They are the cheapo kind that I think will degrade quickly though - maybe one season. Have to look.

I pretty heavily re-worked the flow to be more robust in responding to different events (esp. turning lights on/off during motion active), set the timer to start after the sensor goes to inactive, and be slightly more readable.

JSON:

Summary
[
{
    "id": "32054f7b.6f13c",
    "type": "tab",
    "label": "Flow 11",
    "disabled": false,
    "info": ""
},
{
    "id": "cd2e24c3.24164",
    "type": "state-machine",
    "z": "32054f7b.6f13c",
    "name": "",
    "triggerProperty": "payload",
    "triggerPropertyType": "msg",
    "stateProperty": "payload",
    "statePropertyType": "msg",
    "outputStateChangeOnly": true,
    "throwException": false,
    "states": [
        "st_switch",
        "st_motion-on",
        "st_motion-timer",
        "st_motion-off",
        "st_off",
        "st_on",
        "st_switch_off",
        "st_switch_on"
    ],
    "transitions": [
        {
            "name": "tr_off",
            "from": "*",
            "to": "st_off"
        },
        {
            "name": "tr_on",
            "from": "*",
            "to": "st_on"
        },
        {
            "name": "tr_motion-active",
            "from": "st_off",
            "to": "st_motion-on"
        },
        {
            "name": "tr_motion-active",
            "from": "st_motion-timer",
            "to": "st_motion-on"
        },
        {
            "name": "tr_motion-on",
            "from": "st_motion-on",
            "to": "st_motion-timer"
        },
        {
            "name": "tr_motion-inactive",
            "from": "st_motion-on",
            "to": "st_motion-timer"
        },
        {
            "name": "tr_motion-off",
            "from": "st_motion-timer",
            "to": "st_motion-off"
        },
        {
            "name": "tr_switch-off",
            "from": "*",
            "to": "st_switch_off"
        },
        {
            "name": "tr_switch-on",
            "from": "st_motion-timer",
            "to": "st_switch_on"
        },
        {
            "name": "tr_switch-on",
            "from": "st_motion-off",
            "to": "st_switch_on"
        },
        {
            "name": "tr_switch-on",
            "from": "st_switch_off",
            "to": "st_switch_on"
        },
        {
            "name": "tr_switch-on",
            "from": "st_off",
            "to": "st_switch_on"
        }
    ],
    "x": 500,
    "y": 540,
    "wires": [
        [
            "e4bc4a4c.a41c88",
            "360cbf98.e378a8",
            "56259156.cacac",
            "3abe544f.9780ec",
            "628ae107.126778",
            "159bf659.920b8a"
        ]
    ]
},
{
    "id": "2e7249fe.b79626",
    "type": "change",
    "z": "32054f7b.6f13c",
    "name": "tr_switch-on",
    "rules": [
        {
            "t": "set",
            "p": "payload",
            "pt": "msg",
            "to": "tr_switch-on",
            "tot": "str"
        }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 230,
    "y": 780,
    "wires": [
        [
            "cd2e24c3.24164",
            "8ad74838.a063f"
        ]
    ]
},
{
    "id": "81b55db6.ac465",
    "type": "change",
    "z": "32054f7b.6f13c",
    "name": "tr_motion-active",
    "rules": [
        {
            "t": "set",
            "p": "payload",
            "pt": "msg",
            "to": "tr_motion-active",
            "tot": "str"
        }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 360,
    "y": 440,
    "wires": [
        [
            "cd2e24c3.24164",
            "8ad74838.a063f"
        ]
    ]
},
{
    "id": "18468b2f.edbca5",
    "type": "change",
    "z": "32054f7b.6f13c",
    "name": "stop timer",
    "rules": [
        {
            "t": "set",
            "p": "payload",
            "pt": "msg",
            "to": "stop",
            "tot": "str"
        }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 910,
    "y": 480,
    "wires": [
        [
            "c65ec7b5.1a812"
        ]
    ]
},
{
    "id": "9fdf23ab.1043a8",
    "type": "change",
    "z": "32054f7b.6f13c",
    "name": "tr_motion-off",
    "rules": [
        {
            "t": "set",
            "p": "payload",
            "pt": "msg",
            "to": "tr_motion-off",
            "tot": "str"
        }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 1130,
    "y": 420,
    "wires": [
        [
            "81434535.f6326"
        ]
    ]
},
{
    "id": "1f3745d7.2e5fa2",
    "type": "inject",
    "z": "32054f7b.6f13c",
    "name": "Current State",
    "topic": "",
    "payload": "stop",
    "payloadType": "str",
    "repeat": "",
    "crontab": "",
    "once": true,
    "onceDelay": 0.1,
    "x": 1300,
    "y": 860,
    "wires": [
        [
            "9d1eb16.c4c095",
            "a2131a41.ef7608"
        ]
    ]
},
{
    "id": "e7869b10.0f8bf",
    "type": "inject",
    "z": "32054f7b.6f13c",
    "name": "",
    "topic": "",
    "payload": "simulate",
    "payloadType": "str",
    "repeat": "",
    "crontab": "",
    "once": false,
    "onceDelay": 0.1,
    "x": 1240,
    "y": 160,
    "wires": [
        [
            "81b55db6.ac465",
            "4ed301e3.bd1a78"
        ]
    ]
},
{
    "id": "e4bc4a4c.a41c88",
    "type": "switch",
    "z": "32054f7b.6f13c",
    "name": "st_motion-on",
    "property": "payload",
    "propertyType": "msg",
    "rules": [
        {
            "t": "eq",
            "v": "st_motion-on",
            "vt": "str"
        }
    ],
    "checkall": "true",
    "repair": false,
    "outputs": 1,
    "x": 720,
    "y": 360,
    "wires": [
        [
            "18468b2f.edbca5",
            "1066966d.019372"
        ]
    ]
},
{
    "id": "360cbf98.e378a8",
    "type": "switch",
    "z": "32054f7b.6f13c",
    "name": "st_motion-timer",
    "property": "payload",
    "propertyType": "msg",
    "rules": [
        {
            "t": "eq",
            "v": "st_motion-timer",
            "vt": "str"
        }
    ],
    "checkall": "true",
    "repair": false,
    "outputs": 1,
    "x": 720,
    "y": 420,
    "wires": [
        [
            "c65ec7b5.1a812"
        ]
    ]
},
{
    "id": "b1cbc49a.9cd008",
    "type": "link in",
    "z": "32054f7b.6f13c",
    "name": "kitchen state machine",
    "links": [
        "81434535.f6326"
    ],
    "x": 335,
    "y": 500,
    "wires": [
        [
            "cd2e24c3.24164",
            "8ad74838.a063f"
        ]
    ]
},
{
    "id": "81434535.f6326",
    "type": "link out",
    "z": "32054f7b.6f13c",
    "name": "kitchen state machine",
    "links": [
        "b1cbc49a.9cd008"
    ],
    "x": 1555,
    "y": 420,
    "wires": []
},
{
    "id": "56259156.cacac",
    "type": "switch",
    "z": "32054f7b.6f13c",
    "name": "st_switch_on",
    "property": "payload",
    "propertyType": "msg",
    "rules": [
        {
            "t": "eq",
            "v": "st_switch_on",
            "vt": "str"
        }
    ],
    "checkall": "true",
    "repair": false,
    "outputs": 1,
    "x": 710,
    "y": 660,
    "wires": [
        [
            "18468b2f.edbca5",
            "9d1eb16.c4c095",
            "a2131a41.ef7608"
        ]
    ]
},
{
    "id": "3abe544f.9780ec",
    "type": "switch",
    "z": "32054f7b.6f13c",
    "name": "st_motion-off",
    "property": "payload",
    "propertyType": "msg",
    "rules": [
        {
            "t": "eq",
            "v": "st_motion-off",
            "vt": "str"
        }
    ],
    "checkall": "true",
    "repair": false,
    "outputs": 1,
    "x": 720,
    "y": 540,
    "wires": [
        [
            "be1931cb.958768"
        ]
    ]
},
{
    "id": "b7009f7c.1475a8",
    "type": "hubitat device",
    "z": "32054f7b.6f13c",
    "name": "Motion Sensor",
    "server": "d0c8b8e.6894848",
    "deviceId": "2695",
    "attribute": "motion",
    "sendEvent": true,
    "x": 100,
    "y": 300,
    "wires": [
        [
            "d768f4ca.32357",
            "d4a8da8b.9feeb8"
        ]
    ]
},
{
    "id": "8b7bf52b.866948",
    "type": "hubitat device",
    "z": "32054f7b.6f13c",
    "name": "DR Lights",
    "server": "d0c8b8e.6894848",
    "deviceId": "7",
    "attribute": "switch",
    "sendEvent": true,
    "x": 80,
    "y": 660,
    "wires": [
        [
            "7b856664.62a66"
        ]
    ]
},
{
    "id": "76ef38e1.e0c138",
    "type": "hubitat command",
    "z": "32054f7b.6f13c",
    "name": "DR Lights On",
    "server": "d0c8b8e.6894848",
    "deviceId": "7",
    "command": "on",
    "commandArgs": "",
    "x": 1120,
    "y": 360,
    "wires": [
        [
            "7676191b.c2c53"
        ]
    ]
},
{
    "id": "e4033469.c56598",
    "type": "hubitat command",
    "z": "32054f7b.6f13c",
    "name": "DR Lights Off",
    "server": "d0c8b8e.6894848",
    "deviceId": "7",
    "command": "off",
    "commandArgs": "",
    "x": 1120,
    "y": 540,
    "wires": [
        [
            "a27508c.116b578"
        ]
    ]
},
{
    "id": "9d1eb16.c4c095",
    "type": "hubitat device",
    "z": "32054f7b.6f13c",
    "name": "DR Lights",
    "server": "d0c8b8e.6894848",
    "deviceId": "7",
    "attribute": "switch",
    "sendEvent": false,
    "x": 1480,
    "y": 660,
    "wires": [
        [
            "17dcd9bd.e783d6"
        ]
    ]
},
{
    "id": "82d17be7.3b429",
    "type": "hubitat command",
    "z": "32054f7b.6f13c",
    "name": "DR Lights Off",
    "server": "d0c8b8e.6894848",
    "deviceId": "7",
    "command": "off",
    "commandArgs": "",
    "x": 1420,
    "y": 40,
    "wires": [
        []
    ]
},
{
    "id": "90b4d9cc.00d748",
    "type": "hubitat command",
    "z": "32054f7b.6f13c",
    "name": "DR Lights On",
    "server": "d0c8b8e.6894848",
    "deviceId": "7",
    "command": "setLevel",
    "commandArgs": "55",
    "x": 1420,
    "y": 100,
    "wires": [
        []
    ]
},
{
    "id": "82637f9c.d91bf8",
    "type": "inject",
    "z": "32054f7b.6f13c",
    "name": "",
    "topic": "",
    "payload": "",
    "payloadType": "date",
    "repeat": "",
    "crontab": "",
    "once": false,
    "onceDelay": 0.1,
    "x": 1240,
    "y": 40,
    "wires": [
        [
            "82d17be7.3b429"
        ]
    ]
},
{
    "id": "78757e7a.f06d4",
    "type": "inject",
    "z": "32054f7b.6f13c",
    "name": "",
    "topic": "",
    "payload": "",
    "payloadType": "date",
    "repeat": "",
    "crontab": "",
    "once": false,
    "onceDelay": 0.1,
    "x": 1240,
    "y": 100,
    "wires": [
        [
            "90b4d9cc.00d748"
        ]
    ]
},
{
    "id": "e64c4e31.36aaf8",
    "type": "time-range-switch",
    "z": "32054f7b.6f13c",
    "name": "",
    "lat": "",
    "lon": "",
    "startTime": "06:00",
    "endTime": "22:00",
    "startOffset": 0,
    "endOffset": 0,
    "x": 340,
    "y": 100,
    "wires": [
        [
            "aec70c57.f1e2d8"
        ],
        []
    ]
},
{
    "id": "afbbd0dd.bb8b38",
    "type": "hubitat device",
    "z": "32054f7b.6f13c",
    "name": "Lux - Back Entrance",
    "server": "d0c8b8e.6894848",
    "deviceId": "1579",
    "attribute": "illuminance",
    "sendEvent": true,
    "x": 340,
    "y": 160,
    "wires": [
        [
            "ec312867.891898"
        ]
    ]
},
{
    "id": "3b7e53e0.d21554",
    "type": "change",
    "z": "32054f7b.6f13c",
    "name": "Lux Blocked?",
    "rules": [
        {
            "t": "set",
            "p": "lux_block",
            "pt": "flow",
            "to": "0",
            "tot": "num"
        }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 680,
    "y": 160,
    "wires": [
        [
            "decd31d2.ac43e"
        ]
    ]
},
{
    "id": "aec70c57.f1e2d8",
    "type": "switch",
    "z": "32054f7b.6f13c",
    "name": "",
    "property": "payload",
    "propertyType": "msg",
    "rules": [
        {
            "t": "nnull"
        }
    ],
    "checkall": "true",
    "repair": false,
    "outputs": 1,
    "x": 510,
    "y": 100,
    "wires": [
        [
            "aa9f4f85.57da7"
        ]
    ]
},
{
    "id": "aa9f4f85.57da7",
    "type": "change",
    "z": "32054f7b.6f13c",
    "name": "Time Blocked?",
    "rules": [
        {
            "t": "set",
            "p": "time_block",
            "pt": "flow",
            "to": "0",
            "tot": "num"
        }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 680,
    "y": 100,
    "wires": [
        [
            "a0ee8250.47b91"
        ]
    ]
},
{
    "id": "ec312867.891898",
    "type": "switch",
    "z": "32054f7b.6f13c",
    "name": "",
    "property": "payload.value",
    "propertyType": "msg",
    "rules": [
        {
            "t": "lt",
            "v": "100",
            "vt": "num"
        }
    ],
    "checkall": "true",
    "repair": false,
    "outputs": 1,
    "x": 510,
    "y": 160,
    "wires": [
        [
            "3b7e53e0.d21554"
        ]
    ]
},
{
    "id": "d768f4ca.32357",
    "type": "function",
    "z": "32054f7b.6f13c",
    "name": "Blocked?",
    "func": "var a= flow.get('time_block')\nvar b= flow.get('lux_block')\nmsg.payload.blockValue = a+b\nreturn msg;",
    "outputs": 1,
    "noerr": 0,
    "x": 280,
    "y": 300,
    "wires": [
        [
            "1c635c36.ad33ec"
        ]
    ]
},
{
    "id": "1c635c36.ad33ec",
    "type": "switch",
    "z": "32054f7b.6f13c",
    "name": "Blocked =0",
    "property": "payload.blockValue",
    "propertyType": "msg",
    "rules": [
        {
            "t": "eq",
            "v": "0",
            "vt": "num"
        }
    ],
    "checkall": "true",
    "repair": false,
    "outputs": 1,
    "x": 450,
    "y": 300,
    "wires": [
        [
            "70024162.dae038"
        ]
    ]
},
{
    "id": "4ccc06b2.f00188",
    "type": "comment",
    "z": "32054f7b.6f13c",
    "name": "Filters",
    "info": "",
    "x": 70,
    "y": 40,
    "wires": []
},
{
    "id": "1578ab31.0d2b6d",
    "type": "comment",
    "z": "32054f7b.6f13c",
    "name": "Control the lights",
    "info": "",
    "x": 100,
    "y": 240,
    "wires": []
},
{
    "id": "17dcd9bd.e783d6",
    "type": "change",
    "z": "32054f7b.6f13c",
    "name": "Transition Name",
    "rules": [
        {
            "t": "set",
            "p": "payload",
            "pt": "msg",
            "to": "\"tr_\"&payload.value",
            "tot": "jsonata"
        }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 1480,
    "y": 560,
    "wires": [
        [
            "81434535.f6326"
        ]
    ]
},
{
    "id": "decd31d2.ac43e",
    "type": "debug",
    "z": "32054f7b.6f13c",
    "name": "",
    "active": false,
    "tosidebar": true,
    "console": false,
    "tostatus": false,
    "complete": "( { \"Lux Block\": $flowContext('lux_block') } )",
    "targetType": "jsonata",
    "x": 880,
    "y": 160,
    "wires": []
},
{
    "id": "628ae107.126778",
    "type": "debug",
    "z": "32054f7b.6f13c",
    "name": "To State",
    "active": true,
    "tosidebar": true,
    "console": false,
    "tostatus": false,
    "complete": "payload",
    "targetType": "msg",
    "x": 700,
    "y": 600,
    "wires": []
},
{
    "id": "70024162.dae038",
    "type": "switch",
    "z": "32054f7b.6f13c",
    "name": "Active?",
    "property": "payload.value",
    "propertyType": "msg",
    "rules": [
        {
            "t": "eq",
            "v": "active",
            "vt": "str"
        }
    ],
    "checkall": "true",
    "repair": false,
    "outputs": 1,
    "x": 340,
    "y": 380,
    "wires": [
        [
            "81b55db6.ac465"
        ]
    ]
},
{
    "id": "8ad74838.a063f",
    "type": "debug",
    "z": "32054f7b.6f13c",
    "name": "Transition",
    "active": true,
    "tosidebar": true,
    "console": false,
    "tostatus": false,
    "complete": "payload",
    "targetType": "msg",
    "x": 520,
    "y": 780,
    "wires": []
},
{
    "id": "c65ec7b5.1a812",
    "type": "stoptimer2",
    "z": "32054f7b.6f13c",
    "duration": "10",
    "durationType": "num",
    "units": "Second",
    "payloadtype": "num",
    "payloadval": "0",
    "name": "",
    "x": 930,
    "y": 420,
    "wires": [
        [
            "9fdf23ab.1043a8"
        ],
        []
    ]
},
{
    "id": "e2b82781.7af5e",
    "type": "stoptimer2",
    "z": "32054f7b.6f13c",
    "duration": "1",
    "durationType": "num",
    "units": "Minute",
    "payloadtype": "num",
    "payloadval": "0",
    "name": "pause motion detection for 1 min",
    "x": 1200,
    "y": 720,
    "wires": [
        [
            "9d1eb16.c4c095"
        ],
        []
    ]
},
{
    "id": "c97a4d6d.1f772",
    "type": "switch",
    "z": "32054f7b.6f13c",
    "name": "On or Off",
    "property": "payload.value",
    "propertyType": "msg",
    "rules": [
        {
            "t": "eq",
            "v": "on",
            "vt": "str"
        },
        {
            "t": "eq",
            "v": "off",
            "vt": "str"
        }
    ],
    "checkall": "true",
    "repair": false,
    "outputs": 2,
    "x": 220,
    "y": 720,
    "wires": [
        [
            "2e7249fe.b79626"
        ],
        [
            "547fa841.80388"
        ]
    ]
},
{
    "id": "547fa841.80388",
    "type": "change",
    "z": "32054f7b.6f13c",
    "name": "tr_switch-off",
    "rules": [
        {
            "t": "set",
            "p": "payload",
            "pt": "msg",
            "to": "tr_switch-off",
            "tot": "str"
        }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 230,
    "y": 840,
    "wires": [
        [
            "cd2e24c3.24164",
            "8ad74838.a063f"
        ]
    ]
},
{
    "id": "159bf659.920b8a",
    "type": "switch",
    "z": "32054f7b.6f13c",
    "name": "st_switch_off",
    "property": "payload",
    "propertyType": "msg",
    "rules": [
        {
            "t": "eq",
            "v": "st_switch_off",
            "vt": "str"
        }
    ],
    "checkall": "true",
    "repair": false,
    "outputs": 1,
    "x": 710,
    "y": 720,
    "wires": [
        [
            "e2b82781.7af5e",
            "18468b2f.edbca5"
        ]
    ]
},
{
    "id": "95b3ed1f.620b18",
    "type": "inject",
    "z": "32054f7b.6f13c",
    "name": "Update every 1 min",
    "topic": "",
    "payload": "",
    "payloadType": "date",
    "repeat": "60",
    "crontab": "",
    "once": true,
    "onceDelay": 0.1,
    "x": 140,
    "y": 100,
    "wires": [
        [
            "e64c4e31.36aaf8",
            "afbbd0dd.bb8b38"
        ]
    ]
},
{
    "id": "a0ee8250.47b91",
    "type": "debug",
    "z": "32054f7b.6f13c",
    "name": "",
    "active": false,
    "tosidebar": true,
    "console": false,
    "tostatus": false,
    "complete": "( { \"Time Block\": $flowContext('time_block') } )",
    "targetType": "jsonata",
    "x": 880,
    "y": 100,
    "wires": []
},
{
    "id": "a2131a41.ef7608",
    "type": "change",
    "z": "32054f7b.6f13c",
    "name": "stop timer",
    "rules": [
        {
            "t": "set",
            "p": "payload",
            "pt": "msg",
            "to": "stop",
            "tot": "str"
        }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 930,
    "y": 780,
    "wires": [
        [
            "e2b82781.7af5e"
        ]
    ]
},
{
    "id": "d4a8da8b.9feeb8",
    "type": "switch",
    "z": "32054f7b.6f13c",
    "name": "Inactive?",
    "property": "payload.value",
    "propertyType": "msg",
    "rules": [
        {
            "t": "eq",
            "v": "inactive",
            "vt": "str"
        }
    ],
    "checkall": "true",
    "repair": false,
    "outputs": 1,
    "x": 140,
    "y": 500,
    "wires": [
        [
            "38012087.2eab18"
        ]
    ]
},
{
    "id": "38012087.2eab18",
    "type": "change",
    "z": "32054f7b.6f13c",
    "name": "tr_motion-inactive",
    "rules": [
        {
            "t": "set",
            "p": "payload",
            "pt": "msg",
            "to": "tr_motion-inactive",
            "tot": "str"
        }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 170,
    "y": 560,
    "wires": [
        [
            "cd2e24c3.24164",
            "8ad74838.a063f"
        ]
    ]
},
{
    "id": "1066966d.019372",
    "type": "change",
    "z": "32054f7b.6f13c",
    "name": "Manual Block =1",
    "rules": [
        {
            "t": "set",
            "p": "manual_block",
            "pt": "flow",
            "to": "1",
            "tot": "num"
        }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 930,
    "y": 360,
    "wires": [
        [
            "76ef38e1.e0c138"
        ]
    ]
},
{
    "id": "9cb826db.929388",
    "type": "change",
    "z": "32054f7b.6f13c",
    "name": "Manual Block =0",
    "rules": [
        {
            "t": "set",
            "p": "manual_block",
            "pt": "flow",
            "to": "0",
            "tot": "num"
        }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 1450,
    "y": 360,
    "wires": [
        []
    ]
},
{
    "id": "7676191b.c2c53",
    "type": "delay",
    "z": "32054f7b.6f13c",
    "name": "",
    "pauseType": "delay",
    "timeout": "1",
    "timeoutUnits": "seconds",
    "rate": "1",
    "nbRateUnits": "1",
    "rateUnits": "second",
    "randomFirst": "1",
    "randomLast": "5",
    "randomUnits": "seconds",
    "drop": false,
    "x": 1280,
    "y": 360,
    "wires": [
        [
            "9cb826db.929388"
        ]
    ]
},
{
    "id": "be1931cb.958768",
    "type": "change",
    "z": "32054f7b.6f13c",
    "name": "Manual Block =1",
    "rules": [
        {
            "t": "set",
            "p": "manual_block",
            "pt": "flow",
            "to": "1",
            "tot": "num"
        }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 930,
    "y": 540,
    "wires": [
        [
            "e4033469.c56598"
        ]
    ]
},
{
    "id": "a557edf7.e7b4",
    "type": "change",
    "z": "32054f7b.6f13c",
    "name": "Manual Block =0",
    "rules": [
        {
            "t": "set",
            "p": "manual_block",
            "pt": "flow",
            "to": "0",
            "tot": "num"
        }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 1270,
    "y": 600,
    "wires": [
        [
            "9d1eb16.c4c095"
        ]
    ]
},
{
    "id": "7b856664.62a66",
    "type": "switch",
    "z": "32054f7b.6f13c",
    "name": "Manual Block=1",
    "property": "manual_block",
    "propertyType": "flow",
    "rules": [
        {
            "t": "eq",
            "v": "0",
            "vt": "num"
        }
    ],
    "checkall": "true",
    "repair": false,
    "outputs": 1,
    "x": 240,
    "y": 660,
    "wires": [
        [
            "c97a4d6d.1f772"
        ]
    ]
},
{
    "id": "a27508c.116b578",
    "type": "delay",
    "z": "32054f7b.6f13c",
    "name": "",
    "pauseType": "delay",
    "timeout": "1",
    "timeoutUnits": "seconds",
    "rate": "1",
    "nbRateUnits": "1",
    "rateUnits": "second",
    "randomFirst": "1",
    "randomLast": "5",
    "randomUnits": "seconds",
    "drop": false,
    "x": 1280,
    "y": 540,
    "wires": [
        [
            "a557edf7.e7b4"
        ]
    ]
},
{
    "id": "4ed301e3.bd1a78",
    "type": "delay",
    "z": "32054f7b.6f13c",
    "name": "",
    "pauseType": "delay",
    "timeout": "5",
    "timeoutUnits": "seconds",
    "rate": "1",
    "nbRateUnits": "1",
    "rateUnits": "second",
    "randomFirst": "1",
    "randomLast": "5",
    "randomUnits": "seconds",
    "drop": false,
    "x": 1400,
    "y": 160,
    "wires": [
        [
            "38012087.2eab18"
        ]
    ]
},
{
    "id": "d0c8b8e.6894848",
    "type": "hubitat config",
    "z": "",
    "name": "Hubitat",
    "usetls": false,
    "host": "192.168.1.17",
    "port": "80",
    "token": "e5653e7e-56a0-43fc-8e19-96a6d9f22711",
    "appId": "2834",
    "nodeRedServer": "http://192.168.1.10:1882",
    "webhookPath": "/hubitat/webhook"
}]

Wow you have a lot going on there! I am intrigued by the FSM.

You could name that "chaos theory" in terms of the "art".
:grinning:

3 Likes

It is kind of funny.. a quick glance at the attached picture it seems like a lot to take in, but opening up the full sized version and following along, it all makes so much sense..

I can't even imagine what a fustercluck that would be to do in Rule Machine™

NR rocks!

3 Likes

Whats kind of interesting is with dynamic device selection (which we were discussing that desired feature in the other thread) in the HE Nodes you could possibly make this a subflow and use it for other lights..

1 Like

Ha ha. It's more or less a standard Motion Lighting app. Both this and the equivalent ML app run this flow in about 300 ms.

The one thing it does that ML doesn't (I think) is to put in a re-triggering delay if the light is manually turned off.

A fair amount of the extra stuff is debug/testing nodes that can be gotten rid of.

Once you get the idea of triggers and states and valid combinations the FSM makes more sense.

I had to put some delays in the flow as switching the lights with motion would trip the light switch events (bottom left of the flow) and would sometimes get the state machine to run valid but unintended transitions.

You might be able to get around that with physical/digital filters. But those aren't foolproof either. For example: all button (e.g. Pico) presses would be flagged as digital if you are monitoring the light events. You have to monitor the physical button to get the event to be physical.

1 Like

Follow up here for more show and tell:

This implements a loop, but because of the left-to-right nature of node-red, I think it's a "twisted circle":

It's purpose is to shut off the lights after 8:30, and after the motion zone is inactive.


This one looks like a Saturn rocket to me:

image

It's a porch-lights-on-at-dusk-off-at-sunrise flow.

1 Like

I saw this but missing the lower wings. Add another Inject and Comment Node at the bottom then add more text to each Comment Node to make them longer and you nailed it!
image

2 Likes

That's pretty complex for a straight dusk/dawn on/off. There are nodes that can do dusk/dawn triggering in 1 node.

Here's an example using bigtimer for on=dusk, off=23:45:


The link out is because I use those times other places, too.

Just curious how people are creating sequences.

Are you organizing things in different flows. One flow is button devices, another flow is motion sensors, another flow is general rules to turn on and off stuff.

Can you also call other flow sequences?

Lastly, by no means does looking at flows and sequences make it easy on the eyes. I find it much easier to look at rule machine or an event engine.

I have my flows arranged this way for now:

  • Exterior and Entrance - Entry alerts, exterior lighting etc.
  • Main Floor - main floor hub sequences.
  • Basement - basement lighting etc (on main hub).
  • Upstairs - my upstairs hub sequences - lighting/fan control etc.
  • Control - used for global operations affecting all my hubs/flows. Cloud/presence stuff etc.
  • Dashboard Config - use for dashboard initialization stuff.
  • Testing - testing stuff, just a place to mess around.
  • On Ice / Trash - this is a disabled flow for parking things.

Also use a lot of subflows if possible - even very simple ones like a notification subflow containing just an email node... the idea being I can change things in one place and it changes everywhere. stuff like that.

edit: The way you call other sequences in flows is by using the "link in" "link out" nodes... also for me reading sequences is mostly easier than RM - depends on the sequence of course and how descriptive I've been with my node naming. Really complex sequences can be confusing but likewise with RM but in general I find it easier to trace out whats happening.

I group by common function - lights 1, lights 2, etc.

Yes. Typically with link in/link out nodes.

That's, of course, an opinion. One I completely disagree with. With a little care in naming of the nodes you can visually walk your way through any flow of any complexity and know EXACTLY what it does without digging into the details of any individual node. Very intuitive to me - basically connect the dots.

2 Likes

For sure. Lots of ways to solve the problems, each one with their different nuances. I've never used bigtimer, perhaps it'd simplify what I'm doing. But I already have the sun contrib package of nodes and was able to accomplish this without adding more dependencies to my node red stack.

1 Like

I certainly can't argue with that! There is definitely no right/wrong way to do it!

If it works, that's the right way. :slight_smile:

2 Likes

My general undestanding on when to introduce Node Red are the following.

  • Home Assistant - Rule creations are terrible from what I understand.
  • Pulling multiple machines together and only focusing on those specific sequences
  • Perhaps for speed in comparison to some hubs. Again only focusing on those sequences/rules for those specific events.

I would also add:

  • wanting to have a flexible and abstract opensource control system that is not reliant on any one platform/company to function.

"One ring to rule them all" - very powerful.. maybe evil too.

:wink: