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


  • 0

How to communicate between VD button lua code and main loop


Question

Posted (edited)

Let's say I have thermostat device, main loop queries temperature from the sensor and turns the heater on/off based on the temperature.

Also there is button configured VD that switches temperature control on/off so that if the VD is in off state it would not turn on heater event if the temperature goes down.

on/off state needs to be stored somewhere.  I do not like having a global variable for it since it is internal state of VD and it makes sense to keep it private for VD.

But I failed to find any way to set some value from button lua that mainloop lua will have access to...

Edited by [email protected]

16 answers to this question

Recommended Posts

  • 0
Posted

Just store the value in a label ?

  • 0
Posted

@[email protected] 

@ojc absolutely correct. You can use the label  as some kind of global variable.

In "button" code update the label

Please login or register to see this code.


Now you can read the value "ON" at main loop

Please login or register to see this code.

 

  • 0
  • Inquirer
  • Posted

    yep this might work, but there is no way to hide the label. If VD has several state variables, VD will look messy...

    • 0
    Posted (edited)

    Not exactly... you can use same label for several variables, just use some separator that you can extract the data in main loop

    for example:

    Set label to ON|YES|12

    Now get the label and extract the information by using string.match() function. You can do it in a loop with few lines only.

    One label could hold a lot of information, but if the label is long, you won't see all of it on display. But the data is there.

    By the way same label could be update from any button. 

    If you don't want to see the label at VD, don't use header and format the string with black color. Way to hide the label

     

    Edited by cag014
    • 0
  • Inquirer
  • Posted

    Does not look like a clean solution , but it solves my issue, thank you

    • 0
    Posted

    By the way, on second thought you can actually save entire json table, much easier to encode/decode.

    For example:

    testVal = { mode=1,tst=2,light="test"}
    fibaro:call(fibaro:getSelfId(), "setProperty", "ui.Label1.value", json.encode(testVal))
    jTst=json.decode(fibaro:getValue(fibaro:getSelfId(), "ui.Label1.value"))
    fibaro:debug(jTst.mode .. jTst.tst .. jTst.light)

     

    Now you can have as many as variables you need without extra work, standard jSon table

     

    • 0
    Posted

    I use json.encode to store a complete table in the global variables. This way, you can pass on multiple values to other scripts.

     

    I use this to have the following functions:

    * A script that writes a master table with global configurations in

    * VD that calculates the position of the sun in the sky, relative to my house

    * VD that fetches the weather and a 5 day forecast

    * VD that checks the devices on the network (and the number of users that are home)

    * ...

     

    Al this data is generated by a script under an 'Update' button, the main loop presses that button regularly (so a bug doesn't stop the loop like a scene with a do action sleep loop).

    The result is stored in Global Variables and can be used by any other script and even by the main loop. (Keep in mind that the main loop and the button code probably run in parallel)

     

    • 0
    Posted
    3 godziny temu, sirKitKat napisał:

    I use json.encode to store a complete table in the global variables. This way, you can pass on multiple values to other scripts.

     

    I found it very practical too. Less global variables. 

    I have a VD for building (default values) and testing my JSON variables. If something is wrong with the JSON I get the PUSH notification. 

     

    How do you handle race conditions with that way of storing data? I mean when two scripts operates on the same JSON. When you decode the JSON in one script and before you make a changes and save it back to the global variable another script wants to do the same and it operates on the old data and what is even worse it overwrites previous changes (from the first script). 

    • 0
  • Inquirer
  • Posted (edited)

     

    4 hours ago, sirKitKat said:

    I use json.encode to store a complete table in the global variables. This way, you can pass on multiple values to other scripts.

     

    I use this to have the following functions:

    * A script that writes a master table with global configurations in

    * VD that calculates the position of the sun in the sky, relative to my house

    * VD that fetches the weather and a 5 day forecast

    * VD that checks the devices on the network (and the number of users that are home)

    * ...

     

    Al this data is generated by a script under an 'Update' button, the main loop presses that button regularly (so a bug doesn't stop the loop like a scene with a do action sleep loop).

    The result is stored in Global Variables and can be used by any other script and even by the main loop. (Keep in mind that the main loop and the button code probably run in parallel)

     

    2

    Never knew that global variable may store anything but integer or enum value. Looks like it is just UI check. Thanks for pointing this out

    1 hour ago, Jacławiciel said:

     

    I found it very practical too. Less global variables. 

    I have a VD for building (default values) and testing my JSON variables. If something is wrong with the JSON I get the PUSH notification. 

     

    How do you handle race conditions with that way of storing data? I mean when two scripts operates on the same JSON. When you decode the JSON in one script and before you make a changes and save it back to the global variable another script wants to do the same and it operates on the old data and what is even worse it overwrites previous changes (from the first script). 

    Guess there should be one owner script that edits and the rest just read the value.  Global vars are high-level concept so it should not be possible to read partially changed value consumer script will just get the value before or after it is changed by the owner.  

     

     

    Edited by [email protected]
    • 0
    Posted (edited)
    3 hours ago, [email protected] said:

     

    Never knew that global variable may store anything but integer or enum value. Looks like it is just UI check. Thanks for pointing this out

     

     

    sure, one can use them, the only problem remains on UI interaction, when you change manually (from UI) any variable and save it, your non numeric variable will get killen and NaN will get stored. Therefore i don't like it.

     

    But there is something else what can be used, every device have property "userDescription"

     

     

    Edited by tinman
    • Like 1
    • 0
    Posted
    3 godziny temu, [email protected] napisał:

    Guess there should be one owner script that edits and the rest just read the value.  Global vars are high-level concept so it should not be possible to read partially changed value consumer script will just get the value before or after it is changed by the owner.  

     

    Sure, there is no partial reading of a global variable but when you read a global that holds a json then you make a copy of it, decode, do some stuff, encode, and save it back to the variable. In the meantime other script could do the same and we have a race condition. 

    • 0
    Posted
    24 minutes ago, Jacławiciel said:

     

    Sure, there is no partial reading of a global variable but when you read a global that holds a json then you make a copy of it, decode, do some stuff, encode, and save it back to the variable. In the meantime other script could do the same and we have a race condition. 

    Had same issue, so have defined another global variable which used as flag. Before changing json, you need to check if this variable is 0.

    Once it zero, you set the variable to 1, changing json, saving and then set back the variable to 0.

     

    • 0
  • Inquirer
  • Posted
    12 hours ago, Jacławiciel said:

     

    Sure, there is no partial reading of a global variable but when you read a global that holds a json then you make a copy of it, decode, do some stuff, encode, and save it back to the variable. In the meantime other script could do the same and we have a race condition. 

    Key point is to write variable only from one script/vd/scene.  Lock emulation as

    Please login or register to see this link.

     suggests reduces probability of race condition rather than protects from it.

     

    1. Global var should be changed by single scene/vd  (split your var to 2 or more to achieve it)

    2. owning scene/vd should ensure that there is only one instance of it e.g. with fibaro:countScenes()

    3. If there is real need to write from multiple places - delegate writing to woning scene/VD rather than writing directly

      

     

     

    • 0
    Posted

    I have a presence main scene that is responsible for setting users presence. Presence is checked by the Raspberry Pi (there are a couple of them, big home). Pi is looking for the beacon in range. When beacon is found it sends a POST request with parameters passed in - found user, beacon, location etc. 

    I save the data about user presence in one JSON because there is too much data for seperate globals. Every user has a table with locations state in/out and more... And it is much easier to make changes, add new users. Imagine that two users enter the house. Separate JSONs could solve it. But... Imagine that user enters two or more zones and two POST are send to my scene at the same time. Presence in one of the locations won't be saved possibly. 

     

    @cag014 suggestion seems to be the best for me at this time. Thanks! 

    • 0
  • Inquirer
  • Posted (edited)

    You could use something like the following to handle posts sequentially:

     

    Please login or register to see this code.

     

    Edited by [email protected]
    • 0
    Posted
    11 hours ago, [email protected] said:

    Key point is to write variable only from one script/vd/scene.  Lock emulation as

    Please login or register to see this link.

     suggests reduces probability of race condition rather than protects from it.

    This lock mechanize provides full proof, you cannot change the variable till the lock releases.

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