openLuup: debugging plugins with ZeroBrane Studio

I use ZBS for developing openLuup - it’s an excellent IDE, and one of my frustrations has been that I couldn’t easily use its extensive breakpoints, watch window, and stack window capabilities to debug plugins.

The reason it doesn’t (didn’t) work is that the Lua implementation files and code, referenced in the I_xxx.xml device file, are not imported into openLuup with the usual ‘require’ mechanism, but are loaded as text files and ‘compiled’ into the device environment in a complicated mix of code coming from and tags in various places, so ZBS doesn’t know they’re being used.

However, it turns out there’s a simple way around this. Here’s a new plugin I’m developing/ testing… (good, eh?)

module ("L_TestPlugin", package.seeall)

function init (lul_device) 
  luup.log ("TEST device number is: " .. lul_device) 
end

The following is the I_TestPlugin.xml implementation file:

<?xml version="1.0"?>
<implementation>
  <functions>
    function startup (lul_device)
      local m = require "L_TestPlugin"
      return m.init (lul_device)
    end
  </functions>
  <startup>startup</startup>
</implementation>

…so the implementation file simply uses ‘require’ and calls the entry point (with the device number) directly.

You can set breakpoints, debug as usual, and get the right line numbers in any error messages that openLuup generates.

My thanks to both @explorer and @vosmont for sowing the seeds of this idea a long time ago.


see @vosmont’s: openLuup: Unit/fonctional testing on openLuup

for @explorer’s contributions, they are PMs to me during April 2016…
…and a key post on this thread!

Let me add one caveat to this approach on debugging openLuup plugins… it may only work if you have one device instance of the plugin installed.

The reason for this is that all openLuup code (devices, plugins, scenes, …) runs in a single Lua instance (this is why it is so memory efficient.) While the various code environments are generally separate so that variables are in separate namespaces, loading an actual module with require will mean that if it is not fully re-entrant (ie. does not have any top-level variables, either local or global) then top-level variables will be shared between instantiations. This could certainly lead to unexpected behaviour.

However, for almost all debugging needs (who would choose to debug multiple intsances simultaneously?) this modification to the implementation file works like a charm… just remember to revert to the more usual format for any production-ready code which may require multiple plugin instances.

Do I need to use ZeroBrane for Vera to debug a plugin, or can I connect the vanilla ZeroBrane to your debug plugin? I’m not sure how to setup the vanilla ZeroBrane for openLuup.

I do all my development and debugging of openLuup within vanilla ZeroBrane Studio on a Mac.

There are several approaches and ‘tricks’ which I could describe given the need and some time, but my basic method is to run an entire openLuup process within ZBS.

Because of the XML content of implementation files, openLuup loads them itself, so the debugger doesn’t have the context for those files. However, there is an easy way around this, described in the previous post in this thread, and then you can set breakpoints, examine variables, etc., etc…

Let me know if you need more.

PS: you did well to find this old and neglected thread!

I was checking this forum after upgrading my openLuup system to version 18.3.15 after almost a year away from it, and noticed some activity on this “neglected” topic. It brought some good memories, so I thought I’d share my vanilla ZBS debugging techniques…

I updated my old notes and attached them here along with the modified loader code. Hope it helps.

P.S. I really like openLuup, it runs rock solid for months. Had to update to the newer version only because GitHub recently changed the SSL security, and AltUI failed to download. I was happy to see that AK already took care of that. Thanks!

@explorer… what a pleasure to see one of your very rare posts to this forum. I’m sure that most users are quite unaware of the critical input that you’ve had to several key aspects of openLuup. A public “thank you” for that.

Your latest post seems important enough to me to:

[ol][li]make the topic sticky, and,[/li]
[li]look closely at incorporating your changes to the loader.[/li][/ol]

I debug locally on my development system, but there are clearly times when being able to debug a separate system will be useful.

Done! Available in the development branch as v.18.3.17

Thanks again, @explorer, I’d be pleased to hear that these changes work as expected, and save you (or others) from any tedium when updating in future. Perhaps a slight edit now required for your debugging instructions!

I just returned from vacation and what a pleasant surprise! Thank you!

Updated my system to the latest openLuup development branch, it worked like a charm. Adjusted debugging instructions in my original post.

Thanks guys for the shortcuts. That saved a lot of effort. I’m pretty much up and running, however, I am running into an error when running an openluup instance (needed to run/debug an instance of a long abandoned plugin).

The debugger stops at line 579 with a nil value in userdata.lua (local ol = luup.devices[2]). I can get past the error if I substitute “luup.devices[2]” with “user_data.devices[2]” but I don’t want to break anything and chances are the error is the result of a startup environment problem on my part.

I’m running ZB on a Windows 10 machine and openluup on an OrangePi2PC.

Any guidance much appreciated.

luup.devices[2] is the openLuup plugin. It’s always there. (On Vera, this is the scene controller device.)

How did you start up the openLuup instance? What is in the startup log? What’s in the user_data.json file?

It would be wrong to make the substitution you propose. I’ve certainly never seen a problem at this stage of system initialisation.

I start with _debug.lua in the cmh-ludl folder. I’m sure this is an environment problem on my end. The debugger is picking up the JSON and arrays, but is not setting variables—which is causing the nil value. The start-up log shows errors as well with variable initialization:

[code]

2018-04-08 16:15:17.692 luup.create_device:: ERROR [1] D_ZWaveNetwork.xml / / : .\openLuup\loader.lua:388: attempt to call global ‘setfenv’ (a nil value)
2018-04-08 16:15:17.707 luup.create_device:: ERROR [2] D_openLuup.xml / / : .\openLuup\loader.lua:388: attempt to call global ‘setfenv’ (a nil value)[/code]

What version(s) of Lua are you running? Both must be v5.1…

Ah, well that’s probably part of the problem as I’m running 5.2. At least that’s what ZBS says (version running) on the local machine. I realize that Lua has made substantial changes between versions (including 5.3), but why are you using 5.1?

Because that’s what Vera/MiOS uses, and openLuup has to be compatible.

Is it possible to debug startup code (in the AltUI startup window), or do I need to create a temporary plugin to set breakpoints for such code? If so, do I just place the name of the lua code file I want to debug within the startup tag of the temp plugin?

My initial approach to debugging Startup Lua would be to run it first in the Lua Code Test window and sprinkle it liberally with print statements. Within that window, the pretty() function is defined, which allows you to see the Lua structure of tables, etc…

local dev = luup.devices[2]
print "JUST PRINT()"
print(dev)
print "PRETTY PRINT()"
print (pretty(dev))

gives:

JUST PRINT()
table: 0x163738
PRETTY PRINT()
{
	 category_num = 0,
	 description = "    openLuup",
	 device_num_parent = 0,
	 device_type = "openLuup",
	 embedded = false,
	 hidden = false,
	 id = "",
	 invisible = false,
	 ip = "",
	 mac = "",
	 pass = "",
	 room_num = 0,
	 subcategory_num = 0,
	 udn = "uuid:d764c8cc-e932-55c4-478d-7aa05d83f3ea",
	 user = ""
}

You can’t set breakpoints, but you can see what’s going on.

If it’s not interacting with devices, then debug the code in an IDE completely separately first.

To debug as a device then you’d need a full set of D_xxx.xml, I_xxx.xml, L_xxx.lua, … files, with the right functionality for a device, and a global procedure for intitialisation. It’s just the name of that procedure which goes into the tag of the device file. I simply wouldn’t do this unless it’s absolutely necessary.

Hey Guys,

I really like where this is going.

I use ZBS for Vera and love it. The main reason I’m not really deep in OpenLuup is the reason why. Since I never managed to debug within ZBS and get my global and local variables values.

I have various scene that I used and still debug via ZBS, I open the file and simply execute with a breakpoint. The workaround here seems to load the Lua engine but I simply don’t understand how we can debug a single “scene” lua file.

Do we have a workaround to use ZBS for Vera with OpenLuup?

Many thanks guys!

Seb.

I’ve never found a need for remote debugging, but that’s probably because I simply run openLuup entirely within ZBS when developing.

Although I’ve not tried it, it seems to me that there’s no need at all for ‘ZBS for Vera’, since there are comprehensive instructions here: https://studio.zerobrane.com/doc-remote-debugging and the openLuup source is entirely accessible to you.


Edit: @explorer’s notes, attached to an earlier post in this thread, are also quite comprehensive.

Thanks Guys,

I followed the ,pdf posted on this channel. I manage to run OpenLuup in Zerobrane. What I don’t understand is how to break on a scene.

As I mentioned, I’m using ZeroBrane for Vera and I use to add a break point to my .lua. Since I have a lot of global variable I used to be able to see all of them as well.

My question, let’s say that I copied a scene in a .lua file, copied that in my /etc/cmh-ld, how can I break on that file?

Thanks

As it stands, you can’t. Neither can you do that for Lua Test code.

The reason for this is that ZBS needs an actual file to trace line numbers, etc. Scene code does not exist as a file.

However, there may be a work around…

Since I have a lot of global variable I used to be able to see all of them as well.

Scene globals exist in the same space as Lua Test code, so are available for inspection there.

My question, let's say that I copied a scene in a .lua file, copied that in my /etc/cmh-ld, how can I break on that file?

Now you’re talking! This should work, although I’ve never tried it with scenes. I have tried it with plugins which, since they are a synthesis of device file XML and Lua files, suffer at the outset from the same issue.

The things to do would be to put your code into a file which you would require in Lua Test (or, indeed, Lua Startup, which also shares the same space.)

require "mySceneCode"

You should, then, be able to set breakpoints in that file and interact with them in the usual way, assuming that your actual scene Lua calls globals in the required module.

I’m off to try this for myself…