From Domoticz + LUA to HA+Node-red; sequence possible?

Hi there, first ‘real’ question on this forum from my side, so here goes. I’ve written a script in Domoticz which controls my outdoor lights, based on time, lux and motion sensors. This script is written in LUA with the ‘dzVents’ engine. I would like to get some advice on how to best do this with Node-Red.

For your information on my ‘experience level’; i am currently employed as a software architect with over 20+ years of experience and probably touched as much programming languages in the same time; so i am not afraid to put my entire LUA script in a ‘function’ block but still i think there are some bumps to take.

First i’ll paste the script i’ve written (for others to take inspiration from) and then give you a rundown per segment what it does. After each segment i will post the questions i have regarding how to do this in node-red.

return {
        active = true,
        on = {
                ['devices'] = {
                        'Voordeur - Beweging',
                        'Tuin - Beweging BBQ'
                },
                ['timer'] = {
                        'every minute'
                }
        },
        data = {
                insideStatus = { initial = nil },
                outsideStatus = { initial = nil }
        },
        execute = function(domoticz, item)
                -- -------------------------------------------------------------------------------
                -- Dimming variables
                -- -------------------------------------------------------------------------------
                local loweredPercentage = 10            -- When we sleep and the lights are on, the dimming level will be ...
                local normalPercentage = 20             -- When we are awake and the lights are on, the dimming level will be ...
                local highPercentage = 100              -- When movement is detected during the time frame that the lights should be on, the lights are brightend to ...
                local brightDurationMinMinutes = 3      -- For this amount of minutes ...
                local brightDurationMaxMinutes = 4      -- And if (after this amount of minutes) the lights are still bright, we dim them (safeguard for missing timer events)



                -- -------------------------------------------------------------------------------
                -- Supporting functions
                -- -------------------------------------------------------------------------------
                local log = function(msg)
                        domoticz.log(msg, domoticz.LOG_INFO)
                end

                local setDeviceToLevelAfterSecs = function(device, dimLevel, secondsBeforeWeChange)
                        -- Only continue if the device does not yet have this state
                        local stateToCheck = (dimLevel > 0)

                        -- Check state & make sure at least 'x' seconds have passed sinds the last update
                        if ((domoticz.devices(device).bState ~= stateToCheck) and (domoticz.devices(device).lastUpdate.secondsAgo >= secondsBeforeWeChange)) then
                                if (stateToCheck and (domoticz.devices(device).level ~= dimLevel)) then
                                        -- If we should be on and the level != the required level, set it to the right level
                                        domoticz.devices(device).dimTo(dimLevel)
                                else
                                        -- Else we should be off
                                        domoticz.devices(device).switchOff()
                                end
                        end
                end



                -- -------------------------------------------------------------------------------
                -- Calculate level to which the lights should dim
                -- -------------------------------------------------------------------------------

                -- This holds the current hour and minute (format HHMM)
                local currentHourAndMinutes = tonumber(os.date("%H%M"))

                -- By default, we dim to the 'normal' percentage
                local dimLevel = normalPercentage

                -- Between these times, we have a 'minimum' dimming level
                if ((currentHourAndMinutes >= 2130) or (currentHourAndMinutes < 0630)) then
                        dimLevel = loweredPercentage
                end



               -- -------------------------------------------------------------------------------
                -- In case script is triggered via a Timer
                -- -------------------------------------------------------------------------------
                if (item.isTimer) then
                        log('Script activated by a timer event')
                        local weightedLux = tonumber(domoticz.devices('Lux - Voordeur').lux);

                        -- -------------------------------------------------------------------------------
                        -- Determine current 'inside status'
                        -- -------------------------------------------------------------------------------
                        if (currentHourAndMinutes < 1200) then
                                if ((weightedLux > 15) and (domoticz.data.insideStatus ~= 'off')) then
                                        domoticz.data.insideStatus = 'off'

                                        -- Turn off lights
                                        domoticz.devices('Woonkamer - Spotjes').switchOff()
                                end
                        end

                        if (currentHourAndMinutes > 1200) then
                                if ((weightedLux < 15) and (domoticz.data.insideStatus ~= 'evening')) then
                                        domoticz.data.insideStatus = 'evening'

                                        -- Turn on lights
                                        domoticz.devices('Woonkamer - Spotjes').dimTo(15)
                                end
                        end


                        -- -------------------------------------------------------------------------------
                        -- Determine current 'outside status'
                        -- -------------------------------------------------------------------------------
                        if (domoticz.time.matchesRule('at 06:00-23:00')) then
                                if ((weightedLux < 5) and (domoticz.data.outsideStatus ~= 'evening')) then
                                        domoticz.data.outsideStatus = 'evening'
                                end

                                if ((weightedLux > 5) and (domoticz.data.outsideStatus ~= 'off')) then
                                        domoticz.data.outsideStatus = 'off'
                                end
                        else
                                if (domoticz.data.outsideStatus ~= 'midnight') then
                                        domoticz.data.outsideStatus = 'midnight'
                                end
                        end


                        -- -------------------------------------------------------------------------------
                        -- Switch based on 'outside status'
                        -- -------------------------------------------------------------------------------
                        local brightDurationMaxSeconds = (brightDurationMaxMinutes * 60)

                        if (domoticz.data.outsideStatus == 'evening') then
                                setDeviceToLevelAfterSecs('Voordeur - Spotjes', dimLevel, brightDurationMaxSeconds)
                                setDeviceToLevelAfterSecs('Tuin - Spotjes gevel', dimLevel, brightDurationMaxSeconds)
                                setDeviceToLevelAfterSecs('Tuin - Spotjes tuinhuis', dimLevel, brightDurationMaxSeconds)
                        end

                        if (domoticz.data.outsideStatus == 'midnight') then
                                setDeviceToLevelAfterSecs('Tuin - Spotjes gevel', 0, brightDurationMaxSeconds)
                                setDeviceToLevelAfterSecs('Tuin - Spotjes tuinhuis', 0, brightDurationMaxSeconds)
                        end

                        if (domoticz.data.outsideStatus == 'off') then
                                setDeviceToLevelAfterSecs('Voordeur - Spotjes', 0, 0)
                                setDeviceToLevelAfterSecs('Tuin - Spotjes gevel', 0, 0)
                                setDeviceToLevelAfterSecs('Tuin - Spotjes tuinhuis', 0, 0)
                        end
                end


                -- -------------------------------------------------------------------------------
                -- Device event
                -- -------------------------------------------------------------------------------
                if (item.isDevice) then
                        log('Script activated by a device event: ' .. item.name)

                        -- -------------------------------------------------------------------------------
                        -- Movement detected at front door
                        -- -------------------------------------------------------------------------------
                        if (item.name == 'Voordeur - Beweging') then
                                if (domoticz.devices('Voordeur - Beweging').bState) then
                                        if (domoticz.data.outsideStatus ~= 'off') then
                                                domoticz.devices('Voordeur - Spotjes').dimTo(highPercentage)
                                                domoticz.devices('Voordeur - Spotjes').dimTo(dimLevel).afterMin(brightDurationMinMinutes)
                                        end
                                end
                        end

                        -- -------------------------------------------------------------------------------
                        -- Movement detected in the garden
                        -- -------------------------------------------------------------------------------
                        if (item.name == 'Tuin - Beweging BBQ') then
                                if (domoticz.devices('Tuin - Beweging BBQ').bState) then
                                        if (domoticz.data.outsideStatus == 'evening') then
                                                domoticz.devices('Tuin - Spotjes gevel').dimTo(highPercentage)
                                                domoticz.devices('Tuin - Spotjes tuinhuis').dimTo(highPercentage)

                                                domoticz.devices('Tuin - Spotjes gevel').dimTo(dimLevel).afterMin(brightDurationMinMinutes)
                                                domoticz.devices('Tuin - Spotjes tuinhuis').dimTo(dimLevel).afterMin(brightDurationMinMinutes)
                                        end

                                        if (domoticz.data.outsideStatus == 'midnight') then
                                                domoticz.devices('Tuin - Spotjes gevel').dimTo(highPercentage)
                                                domoticz.devices('Tuin - Spotjes tuinhuis').dimTo(highPercentage)

                                                domoticz.devices('Tuin - Spotjes gevel').switchOff().afterMin(brightDurationMinMinutes)
                                                domoticz.devices('Tuin - Spotjes tuinhuis').switchOff().afterMin(brightDurationMinMinutes)
                                        end
                                end
                        end
                end
        end
}

The above script is off course monolithic and huge and probably can be done in a nicer way. Here is the rundown:

        on = {
                ['devices'] = {
                        'Voordeur - Beweging',
                        'Tuin - Beweging BBQ'
                },
                ['timer'] = {
                        'every minute'
                }
        },

The script is triggered every minute on a timer, AND if either one of the devices mentioned in the devices list send an update to OpenZwave (in use by Domoticz). My ‘front door’ motion sensor (the one without BBQ in it :stuck_out_tongue: ) is used throughout the script for the LUX values.

The devices in question are:

  1. Tuin - Beweging BBQ
    Device type: Fibaro Motion Sensor (Z-Wave Plus)
    Powered via battery
  2. Voordeur - Beweging
    Device type: Aeotec 6-in-1 Multisensor GEN5
    Powered via USB power

The current status is that i have not yet installed HASS.io; but i do have a dockerized version of node-red running. I am in preference of having node-red separated from the hass.io install. Reason being is that i would first want to convert the LUA script from dzVents to Node-red (still using Domoticz, but via MQTT) and then install HASS.io (in order to limit my downtime) and use Node-red-contrib-home-assistant-websocket to implement my script.

Question 1: for the timer part i think i should use a ‘timestamp’ block with interval 1 minute?
Question 2: for the devices would need to be the home assistant device triggers?

        data = {
                insideStatus = { initial = nil },
                outsideStatus = { initial = nil }
        }

These are script variables which hold the current status (e.g. state) that the lights should be on. This is persisted on disk and therefore would ‘survive’ a reboot of Domoticz. I assume i could use persistency for this

Question 3: i think i need to know if and how i can access the same functionality from Node-red, that i use in the script:

domoticz.devices(device)
This gets the current state of the device; i am interested in the following properties (they might be named differently in HA off course):

domoticz.devices(device).bState
Boolean indicating the on/off state

domoticz.devices(device).level
Integer showing the current dimming level

domoticz.devices(device).lux
Gets a LUX value of a motion sensor device

domoticz.devices(device).lastUpdate.secondsAgo
Integer showing the number of seconds the device was last updated. I use this for instance to prevent multiple switch commands being sent amongst other things.

domoticz.devices(device).dimTo(dimLevel)
Turns on a device if off, and dims it to a certain level

domoticz.devices(device).switchOff()
Turns a device off

If i can access this all from a function block (using a home-assistant object?) i can write my script entirely in that one function block (with inputs the state change events and the timer block)

Your script to relatively easy to replicate in NR I have included a quick mock on a couple of different possible ways it could be done. It’s not tested but should give you an idea about how to go about things.

  1. There are many ways to go about it and an inject node that repeats on an interval is definitely one.
  2. Using an event state node is what you’re looking for here.
  3. Whatever information is available about a device in HA in available in NR. You can access the cache data of states and services from within a function node via the home assistant global object. But you unable to control a device, dimTo or switchOff, from within a function node.

[{"id":"7a92d509.0ea01c","type":"inject","z":"6be51cf.ba2fce4","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":108,"y":80,"wires":[["5bbd825d.e0958c"]]},{"id":"5bbd825d.e0958c","type":"function","z":"6be51cf.ba2fce4","name":"setup","func":"// Global object that contains HA states\nconst states = global.get('homeassistant').homeAssistant.states;\n\nconst weightedLux = parseFloat(states[\"sensor.lux_voorduer.attributes.lux\"]);\nconst now = new Date();\nconst currentHourAndMinutes = parseInt(`${now.getHours()}${now.getMinutes()}`);\n\nlet insideBrightness = null;\n\n// -------------------------------------------------------------------------------\n// Determine current 'inside status'\n// -------------------------------------------------------------------------------\nif (currentHourAndMinutes < 1200 && weightedLux > 15) {\n    insideBrightness = 0;\n} else if (currentHourAndMinutes > 1200 && weightedLux < 15) {\n    insideBrightness = 15;\n}\n\n\nif(insideBrightness !== null) {\n    // Set inside brightness and pass it to the call-service node\n    msg.payload = insideBrightness\n    \n    return msg;\n}","outputs":1,"noerr":0,"x":254,"y":80,"wires":[["415b6747.673528"]]},{"id":"415b6747.673528","type":"api-call-service","z":"6be51cf.ba2fce4","name":"Inside Lights","version":1,"debugenabled":false,"service_domain":"light","service":"turn_on","entityId":"light.woonkamer_spotjes","data":"{\"brightness_pct\": {{brightness}}}","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":402,"y":80,"wires":[[]]},{"id":"258a6f0.5148b92","type":"server-state-changed","z":"6be51cf.ba2fce4","name":"","version":1,"entityidfilter":"sensor.lux_voorduer","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"$entity().attributes.lux > 15","halt_if_type":"jsonata","halt_if_compare":"is","outputs":2,"output_only_on_state_change":false,"x":172,"y":176,"wires":[["29d32f55.eb7a6"],["a41668a9.f751e8"]]},{"id":"29d32f55.eb7a6","type":"time-range-switch","z":"6be51cf.ba2fce4","name":"","startTime":"00:00","endTime":"12:00","startOffset":0,"endOffset":0,"x":422,"y":176,"wires":[["2971ccd1.175934"],[]]},{"id":"a41668a9.f751e8","type":"time-range-switch","z":"6be51cf.ba2fce4","name":"","startTime":"12:00","endTime":"23:59","startOffset":0,"endOffset":0,"x":422,"y":224,"wires":[["b8074dd3.07975"],[]]},{"id":"2971ccd1.175934","type":"api-call-service","z":"6be51cf.ba2fce4","name":"Inside Lights","version":1,"debugenabled":false,"service_domain":"light","service":"turn_on","entityId":"light.woonkamer_spotjes","data":"{\"brightness_pct\": $exists(brightness) ? brightness : 0}","dataType":"jsonata","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":614,"y":176,"wires":[[]]},{"id":"b8074dd3.07975","type":"change","z":"6be51cf.ba2fce4","name":"","rules":[{"t":"set","p":"brightness","pt":"msg","to":"15","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":634,"y":224,"wires":[["2971ccd1.175934"]]},{"id":"2da6d1b4.2ee45e","type":"comment","z":"6be51cf.ba2fce4","name":"Example #1 Inside Light: Using just an function node, timestamp would need to be changed to interval","info":"","x":382,"y":32,"wires":[]},{"id":"6bc5b22a.89448c","type":"comment","z":"6be51cf.ba2fce4","name":"Example #2 Inside Light","info":"","x":132,"y":128,"wires":[]}]

[{"id":"288d9f13.c2b5a","type":"ha-wait-until","z":"6be51cf.ba2fce4","name":"","outputs":2,"entityId":"light.voordeur_beweging","property":"state","comparator":"is","value":"off","valueType":"str","timeout":"4","timeoutUnits":"minutes","entityLocation":"","entityLocationType":"none","checkCurrentState":true,"blockInputOverrides":true,"x":428,"y":544,"wires":[[],["13af091.c8d7bf7"]]},{"id":"21459b9a.96bb24","type":"api-call-service","z":"6be51cf.ba2fce4","name":"Voordeur - Spotjes","version":1,"debugenabled":true,"service_domain":"light","service":"turn_on","entityId":"light.voordeur_spotjes","data":"{\t   \"brightness_pct\": $exists(brightness) ? brightness : $flowContext(\"highPercentage\")\t   \t}","dataType":"jsonata","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":842,"y":496,"wires":[[]]},{"id":"13af091.c8d7bf7","type":"change","z":"6be51cf.ba2fce4","name":"brightness to dimLevel","rules":[{"t":"set","p":"brightness","pt":"msg","to":"dimLevel","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":628,"y":544,"wires":[["21459b9a.96bb24"]]},{"id":"96f8b371.6194f","type":"inject","z":"6be51cf.ba2fce4","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":220,"y":384,"wires":[["e44b58e7.2e5628"]]},{"id":"e44b58e7.2e5628","type":"function","z":"6be51cf.ba2fce4","name":"setup","func":"// Global object that contains HA states\nconst states = global.get('homeassistant').homeAssistant.states;\n\nconst loweredPercentage = 10;        // When we sleep and the lights are on, the dimming level will be ...\nconst normalPercentage = 20;         // When we are awake and the lights are on, the dimming level will be ...\nconst highPercentage = 100;          // When movement is detected during the time frame that the lights should be on, the lights are brightend to ...\nconst brightDurationMinMinutes = 3;  // For this amount of minutes ...\nconst brightDurationMaxMinutes = 4;  // And if (after this amount of minutes) the lights are still bright, we dim them (safeguard for missing timer events)\n\nconst weightedLux = parseFloat(states[\"sensor.lux_voorduer.attributes.lux\"]);\nconst now = new Date();\nconst currentHourAndMinutes = parseInt(`${now.getHours()}${now.getMinutes()}`);\n\n// -------------------------------------------------------------------------------\n// Calculate level to which the lights should dim\n// -------------------------------------------------------------------------------\n\n// By default, we dim to the 'normal' percentage\nlet dimLevel = normalPercentage;\n\n// Between these times, we have a 'minimum' dimming level\nif (currentHourAndMinutes >= 2130 || currentHourAndMinutes < 630) {\n    dimLevel = loweredPercentage;\n}\n\n// -------------------------------------------------------------------------------\n// Determine current 'outside status'\n// -------------------------------------------------------------------------------\nlet outsideStatus;\n\nif (currentHourAndMinutes >= 600 && currentHourAndMinutes <= 2300) {\n    if (weightedLux < 5) {\n        outsideStatus = 'evening';\n    } else {\n        outsideStatus = 'off';\n    }\n} else {\n    outsideStatus = 'midnight';\n}\n\n// Save values to flow variables\nflow.set(\"dimLevel\", dimLevel);\nflow.set(\"outsideStatus\", outsideStatus);\nflow.set(\"outsideStatus\", outsideStatus);\nflow.set(\"brightDurationMinMinutes\", brightDurationMinMinutes);\nflow.set(\"brightDurationMaxMinutes\", brightDurationMaxMinutes);\n\n\nswitch(outsideStatus) {\n    case 'evening':\n        msg.brightness = dimLevel;\n        return [null, msg];\n        \n    case 'midnight':\n        msg.brightness = 0;\n        return [null, msg];\n\n    case 'off':\n        msg.brightness = 0;\n        return [msg, msg];\n        \n}","outputs":2,"noerr":0,"x":354,"y":384,"wires":[["21459b9a.96bb24"],["e5c3e87d.f51318"]]},{"id":"6d0fd240.0af1bc","type":"comment","z":"6be51cf.ba2fce4","name":"Movement detected at front door","info":"","x":274,"y":448,"wires":[]},{"id":"b6213c7f.15c2f","type":"server-state-changed","z":"6be51cf.ba2fce4","name":"Voordeur - Beweging","version":1,"entityidfilter":"light.voordeur_beweging","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"x":244,"y":496,"wires":[["288d9f13.c2b5a","21459b9a.96bb24"]]},{"id":"e5c3e87d.f51318","type":"api-call-service","z":"6be51cf.ba2fce4","name":"Garden Lights","version":1,"debugenabled":true,"service_domain":"light","service":"turn_on","entityId":"light.tuin_spotjes_gevel,light.tuin_spotjes_tuinhuis","data":"{\t   \"brightness_pct\": $exists(brightness) ? brightness : $flowContext(\"highPercentage\")\t   \t}","dataType":"jsonata","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":992,"y":656,"wires":[[]]},{"id":"9ec7eb9a.ab64b8","type":"change","z":"6be51cf.ba2fce4","name":"brightness to dimLevel","rules":[{"t":"set","p":"brightness","pt":"msg","to":"dimLevel","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":756,"y":704,"wires":[["e5c3e87d.f51318"]]},{"id":"4f816e69.bb1ee","type":"comment","z":"6be51cf.ba2fce4","name":"Movement detected in the garden","info":"","x":274,"y":608,"wires":[]},{"id":"d1c35601.39b328","type":"server-state-changed","z":"6be51cf.ba2fce4","name":"Tuin - Beweging BBQ","version":1,"entityidfilter":"light.tuin_beweging_bbq","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"x":244,"y":656,"wires":[["e5c3e87d.f51318","5d54e986.cfe908"]]},{"id":"5d54e986.cfe908","type":"trigger","z":"6be51cf.ba2fce4","op1":"","op2":"","op1type":"nul","op2type":"payl","duration":"4","extend":true,"units":"min","reset":"","bytopic":"all","name":"","x":422,"y":704,"wires":[["541c37b1.c38098"]]},{"id":"541c37b1.c38098","type":"switch","z":"6be51cf.ba2fce4","name":"","property":"outsideStatus","propertyType":"flow","rules":[{"t":"eq","v":"evening","vt":"str"},{"t":"eq","v":"midnight","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":576,"y":704,"wires":[["9ec7eb9a.ab64b8"],["b393ed76.02dbf"]]},{"id":"b393ed76.02dbf","type":"change","z":"6be51cf.ba2fce4","name":"brightness to 0","rules":[{"t":"set","p":"brightness","pt":"msg","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":736,"y":752,"wires":[["e5c3e87d.f51318"]]}]

Wow, this is already more then i would have hoped for :slight_smile:

If i don’t have the node-red add-on (e.g. installed it via “add-ons”) but instead installed the node-red-websocket palette; would i also have all the entity state information available? Do you have an example snippet of a few lines of JS code?

You could always do an API-call technically speaking, but why would you want to do it since NR also has this for you? :stuck_out_tongue:

What is the difference between ‘trigger 4 min’ for the BBQ and the ‘wait until’ for the front-door? The best flow would be that the timer would reset in case there would be new motion within those 5 minutes. E.g. lights only turn off in case no motion is detected AND we are 5 minutes later.

Yes, you don’t need the hass.io addon the websocket palette contains everything you need, I don’t run hass.io.

The wait-until can only listen for a state change of one entity. So it works for the front door to reset itself if the light is turned off. Since there are two lights in the BBQ flow can’t really use the wait-until node and there’s no reset if one of the lights is turned off. This could be fixed by adding a trigger-state node and resetting the trigger node if both lights are turned off.

[{"id":"e5c3e87d.f51318","type":"api-call-service","z":"6be51cf.ba2fce4","name":"Garden Lights","version":1,"debugenabled":true,"service_domain":"light","service":"turn_on","entityId":"light.tuin_spotjes_gevel,light.tuin_spotjes_tuinhuis","data":"{\t   \"brightness_pct\": $exists(brightness) ? brightness : $flowContext(\"highPercentage\")\t   \t}","dataType":"jsonata","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":992,"y":656,"wires":[[]]},{"id":"9ec7eb9a.ab64b8","type":"change","z":"6be51cf.ba2fce4","name":"brightness to dimLevel","rules":[{"t":"set","p":"brightness","pt":"msg","to":"dimLevel","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":756,"y":704,"wires":[["e5c3e87d.f51318"]]},{"id":"4f816e69.bb1ee","type":"comment","z":"6be51cf.ba2fce4","name":"Movement detected in the garden","info":"","x":274,"y":608,"wires":[]},{"id":"d1c35601.39b328","type":"server-state-changed","z":"6be51cf.ba2fce4","name":"Tuin - Beweging BBQ","version":1,"entityidfilter":"light.tuin_beweging_bbq","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"x":244,"y":656,"wires":[["e5c3e87d.f51318","5d54e986.cfe908"]]},{"id":"5d54e986.cfe908","type":"trigger","z":"6be51cf.ba2fce4","op1":"","op2":"","op1type":"nul","op2type":"payl","duration":"4","extend":true,"units":"min","reset":"","bytopic":"all","name":"","x":422,"y":704,"wires":[["541c37b1.c38098"]]},{"id":"541c37b1.c38098","type":"switch","z":"6be51cf.ba2fce4","name":"","property":"outsideStatus","propertyType":"flow","rules":[{"t":"eq","v":"evening","vt":"str"},{"t":"eq","v":"midnight","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":576,"y":704,"wires":[["9ec7eb9a.ab64b8"],["b393ed76.02dbf"]]},{"id":"b393ed76.02dbf","type":"change","z":"6be51cf.ba2fce4","name":"brightness to 0","rules":[{"t":"set","p":"brightness","pt":"msg","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":736,"y":752,"wires":[["e5c3e87d.f51318"]]},{"id":"4aa368a4.b00268","type":"change","z":"6be51cf.ba2fce4","name":"","rules":[{"t":"set","p":"reset","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":464,"y":768,"wires":[["5d54e986.cfe908"]]},{"id":"7ef87a40.ab4044","type":"trigger-state","z":"6be51cf.ba2fce4","name":"Both lights turned off","entityid":"light.tuin_spotjes_gevel,light.tuin_spotjes_tuinhuis","entityidfiltertype":"substring","debugenabled":false,"constraints":[{"id":"tgnmgnt6ch","targetType":"entity_id","targetValue":"light.tuin_spotjes_gevel","propertyType":"current_state","propertyValue":"new_state.state","comparatorType":"is","comparatorValueDatatype":"str","comparatorValue":"off"},{"id":"tipmr0npt6m","targetType":"entity_id","targetValue":"light.tuin_spotjes_tuinhuis","propertyType":"current_state","propertyValue":"new_state.state","comparatorType":"is","comparatorValueDatatype":"str","comparatorValue":"off"}],"constraintsmustmatch":"all","outputs":2,"customoutputs":[],"outputinitially":false,"state_type":"str","x":260,"y":768,"wires":[["4aa368a4.b00268"],[]]}]

Thanx, i’ll see if i can make it work based on the above info. When you said:

You can access the cache data of states and services from within a function node via the home assistant global object.

Can you post a sample snippet?

1 Like

It’s the first line of the function nodes in the examples above. Also in the server config info tab with in node-red

1 Like