Logic Machine Forum
Delay script - Printable Version

+- Logic Machine Forum (https://forum.logicmachine.net)
+-- Forum: LogicMachine eco-system (https://forum.logicmachine.net/forumdisplay.php?fid=1)
+--- Forum: Scripting (https://forum.logicmachine.net/forumdisplay.php?fid=8)
+--- Thread: Delay script (/showthread.php?tid=4433)

Pages: 1 2


Delay script - josdegroot - 08.12.2022

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?


RE: Delay script - admin - 08.12.2022

What should happen if another ON arrives during the 6 minute wait time?


RE: Delay script - josdegroot - 08.12.2022

(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.


RE: Delay script - admin - 08.12.2022

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



RE: Delay script - josdegroot - 08.12.2022

it's working!!!

Thank you for the help!!


RE: Delay script - josdegroot - 10.12.2022

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



RE: Delay script - admin - 10.12.2022

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.


RE: Delay script - josdegroot - 11.12.2022

Thanks! sometimes a solution is even more simple then expected Smile copy of the script works great!


RE: Delay script - KoBra - 15.08.2023

(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?


RE: Delay script - admin - 16.08.2023

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



RE: Delay script - myg - 17.08.2023

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())



RE: Delay script - admin - 17.08.2023

Such event script won't work if value is sent periodically faster than os.sleep delay.


RE: Delay script - KoBra - 17.08.2023

(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.


RE: Delay script - sjfp - 15.11.2023

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


RE: Delay script - admin - 15.11.2023

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)



RE: Delay script - sjfp - 15.11.2023

Many thanks, but sorry doesn't appear to be working.


RE: Delay script - Daniel - 17.11.2023

Any errors? past your script.


RE: Delay script - sjfp - 17.11.2023

(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.


RE: Delay script - admin - 22.11.2023

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.


RE: Delay script - sjfp - 22.11.2023

That's fixed it, many thanks for the explanation of error.