Page 1 of 1

Timer check

Posted: Monday 10 June 2019 11:24
by pvklink
Hi,

is there a way to check the timerqueue ?, like for exampe: device.switchOff().afterHour(24)
Timers sometimes dont work, perhaps after update or reboot system? or a mistake
Where are these events stored? Is there a table where i can check this timer?

For the time being:
I try to store the timers manually in a text field so i have my own timer log in dashticz..
Next script seems to work ok when i add 1 thing i dont now how to do...:
a) log execute date/time, see !!!! execute date time in the script for the exact place (this date/time = dz.time.rawTime + Durtimer

Code: Select all

return {
	on = {devices = {'hetregent','voordeurbel','tuindeurbel','voice_vorstalarm','voice_wasmachine','regensensor'}},    

    logging =   { level   = domoticz.LOG_ERROR ,                 
                  marker  = "Voices en bellen"},
	
    execute = function(dz, device, info)
    local switch0 = dz.devices('timerlog')
    local switch1 = dz.devices('hetregent')
    local switch2 = dz.devices('regensensor')
    local Durtimer= 10                                       -- default secondes
    local Durtimer_regen = 30                                -- 24 uren = 86400 seconden

    if device.state == 'On' then                               

        if device.name == 'hetregent' or device.name == 'regensensor' then
            Durtimer = Durtimer_regen
        end
        
        timertekst = dz.time.rawDate .. '  ' .. dz.time.rawTime .. ' : ' .. device.name .. ' wordt na: ' .. tostring(Durtimer) .. ' seconden uitgezet, om: ' .. 'execute date time!!!!!!!' .. '<br>' ..  dz.devices('timerlog').text 
        
        device.switchOff().afterSec(Durtimer)

    elseif device.state == 'Off' then                               

        timertekst = dz.time.rawDate .. '  ' .. dz.time.rawTime .. ' : ' .. device.name .. ' is uitgezet en queue is geleegd' .. '<br>' ..  dz.devices('timerlog').text 
 
        device.cancelQueuedCommands()

    end
 
   switch0.updateText(timertekst)
   dz.log(timertekst, dz.LOG_DEBUG)
 
end
}

Re: Timer check

Posted: Monday 10 June 2019 18:55
by waaren
pvklink wrote: Monday 10 June 2019 11:24 is there a way to check the timerqueue ?, like for exampe: device.switchOff().afterHour(24)
Timers sometimes dont work, perhaps after update or reboot system? or a mistake
Where are these events stored? Is there a table where i can check this timer?
This timer-queue is not stored in a physical file/ database and that is also the reason why no such timers are executed after a restart of domoticz.

You could do something with dzVents global_data to ensure actions are executed even after such a restart or system boot. If you integrate this global_data.lua in your current one.

Code: Select all

return  -- global_data.lua 
{
    data = 
    {
        delayedActions = { initial = {}},
    },

    helpers =   
    {
        managedDelayedActions = function(dz, id, action, delay, silent, dimLevel) -- silent and dimLevel are optional parms
            local now = dz.time.dDate                
            dz.globalData.delayedActions[#dz.globalData.delayedActions + 1] = {["id"]=id,["action"]=action, ["at"]=(now + delay), ["silent"]=silent, dimLevel = dimLevel}    
        end,
    },
}
You can then replace the afterNNN commands and fill the delayedActions table from every dzVents script like below

Code: Select all

return 
{
    on = 
    {
        devices = { 'test*', 'dimmerTest' },
    },

       logging =    
       {   
        level   =   domoticz.LOG_DEBUG,
        marker  =   "delay (user)" 
       },  
                
    execute = function(dz, item)
        if item.name == 'dimmerTest' then
            dz.helpers.managedDelayedActions(dz, item.id, 'dimTo', 1800, false, 40) -- replacement for  dimTo(40).afterSec(1800) 
        elseif item.active then 
            dz.helpers.managedDelayedActions(dz, item.id, 'switchOff', 3600, true)  -- replacement for item.switchOff().afterSec(3600).silent()
        else
            dz.helpers.managedDelayedActions(dz, item.id,' switchOn', 600)  -- replacement for item.switchOn().afterSec(600)
        end
    end
}
To actually execute the timers that are set with this, you need a time based manager script (see below) that will look at the table and act upon.
To optimize the process you could also use the standard afterNNN command besides the dz.helpers.managedDelayedActions() and only execute the manager script on domoticz startup. When you want to use that concept though, you would also need a daily script to do the required housekeeping of the delayedActions table.
For me all of this would be a bit over the top for house automation but YMMV.

Code: Select all

return 
{
    on = 
    {
        timer = { 'every minute' } -- 
    },
    
    logging =    
    {   
        level   =   domoticz.LOG_DEBUG,
        marker  =   "delay (user)" 
    }, 
    
    execute = function(dz)
        
        local function action(id, action, silent, dimLevel )
            if action == 'switchOff' and silent then dz.devices(id).switchOff().silent()
            elseif action == 'switchOff'  then dz.devices(id).switchOff()
            elseif action == 'switchOn' and silent then dz.devices(id).switchOn().silent()
            elseif action == 'switchOn' then dz.devices(id).switchOn()     
            elseif action == 'dimTo' and silent then dz.devices(id).dimTo(dimLevel)          
            elseif action == 'dimTo' then dz.devices(id).dimTo(dimLevel)          
            end
        end
        
        if dz.globalData.delayedActions then 
            tClear = {}
            local now = dz.time.dDate
            for i, delay in ipairs(dz.globalData.delayedActions) do
                actionRequired = delay.at-now < 0
                if actionRequired then
                    dz.log("Device " .. dz.devices(delay.id).name .. " will " .. delay.action .. ' now!',dz.LOG_DEBUG )   
                    action(delay.id, delay.action, delay.silent, delay.dimLevel )
                    tClear[#tClear+1] = i
                else      
                  dz.log("Device " .. dz.devices(delay.id).name .. " will " .. delay.action .. ' in ' .. (delay.at-now) .. ' seconds',dz.LOG_DEBUG )   
                end
            end
            
            for i = #tClear, 1, -1 do
                 dz.log('Record ' .. i .. " will be removed from delayedActions",dz.LOG_DEBUG)
                table.remove(dz.globalData.delayedActions, i )
            end    
       end
   end
}

Re: Timer check

Posted: Tuesday 11 June 2019 20:29
by pvklink
hi @waaren,
I agree with you, replacing the triggersystem is over the top for my domotica (and for me). I only wanted to view the triggers to check if i miss some triggers or that some of them dont fire at all... (perhaps i made some mistakes in scripting)
Replacing them is not n option (maybe during the holiday for playing around).

In the meantime a made a second logging for some triggers like: for xx minutes or after xx time. I write them in a switch as text and publish them on dashticz so i can check if they fire!
Only thing i cant get to work is to make a global service thats calculates the daytime from now + seconds...
For example now+ 86.400 is tomorrow 12-6-2019 20:27. I need this function in more scripts.

If i have this i can easily check when a event has to start and if it has started....
i need this info in the below script (that does work) on place "execute date time!!!!
it has to calulate something like: tonumber(dz.time.rawTime) + tonumber(Durtimer)

Code: Select all

return {
	on = {devices = {'voordeurbel','tuindeurbel','voice_vorstalarm','voice_wasmachine','regensensor','hetregent','clean_timerlog'}},    

    logging =   { level   = domoticz.LOG_ERROR ,                 
                  marker  = "timers"},
	
    execute = function(dz, device, info)
    local switch0 = dz.devices('timerlog')
    local switch1 = dz.devices('hetregent')
    local switch2 = dz.devices('regensensor')
    local Durtimer= 10                                      -- default 10 secondes
    local Durtimer_regen = 86400                            -- default 86400, 1 uur 3600, 12 uren = 43200,24 uren = 86400 seconden.
    local Durtimer_clean = 0                                -- default 2

    if device.state == 'On' then                               

        if device.name == 'hetregent' or device.name == 'regensensor' then
            Durtimer = Durtimer_regen
            -- execute date time nog uitrekenen
            -- x = tonumber(dz.time.rawTime) + tonumber(Durtimer)

            timertekst = dz.time.rawDate .. '  ' .. dz.time.rawTime .. ' : ' .. device.name .. ' is aangezet en wordt na: ' .. tostring(Durtimer) .. ' sec / ' ..  tostring(Durtimer/60) .. ' min / ' .. tostring(Durtimer/3600) .. ' uur uitgezet, om: ' .. 'execute date time!!!!!!!' .. '<br>' ..  dz.devices('timerlog').text 
            device.cancelQueuedCommands()
 
        elseif device.name == 'clean_timerlog' then
            Durtimer = Durtimer_clean
            timertekst = dz.time.rawDate .. '  ' .. dz.time.rawTime .. ' : ' .. device.name .. ' is aangezet en timerlog wordt geschoond...' .. '<br>'
        else
            -- execute date time nog uitrekenen
            -- x = tonumber(dz.time.rawTime) + tonumber(Durtimer)

            timertekst = dz.time.rawDate .. '  ' .. dz.time.rawTime .. ' : ' .. device.name .. ' is aangezet en wordt na: ' .. tostring(Durtimer) .. ' sec / ' ..  tostring(Durtimer/60) .. ' min / ' .. tostring(Durtimer/3600) .. ' uur uitgezet, om: ' .. 'execute date time!!!!!!!' .. '<br>' ..  dz.devices('timerlog').text 

        end
        
        --- deze regels niet weghalen  en niet aan t einde plaatsen, dan mis je een log regel
        switch0.updateText(timertekst)
        dz.log(timertekst, dz.LOG_INFO)
        device.switchOff().afterSec(Durtimer)

    elseif device.state == 'Off' then                               

        if device.name == 'clean_timerlog' then
            timertekst = dz.time.rawDate .. '  ' .. dz.time.rawTime .. ' : ' .. device.name .. ' is uitgezet' .. '<br>' ..  dz.devices('timerlog').text 

        elseif device.name == 'hetregent' or device.name == 'regensensor' then
            timertekst = dz.time.rawDate .. '  ' .. dz.time.rawTime .. ' : ' .. device.name .. ' is uitgezet en queue is geleegd' .. '<br>' ..  dz.devices('timerlog').text 
            device.cancelQueuedCommands()

        else   
            timertekst = dz.time.rawDate .. '  ' .. dz.time.rawTime .. ' : ' .. device.name .. ' is uitgezet' .. '<br>' ..  dz.devices('timerlog').text 

        end

        --- deze regels niet weghalen  en niet aan t einde plaatsen, dan mis je een log regel
        switch0.updateText(timertekst)
        dz.log(timertekst, dz.LOG_INFO)
 
    end

end
}
exe_date.png
exe_date.png (123.42 KiB) Viewed 2730 times

Re: Timer check

Posted: Wednesday 12 June 2019 1:09
by waaren
pvklink wrote: Tuesday 11 June 2019 20:29 For example now+ 86.400 is tomorrow 12-6-2019 20:27. I need this function in more scripts.
The Lua date / time handling is indeed not the easiest part to understand ( even with the simplified API that dzVents brings to the (time) table )

If you implement the script below and look at the produced log it might help you to understand how Lua deals with displaying dates / times (now, past and future)

Code: Select all

return 
{
    on = { timer = { 'every minute' }},
    
    execute = function(dz)
      
        local now = dz.time.dDate -- in seconds since 01-01-1970
       
        dz.log('\ndz.time.raw                                   : ' .. dz.time.raw  .. 
               '\nos.date("%Y-%m-%d %H:%M:%S")                  : ' .. os.date('%Y-%m-%d %H:%M:%S') .. 
               '\nos.date("%Y-%m-%d %H:%M:%S",1)                : ' .. os.date('%Y-%m-%d %H:%M:%S',1) .. 
               '\nos.date("%Y-%m-%d %H:%M:%S", now + 12 * 3600) : ' .. os.date('%Y-%m-%d %H:%M:%S', now + 12 * 3600) .. 
                                      '\n-\n',dz.LOG_FORCE)
        
        local function makeAdjustedDateString(delta, formatString) 
            if not formatString then formatString = '%Y-%m-%d %H:%M:%S' end 
            return ( os.date(formatString, now + delta) ) 
        end
        
        dz.log('One year back with default format: '.. makeAdjustedDateString(-365 * 24 * 3600),dz.LOG_FORCE)
        dz.log('Add a year and use your own format: ' .. makeAdjustedDateString(365 * 24 * 3600,'%Y-%m-%d'),dz.LOG_FORCE)
    end
}

Re: Timer check  [Solved]

Posted: Wednesday 12 June 2019 10:06
by pvklink
@waaren Perfect! with the given examples it was a piece of cake!
Looks great now!

do you also have knowledge of scripting in node-red in combination with mqtt and domoticz?