Page 1 of 1

help with script

Posted: Saturday 02 January 2021 19:57
by pvklink
hi @waaren.

You made (a year agoo) two scripts for me.
One to manage a usb lamp, one to save and restore states of devices.
My usb lamp normally gives a flame in the evening. When the doorbell rings it becomes red for 30 seconds.
It sometimes does not return to flame-state.
So i thought to use another script made by you, backup and restore the state of devices.
So i tried the restore the state with below test script, and yes this works!
Problem is that the lamp becomes red for 30 seconds and that i have to restore the lamp after x-second, 30 in this case..
Could you help me to add this option to the restore script?
@update, could you check my trial to fix this, i added a variable(timer) but that gives an error ?

error:
2021-01-02 20:29:44.244 Error: dzVents: Error: (3.0.19) /home/pi/domoticz/scripts/dzVents/scripts/global_data.lua:111: attempt to index a number value (field '?')

my programming trial (relevant part of global_data.lua)

Code: Select all

   state_devices = 
	function(dz,devstate,checkLights,checkDimmable,timer)	-- added the timer PVK
    
        if devstate == 'backup' then
            for index, deviceName in ipairs(checkLights) do
                dz.globalData.states[deviceName] = dz.devices(deviceName).active
            end    
            for index, deviceName in ipairs(checkDimmable) do
                dz.globalData.levels[deviceName] = dz.devices(deviceName).levelVal or dz.devices(deviceName).level
            end    

        elseif devstate == 'restore' then
			if timer == nil then timer = 0 end

            for index, deviceName in ipairs(checkLights) do
                if dz.globalData.states[deviceName] == true then 
                    dz.devices(deviceName).switchOn().afterSec(timer)
                else
                    dz.devices(deviceName).switchOff().afterSec(timer)
                end
            end 
            for index, deviceName in ipairs(checkDimmable) do
                dz.devices(deviceName).dimTo(dz.globalData.levels[deviceName].afterSec(timer))
            end
        elseif devstate == 'clean' then
	    dz.globalData.states = {} 
            dz.globalData.levels = {}
 
        end
    end,
 
testscript

Code: Select all

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

	execute = function(dz, item)

    if item.state == 'On' then  
        dz.helpers.state_devices(dz,'backup',{},{'usb lamp'})
        dz.helpers.alertLidl(dz, "rood", 30)        

    else
        dz.helpers.state_devices(dz,'restore',{},{'usb lamp'})

	end
end
}
original global_data.lua

Code: Select all

return 
{
  data = 
    {
        myGlobalVar = { initial = 12 },
        mylogging = {initial = 'Eerst aanmaak van global variable mylogging in global_data.lua'},
        states = { initial = {}}, 
        levels = { initial = {}},
    },

    helpers = 
    {
        alertLidl = function(dz, action, period)
            local controlVar = dz.variables("controlVar")
            local value = controlVar.value
            if controlVar.value ~= action then
                controlVar.set(action) 
                if period then
                    controlVar.set(value).afterSec(period)
                    dz.log("alert requested; controlVar set to " .. action .. ". It will return to ".. value .. " after " .. period .. " seconds." ,dz.LOG_FORCE)
                else
                    dz.log("alert requested; controlVar set to " .. action  ,dz.LOG_FORCE)
                end
            else
                dz.log("No changed needed; controlVar is already set to " .. value,dz.LOG_DEBUG)
            end
    end,

        globalMessage2 = function(dz,item,info,messageTable,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,
    
   addMessage = 
        function(dz, item, info, message, messages,logcode)
	        	local trigger  
		if item.isDevice then
				trigger = ", Device: " .. item.name
	        elseif item.isTimer then
				trigger = ", Timer: " .. item.trigger
		elseif item.isVariable then
				trigger = ", Variable: " .. item.name
	        	else
				trigger = ", Unknown trigger"
		end
		messages[#messages + 1] = {}
		if logcode ~= 2 then
		            messages[#messages].log  = 'scriptname: ' .. info.scriptName .. trigger .. ' ' .. message
		end
		if logcode ~= 1 then
			messages[#messages].text = dz.time.rawDate .. '  ' .. dz.time.rawTime .. ' : ' .. message
			--messages[#messages].text = dz.time.rawDate .. '  ' .. dz.time.rawTime .. ' : ' .. message .. '<br>'
		end
           	return messages
	end,

   matchesWildCardedString =
	function (dz,stringToMatch, wildCardedString) 
        	local magicalChars  =  '[^%w%s~{\\}:&(/)<>,?@#|_^*$]'  -- Lua 'magical chars' 
	        local regExpression = ('^' .. wildCardedString:gsub("[%^$]",".")) -- make it a valid regexpression 
    
        	if wildCardedString:find('*') and wildCardedString:find('?') then
	            dz.log('Not possible to combine single char wildcard(s) "?" with multi char wildcard(s) "*"',dz.LOG_ERROR)
        	    return false
	        elseif wildCardedString:find('*') then -- a * wild-card was used
        	    wildCardedString = (regExpression:gsub("*", ".*") .. '$'):gsub(magicalChars,'.') -- replace * with .* (Lua for zero or more of any char)
	        elseif wildCardedString:find('?') then -- a ? wild-card was used
        	    wildCardedString = (regExpression:gsub("?", ".") .. '$'):gsub(magicalChars,'.') -- replace ? with . (Lua for single any char)
	        end
		return stringToMatch:match(wildCardedString) == stringToMatch
	end,

   delayedURL = 
	function(dz,callback,delay)   --functie om een andere script aan te roepen
        	local logString = "/json.htm?type=command&param=addlogmessage&message=" .. dz.utils.urlEncode("Hook_alarm")
	        local url= dz.settings['Domoticz url'] .. logString
        	dz.openURL({    url = url,method = "GET",callback = callback }).afterSec(delay)                      
	end,

    state_devices = 
	function(dz,devstate,checkLights,checkDimmable)
    
        if devstate == 'backup' then
            for index, deviceName in ipairs(checkLights) do
                dz.globalData.states[deviceName] = dz.devices(deviceName).active
            end    
            for index, deviceName in ipairs(checkDimmable) do
                dz.globalData.levels[deviceName] = dz.devices(deviceName).levelVal or dz.devices(deviceName).level
            end    

        elseif devstate == 'restore' then
            for index, deviceName in ipairs(checkLights) do
                if dz.globalData.states[deviceName] == true then 
                    dz.devices(deviceName).switchOn()
                else
                    dz.devices(deviceName).switchOff()
                end
            end 
            for index, deviceName in ipairs(checkDimmable) do
                dz.devices(deviceName).dimTo(dz.globalData.levels[deviceName])
            end
        elseif devstate == 'clean' then
	    dz.globalData.states = {} 
            dz.globalData.levels = {}
 
        end
    end,
      
    dumpMessages = 
        function(dz, messages)
            local textDevice = dz.devices('timerlog')
	    local currentText = dz.globalData.mylogging
            local newText = currentText
	    local lf = '<br>'					--local lf = "\n" 	--local lf = "\r\n"	--PVK \n of \r\n UITGEZET ANDERS werkt dashticz niet
            local maxLines = 8
            
            for i, record in ipairs(messages) do
                if record.log then dz.log(record.log, dz.LOG_INFO) end 
                if record.text then newText = record.text .. lf .. newText end
            end
            
            dz.log(newText, dz.LOG_INFO)
            
            if newText ~= currentText then
                --lines = dz.utils.stringSplit(newText, lf)  -- create lines table from newText string						--PVK UITGEZET ANDERS werkt dashticz niet
                --newText = table.concat(lines, lf, 1, (math.min(maxLines,#lines))) -- recreate newText string from first maxLines 		--PVK UITGEZET ANDERS werkt dashticz niet
                textDevice.updateText(newText) 
		dz.globalData.mylogging = newText  -- ADDED

            end    
        end,       
    }
}

Re: help with script

Posted: Saturday 02 January 2021 20:58
by pvklink
Think i solved it myself...

old
dz.devices(deviceName).dimTo(dz.globalData.levels[deviceName].afterSec(timer))
new
dz.devices(deviceName).dimTo(dz.globalData.levels[deviceName]).afterSec(timer)

Re: help with script

Posted: Saturday 02 January 2021 23:01
by waaren
pvklink wrote: Saturday 02 January 2021 20:58 Think i solved it myself...

old
dz.devices(deviceName).dimTo(dz.globalData.levels[deviceName].afterSec(timer))
new
dz.devices(deviceName).dimTo(dz.globalData.levels[deviceName]).afterSec(timer)
Top!

[Tip]
the dzVents errormessage contains a line number so it make sense to share the original file with unchanged line numbers (So no extra lines and no deleted lines) if you are looking for help.

Re: help with script

Posted: Sunday 03 January 2021 10:09
by pvklink
Yes, sorry, too enthousiastic...