checkFirst() with uservariable  [Solved]

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

Moderator: leecollings

Post Reply
dpcreel
Posts: 44
Joined: Friday 25 November 2016 14:30
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

checkFirst() with uservariable

Post by dpcreel »

I've been checkFirst() with a uservariable for a long time. Just noticed a lag and traced it back to error on line 45 and 91 of the script below.
(2019-10-28 08:16:00.511 Error: dzVents: Error: (2.4.29) ...icz/scripts/dzVents/generated_scripts/Garage Door V2.lua:91: attempt to call field 'checkFirst' (a nil value)
2019-10-28 08:17:30.026 Error: dzVents: Error: (2.4.29) An error occurred when calling event handler Garage Door V2
2019-10-28 08:17:30.026 Error: dzVents: Error: (2.4.29) ...icz/scripts/dzVents/generated_scripts/Garage Door V2.lua:45: attempt to call field 'checkFirst' (a nil value).

This script has been running for several years without an issue. In one section of the dzvents documentation it says it's OK to use with uservariables (2.3.0), in another it says its only for switch-like-devices (checkFirst(): Function. Checks if the current state of the device is different than the desired new state. If the target state is the same, no command is sent. If you do mySwitch.switchOn().checkFirst(), then no switch command is sent if the switch is already on. This command only works with switch-like devices. It is not available for toggle and dim commands, either.).

What am I missing? Thanks is advance.

The uservariable is an integer, I'm running the latest beta version on a pi3 B+ using a usb drive instead of an SD card (seems more reliable).

Code: Select all

local function getMinutes(dTime)
    local raw = dTime.rawTime
    local a = {}
    local i = 0
    for v in string.gmatch(raw, "%d+") do
        a[i] = tonumber(v)
        i = i + 1
    end
    local min = a[1] + a[0] * 60
    return min
end

local function canLights(dTime)
    local min = getMinutes(dTime)
    return (min >= dTime.sunsetInMinutes - 60 or min <= dTime.sunriseInMinutes + 60)
    --return true       --timing disabled for debugging purposes, when done comment out and uncomment out the above line to enable timing.
end

local function activateGarageLights(data,delay)
    data.devices('Garage Lights').cancelQueuedCommands()
    data.devices('Garage Lights').switchOn().checkFirst().silent()
    data.devices('Garage Lights').switchOff().silent().afterMin(delay)
end

return {
	on = {
		devices = {'Garage Door State','Garage Motion','Lights Group','Garage Lights'},
		timer = {'every minute'}
    },

	execute = function(domoticz,item,triggerInfo)
        local tempDiff = 1.0       --Maximum satisfactory garage temperature differential (F)
        local lightDelay = 5        --Garage Light turn off delay
            
        if item.isDevice then    --Device change scripts go here
            domoticz.log('Script triggered on device change',domoticz.LOG_INFO)
            if item.name == 'Garage Door State' then
                --Turn on/keep on the garage lights if the door is Opening.
                if (item.text == 'Opening' and canLights(domoticz.time)) then
                    activateGarageLights(domoticz,lightDelay)
                    domoticz.log('Garage door opened, switching on the garage lights',domoticz.LOG_INFO)
                --Set close = 0 after the door is closed or someone may have closed the door manually.
                end
                if item.text == 'Closed' then
                  domoticz.variables('autoCloseStatus').set(0).checkFirst().silent()
                   domoticz.devices('Door Auto-Close').switchOff().checkFirst().silent()
                end
            elseif item.name == 'Lights Group' and item.active then
                --Turn on the Lights Group - pressing the number II buton on the garage door remote.     
                if (getMinutes(domoticz.time) >= domoticz.time.sunsetInMinutes - 60 or getMinutes(domoticz.time) <= domoticz.time.sunriseInMinutes + 60) then --allow script to run if it is between a certian time.
                    domoticz.groups('Lights Group Group').switchOn().checkFirst().forMinutes(20) --had added .silent() but there was an issue with another script.
                    domoticz.log('Lights Group Group activated for 20 minutes.',domoticz.LOG_INFO)
                end
            elseif item.name == 'Garage Motion' then
                if item.active then
                    --Abort the auto-close function is there is motion.
                    domoticz.devices('Door Auto-Close').cancelQueuedCommands()
                    domoticz.devices('Door Auto-Close').switchOff().checkFirst().silent()
                    domoticz.variables('autoCloseStatus').set(0).checkFirst().silent()
                    --if motion is detected and is dark emough, turn on/keep on the garage lights for 5 min. 
                    if canLights(domoticz.time) then
                        activateGarageLights(domoticz,lightDelay)
                        domoticz.log('Motion detected, switching on the garage lights',domoticz.LOG_INFO)
                    end
                elseif not item.active then
                    --Turn off lights if no motion detected after a while, after a delay
                    domoticz.devices('Garage Lights').cancelQueuedCommands()
                    domoticz.devices('Garage Lights').switchOff().checkFirst().silent().afterMin(lightDelay)
                    domoticz.log('No motion detected, turning garage lights off after ' .. lightDelay .. ' minutes', domoticz.LOG_INFO)
                end
            elseif item.name == 'Garage Lights' and item.active then
                --set timer if light switch is manually activated
                activateGarageLights(domoticz,lightDelay)
                domoticz.log('Manual activation of garage lights detected, switching off in ' .. lightDelay .. ' minutes if there is no motion',domoticz.LOG_INFO)
                --send an email an set a log event if the garage door auot close function has been on too long
            else
                domoticz.log('<<<<<<<<<<<<<<<<<<<<<<<< No device events triggered! >>>>>>>>>>>>>>>>>>>>>>>>>>>>>',domoticz.LOG_INFO)
            end
    
        elseif item.isTimer then    --Timed scripts go here
            --domoticz.log('Script triggered on timer',domoticz.LOG_INFO)
            --Check if we need to auto-close the garage door, based of house-garage temperature differential
            if (math.abs(domoticz.devices('Garage Temperature').temperature - domoticz.devices('House TempHum').temperature)) > tempDiff
                and (not domoticz.devices('Garage Motion').active) 
                and (not (domoticz.devices('Garage Door State').text == 'Closing' or domoticz.devices('Garage Door State').text == 'Closed'))
                and domoticz.variables('autoCloseStatus').value == 0 then
                    local wait = domoticz.time.isDayTime and 30 or 15 --this is not wrong, it's LUA's ternary operation (A ? B : C) 25 or 10
                    domoticz.devices('Door Auto-Close').cancelQueuedCommands()
                    domoticz.devices('Door Auto-Close').switchOn().checkFirst().silent().afterMin(wait)
                    domoticz.log('Garage door Auto-Close set for ' .. wait .. ' minutes from now',domoticz.LOG_INFO)
                    domoticz.variables('autoCloseStatus').set(1).checkFirst().silent() --this variable is also set in the BT Occupancy event.
            elseif (domoticz.devices('Door Auto-Close').lastUpdate.minutesAgo > 3) and domoticz.devices('Door Auto-Close').active then
                domoticz.log('Auto-Close timed error event',domoticz.LOG_INFO)
                domoticz.log('Garage Door Auto Close Error, Sending Email...',domoticz.LOG_ERROR)  
                domoticz.email('Garage Door Auto Close Error!','Please check the garage door, it has tried to auto close too long unsuccessfully.','[email protected]')
            end       
        end    
    end
}
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: checkFirst() with uservariable

Post by waaren »

dpcreel wrote: Monday 28 October 2019 14:24 I've been checkFirst() with a uservariable for a long time.
I am not aware that checkFirst() was ever available in dzVents for uservariables. Domoticz does not provide the necessary underlying Lua commands. Having said that it quite simple to code a Lua snippet that emulates it.

Code: Select all

 
if myVar.value  ~= newValue then myVar.set(newValue) end
and add .silent() or .afterXXX() methods to the set(newValue) when required. (NOT both as silent() does not work in combination with afterXXX() for uservariables

On a side note; is there a specific reason why you place your functions outside the execute = section ? By doing so you force dzVents to interpret all these functions every minute and on every device change. For performance it is best to place these functions inside the execute = section.
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
dpcreel
Posts: 44
Joined: Friday 25 November 2016 14:30
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: checkFirst() with uservariable

Post by dpcreel »

Waaren,

Check the dzvents documentation, everything is there. Section 2.3.0 it says: "Added more options to the various commands/methods: e.g. myDevice.switchOff().silent(), .forSec(), .forHour(), .afterHour(), .repeatAfterSec(), .repeatAfterMin(), .repeatAfterHour(), .withinHour() and .checkFirst(). This now works not only for devices but also scenes, groups and user variables. See documentation about command options."

I thought that only functions inside the execute= were interpreted based on the on =. I was just wanted to call on them as needed so that's why I did it that way. Please correct me if I'm mistaken. Myself and my son wrote this several years ago so I'm a little foggy on exactly why we did it that way.

I'm a hack at coding, I try my best but usually need help.
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: checkFirst() with uservariable  [Solved]

Post by waaren »

dpcreel wrote: Monday 28 October 2019 20:08 Check the dzvents documentation, everything is there. Section 2.3.0 it says: "Added more options to the various commands/methods: e.g. myDevice.switchOff().silent(), .forSec(), .forHour(), .afterHour(), .repeatAfterSec(), .repeatAfterMin(), .repeatAfterHour(), .withinHour() and .checkFirst(). This now works not only for devices but also scenes, groups and user variables. See documentation about command options."
Sorry if it is not clear for you.
e.g. is a Latin abbreviations. It stands for exempli gratia and means “for example.” In this text it is not meant in a sense that all options worked for all devices , scenes groups and user variables. In the documentation it is explained what works where.
checkFirst() never worked in dzVents for uservariables.

I thought that only functions inside the execute= were interpreted based on the on =. I was just wanted to call on them as needed so that's why I did it that way. Please correct me if I'm mistaken.
That is not how it works. You can try it yourself by add a

Code: Select all

print('hey I am executed (again)....')
before the initial
return {
line in one of your scripts and look what you see in the log
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
dpcreel
Posts: 44
Joined: Friday 25 November 2016 14:30
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: checkFirst() with uservariable

Post by dpcreel »

Thanks for the clarification.

One question - if checkFirst() never work for uservariables then why has this script been running fine with no errors for several years? That's all I wanted to know from the beginning. Sorry for any problems caused, I just wanted an answer to my question. Thanks for your time and expertise.

If anyone else has any thoughts please let me know.
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: checkFirst() with uservariable

Post by waaren »

dpcreel wrote: Thursday 31 October 2019 3:32 One question - if checkFirst() never work for uservariables then why has this script been running fine with no errors for several years? That's all I wanted to know from the beginning.
Sorry. I cannot answer that one conclusive because I do not have a pre dzVents 2.4 installation to test on but I do know that dzVents pré 2.4 used quite different techniques. So it could be that the checkFirst() was simply ignored on the versions where you did not saw this error.
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest