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.

Remaining time or counter
#41
Hello, using this great script I would like to modify it with your help.

So far this script is executed with the detection object. In my case, this object, through another script, is just a 1-second toggle to correct issues that sometimes occur when the detector does not send 'no detection'. The output object is modified with a checkwrite so that it only sends it once.

On the other hand, I have a Lock object and I want to use it to lock the detector and this script.

I would like if it is possible that this Blocking object, apart from blocking the script, could reset the time to zero and not modify the output object..



Code:
-- Set output address
AddressOutput = '39/0/1' -- 01. 1 bit (boolean)

--ID Detector Zone
i = 1

-- Set input address
AddressInput = '9/1/'..i -- 01. 1 bit (boolean)

-- Set external time address (optional)
AddressExternalTime = '38/1/'..i -- 07. 2 byte unsigned integer

-- Set feedback adress of time left indication (optional)
AddressTimeLeft = '38/2/'..i -- 255 byte string

-- Seconds or Minutes
SetSec = '38/3/'..i -- Set to false for Minutes or true for seconds

-- Set blocking address
AddressBlocking = '38/4/'..i -- 01. 1 bit (boolean)

-- Use time left indication
UseTimeLeft = true -- Set to false if no time left indication is used

-- Set time delay (Used when external time is not available)
SetDelay = 120 -- 2 minutes

-- Set factor delay (Multiplies Delay)
SetFac = 1

-- Logic can be turned of by value 0
Off_by_Value_Zero = false




-- ************************************** END PARAMETERS ************************************ --
-- *************************** DON'T CHANGE ANYTHING UNDER THIS LINE ************************ --


Input_Value = event.getvalue()
if Off_by_Value_Zero == false and (Input_Value == false or Input_Value == 0) then
return
else
tpid = storage.get('PID:' .. _SCRIPTNAME)
if tpid == nil then
     pid = os.getpid()
     storage.set('PID:' .. _SCRIPTNAME, pid)
else
   pid = os.getpid()  
   storage.set('PID:' .. _SCRIPTNAME, pid)
   os.kill(tpid, signal.SIGKILL)
end
 
blocking = grp.getvalue(AddressBlocking)
if not blocking then
   return
end

 
function Calculate_Time(StairCaseTime)
   if StairCaseTime > (86400 -1) then
     StairCaseTime = (86400 -1)
   end
   local hours = math.floor(StairCaseTime / 3600 % 24)
   local minutes = math.floor(StairCaseTime / 60 % 60)
   local seconds = math.floor(StairCaseTime % 60)
   time = {
     day = 0,
     hour = hours,
     minute = minutes,
     second = seconds,
   }
   time =string.format('%02d:%02d:%02d',time.hour,time.minute,time.second)
   return time
end
if Input_Value == true or Input_Value == 1 then
   ValueExternalTime = grp.getvalue(AddressExternalTime) or SetDelay
   if grp.getvalue(SetSec) then
    Multiply_Seconds = 1
   else
     Multiply_Seconds = 60
    end
   StairCaseTime = ValueExternalTime * Multiply_Seconds * SetFac
   grp.checkwrite(AddressOutput, true)
   if UseTimeLeft == true then
     if StairCaseTime > 0 then
       time = Calculate_Time(StairCaseTime)
       grp.write(AddressTimeLeft, time)
       repeat
         StairCaseTime = StairCaseTime - 1
         time = Calculate_Time(StairCaseTime)
         grp.write(AddressTimeLeft, time)
         os.sleep(1)
       until StairCaseTime == 0
     end   
   else
     os.sleep(StairCaseTime)
   end
   grp.write(AddressOutput, false)
elseif Input_Value == false or Input_Value == 0 then
   ValueOutput = grp.getvalue(AddressOutput)
   if ValueOutput == false then
     if UseTimeLeft == true then
       time = Calculate_Time(0)
       grp.write(AddressTimeLeft, time)
     end
     grp.write(AddressOutput, false)
   end
end
storage.delete('PID:' .. _SCRIPTNAME)
end
Reply
#42
Well, after a lot of trial/error, I got the result.

I think it can surely be simplified, so any suggestions are welcome.

This is triggered by events assigning the same tag on the input object and the lock object.

Every time the input object is activated (I do it with a 1 second toggle), the parameterized time starts. Activating the lock, locks the function, does not modify the output object, resets the timer, and removes it from storage.


Code:
-- Set output address
AddressOutput = '39/0/1' -- 01. 1 bit (boolean)

--ID Detector Zone
i = 1

-- Set input address
AddressInput = '9/1/'..i -- 01. 1 bit (boolean)

-- Set external time address (optional)
AddressExternalTime = '38/1/'..i -- 07. 2 byte unsigned integer

-- Set feedback adress of time left indication (optional)
AddressTimeLeft = '38/2/'..i -- 255 byte string

-- Seconds or Minutes
SetSec = '38/3/'..i -- Set to false for Minutes or true for seconds

-- Set blocking address
AddressBlocking = '38/4/'..i -- 01. 1 bit (boolean)

-- Use time left indication
UseTimeLeft = true -- Set to false if no time left indication is used

-- Set time delay (Used when external time is not available)
SetDelay = 120 -- 2 minutes

-- Set factor delay (Multiplies Delay)
SetFac = 1

-- Logic can be turned of by value 0
Off_by_Value_Zero = not grp.getvalue(AddressBlocking)




-- ************************************** END PARAMETERS ************************************ --
-- *************************** DON'T CHANGE ANYTHING UNDER THIS LINE ************************ --


Input_Value = grp.getvalue(AddressInput)
if Off_by_Value_Zero == false and (Input_Value == false or Input_Value == 0) then
return
else
tpid = storage.get('PID:' .. _SCRIPTNAME)
if tpid == nil then
     pid = os.getpid()
     storage.set('PID:' .. _SCRIPTNAME, pid)
else
   pid = os.getpid()   
   storage.set('PID:' .. _SCRIPTNAME, pid)
   os.kill(tpid, signal.SIGKILL)
end
 
blocking = grp.getvalue(AddressBlocking)
if not blocking then
    grp.checkwrite(AddressTimeLeft, '00:00:00')
    storage.delete('PID:' .. _SCRIPTNAME)
   return
end

 
function Calculate_Time(StairCaseTime)
   if StairCaseTime > (86400 -1) then
     StairCaseTime = (86400 -1)
   end
   local hours = math.floor(StairCaseTime / 3600 % 24)
   local minutes = math.floor(StairCaseTime / 60 % 60)
   local seconds = math.floor(StairCaseTime % 60)
   time = {
     day = 0,
     hour = hours,
     minute = minutes,
     second = seconds,
   }
   time =string.format('%02d:%02d:%02d',time.hour,time.minute,time.second)
   return time
end
if Input_Value == true or Input_Value == 1 then
   ValueExternalTime = grp.getvalue(AddressExternalTime) or SetDelay
   if grp.getvalue(SetSec) then
    Multiply_Seconds = 1
   else
     Multiply_Seconds = 60
    end
   StairCaseTime = ValueExternalTime * Multiply_Seconds * SetFac
   grp.checkwrite(AddressOutput, true)
   if UseTimeLeft == true then
     if StairCaseTime > 0 then
       time = Calculate_Time(StairCaseTime)
       grp.write(AddressTimeLeft, time)
       repeat
         StairCaseTime = StairCaseTime - 1
         time = Calculate_Time(StairCaseTime)
         grp.write(AddressTimeLeft, time)
         os.sleep(1)
       until StairCaseTime == 0
     end   
   else
     os.sleep(StairCaseTime)
   end
   grp.write(AddressOutput, false)
elseif Input_Value == false or Input_Value == 0 then
   ValueOutput = grp.getvalue(AddressOutput)
   if ValueOutput == false then
     if UseTimeLeft == true then
       time = Calculate_Time(0)
       grp.write(AddressTimeLeft, time)
     end
     grp.write(AddressOutput, false)
   end
end
storage.delete('PID:' .. _SCRIPTNAME)
end
Reply
#43
Hi,
It asked above but i cannot find an answer.
With an additional reset group addres, can we stop the script and make remaning time max . We need to stop process during countdown with an additional group address
Reply
#44
Can you describe your task in more detail? There's a similar script that can be adapted: https://forum.logicmachine.net/showthrea...5#pid26505
Reply
#45
(09.08.2022, 08:20)admin Wrote: Can you describe your task in more detail? There's a similar script that can be adapted: https://forum.logicmachine.net/showthrea...5#pid26505

Hi , I am looking a non residential script solution. I need 200 timer like in 1 LM and it's impossible to do with zero timer residential script. 
I need an update version of Mr. Erwin's script. It's event script. I need another event script which kill immediately main script which has some ossleep timer function.

Regards
Reply
#46
Single resident script that I've posted can handle multiple timers.

Erwin's script saves process ID into storage. You can stop the script like this, change scriptname as needed:
Code:
scriptname = 'my_event_script'

key = 'PID:' .. scriptname
pid = storage.get(key)
if pid then
  os.kill(pid, signal.SIGKILL)
  storage.delete(key)
end
But this approach is not 100% correct though because in some rare cases several event script instances can run in parallel.
Reply
#47
(09.08.2022, 10:09)It worked. Thanks a lotadmin Wrote: Single resident script that I've posted can handle multiple timers.

Erwin's script saves process ID into storage. You can stop the script like this, change scriptname as needed:
Code:
scriptname = 'my_event_script'

key = 'PID:' .. scriptname
pid = storage.get(key)
if pid then
  os.kill(pid, signal.SIGKILL)
  storage.delete(key)
end
But this approach is not 100% correct though because in some rare cases several event script instances can run in parallel.
Reply


Forum Jump: