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.

Delay script
#1
Hopefully someone here can help me with the following. My programming skills are very bad, but sometimes I can go a long way with some cutting and pasting Smile.

I am looking for a scrypt for my LogicMachine with the following function.

If an ON is given at group address 0/0/1, a timer must start running for 6 minutes, after which an ON must be given to group address 0/0/2.

However, when an OFF arrives on 0/0/1, it must be passed on to 0/0/2 with 30 seconds delay.

So a delay of 6 minutes needs to be given when switching on and 30 seconds when swithcing Off may be right.

Does anyone have an example of this perhaps?
Reply
#2
What should happen if another ON arrives during the 6 minute wait time?
Reply
#3
(08.12.2022, 10:59)admin Wrote: What should happen if another ON arrives during the 6 minute wait time?

That normally can't happen. But if it's happening the timer can still continue and ignore this extra ON within the 6 min.


Might be good as background information. I want to use this script to control valves for underfloor heating.

Since I only have electric valves on all groups that are closed by default, the boiler cannot lose its heat when there is a demand for heat. The valves need time to open. The heat controller only immediately sends an ON to the central heating boiler, which immediately starts firing. It then breaks down because the valves are not yet open.
Reply
#4
Resident script with 0 sleep time. Single script can be used for multiple timers by adding more entries to the timers table at the top of the script.
Code:
1234567891011121314151617181920212223242526272829303132333435363738394041
if not client then   timers = {     ['1/1/1'] = {       output = '1/1/2', -- binary output       delayon = 6 * 60, -- on delay time (seconds)       delayoff = 30, -- off delay time (seconds)     }   }   grp.sender = 'tm'   client = require('localbus').new(0.1)   client:sethandler('groupwrite', function(event)     local timer = timers[ event.dst ]          if timer and event.sender ~= grp.sender then       local value = tonumber(event.datahex, 16) or 0       local state = value > 0 and 'on' or 'off'              if timer.state ~= state then         timer.state = state         timer.ticks = timer['delay' .. state]       end     end   end) end client:loop(1) for _, timer in pairs(timers) do   if timer.ticks then     timer.ticks = timer.ticks - 1     if timer.ticks == 0 then       grp.checkwrite(timer.output, timer.state == 'on')       timer.state = nil       timer.ticks = nil     end   end end
Reply
#5
it's working!!!

Thank you for the help!!
Reply
#6
Is this going to work? I would like to add a second timer with input 0/0/17 but to a different output.

Wondering if this is right?

Code:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546
if not client then   timers = {     ['0/0/17'] = {       output = '0/0/24', -- binary output       delayon = 3 * 60, -- on delay time (seconds)       delayoff = 2, -- off delay time (seconds)     },     ['0/0/17'] = {       output = '0/0/25', -- binary output       delayon = 2, -- on delay time (seconds)       delayoff = 2 * 60, -- off delay time (seconds)     }   }   grp.sender = 'tm'   client = require('localbus').new(0.1)   client:sethandler('groupwrite', function(event)     local timer = timers[ event.dst ]         if timer and event.sender ~= grp.sender then       local value = tonumber(event.datahex, 16) or 0       local state = value > 0 and 'on' or 'off'             if timer.state ~= state then         timer.state = state         timer.ticks = timer['delay' .. state]       end     end   end) end client:loop(1) for _, timer in pairs(timers) do   if timer.ticks then     timer.ticks = timer.ticks - 1     if timer.ticks == 0 then       grp.checkwrite(timer.output, timer.state == 'on')       timer.state = nil       timer.ticks = nil     end   end end
Reply
#7
You can only assign one timer per trigger group address with this script. Different timers must have different trigger addresses. One solution is to make a copy of this script.
Reply
#8
Thanks! sometimes a solution is even more simple then expected Smile copy of the script works great!
Reply
#9
(08.12.2022, 13:02)admin Wrote: Resident script with 0 sleep time. Single script can be used for multiple timers by adding more entries to the timers table at the top of the script.
Code:
1234567891011121314151617181920212223242526272829303132333435363738394041
if not client then   timers = {     ['1/1/1'] = {       output = '1/1/2', -- binary output       delayon = 10, -- on delay time (seconds)       delayoff = 0, -- off delay time (seconds)     }   }   grp.sender = 'tm'   client = require('localbus').new(0.1)   client:sethandler('groupwrite', function(event)     local timer = timers[ event.dst ]         if timer and event.sender ~= grp.sender then       local value = tonumber(event.datahex, 16) or 0       local state = value > 0 and 'on' or 'off'             if timer.state ~= state then         timer.state = state         timer.ticks = timer['delay' .. state]       end     end   end) end client:loop(1) for _, timer in pairs(timers) do   if timer.ticks then     timer.ticks = timer.ticks - 1     if timer.ticks == 0 then       grp.checkwrite(timer.output, timer.state == 'on')       timer.state = nil       timer.ticks = nil     end   end end
I use the script above when the input becomes 1 the output becomes 1 10 seconds later. If the input becomes 0 the output stays 1 not going back to 0. What is the problem?
Reply
#10
Previous version did not handle zero timer values. Try this one instead:
Code:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
if not client then   timers = {     ['1/1/1'] = {       output = '1/1/2', -- binary output       delayon = 10, -- on delay time (seconds)       delayoff = 0, -- off delay time (seconds)     }   }   grp.sender = 'tm'   function set(timer)     grp.checkwrite(timer.output, timer.state == 'on')     timer.state = nil     timer.ticks = nil   end   client = require('localbus').new(0.1)   client:sethandler('groupwrite', function(event)     local timer = timers[ event.dst ]          if timer and event.sender ~= grp.sender then       local value = tonumber(event.datahex, 16) or 0       local state = value > 0 and 'on' or 'off'              if timer.state ~= state then         timer.state = state         local ticks = timer['delay' .. state]                  if ticks > 0 then           timer.ticks = ticks         else           set(timer)         end       end     end   end) end client:loop(1) for _, timer in pairs(timers) do   if timer.ticks then     timer.ticks = timer.ticks - 1     if timer.ticks == 0 then       set(timer)     end   end end
Reply
#11
why so complicated? with new Execution mode setting in LM (Last instance only) script can be simplified to Event script for the trigger address with simple logic


