optimize script  [Solved]

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

Moderator: leecollings

Post Reply
pvklink
Posts: 822
Joined: Wednesday 12 November 2014 15:01
Target OS: Raspberry Pi / ODroid
Domoticz version: latest b
Contact:

optimize script

Post by pvklink »

Hi,

i have i script that manages 5 waterareas.
1. First It calculates when the 5 zone has to start and then
2. activates these areas one by one so the waterpressure is enough.
3. After that it does some reset stuff
4. the script works with timers and also with on and off (on activate alle zones one time) off stops everything, auto uses timed events)
another scripts puts the switches off after x time, this script is very small and already optimized because it is triggered for each individual switch.

The script works great, no problems at all!
I added zone 5 recently and saw that the 5 area's all have for 95% the same code (see section between ---xxx and ---xxx)
i find it scary to change this working script but i know that half of the code is unnecessary...

It is possible to change this with something like:

local function irrigation_zones(actions)

for action in pairs(actions) do
--- the adjusted code
end
end

actions = {Tuinirrigatie_border_links,Tuinirrigatie_border_rechts,Tuinirrigatie_gazon,Tuinirrigatie_planten,Tuinirrigatie_voortuin}
irrigation_zones(actions)

original code

Code: Select all

-- timers mogen niet op t exacte moment draaien, dus 5mn verschil
-- local Tuinirrigatietimer10 = 'at 18:10 on mon,tue,wed,thu,fri,sat,sun'
--
local Tuinirrigatietimer10 = 'every day at sunset'
local Tuinirrigatietimer20 = 'every other day 5 minutes after sunset'
local Tuinirrigatietimer30 = '10 minutes after sunset on mon,thu,sun'
local Tuinirrigatietimer40 = '10 minutes before sunset on sat'
local Tuinirrigatietimer50 = '5 minutes before sunset on 1/*'

