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:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
-- ** 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:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
-- ** 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: