Need some advice with this "complex" flow

I have created a “basic” flow that allows me to turn on/off two fans every hour if during daytime or every 30 minutes if it is nighttime. Here is what it looks like:

And here is the JSON for such flow (apologies in advance is big chunk of code):

[
  {
    "id": "4d66e46fdf014b28",
    "type": "group",
    "z": "6d9e82a8948d508f",
    "name": "Server Rack Fans Control",
    "style": {
      "label": true,
      "color": "#001f60"
    },
    "nodes": [
      "2f62d03b6a0a24cd",
      "6c40a92288e7dea6",
      "fc02b28200938932",
      "2c6fceee29cc9a24",
      "0fd4d0bd078281a1",
      "e6c428dab477e438",
      "1b71cc1de3464325",
      "73ffcdfc1958de42",
      "a94ba14e2b1859c8",
      "71d6d13e3de86cf5",
      "49bcb9da63a5e46f",
      "775a4b1771455dfc",
      "2d2c5b3a996cd962",
      "36678338ef5ba40f"
    ],
    "x": 34,
    "y": 19,
    "w": 1522,
    "h": 342
  },
  {
    "id": "2f62d03b6a0a24cd",
    "type": "time-range-switch",
    "z": "6d9e82a8948d508f",
    "g": "4d66e46fdf014b28",
    "name": "",
    "lat": "28.496890",
    "lon": "-82.553900",
    "startTime": "08:00",
    "endTime": "20:00",
    "startOffset": 0,
    "endOffset": 0,
    "x": 370,
    "y": 100,
    "wires": [
      [
        "0fd4d0bd078281a1"
      ],
      []
    ]
  },
  {
    "id": "6c40a92288e7dea6",
    "type": "inject",
    "z": "6d9e82a8948d508f",
    "g": "4d66e46fdf014b28",
    "name": "",
    "props": [
      {
        "p": "payload"
      },
      {
        "p": "topic",
        "vt": "str"
      }
    ],
    "repeat": "3600",
    "crontab": "",
    "once": false,
    "onceDelay": "20",
    "topic": "",
    "payload": "",
    "payloadType": "date",
    "x": 150,
    "y": 100,
    "wires": [
      [
        "2f62d03b6a0a24cd"
      ]
    ]
  },
  {
    "id": "fc02b28200938932",
    "type": "time-range-switch",
    "z": "6d9e82a8948d508f",
    "g": "4d66e46fdf014b28",
    "name": "",
    "lat": "28.496890",
    "lon": "-82.553900",
    "startTime": "20:01",
    "endTime": "07:59",
    "startOffset": 0,
    "endOffset": 0,
    "x": 370,
    "y": 280,
    "wires": [
      [
        "e6c428dab477e438"
      ],
      []
    ]
  },
  {
    "id": "2c6fceee29cc9a24",
    "type": "inject",
    "z": "6d9e82a8948d508f",
    "g": "4d66e46fdf014b28",
    "name": "",
    "props": [
      {
        "p": "payload"
      },
      {
        "p": "topic",
        "vt": "str"
      }
    ],
    "repeat": "1800",
    "crontab": "",
    "once": false,
    "onceDelay": "20",
    "topic": "",
    "payload": "",
    "payloadType": "date",
    "x": 150,
    "y": 280,
    "wires": [
      [
        "fc02b28200938932"
      ]
    ]
  },
  {
    "id": "0fd4d0bd078281a1",
    "type": "api-current-state",
    "z": "6d9e82a8948d508f",
    "g": "4d66e46fdf014b28",
    "name": "",
    "server": "e593dd3.052432",
    "version": 3,
    "outputs": 2,
    "halt_if": "on",
    "halt_if_type": "str",
    "halt_if_compare": "is",
    "entity_id": "switch.smartplug_bottom_fan_switch",
    "state_type": "str",
    "blockInputOverrides": false,
    "outputProperties": [
      {
        "property": "payload",
        "propertyType": "msg",
        "value": "",
        "valueType": "entityState"
      },
      {
        "property": "data",
        "propertyType": "msg",
        "value": "",
        "valueType": "entity"
      }
    ],
    "for": "0",
    "forType": "num",
    "forUnits": "minutes",
    "override_topic": false,
    "state_location": "payload",
    "override_payload": "msg",
    "entity_location": "data",
    "override_data": "msg",
    "x": 750,
    "y": 100,
    "wires": [
      [
        "1b71cc1de3464325"
      ],
      [
        "73ffcdfc1958de42"
      ]
    ]
  },
  {
    "id": "e6c428dab477e438",
    "type": "api-current-state",
    "z": "6d9e82a8948d508f",
    "g": "4d66e46fdf014b28",
    "name": "",
    "server": "e593dd3.052432",
    "version": 3,
    "outputs": 2,
    "halt_if": "on",
    "halt_if_type": "str",
    "halt_if_compare": "is",
    "entity_id": "switch.smartplug_bottom_fan_switch",
    "state_type": "str",
    "blockInputOverrides": false,
    "outputProperties": [
      {
        "property": "payload",
        "propertyType": "msg",
        "value": "",
        "valueType": "entityState"
      },
      {
        "property": "data",
        "propertyType": "msg",
        "value": "",
        "valueType": "entity"
      }
    ],
    "for": "0",
    "forType": "num",
    "forUnits": "minutes",
    "override_topic": false,
    "state_location": "payload",
    "override_payload": "msg",
    "entity_location": "data",
    "override_data": "msg",
    "x": 750,
    "y": 280,
    "wires": [
      [
        "49bcb9da63a5e46f"
      ],
      [
        "775a4b1771455dfc"
      ]
    ]
  },
  {
    "id": "1b71cc1de3464325",
    "type": "api-call-service",
    "z": "6d9e82a8948d508f",
    "g": "4d66e46fdf014b28",
    "name": "",
    "server": "e593dd3.052432",
    "version": 5,
    "debugenabled": false,
    "domain": "switch",
    "service": "turn_off",
    "areaId": [],
    "deviceId": [],
    "entityId": [
      "switch.smartplug_bottom_fan_switch"
    ],
    "data": "",
    "dataType": "jsonata",
    "mergeContext": "",
    "mustacheAltTags": false,
    "outputProperties": [
      {
        "property": "payload",
        "propertyType": "msg",
        "value": "OFF",
        "valueType": "str"
      }
    ],
    "queue": "none",
    "x": 1080,
    "y": 60,
    "wires": [
      [
        "a94ba14e2b1859c8"
      ]
    ]
  },
  {
    "id": "73ffcdfc1958de42",
    "type": "api-call-service",
    "z": "6d9e82a8948d508f",
    "g": "4d66e46fdf014b28",
    "name": "",
    "server": "e593dd3.052432",
    "version": 5,
    "debugenabled": false,
    "domain": "switch",
    "service": "turn_on",
    "areaId": [],
    "deviceId": [],
    "entityId": [
      "switch.smartplug_bottom_fan_switch"
    ],
    "data": "",
    "dataType": "jsonata",
    "mergeContext": "",
    "mustacheAltTags": false,
    "outputProperties": [
      {
        "property": "payload",
        "propertyType": "msg",
        "value": "ON",
        "valueType": "str"
      }
    ],
    "queue": "none",
    "x": 1080,
    "y": 140,
    "wires": [
      [
        "a94ba14e2b1859c8"
      ]
    ]
  },
  {
    "id": "a94ba14e2b1859c8",
    "type": "change",
    "z": "6d9e82a8948d508f",
    "g": "4d66e46fdf014b28",
    "name": "Set notification attributes",
    "rules": [
      {
        "t": "set",
        "p": "title",
        "pt": "msg",
        "to": "Server Rack",
        "tot": "str"
      },
      {
        "t": "set",
        "p": "message1",
        "pt": "msg",
        "to": "The bottom fan has been turned:",
        "tot": "str"
      },
      {
        "t": "set",
        "p": "message2",
        "pt": "msg",
        "to": "payload",
        "tot": "msg"
      },
      {
        "t": "set",
        "p": "message3",
        "pt": "msg",
        "to": "",
        "tot": "str"
      },
      {
        "t": "set",
        "p": "critical",
        "pt": "msg",
        "to": "0",
        "tot": "str"
      },
      {
        "t": "set",
        "p": "sound",
        "pt": "msg",
        "to": "default",
        "tot": "str"
      },
      {
        "t": "set",
        "p": "volume",
        "pt": "msg",
        "to": "0.5",
        "tot": "str"
      },
      {
        "t": "set",
        "p": "target",
        "pt": "msg",
        "to": "mobile_app_reynier_iphone",
        "tot": "str"
      },
      {
        "t": "set",
        "p": "entity_id",
        "pt": "msg",
        "to": "",
        "tot": "str"
      },
      {
        "t": "set",
        "p": "friendly_name",
        "pt": "msg",
        "to": "",
        "tot": "str"
      },
      {
        "t": "set",
        "p": "event_action",
        "pt": "msg",
        "to": "",
        "tot": "str"
      },
      {
        "t": "set",
        "p": "event_action_title",
        "pt": "msg",
        "to": "",
        "tot": "str"
      }
    ],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 1350,
    "y": 100,
    "wires": [
      [
        "71d6d13e3de86cf5"
      ]
    ]
  },
  {
    "id": "71d6d13e3de86cf5",
    "type": "link out",
    "z": "6d9e82a8948d508f",
    "g": "4d66e46fdf014b28",
    "name": "",
    "mode": "link",
    "links": [
      "b6171fec.b478f"
    ],
    "x": 1515,
    "y": 100,
    "wires": []
  },
  {
    "id": "49bcb9da63a5e46f",
    "type": "api-call-service",
    "z": "6d9e82a8948d508f",
    "g": "4d66e46fdf014b28",
    "name": "",
    "server": "e593dd3.052432",
    "version": 5,
    "debugenabled": false,
    "domain": "switch",
    "service": "turn_off",
    "areaId": [],
    "deviceId": [
      "bd76567dec27ab2b7e2234b19e56452d"
    ],
    "entityId": [],
    "data": "",
    "dataType": "jsonata",
    "mergeContext": "",
    "mustacheAltTags": false,
    "outputProperties": [
      {
        "property": "payload",
        "propertyType": "msg",
        "value": "OFF",
        "valueType": "str"
      }
    ],
    "queue": "none",
    "x": 1100,
    "y": 240,
    "wires": [
      []
    ]
  },
  {
    "id": "775a4b1771455dfc",
    "type": "api-call-service",
    "z": "6d9e82a8948d508f",
    "g": "4d66e46fdf014b28",
    "name": "",
    "server": "e593dd3.052432",
    "version": 5,
    "debugenabled": false,
    "domain": "switch",
    "service": "turn_on",
    "areaId": [],
    "deviceId": [
      "bd76567dec27ab2b7e2234b19e56452d"
    ],
    "entityId": [],
    "data": "",
    "dataType": "jsonata",
    "mergeContext": "",
    "mustacheAltTags": false,
    "outputProperties": [
      {
        "property": "payload",
        "propertyType": "msg",
        "value": "ON",
        "valueType": "str"
      }
    ],
    "queue": "none",
    "x": 1100,
    "y": 320,
    "wires": [
      []
    ]
  },
  {
    "id": "2d2c5b3a996cd962",
    "type": "comment",
    "z": "6d9e82a8948d508f",
    "g": "4d66e46fdf014b28",
    "name": "Check every 1h",
    "info": "",
    "x": 140,
    "y": 60,
    "wires": []
  },
  {
    "id": "36678338ef5ba40f",
    "type": "comment",
    "z": "6d9e82a8948d508f",
    "g": "4d66e46fdf014b28",
    "name": "Check every 30m",
    "info": "",
    "x": 140,
    "y": 240,
    "wires": []
  },
  {
    "id": "e593dd3.052432",
    "type": "server",
    "name": "Home Assistant",
    "addon": true
  }
]

I want to go beyond and do something like:

if it is daytime then keep the fans running for one hour stop them for 30 min then run them again for the next hour and so on. If it is nighttime then I want the opposite keep them running for 30 minutes and have them stopped for one hour.

As you can see I am using an Inject node which injects a timestamp every hour or every 30 min but this will not allow me to do what I am looking for.

Can I get some ideas? or if you have something similar can you share it with me?

You have the same start time for each scenario, every hour and a half. It’s only the shut off that differs so this should work.

[{"id":"4061857826bd2276","type":"inject","z":"60f2d2277843c698","name":"every 90 minutes","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"5400","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":230,"y":1480,"wires":[["d07c0c100d12a456"]]},{"id":"d07c0c100d12a456","type":"api-call-service","z":"60f2d2277843c698","name":"turn on fan","server":"6b1110b5.183a4","version":5,"debugenabled":false,"domain":"","service":"","areaId":[],"deviceId":[],"entityId":[],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":430,"y":1480,"wires":[["6bfa0a5515c184a8"]]},{"id":"6bfa0a5515c184a8","type":"time-range-switch","z":"60f2d2277843c698","name":"","lat":"","lon":"","startTime":"sunrise","endTime":"sunset","startOffset":0,"endOffset":0,"x":620,"y":1480,"wires":[["ac167bb3113025b0"],["128392986be75237"]]},{"id":"128392986be75237","type":"trigger","z":"60f2d2277843c698","name":"shut off after 30 min","op1":"","op2":"0","op1type":"nul","op2type":"str","duration":"30","extend":false,"overrideDelay":false,"units":"min","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":880,"y":1500,"wires":[["08ad5918a5517325"]]},{"id":"ac167bb3113025b0","type":"trigger","z":"60f2d2277843c698","name":"shut off after an hour","op1":"","op2":"0","op1type":"nul","op2type":"str","duration":"1","extend":false,"overrideDelay":false,"units":"hr","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":880,"y":1460,"wires":[["08ad5918a5517325"]]},{"id":"08ad5918a5517325","type":"api-call-service","z":"60f2d2277843c698","name":"fan turn off","server":"6b1110b5.183a4","version":5,"debugenabled":false,"domain":"","service":"","areaId":[],"deviceId":[],"entityId":[],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1130,"y":1480,"wires":[[]]},{"id":"6b1110b5.183a4","type":"server","name":"Home Assistant","version":5,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":false,"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}]

Wouldn’t that keep the fan running until sunset all the time? where or how does it check whether the fan has been running for one hour and then turn it off for the next 30 minutes?

Every 90 minutes the fan turns on in both scenario’s, the first 2 nodes in the flow. Depending on the time of day (orange node) it will activate either the shut off in an hour node or the shut off in a half hour. One will wait 30 minutes before sending the off trigger the other will wait 60.

if you look in the trigger nodes you will see when it receives a message it does nothing. Then waits 30/60 minutes and then sends a message to the turn off fan call service.

image

1 Like

I am running your suggestion now. Let’s see how it behaves:

I believe there is more room for improvements as for example:

  • I am waiting until the fans gets on/off and then if the time is before 22:00 then I will send a message to my phone but as you can see this is repeated twice. Do you see a way to not repeat them?
[{"id":"b176980c50a6efdd","type":"group","z":"6d9e82a8948d508f","name":"Server Rack Fans Control","style":{"label":true},"nodes":["2d02337c567650f8","e4cb1fadb9792fb5","aa4f51bd9ac2e333","e1596a88e14c542d","0e270d0ae99a2553","1dc229d07d2983fc","0e17eccc1078d13f","bfae43d31d566272","a04487677fcf92b3","ad45c15f630fc814","4ba715fa51552872","b8f346b0982ba437","2c3fd1e1a4b32792","306d4d5db31254a3"],"x":14,"y":39,"w":1882,"h":242},{"id":"2d02337c567650f8","type":"inject","z":"6d9e82a8948d508f","g":"b176980c50a6efdd","name":"Every 90 minutes ","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"5400","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":150,"y":120,"wires":[["e4cb1fadb9792fb5"]]},{"id":"e4cb1fadb9792fb5","type":"api-call-service","z":"6d9e82a8948d508f","g":"b176980c50a6efdd","name":"","server":"e593dd3.052432","version":5,"debugenabled":false,"domain":"switch","service":"turn_on","areaId":[],"deviceId":[],"entityId":["switch.rackfans"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":380,"y":120,"wires":[["306d4d5db31254a3","0e17eccc1078d13f"]]},{"id":"aa4f51bd9ac2e333","type":"trigger","z":"6d9e82a8948d508f","g":"b176980c50a6efdd","name":"","op1":"","op2":"0","op1type":"pay","op2type":"str","duration":"60","extend":false,"overrideDelay":false,"units":"min","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":810,"y":80,"wires":[["0e270d0ae99a2553"]]},{"id":"e1596a88e14c542d","type":"trigger","z":"6d9e82a8948d508f","g":"b176980c50a6efdd","name":"","op1":"","op2":"0","op1type":"pay","op2type":"str","duration":"30","extend":false,"overrideDelay":false,"units":"min","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":810,"y":160,"wires":[["0e270d0ae99a2553"]]},{"id":"0e270d0ae99a2553","type":"api-call-service","z":"6d9e82a8948d508f","g":"b176980c50a6efdd","name":"","server":"e593dd3.052432","version":5,"debugenabled":false,"domain":"switch","service":"turn_off","areaId":[],"deviceId":[],"entityId":["switch.rackfans"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1040,"y":120,"wires":[["ad45c15f630fc814"]]},{"id":"1dc229d07d2983fc","type":"time-range-switch","z":"6d9e82a8948d508f","g":"b176980c50a6efdd","name":"","lat":"28.496890","lon":"-82.553900","startTime":"08:00","endTime":"22:00","startOffset":0,"endOffset":0,"x":730,"y":240,"wires":[["bfae43d31d566272"],[]]},{"id":"0e17eccc1078d13f","type":"ha-wait-until","z":"6d9e82a8948d508f","g":"b176980c50a6efdd","name":"","server":"e593dd3.052432","version":2,"outputs":2,"entityId":"switch.rackfans","entityIdFilterType":"exact","property":"state","comparator":"is","value":"on","valueType":"str","timeout":"30","timeoutType":"num","timeoutUnits":"seconds","checkCurrentState":true,"blockInputOverrides":true,"outputProperties":[{"property":"payload","propertyType":"msg","value":"ON","valueType":"str"}],"entityLocation":"data","entityLocationType":"none","x":560,"y":240,"wires":[["1dc229d07d2983fc"],[]]},{"id":"bfae43d31d566272","type":"change","z":"6d9e82a8948d508f","g":"b176980c50a6efdd","name":"Set notification attributes","rules":[{"t":"set","p":"title","pt":"msg","to":"Server Rack","tot":"str"},{"t":"set","p":"message1","pt":"msg","to":"The bottom fan has been turned:","tot":"str"},{"t":"set","p":"message2","pt":"msg","to":"payload","tot":"msg"},{"t":"set","p":"message3","pt":"msg","to":"","tot":"str"},{"t":"set","p":"critical","pt":"msg","to":"0","tot":"str"},{"t":"set","p":"sound","pt":"msg","to":"default","tot":"str"},{"t":"set","p":"volume","pt":"msg","to":"0.5","tot":"str"},{"t":"set","p":"target","pt":"msg","to":"mobile_app_reynier_iphone","tot":"str"},{"t":"set","p":"entity_id","pt":"msg","to":"","tot":"str"},{"t":"set","p":"friendly_name","pt":"msg","to":"","tot":"str"},{"t":"set","p":"event_action","pt":"msg","to":"","tot":"str"},{"t":"set","p":"event_action_title","pt":"msg","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":990,"y":240,"wires":[["a04487677fcf92b3"]]},{"id":"a04487677fcf92b3","type":"link out","z":"6d9e82a8948d508f","g":"b176980c50a6efdd","name":"","mode":"link","links":["b6171fec.b478f"],"x":1155,"y":240,"wires":[]},{"id":"ad45c15f630fc814","type":"ha-wait-until","z":"6d9e82a8948d508f","g":"b176980c50a6efdd","name":"","server":"e593dd3.052432","version":2,"outputs":2,"entityId":"switch.rackfans","entityIdFilterType":"exact","property":"state","comparator":"is","value":"off","valueType":"str","timeout":"30","timeoutType":"num","timeoutUnits":"seconds","checkCurrentState":true,"blockInputOverrides":true,"outputProperties":[{"property":"payload","propertyType":"msg","value":"OFF","valueType":"str"}],"entityLocation":"data","entityLocationType":"none","x":1240,"y":120,"wires":[["4ba715fa51552872"],[]]},{"id":"4ba715fa51552872","type":"time-range-switch","z":"6d9e82a8948d508f","g":"b176980c50a6efdd","name":"","lat":"28.496890","lon":"-82.553900","startTime":"08:00","endTime":"22:00","startOffset":0,"endOffset":0,"x":1430,"y":120,"wires":[["b8f346b0982ba437"],[]]},{"id":"b8f346b0982ba437","type":"change","z":"6d9e82a8948d508f","g":"b176980c50a6efdd","name":"Set notification attributes","rules":[{"t":"set","p":"title","pt":"msg","to":"Server Rack","tot":"str"},{"t":"set","p":"message1","pt":"msg","to":"The bottom fan has been turned:","tot":"str"},{"t":"set","p":"message2","pt":"msg","to":"payload","tot":"msg"},{"t":"set","p":"message3","pt":"msg","to":"","tot":"str"},{"t":"set","p":"critical","pt":"msg","to":"0","tot":"str"},{"t":"set","p":"sound","pt":"msg","to":"default","tot":"str"},{"t":"set","p":"volume","pt":"msg","to":"0.5","tot":"str"},{"t":"set","p":"target","pt":"msg","to":"mobile_app_reynier_iphone","tot":"str"},{"t":"set","p":"entity_id","pt":"msg","to":"","tot":"str"},{"t":"set","p":"friendly_name","pt":"msg","to":"","tot":"str"},{"t":"set","p":"event_action","pt":"msg","to":"","tot":"str"},{"t":"set","p":"event_action_title","pt":"msg","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1690,"y":120,"wires":[["2c3fd1e1a4b32792"]]},{"id":"2c3fd1e1a4b32792","type":"link out","z":"6d9e82a8948d508f","g":"b176980c50a6efdd","name":"","mode":"link","links":["b6171fec.b478f"],"x":1855,"y":120,"wires":[]},{"id":"306d4d5db31254a3","type":"time-range-switch","z":"6d9e82a8948d508f","g":"b176980c50a6efdd","name":"sunrise - sunset","lat":"28.496890","lon":"-82.553900","startTime":"07:28","endTime":"goldenHour","startOffset":0,"endOffset":0,"x":580,"y":120,"wires":[["aa4f51bd9ac2e333"],["e1596a88e14c542d"]]},{"id":"e593dd3.052432","type":"server","name":"Home Assistant","addon":true}]

You could remove the wait node and set a trigger for when the fans turn on and off. You’ll likely need to adjust the message paths for the change node. You would only need one change node to format the message.

[{"id":"5d3170949f3f2937","type":"trigger-state","z":"60f2d2277843c698","name":"","server":"","version":4,"inputs":0,"outputs":4,"exposeAsEntityConfig":"","entityId":"switch.rackfans","entityIdType":"exact","debugEnabled":false,"constraints":[],"customOutputs":[{"messageType":"custom","messageValue":"$outputData(\"eventData\")","messageValueType":"jsonata","comparatorPropertyType":"previous_state","comparatorPropertyValue":"old_state.state","comparatorType":"is","comparatorValue":"off","comparatorValueDataType":"str"},{"messageType":"custom","messageValue":"$outputData(\"eventData\")","messageValueType":"jsonata","comparatorPropertyType":"previous_state","comparatorPropertyValue":"old_state.state","comparatorType":"is","comparatorValue":"on","comparatorValueDataType":"str"}],"outputInitially":false,"stateType":"str","enableInput":false,"x":420,"y":1240,"wires":[[],[],["158894c5372fdf08","2314bca0d58b9256"],["c43e89de684d31d7","2314bca0d58b9256"]]},{"id":"158894c5372fdf08","type":"debug","z":"60f2d2277843c698","name":"on","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":790,"y":1200,"wires":[]},{"id":"c43e89de684d31d7","type":"debug","z":"60f2d2277843c698","name":"off","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":790,"y":1320,"wires":[]},{"id":"2314bca0d58b9256","type":"change","z":"60f2d2277843c698","name":"Set notification attributes","rules":[{"t":"set","p":"title","pt":"msg","to":"Server Rack","tot":"str"},{"t":"set","p":"message1","pt":"msg","to":"The bottom fan has been turned:","tot":"str"},{"t":"set","p":"message2","pt":"msg","to":"payload","tot":"msg"},{"t":"set","p":"message3","pt":"msg","to":"","tot":"str"},{"t":"set","p":"critical","pt":"msg","to":"0","tot":"str"},{"t":"set","p":"sound","pt":"msg","to":"default","tot":"str"},{"t":"set","p":"volume","pt":"msg","to":"0.5","tot":"str"},{"t":"set","p":"target","pt":"msg","to":"mobile_app_reynier_iphone","tot":"str"},{"t":"set","p":"entity_id","pt":"msg","to":"","tot":"str"},{"t":"set","p":"friendly_name","pt":"msg","to":"","tot":"str"},{"t":"set","p":"event_action","pt":"msg","to":"","tot":"str"},{"t":"set","p":"event_action_title","pt":"msg","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":790,"y":1260,"wires":[["297b66c9d8c26f8b"]]},{"id":"297b66c9d8c26f8b","type":"link out","z":"60f2d2277843c698","name":"","mode":"link","links":["b6171fec.b478f"],"x":985,"y":1260,"wires":[]}]
1 Like

The debug nodes are logging something like:

{
  "event_type": "state_changed",
  "entity_id": "switch.rackfans",
  "event": {
    "entity_id": "switch.rackfans",
    "old_state": {
      "entity_id": "switch.rackfans",
      "state": "on",
      "attributes": {
        "entity_id": [
          "switch.smartplug_top_fan_switch",
          "switch.smartplug_bottom_fan_switch"
        ],
        "friendly_name": "RackFans"
      },
      "last_changed": "2024-02-27T01:29:46.391362+00:00",
      "last_updated": "2024-02-27T01:29:46.391362+00:00",
      "context": {
        "id": "01HQM2X837TBWEMHAGNPXZQEXQ",
        "parent_id": null,
        "user_id": "b36d903e5a904732811c3ccab3503bcb"
      }
    },
    "new_state": {
      "entity_id": "switch.rackfans",
      "state": "off",
      "attributes": {
        "entity_id": [
          "switch.smartplug_top_fan_switch",
          "switch.smartplug_bottom_fan_switch"
        ],
        "friendly_name": "RackFans"
      },
      "last_changed": "2024-02-27T01:33:39.379938+00:00",
      "last_updated": "2024-02-27T01:33:39.379938+00:00",
      "context": {
        "id": "01HQM34BK7KS0J07K5N415CJH0",
        "parent_id": null,
        "user_id": "b36d903e5a904732811c3ccab3503bcb"
      },
      "timeSinceChangedMs": 4
    }
  },
  "origin": "LOCAL",
  "time_fired": "2024-02-27T01:33:39.379938+00:00",
  "context": {
    "id": "01HQM34BK7KS0J07K5N415CJH0",
    "parent_id": null,
    "user_id": "b36d903e5a904732811c3ccab3503bcb"
  },
  "_msgid": "e5d40eb8957ebe36"
}

do I need to traverse all the output down to the new_state.state to get the off/on string or do you see an easy way?

In the change node “message 2” is the state? So instead of payload

image

1 Like

I may not explain myself correctly but this does not seem to be working. Check the following screenshot:

the call service node to turn on the fans was called at 5:33 AM, that is still within sunset, and right away the call service node to turn off the fan was called. Right now fans has been off during all the sunset.

Here is a detailed explanation for what I was trying to do and apologies if this was not clear in advance:

  • From 8 AM to 8 PM (sunrise can be used here it does not matter to me): fans should run for an hour and stop for 30 min
  • From 8 PM to 8 AM (sunset can be used here): fans should run for 30 min and stop for an hour

Let’s say I started NodeRED at 8AM and fans are running, after 1 hour the should turn off for the next 30 min and then go back to on for another hour and so on.

I might be missing something from your above explanation so I am leaving the JSON here so you can take a closer look.

[
    {
        "id": "2d02337c567650f8",
        "type": "inject",
        "z": "6d9e82a8948d508f",
        "name": "Every 90 minutes ",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "5400",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 170,
        "y": 120,
        "wires": [
            [
                "e4cb1fadb9792fb5"
            ]
        ]
    },
    {
        "id": "e4cb1fadb9792fb5",
        "type": "api-call-service",
        "z": "6d9e82a8948d508f",
        "name": "",
        "server": "e593dd3.052432",
        "version": 5,
        "debugenabled": false,
        "domain": "switch",
        "service": "turn_on",
        "areaId": [],
        "deviceId": [],
        "entityId": [
            "switch.rackfans"
        ],
        "data": "",
        "dataType": "jsonata",
        "mergeContext": "",
        "mustacheAltTags": false,
        "outputProperties": [],
        "queue": "none",
        "x": 400,
        "y": 120,
        "wires": [
            [
                "306d4d5db31254a3"
            ]
        ]
    },
    {
        "id": "306d4d5db31254a3",
        "type": "time-range-switch",
        "z": "6d9e82a8948d508f",
        "name": "sunrise - sunset",
        "lat": "28.496890",
        "lon": "-82.553900",
        "startTime": "07:28",
        "endTime": "goldenHour",
        "startOffset": 0,
        "endOffset": 0,
        "x": 660,
        "y": 120,
        "wires": [
            [
                "aa4f51bd9ac2e333"
            ],
            [
                "e1596a88e14c542d"
            ]
        ]
    },
    {
        "id": "aa4f51bd9ac2e333",
        "type": "trigger",
        "z": "6d9e82a8948d508f",
        "name": "",
        "op1": "",
        "op2": "0",
        "op1type": "pay",
        "op2type": "str",
        "duration": "60",
        "extend": false,
        "overrideDelay": false,
        "units": "min",
        "reset": "",
        "bytopic": "all",
        "topic": "topic",
        "outputs": 1,
        "x": 890,
        "y": 80,
        "wires": [
            [
                "0e270d0ae99a2553"
            ]
        ]
    },
    {
        "id": "e1596a88e14c542d",
        "type": "trigger",
        "z": "6d9e82a8948d508f",
        "name": "",
        "op1": "",
        "op2": "0",
        "op1type": "pay",
        "op2type": "str",
        "duration": "30",
        "extend": false,
        "overrideDelay": false,
        "units": "min",
        "reset": "",
        "bytopic": "all",
        "topic": "topic",
        "outputs": 1,
        "x": 890,
        "y": 160,
        "wires": [
            [
                "0e270d0ae99a2553"
            ]
        ]
    },
    {
        "id": "0e270d0ae99a2553",
        "type": "api-call-service",
        "z": "6d9e82a8948d508f",
        "name": "",
        "server": "e593dd3.052432",
        "version": 5,
        "debugenabled": false,
        "domain": "switch",
        "service": "turn_off",
        "areaId": [],
        "deviceId": [],
        "entityId": [
            "switch.rackfans"
        ],
        "data": "",
        "dataType": "jsonata",
        "mergeContext": "",
        "mustacheAltTags": false,
        "outputProperties": [],
        "queue": "none",
        "x": 1140,
        "y": 120,
        "wires": [
            []
        ]
    },
    {
        "id": "e593dd3.052432",
        "type": "server",
        "name": "Home Assistant",
        "addon": true
    }
]

one more time, thank you so much for taking a time to look into this and try to help me out, much appreciated

It seems you changed the settings in the trigger nodes. When the message arrives it should be set to send nothing. You have it set so it sends a message immediately instead of waiting the allotted time.

you have

image

Should be

That is why it shuts off immediately.

1 Like

this is working now, however, I do not quite understand what’s the difference between sending “something” from sending “nothing”. Could you explain this a little bit so I understand it properly for future reference?

What is not working yet is the notification and I do not get why because the message is coming to the debug node and I am seeing the path being correct however is not coming to the “Set notification attributes” node :confused:

In the way nodered works when a message hits a node, that node will execute the code inside it. Then it sends a message that triggers the next node, so on and so forth.

With the trigger, setting it to send nothing, when a message is received, it does not pass the message on, instead it holds that message until the time runs down and then sends it. It is basically working as a delay.

Another way to use it, example:

image

[{"id":"022630612f7a0bc1","type":"inject","z":"60f2d2277843c698","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":240,"y":900,"wires":[["3dc33f2d01d3b155"]]},{"id":"3dc33f2d01d3b155","type":"trigger","z":"60f2d2277843c698","name":"","op1":"on","op2":"off","op1type":"str","op2type":"str","duration":"5","extend":false,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":420,"y":900,"wires":[["71ac962322ed9c3c"]]},{"id":"71ac962322ed9c3c","type":"api-call-service","z":"60f2d2277843c698","name":"","server":"6b1110b5.183a4","version":5,"debugenabled":false,"domain":"light","service":"turn_{{payload}}","areaId":[],"deviceId":[],"entityId":[],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":640,"y":900,"wires":[[]]},{"id":"6b1110b5.183a4","type":"server","name":"Home Assistant","version":5,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":false,"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}]

when a message arrives, the trigger immediately sends on then it will wait 5 seconds then send another message off

image

Put a light entity in the above flow to try it.

This needs to be continous, btw if the box is red that means the message format is wrong.

image

event.new_state.state

As you asked, and for general interest only, here is another idea for how to approach something like this.

Yes, there are many ways to do this. For myself, I have found that a simple delay node in a repeating loop can often do what I want, using a calculated msg.delay in milliseconds in the input message to set a variable delay period.

The call service node can be used for both ‘on’ and ‘off’ by sending in the required settings using msg.payload, and in your case all we really need to do is turn the switch on (or off) and set a delay for the next off (or on), then loop back to the call service node and so on ad nauseam.

This is the flow I built from your requirements. As you can see, I am going for the ‘least number of nodes required’ award this week, as I only need three nodes. An inject node to set the thing going, a call service node to do the switching (and calculations) and a delay node to wait for the next switch event.

The simplicity of the flow hides the complexity of the calculations - in effect the flow has to manage itself. At each ‘call service’ action, there is some code that recalculates the current switching requirement, sets up the delay period, and the next switching action required. This is therefore neither visually obvious as to what is going on, nor exactly easy to write and maintain, however it does work (I have tested it carefully).

In your situation, given the requirement for either 60 mins ON and 30 mins OFF, or 30 mins ON and 60 mins OFF, the sequence is 90 minutes, which fits into 24 hours neatly.

As you ideally want the fans to start ‘on’ at 08:00, I have built the calculations so that you can define the period (90 minutes) the ‘day’ on period (60 minutes) the ‘night’ on period (30 minutes) and the day period (08:00 inclusive to 20:00 not inclusive) as well as the ‘sync to’ time (08:00) so that the on periods will start at the sync to time and run accordingly.

To get the flow started, we inject a basic message that turns the fans ‘off’ and then does the calculations in the call service node output properties. If ‘now’ is actually in an ‘on’ period, the delay is set to 0 and the next action is set to ‘on’, so the service call happens again to turn on immediately. If ‘now’ is an ‘off’ period, the correct delay for the next ‘on’ to align with the on sequence is calculated, and the flow will go from there.

This may sound rather complicated, but it does provide a fully parameterised flow, which means that it would be possible for example to adjust the ‘on’ periods in the flow, using another (eg temperature) sensor input. Turning the flow off is provided for using a second inject, but again with a msg.loop control it is possible to start and stop the loop from other inputs. The delay node accepts inputs for reset, and flush, which means the next queued message (say of ‘on’) could be triggered early by adding a ‘flush’ input from an input button (‘boost’).

I have several (more complicated) loops like this running all the time, used to poll solar inverter and battery information on a variable-time basis. In general, loops in Node-RED are not a good idea, and it is essential to ensure that there is no opportunity for catastrophic runaway or memory leaks. I always test loop development with a rate-limit node, provide an ‘emergency stop’ input somewhere, and I have found it necessary to avoid message growth, especially when using http requests. Also, the use of ‘var’ in JavaScript in a function node is a very bad idea!

Here is the code, for anyone who is interested:

Note that I am using sensor.time to read the current local time for the calculations. This has to be added using the time and date integration, and provides a really useful way to get local and UTC time / date for calculations.
You will need to change the entity id as required - all the settings are in the inject node.

[{"id":"2f0ab8bae6cfe098","type":"api-call-service","z":"1cc7d2e94a4815fe","name":"","server":"","version":5,"debugenabled":false,"domain":"","service":"","areaId":[],"deviceId":[],"entityId":[],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[{"property":"timecalcs","propertyType":"msg","value":"(\t/* FUNCTION: get minutes in day from 'hh:mm' */\t    $getmins:=function($t){(\t        $x:=$split($t,\":\").$number();\t        60*$x[0] + $x[1]\t    )};\t\t/* MAIN */\t\t    $cycle:=settings.cycle;\t    $syncd:=settings.syncto;\t\t    $time:=$entities('sensor.time').state;\t    $isday:= $time>=settings.daytime[0] and $time<settings.daytime[1];\t\t    $mtime:=$getmins($time);\t    $first:=$getmins($syncd) % $cycle;\t\t    $position:=($mtime +$cycle -$first) % $cycle;\t    $syncmins:= $cycle-$position;\t\t    $onfor:= $isday ? settings.dayontime : settings.nightontime;\t    $ison:=  $position+1 <= $onfor;\t\t    $this:= $ison ? \"ON\" : \"OFF\";\t    $next:= $ison ? \"turn_off\" : \"turn_on\";\t\t    $delay:= $ison ? ($onfor - $position) : ($cycle - $position);\t\t    {\"time\": $time,\t    \"isday\": $isday,\t    \"first\": $first,\t    \"position\": $position,\t    \"syncmins\": $syncmins,\t    \"onfortime\": $onfor,\t    \"isonnow\": $ison,\t    \"this\": $this,\t    \"next\": $next,\t    \"delay\": $delay\t    }\t\t)","valueType":"jsonata"},{"property":"delay","propertyType":"msg","value":"    (loop=\"start\" and timecalcs.isonnow) or loop=\"stop\" ? 0 : timecalcs.delay*60000","valueType":"jsonata"},{"property":"switchfans","propertyType":"msg","value":"payload.service=\"turn_on\" ? \"ON\" : \"OFF\"","valueType":"jsonata"},{"property":"payload","propertyType":"msg","value":"(\t    $action:=loop=\"start\" and timecalcs.isonnow ? \"turn_on\" : loop=\"stop\" ? \"turn_off\" : timecalcs.next;\t    payload~>|$|{\"service\": $action}|;\t)","valueType":"jsonata"},{"property":"loop","propertyType":"msg","value":"loop=\"start\" ? \"run\" : loop","valueType":"jsonata"},{"property":"reset","propertyType":"msg","value":"loop=\"stop\" ? true : [1][1]","valueType":"jsonata"}],"queue":"none","x":490,"y":2160,"wires":[["5a1981878974943b","9d3fa2b1cf403d08","0f37b2adf6c45bec"]]},{"id":"09dfd5f894a604b3","type":"inject","z":"1cc7d2e94a4815fe","name":"Startup","props":[{"p":"loop","v":"start","vt":"str"},{"p":"starting","v":"turn_off","vt":"str"},{"p":"settings","v":"{\"cycle\":90,\"syncto\":\"08:00\",\"daytime\":[\"08:00\",\"20:00\"],\"dayontime\":60,\"nightontime\":30}","vt":"json"},{"p":"entitylist","v":"[\"switch.t1_2\", \"switch.t2_2\"]","vt":"json"},{"p":"payload"}],"repeat":"","crontab":"","once":true,"onceDelay":"3","topic":"","payload":"{\t   \"domain\": \"switch\",\t   \"service\": starting,\t   \"target\": {\t       \"entity_id\": entitylist\t    }\t}","payloadType":"jsonata","x":260,"y":2160,"wires":[["2f0ab8bae6cfe098"]]},{"id":"f700d770a75645d9","type":"inject","z":"1cc7d2e94a4815fe","name":"Manual STOP","props":[{"p":"loop","v":"stop","vt":"str"},{"p":"entitylist","v":"[\"switch.t1_2\", \"switch.t2_2\"]","vt":"json"},{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":"5","topic":"","payload":"{\t   \"domain\": \"switch\",\t   \"service\": \"turn_off\",\t   \"target\": {\t       \"entity_id\": entitylist\t    }\t}","payloadType":"jsonata","x":250,"y":2200,"wires":[["2f0ab8bae6cfe098"]]},{"id":"5a1981878974943b","type":"debug","z":"1cc7d2e94a4815fe","name":"Fans","active":false,"tosidebar":true,"console":false,"tostatus":true,"complete":"switchfans","targetType":"msg","statusVal":"timecalcs.switchfans","statusType":"auto","x":770,"y":2100,"wires":[]},{"id":"9d3fa2b1cf403d08","type":"delay","z":"1cc7d2e94a4815fe","name":"Wait","pauseType":"delayv","timeout":"30","timeoutUnits":"hours","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":770,"y":2160,"wires":[["2f0ab8bae6cfe098"]]},{"id":"0f37b2adf6c45bec","type":"debug","z":"1cc7d2e94a4815fe","name":"Delay Min","active":true,"tosidebar":false,"console":false,"tostatus":true,"complete":"timecalcs.delay","targetType":"msg","statusVal":"timecalcs.switchfans","statusType":"auto","x":640,"y":2100,"wires":[]}]
1 Like

this is neat, both of you are awesome, thank you, guys! I have learn something new on this challenging flow

Hmm, I am having some issues with the following flow and I am not sure what the fix would be. The issue is that I am receiving a 2nd notification with the message undefined which makes sense because the fans can be only on or off. When they turn on then I get the right message saying they were turned on but also get a second message with undefined and I believe that’s because they are not off. How can this be fixed?:

[
    {
        "id": "003330c559c7b80d",
        "type": "trigger-state",
        "z": "6d9e82a8948d508f",
        "name": "",
        "server": "e593dd3.052432",
        "version": 4,
        "inputs": 0,
        "outputs": 4,
        "exposeAsEntityConfig": "",
        "entityId": "switch.rackfans",
        "entityIdType": "exact",
        "debugEnabled": false,
        "constraints": [],
        "customOutputs": [
            {
                "messageType": "custom",
                "messageValue": "$outputData(\"eventData\")",
                "messageValueType": "jsonata",
                "comparatorPropertyType": "previous_state",
                "comparatorPropertyValue": "old_state.state",
                "comparatorType": "is",
                "comparatorValue": "off",
                "comparatorValueDataType": "str"
            },
            {
                "messageType": "custom",
                "messageValue": "$outputData(\"eventData\")",
                "messageValueType": "jsonata",
                "comparatorPropertyType": "previous_state",
                "comparatorPropertyValue": "old_state.state",
                "comparatorType": "is",
                "comparatorValue": "on",
                "comparatorValueDataType": "str"
            }
        ],
        "outputInitially": false,
        "stateType": "str",
        "enableInput": false,
        "x": 200,
        "y": 260,
        "wires": [
            [],
            [],
            [
                "805e6c17a4863f88",
                "4eeede7befb1931b"
            ],
            [
                "a9d254e39ce6cf5b",
                "4eeede7befb1931b"
            ]
        ]
    },
    {
        "id": "805e6c17a4863f88",
        "type": "debug",
        "z": "6d9e82a8948d508f",
        "name": "on",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 570,
        "y": 220,
        "wires": []
    },
    {
        "id": "a9d254e39ce6cf5b",
        "type": "debug",
        "z": "6d9e82a8948d508f",
        "name": "off",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 570,
        "y": 340,
        "wires": []
    },
    {
        "id": "4eeede7befb1931b",
        "type": "change",
        "z": "6d9e82a8948d508f",
        "name": "Set notification attributes",
        "rules": [
            {
                "t": "set",
                "p": "title",
                "pt": "msg",
                "to": "Server Rack",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "message1",
                "pt": "msg",
                "to": "The bottom fan has been turned:",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "message2",
                "pt": "msg",
                "to": "event. new_state. state",
                "tot": "jsonata"
            },
            {
                "t": "set",
                "p": "message3",
                "pt": "msg",
                "to": "",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "critical",
                "pt": "msg",
                "to": "0",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "sound",
                "pt": "msg",
                "to": "default",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "volume",
                "pt": "msg",
                "to": "0.5",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "target",
                "pt": "msg",
                "to": "mobile_app_reynier_iphone",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "entity_id",
                "pt": "msg",
                "to": "",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "friendly_name",
                "pt": "msg",
                "to": "",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "event_action",
                "pt": "msg",
                "to": "",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "event_action_title",
                "pt": "msg",
                "to": "",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 570,
        "y": 280,
        "wires": [
            [
                "e532694baa48bfcf"
            ]
        ]
    },
    {
        "id": "e532694baa48bfcf",
        "type": "link out",
        "z": "6d9e82a8948d508f",
        "name": "",
        "mode": "link",
        "links": [
            "b6171fec.b478f"
        ],
        "x": 765,
        "y": 280,
        "wires": []
    },
    {
        "id": "e593dd3.052432",
        "type": "server",
        "name": "Home Assistant",
        "addon": true
    }
]

I’m surprised that you are getting either on or off. Can you confirm that on your deployed flow has the spacing shown below?

image

there should be no spaces event.new_state.state

Here, are you trying to delete these messages? Use the delete option(see last entry)

image

If you still get undefined, it is looking for a message part that isn’t there. Meaning the on and off message differ. You would need a separate change nodes for each output to account for the change.

1 Like

Yes, it had the space in between I am impressed how it was working for the one time but failing a second time … I fixed it, less see how it behaves, thank you