Generic auto-off

Moderator: leecollings

Vondee
Posts: 30
Joined: Sunday 12 January 2020 19:06
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Generic auto-off

Post by Vondee »

Unfortunately I need the script also for turning lights off, is it possible to have a command like "auto_level_minutes" next to the command "auto_off_minutes"?
rrozema
Posts: 470
Joined: Thursday 26 October 2017 13:37
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Delft
Contact:

Re: Generic auto-off

Post by rrozema »

Of course. Everything is possible. It just needs some time. I like your idea to first dim the light and then somewhat later switch it off completely. I'll see what i can do after i return home and let you know in a few days.
rrozema
Posts: 470
Joined: Thursday 26 October 2017 13:37
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Delft
Contact:

Re: Generic auto-off

Post by rrozema »

Vondee wrote: Monday 27 January 2020 10:36 Unfortunately I need the script also for turning lights off, is it possible to have a command like "auto_level_minutes" next to the command "auto_off_minutes"?
Below code is not working yet. I get an error that I can't fix yet but I'm running out of time for the moment. Maybe @waaren can have a look at what I'm doing wrong? I've not even activated the new features yet; still using the original json values in the descriptions of my devices.

Code: Select all

2020-02-01 21:52:00.945 Error: dzVents: Error: (2.5.0) An error occurred when calling event handler Generic Auto Off
2020-02-01 21:52:00.945 Error: dzVents: Error: (2.5.0) ...z/scripts/dzVents/generated_scripts/Generic Auto Off.lua:105: attempt to compare number with table
Line 105 is the line

Code: Select all

	                            elseif motion_device.lastUpdate.compare(lastUpdate) > 0 then
but I don't see how lastUpdate could suddenly be a number?

Code: Select all

-- This script will run every minute and can automatically send an 'Off' command to turn off any device after
-- it has been on for some specified time. Each device can be individually configured by putting json coded 
-- settings into the device's description field. The settings currently supported are:
-- - "auto_off_minutes" : <time in minutes>
-- - "auto_off_motion_device" : "<name of a motion detection device>"
-- If "auto_off_minutes" is not set, the device will never be turned off by this script. If 
-- "auto_off_minutes" is set and <time in minutes> is a valid number, the device will be turned off when it 
-- is found to be on plus the device's lastUpdate is at least <time in minutes> minutes old. This behavior 
-- can be further modified by specifying a valid device name after "auto_off_motion_device". When a motion 
-- device is specified and the device's lastUpdate is at least <time in minutes> old, the device will not 
-- be turned off until the motion device is off and it's lastUpdate is also <time in minutes> old. 
-- Specifying "auto_off_motion_device" without specifying "auto_off_minutes" does nothing.
--
-- Example 1: turn off the device after 2 minutes:
-- {
-- "auto_off_minutes": 2
-- }
--
-- Example 2: turn off the device when it has been on for 5 minutes and no motion has been detected for 
-- at least 5 minutes:
-- {
-- "auto_off_minutes": 5,
-- "auto_off_motion_device": "Overloop: Motion"
-- }
--
-- Example 3: turn off the device when it has been on for 1 minute and not motion was detected for at least 1 
-- minute on either one of a set of motion sensors.
--{
--"auto_off_minutes": 1,
--"auto_off_motion_device": ["Overloop 1: Motion 1", "Overloop 1: Motion 2"]
--}

return {
	on = {

		-- timer triggers
		timer = {
			'every minute'
		}
	},

	execute = function(domoticz, triggeredItem, info)
	    local cnt = 0

        domoticz.devices().forEach(
	        function(device)
	            cnt = cnt + 1
                local description = device.description
                if description ~= nil and description ~= '' then
                    local ok, settings = pcall( domoticz.utils.fromJSON, description)
                    if ok and settings ~= nil then
                        -- Determine highest level available in the settings that is 
                        -- lower than the current level where 'Off' equals level 0.
                        local dimlevel = nil;
                        
                        -- Lowest dim level is 'Off', this I will represent as level == 0.
                        -- If auto_off_minutes was specified, I will use this to
                        -- initialise the dimlevel variable with a level of 0.
                        if settings.auto_off_minutes ~= nil then
                            dimlevel = { level = 0, minutes = settings.auto_off_minutes }
                        end
                        
                        -- If one or more dimlevels were specified, the user must think our
                        -- device is a dimmer switch, so it should be safe to reference
                        -- its level attribute. We search for the dimlevel that has the
                        -- highest level below that of our device's level.
                        if settings.auto_off_dimlevel ~= nil then
                            dimlevel = settings.auto_off_dimlevel.reduce(
                                    function(acc, dl)
                                        if dl.level < device.level then
                                            if acc == nil or dl.level > acc.level then
                                                acc = dl
                                            end
                                        end
                                        return acc -- always return the accumulator
                                    end, 
                                dimlevel )  -- Initial value for the accumulator is either nil
                                            -- if no auto_off_minutes was specified or it is
                                            -- {level = 0, minutes = <auto_off_minutes>}.
                        end
                            
                        -- If we have found a new dim level then see if it is time yet to
                        -- set this new level.
                        if dimlevel ~= nil then
                            local minutes = dimlevel.minutes
                            
                            -- Find the latest last modified date from our device plus
                            -- any motion devices that may have been specified. Initially
                            -- assume our device has the latest last modified date.
                            local lastUpdate = device.lastUpdate
                            
                            -- We will skip setting a new level if either of the following is true: 
                            -- one or more of the motion devices has state 'On' or the lastUpdate 
                            -- on our device or any of the specified motion devices is less than 
                            -- <minutes> ago. To accomplish this, lets find out if any of the 
                            -- motion devices has a more recent lastUpdate than that of our device.
                            -- If a motion device has state 'On', we will set lastUpdate to nil,
                            -- indicating we can skip the check for lastUpdate completely.
                            
                            if type(settings.auto_off_motion_device) == "string" then
                                -- a single motion device was specified
	                            local motion_device = domoticz.devices(settings.auto_off_motion_device)
	                            if motion_device.state ~= 'Off' then
	                                lastUpdate = nil
	                            elseif motion_device.lastUpdate.compare(lastUpdate) > 0 then
	                                lastUpdate = motion_device.lastUpdate
	                            end
                            elseif type(settings.auto_off_motion_device) == "table" then
                                local motion_devices = domoticz.devices().filter(settings.auto_off_motion_device)
                                lastUpdate = motion_devices.reduce(
                                        function(acc, md)
                                            if md.timedOut ~= true then -- Ignore motion devices that have timed out, to 
                                                                        -- avoid leaving the light on because a sensor that 
                                                                        -- has an empty battery isn't updated to 'Off'.
                                                if acc ~= nil then      -- If a previous sensor was 'On', we will have set 
                                                                        -- lastUpdate to nil and we don't want to overwrite
                                                                        -- this.
                                                    if md.state ~= 'Off' then
                                                        acc = nil               -- Set lastUpdate to nil to indicate at least 
                                                                                -- one sensor is 'On'.
                                                    elseif md.lastUpdate.compare(acc) > 0 then
                                                        acc = md.lastUpdate     -- We've found a more recent lastUpdate.
                                                    end
                                                end
                                            end
                                            return acc -- Always return the accumulator.
                                        end, lastUpdate)
                            end

                            if lastUpdate ~= nil and lastUpdate.minutesAgo > tonumber(minutes) then
                                if dimlevel.level > 0 then
            		                domoticz.log(device.name .. ' is dimmed to level ' .. dimlevel.level .. ' after ' .. settings.auto_off_minutes .. ' minutes.', domoticz.LOG_INFO)
                                    device.setLevel(tonumber(dimlevel.level))
                                else
            		                domoticz.log(device.name .. ' is switched off after ' .. settings.auto_off_minutes .. ' minutes.', domoticz.LOG_INFO)
                                    device.switchOff()
                                end
                            end
                        end
                    else
                        domoticz.log( 'Device description for '.. device.name ..' is not in json format. Ignoring this device.', domoticz.LOG_WARNING)
                    end
                end
--                end
            end
        )
    
        domoticz.log('Scanned ' .. tostring(cnt) .. ' devices.', domoticz.LOG_INFO)
    

--        -- Set ventilation back to automatic after 2 hours of manual control.
--        local hs = domoticz.devices('Humidity SetPoint')
--        if hs.state ~= 'On' and hs.lastUpdate.hoursAgo >= 2 then
--            hs.switchOn()
--        end
    
	end
}
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: Generic auto-off

Post by waaren »

rrozema wrote: Saturday 01 February 2020 22:01 Below code is not working yet. I get an error that I can't fix yet but I'm running out of time for the moment. Maybe @waaren can have a look at what I'm doing wrong? I've not even activated the new features yet; still using the original json values in the descriptions of my devices.

Code: Select all

2020-02-01 21:52:00.945 Error: dzVents: Error: (2.5.0) An error occurred when calling event handler Generic Auto Off
2020-02-01 21:52:00.945 Error: dzVents: Error: (2.5.0) ...z/scripts/dzVents/generated_scripts/Generic Auto Off.lua:105: attempt to compare number with table
Line 105 is the line

Code: Select all

	                            elseif motion_device.lastUpdate.compare(lastUpdate) > 0 then
but I don't see how lastUpdate could suddenly be a number?
lastUpdate and motion_device.lastUpdate are both dzVents time objects... But 0 is a number and the result of the compare function is a time object.
You can see how the result is structured by using the lodash _.print or dzVents dumpTable

Code: Select all

dz.utils._.print(motion_device.lastUpdate.compare(lastUpdate))
{["mins"]=87, ["seconds"]=5228, ["secs"]=5228, ["minutes"]=87, ["compare"]=-1, ["milliseconds"]=5228811, ["ms"]=5228811, ["days"]=0, ["hours"]=1}

dz.utils.dumpTable(motion_device.lastUpdate.compare(lastUpdate))
 > days: 0
 > mins: 92
 > hours: 1
 > minutes: 92
 > compare: -1
 > seconds: 5557
 > milliseconds: 5557487
 > ms: 5557487
 > secs: 5557
so what you probably need is something like

Code: Select all

elseif motion_device.lastUpdate.compare(lastUpdate).minutes > 0 then
or

Code: Select all

elseif motion_device.lastUpdate.compare(lastUpdate).seconds > 0 then
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
rrozema
Posts: 470
Joined: Thursday 26 October 2017 13:37
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Delft
Contact:

Re: Generic auto-off

Post by rrozema »

waaren wrote: Sunday 02 February 2020 1:30 ...
so what you probably need is something like

Code: Select all

elseif motion_device.lastUpdate.compare(lastUpdate).minutes > 0 then
or

Code: Select all

elseif motion_device.lastUpdate.compare(lastUpdate).seconds > 0 then
Thanks, that was helpful. I keep forgetting that compare() returns that structure. Not there yet, but this helped me further. What I needed was:

Code: Select all

	                            elseif motion_device.lastUpdate.compare(lastUpdate).compare > 0 then
rrozema
Posts: 470
Joined: Thursday 26 October 2017 13:37
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Delft
Contact:

Re: Generic auto-off

Post by rrozema »

Vondee wrote: Monday 27 January 2020 10:36 Unfortunately I need the script also for turning lights off, is it possible to have a command like "auto_level_minutes" next to the command "auto_off_minutes"?
I am not completely satisfied yet, but here's a 1st version that does mostly what you asked for. I'm not putting the code in the opening post yet, but you can give it a try, see how you like it.

The json to put into the description is like before. I've only added one new option: auto_off_dimlevel. Note the different brace types if you specify multiple dim levels. The code will search for the highest dim level below the current dim level. When then light has been on the current level for as long as the minutes specifies, the next level is set. Here's an example how to use it. When the light is set to 100%, this will dim the light to 50% after 2 minutes, then 2 minutes later it dims to 33% and finally 10 minutes after that it switches off.

Code: Select all

{
"auto_off_dimlevel": [{ "level": 50, "minutes": 2 }, { "level": 33, "minutes": 2 }],
"auto_off_minutes": 10
}
I haven't tried it yet, but this should work for a single level dim followed by switching the light off:

Code: Select all

{
"auto_off_dimlevel": { "level": 33, "minutes": 2 },
"auto_off_minutes": 10
}
I haven't tested this either but this should dim the light after 2 minutes and never turn it off:

Code: Select all

{
"auto_off_dimlevel": { "level": 33, "minutes": 2 }
}

Code: Select all

-- This script will run every minute and can automatically send an 'Off' command to turn off any device after
-- it has been on for some specified time. Each device can be individually configured by putting json coded 
-- settings into the device's description field. The settings currently supported are:
-- - "auto_off_minutes" : <time in minutes>
-- - "auto_off_motion_device" : "<name of a motion detection device>"
-- If "auto_off_minutes" is not set, the device will never be turned off by this script. If 
-- "auto_off_minutes" is set and <time in minutes> is a valid number, the device will be turned off when it 
-- is found to be on plus the device's lastUpdate is at least <time in minutes> minutes old. This behavior 
-- can be further modified by specifying a valid device name after "auto_off_motion_device". When a motion 
-- device is specified and the device's lastUpdate is at least <time in minutes> old, the device will not 
-- be turned off until the motion device is off and it's lastUpdate is also <time in minutes> old. 
-- Specifying "auto_off_motion_device" without specifying "auto_off_minutes" does nothing.
--
-- Example 1: turn off the device after 2 minutes:
-- {
-- "auto_off_minutes": 2
-- }
--
-- Example 2: turn off the device when it has been on for 5 minutes and no motion has been detected for 
-- at least 5 minutes:
-- {
-- "auto_off_minutes": 5,
-- "auto_off_motion_device": "Overloop: Motion"
-- }
--
-- Example 3: turn off the device when it has been on for 1 minute and not motion was detected for at least 1 
-- minute on either one of a set of motion sensors.
--{
--"auto_off_minutes": 1,
--"auto_off_motion_device": ["Overloop 1: Motion 1", "Overloop 1: Motion 2"]
--}

