stateVariable default not showing in the Advanced->Variables tab

I have in my S_MyDevice.xml state definitions a few variables like this:

		<stateVariable>
			<name>PingInterval</name>
			<datatype>number</datatype>
			<defaultValue>30</defaultValue>
		</stateVariable>

but, even though I’m using the defaultValue tag, I am not seeing the variable in the Advanced → Variables tab on a newly created Device/Instance, unless I set the variable otherwise in the plugin…

How do I get variables like the to initialize to the “defaultValue” value and then remain persistent?

Have you, perchance, tried setting a shortCode name for your variable?

  <shortCode>pingInt</shortCode>

I’m not convinced of the effect, but it’s worth a try.

Doing this will ensure that it ends up in sdata request responses, FWIW.

[quote=“BulldogLowell”]I have in my S_MyDevice.xml state definitions a few variables like this:
[…]
but, even though I’m using the defaultValue tag, I am not seeing the variable in the Advanced → Variables tab on a newly created Device/Instance, unless I set the variable otherwise in the plugin…[/quote]

I don’t think that’s ever worked. It’s probably not promised anywhere that a UPnP variable (which is what the S_*.xml file contains) automatically becomes a Luup variable (which is what the Variables tab in the UI contains). Indeed, the UPnP service file is a complicated beast (try to read the spec) and it’s not clear how much of it is implemented, noticed, or respected by the reference implementation of Luup (LuaUPnP).

My plugins always set default values for Luup variables with an if-not-existing-then-set-value block at plugin startup.

I see… another Vera peccadillo.

can you point me to an example of how you do that?

Thanks!!

Ooh, that would be evil.

My plugins always set default values for Luup variables with an if-not-existing-then-set-value block at plugin startup.

Definitely.

…thinking further about this, it seems to me that this would be a way to force Vera to make it into a Luup variable.

Again, worth a try, at least to find out THE TRUTH.

From a robustness POV, though, you can’t beat doing it manually:

local x = luup.variable_get (SID, NAME, DEV)
if not x then
  luup.variable_set (SID, NAME, DEFAULT, DEV)
end

…which you’d probably want to wrap into a function and call for all your initial variables.

[quote=“akbooer, post:6, topic:197104”] local x = luup.variable_get (SID, NAME, DEV) if not x then luup.variable_set (SID, NAME, DEFAULT, DEV) end

…which you’d probably want to wrap into a function and call for all your initial variables.[/quote]

I did this:

if (luup.variable_get("urn:mydomain-com:serviceId:MyPlugin1", "SomeValue", lul_device) == nil) then
  luup.variable_set("urn: mydomain-com:serviceId: MyPlugin1", "SomeValue", 120, lul_device)
end

and it worked well.

I will wrap all of the variables as such…

thanks for (both) your help!

@akbooer and @futzle (or any one else who can assist),

So after working on my plugin for a while, and with the help from the forum, I’m pretty far along and have an (early) working device. :smiley:

I’m struggling with one part that I cannot for the life of me debug. I noticed when I delete and create a new instance of the plugin, I am getting a Startup Lua Failed error. ???

I’ve pored over my code but cannot find what I’ve done wrong, though I believe it related to improper initialization of luup variables which I’m manipulating during the function. As I’ve written the code, it was all evolutionary. I’ve not kept a keen eye on the creation of a new object, I’m afraid.

While I am not asking for anyone to write code for me, I was hoping that someone with experience in Luup could help spot my errors. The logging during startup is difficult for me to capture; there is significant output that obfuscates what’s happening during the startup of my plugin.

Would anyone be able to offer up some help on how to either a) filter the log output in order to clearly see what’s happening (and only that) during the startup functions, or b) critique my code for errors.

Yeah, this is painful, particularly if you’re accustomed to nice IDEs. (If you absolutely have to have an IDE then I’ve heard good things about ZeroBrane Studio. Never used it myself.)

My low-tech debug technique is to do something like:

# tail -f /var/log/cmh/LuaUPnP.log | grep SOMETHING 

from the command prompt. For SOMETHING substitute text that is specific to your plugin’s log messages. I’m away from my Vera at the moment but I recall that any use of luup.log() in a device will produce lines that contain :69: (or whatever the device number is) with two colons around it, which is unlikely to appear in other lines of log. Look at some unfiltered log output to see what’s appropriate.

Use Control-C to get back to the command prompt.

Liberally put calls to luup.log() in your code, starting at the entry point. You can log variable values but often it’s enough just to log a fixed string so you know you hit a certain line in your code. Take a look at a debug() function I wrote that makes these log messages configurable based on a Luup variable.

A crash, which you must be getting, will produce very distinct output in the log. Just make sure you haven’t hidden it with aggressive grepping. The line number in the crash message will give you a pointer to the line of your code (either from the beginning of the file if it’s an L_.lua file, or from the start of the embedded Lua fragment if it’s an I_.xml file).

If you’re getting the crash at plugin startup then you’ll need to reload the Luup engine in order to trigger the crash.

You could also run it in openLuup which gives much better diagnostic opportunities.

One other tip.

If you plan to define triggers on a variable make sure it listed in the S_device.xml file or LUUP will crash the moment the trigger fires. So its content is not completely ignored.

Cheers Rene

thanks everyone…

I’m using these functions:

	<functions>

	  local MyDevice

		function startup (lul_device)
			luup.log("ThreeGee1: Bridge Plugin: Loading Library L_ThreeGee1...")

			if (package.path:find ("/etc/cmh-ludl/?.lua;/etc/cmh-lu/?.lua", 1, true) == nil) then
				package.path = package.path .. ";/etc/cmh-ludl/?.lua;/etc/cmh-lu/?.lua"
			end

			package.loaded.L_ThreeGee1 = nil
			MyDevice = require("L_ThreeGee1")

			if (package.loaded.L_ThreeGee1 == nil)
			then
				luup.log("ThreeGee1 plugin: plugin is not installed correctly. Library L_ThreeGee1 cannot be loaded.", 1)
				luup.task("Plugin not correctly installed", 2, "ThreeGee1 plugin", -1)
				return false
			end

			luup.set_failure(false, lul_device)
			luup.log("ThreeGee1 plugin: library L_ThreeGee1 loaded")

			luup.variable_set("urn:konektedplay-com:serviceId:ThreeGee1", "Received", "no message received", lul_device)

			MyDevice.initializeVariables(lul_device)
			luup.log("ThreeGee1: start pingGateway")
			pingGateway(lul_device)
		end

		-- callback function to repeat ping to gateway
		function pingGateway (lul_device)
		  luup.log("ThreeGee1: running pingGateway()")
		  luup.io.write("PING:-1", tonumber(lul_device))
			luup.log("ThreeGee1: getting LastUpdate timestamp")
		  local value, timestamp = luup.variable_get("urn:micasaverde-com:serviceId:SecuritySensor1", "LastUpdate", tonumber(lul_device))
			luup.log("ThreeGee1: getting current tripped state")
			local currentTrippedState = luup.variable_get("urn:micasaverde-com:serviceId:SecuritySensor1", "Tripped", tonumber(lul_device))
			if not currentTrippedState then
			  luup.log("ThreeGee1: error currentTrippedState")
			end
			luup.log("ThreeGee1: getting current PingTimeout")
			local pingTimeout = luup.variable_get("urn:konektedplay-com:serviceId:ThreeGee1", "PingTimeout", tonumber(lul_device))
			luup.log("ThreeGee1: checking...")
			luup.log("ThreeGee1: os.time:"..os.time())
			luup.log("ThreeGee1: timestamp:"..tonumber(timestamp))
			luup.log("ThreeGee1: pingTimeout:"..tonumber(pingTimeout))
			if (os.time() - tonumber(timestamp) > tonumber(pingTimeout)) then
		    luup.log("Sensor Is Tripped")
		    if(currentTrippedState == "0") then
		      luup.log("Setting to Tripped")
		      luup.variable_set("urn:micasaverde-com:serviceId:SecuritySensor1", "Tripped", 1, tonumber(lul_device))
		    end
		  else
		    luup.log("Sensor Is Not Tripped")
		    if(currentTrippedState == "1") then
		      luup.log("setting to not tripped")
		      luup.variable_set("urn:micasaverde-com:serviceId:SecuritySensor1", "Tripped", 0, tonumber(lul_device))
		    end
		  end
		  local pingFrequency = luup.variable_get("urn:konektedplay-com:serviceId:ThreeGee1", "PingFrequency", tonumber(lul_device))
			luup.call_timer("pingGateway", 1, tostring(pingFrequency), "", lul_device)
		end

	</functions>

with this in my lua module:

[code]
function initializeVariables(device)

assert(device ~= nil)
luup.log(“ThreeGee1: running initializeVariables”)
luup.log(“ThreeGee1: initializing…”)
if (luup.variable_get(SECURITY_SENSOR_SID, “Tripped”, device) == nil) then
luup.log(“ThreeGee1: initializing Tripped”)
luup.variable_set(SECURITY_SENSOR_SID, “Tripped”, 0, device)
end

if (luup.variable_get(SECURITY_SENSOR_SID, “Armed”, device) == nil) then
luup.log(“ThreeGee1: initializing Armed”)
luup.variable_set(SECURITY_SENSOR_SID, “Armed”, 0, device)
end

if (luup.variable_get(SECURITY_SENSOR_SID, “ArmedTripped”, device) == nil) then
luup.log(“ThreeGee1: initializing ArmedTripped”)
luup.variable_set(SECURITY_SENSOR_SID, “ArmedTripped”, 0, device)
end

if (luup.variable_get(THREEGEE_SID, “GatewayTimeout”, device) == nil) then
luup.log(“ThreeGee1: initializing GatewayTimeout”)
luup.variable_set(THREEGEE_SID, “GatewayTimeout”, GATEWAY_TIMEOUT, device)
end

if (luup.variable_get(THREEGEE_SID, “PingFrequency”, device) == nil) then
luup.log(“ThreeGee1: initializing PingFrequency”)
luup.variable_set(THREEGEE_SID, “PingFrequency”, PING_INTERVAL, device)
end

if (luup.variable_get(THREEGEE_SID, “PingTimeout”, device) == nil) then
luup.log(“ThreeGee1: initializing PingTimeout”)
luup.variable_set(THREEGEE_SID, “PingTimeout”, PING_TIMEOUT, device)
end
luup.log(“ThreeGee1: completed initializeVariables”)
return true
end[/code]

you can see from the output that the value isn’t being initialized properly… am I making some scope errors?

log:

50	09/06/17 8:40:23.521	luup_log:257: ThreeGee1: Bridge Plugin: Loading Library L_ThreeGee1... <0x2bd33680>
50	09/06/17 8:40:23.543	luup_log:257: ThreeGee1: running initializeVariables <0x2bd33680>
50	09/06/17 8:40:23.543	luup_log:257: ThreeGee1: initializing... <0x2bd33680>
50	09/06/17 8:40:23.556	luup_log:257: ThreeGee1: initializing Tripped <0x2bd33680>
50	09/06/17 8:40:23.557	luup_log:257: ThreeGee1: initializing Armed <0x2bd33680>
50	09/06/17 8:40:23.559	luup_log:257: ThreeGee1: initializing ArmedTripped <0x2bd33680>
50	09/06/17 8:40:23.561	luup_log:257: ThreeGee1: initializing GatewayTimeout <0x2bd33680>
50	09/06/17 8:40:23.562	luup_log:257: ThreeGee1: initializing PingFrequency <0x2bd33680>
50	09/06/17 8:40:23.564	luup_log:257: ThreeGee1: initializing PingTimeout <0x2bd33680>
50	09/06/17 8:40:23.575	luup_log:257: ThreeGee1: completed initializeVariables <0x2bd33680>
50	09/06/17 8:40:23.575	luup_log:257: ThreeGee1: start pingGateway <0x2bd33680>
50	09/06/17 8:40:23.576	luup_log:257: ThreeGee1: running pingGateway() <0x2bd33680>
50	09/06/17 8:40:23.580	luup_log:257: ThreeGee1: getting LastUpdate timestamp <0x2bd33680>
50	09/06/17 8:40:23.581	luup_log:257: ThreeGee1: getting current tripped state <0x2bd33680>
50	09/06/17 8:40:23.581	luup_log:257: ThreeGee1: error currentTrippedState <0x2bd33680> // <<<<<< look here!!
50	09/06/17 8:40:23.582	luup_log:257: ThreeGee1: getting current PingTimeout <0x2bd33680>
50	09/06/17 8:40:23.583	luup_log:257: ThreeGee1: checking... <0x2bd33680>
50	09/06/17 8:40:23.583	luup_log:257: ThreeGee1: os.time:1504701623 <0x2bd33680> // <<<<< crashes here

You set the variable to a numeric value of 0
When you test a numeric value of 0 (i.e. cast it as a boolean) it is treated as false.

Vera usually sets variables to the string representation of numbers … i.e. “0”
But you can do what you want … you just need to know the implication of ANY other software that will look at your variables.

[quote=“RichardTSchaefer, post:13, topic:197104”]You set the variable to a numeric value of 0
When you test a numeric value of 0 (i.e. cast it as a boolean) it is treated as false.

Vera usually sets variables to the string representation of numbers … i.e. “0”
But you can do what you want … you just need to know the implication of ANY other software that will look at your variables.[/quote]

Thanks Richard,

Coming from C++ I’m having a hard time adjusting to lua’s loose typing.

Regarding your comment, I realized an error here:

  if (luup.variable_get(THREEGEE_SID, "LastUpdate", device) == nil) then
    luup.log("ThreeGee1: initializing LastUpdate")
    luup.variable_set(THREEGEE_SID, "LastUpdate", 0, device)
  end

should be:

  if (luup.variable_get(THREEGEE_SID, "LastUpdate", device) == nil) then
    luup.log("ThreeGee1: initializing LastUpdate")
    luup.variable_set(THREEGEE_SID, "LastUpdate", os.date("%c"), device)
  end

I’m actually using the timestamp that is returned as part of the call to luup.variable_get, not the actual data I’m populating.

So, the initialization function works now… bear in mind I’m looking for ‘nil’ not zeroes or true or false.

I have it worked out now; it happens that I had a syntax error in my module. :-[

This has been quite the journey, I’m nearly ready, just tweaking the UI stuff to make it look more pretty (vis ? vis Vera ;D). Now I can focus more on the 3G bridge and less on all this plugin work.

Thanks again… you are part of the core group (like the other responders to this post) of capable folks on this forum that make this journey a heck of a lot easier!