Help with complicated timing flow

I have a Hue setup I'm trying to migrate to zigbee2mqtt with node-red on HomeAssistant. I've managed to move almost everything over except the most complicated bit, which I had already hacked together even on the Hue bridge. It almost but not quite works, but from what I gather in the forum here, using function nodes, and especially using timers in function nodes, is probably not the solution I'm looking for.

I have two Hue motion sensors at either end of the hallway, and I'd like for the following to happen:

If either motion sensor detects motion (occupancy = true), then:

  • if it's between 23:00 and 7:00,
    -- set brightness of two lamps to 10
    -- after n seconds, turn the lights off, unless there is additional activity.
  • if it's between 7:00 and 23:00,
    -- set brightness of two lamps to 255
    -- after a seconds, set it to 127
    -- after b more seconds, set it to 10
    -- after c more seconds, turn the light off.
    -- if there is additional activity at any point, go back up to 255 and start again.

Bonus: if the "on" button is pressed on the switch, the brightness should go to 255 and the dimming flow disabled until the "off" button is pressed. I think that could be done with setting a state and checking it in the dimming flow?

Here's what I've badly cobbled together, using node-red-contrib-zigbee2mqtt. Any help would be much appreciated - I'm, as you can probably tell from the atrocity below, relatively new to the whole thing.

[{"id":"7f59364f045fd16d","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"98196556164b7185","type":"zigbee2mqtt-in","z":"7f59364f045fd16d","name":"Gang Motion 1","server":"b6a204d939227d2b","friendly_name":"gang_motion_wz","device_id":"0x00178801021030ff","state":"0","outputAtStartup":true,"x":140,"y":120,"wires":[["7c7d1ff73eb85733"]]},{"id":"85f5ece225d32cb3","type":"zigbee2mqtt-in","z":"7f59364f045fd16d","name":"Gang Motion 2","server":"b6a204d939227d2b","friendly_name":"gang_motion_sz","device_id":"0x0017880102103dff","state":"occupancy","outputAtStartup":true,"x":140,"y":200,"wires":[["7c7d1ff73eb85733"]]},{"id":"7c7d1ff73eb85733","type":"join","z":"7f59364f045fd16d","name":"","mode":"custom","build":"object","property":"payload.occupancy","propertyType":"msg","key":"device.friendly_name","joiner":"\\n","joinerType":"str","accumulate":true,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":310,"y":160,"wires":[["4478758eb2e76ab9"]]},{"id":"4478758eb2e76ab9","type":"function","z":"7f59364f045fd16d","name":"Test","func":"if (msg.payload && msg.payload.occupancy && (\n    msg.payload.occupancy.gang_motion_sz \n|| msg.payload.occupancy.gang_motion_wz)) {\n    msg.payload = \"on\";\n} else {\n    msg.payload = \"off\";\n}\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":430,"y":160,"wires":[["2a035521e831b1f6"]]},{"id":"2a035521e831b1f6","type":"switch","z":"7f59364f045fd16d","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"on","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":550,"y":160,"wires":[["8b8bb051c2dfda54"]]},{"id":"8b8bb051c2dfda54","type":"time-range-switch","z":"7f59364f045fd16d","name":"Daytime?","lat":"","lon":"","startTime":"07:30","endTime":"23:00","startOffset":0,"endOffset":0,"x":680,"y":160,"wires":[["de3afad4cd3f3120"],["6f541cefb42d0fdc"]]},{"id":"78dcf074fd230e26","type":"mqtt out","z":"7f59364f045fd16d","name":"Gang WZ","topic":"zigbee2mqtt/gang_lamp_wz/set","qos":"0","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"1e8f979434900837","x":980,"y":80,"wires":[]},{"id":"de3afad4cd3f3120","type":"function","z":"7f59364f045fd16d","name":"","func":"steps = 3;\n\ndimmer()\nvar timer = setInterval(dimmer, 30000);\n\nfunction dimmer() {\n    payload = {};\n    switch(steps) {\n        case 3:\n            payload = { state: \"ON\", brightness: 255, transition: 1 };\n            break;\n        case 2:\n            payload = { brightness: 128, transition: 1 };\n            break;\n        case 1:\n            payload = { brightness: 10, transition: 1 };\n            break;\n        case 0:\n            payload = { state: \"OFF\" };\n            clearInterval(timer);\n    }\n    node.send({ payload: payload });\n    steps--;\n}\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":840,"y":100,"wires":[["78dcf074fd230e26","31823f79e7414c77"]]},{"id":"31823f79e7414c77","type":"mqtt out","z":"7f59364f045fd16d","name":"Gang SZ","topic":"zigbee2mqtt/gang_lamp_sz/set","qos":"0","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"1e8f979434900837","x":980,"y":120,"wires":[]},{"id":"4aeff96bb9331574","type":"mqtt out","z":"7f59364f045fd16d","name":"Gang WZ","topic":"zigbee2mqtt/gang_lamp_wz/set","qos":"0","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"1e8f979434900837","x":980,"y":200,"wires":[]},{"id":"6f541cefb42d0fdc","type":"function","z":"7f59364f045fd16d","name":"","func":"steps = 1;\n\ndimmer()\nvar timer = setInterval(dimmer, 60000);\n\nfunction dimmer() {\n    payload = {};\n    switch(steps) {\n        case 1:\n            payload = { brightness: 10, transition: 1 };\n            break;\n        case 0:\n            payload = { state: \"OFF\" };\n            clearInterval(timer);\n    }\n    node.send({ payload: payload });\n    steps--;\n}\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":840,"y":220,"wires":[["4aeff96bb9331574","a43aef9b64adcebf"]]},{"id":"a43aef9b64adcebf","type":"mqtt out","z":"7f59364f045fd16d","name":"Gang SZ","topic":"zigbee2mqtt/gang_lamp_sz/set","qos":"0","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"1e8f979434900837","x":980,"y":240,"wires":[]},{"id":"b6a204d939227d2b","type":"zigbee2mqtt-server","name":"192.168.1.222","host":"192.168.1.222","mqtt_port":"1883","mqtt_username":"homeassistant","mqtt_password":"wohnaexei1Tie9eeg0leiye7ahmoh0ieFeiG9eishaepao0cuu9osieke5deegoh","tls":"","usetls":false,"base_topic":"zigbee2mqtt"},{"id":"1e8f979434900837","type":"mqtt-broker","name":"","broker":"192.168.1.222","port":"1883","clientid":"","usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"sessionExpiry":""}]

Hi and welcome

here is an example, i have used inject nodes in place of the hue nodes as i don't use hue. Replace them with the sensor and light nodes. I have also made assumptions about the in coming payloads. I have also reduced the mqtt out to one node. The lights mqtt topics are added in the first function node, add one topic for each light in msg.devices

Hope it helps

[{"id":"54263b84.deb65c","type":"inject","z":"7f59364f045fd16d","name":"wz true","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":100,"y":120,"wires":[["4478758eb2e76ab9"]]},{"id":"4478758eb2e76ab9","type":"function","z":"7f59364f045fd16d","name":"Test","func":"msg.devices = [\"zigbee2mqtt/gang_lamp_wz/set\",\"zigbee2mqtt/gang_lamp_sz/set\"];\nlet manual = flow.get(\"manual\") || 0;\nlet t = new Date();\nmsg.hour = (t.getHours()*100) + t.getMinutes();\nif (msg.payload && manual === 0) {\n    msg.payload = \"on\";\n} else {\n    msg = null ;\n}\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":250,"y":180,"wires":[["2a035521e831b1f6"]]},{"id":"2a035521e831b1f6","type":"switch","z":"7f59364f045fd16d","name":"","property":"hour","propertyType":"msg","rules":[{"t":"btwn","v":"0","vt":"num","v2":"700","v2t":"num"},{"t":"btwn","v":"2300","vt":"num","v2":"2400","v2t":"num"},{"t":"else"}],"checkall":"false","repair":false,"outputs":3,"x":400,"y":180,"wires":[["fe1c393b.db2c8"],["fe1c393b.db2c8"],["46fe4d1c.832f2c"]]},{"id":"6fd38966.22732","type":"inject","z":"7f59364f045fd16d","name":"wz false","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"false","payloadType":"bool","x":100,"y":160,"wires":[["4478758eb2e76ab9"]]},{"id":"d75ac051.bf804","type":"inject","z":"7f59364f045fd16d","name":"sz true","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":100,"y":220,"wires":[["4478758eb2e76ab9"]]},{"id":"5e8f9c5.9937164","type":"inject","z":"7f59364f045fd16d","name":"sz false","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"false","payloadType":"bool","x":100,"y":260,"wires":[["4478758eb2e76ab9"]]},{"id":"fe1c393b.db2c8","type":"trigger","z":"7f59364f045fd16d","name":"","op1":"","op2":"","op1type":"pay","op2type":"pay","duration":"3000","extend":true,"overrideDelay":true,"units":"ms","reset":"","bytopic":"all","topic":"topic","outputs":2,"x":620,"y":160,"wires":[["3b1dab6d.03e35c"],["cac0ce4d.1414f8"]]},{"id":"46fe4d1c.832f2c","type":"trigger","z":"7f59364f045fd16d","name":"","op1":"","op2":"","op1type":"pay","op2type":"pay","duration":"3000","extend":true,"overrideDelay":true,"units":"ms","reset":"","bytopic":"all","topic":"topic","outputs":2,"x":620,"y":220,"wires":[["393f6bff.33308c","bcb46a97.3063f"],["8256e0ad.881f"]]},{"id":"3b1dab6d.03e35c","type":"change","z":"7f59364f045fd16d","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"devices.{\"state\": \"on\", \"brightness\":10,\"transition\":1, \"mqtt_topic\": $}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":880,"y":100,"wires":[["74661fcd.0af728"]]},{"id":"cac0ce4d.1414f8","type":"change","z":"7f59364f045fd16d","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"devices.{\"state\": \"off\", \"mqtt_topic\": $}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":880,"y":140,"wires":[["74661fcd.0af728"]]},{"id":"acc4618f.6a4fc8","type":"change","z":"7f59364f045fd16d","name":"","rules":[{"t":"set","p":"manual","pt":"flow","to":"$$.payload ? 1 : 0","tot":"jsonata"},{"t":"set","p":"reset","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":350,"y":400,"wires":[["fe1c393b.db2c8","46fe4d1c.832f2c","a96a9334.a98048","8256e0ad.881f"]]},{"id":"393f6bff.33308c","type":"change","z":"7f59364f045fd16d","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"devices.{\"state\": \"on\", \"brightness\":255,\"transition\":1, \"mqtt_topic\": $}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":880,"y":220,"wires":[["74661fcd.0af728"]]},{"id":"8256e0ad.881f","type":"trigger","z":"7f59364f045fd16d","name":"","op1":"","op2":"","op1type":"pay","op2type":"pay","duration":"3000","extend":true,"overrideDelay":true,"units":"ms","reset":"","bytopic":"all","topic":"topic","outputs":2,"x":620,"y":260,"wires":[["701c15f4.1cf1d4"],["a96a9334.a98048"]]},{"id":"bcb46a97.3063f","type":"change","z":"7f59364f045fd16d","name":"","rules":[{"t":"set","p":"reset","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":350,"y":280,"wires":[["a96a9334.a98048","8256e0ad.881f"]]},{"id":"74661fcd.0af728","type":"split","z":"7f59364f045fd16d","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":1070,"y":200,"wires":[["d3190504.057b8"]]},{"id":"a96a9334.a98048","type":"trigger","z":"7f59364f045fd16d","name":"","op1":"","op2":"","op1type":"pay","op2type":"pay","duration":"3000","extend":true,"overrideDelay":true,"units":"ms","reset":"","bytopic":"all","topic":"topic","outputs":2,"x":620,"y":300,"wires":[["29bb5421.69d0a4"],["108b775b.bd4e29"]]},{"id":"e3798983.589308","type":"inject","z":"7f59364f045fd16d","name":"light on","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":140,"y":380,"wires":[["acc4618f.6a4fc8"]]},{"id":"dbbdf29c.2d60c","type":"inject","z":"7f59364f045fd16d","name":"light off","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"false","payloadType":"bool","x":140,"y":420,"wires":[["acc4618f.6a4fc8"]]},{"id":"701c15f4.1cf1d4","type":"change","z":"7f59364f045fd16d","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"devices.{\"brightness\":127,\"transition\":1, \"mqtt_topic\": $}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":880,"y":260,"wires":[["74661fcd.0af728"]]},{"id":"d3190504.057b8","type":"change","z":"7f59364f045fd16d","name":"","rules":[{"t":"move","p":"payload.mqtt_topic","pt":"msg","to":"topic","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1300,"y":200,"wires":[["d68cf124.8737f"]]},{"id":"108b775b.bd4e29","type":"change","z":"7f59364f045fd16d","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"devices.{\"state\": \"off\", \"mqtt_topic\": $}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":880,"y":340,"wires":[["74661fcd.0af728"]]},{"id":"29bb5421.69d0a4","type":"change","z":"7f59364f045fd16d","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"devices.{\"brightness\":10,\"transition\":1, \"mqtt_topic\": $}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":880,"y":300,"wires":[["74661fcd.0af728"]]},{"id":"d68cf124.8737f","type":"debug","z":"7f59364f045fd16d","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1410,"y":280,"wires":[]}]

Oh wow, thank you for this comprehensive solution! The only changes I made beyond what you said was to replace the time switch with a time range node (and invert the condition), and make the light switch also actually turn on the light :slight_smile:

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