XML2lua problems

Im hitting an issue with xml2lua and i dont understand why.
I’m when i’m running my discovery code on my local dev machine xml2lua works flawlessly and i get everythign i need out of it etc but when I run it on the hub it seems to fail to parse the xml and i end up with a table but with nothing in it… but i dont get any parsinig error messages. it seeems to parse ok.

discovery thread encountered error: [string “discovery.lua”]:56: attempt to index a nil value (field ‘root’)

You are trying to load a xml file, aren’t you ?

It happened to me weeks ago.
As I remember, io.open isn’t available when running on the hub.
I think this is for security reasons.

In my case, I was trying to read yaml file.
I had to convert the yaml to string json inside lua file. Then, I do this: json.decode(require("my_json"))
So, instead of using io.open, I used require.

my_yaml.yml

example:
  test: ok

my_json.lua

return [[{"example":{"test":"ok"}}]] -- string json

We can delimit literal strings also by matching double square brackets [[...]].
Source: https://www.lua.org/pil/2.4.html

Some functions have been removed where they are impossible to use from within the sandbox, such as those dealing with filesystem access. Some have been reimplemented, matching the behavior of the standard lua implementation to work with the sandbox, such as require.
Source: Global Environment — SmartThings Edge Device Drivers documentation

Here is what I’m doing

local function fetch_device_info(url)
  log.info("getting Metadata")
  local res = {}
  local _, status = http.request({
    url=url,
    sink=ltn12.sink.table(res)
  })


  -- XML Parser
  local xmlres = xml_handler:new()
  local xml_parser = xml2lua.parser(xmlres)
  xml_parser:parse(table.concat(res))
  print(xml2lua.printable(xmlres.root))
  
  local meta = xmlres  
  
  if not xmlres.root or not meta then
    log.error('Failed to get Metadata at: '..url)
    return nil
  end
 
  return {
    ip = url:match("http://([^,]+):([^/]+)"),
    name=meta.root.root.device.friendlyName,
    vendor=meta.root.root.device.UDN,
    mn=meta.root.root.device.manufacturer,
    model=meta.root.root.device.modelName,
    description=meta.root.root.device.modelDescription,
    location="http://"..url:match("http://([^,]+):([^/]+)")
  }
end

xmlres ends up as a table but seems to be empty and i get the error discovery thread encountered error: [string “discovery.lua”]:52: attempt to index a nil value (field ‘root’) when trying to get name=meta.root.root.device.friendlyName

If i do the same on my local dev machine it all works fine.

Cheers Hugh

I found this:

The example above was last sent by @nayelyz
Very similar to your case.

I can’t help you much more than this because I don’t know…

  • what is in the line 52
  • the xml structure you are trying to read
  • whether your hub is at the same network of your computer or not
  • the url you are trying to fetch

My first attempt would be to overwrite the current fetch_device_info by the one in the example.

Hi Wesley

I found the problem. You cant use the standard lua socket lib. The request was returning empty but i didnt realise until I started back tracking to make sure i was getting the response.

Replacing it with the cosock version solves the issue

local http = cosock.asyncify "socket.http"

instead of

local http = require "socket.http"

Handy to know.

Cheers Hugh

1 Like

This is exactly what she did…