Jump to content

Welcome to Smart Home Forum by FIBARO

Dear Guest,

 

as you can notice parts of Smart Home Forum by FIBARO is not available for you. You have to register in order to view all content and post in our community. Don't worry! Registration is a simple free process that requires minimal information for you to sign up. Become a part of of Smart Home Forum by FIBARO by creating an account.

 

As a member you can:

  •     Start new topics and reply to others
  •     Follow topics and users to get email updates
  •     Get your own profile page and make new friends
  •     Send personal messages
  •     ... and learn a lot about our system!

 

Regards,

Smart Home Forum by FIBARO Team


Shared code/libraries - poor mans solution


jgab

Recommended Posts

This is a way to having shared code in your scenes. A half-manual/half-automatic version of require.

 

The idea is to setup up a "Library" scene with reusable functions.

Then, scenes needing those functions, will copy these functions into their scene's code. Simple?

Ex.

Please login or register to see this code.

So, 'frequire' get the shared library and assigns it to funs1. A library is a table with functions, so we call them like:

funs1.a(), funs1.c() etc.

Like we do with 'json.decode()' etc.

 

Unfortunately, it's not as simple as above. We need to define the 'frequire' function and do some adjustments to our scene.

Please login or register to see this code.

The first trick is to wrap our main code in a 'scene' function. That way we can keep our main code at the beginning of the scene and keep the shared code and the 'frequire' function at the end of the scene. Usually more convenient to have it at the beginning and the code we don't touch at the end. However, we can't call 'frequire' before it is defined, so we let all functions in the scene be defined and at the end we call back to 'scene' and let our main code begin. This is a convenient trick for all kind of scenes.

 

What happens when we run this for the first time?

'frequire' will discover that "My functions 1"and "My functions 2" is not loaded and insert them at the end of our scene

Please login or register to see this code.

It will then terminate and ask us to re-run the scene again.

Next time we run it, 'frequire' sees that the functions exist in the scene and returns the library (table of function) directly.

There is a _version field for libraries so frequire discovers if we have a new version of a library/shared code, and updates in that case too.

 

To make this work we need to declare a fibaro global "LIBS" and declare some library scenes (we can have many scenes with many libraries but each library need to have an unique name)

 

A library scene file looks like this:

Please login or register to see this code.

A library scene can declare many libraries, and a library can contain may functions. In principle, you can put any code between the comment markers, as long as no global Lua variables are declared (can clash with user code) and it ends with an assignment to LIBMAP with a table of functions and a _version field.

Ex.

Please login or register to see this code.

When we run the library scene, it will update the fibaro global "LIBS" with the latest versions of defined libraries.

 

The code could be improved.

  • At the moment, only one require will be resolved each time the scene is started. Maybe there is a way to do all at once.
  • frequire will not do anything if the scene is autostarted. The reason is that if the scene autostarted (box restarting) and it updates the code and terminates - it's not being started again. Maybe a warning in case the code is outdated?
  • There is no way to automatically remove an unused "included" library. However, just delete the included libraries at the end and re-run.
  • making ‘frequire’ smaller by moving the scene updating responsibility to the library scene - then scene could also be restarted if it was autostarted.
  • Undiscovered bugs could be fixed...

 

 

Edited by jgab
Fixed resolving multiple libraries at once
  • Like 1
Link to comment
Share on other sites

Interesting solution, but this is good only for easy updating code of other scenes that are of course prepared to use code from library. I think it is just enough to run library scene after any changes done to common functions and then it should scan all scenes and update any common code that is either still missing or outdated.

 

LUA can actually store functions to global variables same as any other data and the only problem that prevents us from using functions stored in global variables is that Fibaro experts for security disabled loadstring function.

Link to comment
Share on other sites

  • Topic Author
  • Yep, we had

    Please login or register to see this link.

    r - just wanted to be a bit constructive and point at a possibility.

    ...and there's  no such thing as "easy updating of code" :-) 

     

    One could put more responsibility on the library to update other scenes, but it comes with some tradeoffs; should it kill running scenes to update them? If not, then when? Kill them may be ok. Then if we have several library scenes we have to make sure they don't update at the same time... but its probably solvable. The current "pull" approach solves both that it serves as a method for scenes to declare what libraries they need, it serves as a way to get a pointer to the library functions,  and it allows scenes to be updated on a per needs basis. Maybe a compromise - if not running, update scene, otherwise wait until they restart and request an update.'

     

    Yes, loadstring and co-routines and we could make some really cool scenes. However, they need to fix their fibaro globals before we can trust them; persistence between saves (I know we can have predefines)... and some kind of lock mechanism so we have a fair chance to avoid race conditions...

     

    Assume we had loadstring, I guess it would be good for the community to agree about a "library" format so it would be easy to share and replace functionality?

     

    ...and while we wait (forever) for that, we could come up with an interim solution that helps people publish code snippets and include them in their scenes. We could even define our own "apt-get" or "npm install" VD for installing library scenes from a community moderated repository... 

    Edited by jgab
    Link to comment
    Share on other sites

  • Topic Author
  • Here is an example with a library providing time and scheduling function + a simple debug,

    and a scene that make use of it.

    Please login or register to see this code.

    and a library scene that looks like this:

    Please login or register to see this spoiler.

     

    Edited by jgab
    Fixed resolving multiple libraries at once, added functions to library
    Link to comment
    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
    Reply to this topic...

    ×   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...