return {
	on = {

		-- timer triggers
		timer = {
			'every minute'
		}
	},
	data = { 
	    triggers = {initial = {}},      -- Holds a list of (unique) motion devices and a list of devices it triggers.
	    triggered_by = {initial = {}}   -- Holds a list of (unique) triggered devices and a list of motion devices that trigger it.
	},
	logging = {
        level = domoticz.LOG_INFO,
        marker = "Generic Auto Off v2"
    },
	execute = function(domoticz, triggeredItem, info)
        local cnt = 0
        
        --domoticz.dump(domoticz.utils)
        --domoticz.utils.dumpTable(domoticz)
        --domoticz.utils.dumpTable(domoticz.utils)
        
        --local Time = require('Time')
        local now = domoticz.time
        
--        if domoticz.data.triggers == nil then
	        domoticz.data.triggers = {}
--	    end
	   
--	    if domoticz.data.triggered_by == nil then
            domoticz.data.triggered_by = {}
--	    end

        domoticz.devices().forEach(
	        function(device)
	            cnt = cnt + 1
	            local description
                local motion_device_names  -- If no settings are found we may still have to
                                           -- remove some device's motion devices from the 
                                           -- trigger lists. So we start with an empty list.

                motion_device_names = {}
                description = device.description

                if description ~= nil and description ~= '' then
                    local ok, settings = pcall( domoticz.utils.fromJSON, description)
                    if ok and settings ~= nil then
                        -- Determine highest level available in the settings that is 
                        -- lower than the current level where 'Off' equals level 0.
                        local dimlevel = nil;

                        -- Determine the list of motion devices configured for this
                        -- device in the settings.
                        if type(settings.auto_off_motion_device) == "string" then
                            table.insert( motion_device_names, settings.auto_off_motion_device)
                        elseif type(settings.auto_off_motion_device) == "table" then
                            for i,v in ipairs(settings.auto_off_motion_device) do
                                table.insert( motion_device_names, v)
                            end
                        end
                    
                        -- Lowest dim level is 'Off', this I will represent as level == 0.
                        -- If auto_off_minutes was specified and the device is not off, I 
                        -- will use this to initialise the dimlevel variable with a level 
                        -- of 0. If the device is off already, we don't need to change it.
                        if settings.auto_off_minutes ~= nil and device.state ~= 'Off' then
                            dimlevel = { level = 0, minutes = settings.auto_off_minutes}
                        end
                        
                        -- If one or more dimlevels were specified, the user must think our
                        -- device is a dimmer switch, so it should be safe to reference
                        -- its level attribute. We search for the dimlevel that has the
                        -- highest level below that of our device's level.
                        if settings.auto_off_dimlevel ~= nil and type(settings.auto_off_dimlevel) == "table" then
                            -- if a single dimlevel was specified...
                            if settings.auto_off_dimlevel.level ~= nil then
                                if settings.auto_off_dimlevel.level < device.level then
                                    if dimlevel == nil or settings.auto_off_dimlevel.level > dimlevel.level then
                                        dimlevel = settings.auto_off_dimlevel
                                    end
                                end
                            else
                                -- or when multiple dimlevels were specified as a table of tables.
                                for i,v in ipairs(settings.auto_off_dimlevel) do
                                    if v.level < device.level then
                                        if dimlevel == nil or v.level > dimlevel.level then
                                            dimlevel = v
                                        end
                                    end
                                end
                            end
                        end

                        -- If we have found a new dim level then see if it is time yet to
                        -- set this new level.
                        if dimlevel ~= nil then
                            local minutes = dimlevel.minutes
                            
                            -- Find the latest last modified date from our device plus
                            -- any motion devices that may have been specified. Initially
                            -- assume our device has the latest last modified date.
                            local lastUpdate = device.lastUpdate
                            
                            --domoticz.utils.dumpTable(lastUpdate)
                            
                            -- We will skip setting a new level if either of the following is true: 
                            -- at least one of the motion devices has state 'On' or the lastUpdate 
                            -- on our device or any of the specified motion devices is less than 
                            -- <minutes> ago. To accomplish this, lets find out if any of the 
                            -- motion devices has a more recent lastUpdate than that of our device.
                            -- If a motion device has state 'On', we will set lastUpdate to nil,
                            -- indicating we can skip the check for lastUpdate completely.
                            local motion_devices = domoticz.devices().filter(motion_device_names)
                            lastUpdate = motion_devices.reduce(
                                    function(acc, md)
                                        if md.timedOut ~= true then -- Ignore motion devices that have timed out, to 
                                                                    -- avoid leaving the light on because a sensor that 
                                                                    -- has an empty battery isn't updated to 'Off'.
                                            if acc ~= nil then      -- If a previous sensor was 'On', we will have set 
                                                                    -- lastUpdate to nil and we don't want to overwrite
                                                                    -- this.
                                                if md.state ~= 'Off' then
                                                    --domoticz.utils._.print( 'Sensor ' .. md.name .. ' is on')
                                                    acc = nil               -- Set lastUpdate to nil to indicate at least 
                                                                            -- one sensor is 'On'.
                                                elseif md.lastUpdate.compare(acc).compare < 0 then  -- If acc < lastUpdate
                                                    domoticz.utils._.print( 'Found lastUpdate ' .. md.lastUpdate.raw .. ' on ' .. md.name .. ' to be more recent than ' .. acc.raw .. '.')
                                                    acc = md.lastUpdate     -- We've found a more recent lastUpdate.
                                                end
                                            end
                                        else
                                            domoticz.log( 'Ignoring motion device ' .. md.name .. ' because it timed out. Do you need to replace it\'s battery?', domoticz.LOG_WARNING)
                                        end
                                        return acc -- Always return the accumulator.
                                    end, lastUpdate)

                            if lastUpdate ~= nil and lastUpdate.secondsAgo > tonumber(minutes * 60) then
                                if dimlevel.level > 0 then
            		                domoticz.log(device.name .. ' is dimmed to level ' .. dimlevel.level .. ' after ' .. dimlevel.minutes .. ' minutes.', domoticz.LOG_INFO)
                                    device.setLevel(tonumber(dimlevel.level))
                                else
            		                domoticz.log(device.name .. ' is switched off after ' .. dimlevel.minutes .. ' minutes.', domoticz.LOG_INFO)
                                    device.switchOff()
                                end
                            end
                        end
                    
                        -- Now see if we need to update our triggers lists. I keep a list of trigger devices that I 
                        -- use to see 1) which devices are our motion devices and 2) which devices need to be 
                        -- switched on for each motion device. Plus I keep an additional list of triggered devices 
                        -- so I can determine that a motion device was removed from the settings. Because in this 
                        -- case I need to remove it from the list of trigger devices too.
                        --

                        -- Do we need to add entries to the triggers lists?
                        --      For each of the motion devices in settings
                        --          If not exists data.triggers[ <settings.motion device> ]
                        --          Then
                        --              add a new entry in data.triggers with our current device in the list of devices to trigger.
                        --          Else
                        --              If our current device is not in the list of devices to trigger
                        --              Then
                        --                  Add our device to the list of devices to trigger.
                        --
                        --          If data.triggered_by does not have our device
                        --          Then
                        --              add a new entry in data.triggered_by for our current device with our motion device in the triggered_by list.
                        --          Else
                        --              If our motion device is not in the list of trigger devices
                        --              Then
                        --                  add the motion device to the list of trigger devices
                        -- 
                        
                        for i,v in ipairs(motion_device_names) do
                            if domoticz.data.triggers[v] == nil then
                                --domoticz.log('adding trigger ' .. v .. '.', domoticz.LOG_DEBUG)
                                domoticz.data.triggers[v] = {}
                            end
                            -- TODO: This code keeps adding entries, even though following if exists. Why?
                            if domoticz.data.triggers[v][device.name] == nil then
                                --domoticz.log('adding triggered device ' .. device.name .. '.', domoticz.LOG_DEBUG)
                                table.insert(domoticz.data.triggers[v], device.name)
                            end

                            if domoticz.data.triggered_by[device.name] == nil then
                                domoticz.data.triggered_by[device.name] = {}
                            end
                            if domoticz.data.triggered_by[device.name][v] == nil then
                                table.insert(domoticz.data.triggered_by[device.name], v)
                            end
                        end
                    else
                        domoticz.log( 'Device description for '.. device.name ..' is not in json format. Ignoring this device.', domoticz.LOG_WARNING)
                    end
                    
                    -- Do we need to remove entries from the triggers lists?
                    --      For each of the entries in the list of trigger devices from data.triggered_by[ <current device> ]
                    --          If settings does not have a motion device[ <listed motion device> ]
                    --          Then
                    --              remove data.triggered_by[<current device>][ <listed motion device> ]
                    --              If data.triggered_by[<current device>] has no more entries
                    --              Then 
                    --                  remove data.triggered_by[<current device>]
                    --              If exists data.triggers[ <listed motion device> ][ <current device> ]
                    --              Then
                    --                  remove data.triggers[ <listed motion device> ][ <current device> ]
                    --              If data.triggers[ <listed motion device> ] has no more entries
                    --                  remove data.triggers[ <listed motion device> ]
                    if domoticz.data.triggered_by[device.name] ~= nil then
                        for i,v in ipairs(domoticz.data.triggered_by[device.name]) do
                            if motion_device_names[v] == nil then
                                domoticz.data.triggered_by[device.name][v] = nil
                                if #(domoticz.data.triggered_by[device.name]) <= 0 then
                                    domoticz.data.triggered_by[device.name] = nil
                                end
                                if domoticz.data.triggers[v][device.name] ~= nil then
                                    domoticz.data.triggers[v][device.name] = nil
                                end
                                if #(domoticz.data.triggers[v]) <= 0 then
                                    domoticz.data.triggers[v] = nil
                                end
                            end
                        end
                    end
                end
            end
        )
    
        domoticz.log('Scanned ' .. tostring(cnt) .. ' devices.', domoticz.LOG_INFO)
    
        --domoticz.utils.dumpTable(domoticz.data.triggers)
        --domoticz.utils.dumpTable(domoticz.data.triggered_by)

 --       -- Set ventilation back to automatic after 2 hours of manual control.
 --       local hs = domoticz.devices('Humidity SetPoint')
 --       if hs.state ~= 'On' and hs.lastUpdate.hoursAgo >= 2 then
 --           hs.switchOn()
 --       end
	end
}
Last edited by rrozema on Sunday 16 February 2020 22:40, edited 2 times in total.
Vondee
Posts: 30
Joined: Sunday 12 January 2020 19:06
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Generic auto-off

