Jump to content
  • 0

Global Functions in Fibaro HC2 LUA?


Question

Hello,

 

Is it posible in HC2 LUA to create global functions?

I use o lot of functions over and over again and have to include them in every scene

 

Is it possible to create functions in a centralized scene and use them from every other scene?

 

Example:

 

------------------------------------------------------------------------------------

GlobalFunctions

------------------------------------------------------------------------------------

global function BeepXseconds(x)

   fibaro:call(42, "turnOn")

   fibaro:sleep(x * 1000)

   fibaro:call(42, "turnOff")

end

 

global function MyDebug(text, color)

   -- read GlobalGlob

  if DebugGlob = true then   

       -- do something with formatting text, add OS.date and add colors

      fibaro:debug(text)

   end

end

------------------------------------------------------------------------------------

 

 

now i can use the global functions in other scenes

 

------------------------------------------------------------------------------------

scene 161 - TurnAlarmOn

------------------------------------------------------------------------------------

-- do something

MyDebug("Turn Alarm on", "red")

BeepXseconds(5)

-- do something

------------------------------------------------------------------------------------

 

 

 

 

------------------------------------------------------------------------------------

scene 254 - Doorbell

------------------------------------------------------------------------------------

-- do something

MyDebug("Someone is ringing", "BLUE")

BeepXseconds(2)

-- do something

------------------------------------------------------------------------------------

 

 

 

AND OFCOURSE I CAN CREATE SCENES AND USE THEM LIKE GLOBAL FUNCTIONS

BUT PARSING VARIABLES IS NOT THAT SIMPLE,  I THEN HAVE TO USE GLOBAL VARIABLES

 

REAL GLOBAL FUNCTIONS (LIKE A LIBRARY) WOULD BE GREAT !!!

 

 

Edited by xirilius
Link to post
Share on other sites

17 answers to this question

Recommended Posts

  • 1
5 hours ago, xirilius said:

AND OFCOURSE I CAN CREATE SCENES AND USE THEM LIKE GLOBAL FUNCTIONS

BUT PARSING VARIABLES IS NOT THAT SIMPLE,  I THEN HAVE TO USE GLOBAL VARIABLES

 

Not necessarily by using global variables, you can pass parameters to a scene.

 

Suppose you want to pass an  ID and a Value to another scene. Sending scene:

fibaro:startScene(207,{1437,99})

 

Receiving scene (this has ID 207):

local id,value=fibaro:args()[1],fibaro:args()[2]

fibaro:debug(("args: %d %d."):format(id, value))

 

  • Thanks 1
Link to post
Share on other sites
  • 1

Haven't tested this really, but this is a concept of how a homemade 'require' could work.

require(sceneID,module_name) checks if the  calling scene has the same version of the module as is in the scene with sceneID. If yes it just returns the local module, otherwise it patches in the module code from the other scene and  aborts. If the scene has autostart it will restart with the new code.

When require is called the module code needs to have loaded, that's why we call a 'main' after the scene is fully loaded.

If scene 320 looks like this (the Library scene) ( a library scene can have many modules)

module_foo = {
  version = 57,
  loader = function()
    local self,b,c = {},58,67
    function self.test1(a) return a+b end
    function self.test2(a) return a+c end
    return self
  end
}

and scene 319 looks like this (the client scene), it will patch in the new module from 320

function main()
  foo = require(320,"foo")
  
  foo.test1(2)
  foo.test2(3)
end

-- do setups
function require(sceneID,mod)
  local scene = api.get("/scenes/"..sceneID)
  local libcode = scene.lua:match("(module_"..mod.."%s*=%s*%b{})")
  local version = libcode:match("version = (%d+)")
  local loadedLib = _ENV['module_'..mod]
  if loadedLib and (loadedLib.version == tonumber(version)) then
    return loadedLib.loader()
  else
    scene = api.get("/scenes/"..__fibaroSceneId)
    if loadedLib then
      scene.lua = scene.lua:gsub("module_"..mod.."%s*=%s*%b{}",libcode)
    else
      scene.lua = scene.lua:gsub("---------- Library -----------",
                       "---------- Library -----------/n"..libcode.."/n")
    end
    api.put("/scenes/"..__fibaroSceneId,scene)
    fibaro:abort()
  end
end

---------- Library -----------
module_foo = {
  version = 56,
  loader = function()
    local self,b,c = {},53,66
    function self.test1(a) return a+b end
    function self.test2(a) return a+c end
    return self
  end
}

-- call main
main()

 

Edited by jgab
Link to post
Share on other sites
  • 0

i am not realy understand.

tell me if i am rong

you want a global that have al the globals you need and refer them in a scene, something like the Hometable??

Link to post
Share on other sites
  • 0

As far as I know your only option is to store the "global function" some way (e.g. json formated) in a global variable and import it where it is needed. 

Link to post
Share on other sites
  • 0

@petergebruers hi!

 

can help me?

 

scene id 123

 

function checkTime()
	local args = fibaro:args()
  	if #args > 0 then
      local str = args()[1]
      local t = os.date("*t",osTime());
      local h1,m1,h2,m2 = str:match("(%d+):(%d+)-(%d+):(%d+)")
      m1, m2, t = h1*60+m1, h2*60+m2, t.hour*60+t.min
      if (m1 <= m2) then
        return m1 <= t and t <= m2 -- 01:00-02:00
      else
        return m1 <= t or t <= m2 -- 23:00-21:00
      end
    end
	return false
end

calling

fibaro:startScene(123,{"18:00-22:00"})

my question is -how I can get function result?

Your workaround OK for calling, but FIBARO how that deaf can't understand what all users wish declaring a global function... 

 

PS: please do not recommend me "remove tonsils through the anus..."  ;D  I want simple get a result from a function...

 

Link to post
Share on other sites
  • 0

So, this is one of the reasons that I'm working with an 'event' based model when programming my scenes. I have scenes that send requests to 'library' scenes that perform some functions and return results. The implementation uses startScene and attaches the scene ID of the calling scene so the 'library' scene knows where to return the answer. However, it becomes asynchronous so it is easier if the whole scene logic is based on events. Here is an example that calls a scene that looks up users in Apple's iCloud. (the iCloud code is not included)

 

I have a new approach with a 'scripting' language that can hide the asynchronous nature of the call and just allow for ex. "location=callILocator(credentials)"... I will shows some examples in a later post in the thread below.

 

 

  • Thanks 1
Link to post
Share on other sites
  • 0

dear @jgab you as always cool :) 

I am learning LUA by your code, it's true. but now I am simply asking to implement easily including user library in any scenes / VDs for example via LUA FIBARO header 

Link to post
Share on other sites
  • 0
Just now, 10der said:

dear @jgab you as always cool :) 

I am learning LUA by your code, it's true. but now I am simply asking to implement easily including user library in any scenes / VDs for example via LUA FIBARO header 

Yes, you're right. Fibaro should find a way for shared user libraries. The best way would be to support Lua's 'require', but they would need to find a place to store the code - some new type of scene, call it library? The other issue is possible code/scene bloat as people would start to include a lot of 'good to have' code... :-) 

Link to post
Share on other sites
  • 0

 

--[[
%% properties
%% events
%% globals
%% using
34
--]]

orabif:test()



-- 34.lua - scene #34
local orabif = {}

function orabif:test()
  print("Test!")
end

return orabif

 

Edited by 10der
Link to post
Share on other sites
  • 0
1 minute ago, jgab said:

 

-- do setups
function require(sceneID,mod)
  local scene = api.get("/scenes/"..sceneID)

 

 

 

Aaaah! @Fibaro  Do you even know what you're doing? :oops:

 

Link to post
Share on other sites
  • 0

the regexp parsing of module is a bit too simplistic. e.g. can't have mismatching brackets in strings inside the module code.

A trick here is to use the _ENV table that holds all available globals and functions. Normally Lua has a _G table, but here we have a more limited table _ENV. However, it is still useful for calling functions or accessing variables given their names. The closest to meta-programming we have in the HC2 environment..

Link to post
Share on other sites
  • 0

What do you mean? __fibarosceneid only defined in scenes, so this only works in scenes 

Link to post
Share on other sites
  • 0

sorry, I am still talking about cost and how owner HC2 developers trying to find workarounds for require

Don't mind me. I was just leaving.

Link to post
Share on other sites
  • 0

Do you know if HC3 has a better way of handling require?

AFAIK, here the only option is to put the definition of this require() function to every scene in which we want to use libraries, right? It'd be great to have something tidier...


If this is supported in HC3, it's a good reason to upgrade...

Link to post
Share on other sites
  • 0
22 minutes ago, Tamar said:

Do you know if HC3 has a better way of handling require?

AFAIK, here the only option is to put the definition of this require() function to every scene in which we want to use libraries, right? It'd be great to have something tidier...


If this is supported in HC3, it's a good reason to upgrade...

It's easier - on the HC2 it was high-wire acrobatics. On the HC3 it's more like a ground floor somersault.

The HC3 QAs (VDs) have can consist of several 'files' and you can pull in files from other QAs or over the network (like your Github) with common code. There are a couple of examples in the forum. I have a module system I use myself for all QA code on the HC3 <link>

  • Like 1
Link to post
Share on other sites
  • -1
11 minutes ago, jgab said:

the regexp parsing of module is a bit too simplistic. e.g. can't have mismatching brackets in strings inside the module code.

A trick here is to use the _ENV table that holds all available globals and functions. Normally Lua has a _G table, but here we have a more limited table _ENV. However, it is still useful for calling functions or accessing variables given their names. The closest to meta-programming we have in the HC2 environment..

 

@jgab it's really cool but

 

scene = api.get("/scenes/"..__fibaroSceneId)
[skipped...]
api.put("/scenes/"..__fibaroSceneId,scene)

:(

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...