amg0 / ALTUI

Enhancement Interface for VERA home automation system
16 stars 8 forks source link

Sle118 patch dataprovider #2

Closed sle118 closed 7 years ago

sle118 commented 7 years ago

see post for details http://forum.micasaverde.com/index.php/topic,35860.msg297561.html#msg297561

sle118 commented 7 years ago

In lua, it is not possible to call functions from a "string" variable, as far as I know. So the recursive search in _G is used to find the function declaration "somewhere" in the lua globals, based on the function name. In this specific context, we have a global function (the data push function) which was created in the lua startup, which means it will exist inside a sub-table that cannot be accessed from the top level _G. By reading recursively, the hope is that we'll hit the startup lua code's "globals" from which we'll extract the current function definition (and address). Now recursively processing _G and all internal tables is time consuming as it is a deep rabbit hole. From my experience, the lua startup code in openLuup is well above level 5, and was chosen arbitrarily.

I believe it would be possible to speed up processing by only searching inside tables with names '_G' and ignore all other ones.

You can dump the content of the lua _G variable using a function similar to the one here: https://gist.github.com/stuby/5445834#file-rprint-lua

this is very usefull when dealing with lua outside of a proper debugging environment!

amg0 commented 7 years ago

I understand, you can do simple debug in ALTUI test Lua screen and type this for instance for n,v in pairs(_G) do print(n , type(v)) end return true

but remains not clear to me is 2 things :

1) why would the function not be in the immediate first level ( _G["function name"] for instance ? why would we need to walk up the tree ?

2) if the function is found in _G then called directly by ALTUI lua device, then what will be the lua context it is called in ? ( same as altui one ? ) , meaning will your function be able to access ALTUI internal global variables ?

sle118 commented 7 years ago

To answer your questions 1) the function seems to be loaded at a lower level and I am unsure why. I am declaring the function in a standard way and it just 'lands' in the lower context. 2) the context that the function is called is the one where the function got declared. Basically, whatever is available in the start up, which is not much.

I have thought about another way to implement this, possibly better. It would be possible to resolve the function pointers when calling "_loadDataProviders", which could loop through the providers and pull the functions as they are found.

so I think I would re-write to something like this (untested!)

local function _loadDataProviders()
    local str = luup.variable_get(ALTUI_SERVICE, "DataStorageProviders",  lul_device) or "{}"
    DataProviders = json.decode(str)
    for k,v in pairs (DataProviders) do
        if (v["callback"] ~= nil) then
            local callback_fn = table_search(_G,DataProviders[provider]["callback"],"",0)
            if callback_fn ~= nil then
                DataProvidersCallbacks[DataProviders[provider]["callback"]] = callback_fn
            end         
        end
    end
end
sle118 commented 7 years ago

Refactored the code to align logic around loading data providers. Will open a new PR.