'General purpose' timers

Easy to use, 100% Lua-based event scripting framework.

Moderator: leecollings

Andyf66
Posts: 44
Joined: Wednesday 13 June 2018 12:13
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

'General purpose' timers

Post by Andyf66 »

Is there any way to configure a general purpose timer and have it fire after a certain time period, and execute an arbitrary block of code?

I don't mean timed events, and I don't mean things like device.switchOn().afterSecs(10)

I would like to be able to run arbitrary code, and possibly switch devices/scenes etc, all triggered from a single one shot timer. Something like the capabilities that this has?

http://wiki.garrysmod.com/page/timer/Create

Any thoughts?

Andy.
dannybloe
Posts: 1355
Joined: Friday 29 August 2014 11:26
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Ermelo
Contact:

Re: 'General purpose' timers

Post by dannybloe »

Eh... use the timer trigger?
Creator dzVents - RPi3, loads of zwave devices, esp8266, evohome.
Andyf66
Posts: 44
Joined: Wednesday 13 June 2018 12:13
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: 'General purpose' timers

Post by Andyf66 »

dannybloe wrote: Friday 29 June 2018 11:46 Eh... use the timer trigger?
I'm not sure that fits my needs? Say I have a switch that gets triggered. If I want to execute some arbitrary code 5 minutes after the switch is triggered how would I use that as a timer trigger, which seems to trigger at predefined times?

I guess I could make it repeatedly trigger every minute until the trigger time matches the 'delay' required, but it seems a bit inefficient and back-to-front to do it that way?
dannybloe
Posts: 1355
Joined: Friday 29 August 2014 11:26
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Ermelo
Contact:

Re: 'General purpose' timers

Post by dannybloe »

Just create one dummy switch with it's own event script for these purposes. And set it in whatever script with an .afterXXX().
Creator dzVents - RPi3, loads of zwave devices, esp8266, evohome.
Lebo2d9
Posts: 139
Joined: Tuesday 06 September 2016 20:39
Target OS: Raspberry Pi / ODroid
Domoticz version: L stab
Location: Belgium
Contact:

Re: 'General purpose' timers

Post by Lebo2d9 »

Hi, you can maybe use the lastseen value time of the the switch rhat was triggerd and add your delay time
Domoicz on RPI3 (wifi) directly connected 3x ds18b20 for CV temp, Evohome (9 zone), 1 remote 220V switch based on ESP-12. RFXtrx433E, 16x AMST-606, 5 Somfy RTS motors
Domoticz on RPI3(wifi) as slave for terraruim control
More to come
Andyf66
Posts: 44
Joined: Wednesday 13 June 2018 12:13
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: 'General purpose' timers

Post by Andyf66 »

dannybloe wrote: Friday 29 June 2018 12:07 Just create one dummy switch with it's own event script for these purposes. And set it in whatever script with an .afterXXX().
That would work! As a long time coder it just feels a bit ugly :-(

Thanks anyway!
dannybloe
Posts: 1355
Joined: Friday 29 August 2014 11:26
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Ermelo
Contact:

Re: 'General purpose' timers

Post by dannybloe »

dzVents is a pure slave of Domoticz. If there is no event then nothing happens. So you need something that triggers the event system.
Creator dzVents - RPi3, loads of zwave devices, esp8266, evohome.
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: 'General purpose' timers

Post by waaren »

Andyf66 wrote: Friday 29 June 2018 11:50 Say I have a switch that gets triggered. If I want to execute some arbitrary code 5 minutes after the switch is triggered how would I use that as a timer trigger, which seems to trigger at predefined times?
Would this approach using set a delayed uservar be an option for you ?

Code: Select all

return {
    on  = {     devices   = { "yourSwitch" },
                variables = { "yourSwitchDelay" }},      -- Need to be defined once via setup -> more options -> uservariables (as integer)
    
    logging =   {   level     =   domoticz.LOG_INFO,           -- Change to LOG_DEBUG to check what happens
                    marker    =   "delaySwitch"    },
                
    execute = function(dz, trigger)
        local delay  =  300               -- delay in seconds Adjust to your needs
        local delayVar = dz.variables("yourSwitchDelay")
        
        if trigger.isVariable then 
            delayVar.set(0).silent()
            dz.log("your code here",dz.LOG_INFO)
        else
           delayVar.set(1).afterSec(delay)                   -- Change var after offDelay seconds causing the script 
        end                                                  -- to come back after offDelay seconds 
    end
}
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
Andyf66
Posts: 44
Joined: Wednesday 13 June 2018 12:13
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: 'General purpose' timers

Post by Andyf66 »

Yep, I guess that would probably work too. So many ways to do things!
Andyf66
Posts: 44
Joined: Wednesday 13 June 2018 12:13
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: 'General purpose' timers

Post by Andyf66 »

dannybloe wrote: Friday 29 June 2018 12:58 dzVents is a pure slave of Domoticz. If there is no event then nothing happens. So you need something that triggers the event system.
That makes complete sense as it is event driven and for your Lua/dzvents script to not have its own runloop or to block, it's just the fact that it has to go via a dummy switch that feels a bit of a hack. When I was considering which platform to go for I ran across a few people commenting that if you want to do any kind of complex scripting you end up with a whole pile of dummy switches to maintain state and trigger things. That's starting to hit me now.

Maybe extending the way that an event script could be triggered by adding a 'user generated event'type, that the script itself could generate in the future. Something like

Code: Select all

 
 on = {
    devices = {
      'Stairs Motion'
    },
    userEvents = {
      'My Custom Event Name'
    }
  },

......

domoticz.triggerEvent('My Custom Event Name').afterSeconds(99)
This doesn't really add anything that can't be done already via a the methods mentioned already, it just seems a bit cleaner.
dannybloe
Posts: 1355
Joined: Friday 29 August 2014 11:26
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Ermelo
Contact:

Re: 'General purpose' timers

Post by dannybloe »

Now well, that is certainly an interesting idea! I'll consider it...
Creator dzVents - RPi3, loads of zwave devices, esp8266, evohome.
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: 'General purpose' timers

Post by waaren »

Andyf66 wrote: Friday 29 June 2018 14:21
Maybe extending the way that an event script could be triggered by adding a 'user generated event'type, that the script itself could generate in the future.
Hmm.. A user generated eventtype isn't it already there ?

Code: Select all

return {
    on  = {     devices   = { "yourSwitch" },
                httpResponses   =  { "yourSwitchDelay" }},
                
    logging =   {   level     =   domoticz.LOG_INFO,           -- Change to LOG_DEBUG to check what happens
                    marker    =   "delaySwitch"    },
                
    execute = function(dz, trigger)
        local  delay  =  300              -- delay in seconds Adjust to your needs
        local  jsonString   = dz.settings['Domoticz url'] .. "/json.htm?type=command&param=addlogmessage&message=Waiting%20is%20over"

        if trigger.isHTTPResponse then
            dz.log("your code here",dz.LOG_INFO)
        else
           dz.openURL  ({ url      = jsonString,  
                          method   = "GET", 
                          callback = "yourSwitchDelay" }).afterSec(delay)             -- to come back after delay seconds 
        end                                      
    end
}
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
dannybloe
Posts: 1355
Joined: Friday 29 August 2014 11:26
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Ermelo
Contact:

Re: 'General purpose' timers

Post by dannybloe »

Yes but you are misusing the httpRequest here. But it indeed works.
Creator dzVents - RPi3, loads of zwave devices, esp8266, evohome.
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: 'General purpose' timers

Post by waaren »

dannybloe wrote: Friday 29 June 2018 15:57 Yes but you are misusing the httpRequest here. But it indeed works.
Yes that's me... living on the edge :lol:
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
Andyf66
Posts: 44
Joined: Wednesday 13 June 2018 12:13
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: 'General purpose' timers

Post by Andyf66 »

dannybloe wrote: Friday 29 June 2018 14:23 Now well, that is certainly an interesting idea! I'll consider it...
Cool. I've seen lots of approaches on here to achieve the similar things but they all have 'code smell' in some form... Dummy switches, shared variables, timers that trigger every minute etc. A simple publish/subscribe model with no 3rd party actors is nice and clean.
rogzon
Posts: 11
Joined: Monday 14 November 2016 9:30
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: 'General purpose' timers

Post by rogzon »

It's pretty OK to trigger on a uservariable also....
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: 'General purpose' timers

Post by waaren »

Andyf66 wrote: Friday 29 June 2018 23:51 ...
A simple publish/subscribe model with no 3rd party actors is nice and clean.
...
@Andyf66, can you please explain in layman's terms what you are looking for and give me an idea how this could be implemented in dzVents, -Lua and or domoticz ? I now have the idea that I miss your point and searching for the terms you use only give me results that are a bit to abstract for me.
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
Andyf66
Posts: 44
Joined: Wednesday 13 June 2018 12:13
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: 'General purpose' timers

Post by Andyf66 »

waaren wrote: Saturday 30 June 2018 0:24 @Andyf66, can you please explain in layman's terms what you are looking for and give me an idea how this could be implemented in dzVents, -Lua and or domoticz ? I now have the idea that I miss your point and searching for the terms you use only give me results that are a bit to abstract for me.
Imagine the following scenario. A motion sensor gets tripped. This calls my event driven dzvents script. five minutes after this happens I would like to run some arbitrary code, maybe do come calculations etc. After another 5 minutes I'd like to do some other calculations/switch things on/switch off etc.

Many ways of achieving this have been posted, but none of them really appear to be particularly well engineered solutions.

- Having your script react to a timer that fires *every* minute and then calculates delay based on the lastUpdated function. Inefficient as your script is called even minute, forever. Also involves some potentially complex and fragile maths code to calculate time offsets etc. Also open to unpredictable interference from other scripts if they change the state of the device you are monitoring for lastUpdated (Maybe you want this though?)

- Having a dummy switch or a shared variable - Potentially more efficient (resources wise) but not immediately transparent in terms of operation. You need to know the code and know the switch/variable and then know the script that gets triggered from the switch. A chain of events that's easily forgotten over time. This makes the setup very 'fragile' or 'brittle'. It's very easy to break the chain by accident when making future modifications some point down the line. Basically, your logic flow isn't transparent - you're relying on 'side effects' of an action to trigger something else.

- Using the HTTP method given previously. Not sure where to start on that one!

All of the Above mentioned methods do work, but are not transparently clear in intention. Code you write one day will be edited at some point down the line, and you'll likely have forgotten how it all fits together. Also, all of the methods require an amount of code/logic just to perform the basic action of triggering after a delay. My proposed solution is literally two lines of code - one to say that your code is interested in a 'user' event, and another line of code to actually generate the event. Completely clear intention and no reliance on side effects. As I posted previously, something like the code below is all you would need, and it would replace all the counting logic / dummy switches etc.

Expanding on the example I previously gave in the previous post, and expanding to the two events proposed in the scenario. something like this would cause two 'user' events to trigger my script, one after 5 minutes and one after 10. Completely clear intention, no 3rd party components (dummy switches/user variables needed) No reliance on 'side effects of other actions and completely transparent in function. You can see exactly what it does just by looking at single file.

Code: Select all

on = {
    devices = {
      'Stairs Motion'
    },
    userTriggers = {
      'My 5 minute event',
      'My 10 minute event'
    }
  },

    execute = function(dz, trigger)
        if trigger.isUserTrigger then
            if (trigger.name == 'My 5 minute event')
               -- Execute my 5 minute tasks
            else
               -- Execute my 10 minute tasks
        else
            -- Must be the motion sensor...
            domoticz.userEvent('My 5 minute event').afterMins(5)
            domoticz.userEvent('My 10 minute event').afterMins(10)
        end                                           
    end
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: 'General purpose' timers

Post by waaren »

@Andyf66,
thanks for your comprehensive explanation. I think I understand where you are coming from better now. If I remember correctly, a feature request for a countdown timer was done earlier to @gizmocuz / developers. If implemented that might be a good starting point for designing the userTrigger functionality you described.

Always good to keep learning and improving code. Thanks for that !
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
Andyf66
Posts: 44
Joined: Wednesday 13 June 2018 12:13
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: 'General purpose' timers

Post by Andyf66 »

Indeed, a countdown timer is actually a logical extension of this mechanism. What I’m proposing is really just a ‘one shot’ countdown.
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest