Posts: 13 
	Threads: 3 
	Joined: Oct 2019
	
 Reputation: 
 0
	 
 
	
	
		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   .
 
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?
	  
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 8422 
	Threads: 45 
	Joined: Jun 2015
	
 Reputation: 
 481
	 
 
	
	
		What should happen if another ON arrives during the 6 minute wait time?
	 
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 13 
	Threads: 3 
	Joined: Oct 2019
	
 Reputation: 
 0
	 
 
	
		
		
		08.12.2022, 11:29 
(This post was last modified: 08.12.2022, 11:32 by josdegroot.)
		
	 
	
		 (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.
	  
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 8422 
	Threads: 45 
	Joined: Jun 2015
	
 Reputation: 
 481
	 
 
	
	
		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: 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
  
	 
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 13 
	Threads: 3 
	Joined: Oct 2019
	
 Reputation: 
 0
	 
 
	
		
		
		08.12.2022, 15:49 
(This post was last modified: 08.12.2022, 18:55 by josdegroot.)
		
	 
	
		it's working!!! 
 
Thank you for the help!!
	 
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 13 
	Threads: 3 
	Joined: Oct 2019
	
 Reputation: 
 0
	 
 
	
		
		
		10.12.2022, 07:56 
(This post was last modified: 10.12.2022, 10:37 by josdegroot.)
		
	 
	
		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: 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
  
	 
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 8422 
	Threads: 45 
	Joined: Jun 2015
	
 Reputation: 
 481
	 
 
	
	
		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.
	 
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 13 
	Threads: 3 
	Joined: Oct 2019
	
 Reputation: 
 0
	 
 
	
	
		Thanks! sometimes a solution is even more simple then expected    copy of the script works great!
	  
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 123 
	Threads: 23 
	Joined: Apr 2018
	
 Reputation: 
 2
	 
 
	
	
		 (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: 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?
	  
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 8422 
	Threads: 45 
	Joined: Jun 2015
	
 Reputation: 
 481
	 
 
	
	
		Previous version did not handle zero timer values. Try this one instead: 
Code: 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
  
	 
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 48 
	Threads: 5 
	Joined: Jan 2020
	
 Reputation: 
 4
	 
 
	
	
		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: os.sleep(event.getvalue() and (6*60) or 30) 
grp.write(dest_address, event.getvalue())
  
	 
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 8422 
	Threads: 45 
	Joined: Jun 2015
	
 Reputation: 
 481
	 
 
	
	
		Such event script won't work if value is sent periodically faster than os.sleep delay.
	 
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 123 
	Threads: 23 
	Joined: Apr 2018
	
 Reputation: 
 2
	 
 
	
	
		 (16.08.2023, 06:19)admin Wrote:  Previous version did not handle zero timer values. Try this one instead: 
Code: 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.
	  
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 109 
	Threads: 41 
	Joined: Apr 2018
	
 Reputation: 
 0
	 
 
	
	
		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
	 
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 8422 
	Threads: 45 
	Joined: Jun 2015
	
 Reputation: 
 481
	 
 
	
	
		Create user library named  timers:
 Code: 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: 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)
  
	 
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 109 
	Threads: 41 
	Joined: Apr 2018
	
 Reputation: 
 0
	 
 
	
		
		
		15.11.2023, 14:35 
(This post was last modified: 15.11.2023, 15:45 by sjfp.)
		
	 
	
		Many thanks, but sorry doesn't appear to be working.
	 
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 5287 
	Threads: 29 
	Joined: Aug 2017
	
 Reputation: 
 237
	 
 
	
	
		Any errors? past your script.
	 
	
	
------------------------------ 
Ctrl+F5
 
	
		
	 
 
 
	
	
	
		
	Posts: 109 
	Threads: 41 
	Joined: Apr 2018
	
 Reputation: 
 0
	 
 
	
	
		 (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.
	  
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 8422 
	Threads: 45 
	Joined: Jun 2015
	
 Reputation: 
 481
	 
 
	
	
		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.
	 
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 109 
	Threads: 41 
	Joined: Apr 2018
	
 Reputation: 
 0
	 
 
	
	
		That's fixed it, many thanks for the explanation of error.
	 
	
	
	
		
	 
 
 
	 
 |