return {
    on =    { timer = {Tuinirrigatietimer10,Tuinirrigatietimer20,Tuinirrigatietimer30,Tuinirrigatietimer40,Tuinirrigatietimer50},
              devices = {'Tuinirrigatie'}},

    logging =   { level   = domoticz.LOG_ERROR ,                  
                  marker  = "Timers irrigatie"},
              
    execute = function(dz,item,info)

    local logcode = 3
    local messageTable = {}
    local add = 'add'
    local del = 'del'
    local chg = 'chg'
        
    local function globalMessage(action, message, logcode)
 
        if logcode == nil then logcode = 3 end
 
        if action == add and logcode > 0 then
            messageTable = dz.helpers.addMessage(dz, item, info, message, messageTable, logcode)
        elseif action == del then
            dz.globalData.mylogging = message
            dz.devices('timerlog').updateText(message)
        elseif action == chg then 
            dz.helpers.dumpMessages(dz, messageTable)
        end
 
    end
        
    local iswitch1      = dz.devices('Tuinirrigatie_border_links_timer')
    local iswitch2      = dz.devices('Tuinirrigatie_border_rechts_timer')
    local iswitch3      = dz.devices('Tuinirrigatie_gazon_timer')
    local iswitch4      = dz.devices('Tuinirrigatie_planten_timer')
    local iswitch5      = dz.devices('Tuinirrigatie_voortuin_timer')
    local now           = os.time(os.date('*t'))      
    local devduur1      = tonumber(dz.devices('Tuinirrigatie_border_links_waarde').levelName)
    local devduur2      = tonumber(dz.devices('Tuinirrigatie_border_rechts_waarde').levelName)
    local devduur3      = tonumber(dz.devices('Tuinirrigatie_gazon_waarde').levelName)
    local devduur4      = tonumber(dz.devices('Tuinirrigatie_planten_waarde').levelName)
    local devduur5      = tonumber(dz.devices('Tuinirrigatie_voortuin_waarde').levelName)
    local devpauze      = 1
    local aftertimer1   = 0     -- toegevoegd als t niet werkt verwijderen
    local aftertimer2   = 0
    local aftertimer3   = 0
    local aftertimer4   = 0
    local aftertimer5   = 0

    -- hier de tijden bepalen (wanneer de 4 groepen mogen worden gestart... 
    -- kijkt wel of de duur is gevuld en neemt de tijd anders niet mee
    -- kijkt bij timers of de timer aan staat 
    -- bij manueel of het AAN betreft bij AUTO en OFF spelen deze geen rol, wordt berekend bij timed event of bij aan

    aftertimer1   = 0
    if (devduur1 >0 and ((item.isTimer and iswitch1.level > 0) or (item.isDevice and dz.devices('Tuinirrigatie').state == 'aan'))) then aftertimer1 = devduur1 + devpauze end
    aftertimer2   = aftertimer1
    if (devduur2 >0 and ((item.isTimer and iswitch2.level > 0) or (item.isDevice and dz.devices('Tuinirrigatie').state == 'aan'))) then aftertimer2 = aftertimer1 + devduur2 + devpauze end
    aftertimer3   = aftertimer2
    if (devduur3 >0 and ((item.isTimer and iswitch3.level > 0) or (item.isDevice and dz.devices('Tuinirrigatie').state == 'aan'))) then aftertimer3 = aftertimer2 + devduur3 + devpauze end
    aftertimer4   = aftertimer3
    if (devduur4 >0 and ((item.isTimer and iswitch4.level > 0) or (item.isDevice and dz.devices('Tuinirrigatie').state == 'aan'))) then aftertimer4 = aftertimer3 + devduur4 + devpauze end
    aftertimer5   = aftertimer4
    if (devduur5 >0 and ((item.isTimer and iswitch5.level > 0) or (item.isDevice and dz.devices('Tuinirrigatie').state == 'aan'))) then aftertimer5 = aftertimer4 + devduur5 + devpauze end
    
    
    if (
        (item.isTimer and dz.devices('hetregent').state == 'Off' and dz.devices('Tuinirrigatie').state == 'auto') 
         or (item.isDevice and dz.devices('Tuinirrigatie').state == 'aan')
        ) then      
            -- timed event, het regent niet en irrigatie handeling is auto or     
            -- device handeling en irrigatie handeling is AAN

---    xxx

        if  (item.isTimer  and iswitch1.level == 10 and item.trigger == Tuinirrigatietimer10) or        -- controleer of de irrigatiezone of er aan een van de 4 programma's is voldaan of AAN
            (item.isTimer  and iswitch1.level == 20 and item.trigger == Tuinirrigatietimer20) or 
            (item.isTimer  and iswitch1.level == 30 and item.trigger == Tuinirrigatietimer30) or 
            (item.isTimer  and iswitch1.level == 40 and item.trigger == Tuinirrigatietimer40) or
            (item.isTimer  and iswitch1.level == 50 and item.trigger == Tuinirrigatietimer50) or 
            (item.isDevice and dz.devices('Tuinirrigatie').state == 'aan') then
    
                if devduur1 >0 then 
                    dz.devices('Tuinirrigatie_border_links').switchOn().checkFirst()                            --.forMin(devtimer1) wordt in DZ_irrigatie_source bepaalt
                    globalMessage(add, ' IRRIGATIE AAN: ZONE: Tuinirrigatie_border_links wordt aangezet om: ' .. os.date('%Y-%m-%d %H:%M:%S', now) .. ' voor ' .. devduur1 .. ' minuten...',logcode)

                else
                    globalMessage(add, ' IRRIGATIE UIT: ZONE: Tuinirrigatie_border_links is niet aangezet, de duur stond uit',logcode)
                end
        end
        
        if  (item.isTimer  and iswitch2.level == 10 and item.trigger == Tuinirrigatietimer10) or
            (item.isTimer  and iswitch2.level == 20 and item.trigger == Tuinirrigatietimer20) or 
            (item.isTimer  and iswitch2.level == 30 and item.trigger == Tuinirrigatietimer30) or 
            (item.isTimer  and iswitch2.level == 40 and item.trigger == Tuinirrigatietimer40) or
            (item.isTimer  and iswitch2.level == 50 and item.trigger == Tuinirrigatietimer50) or 
            (item.isDevice and dz.devices('Tuinirrigatie').state == 'aan') then

                if devduur2 > 0 then 
                    dz.devices('Tuinirrigatie_border_rechts').switchOn().checkFirst().afterMin(aftertimer1) 
                    globalMessage(add, ' IRRIGATIE AAN: ZONE: Tuinirrigatie_border_rechts wordt aangezet om: ' .. os.date('%Y-%m-%d %H:%M:%S', now + aftertimer1 * 60) .. ' voor ' .. devduur2 .. ' minuten...',logcode)

                else
                    globalMessage(add, ' IRRIGATIE UIT: ZONE: Tuinirrigatie_border_rechts is niet aangezet, de duur stond uit',logcode)
                end
        end

        if  (item.isTimer  and iswitch3.level == 10 and item.trigger == Tuinirrigatietimer10) or
            (item.isTimer  and iswitch3.level == 20 and item.trigger == Tuinirrigatietimer20) or 
            (item.isTimer  and iswitch3.level == 30 and item.trigger == Tuinirrigatietimer30) or 
            (item.isTimer  and iswitch3.level == 40 and item.trigger == Tuinirrigatietimer40) or
            (item.isTimer  and iswitch3.level == 50 and item.trigger == Tuinirrigatietimer50) or 
            (item.isDevice and dz.devices('Tuinirrigatie').state == 'aan') then

                if devduur3 > 0 then 
                    dz.devices('Tuinirrigatie_gazon').switchOn().checkFirst().afterMin(aftertimer2) 
                    globalMessage(add, ' IRRIGATIE AAN: ZONE: Tuinirrigatie_gazon wordt aangezet om: ' .. os.date('%Y-%m-%d %H:%M:%S', now + aftertimer2 * 60) .. ' voor ' .. devduur3 .. ' minuten...',logcode)

                else 
                    globalMessage(add, ' IRRIGATIE UIT: ZONE: Tuinirrigatie_gazon is niet aangezet, de duur stond uit',logcode)

                end
        end
    
        if  (item.isTimer  and iswitch4.level == 10 and item.trigger == Tuinirrigatietimer10) or
            (item.isTimer  and iswitch4.level == 20 and item.trigger == Tuinirrigatietimer20) or 
            (item.isTimer  and iswitch4.level == 30 and item.trigger == Tuinirrigatietimer30) or 
            (item.isTimer  and iswitch4.level == 40 and item.trigger == Tuinirrigatietimer40) or
            (item.isTimer  and iswitch4.level == 50 and item.trigger == Tuinirrigatietimer50) or 
            (item.isDevice and dz.devices('Tuinirrigatie').state == 'aan') then

                if devduur4 > 0 then 
                    dz.devices('Tuinirrigatie_planten').switchOn().checkFirst().afterMin(aftertimer3) 
                    globalMessage(add, ' IRRIGATIE AAN: ZONE: Tuinirrigatie_planten wordt aangezet om: ' .. os.date('%Y-%m-%d %H:%M:%S', now + aftertimer3 * 60) .. ' voor ' .. devduur4 .. ' minuten...',logcode)

                else 
                    globalMessage(add, ' IRRIGATIE UIT: ZONE: Tuinirrigatie_planten is niet aangezet, de duur stond uit',logcode)

                end
        end

        if  (item.isTimer  and iswitch5.level == 10 and item.trigger == Tuinirrigatietimer10) or
            (item.isTimer  and iswitch5.level == 20 and item.trigger == Tuinirrigatietimer20) or 
            (item.isTimer  and iswitch5.level == 30 and item.trigger == Tuinirrigatietimer30) or 
            (item.isTimer  and iswitch5.level == 40 and item.trigger == Tuinirrigatietimer40) or
            (item.isTimer  and iswitch5.level == 50 and item.trigger == Tuinirrigatietimer50) or 
            (item.isDevice and dz.devices('Tuinirrigatie').state == 'aan') then

                if devduur5 > 0 then 
                    dz.devices('Tuinirrigatie_voortuin').switchOn().checkFirst().afterMin(aftertimer3) 
                    globalMessage(add, ' IRRIGATIE AAN: ZONE: Tuinirrigatie_voortuin wordt aangezet om: ' .. os.date('%Y-%m-%d %H:%M:%S', now + aftertimer4 * 60) .. ' voor ' .. devduur5 .. ' minuten...',logcode)

                else 
                    globalMessage(add, ' IRRIGATIE UIT: ZONE: Tuinirrigatie_voortuin is niet aangezet, de duur stond uit',logcode)

                end
        end

---    xxx


        if (item.isDevice) then        -- als alle zones zijn gesproeid en dit is als het manueel is altijd AAN geweest, dan deze UIT zetten
            dz.devices('Tuinirrigatie').switchSelector(0).afterMin(aftertimer5)     --    dz.devices('Tuinirrigatie').switchSelector(dz.devices('Tuinirrigatie').lastLevel).afterMin(aftertimer5) GEEFT problemen soms autom weer op AAN
            globalMessage(add, ' IRRIGATIE UIT: Tuinirrigatie wordt uitgezet om: ' .. os.date('%Y-%m-%d %H:%M:%S', now + aftertimer5 * 60) .. ' ...',logcode)

        end    

    elseif (item.isTimer and iswitch1.level == 0 and iswitch2.level == 0 and iswitch3.level == 0 and iswitch4.level == 0 and iswitch5.level == 0) then                      -- TIMER 
        globalMessage(add, ' IRRIGATIE UIT: Timerevent gestart maar alle timerzones staat uit',logcode)

    elseif (item.isTimer and dz.devices('Tuinirrigatie').state == 'uit') then
        globalMessage(add, ' IRRIGATIE UIT: Timerevent gestart maar het timerssysteem staat uit',logcode)

    elseif (item.isTimer and dz.devices('Tuinirrigatie').state == 'auto' and dz.devices('hetregent').state == 'On') then
        globalMessage(add, ' IRRIGATIE UIT: Timerevent gestart en is niet aangezet, het is aan t regenen... ',logcode)

    elseif (item.isDevice and dz.devices('Tuinirrigatie').state == 'uit') then                       -- er is gekozen voor OFF op de switch                                                   
        -- device handeling en irrigatie handeling is uit

        dz.devices('Tuinirrigatie_border_links').switchOff()    -- gebruik geen checkfirst want bij voortijdig annuleren kan het zijn dat het device nog niet aanstaat ivm after xxx... dan gebeurt er dus niets ook geen cancelqueue
        dz.devices('Tuinirrigatie_border_rechts').switchOff() 
        dz.devices('Tuinirrigatie_gazon').switchOff()   
        dz.devices('Tuinirrigatie_planten').switchOff() 
        dz.devices('Tuinirrigatie_voortuin').switchOff() 

        globalMessage(add, ' IRRIGATIE UIT: irrigatie timers/queue verwijderd... ',logcode)

    elseif (item.isDevice and dz.devices('Tuinirrigatie').state == 'auto') then                       -- er is gekozen voor AUTO op de switch                                                   
        -- device handeling is AUTO
        globalMessage(add, ' IRRIGATIE AUTO: irrigatie is op automatisch gezet, timers worden actief... ',logcode)

    else
        globalMessage(add, ' IRRIGATIE UIT: is niet aangezet, onbekende reden... ' .. item.name .. '/' .. item.state,logcode)

    end
    
    globalMessage(chg) -- dump

end
}
i also made some pseudo code for the 5 zones
attention the first switch has no .aftermin and and another message...
no idea how i pass code 1-5 for nr

Code: Select all

function(name)

        if  (item.isTimer  and iswitch<nr>.level == 10 and item.trigger == Tuinirrigatietimer10) or        -- controleer of de irrigatiezone of er aan een van de 4 programma's is voldaan of AAN
            (item.isTimer  and iswitch<nr>.level == 20 and item.trigger == Tuinirrigatietimer20) or 
            (item.isTimer  and iswitch<nr>.level == 30 and item.trigger == Tuinirrigatietimer30) or 
            (item.isTimer  and iswitch<nr>.level == 40 and item.trigger == Tuinirrigatietimer40) or
            (item.isTimer  and iswitch<nr>.level == 50 and item.trigger == Tuinirrigatietimer50) or 
            (item.isDevice and dz.devices('Tuinirrigatie').state == 'aan') then
    
                if devduur<nr> >0 then 

                 bij <nr> =1
                    dz.devices('Tuinirrigatie_border_links').switchOn().checkFirst()                            --.forMin(devtimer1) wordt in DZ_irrigatie_source bepaalt
                    globalMessage(add, ' IRRIGATIE AAN: ZONE: Tuinirrigatie_<name> wordt aangezet om: ' .. os.date('%Y-%m-%d %H:%M:%S', now) .. ' voor ' .. devduur<nr> .. ' minuten...',logcode)
                bij nr <>1
                    dz.devices('Tuinirrigatie_<name>').switchOn().checkFirst().afterMin(aftertimer<nr-1>) 
                    globalMessage(add, ' IRRIGATIE AAN: ZONE: Tuinirrigatie_<name> wordt aangezet om: ' .. os.date('%Y-%m-%d %H:%M:%S', now + aftertimer<nr-1> * 60) .. ' voor ' .. devduur<nr> .. ' minuten...',logcode)
 
                else
                    globalMessage(add, ' IRRIGATIE UIT: ZONE: Tuinirrigatie_<name> is niet aangezet, de duur stond uit',logcode)
                end
        end
end
Raspberry (raspbian on rpi 3) , Domoticz Beta, dzVents , RFXtrx433e, P1, Hue, Yeelight, Zwave+, X10, ESP(easy), MQTT,Weather Underground, System Alive Checker, Domoticz Remote Server to RPI with Google Assistant,
Jablotron connection, Ikea
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: optimize script

Post by waaren »

pvklink wrote: Thursday 29 August 2019 22:09 i have i script that manages 5 waterareas; the script works great, no problems at all!
I added zone 5 recently and saw that the 5 area's all have for 95% the same code (see section between ---xxx and ---xxx)
i find it scary to change this working script but i know that half of the code is unnecessary...
None of the code is unnecessary.
It is possible to change this with something like: (or smarter) or with for next ??
Some of the codelines can be placed into a function and then call that function multiple times. This will lead to less code lines but it is not necessarily smarter / better. That will always be a matter of preference but in general you should try and use functions if you have repeated code and you can limit the amount of parms. If you need 4 or more mandatory parms for a function it is likely that it will make your code less readable and therefore difficult to maintain / extend.
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
pvklink
Posts: 822
Joined: Wednesday 12 November 2014 15:01
Target OS: Raspberry Pi / ODroid
Domoticz version: latest b
Contact:

Re: optimize script

Post by pvklink »

i need one parm for the function..
the function can retrieve the rest based on that parm...
Raspberry (raspbian on rpi 3) , Domoticz Beta, dzVents , RFXtrx433e, P1, Hue, Yeelight, Zwave+, X10, ESP(easy), MQTT,Weather Underground, System Alive Checker, Domoticz Remote Server to RPI with Google Assistant,
Jablotron connection, Ikea
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: optimize script

Post by waaren »

pvklink wrote: Friday 30 August 2019 7:39 i need one parm for the function..
the function can retrieve the rest based on that parm...
The way you proposed it in your pseudo code is as far as I understand it, not possible without complex coding in Lua / dzVents. iswitch1.. iswitchxx are device objects. So you will have to pass a device in your function call and not a number or string. Same type of restriction is there for devduur.
As said it is possible to restrict the number of code lines in your script but I doubt if it will make better code.
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
pvklink
Posts: 822
Joined: Wednesday 12 November 2014 15:01
Target OS: Raspberry Pi / ODroid
Domoticz version: latest b
Contact:

Re: optimize script

Post by pvklink »

and something like this isnt possible?
it does not give errors when saving....
putting irrigation zone manual to ON, does executes the first 2 zones after each other !
zone 3 has no irrigation minutes, so isnt executed after that it stops...
i also dont see globalMessage(add .....)
so i am half way!

dont now if i use local declarions right...

Code: Select all

-- timers mogen niet op t exacte moment draaien, dus 5mn verschil
-- local Tuinirrigatietimer10 = 'at 18:10 on mon,tue,wed,thu,fri,sat,sun'
--
local Tuinirrigatietimer10 = 'every day at sunset'
local Tuinirrigatietimer20 = 'every other day 5 minutes after sunset'
local Tuinirrigatietimer30 = '10 minutes after sunset on mon,thu,sun'
local Tuinirrigatietimer40 = '10 minutes before sunset on sat'
local Tuinirrigatietimer50 = '5 minutes before sunset on 1/*'

return {
    on =    { timer = {Tuinirrigatietimer10,Tuinirrigatietimer20,Tuinirrigatietimer30,Tuinirrigatietimer40,Tuinirrigatietimer50},
              devices = {'Tuinirrigatie'}},

    logging =   { level   = domoticz.LOG_ERROR ,                  
                  marker  = "Timers irrigatie"},
              
    execute = function(dz,item,info)

    local logcode = 3
    local messageTable = {}
    local add = 'add'
    local del = 'del'
    local chg = 'chg'
        
    local function globalMessage(action, message, logcode)
 
        if logcode == nil then logcode = 3 end
 
        if action == add and logcode > 0 then
            messageTable = dz.helpers.addMessage(dz, item, info, message, messageTable, logcode)
        elseif action == del then
            dz.globalData.mylogging = message
            dz.devices('timerlog').updateText(message)
        elseif action == chg then 
            dz.helpers.dumpMessages(dz, messageTable)
        end
 
    end


    local now           = os.time(os.date('*t'))      
    aftertimer=0 -- wordt automatisch opgehoogd door de functie

    local function irrigation_zones(dz,item,switchname)
        local devpauze      = 1
        local devduur       = tonumber(dz.devices('Tuinirrigatie_' .. switchname .. '_waarde').levelName)

        if  (
             (item.isTimer  and dz.devices('Tuinirrigatie_' .. switchname .. '_timer').state == item.trigger)
              or  (item.isDevice and dz.devices('Tuinirrigatie').state == 'aan') 
            ) then
                if devduur > 0	then    -- check of sproeiduur groter is dan 0
                    dz.devices('Tuinirrigatie_' .. switchname).switchOn().checkFirst().afterMin(aftertimer)
                    globalMessage(add, ' IRRIGATIE AAN: ZONE: Tuinirrigatie_' .. switchname .. ' wordt aangezet om: ' .. os.date('%Y-%m-%d %H:%M:%S', now + aftertimer * 60) .. ' voor ' .. devduur .. ' minuten...',logcode)
					aftertimer = aftertimer + devduur + devpauze
                else
                    globalMessage(add, ' IRRIGATIE UIT: ZONE: Tuinirrigatie_' .. switchname .. 'is niet aangezet, de duur stond uit',logcode)
                end

        else

            globalMessage(add, ' IRRIGATIE UIT: ZONE: Tuinirrigatie_' .. switchname .. ' is niet aangezet, de timer komt niet overeen',logcode)

        end
    end

    if (item.isDevice and dz.devices('Tuinirrigatie').state == 'uit') then                       -- er is gekozen voor OFF op de switch                                                   
        -- device handeling en irrigatie handeling is uit

        dz.devices('Tuinirrigatie_border_links').switchOff()    -- gebruik geen checkfirst want bij voortijdig annuleren kan het zijn dat het device nog niet aanstaat ivm after xxx... dan gebeurt er dus niets ook geen cancelqueue
        dz.devices('Tuinirrigatie_border_rechts').switchOff() 
        dz.devices('Tuinirrigatie_gazon').switchOff()   
        dz.devices('Tuinirrigatie_planten').switchOff() 
        dz.devices('Tuinirrigatie_voortuin').switchOff() 

        globalMessage(add, ' IRRIGATIE UIT: irrigatie timers/queue verwijderd... ',logcode)

    elseif (item.isDevice and dz.devices('Tuinirrigatie').state == 'auto') then                       -- er is gekozen voor AUTO op de switch                                                   

        globalMessage(add, ' IRRIGATIE AUTO: irrigatie is op automatisch gezet, timers worden actief... ',logcode)

    elseif (item.isTimer and dz.devices('Tuinirrigatie').state == 'auto' and dz.devices('hetregent').state == 'On') then

        globalMessage(add, ' IRRIGATIE UIT: Timerevent gestart en is niet aangezet, het is aan t regenen... ',logcode)

    elseif (item.isTimer and dz.devices('Tuinirrigatie').state == 'uit') then
        globalMessage(add, ' IRRIGATIE UIT: Timerevent gestart maar het timerssysteem staat uit',logcode)
        
    else    
        irrigation_zones(dz,item,'border_links',aftertimer)
        irrigation_zones(dz,item,'border_rechts',aftertimer)
        irrigation_zones(dz,item,'border_gazon',aftertimer)
        irrigation_zones(dz,item,'border_planten',aftertimer)
        irrigation_zones(dz,item,'border_planten',aftertimer)

        if (item.isDevice) then        -- als alle zones zijn gesproeid en dit is als het manueel is altijd AAN geweest, dan deze UIT zetten
 
            dz.devices('Tuinirrigatie').switchSelector(0).afterMin(aftertimer)     
            globalMessage(add, ' IRRIGATIE UIT: Tuinirrigatie wordt uitgezet om: ' .. os.date('%Y-%m-%d %H:%M:%S', now + aftertimer * 60) .. ' ...',logcode)

        end    

    end
    
    globalMessage(chg) -- dump

end
}
Raspberry (raspbian on rpi 3) , Domoticz Beta, dzVents , RFXtrx433e, P1, Hue, Yeelight, Zwave+, X10, ESP(easy), MQTT,Weather Underground, System Alive Checker, Domoticz Remote Server to RPI with Google Assistant,
Jablotron connection, Ikea
pvklink
Posts: 822
Joined: Wednesday 12 November 2014 15:01
Target OS: Raspberry Pi / ODroid
Domoticz version: latest b
Contact:

Re: optimize script

Post by pvklink »

Yess..

I have working:
- manual ON (all 5 groups after each other)
- manual OFF all irrigation stops !

still to test:
- timers
- one zone 0 minutes

bugs: globalmessage does not give messages in this script...

Code: Select all

-- timers mogen niet op t exacte moment draaien, dus 5mn verschil
-- local Tuinirrigatietimer10 = 'at 18:10 on mon,tue,wed,thu,fri,sat,sun'
--
local Tuinirrigatietimer10 = 'every day at sunset'
local Tuinirrigatietimer20 = 'every other day 5 minutes after sunset'
local Tuinirrigatietimer30 = '10 minutes after sunset on mon,thu,sun'
local Tuinirrigatietimer40 = '10 minutes before sunset on sat'
local Tuinirrigatietimer50 = '5 minutes before sunset on 1/*'

return {
    on =    { timer = {Tuinirrigatietimer10,Tuinirrigatietimer20,Tuinirrigatietimer30,Tuinirrigatietimer40,Tuinirrigatietimer50},
              devices = {'Tuinirrigatie'}},

    logging =   { level   = domoticz.LOG_ERROR ,                  
                  marker  = "Timers irrigatie"},
              
    execute = function(dz,item,info)

    local logcode = 3
    local messageTable = {}
    local add = 'add'
    local del = 'del'
    local chg = 'chg'
        
    local function globalMessage(action, message, logcode)
 
        if logcode == nil then logcode = 3 end
 
        if action == add and logcode > 0 then
            messageTable = dz.helpers.addMessage(dz, item, info, message, messageTable, logcode)
        elseif action == del then
            dz.globalData.mylogging = message
            dz.devices('timerlog').updateText(message)
        elseif action == chg then 
            dz.helpers.dumpMessages(dz, messageTable)
        end
 
    end


    local now           = os.time(os.date('*t'))      
    aftertimer=0 -- wordt automatisch opgehoogd door de functie

    local function irrigation_zones(dz,item,switchname)
        local devpauze      = 1
        local devduur       = tonumber(dz.devices('Tuinirrigatie_' .. switchname .. '_waarde').levelName)

        if  (
             (item.isTimer  and dz.devices('Tuinirrigatie_' .. switchname .. '_timer').state == item.trigger)
              or  (item.isDevice and dz.devices('Tuinirrigatie').state == 'aan') 
            ) then
                if devduur > 0	then    -- check of sproeiduur groter is dan 0
                    dz.devices('Tuinirrigatie_' .. switchname).switchOn().checkFirst().afterMin(aftertimer)
                    globalMessage(add, ' IRRIGATIE AAN: ZONE: Tuinirrigatie_' .. switchname .. ' wordt aangezet om: ' .. os.date('%Y-%m-%d %H:%M:%S', now + aftertimer * 60) .. ' voor ' .. devduur .. ' minuten...',logcode)
					aftertimer = aftertimer + devduur + devpauze
                else
                    globalMessage(add, ' IRRIGATIE UIT: ZONE: Tuinirrigatie_' .. switchname .. 'is niet aangezet, de duur stond uit',logcode)
                end

        else

            globalMessage(add, ' IRRIGATIE UIT: ZONE: Tuinirrigatie_' .. switchname .. ' is niet aangezet, de timer komt niet overeen',logcode)

        end
    end

    if (item.isDevice and dz.devices('Tuinirrigatie').state == 'uit') then                       -- er is gekozen voor OFF op de switch                                                   
        -- device handeling en irrigatie handeling is uit

        dz.devices('Tuinirrigatie_border_links').switchOff()    -- gebruik geen checkfirst want bij voortijdig annuleren kan het zijn dat het device nog niet aanstaat ivm after xxx... dan gebeurt er dus niets ook geen cancelqueue
        dz.devices('Tuinirrigatie_border_rechts').switchOff() 
        dz.devices('Tuinirrigatie_gazon').switchOff()   
        dz.devices('Tuinirrigatie_planten').switchOff() 
        dz.devices('Tuinirrigatie_voortuin').switchOff() 

        globalMessage(add, ' IRRIGATIE UIT: irrigatie timers/queue verwijderd... ',logcode)

    elseif (item.isDevice and dz.devices('Tuinirrigatie').state == 'auto') then                       -- er is gekozen voor AUTO op de switch                                                   

        globalMessage(add, ' IRRIGATIE AUTO: irrigatie is op automatisch gezet, timers worden actief... ',logcode)

    elseif (item.isTimer and dz.devices('Tuinirrigatie').state == 'auto' and dz.devices('hetregent').state == 'On') then

        globalMessage(add, ' IRRIGATIE UIT: Timerevent gestart en is niet aangezet, het is aan t regenen... ',logcode)

    elseif (item.isTimer and dz.devices('Tuinirrigatie').state == 'uit') then
        globalMessage(add, ' IRRIGATIE UIT: Timerevent gestart maar het timerssysteem staat uit',logcode)
        
    else    
        irrigation_zones(dz,item,'border_links',aftertimer)
        irrigation_zones(dz,item,'border_rechts',aftertimer)
        irrigation_zones(dz,item,'gazon',aftertimer)
        irrigation_zones(dz,item,'planten',aftertimer)
        irrigation_zones(dz,item,'voortuin',aftertimer)

        if (item.isDevice) then        -- als alle zones zijn gesproeid en dit is als het manueel is altijd AAN geweest, dan deze UIT zetten
 
            dz.devices('Tuinirrigatie').switchSelector(0).afterMin(aftertimer)     
            globalMessage(add, ' IRRIGATIE UIT: Tuinirrigatie wordt uitgezet om: ' .. os.date('%Y-%m-%d %H:%M:%S', now + aftertimer * 60) .. ' ...',logcode)

        end    

    end
    
    globalMessage(chg) -- dump

end
}
Raspberry (raspbian on rpi 3) , Domoticz Beta, dzVents , RFXtrx433e, P1, Hue, Yeelight, Zwave+, X10, ESP(easy), MQTT,Weather Underground, System Alive Checker, Domoticz Remote Server to RPI with Google Assistant,
Jablotron connection, Ikea
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: optimize script

Post by waaren »

pvklink wrote: Friday 30 August 2019 17:16 and something like this isnt possible?
it does not give errors when saving....
Yes, it is possible. You don't have to pass dz and aftertimer to the function because they are already known in an outer scope. Best to change line 42 from

Code: Select all

     aftertimer=0 -- wordt automatisch opgehoogd door de functie
to

Code: Select all

     local aftertimer=0 -- wordt automatisch opgehoogd door de functie
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
pvklink
Posts: 822
Joined: Wednesday 12 November 2014 15:01
Target OS: Raspberry Pi / ODroid
Domoticz version: latest b
Contact:

Re: optimize script

Post by pvklink »

bizar, got globalmessage also working...
i use the complete devicename in the function instead of a concatenate

so irrigation_zones(dz,item,'Tuinirrigatie_border_links',aftertimer)
instead off irrigation_zones(dz,item,'border_links',aftertimer) and concatenate Tuinirrigatie in the function....

still to do:
test timers

Code: Select all

-- timers mogen niet op t exacte moment draaien, dus 5mn verschil
-- local Tuinirrigatietimer10 = 'at 18:10 on mon,tue,wed,thu,fri,sat,sun'
--
local Tuinirrigatietimer10 = 'every day at sunset'
local Tuinirrigatietimer20 = 'every other day 5 minutes after sunset'
local Tuinirrigatietimer30 = '10 minutes after sunset on mon,thu,sun'
local Tuinirrigatietimer40 = '10 minutes before sunset on sat'
local Tuinirrigatietimer50 = '5 minutes before sunset on 1/*'

return {
    on =    { timer = {Tuinirrigatietimer10,Tuinirrigatietimer20,Tuinirrigatietimer30,Tuinirrigatietimer40,Tuinirrigatietimer50},
              devices = {'Tuinirrigatie'}},

    logging =   { level   = domoticz.LOG_ERROR ,                  
                  marker  = "Timers irrigatie"},
              
    execute = function(dz,item,info)

    local logcode = 3
    local messageTable = {}
    local add = 'add'
    local del = 'del'
    local chg = 'chg'
        
    local function globalMessage(action, message, logcode)
 
        if logcode == nil then logcode = 3 end
 
        if action == add and logcode > 0 then
            messageTable = dz.helpers.addMessage(dz, item, info, message, messageTable, logcode)
        elseif action == del then
            dz.globalData.mylogging = message
            dz.devices('timerlog').updateText(message)
        elseif action == chg then 
            dz.helpers.dumpMessages(dz, messageTable)
        end
 
    end


    local now           = os.time(os.date('*t'))      
    aftertimer=0 -- wordt automatisch opgehoogd door de functie

    local function irrigation_zones(dz,item,switchname)
        local devpauze      = 1
        local devduur       = tonumber(dz.devices(switchname .. '_waarde').levelName)

        if  (
             (item.isTimer  and dz.devices(switchname .. '_timer').state == item.trigger)
              or  (item.isDevice and dz.devices('Tuinirrigatie').state == 'aan') 
            ) then
                if devduur > 0	then    -- check of sproeiduur groter is dan 0
                    dz.devices(switchname).switchOn().checkFirst().afterMin(aftertimer)
                    globalMessage(add, ' IRRIGATIE AAN: ZONE: ' .. switchname .. ' wordt aangezet om: ' .. os.date('%Y-%m-%d %H:%M:%S', now + aftertimer * 60) .. ' voor ' .. devduur .. ' minuten...',logcode)
					aftertimer = aftertimer + devduur + devpauze
                else
                    globalMessage(add, ' IRRIGATIE UIT: ZONE: ' .. switchname .. 'is niet aangezet, de duur stond uit',logcode)
                end

        else

            globalMessage(add, ' IRRIGATIE UIT: ZONE: ' .. switchname .. ' is niet aangezet, de timer komt niet overeen',logcode)

        end
    end

    if (item.isDevice and dz.devices('Tuinirrigatie').state == 'uit') then                       -- er is gekozen voor OFF op de switch                                                   
        -- device handeling en irrigatie handeling is uit

        dz.devices('Tuinirrigatie_border_links').switchOff()    -- gebruik geen checkfirst want bij voortijdig annuleren kan het zijn dat het device nog niet aanstaat ivm after xxx... dan gebeurt er dus niets ook geen cancelqueue
        dz.devices('Tuinirrigatie_border_rechts').switchOff() 
        dz.devices('Tuinirrigatie_gazon').switchOff()   
        dz.devices('Tuinirrigatie_planten').switchOff() 
        dz.devices('Tuinirrigatie_voortuin').switchOff() 

        globalMessage(add, ' IRRIGATIE UIT: irrigatie timers/queue verwijderd... ',logcode)

    elseif (item.isDevice and dz.devices('Tuinirrigatie').state == 'auto') then                       -- er is gekozen voor AUTO op de switch                                                   

        globalMessage(add, ' IRRIGATIE AUTO: irrigatie is op automatisch gezet, timers worden actief... ',logcode)

    elseif (item.isTimer and dz.devices('Tuinirrigatie').state == 'auto' and dz.devices('hetregent').state == 'On') then

        globalMessage(add, ' IRRIGATIE UIT: Timerevent gestart en is niet aangezet, het is aan t regenen... ',logcode)

    elseif (item.isTimer and dz.devices('Tuinirrigatie').state == 'uit') then
        globalMessage(add, ' IRRIGATIE UIT: Timerevent gestart maar het timerssysteem staat uit',logcode)
        
    else    
        irrigation_zones(dz,item,'Tuinirrigatie_border_links',aftertimer)
        irrigation_zones(dz,item,'Tuinirrigatie_border_rechts',aftertimer)
        irrigation_zones(dz,item,'Tuinirrigatie_gazon',aftertimer)
        irrigation_zones(dz,item,'Tuinirrigatie_planten',aftertimer)
        irrigation_zones(dz,item,'Tuinirrigatie_voortuin',aftertimer)

        if (item.isDevice) then        -- als alle zones zijn gesproeid en dit is als het manueel is altijd AAN geweest, dan deze UIT zetten
 
            dz.devices('Tuinirrigatie').switchSelector(0).afterMin(aftertimer)     
            globalMessage(add, ' IRRIGATIE UIT: irrigatie wordt uitgezet om: ' .. os.date('%Y-%m-%d %H:%M:%S', now + aftertimer * 60) .. ' ...',logcode)

        end    

    end
    
    globalMessage(chg) -- dump

end
}

Raspberry (raspbian on rpi 3) , Domoticz Beta, dzVents , RFXtrx433e, P1, Hue, Yeelight, Zwave+, X10, ESP(easy), MQTT,Weather Underground, System Alive Checker, Domoticz Remote Server to RPI with Google Assistant,
Jablotron connection, Ikea
pvklink
Posts: 822
Joined: Wednesday 12 November 2014 15:01
Target OS: Raspberry Pi / ODroid
Domoticz version: latest b
Contact:

Re: optimize script

Post by pvklink »

My new irrigation script works!
Naamloos.png
Naamloos.png (107.03 KiB) Viewed 2755 times
Irrigation script with
5 zones, individual on/off, all on/off duration, timed events

For those who want to use it..

Code: Select all

-- timers mogen niet op t exacte moment draaien, dus 5mn verschil
--
--
local timer_on1     = 'every day at sunset'
local timer_on2     = 'every other day 5 minutes after sunset'
local timer_on3     = '10 minutes after sunset on mon,thu,sun'
local timer_on4     = '10 minutes before sunset on sat'
local timer_on5     = '5 minutes before sunset on 1/*'
local timer_test    = 'every day at 00:25'
local timer_off     = 'every day 90 minutes after sunset'      -- deze moet alle timers bij elkaar geteld + pauzes later zijn dan de start van de timer

return {
    on =    { timer = {timer_on1,timer_on2,timer_on3,timer_on4,timer_on5,timer_test,timer_off},
              devices = {'Tuinirrigatie'}},

    logging =   { level   = domoticz.LOG_ERROR ,                  
                  marker  = "Timers irrigatie"},
              
    execute = function(dz,item,info)

    local logcode = 3
    local messageTable = {}
    local add = 'add'
    local del = 'del'
    local chg = 'chg'
        
    local function globalMessage(action, message, logcode)
 
        if logcode == nil then logcode = 3 end
 
        if action == add and logcode > 0 then
            messageTable = dz.helpers.addMessage(dz, item, info, message, messageTable, logcode)
        elseif action == del then
            dz.globalData.mylogging = message
            dz.devices('timerlog').updateText(message)
        elseif action == chg then 
            dz.helpers.dumpMessages(dz, messageTable)
        end
 
    end

    local now           = os.time(os.date('*t'))      
    aftertimer=0 -- wordt automatisch opgehoogd door de functie

    local function irrigation_zones(dz,item,switchname)
        local devpauze      = 1
        local devduur       = tonumber(dz.devices(switchname .. '_waarde').levelName)

        if  (
             (item.isTimer  and dz.devices(switchname .. '_timer').state == item.trigger)
              or  (item.isDevice and dz.devices('Tuinirrigatie').state == 'aan') 
            ) then
                if devduur > 0	then    -- check of sproeiduur groter is dan 0
                    dz.devices(switchname).switchOn().checkFirst().afterMin(aftertimer)
                    globalMessage(add, ' IRRIGATIE AAN: ZONE: ' .. switchname .. ' wordt aangezet om: ' .. os.date('%Y-%m-%d %H:%M:%S', now + aftertimer * 60) .. ' voor ' .. devduur .. ' minuten...',logcode)
					aftertimer = aftertimer + devduur + devpauze
                else
                    globalMessage(add, ' IRRIGATIE UIT: ZONE: ' .. switchname .. 'is niet aangezet, de duur stond uit',logcode)
                end

        else

            globalMessage(add, ' IRRIGATIE UIT: ZONE: ' .. switchname .. ' is niet aangezet, de timer komt niet overeen',logcode)

        end

    end

    if  (
         (item.isDevice and dz.devices('Tuinirrigatie').state == 'uit') 
         or (item.isTimer and item.trigger == timer_off)
        ) then                       -- er is gekozen voor OFF op de switch                                                   
        -- device handeling en irrigatie handeling is uit

        dz.devices('Tuinirrigatie_border_links').switchOff()    -- gebruik geen checkfirst want bij voortijdig annuleren kan het zijn dat het device nog niet aanstaat ivm after xxx... dan gebeurt er dus niets ook geen cancelqueue
        dz.devices('Tuinirrigatie_border_rechts').switchOff() 
        dz.devices('Tuinirrigatie_gazon').switchOff()   
        dz.devices('Tuinirrigatie_planten').switchOff() 
        dz.devices('Tuinirrigatie_voortuin').switchOff() 

        globalMessage(add, ' IRRIGATIE UIT: irrigatie timers/queue verwijderd... ',logcode)

    elseif (item.isDevice and dz.devices('Tuinirrigatie').state == 'auto') then                       -- er is gekozen voor AUTO op de switch                                                   

        globalMessage(add, ' IRRIGATIE AUTO: irrigatie is op automatisch gezet, timers worden actief... ',logcode)

    elseif (item.isTimer and dz.devices('Tuinirrigatie').state == 'auto' and dz.devices('hetregent').state == 'On') then

        globalMessage(add, ' IRRIGATIE UIT: Timerevent gestart en is niet aangezet, het is aan t regenen... ',logcode)

    elseif (item.isTimer and dz.devices('Tuinirrigatie').state == 'uit') then
        globalMessage(add, ' IRRIGATIE UIT: Timerevent gestart maar het timerssysteem staat uit',logcode)
        
    else    
        irrigation_zones(dz,item,'Tuinirrigatie_border_links',aftertimer)
        irrigation_zones(dz,item,'Tuinirrigatie_border_rechts',aftertimer)
        irrigation_zones(dz,item,'Tuinirrigatie_gazon',aftertimer)
        irrigation_zones(dz,item,'Tuinirrigatie_planten',aftertimer)
        irrigation_zones(dz,item,'Tuinirrigatie_voortuin',aftertimer)

        if (item.isDevice) then        -- als alle zones zijn gesproeid en dit is als het manueel is altijd AAN geweest, dan deze UIT zetten
 
            dz.devices('Tuinirrigatie').switchSelector(0).afterMin(aftertimer)     
            globalMessage(add, ' IRRIGATIE UIT: irrigatie wordt uitgezet om: ' .. os.date('%Y-%m-%d %H:%M:%S', now + aftertimer * 60) .. ' ...',logcode)

        end    

    end
    
    globalMessage(chg) -- dump

end
}

Code: Select all

return {
    on = {devices = {'Tuinirrigatie_gazon','Tuinirrigatie_border_links','Tuinirrigatie_planten','Tuinirrigatie_border_rechts','Tuinirrigatie_voortuin'}},

    logging = { 
                    level   = domoticz.LOG_ERROR,
                    marker  = "Tuinirrigatie",
              },

    execute = function(dz, item, info)
    local devtimer  = tonumber(dz.devices(item.name .. '_waarde').levelName)  -- timer ophalen. timer heeft altijd de naam van het device met _waarde erachter

    local logcode = 3
    local messageTable = {}
    local add = 'add'
    local del = 'del'
    local chg = 'chg'
        
    local function globalMessage(action, message, logcode)
 
        if logcode == nil then logcode = 3 end
 
        if action == add and logcode > 0 then
            messageTable = dz.helpers.addMessage(dz, item, info, message, messageTable, logcode)
        elseif action == del then
            dz.globalData.mylogging = message
            dz.devices('timerlog').updateText(message)
        elseif action == chg then 
            dz.helpers.dumpMessages(dz, messageTable)
        end
 
    end
   
    if item.state == 'Off' then         -- off commando's vanuit de queue komen hier niet aan vanwege de bewust silent opdracht bij de ON tak want er moeten meerdere offs gepland worden!... wel handmatige OFF en dat is de bedoeling!
        item.cancelQueuedCommands() 
        dz.devices('usb lamp').switchSelector('Off') -- er op 29-6-19 bijgeplaatst
        globalMessage(add, ' IRRIGATIE UIT: ZONE ' .. item.name .. ' uitgezet en queue geleegd...',logcode) -- 'om: ' .. dz.time.rawTime

    else 
        --item.switchOff().afterMin(devtimer).silent() -- soms komt t signaal niet aan
        item.switchOff().afterMin(devtimer).silent().repeatAfterSec(5, 2) -- uitproberen met 2 extra repeats na 5 sec. silent zorgt ervoor dat er geen andere scripts meer worden uitgevoerd

        dz.helpers.alertLidl(dz, "blauw", devtimer*60)   
        globalMessage(add, ' IRRIGATIE AAN: ZONE ' .. item.name .. ' aangezet voor: ' .. devtimer .. ' minuten...',logcode) 

    end
    globalMessage(chg) -- dump

end
}
Last edited by pvklink on Friday 30 August 2019 20:57, edited 1 time in total.
Raspberry (raspbian on rpi 3) , Domoticz Beta, dzVents , RFXtrx433e, P1, Hue, Yeelight, Zwave+, X10, ESP(easy), MQTT,Weather Underground, System Alive Checker, Domoticz Remote Server to RPI with Google Assistant,
Jablotron connection, Ikea
pvklink
Posts: 822
Joined: Wednesday 12 November 2014 15:01
Target OS: Raspberry Pi / ODroid
Domoticz version: latest b
Contact:

Re: optimize script

Post by pvklink »

three questions to get it perfect!

1. does the variable aftertimer=0 has to be declared with local?
i use it within the script and the inclueded function and it must be raised after each funtion execution and it value has to be used in the calling script..

2. i have
local function globalMessage(action, message, logcode) .... and
a call to this function: irrigation_zones(dz,item,'Tuinirrigatie_border_links',aftertimer)

is aftertimer useless in this call, i did not declared it in the function...

3. what is in my case the way to use aftertimer in the script and function.. pass it through as a variable to the function and get the new value back or a variable that can be changed in the script and function as one....
other words, is global, useful over script, or does a variable has to be not local when you want to use/change its value in a function...

Code: Select all

-- timers mogen niet op t exacte moment draaien, dus 5mn verschil
--
--
local timer_on1     = 'every day at sunset'
local timer_on2     = 'every other day 5 minutes after sunset'
local timer_on3     = '10 minutes after sunset on mon,thu,sun'
local timer_on4     = '10 minutes before sunset on sat'
local timer_on5     = '5 minutes before sunset on 1/*'
local timer_test    = 'every day at 00:25'
local timer_off     = 'every day 90 minutes after sunset'      -- deze moet alle timers bij elkaar geteld + pauzes later zijn dan de start van de timer

return {
    on =    { timer = {timer_on1,timer_on2,timer_on3,timer_on4,timer_on5,timer_test,timer_off},
              devices = {'Tuinirrigatie'}},

    logging =   { level   = domoticz.LOG_ERROR ,                  
                  marker  = "Timers irrigatie"},
              
    execute = function(dz,item,info)

    local logcode = 3
    local messageTable = {}
    local add = 'add'
    local del = 'del'
    local chg = 'chg'
        
    local function globalMessage(action, message, logcode)
 
        if logcode == nil then logcode = 3 end
 
        if action == add and logcode > 0 then
            messageTable = dz.helpers.addMessage(dz, item, info, message, messageTable, logcode)
        elseif action == del then
            dz.globalData.mylogging = message
            dz.devices('timerlog').updateText(message)
        elseif action == chg then 
            dz.helpers.dumpMessages(dz, messageTable)
        end
 
    end

    local now           = os.time(os.date('*t'))      
    aftertimer=0 -- wordt automatisch opgehoogd door de functie

    local function irrigation_zones(dz,item,switchname)
        local devpauze      = 1
        local devduur       = tonumber(dz.devices(switchname .. '_waarde').levelName)

        if  (
             (item.isTimer  and dz.devices(switchname .. '_timer').state == item.trigger)
              or  (item.isDevice and dz.devices('Tuinirrigatie').state == 'aan') 
            ) then
                if devduur > 0	then    -- check of sproeiduur groter is dan 0
                    dz.devices(switchname).switchOn().checkFirst().afterMin(aftertimer)
                    globalMessage(add, ' IRRIGATIE AAN: ZONE: ' .. switchname .. ' wordt aangezet om: ' .. os.date('%Y-%m-%d %H:%M:%S', now + aftertimer * 60) .. ' voor ' .. devduur .. ' minuten...',logcode)
					aftertimer = aftertimer + devduur + devpauze
                else
                    globalMessage(add, ' IRRIGATIE UIT: ZONE: ' .. switchname .. 'is niet aangezet, de duur stond uit',logcode)
                end

        else

            globalMessage(add, ' IRRIGATIE UIT: ZONE: ' .. switchname .. ' is niet aangezet, de timer komt niet overeen',logcode)

        end

    end

    if  (
         (item.isDevice and dz.devices('Tuinirrigatie').state == 'uit') 
         or (item.isTimer and item.trigger == timer_off)
        ) then                       -- er is gekozen voor OFF op de switch                                                   
        -- device handeling en irrigatie handeling is uit

        dz.devices('Tuinirrigatie_border_links').switchOff()    -- gebruik geen checkfirst want bij voortijdig annuleren kan het zijn dat het device nog niet aanstaat ivm after xxx... dan gebeurt er dus niets ook geen cancelqueue
        dz.devices('Tuinirrigatie_border_rechts').switchOff() 
        dz.devices('Tuinirrigatie_gazon').switchOff()   
        dz.devices('Tuinirrigatie_planten').switchOff() 
        dz.devices('Tuinirrigatie_voortuin').switchOff() 

        globalMessage(add, ' IRRIGATIE UIT: irrigatie timers/queue verwijderd... ',logcode)

    elseif (item.isDevice and dz.devices('Tuinirrigatie').state == 'auto') then                       -- er is gekozen voor AUTO op de switch                                                   

        globalMessage(add, ' IRRIGATIE AUTO: irrigatie is op automatisch gezet, timers worden actief... ',logcode)

    elseif (item.isTimer and dz.devices('Tuinirrigatie').state == 'auto' and dz.devices('hetregent').state == 'On') then

        globalMessage(add, ' IRRIGATIE UIT: Timerevent gestart en is niet aangezet, het is aan t regenen... ',logcode)

    elseif (item.isTimer and dz.devices('Tuinirrigatie').state == 'uit') then
        globalMessage(add, ' IRRIGATIE UIT: Timerevent gestart maar het timerssysteem staat uit',logcode)
        
    else    
        irrigation_zones(dz,item,'Tuinirrigatie_border_links',aftertimer)
        irrigation_zones(dz,item,'Tuinirrigatie_border_rechts',aftertimer)
        irrigation_zones(dz,item,'Tuinirrigatie_gazon',aftertimer)
        irrigation_zones(dz,item,'Tuinirrigatie_planten',aftertimer)
        irrigation_zones(dz,item,'Tuinirrigatie_voortuin',aftertimer)

        if (item.isDevice) then        -- als alle zones zijn gesproeid en dit is als het manueel is altijd AAN geweest, dan deze UIT zetten
 
            dz.devices('Tuinirrigatie').switchSelector(0).afterMin(aftertimer)     
            globalMessage(add, ' IRRIGATIE UIT: irrigatie wordt uitgezet om: ' .. os.date('%Y-%m-%d %H:%M:%S', now + aftertimer * 60) .. ' ...',logcode)

        end    

    end
    
    globalMessage(chg) -- dump

end
}
Raspberry (raspbian on rpi 3) , Domoticz Beta, dzVents , RFXtrx433e, P1, Hue, Yeelight, Zwave+, X10, ESP(easy), MQTT,Weather Underground, System Alive Checker, Domoticz Remote Server to RPI with Google Assistant,
Jablotron connection, Ikea
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: optimize script

Post by waaren »

pvklink wrote: Saturday 31 August 2019 9:43 three questions to get it perfect!

1. does the variable aftertimer=0 has to be declared with local?
Yes. if you do not declare it as local it might influence other scripts because Lua as default declare variables as Global ( and best to do this before any function )
2. i have
local function globalMessage(action, message, logcode) .... and
a call to this function: irrigation_zones(dz,item,'Tuinirrigatie_border_links',aftertimer)

is aftertimer useless in this call, i did not declared it in the function...
You do not need to include dz and aftertimer here as parms. It does not break anything but has no added value
3. what is in my case the way to use aftertimer in the script and function.. pass it through as a variable to the function and get the new value back or a variable that can be changed in the script and function as one....
other words, is global, useful over script, or does a variable has to be not local when you want to use/change its value in a function...
In general (true for all programming languages) Try to limit the scope of variables to the where they are needed. So in this case define it as local at the script level. Functions in this script can read and modify it.
Also see this post
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
pvklink
Posts: 822
Joined: Wednesday 12 November 2014 15:01
Target OS: Raspberry Pi / ODroid
Domoticz version: latest b
Contact:

Re: optimize script

Post by pvklink »

Thanks, script looks great...and very easy to maintain!
In the meantime i added two water zones under and above the grounde and one lightning zone in my front yard... This script is already for the frontyard.
Now wait for my watervalve from china...

Thanks again @waaren..
Raspberry (raspbian on rpi 3) , Domoticz Beta, dzVents , RFXtrx433e, P1, Hue, Yeelight, Zwave+, X10, ESP(easy), MQTT,Weather Underground, System Alive Checker, Domoticz Remote Server to RPI with Google Assistant,
Jablotron connection, Ikea
pvklink
Posts: 822
Joined: Wednesday 12 November 2014 15:01
Target OS: Raspberry Pi / ODroid
Domoticz version: latest b
Contact:

Re: optimize script

Post by pvklink »

only thing i dont get is why dz can be removed from the function and item not...
i use both item and dz properties in the fuction --> (item.isDevice and dz.devices('Tuinirrigatie').state == 'aan')

both are declared at the start of the script..
execute = function(dz,item,info)

and the function is now: local function irrigation_zones(item,switchname)

Code: Select all

-- timers mogen niet op t exacte moment draaien, dus 5mn verschil
--
--
local timer_on1     = 'every day at sunset'
local timer_on2     = 'every other day 5 minutes after sunset'
local timer_on3     = '10 minutes after sunset on mon,thu,sun'
local timer_on4     = '10 minutes before sunset on sat'
local timer_on5     = '5 minutes before sunset on 1/*'
local timer_test    = 'every day at 00:25'
local timer_off     = 'every day 90 minutes after sunset'      -- deze moet alle timers bij elkaar geteld + pauzes later zijn dan de start van de timer

return {
    on =    { timer = {timer_on1,timer_on2,timer_on3,timer_on4,timer_on5,timer_test,timer_off},
              devices = {'Tuinirrigatie'}},

    logging =   { level   = domoticz.LOG_ERROR ,                  
                  marker  = "Timers irrigatie"},
              
    execute = function(dz,item,info)

    local now           = os.time(os.date('*t'))      
    local aftertimer    = 0 

    local logcode = 3
    local messageTable = {}
    local add = 'add'
    local del = 'del'
    local chg = 'chg'
        
    local function globalMessage(action, message, logcode)
 
        if logcode == nil then logcode = 3 end
 
        if action == add and logcode > 0 then
            messageTable = dz.helpers.addMessage(dz, item, info, message, messageTable, logcode)
        elseif action == del then
            dz.globalData.mylogging = message
            dz.devices('timerlog').updateText(message)
        elseif action == chg then 
            dz.helpers.dumpMessages(dz, messageTable)
        end
 
    end


    local function irrigation_zones(item,switchname)
        local devpauze      = 1
        local devduur       = tonumber(dz.devices(switchname .. '_waarde').levelName)

        if  (
             (item.isTimer  and dz.devices(switchname .. '_timer').state == item.trigger)
              or  (item.isDevice and dz.devices('Tuinirrigatie').state == 'aan') 
            ) then
                if devduur > 0	then    -- check of sproeiduur groter is dan 0
                    dz.devices(switchname).switchOn().checkFirst().afterMin(aftertimer)
                    globalMessage(add, ' IRRIGATIE AAN: ZONE: ' .. switchname .. ' wordt aangezet om: ' .. os.date('%Y-%m-%d %H:%M:%S', now + aftertimer * 60) .. ' voor ' .. devduur .. ' minuten...',logcode)
					aftertimer = aftertimer + devduur + devpauze
                else
                    globalMessage(add, ' IRRIGATIE UIT: ZONE: ' .. switchname .. 'is niet aangezet, de duur stond uit',logcode)
                end

        else

            globalMessage(add, ' IRRIGATIE UIT: ZONE: ' .. switchname .. ' is niet aangezet, de timer komt niet overeen',logcode)

        end

    end

    if  (
         (item.isDevice and dz.devices('Tuinirrigatie').state == 'uit') 
         or (item.isTimer and item.trigger == timer_off)
        ) then                       -- er is gekozen voor OFF op de switch                                                   
        -- device handeling en irrigatie handeling is uit

        dz.devices('Tuinirrigatie_border_links').switchOff()    -- gebruik geen checkfirst want bij voortijdig annuleren kan het zijn dat het device nog niet aanstaat ivm after xxx... dan gebeurt er dus niets ook geen cancelqueue
        dz.devices('Tuinirrigatie_border_rechts').switchOff() 
        dz.devices('Tuinirrigatie_gazon').switchOff()   
        dz.devices('Tuinirrigatie_planten').switchOff() 
        dz.devices('Tuinirrigatie_voortuin').switchOff() 

        globalMessage(add, ' IRRIGATIE UIT: irrigatie timers/queue verwijderd... ',logcode)

    elseif (item.isDevice and dz.devices('Tuinirrigatie').state == 'auto') then                       -- er is gekozen voor AUTO op de switch                                                   

        globalMessage(add, ' IRRIGATIE AUTO: irrigatie is op automatisch gezet, timers worden actief... ',logcode)

    elseif (item.isTimer and dz.devices('Tuinirrigatie').state == 'auto' and dz.devices('hetregent').state == 'On') then

        globalMessage(add, ' IRRIGATIE UIT: Timerevent gestart en is niet aangezet, het is aan t regenen... ',logcode)

    elseif (item.isTimer and dz.devices('Tuinirrigatie').state == 'uit') then
        globalMessage(add, ' IRRIGATIE UIT: Timerevent gestart maar het timerssysteem staat uit',logcode)
        
    else    
        irrigation_zones(item,'Tuinirrigatie_border_links')
        irrigation_zones(item,'Tuinirrigatie_border_rechts')
        irrigation_zones(item,'Tuinirrigatie_gazon')
        irrigation_zones(item,'Tuinirrigatie_planten')
        irrigation_zones(item,'Tuinirrigatie_voortuin')

        if (item.isDevice) then        -- als alle zones zijn gesproeid en dit is als het manueel is altijd AAN geweest, dan deze UIT zetten
 
            dz.devices('Tuinirrigatie').switchSelector(0).afterMin(aftertimer)     
            globalMessage(add, ' IRRIGATIE UIT: irrigatie wordt uitgezet om: ' .. os.date('%Y-%m-%d %H:%M:%S', now + aftertimer * 60) .. ' ...',logcode)

        end    

    end
    
    globalMessage(chg) -- dump

end
}
Raspberry (raspbian on rpi 3) , Domoticz Beta, dzVents , RFXtrx433e, P1, Hue, Yeelight, Zwave+, X10, ESP(easy), MQTT,Weather Underground, System Alive Checker, Domoticz Remote Server to RPI with Google Assistant,
Jablotron connection, Ikea
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: optimize script  [Solved]

Post by waaren »

pvklink wrote: Saturday 31 August 2019 21:05 only thing i dont get is why dz can be removed from the function and item not...
item is also not needed as function parm.
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
pvklink
Posts: 822
Joined: Wednesday 12 November 2014 15:01
Target OS: Raspberry Pi / ODroid
Domoticz version: latest b
Contact:

Re: optimize script

Post by pvklink »

that makes sence...
thanks again and case closed...
Raspberry (raspbian on rpi 3) , Domoticz Beta, dzVents , RFXtrx433e, P1, Hue, Yeelight, Zwave+, X10, ESP(easy), MQTT,Weather Underground, System Alive Checker, Domoticz Remote Server to RPI with Google Assistant,
Jablotron connection, Ikea
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest