Page 1 of 1

Scripting variable PIR (extend time when triggered)

Posted: Friday 10 July 2020 23:24
by studiocascade
Dear Domoticz users,

I am using Domoticz for several years now, and i'm very satisfied.
Currently i have a dusk sensor that turns several lights on automatically.
There are also some lights in the back of the livingroom that are only switched on when a PIR detects movement.
What i currently have is this blockly script:
Blocklyscript.png
Blocklyscript.png (68.95 KiB) Viewed 1684 times
Explanation:
BM (=BewegingsMelder) is my PIR
VL (=VerLichting) is a lamp

The script checks if the lamp at the TV cabinet is on (which is always on when it's dark outside).
If that's the case and the PIR detects movement, it will turn on the light at the dining table (VL-Eettafel) and the other one in the back of the living room.

During the time we will possibly have dinner, the light at the dining table stays on for a longer period.
This is to be sure that the light stays on as long as we have dinner and we don't have to 'wave' to the PIR.
After 8.00pm we usually don't sit at that table anymore, so the light can be turned off much earlier.
That's why i set different delays in the script.

Well, after this very long introduction, i want the script to be a little smarter. But i think i'm not smart enough to achieve that. Maybe someone here can help me out?
(doesn't have to be Blockly. If it can be done another way, that'd be fine with me. But i'm not so good at scripting)

What i want is this:
If one of us walks by occasionally, i want it to turn on the light for - say - 1 minute and then turn off again.
If the PIR gets triggered again within that minute (or shortly after that minute) it's possible that one of us is working at the table.
So i want it to stay on for a longer period. Maybe prolong the time to 3 minutes and if the next trigger is within or short after 3 minutes, prolong it to 6.
Not sure if my explanation is clear and if it is possible to do something like this?

I hope someone can help me with it

Re: Scripting variable PIR (extend time when triggered)

Posted: Sunday 12 July 2020 9:49
by waaren
studiocascade wrote: Friday 10 July 2020 23:24 Currently i have a dusk sensor that turns several lights on automatically.
What i want is this:
If one of us walks by occasionally, i want it to turn on the light for - say - 1 minute and then turn off again.
If the PIR gets triggered again within that minute (or shortly after that minute) it's possible that one of us is working at the table.
So i want it to stay on for a longer period. Maybe prolong the time to 3 minutes and if the next trigger is within or short after 3 minutes, prolong it to 6.
I tried something similar in the past and eventually switched to using a small Xiaomi button (short press -> short period of lights on, long press -> longer period of lights on) because the mechanism with the motion detector was more annoying then useful.

But YMMV and you could try below dzVents script and see if it works for you.

When not yet familiar with dzVents please start with reading Get started Before implementing (~ 5 minutes). Special attention please for "In Domoticz go to Setup > Settings > Other and in the section EventSystem make sure the checkbox 'dzVents enabled' is checked. Also make sure that in the Security section in the settings you allow 127.0.0.1 to not need a password. dzVents uses that port to send certain commands to Domoticz. Finally make sure you have set your current location in Setup > Settings > System > Location, otherwise there is no way to determine nighttime/daytime state."

Code: Select all


return
{
    on =
    {
        devices =
        {
            'BM-achterkamer', -- PIR
        },
    },

    logging =
    {
        level = domoticz.LOG_DEBUG, -- set to LOG_ERROR when tested and OK
        marker = 'iMotion',
    },

    data =
    {
        iMotion =
        {
            history = true,
            maxMinutes = 10,
        },
    },

    execute = function(dz , item)
        local backroom = dz.devices('VL-Achterkamer')
        local dinnertable = dz.devices('VL Eettafel')
        local dinnerWindow = '16:00-19:59'
        local afterDinner = '20:00-05:00'

        local isDark = dz.devices('VL TV-kast').state == 'On'

        item.isOff = not(item.isActive)

        dz.log('isDark is ' .. tostring(isDark) .. ' and State of ' .. item.name .. ' is ' .. item.state, dz.LOG_DEBUG)

        local function switchOffLights(dinnertableDelay, backroomDelay)
            dz.log('I will switch off the the light ' .. dinnertable.name .. ' after ' .. dinnertableDelay .. ' seconds.',dz.LOG_DEBUG)
            dz.log('I will switch off the the light ' .. backroom.name .. ' after ' .. backroomDelay .. ' seconds.',dz.LOG_DEBUG)
            dinnertable.cancelQueuedCommands()
            dinnertable.switchOff().checkFirst().afterSec(dinnertableDelay)
            backroom.cancelQueuedCommands()
            backroom.switchOff().checkFirst().afterSec(backroomDelay)
        end

        if isDark and item.active then
            dz.data.iMotion.add('On')
            backroom.switchOn().checkFirst()
            dinnertable.switchOn().checkFirst()
        elseif item.isOff then
            local iMotionHistory1 = dz.data.iMotion.subsetSince('00:01:00')
            local iMotionHistory3 = dz.data.iMotion.subsetSince('00:03:00')
            local iMotionHistory6 = dz.data.iMotion.subsetSince('00:06:00')

            if dz.time.matchesRule('at ' .. dinnerWindow) then switchOffLights(1000, 800)
            elseif #iMotionHistory6 > 3 then switchOffLights(360,360)
            elseif #iMotionHistory3 > 2 then switchOffLights(180,180)
            elseif #iMotionHistory1 > 1 then switchOffLights(60,60)
            else switchOffLights(30, 30)
            end
        end
    end
}

Re: Scripting variable PIR (extend time when triggered)

Posted: Monday 13 July 2020 7:04
by Egregius
You surely can't do it with blockly. You need to start scripting for that.

The dzVents example of waaren will do, this is a Pass2PHP example:

Code: Select all

//PIR script
if ($status=='On') {
	if ($d['Light']['s']=='Off') {
		sw('Light', 'On');
	}
	if (past('PIR')<60) {
		if ($d['Light']['m']==0) {
			storemode('Light', 1);
		} elseif ($d['Light']['m']==1) {
			storemode('Light', 2);
		}
	}
}

//Light script
if ($status=='Off') {
	if ($d['Light']['m']>0) {
		storemode('Light', 0);
	}
}

//Timer script
if ($d['Light']['s']=='On'&&$d['PIR']['s']=='Off') {
	if ($d['Light']['m']==0&&past('PIR')>60) {
		sw('Light', 'Off');
	} elseif ($d['Light']['m']==1&&past('PIR')>180) {
		sw('Light', 'Off');
	} elseif ($d['Light']['m']==2&&past('PIR')>300) {
		sw('Light', 'Off');
	}
}

Re: Scripting variable PIR (extend time when triggered)

Posted: Wednesday 15 July 2020 23:49
by studiocascade
Thanks a lot for the useful answers!
I will start by reading and learning more about dzVents

Re: Scripting variable PIR (extend time when triggered)

Posted: Tuesday 13 October 2020 20:46
by studiocascade
Thanks a lot for this script, Waaren! Really appreciate it.
I'm running the script for a while now and my lights are getting switched on and off by the sensor.
During dinner the light stays on a bit longer, which is perfect.
But... in the time-window after dinner, the light always switches off after 30 seconds. So there's no extended time after the sensor is triggered for a second or third time.
Every time i trigger the sensor, this is added to the Domoticz log file:
Spoiler: show

Code: Select all

 2020-10-13 20:23:50.641 Status: dzVents: Debug: iMotion: Processing device-adapter for VL-Achterkamer: Switch device adapter
2020-10-13 20:23:50.642 Status: dzVents: Debug: iMotion: Processing device-adapter for VL Eettafel: RGB(W) device adapter
2020-10-13 20:23:50.642 Status: dzVents: Debug: iMotion: Processing device-adapter for VL Eettafel: Switch device adapter
2020-10-13 20:23:50.643 Status: dzVents: Debug: iMotion: Processing device-adapter for VL-Dummy: Switch device adapter
2020-10-13 20:23:50.643 Status: dzVents: Debug: iMotion: isDark is true and State of BM-achterkamer is Off
2020-10-13 20:23:50.644 Status: dzVents: Debug: iMotion: I will switch off the the light VL Eettafel after 30 seconds.
2020-10-13 20:23:50.644 Status: dzVents: Debug: iMotion: I will switch off the the light VL-Achterkamer after 30 seconds.
2020-10-13 20:23:50.644 Status: dzVents: Debug: iMotion: Constructed timed-command: Off
2020-10-13 20:23:50.644 Status: dzVents: Debug: iMotion: Constructed timed-command: Off
2020-10-13 20:23:50.644 Status: dzVents: Debug: iMotion: Constructed timed-command: Off AFTER 30 SECONDS
2020-10-13 20:23:50.644 Status: dzVents: Debug: iMotion: Constructed timed-command: Off
2020-10-13 20:23:50.644 Status: dzVents: Debug: iMotion: Constructed timed-command: Off
2020-10-13 20:23:50.644 Status: dzVents: Debug: iMotion: Constructed timed-command: Off AFTER 30 SECONDS
2020-10-13 20:23:50.646 Status: dzVents: Info: iMotion: ------ Finished Achterkamer smart
2020-10-13 20:23:50.647 Status: EventSystem: Script event triggered: /home/pi/domoticz/dzVents/runtime/dzVents.lua
2020-10-13 20:23:50.752 Status: dzVents: Info: Handling events for: "BM-achterkamer", value: "On"
2020-10-13 20:23:50.752 Status: dzVents: Info: iMotion: ------ Start internal script: Achterkamer smart: Device: "BM-achterkamer (Z-Wave)", Index: 1732
2020-10-13 20:23:50.755 Status: dzVents: Debug: iMotion: Processing device-adapter for VL-Achterkamer: Switch device adapter
2020-10-13 20:23:50.756 Status: dzVents: Debug: iMotion: Processing device-adapter for VL Eettafel: RGB(W) device adapter
2020-10-13 20:23:50.756 Status: dzVents: Debug: iMotion: Processing device-adapter for VL Eettafel: Switch device adapter
2020-10-13 20:23:50.757 Status: dzVents: Debug: iMotion: Processing device-adapter for VL-Dummy: Switch device adapter
2020-10-13 20:23:50.758 Status: dzVents: Debug: iMotion: isDark is true and State of BM-achterkamer is On
2020-10-13 20:23:50.758 Status: dzVents: Debug: iMotion: Constructed timed-command: On
2020-10-13 20:23:50.758 Status: dzVents: Debug: iMotion: Constructed timed-command: On
2020-10-13 20:23:50.759 Status: dzVents: Info: iMotion: ------ Finished Achterkamer smart
2020-10-13 20:24:20.524 Status: dzVents: Info: Handling events for: "BM-achterkamer", value: "Off"
2020-10-13 20:24:20.524 Status: dzVents: Info: iMotion: ------ Start internal script: Achterkamer smart: Device: "BM-achterkamer (Z-Wave)", Index: 1732
2020-10-13 20:24:20.528 Status: dzVents: Debug: iMotion: Processing device-adapter for VL-Achterkamer: Switch device adapter
2020-10-13 20:24:20.529 Status: dzVents: Debug: iMotion: Processing device-adapter for VL Eettafel: RGB(W) device adapter
2020-10-13 20:24:20.529 Status: dzVents: Debug: iMotion: Processing device-adapter for VL Eettafel: Switch device adapter
2020-10-13 20:24:20.530 Status: dzVents: Debug: iMotion: Processing device-adapter for VL-Dummy: Switch device adapter
2020-10-13 20:24:20.530 Status: dzVents: Debug: iMotion: isDark is true and State of BM-achterkamer is Off
2020-10-13 20:24:20.530 Status: dzVents: Debug: iMotion: I will switch off the the light VL Eettafel after 30 seconds.
2020-10-13 20:24:20.530 Status: dzVents: Debug: iMotion: I will switch off the the light VL-Achterkamer after 30 seconds.
2020-10-13 20:24:20.530 Status: dzVents: Debug: iMotion: Constructed timed-command: Off
2020-10-13 20:24:20.530 Status: dzVents: Debug: iMotion: Constructed timed-command: Off
2020-10-13 20:24:20.530 Status: dzVents: Debug: iMotion: Constructed timed-command: Off AFTER 30 SECONDS
2020-10-13 20:24:20.530 Status: dzVents: Debug: iMotion: Constructed timed-command: Off
2020-10-13 20:24:20.531 Status: dzVents: Debug: iMotion: Constructed timed-command: Off
2020-10-13 20:24:20.531 Status: dzVents: Debug: iMotion: Constructed timed-command: Off AFTER 30 SECONDS
2020-10-13 20:24:20.532 Status: dzVents: Info: iMotion: ------ Finished Achterkamer smart
2020-10-13 20:24:20.534 Status: EventSystem: Script event triggered: /home/pi/domoticz/dzVents/runtime/dzVents.lua
2020-10-13 20:24:20.640 Status: dzVents: Info: Handling events for: "BM-achterkamer", value: "Off"
2020-10-13 20:24:20.640 Status: dzVents: Info: iMotion: ------ Start internal script: Achterkamer smart: Device: "BM-achterkamer (Z-Wave)", Index: 1732
2020-10-13 20:24:20.643 Status: dzVents: Debug: iMotion: Processing device-adapter for VL-Achterkamer: Switch device adapter
2020-10-13 20:24:20.644 Status: dzVents: Debug: iMotion: Processing device-adapter for VL Eettafel: RGB(W) device adapter
2020-10-13 20:24:20.644 Status: dzVents: Debug: iMotion: Processing device-adapter for VL Eettafel: Switch device adapter
2020-10-13 20:24:20.645 Status: dzVents: Debug: iMotion: Processing device-adapter for VL-Dummy: Switch device adapter
2020-10-13 20:24:20.646 Status: dzVents: Debug: iMotion: isDark is true and State of BM-achterkamer is Off
2020-10-13 20:24:20.646 Status: dzVents: Debug: iMotion: I will switch off the the light VL Eettafel after 30 seconds.
2020-10-13 20:24:20.646 Status: dzVents: Debug: iMotion: I will switch off the the light VL-Achterkamer after 30 seconds.
2020-10-13 20:24:20.646 Status: dzVents: Debug: iMotion: Constructed timed-command: Off
2020-10-13 20:24:20.646 Status: dzVents: Debug: iMotion: Constructed timed-command: Off
2020-10-13 20:24:20.646 Status: dzVents: Debug: iMotion: Constructed timed-command: Off AFTER 30 SECONDS
2020-10-13 20:24:20.646 Status: dzVents: Debug: iMotion: Constructed timed-command: Off
2020-10-13 20:24:20.646 Status: dzVents: Debug: iMotion: Constructed timed-command: Off
2020-10-13 20:24:20.647 Status: dzVents: Debug: iMotion: Constructed timed-command: Off AFTER 30 SECONDS
2020-10-13 20:24:20.648 Status: dzVents: Info: iMotion: ------ Finished Achterkamer smart
2020-10-13 20:24:20.649 Status: EventSystem: Script event triggered: /home/pi/domoticz/dzVents/runtime/dzVents.lua 
What could be wrong?
I copied waaren's script exactly, because he already put the device names correctly in it.

Like i said, i'm not very good at scripting, so i don't know exactly what I can do to solve this.
But maybe clarifying my idea helps:
After dinnertime, if the sensor is triggered occassionaly the specified lights should stay on for a short time (say 30 sec or 1 min) and then turn off again.
This is the case if we sometimes just have to get something from the table or whatever.
If the sensor gets triggered a second time while the light is still on, the time the light has to stay on should be extended with a few minutes.
This is to prevent the light from turning off while i'm working at the dinner table.

If i finished working and get back to the main living room, the light would - after a while - turn off again.

Feel free to ask me if it needs more explanation.

Re: Scripting variable PIR (extend time when triggered)

Posted: Tuesday 13 October 2020 21:47
by waaren
studiocascade wrote: Tuesday 13 October 2020 20:46 This is to prevent the light from turning off while i'm working at the dinner table.
If i finished working and get back to the main living room, the light would - after a while - turn off again.
Not sure if you only want to extend the light of the dinner table or also from the backroom. For now I assumed both.

You could try this and play a little with the value of afterDinnerDelay

Code: Select all

return
{
    on =
    {
        devices =
        {
            'BM-achterkamer', -- PIR
        },
    },

    logging =
    {
        level = domoticz.LOG_DEBUG, -- set to LOG_ERROR when tested and OK
        marker = 'iMotion',
    },

    data =
    {
        iMotion =
        {
            history = true,
            maxMinutes = 10,
        },
    },

    execute = function(dz , item)
        local backroom = dz.devices('VL-Achterkamer')
        local dinnertable = dz.devices('VL Eettafel')
        local dinnerWindow = '16:00-19:59'
        local afterDinner = '20:00-05:00'
	
	local afterDinnerDelay = 300 -- Change this to a value that suits you
        
        local isDark = dz.devices('VL TV-kast').state == 'On'

        item.isOff = not(item.isActive)

        dz.log('isDark is ' .. tostring(isDark) .. ' and State of ' .. item.name .. ' is ' .. item.state, dz.LOG_DEBUG)

        local function switchOffLights(dinnertableDelay, backroomDelay)
            backroomDelay = backroomDelay or dinnertableDelay
            dz.log('I will switch off the the light ' .. dinnertable.name .. ' after ' .. dinnertableDelay .. ' seconds.',dz.LOG_DEBUG)
            dz.log('I will switch off the the light ' .. backroom.name .. ' after ' .. backroomDelay .. ' seconds.',dz.LOG_DEBUG)
            dinnertable.cancelQueuedCommands()
            dinnertable.switchOff().checkFirst().afterSec(dinnertableDelay)
            backroom.cancelQueuedCommands()
            backroom.switchOff().checkFirst().afterSec(backroomDelay)
        end

        if isDark and item.active then
            dz.data.iMotion.add('On')
            backroom.switchOn().checkFirst()
            dinnertable.switchOn().checkFirst()
        elseif item.isOff then
            local iMotionHistory1 = dz.data.iMotion.subsetSince('00:01:00')
            local iMotionHistory3 = dz.data.iMotion.subsetSince('00:03:00')
            local iMotionHistory6 = dz.data.iMotion.subsetSince('00:06:00')
            
            if not(dz.time.matchesRule('at ' .. afterDinner)) then afterDinnerDelay = 0 end

            if dz.time.matchesRule('at ' .. dinnerWindow) then switchOffLights(1000, 800)
            elseif #iMotionHistory6 > 3 then switchOffLights(360 + afterDinnerDelay * 3)
            elseif #iMotionHistory3 > 2 then switchOffLights(180 + afterDinnerDelay * 2)
            elseif #iMotionHistory1 > 1 then switchOffLights(60 + afterDinnerDelay)
            else switchOffLights(30 + afterDinnerDelay / 2 )
            end
        end
    end
}

Re: Scripting variable PIR (extend time when triggered)

Posted: Wednesday 14 October 2020 14:40
by studiocascade
Thanks a lot again!
I really appreciate it.

I have implemented the new script, tonight i will test it when it's dark enough.

Re: Scripting variable PIR (extend time when triggered)

Posted: Sunday 18 October 2020 10:39
by studiocascade
Lots of thanks!
This script works perfect for me!

Re: Scripting variable PIR (extend time when triggered)

Posted: Monday 09 November 2020 19:56
by studiocascade
we're running this script for a few months now and it works fine.
Although my wife had a request. Maybe someone here who's able to refine the script can help us out?

In the above script, we are switching two lights (backroom and dinnertable) together.
For the lamp 'dinnertable', we sometimes want it to run with the script, sometimes we want it permanent on and sometimes we want it permanent off.
I have been thinking of making a dummy selector, combined with this script.
Is that possible?

Re: Scripting variable PIR (extend time when triggered)  [Solved]

Posted: Monday 09 November 2020 21:17
by waaren
studiocascade wrote: Monday 09 November 2020 19:56 For the lamp 'dinnertable', we sometimes want it to run with the script, sometimes we want it permanent on and sometimes we want it permanent off. I have been thinking of making a dummy selector, combined with this script.
Can you try with below modified script?

Code: Select all

return
{
    on =
    {
        devices =
        {
            'BM-achterkamer', -- PIR
            'DinnerTableControl', -- define as selector with levelnames 'Off', 'On' and 'dzVents' 
        },
    },

    logging =
    {
        level = domoticz.LOG_DEBUG, -- set to LOG_ERROR when tested and OK
        marker = 'iMotion',
    },

    data =
    {
        iMotion =
        {
            history = true,
            maxMinutes = 10,
        },
    },

    execute = function(dz , item)
        local backroom = dz.devices('VL-Achterkamer')
        local dinnertable = dz.devices('VL Eettafel')
        local dinnertableController = dz.devices('DinnerTableControl') -- define as selector with levelnames 'Off', 'On' and 'dzVents' 
        local dinnerWindow = '16:00-19:59'
        local afterDinner = '20:00-05:00'
	
        local afterDinnerDelay = 300 -- Change this to a value that suits you
        local isDark = dz.devices('VL TV-kast').state == 'On'


        if item == dinnerTableController then
            if item.levelName == 'On' then 
                dinnertable.switchOn() 
            elseif item.levelName == 'Off' then 
                dinnertable.switchOff() 
            end
            return
        end
        
        item.isOff = not(item.isActive)

        dz.log('isDark is ' .. tostring(isDark) .. ' and State of ' .. item.name .. ' is ' .. item.state, dz.LOG_DEBUG)


        local function dinnerTableControl(action, delay)
            if dinnertableController.levelName == 'dzVents' then
                if action == 'Off' then
                    dinnertable.cancelQueuedCommands()
                    dinnertable.switchOff().checkFirst().afterSec(delay)
                    dz.log('I will switch off light ' .. dinnertable.name .. ' after ' .. delay .. ' seconds. (if it is not already off)',dz.LOG_DEBUG)
                elseif action == 'On' then
                    dz.log('I will switch on light ' .. dinnertable.name .. ' (if it is not already on)' ,dz.LOG_DEBUG)
                    dinnertable.switchOn().checkFirst()
                end
            else
                dz.log('device ' .. dinnertable.name .. ' is not controlled by this script.',dz.LOG_DEBUG)
            end
        end

        local function switchOffLights(dinnertableDelay, backroomDelay)
            backroomDelay = backroomDelay or dinnertableDelay

            dinnertableControl('Off', dinnertableDelay)
            dz.log('I will switch off the the light ' .. backroom.name .. ' after ' .. backroomDelay .. ' seconds. (if it is not already off)',dz.LOG_DEBUG)
            backroom.cancelQueuedCommands()
            backroom.switchOff().checkFirst().afterSec(backroomDelay)
        end
        
        if isDark and item.active then
            dz.data.iMotion.add('On')
            backroom.switchOn().checkFirst()
            dinnerTableControl('On')
        elseif item.isOff then
            local iMotionHistory1 = dz.data.iMotion.subsetSince('00:01:00')
            local iMotionHistory3 = dz.data.iMotion.subsetSince('00:03:00')
            local iMotionHistory6 = dz.data.iMotion.subsetSince('00:06:00')
            
            if not(dz.time.matchesRule('at ' .. afterDinner)) then afterDinnerDelay = 0 end

            if dz.time.matchesRule('at ' .. dinnerWindow) then switchOffLights(1000, 800)
            elseif #iMotionHistory6 > 3 then switchOffLights(360 + afterDinnerDelay * 3)
            elseif #iMotionHistory3 > 2 then switchOffLights(180 + afterDinnerDelay * 2)
            elseif #iMotionHistory1 > 1 then switchOffLights(60 + afterDinnerDelay)
            else switchOffLights(30 + afterDinnerDelay / 2 )
            end
        end
    end
}

Re: Scripting variable PIR (extend time when triggered)

Posted: Thursday 12 November 2020 15:47
by studiocascade
Yeah, this seems to work!
I had to modify the script slightly, because there was somewhere expected the word 'dinnertablecontroller' instead of 'dinnertablecontrol'.
(not sure anymore where it was)
But that's fixed now.
Thank you so much waaren! I really appreciate that you scripted this for me.
I'm still learning it (and this helps me too)