Code:
12
os.sleep(event.getvalue() and (6*60) or 30) grp.write(dest_address, event.getvalue())
Reply
#12
Such event script won't work if value is sent periodically faster than os.sleep delay.
Reply
#13
(16.08.2023, 06:19)admin Wrote: Previous version did not handle zero timer values. Try this one instead:
Code:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
if not client then   timers = {     ['1/1/1'] = {       output = '1/1/2', -- binary output       delayon = 10, -- on delay time (seconds)       delayoff = 0, -- off delay time (seconds)     }   }   grp.sender = 'tm'   function set(timer)     grp.checkwrite(timer.output, timer.state == 'on')     timer.state = nil     timer.ticks = nil   end   client = require('localbus').new(0.1)   client:sethandler('groupwrite', function(event)     local timer = timers[ event.dst ]         if timer and event.sender ~= grp.sender then       local value = tonumber(event.datahex, 16) or 0       local state = value > 0 and 'on' or 'off'             if timer.state ~= state then         timer.state = state         local ticks = timer['delay' .. state]                 if ticks > 0 then           timer.ticks = ticks         else           set(timer)         end       end     end   end) end client:loop(1) for _, timer in pairs(timers) do   if timer.ticks then     timer.ticks = timer.ticks - 1     if timer.ticks == 0 then       set(timer)     end   end end

I will try but I tried previous also with 1 second and it didn’t work.
Reply
#14
Thanks for code which works great. 
For security I would like to move the code to a user library to hide most of the code, leaving the timer table in the Common Functions area, to allow users to add new entries when needed.
Could some provide a way to achieve this please
Reply
#15
Create user library named timers:
Code:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546
return function(timers)   if not client then     grp.sender = 'tm'     function set(timer)       grp.checkwrite(timer.output, timer.state == 'on')       timer.state = nil       timer.ticks = nil     end     client = require('localbus').new(0.1)     client:sethandler('groupwrite', function(event)       local timer = timers[ event.dst ]              if timer and event.sender ~= grp.sender then         local value = tonumber(event.datahex, 16) or 0         local state = value > 0 and 'on' or 'off'                  if timer.state ~= state then           timer.state = state           local ticks = timer['delay' .. state]                      if ticks > 0 then             timer.ticks = ticks           else             set(timer)           end         end       end     end)   end   client:loop(1)   for _, timer in pairs(timers) do     if timer.ticks then       timer.ticks = timer.ticks - 1       if timer.ticks == 0 then         set(timer)       end     end   end end

Resident script:
Code:
1234567891011
if not timers then   timers = {     ['1/1/1'] = {       output = '1/1/2', -- binary output       delayon = 10, -- on delay time (seconds)       delayoff = 0, -- off delay time (seconds)     }   } end require('user.timers')(timers)
Reply
#16
Many thanks, but sorry doesn't appear to be working.
Reply
#17
Any errors? past your script.
------------------------------
Ctrl+F5
Reply
#18
(17.11.2023, 13:34)Daniel Wrote: Any errors? past your script.

No, there are no errors.
But if you change timer delays to Zero, either the On or OFF then it works for that element. Instant On and OFF following the lighting group.
But change timer to any over Zero, then stops working.
Reply
#19
The resident script was missing a check if timers variable is already defined. I've modified my original post, see if it works for you.
Reply
#20
That's fixed it, many thanks for the explanation of error.
Reply


Forum Jump: