failed attempt to call a nil value

I have made a Lua script that monitor with PingSensor if my or my wife is present. If not, it will close all the lights, music, close the blinds and lock the door.

My issue is that one in a while, I get a error on the script and Lua hangs.

I tried all kind of codes to fix that issue but since I didn’t pin point when it happends, I’m screwed.

Any thoughts?

LuaUpnp Log.
08 06/12/16 15:26:29.100 Scene::RunScene running 91 Presence <0x2bd26680>
01 06/12/16 15:26:29.101 LuaInterface::CallFunction_Scene Scene 91 failed attempt to call a nil value <0x2bd26680>

Scene Lua:
function nopresence(log)
if log == “1” then

    	local filewrite = io.open("/mnt/usb/lognopresence.txt", "a")   
     	filewrite:write(os.date().. " ")
            filewrite:flush()
           	filewrite:close()
end  	       
--[[ If No one if home, flip the VShitch.  --]]
local VSSebHome = assert(tostring(luup.variable_get("urn:upnp-org:serviceId:VSwitch1","Status", 847)),"1")
if log == "1" then
    	local filewrite = io.open("/mnt/usb/lognopresence.txt", "a")   
     	filewrite:write(" VSSebHome:"..VSSebHome)
            filewrite:flush()
            filewrite:close()
end

local VSTashaHome = assert(tostring(luup.variable_get("urn:upnp-org:serviceId:VSwitch1","Status", 848)),"1")
if log == "1" then
    	local filewrite = io.open("/mnt/usb/lognopresence.txt", "a")   
     	filewrite:write(" VSTashaHome:"..VSTashaHome)
            filewrite:flush()
            filewrite:close()
end

local PingSebHome = assert(tostring(luup.variable_get("urn:micasaverde-com:serviceId:SecuritySensor1","Tripped", 843)),"1")
if log == "1" then
    	local filewrite = io.open("/mnt/usb/lognopresence.txt", "a")   
     	filewrite:write(" PingSebHome:"..PingSebHome)
            filewrite:flush()
            filewrite:close()
end	

local PingTashaHome = assert(tostring(luup.variable_get("urn:micasaverde-com:serviceId:SecuritySensor1","Tripped", 846)),"1")
if log == "1" then
    	local filewrite = io.open("/mnt/usb/lognopresence.txt", "a")   
     	filewrite:write(" PingTashaHome:"..PingTashaHome)
            filewrite:flush()
            filewrite:close()
end

local PingNotSebHome = assert(tostring(luup.variable_get("urn:micasaverde-com:serviceId:SecuritySensor1","Tripped",849)),"1")
if log == "1" then
    	local filewrite = io.open("/mnt/usb/lognopresence.txt", "a")   
     	filewrite:write(" PingNotSebHome:"..PingNotSebHome)
            filewrite:flush()
            filewrite:close()
end	

local PingNotTashaHome = assert(tostring(luup.variable_get("urn:micasaverde-com:serviceId:SecuritySensor1","Tripped",850)),"1")
if log == "1" then
    	local filewrite = io.open("/mnt/usb/lognopresence.txt", "a")   
     	filewrite:write(" PingNotTashaHome:"..PingNotTashaHome)
            filewrite:flush()
            filewrite:close()
end	

	local res,mode = luup.inet.wget("http://192.168.1.146:3480/data_request?id=variableget&Variable=Mode",5)
if log == "1" then
    	local filewrite = io.open("/mnt/usb/lognopresence.txt", "a")   
     	filewrite:write(" Mode:"..mode)
            filewrite:flush()
            filewrite:close()
end

mode = assert(tostring(mode),"1")
--[[ If seb not home and reverse tripped, change status VS to 0 --]]
if (PingSebHome == "0" and PingNotSebHome == "1") then
	if log == "1" then
    		local filewrite = io.open("/mnt/usb/lognopresence.txt", "a")   
     		filewrite:write(" Seb not home ")
            	filewrite:flush()
           		filewrite:close()
	end
	luup.call_action("urn:upnp-org:serviceId:VSwitch1", "SetTarget", {newTargetValue = "0"}, 847)
    end 
    
   if (PingSebHome == "1" and PingNotSebHome == "0") then
		if log == "1" then
    			local filewrite = io.open("/mnt/usb/lognopresence.txt", "a")   
     			filewrite:write(" Seb is home ")
            		filewrite:flush()
           			filewrite:close()
		end
		luup.call_action("urn:upnp-org:serviceId:VSwitch1", "SetTarget", {newTargetValue = "1"}, 847)
   end

    --[[ If Tasha not home and reverse tripped, change status VS to 0 --]]
    if (PingTashaHome == "0" and PingNotTashaHome == "1") then
	if log == "1" then
    			local filewrite = io.open("/mnt/usb/lognopresence.txt", "a")   
     			filewrite:write(" Tasha not home ")
            		filewrite:flush()
           			filewrite:close()
	end    
	luup.call_action("urn:upnp-org:serviceId:VSwitch1", "SetTarget", {newTargetValue = "0"}, 848)
    end 

   if (PingTashaHome == "1" and PingNotTashaHome == "0") then
	luup.call_action("urn:upnp-org:serviceId:VSwitch1", "SetTarget", {newTargetValue = "1"}, 848)
	if log == "1" then
    			local filewrite = io.open("/mnt/usb/lognopresence.txt", "a")   
     			filewrite:write(" Tasha is home ")
            		filewrite:flush()
           			filewrite:close()
	end
   end 

	if log == "1" then
    			local filewrite = io.open("/mnt/usb/lognopresence.txt", "a")   
     			filewrite:write(" check 1 ")
            		filewrite:flush()
           			filewrite:close()
	end
    if (VSSebHome == "0" and PingNotSebHome == "1") then
       	if (VSTashaHome == "0" and PingNotTashaHome== "1") then
		if log == "1" then
    			local filewrite = io.open("/mnt/usb/lognopresence.txt", "a")   
     			filewrite:write(" Nobody home ")
            		filewrite:flush()
           			filewrite:close()
		end  	
		luup.call_action("urn:upnp-org:serviceId:VSwitch1", "SetTarget", {newTargetValue = "0"}, 845)
    	end 
    end

if log == “1” then
local filewrite = io.open(“/mnt/usb/lognopresence.txt”, “a”)
filewrite:write(" check 2 ")
filewrite:flush()
filewrite:close()
end

if log == "1" then
    	local filewrite = io.open("/mnt/usb/lognopresence.txt", "a")   
     	filewrite:write(" ", "\n")
            filewrite:flush()
           	filewrite:close()
end 	    

end

nopresence(“1”)

I glazed over this pretty quickly and might have missed a mis-spelled function name in an infrequently-taken branch of your code, which in my experience is the most common way of getting that error, but I didn’t see any issues.

My guess is that you’re getting a file open failure on the log at some point. I would (1) reduce all of your repeated log writing code (open, write, flush, close) to a single function to tighten up the code, and then (2) within that function make sure you’re getting a non-nil value back from io.open() before attempting to write to it. If the call fails, it returns two values (nil and an error message), so make sure your new logging function gets both, and if you get a nil filehandle, log the error and your log message using luup.log() as a fallback.

function printLog(myMsg)
    local filehandle, err
    filehandle, err  = io.open("/mnt/usb/lognopresence.txt", "a")
    if (filehandle == nil) then
        luup.log("Failed to open /mnt/usb/lognopresence.txt: " .. err)
        luup.log(myMsg)
    else
        filehandle:write(os.date .. ": " .. myMsg)
        filehandle:flush()
        filehandle:close()
    end
end

Thanks for you help,

I added the flat file to see where exactly it crashed. In fact, it was crashing before I added the log part.

What I realized is that it always run the scene completelly and never crash within. I see in the log, launch scene “presence” I look at my log, see that in deed it was completelly and sometime, I get the ERROR in Scene (Nil)…

Hmmm… also don’t forget that your scene Lua should always end with a “return true”, unless you specifically want the scene execution to fail.

To help find the issue you can also use the pcall function to “trap” any errors and provide a “default” action and log message(s).

JohnRob

Didn’t know about the pcall.

Thanks, I will try that one out.

Hmmm... also don't forget that your scene Lua should always end with a "return true", unless you specifically want the scene execution to fail.

That’s not true!
If you do not provide a return value it will act like a return TRUE. The ONLY way to terminate execution of the scene is to “return false”. ALL other returns, or the absence of a return are considered a success.

But it is good form to always explicitly provide a return value that indicates your intentions … and not depend on the obscure rules.

Still have the same issue with “pcall”

So what I did is when I call my presence function, I call it like that:

local err = pcall(“presence”)

But still, I got an error this morning. Nill…

I was looking at my available resource, when I send a TOP command, i realized that my physical memory is at 157%. I’m trying to find a solution but could it be related?

9388 3079 root S 98516 157% 18% /usr/bin/LuaUPnP

You would replace:

nopresence("1")

with:

local status = pcall(nopresence, "1")
if (not status) then
  luup.log("XYZZY:Error calling:nopresense")
end

Of course you can put calls to luup.log inside your nopresense function to trace it’s progress.
I usually put some unique string (XYZZY) in the string to make it easier to find in Vera’s log file.

I would just use the luup.log and eliminate all the calls to filewrite … you may have problems keeping the USB drive mounted.
Then you find the results in Vera’s log file.

Thanks for your help guys,

BUT! still get the same error after all the changes…

Here’s my latest updates.

FYI, I run this script every 10 seconds with my vera lite

08 06/14/16 19:23:44.100 Scene::RunScene running 91 Presence <0x2babc680>
01 06/14/16 19:23:44.101 LuaInterface::CallFunction_Scene Scene 91 failed attempt to call a nil value <0x2babc680>

function nopresence(log)
if log == “1” then
luup.log("PRESENCE: “…os.date()… " “)
end
–[[ If No one if home, flip the VShitch. --]]
local VSSebHome = assert(tostring(luup.variable_get(“urn:upnp-org:serviceId:VSwitch1”,“Status”, 847)),“1”)
if log == “1” then
luup.log(” VSSebHome:”…VSSebHome)
end

local VSTashaHome = assert(tostring(luup.variable_get("urn:upnp-org:serviceId:VSwitch1","Status", 848)),"1")
if log == "1" then
	luup.log(" VSTashaHome:"..VSTashaHome)
end

local PingSebHome = assert(tostring(luup.variable_get("urn:micasaverde-com:serviceId:SecuritySensor1","Tripped", 843)),"1")
if log == "1" then
    	luup.log(" PingSebHome:"..PingSebHome)
end	

local PingTashaHome = assert(tostring(luup.variable_get("urn:micasaverde-com:serviceId:SecuritySensor1","Tripped", 846)),"1")
if log == "1" then
    	luup.log(" PingTashaHome:"..PingTashaHome)
end

local PingNotSebHome = assert(tostring(luup.variable_get("urn:micasaverde-com:serviceId:SecuritySensor1","Tripped",849)),"1")
if log == "1" then
        luup.log(" PingNotSebHome:"..PingNotSebHome)
end	

local PingNotTashaHome = assert(tostring(luup.variable_get("urn:micasaverde-com:serviceId:SecuritySensor1","Tripped",850)),"1")
if log == "1" then
	luup.log(" PingNotTashaHome:"..PingNotTashaHome)
end	

	local res,mode = luup.inet.wget("http://192.168.1.146:3480/data_request?id=variableget&Variable=Mode",5)
if log == "1" then
	luup.log(" Mode:"..mode)        	
end

mode = assert(tostring(mode),"1")
--[[ If seb not home and reverse tripped, change status VS to 0 --]]
if (PingSebHome == "0" and PingNotSebHome == "1") then
	if log == "1" then
		luup.log(" Seb not home ")        		
	end
	luup.call_action("urn:upnp-org:serviceId:VSwitch1", "SetTarget", {newTargetValue = "0"}, 847)
    end 
    
   if (PingSebHome == "1" and PingNotSebHome == "0") then
		if log == "1" then
			luup.log(" Seb is home ")     
		end
		luup.call_action("urn:upnp-org:serviceId:VSwitch1", "SetTarget", {newTargetValue = "1"}, 847)
   end

    --[[ If Tasha not home and reverse tripped, change status VS to 0 --]]
    if (PingTashaHome == "0" and PingNotTashaHome == "1") then
	if log == "1" then
		luup.log(" Tasha not home ")  
	end    
	luup.call_action("urn:upnp-org:serviceId:VSwitch1", "SetTarget", {newTargetValue = "0"}, 848)
    end 

   if (PingTashaHome == "1" and PingNotTashaHome == "0") then
	luup.call_action("urn:upnp-org:serviceId:VSwitch1", "SetTarget", {newTargetValue = "1"}, 848)
	if log == "1" then
		luup.log(" Tasha is home ")          			
	end
   end 

	if log == "1" then
		luup.log(" check 1 ")    
	end
    if (VSSebHome == "0" and PingNotSebHome == "1") then
       	if (VSTashaHome == "0" and PingNotTashaHome== "1") then
		if log == "1" then
			luup.log(" Nobody home ")         			
		end  	
		luup.call_action("urn:upnp-org:serviceId:VSwitch1", "SetTarget", {newTargetValue = "0"}, 845)
    	end 
    end
    
       if log == "1" then
    			luup.log(" check2 ")     
	end


   return true	    

end

local status = pcall(nopresence, “1”)
if (not status) then
luup.log(“XYZZY:Error calling:nopresense”)
end

Haven’t a clue why you are getting the error.
Do you get the error if you delete the contents of the function (i.e. an empty function) ?
I do not understand why you have a “1” for the second argument in the assert calls ? That is typically the error message that is printed.

Most of the time, I get the error when I change something in an other scene and save it. I will get the “ERROR SCENE…”, I go in the “presence” scene and create a space “enter” in my code, save it and it’s fine.

The other time I will get the error is for no real reason, I will look at my vera and I will see that I have the “ERROR message” and I do the same thing to make it go away.

I’ve been trying to fix this for ever… just don’t know what to do anymore…

Where are you declaring these functions?

They should be declared in the LUA startup code section. If you are declaring that code as part of a scene, then the effect that you are seeing can occur. LUA is a just-in-time type compiler, so scene code is not compiled until the scene is first run (after a reboot or LUA reload). However, the startup code section is always compiled, so you can expect that code to exist.

oh really???

didn’t know about the fact the every fonction should declared in the startup lua?

I looked up and can’t really find the proper way to do so.

Could you please tell me how should I proceed?

And just to be sure, that declaration should be in the Startup LUA in the APP Developper right?

Thanks you !!!

Thanks guys but still same issue.

As suggested, I copied my function in the startup lua and called the fonction in the scene.

Lua startup
function nopresence(log)
if log == “1” then
luup.log("PRESENCE: "…os.date()… " ")
end

--[[ If No one if home, flip the VShitch.  --]]
local VSSebHome = assert(tostring(luup.variable_get("urn:upnp-org:serviceId:VSwitch1","Status", 847)),"1")
if log == "1" then

    	luup.log(" VSSebHome:"..VSSebHome)
end

local VSTashaHome = assert(tostring(luup.variable_get("urn:upnp-org:serviceId:VSwitch1","Status", 848)),"1")
if log == "1" then
	luup.log(" VSTashaHome:"..VSTashaHome)
end

local PingSebHome = assert(tostring(luup.variable_get("urn:micasaverde-com:serviceId:SecuritySensor1","Tripped", 843)),"1")
if log == "1" then
    	luup.log(" PingSebHome:"..PingSebHome)
end	

local PingTashaHome = assert(tostring(luup.variable_get("urn:micasaverde-com:serviceId:SecuritySensor1","Tripped", 846)),"1")
if log == "1" then
    	luup.log(" PingTashaHome:"..PingTashaHome)
end

local PingNotSebHome = assert(tostring(luup.variable_get("urn:micasaverde-com:serviceId:SecuritySensor1","Tripped",849)),"1")
if log == "1" then
        luup.log(" PingNotSebHome:"..PingNotSebHome)
end	

local PingNotTashaHome = assert(tostring(luup.variable_get("urn:micasaverde-com:serviceId:SecuritySensor1","Tripped",850)),"1")
if log == "1" then
	luup.log(" PingNotTashaHome:"..PingNotTashaHome)
end	

	local res,mode = luup.inet.wget("http://192.168.1.146:3480/data_request?id=variableget&Variable=Mode",5)
if log == "1" then
	luup.log(" Mode:"..mode)        	
end

mode = assert(tostring(mode),"1")
--[[ If seb not home and reverse tripped, change status VS to 0 --]]
if (PingSebHome == "0" and PingNotSebHome == "1") then
	if log == "1" then
		luup.log(" Seb not home ")        		
	end
	luup.call_action("urn:upnp-org:serviceId:VSwitch1", "SetTarget", {newTargetValue = "0"}, 847)
    end 
    
   if (PingSebHome == "1" and PingNotSebHome == "0") then
		if log == "1" then
			luup.log(" Seb is home ")     
		end
		luup.call_action("urn:upnp-org:serviceId:VSwitch1", "SetTarget", {newTargetValue = "1"}, 847)
   end

    --[[ If Tasha not home and reverse tripped, change status VS to 0 --]]
    if (PingTashaHome == "0" and PingNotTashaHome == "1") then
	if log == "1" then
		luup.log(" Tasha not home ")  
	end    
	luup.call_action("urn:upnp-org:serviceId:VSwitch1", "SetTarget", {newTargetValue = "0"}, 848)
    end 

   if (PingTashaHome == "1" and PingNotTashaHome == "0") then
	luup.call_action("urn:upnp-org:serviceId:VSwitch1", "SetTarget", {newTargetValue = "1"}, 848)
	if log == "1" then
		luup.log(" Tasha is home ")          			
	end
   end 

	if log == "1" then
		luup.log(" check 1 ")    
	end
    if (VSSebHome == "0" and PingNotSebHome == "1") then
       	if (VSTashaHome == "0" and PingNotTashaHome== "1") then
		if log == "1" then
			luup.log(" Nobody home ")         			
		end  	
		luup.call_action("urn:upnp-org:serviceId:VSwitch1", "SetTarget", {newTargetValue = "0"}, 845)
    	end 
    end
    
       if log == "1" then
    			luup.log(" check2 ")     
	end


   return true	    

end

Scene Lua
local status = pcall(nopresence, “1”)
if (not status) then
luup.log(“XYZZY:Error calling:nopresense”)
end

Same issue.
06/15/16 13:22:14.100 Scene::RunScene running 91 Presence <0x2b79a680>
01 06/15/16 13:22:14.101 LuaInterface::CallFunction_Scene Scene 91 failed attempt to call a nil value <0x2b79a680>

Any other ideas guys?

Try putting it in a new scene.
It’s not required to put the functions in the startup LUA set in.

But I do think it is good form. You will catch the syntax errors earlier.

I did not see any syntax errors in your code.

Not every function. Just global functions that are called from outside the scene that the function is created in.

I tried to recreate the new scene but the more I investigate the more I think the issue is releated to the PingSensor I use. BUT, I still have no clue how to fix this… starting to be quick the pain…

Any other ideas guys, and thank you so much for your help.

Guys, does it make any sens that I seem to only get the Nil error when I have the INTERVAL scene trigger activated. If I launch the scene manually, every 2-3 seconds, I do not get any issue…

I tried to do a loop and handle the launch every 10 seconds, but vera do not seem to like it as it restart the LUUP engine.

Any ideas?

Have you thought about using PLEG ?