This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

Presence sensor - Reset timer/delay
#1
Hi,

I am struggling getting a script related to a presence sensor to work. I have made an event based script, but it does not turn out the way I like.

value = event.getvalue()
val1 = 15
if value == true then
  grp.write('2/2/2', 1)
elseif value == false then
  os.sleep(300)
  grp.write('2/2/2', 0)
end

If the presence sensor (1/1/1) is triggered and writes a 1, then I would like the light (2/2/2) to be turned on.
When presence is no longer detected it writes a 0, and I would like the light to be turned off. However, I do not want the light to be turned of straight away, I would like to wait 5 min before the light is turned off. 
So far so good...
This is where I am struggling, if presence again is detected before the 5 min expires, the presence sensor writes another 1. However, the previous script is still running so the light gets turned off before the last 5 min expires.

I would like a solution where another 1 from the presence detector resets the timer. So if someone constantly walks in and out of the room within a time frame of less then 5 minutes, then the light constantly stays on.

I am not sure if an event based script is the way to go...
BR
Mr. D
Reply
#2
Hi,

Yes event based scripts initiate a new script instance on each new event, so there can be multiple events running in parallel, especialy when you use a os.sleep in it.

We can solve it by registering the program id (pid) on each created event and kiil the previous script again on a new event.

I created a long time ago a staircase timer with external time object (end user can change it from visu) and retrigger option. 

This is one of my first scripts when i started to work with homeLYnk so it might be possible to make it more compact, but it does it work (:

Code:
-- ** Staircase logic with external time object and retriggering on input object Version 3.1 ** --
-- ****************************** Created by Erwin van der Zwart **************************** --
-- ************************************** SET PARAMETERS ************************************ --

-- Set input address
AddressInput = '6/0/0'

-- Set output address
AddressOutput = '6/0/1'

-- Set external time address (optional)
AddressExternalTime = '6/0/2'

-- Use time left indication
UseTimeLeft = false -- Set to true if time left indication will be used

-- Set feedback adress of time left indication (optional)
AddressTimeLeft = '6/0/3'

-- Set time delay (Used when external time is not available)
SetDelay = 10

-- Seconds or Minutes
SetSec = true -- Set to false for Minutes

-- Set factor delay (Multiplies Delay)
SetFac = 1

-- Set unique name for staircase timer (to avoid same storage name usage)
StaircaseName = 'Staircase_1'

-- Logic can be turned of by value 0
Off_by_Value_Zero = false

-- ************************************** END PARAMETERS ************************************ --
-- *************************** DON'T CHANGE ANYTHING UNDER THIS LINE ************************ --

inputvalue = event.getvalue
if Off_by_Value_Zero == false and (event.getvalue() == false or event.getvalue() == 0) then
 -- Exit script
 return
end

ValueInput = grp.getvalue(AddressInput)
ValueOutput = grp.getvalue(AddressOutput)
ValueExternalTime = grp.getvalue(AddressExternalTime)
if SetSec == true then
 SetSeconds = 1
else
 SetSeconds = 60
end
if ValueExternalTime == nil then
ValueExternalTime = 0
end
if ValueExternalTime > 0 then
 StairCaseTime = ValueExternalTime * SetSeconds * SetFac
else
 StairCaseTime = SetDelay * SetSeconds * SetFac
end
if ValueInput == true then
 --check for earlier started scrips
 --check storage for stpid value
 stpid = storage.get(StaircaseName)  
 --check if stpid has a value
 if stpid == nil then
    pid = os.getpid()
    storage.set(StaircaseName, pid)
 else
    -- kill earlier running script    
    os.kill(stpid, signal.SIGKILL)
    -- create new pid for next time to kill
    pid = os.getpid()  
    storage.set(StaircaseName, pid)
 end
 if ValueOutput == false then
   grp.write(AddressOutput, true)
   ValueOutput = true
 end
 -- Check time left indication is used
 if UseTimeLeft == true then
   if StairCaseTime > 0 then
       grp.update(AddressTimeLeft, StairCaseTime)
       repeat
         StairCaseTime = StairCaseTime - 1
         grp.update(AddressTimeLeft, StairCaseTime)
         os.sleep(1)
       until StairCaseTime == 0
   end    
 else
   os.sleep(StairCaseTime)
 end
 ValueOutput = grp.getvalue(AddressOutput)
 if ValueOutput == true then
   ValueInput = grp.getvalue(AddressInput)
   if ValueInput == true then
       grp.write(AddressInput, false)
     ValueInput = false
   end
   if Off_by_Value_Zero == false then
     if ValueOutput == true then
           grp.write(AddressOutput, false)
       ValueOutput = false
         end
   else
     -- Do nothing, this will trigger else condition below on next run
   end
 end  
else
 --check for earlier started scrips
 --check storage for stpid value
 stpid = storage.get(StaircaseName)  
 --check if stpid has a value
 if stpid == nil then
 else
   -- kill earlier running script    
   os.kill(stpid, signal.SIGKILL)
   grp.update(AddressTimeLeft, 0)
   pid = nil
   storage.set(StaircaseName, pid)
 end
 if ValueOutput == true then
   grp.write(AddressOutput, false)
 end
end

BR,

Erwin
Reply
#3
Thanks for your help Erwin,
However, I get an error from line 66 when trying to run your script. I might have done something wrong... I am completely new to lua programming.

I am also wondering if using a combination of an event-based script and a resident script could do the job.
I created the following two scripts before I saw your reply. The two scripts seem to work as intended, but this might be a poor use of resources in terms of memory etc compared to your script?

The logic is enabling and disabling the resident script...

Event-based script:
value = event.getvalue()
if value == true then
grp.write('Lights', 1)
script.disable('Sensor')
end
if value == false then
script.enable('Sensor')
end

Resident script:
os.sleep(300)
value1 = grp.getvalue('motion sensor')
if value1 == false then
grp.write('Lights', 0)
end
script.disable('Sensor')

What you think?

BR
Mr. D
Reply
#4
Hi,

I tested my script in a empty controller before i posted it (just to be sure) and worked as intended.

How do you use this script? You need to make it a event based and link it to the sensor output object.

BR,

Erwin
Reply
#5
Hi Erwin,

I tried your script once more, and this time I got it to work. I must have made a copy error or something the last time Smile
Thank you!

In regards to my 2 scripts. I am trying to understand how things work, and I don't understand how they can not be a stable solution. Could you try and explain it to me in a bit more detail. This way I get a better understanding. Because I am also writing scripts that controls one light depending on the status of two doors... and there is also a delay involved... These scripts is based on the same logic, thus making it important for me to understand (:

Just so you know the way my motion sensor is set up:
If presence is detected it will send a 1 straight away.
If presence is no longer detected, it will wait 10 seconds, and then send a 0.
As long as there is presence, nothings is being sent.

My Event-based script is triggered by my motion sensor.
If a 1 is received the script turns on the light and disables the resident script called "Sensor".
If a 0 is received it activates the resident script called "Sensor"

The resident script is called "Sensor"
If active, waits 5 min, then checks if value of my motion sensor = 0 (no presence), if so it turns the light of.

Thanks for your help so far!

BR
Mr. D
Reply
#6
Hi
I have another way of running this logic that works perfect for me.

Here is a resident script with 60 seconds interval.
My motion/door detector sends 70%( or 1 in case of on/off object) to the light output(Kjøkken Hvit) and sets timer lys kjøkken to 10(this is the wanted off delay)
Then the first script underneath checks if the object is greater than 1, if it is it subtracts one from the object each minute until the object is 1.
Then it turns of the light.
This script support retriggering as it sets the timer back to the wanted off delay.
In case you want a warning or two step off lightning you could on object =2 or 3 make the light dim down to for instance 20%.

You can put many different light object in same resident script. That is the reason I got three in this oneSmile

The first and the third script is only triggering when the house is in nightmode. It dims the light up and down automatically by night and works as a normal switch controlled Zone by daySmile

The second script is the garage that always is on motion detector.

Lykke tilSmile
Ruben

kjøkken = grp.getvalue('Timer Lys Kjøkken')
if kjøkken > 1 then
 grp.write('Timer Lys Kjøkken', kjøkken - 1)
elseif kjøkken == 1 then
 grp.write('Timer Lys Kjøkken', kjøkken - 1)
   if grp.getvalue('Scene Natt') == true then
   grp.write('Kjøkken Hvit', 0)
end
end

garasje = grp.getvalue('6/2/3')
if garasje > 1 then
 grp.write('6/2/3', garasje - 1)
elseif garasje == 1 then
 grp.write('6/2/3', garasje - 1)
   grp.write('Bryter Rele 3 kanal 6', 0)
end


gang = grp.getvalue('6/2/1')
if gang > 1 then
 grp.write('6/2/1', gang - 1)
elseif gang == 1 then
 grp.write('6/2/1', gang - 1)
 if grp.getvalue('Scene Natt') == true then
   grp.write('Sluse 1 Etg Dim', 5)
   grp.write('Bad 1 etg Dim', 0)
end
end
Reply
#7
Hi Ruben
Thanks for your input, it was most helpful!
I just have one rookie question, how to you set the "timer lys kjøkken" to a delay of 10?
Is this a timer script, if so how does one write this?
Takk Smile
Mr. D
Reply
#8
I made this script running as an event script. As you can see I also got the scene night logic in here. You can delete this line and the first end line in case you dont need a second variable logic.

Each time the motion detector gets movement the light goes to 25% and after off delay, here set to 10 minutes, the other script turns it offSmile

if event.getvalue() == true then
if grp.getvalue('Scene Natt') == true then
grp.write('Kjøkken Hvit', 25)
grp.write('Timer Lys Kjøkken', 10)
end
end

Mvh Ruben
Reply
#9
Thanks Ruben!! Smile
This was very helpful and gave me some new ideas!
Mvh
Mr. D
Reply
#10
No problem. Just share incase you find good improvementsSmile
Reply
#11
@Erwin

I used your script and it woked fine, but then i disabel the timer i like to kill the remaining time counter. I see that it repeat until the value = 0 but it will be nice to kill thit timer counter.

Code:
-- ** Staircase logic with external time object and retriggering on input object Version 3.1 ** --
-- ****************************** Created by Erwin van der Zwart **************************** --
-- ************************************** SET PARAMETERS ************************************ --

-- Set input address
AddressInput = '40/0/1'

-- Set output address
AddressOutput = '40/0/4'

-- Set external time address (optional)
AddressExternalTime = '40/0/2'

-- Use time left indication
UseTimeLeft = true -- Set to true if time left indication will be used

-- Set feedback adress of time left indication (optional)
AddressTimeLeft = '40/0/3'

-- Set time delay (Used when external time is not available)
SetDelay = 10

-- Seconds or Minutes
SetSec = true -- Set to false for Minutes

-- Set factor delay (Multiplies Delay)
SetFac = 1

-- Set unique name for staircase timer (to avoid same storage name usage)
StaircaseName = 'Staircase_1'

-- Logic can be turned of by value 0
Off_by_Value_Zero = false

-- ************************************** END PARAMETERS ************************************ --
-- *************************** DON'T CHANGE ANYTHING UNDER THIS LINE ************************ --

inputvalue = event.getvalue
if Off_by_Value_Zero == false and (event.getvalue() == false or event.getvalue() == 0) then
  -- Exit script
  return
end

ValueInput = grp.getvalue(AddressInput)
ValueOutput = grp.getvalue(AddressOutput)
ValueExternalTime = grp.getvalue(AddressExternalTime)
if SetSec == true then
  SetSeconds = 1
else
  SetSeconds = 60
end
if ValueExternalTime == nil then
ValueExternalTime = 0
end
if ValueExternalTime > 0 then
  StairCaseTime = ValueExternalTime * SetSeconds * SetFac
else
  StairCaseTime = SetDelay * SetSeconds * SetFac
end
if ValueInput == true then
  --check for earlier started scrips
  --check storage for stpid value
  stpid = storage.get(StaircaseName)  
  --check if stpid has a value
  if stpid == nil then
     pid = os.getpid()
     storage.set(StaircaseName, pid)
  else
     -- kill earlier running script    
     os.kill(stpid, signal.SIGKILL)
     -- create new pid for next time to kill
     pid = os.getpid()  
     storage.set(StaircaseName, pid)
  end
  if ValueOutput == false then
    grp.write(AddressOutput, true)
    ValueOutput = true
  end
  -- Check time left indication is used
  if UseTimeLeft == true then
    if StairCaseTime > 0 then
        grp.update(AddressTimeLeft, StairCaseTime)
        repeat
          StairCaseTime = StairCaseTime - 1
          grp.update(AddressTimeLeft, StairCaseTime)
          os.sleep(1)
        until StairCaseTime == 0
    end    
  else
    os.sleep(StairCaseTime)
  end
  ValueOutput = grp.getvalue(AddressOutput)
  if ValueOutput == true then
    ValueInput = grp.getvalue(AddressInput)
    if ValueInput == true then
        grp.write(AddressInput, false)
      ValueInput = false
    end
    if Off_by_Value_Zero == false then
      if ValueOutput == true then
            grp.write(AddressOutput, false)
        ValueOutput = false
          end
    else
      -- Do nothing, this will trigger else condition below on next run
    end
  end  
else
  --check for earlier started scrips
  --check storage for stpid value
  stpid = storage.get(StaircaseName)  
  --check if stpid has a value
  if stpid == nil then
  else
    -- kill earlier running script    
    os.kill(stpid, signal.SIGKILL)
    grp.update(AddressTimeLeft, 0)
    pid = nil
    storage.set(StaircaseName, pid)
  end
  if ValueOutput == true then
    grp.write(AddressOutput, false)
  end
end-- ** Staircase logic with external time object and retriggering on input object Version 3.1 ** --
-- ****************************** Created by Erwin van der Zwart **************************** --
-- ************************************** SET PARAMETERS ************************************ --

-- Set input address
AddressInput = '40/0/1'

-- Set output address
AddressOutput = '40/0/4'

-- Set external time address (optional)
AddressExternalTime = '40/0/2'

-- Use time left indication
UseTimeLeft = true -- Set to true if time left indication will be used

-- Set feedback adress of time left indication (optional)
AddressTimeLeft = '40/0/3'

-- Set time delay (Used when external time is not available)
SetDelay = 10

-- Seconds or Minutes
SetSec = true -- Set to false for Minutes

-- Set factor delay (Multiplies Delay)
SetFac = 1

-- Set unique name for staircase timer (to avoid same storage name usage)
StaircaseName = 'Staircase_1'

-- Logic can be turned of by value 0
Off_by_Value_Zero = false

-- ************************************** END PARAMETERS ************************************ --
-- *************************** DON'T CHANGE ANYTHING UNDER THIS LINE ************************ --

inputvalue = event.getvalue
if Off_by_Value_Zero == false and (event.getvalue() == false or event.getvalue() == 0) then
  -- Exit script
  return
end

ValueInput = grp.getvalue(AddressInput)
ValueOutput = grp.getvalue(AddressOutput)
ValueExternalTime = grp.getvalue(AddressExternalTime)
if SetSec == true then
  SetSeconds = 1
else
  SetSeconds = 60
end
if ValueExternalTime == nil then
ValueExternalTime = 0
end
if ValueExternalTime > 0 then
  StairCaseTime = ValueExternalTime * SetSeconds * SetFac
else
  StairCaseTime = SetDelay * SetSeconds * SetFac
end
if ValueInput == true then
  --check for earlier started scrips
  --check storage for stpid value
  stpid = storage.get(StaircaseName)  
  --check if stpid has a value
  if stpid == nil then
     pid = os.getpid()
     storage.set(StaircaseName, pid)
  else
     -- kill earlier running script    
     os.kill(stpid, signal.SIGKILL)
     -- create new pid for next time to kill
     pid = os.getpid()  
     storage.set(StaircaseName, pid)
  end
  if ValueOutput == false then
    grp.write(AddressOutput, true)
    ValueOutput = true
  end
  -- Check time left indication is used
  if UseTimeLeft == true then
    if StairCaseTime > 0 then
        grp.update(AddressTimeLeft, StairCaseTime)
        repeat
          StairCaseTime = StairCaseTime - 1
          grp.update(AddressTimeLeft, StairCaseTime)
          os.sleep(1)
        until StairCaseTime == 0
    end    
  else
    os.sleep(StairCaseTime)
  end
  ValueOutput = grp.getvalue(AddressOutput)
  if ValueOutput == true then
    ValueInput = grp.getvalue(AddressInput)
    if ValueInput == true then
        grp.write(AddressInput, false)
      ValueInput = false
    end
    if Off_by_Value_Zero == false then
      if ValueOutput == true then
            grp.write(AddressOutput, false)
        ValueOutput = false
          end
    else
      -- Do nothing, this will trigger else condition below on next run
    end
  end  
else
  --check for earlier started scrips
  --check storage for stpid value
  stpid = storage.get(StaircaseName)  
  --check if stpid has a value
  if stpid == nil then
  else
    -- kill earlier running script    
    os.kill(stpid, signal.SIGKILL)
    grp.update(AddressTimeLeft, 0)
    pid = nil
    storage.set(StaircaseName, pid)
  end
  if ValueOutput == true then
    grp.write(AddressOutput, false)
  end
end
Reply


Forum Jump: