Posts: 136
Threads: 18
Joined: Apr 2017
Reputation:
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
Posts: 1759
Threads: 6
Joined: Jul 2015
Reputation:
115
14.04.2017, 22:04
(This post was last modified: 14.04.2017, 22:31 by Erwin van der Zwart.)
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
Posts: 136
Threads: 18
Joined: Apr 2017
Reputation:
1
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
Posts: 1759
Threads: 6
Joined: Jul 2015
Reputation:
115
15.04.2017, 23:54
(This post was last modified: 17.04.2017, 06:38 by Erwin van der Zwart.)
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
Posts: 136
Threads: 18
Joined: Apr 2017
Reputation:
1
16.04.2017, 10:27
(This post was last modified: 16.04.2017, 10:54 by Mr.D.)
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
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
Posts: 176
Threads: 42
Joined: Jul 2015
Reputation:
2
16.04.2017, 15:25
(This post was last modified: 16.04.2017, 15:27 by PassivPluss.)
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 one
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 day
The second script is the garage that always is on motion detector.
Lykke til
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
Posts: 136
Threads: 18
Joined: Apr 2017
Reputation:
1
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
Mr. D
Posts: 176
Threads: 42
Joined: Jul 2015
Reputation:
2
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 off
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
Posts: 136
Threads: 18
Joined: Apr 2017
Reputation:
1
Thanks Ruben!!
This was very helpful and gave me some new ideas!
Mvh
Mr. D
Posts: 176
Threads: 42
Joined: Jul 2015
Reputation:
2
No problem. Just share incase you find good improvements
Posts: 6
Threads: 1
Joined: Dec 2020
Reputation:
0
@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
|