Post by Vondee »

Nice!

Coming week I am traveling and have no time to try :cry:

Will keep you posted on the result!

Again, many thanks the work and as soon as I am back I will try it!
Vondee
Posts: 30
Joined: Sunday 12 January 2020 19:06
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Generic auto-off

Post by Vondee »

Hi,

I tried the script with only setting the dim-level.

{
"auto_off_dimlevel": { "level": 20, "minutes": 10 }
}

After the set time, Domoticz has an error:

2020-02-15 20:43:00.454 Error: dzVents: Error: (2.5.5) An error occurred when calling event handler Generec_Auto_Off
2020-02-15 20:43:00.454 Error: dzVents: Error: (2.5.5) ...z/scripts/dzVents/generated_scripts/Generec_Auto_Off.lua:143: attempt to concatenate a nil value (field 'auto_off_minutes')

When I add

"auto_off_minutes": 300

Then the script works! the light is dimmed to 20%: :)

2020-02-15 20:47:00.447 Status: dzVents: {["level"]=20, ["minutes"]=10}
2020-02-15 20:47:00.447 Status: dzVents: Info: Spots Keuken is dimmed to level 20 after 300 minutes.

So the code expect to always have the "auto_off_minutes" set.

Best regards,
Vondee
Posts: 30
Joined: Sunday 12 January 2020 19:06
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Generic auto-off

Post by Vondee »

There is however another issue, now the normal switches having settings of 30 minutes and controlled by a PIR sensor now switch off after a minute.
rrozema
Posts: 470
Joined: Thursday 26 October 2017 13:37
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Delft
Contact:

Re: Generic auto-off

Post by rrozema »

Vondee wrote: Saturday 15 February 2020 20:51 After the set time, Domoticz has an error:

2020-02-15 20:43:00.454 Error: dzVents: Error: (2.5.5) An error occurred when calling event handler Generec_Auto_Off
2020-02-15 20:43:00.454 Error: dzVents: Error: (2.5.5) ...z/scripts/dzVents/generated_scripts/Generec_Auto_Off.lua:143: attempt to concatenate a nil value (field 'auto_off_minutes')
Thanks, you're right. I update the script in my previous post. I'm not done with it yet, so I'm not putting it in the opening post yet. As You may see from the code I'm trying to add auto_on functionality to it too: I would like to have the possibility to specify in the settings the name of the sensor(s) that should switch the device On too. This would reduce the number of scripts running in my system even more. Because dzvents doesn't have meta-data triggers I am building a list of trigger devices, which gets updated every minute. Using this list I can then have this script check for every device activation if a device needs to be switched "On" too. This would make the functionality of auto_dim more useful, as I've noticed that swithcing a dimmer "On", returns it to the last level set. So that will always be the lowest dim level specified for that device. I want auto_on to set it to a specified level so that the light for can example go on at 100%, dim to 20% after 5 minutes of no movement and only after another 10 minutes go Off. If however someone enters the room, the light should go back to 100% again, even if it hasn't gone Off yet. But I'm still trying to get this to work correctly and I don't have a lot a free time for it.
Last edited by rrozema on Sunday 16 February 2020 11:34, edited 1 time in total.
rrozema
Posts: 470
Joined: Thursday 26 October 2017 13:37
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Delft
Contact:

Re: Generic auto-off

Post by rrozema »

Vondee wrote: Saturday 15 February 2020 22:10 There is however another issue, now the normal switches having settings of 30 minutes and controlled by a PIR sensor now switch off after a minute.
Please post the settings you've used, because I don't see this happening for my settings.
Vondee
Posts: 30
Joined: Sunday 12 January 2020 19:06
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Generic auto-off

Post by Vondee »

Hi,

settings:

{
"auto_off_minutes": 30,
"auto_off_motion_device": "kamer sensor PIR",
"auto_off_motion_device": "Keuken Sensor PIR",
"auto_off_motion_device": "PIR Garage"
}
rrozema
Posts: 470
Joined: Thursday 26 October 2017 13:37
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Delft
Contact:

Re: Generic auto-off

Post by rrozema »

Vondee wrote: Sunday 16 February 2020 20:06 Hi,

settings:

{
"auto_off_minutes": 30,
"auto_off_motion_device": "kamer sensor PIR",
"auto_off_motion_device": "Keuken Sensor PIR",
"auto_off_motion_device": "PIR Garage"
}
ah, That's my mistake. These are the settings I initially described for when you have more than one (motion) sensor for a light. Waaren pointed out however, that when you put them like this, only one of the auto_motion_device entries is used. The correct way to list multiple motion devices is like this:

Code: Select all

{
"auto_off_minutes": 30,
"auto_off_motion_device": ["kamer sensor PIR", "Keuken Sensor PIR", "PIR Garage"]
}
An additional tip: your device names do not seem to follow a pattern. Since device names are case-sensitive it helps a lot if you name your devices consistently. It doesn't matter what pattern you choose: all small, all caps, first letter capital, or camel case, but it really avoids a lot of issues if you always use the same method for naming all of your devices. So I would suggest to rename those sensors for example into "Kamer Sensor PIR", "Keuken Sensor PIR" and "Garage Sensor PIR".
Vondee
Posts: 30
Joined: Sunday 12 January 2020 19:06
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Generic auto-off

Post by Vondee »

Sorry for that, I did not read the whole post. I looked at the log's and found more strange things, so I suspect it all has to do with the wrong format of the motion detectors. I changed the descriptions to the new format and tomorrow I will try to run the new script.
The tip you had is an eyeopener for me and will take more care for naming new devices.
Many thanks so far for helping me. The script has great potential!

Again, thanks!
rrozema
Posts: 470
Joined: Thursday 26 October 2017 13:37
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Delft
Contact:

Re: Generic auto-off

Post by rrozema »

I updated the auto_dim (test) version another time: a small improvement for the timing. It now looks for secondsAgo to be greater than minutes * 60. This should make the timing more accurate when you've set only a small delay like 1 or 2 minutes.
Vondee
Posts: 30
Joined: Sunday 12 January 2020 19:06
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Generic auto-off

Post by Vondee »

I use now your latest script and seems to work OK now.
If however someone enters the room, the light should go back to 100% again, even if it hasn't gone Off yet. But I'm still trying to get this to work correctly and I don't have a lot a free time for it.
I do not think that I would use this functionality, since time / lux etc. is also an input to determine that a light should go on.
Vondee
Posts: 30
Joined: Sunday 12 January 2020 19:06
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Generic auto-off

Post by Vondee »

If I manually (or on time) turn the dimmed light off, then the script put it back at the level what was set by the '"auto_off_dimlevel".
The light was at the selected level for the "auto_off_dimlevel" when I turned off the light.

Or do I something wrong?
rrozema
Posts: 470
Joined: Thursday 26 October 2017 13:37
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Delft
Contact:

Re: Generic auto-off

Post by rrozema »

Vondee wrote: Thursday 20 February 2020 13:39 If I manually (or on time) turn the dimmed light off, then the script put it back at the level what was set by the '"auto_off_dimlevel".
The light was at the selected level for the "auto_off_dimlevel" when I turned off the light.

Or do I something wrong?
That should not be possible: at every run the script searches in the settings for a dim level that is lower than the light's current level and only activates that dim level. In other words: if the light is off, it should not find a new dim level to set, i.e. it makes no changes to the light's settings. Please post your settings for this light, maybe something is still wrong with that. Please also post the type of dimmer you have installed and the domoticz & dzvents version you are running on.
Vondee
Posts: 30
Joined: Sunday 12 January 2020 19:06
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Generic auto-off

Post by Vondee »

{
"auto_off_dimlevel": { "level": 20, "minutes": 30 },
"auto_off_motion_device": ["Keuken Sensor PIR"]
}
Vondee
Posts: 30
Joined: Sunday 12 January 2020 19:06
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Generic auto-off

Post by Vondee »

{
"auto_off_dimlevel": { "level": 20, "minutes": 30 },
"auto_off_motion_device": ["Keuken Sensor PIR"]
}
Dzvents 2.5.5
Zwave PIR
Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests