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


Tutorial - Using a Hometable to store device and scene ID's


AutoFrank

Recommended Posts

Guest FredrikKarlsson

Great tutorial @AutoFrank ! 

 

Just a quick addition for the international crowd here. What this scene / script does is create a nested table containing your existing device names.

Therefore, your scene "Start på morgonen" will be encoded as ""Startpåmorgonen" in the table. However, when you try to get the value from it

 

Please login or register to see this code.

will not work.

Please login or register to see this code.

will however work. And, if you have nested some labels with international characters in them:

 

Please login or register to see this code.

 

you can access them like this

 

Please login or register to see this code.

 

to get the '86'.

 

 

Link to comment
Share on other sites

Very nice to put this here for everyone. thank you.

 

Another addition:  you can group the devices by type so you can call all of them at once.  Very useful for roller shutters for example to have them in their own sub table.

 

just add something like

 

Please login or register to see this code.

or anything like this.

 

and to call them in a scene use : 

 

Please login or register to see this code.

 

Now i have a question: how can you get only the devices of one kind - lets say roller shutters - that belong only to a section of the house ?!  I can't find any way to manipulate the sections:( 

Edited by Momos
Link to comment
Share on other sites

Been playing around with the jT table. Since this thread is all about discovering it more, here is my remarks.

 

What if you have 2 scenes running, but read the JT and both write to it at different times. Then at that point you might have changed a setting but is overwritten by another. I presume that is the reason why the original maker used it purely for the id's of the devices and be able to use names instead. A read only makes sense. That being said, there is no real limit on how far you want to go with your json, as example i have a entry which is:

 

Please login or register to see this code.

So the contents doesn't have to be a number, you can use other stuff too (like my pvoutput example) and you can go deeper in the json too. So i can say  jT.users.erik.mac and it will get me my mac, you can even add a "away" yes/no into this json example, but then i got worried about what happens when you have 2 scenes updating it at the same time again :) so i stopped trying to place 'writable' entries in there. Ofcourse you can resolve this my creating seperate json globals..

 

Anyways, this might be of value to see that you can store more in here then just a single line and digits (if it wasn't already spoken about)

Link to comment
Share on other sites

  • Topic Author
  • 8 hours ago, riemers said:

    Been playing around with the jT table. Since this thread is all about discovering it more, here is my remarks.

     

    What if you have 2 scenes running, but read the JT and both write to it at different times. Then at that point you might have changed a setting but is overwritten by another. I presume that is the reason why the original maker used it purely for the id's of the devices and be able to use names instead. A read only makes sense. That being said, there is no real limit on how far you want to go with your json, as example i have a entry which is:

     

    Please login or register to see this code.

    So the contents doesn't have to be a number, you can use other stuff too (like my pvoutput example) and you can go deeper in the json too. So i can say  jT.users.erik.mac and it will get me my mac, you can even add a "away" yes/no into this json example, but then i got worried about what happens when you have 2 scenes updating it at the same time again :) so i stopped trying to place 'writable' entries in there. Ofcourse you can resolve this my creating seperate json globals..

     

    Anyways, this might be of value to see that you can store more in here then just a single line and digits (if it wasn't already spoken about)

     

    HI @riemers

     

    That raises a good point on and one that I have thinking about since I implemented this over the christmas holidays...

    I think your correct in assuming that the original use was a static list of devices that changed very little over time and I agree the use of json encoded tables in predefined variables has many applications and the ability to have nested table makes the 'sky the limit' 

    For me the primary use of my HomeTable is to track my device, vd and scene ID's. I think @ReneNLcode is fantastic for gathering the data and I would have liked to have had that when I created mine. After that I like to maintain my table manually as it is a little different to how my devices, scenes and VD are structured within my HC2 and this is probably what I'll continue to do. I also like the ability to reference the table when I'm writing new scenes or vd and for this reason I have a master copy that I keep with all the rest of my code base. When I want to update the table I modify that copy and then upload it using my scene.

     

    I have recently created a second table that tracks state. I originally had some of these in my HomeTable ('isPlaying' and  'nowPlaying' for my music in each room) but when I update my device/vd/scene ID's I didn't want to overwrite this state information. My new table called StateTable is tracking some music states, light level (dark or light) , whether its occupied or not as well as which on my devices are online of not. I plan to use this table for any dynamic conditions that can be naturally grouped.

     

    This is what the table structure looks like so far, Its a bit rough but should give the idea....

    Please login or register to see this code.

     

    Link to comment
    Share on other sites

    The only way you can be sure that things will be "ok" if you use that global timer scene for example. Then add all the thing you need to trigger in there so that once it updates, it only updates the status from one place. In reality this could be pretty hard. Too bad you can't pass arguments to scene's otherwise you could create a scene that says update global, but when this scene is running sleep and reread the table. You can always make globals jsons per room to minify the chance this happens. Or just make sure you only have a few scripts running so that you know the chance is pretty low. Anyways, chance it happens is tiny i would think. I have not read people with this problem. Just make sure that when you write a scene, you do your stuff like http calls etc, THEN read the json table and update it. Don't read the json, then do http calls and then write it, because then it makes it more likely to fall in this issue.

    Link to comment
    Share on other sites

  • Topic Author
  • 2 minutes ago, riemers said:

    The only way you can be sure that things will be "ok" if you use that global timer scene for example. Then add all the thing you need to trigger in there so that once it updates, it only updates the status from one place. In reality this could be pretty hard. Too bad you can't pass arguments to scene's otherwise you could create a scene that says update global, but when this scene is running sleep and reread the table. You can always make globals jsons per room to minify the chance this happens. Or just make sure you only have a few scripts running so that you know the chance is pretty low. Anyways, chance it happens is tiny i would think. I have not read people with this problem. Just make sure that when you write a scene, you do your stuff like http calls etc, THEN read the json table and update it. Don't read the json, then do http calls and then write it, because then it makes it more likely to fall in this issue.

     

    agreed

    I've a lot of issues trying to sequence http calls and have now divided them into smaller chunks and they work very reliably

     

    My plan is to sue a number of VD's to update the state tabel - one for motion, one for lux, one for music states, etc

    I think the chances of a "read" conflicting with a "write" for the same parameter are slim as you say but only time will tell. I can always splitthe state table into smaller chunks if needs be

     

     

     

    Link to comment
    Share on other sites

    I guess my question got lost in all the information exchanged.  Would you happen to know how to manipulate the sections, as in get the devices of one kind that belong in a section of the house.

    The goal would be to automatically add a subtable with all PIRs from each section of the house for example.

     

    Thank you

    Link to comment
    Share on other sites

  • Topic Author
  • 47 minutes ago, Momos said:

    I guess my question got lost in all the information exchanged.  Would you happen to know how to manipulate the sections, as in get the devices of one kind that belong in a section of the house.

    The goal would be to automatically add a subtable with all PIRs from each section of the house for example.

     

    Thank you

     

    Hi @Momos

     

    definitely not a single threaded discussion :-)

     

    I can think of 2 possible ways to solve that one...

    1) when the table is being created you group all these like types into one table group- at execution time you could step through the group to get the devices

     2) Use smart naming - living_room.blinds, kitchen.blinds, etc. This would enable you to step through the table to get all the devices of type blinds by matching strings...

     

    I have structured my table a little like this

    The main light in all mu rooms rooms is called light, same with humidity, lux, temp, isPlayng (music), etc

    This means that I'll be able to step through the table and check all motion (for occupancy), all lights (to switch off during daylight), etc

     

    There are probably other ways to achieve this...

     

    Link to comment
    Share on other sites

    Yup. They already have 'smart' names like living.xxx.xxx but there is no room to make names even longer.  Besides rooms, there are also the sections- for example i have defined section 1 ground floor, section 2 first floor, section 3 third floor.

    I know you can get through the api the section number to which a certain device belongs to.  But i'd like the reverse: to automatically make the table with all the PIRs in section 1 and all the blinds in section 1. 

    I have these tables set up now manually. Was wondering if there is any way to do it automatically.

     

    Another piece of info which might be of interest. I used yo have naming just like you do.  Each room had, light, temp, radiator and so on.  And from time to time i would have a blind close/open on its own, a wall plug turning on/off without any exterior input.  That happened like forever, since i got the HC2. 

    About 2 months ago i renamed every device differently, even if they belong to different rooms.  Strangely enough, The random power on/off or open/close is gone. Coincidence or not , just wanted to share.

    Link to comment
    Share on other sites

  • Topic Author
  • 22 minutes ago, Momos said:

    up. They already have 'smart' names like living.xxx.xxx but there is no room to make names even longer.  Besides rooms, there are also the sections- for example i have defined section 1 ground floor, section 2 first floor, section 3 third floor.

    I know you can get through the api the section number to which a certain device belongs to.  But i'd like the reverse: to automatically make the table with all the PIRs in section 1 and all the blinds in section 1. 

    I have these tables set up now manually. Was wondering if there is any way to do it automatically.

     

    Hi @Momos

     

    You could do tables inside tables to get a extra number of levels

    House

    -----> Floors

         -----> Rooms

              -----> Devices

     

    and perhaps use two levels of processing to achieve thie

    On pass using @ReneNL script to create the first table and a second pass using a modified script to create the extra nested levels

    There might even be a way to modify the ReneNL script to do it all in one go.

    Edited by AutoFrank
    Link to comment
    Share on other sites

  • Topic Author
  • 21 minutes ago, Momos said:

    Another piece of info which might be of interest. I used yo have naming just like you do.  Each room had, light, temp, radiator and so on.  And from time to time i would have a blind close/open on its own, a wall plug turning on/off without any exterior input.  That happened like forever, since i got the HC2. 

    About 2 months ago i renamed every device differently, even if they belong to different rooms.  Strangely enough, The random power on/off or open/close is gone. Coincidence or not , just wanted to share.

     

    Interesting .. I'll keep this on mind in case I get some gremlins :-)

     

    thanks

     

    Link to comment
    Share on other sites

    Sorry, newbie here... It seems it does not populate the variable HomeTable for me, it just shows "Value 1"? I've removed and re-created the variable a couple of times before running the population scene, but without luck. Is there some scene names or VD's that must be created before running the scene?

    If I run the scene below (I've emptied the jsonHome in the beginning of the code), it throws error "[DEBUG] 13:51:04: line 60: attempt to index field 'scene' (a nil value). Indicating the line in the code "log(jT.scene.MainScene)". If I remove that line I get no error, but it still don't populate HomeTable.
     
    As it works for others, I miss/don't understand something here. Can you you help please? This is the code:
     
    --[[
    %% autostart
    %% properties
    %% events
    %% globals
    --]]
    local debug = true --set to false to stop debug messages
    -- HOME TABLE FOR ANYTHING IN ADDITION TO DEVICES, VDs, iOS DEVICES
    -- EDIT TO YOUR NEEDS OR KEEP BLANK: jsonHome = {}
    jsonHome = {}
    -- NO USER EDITS NEEDED BELOW
    local function log(str) if debug then fibaro:debug(str); end; end
    devices=fibaro:getDevicesId({visible = true, enabled = true}) -- get list of all visible and enabled devices
    log("Fill hometable with "..#devices.." devices")
    -- FILL THE HOMETABLE WITH ALL VDs, DEVICES AND iOS DEVICES
    for k,i in ipairs(devices) do
     deviceName=string.gsub(fibaro:getName(i), "%s+", "") -- eliminate spaces in devicename
     
     if fibaro:getType(i) == "virtual_device" then -- Add VDs to Hometable
      if jsonHome.VD == nil then -- Add VD to the table
       jsonHome.VD = {} 
      end
      jsonHome.VD[deviceName]=i
      log("i="..i..", type="..fibaro:getType(i)..", device="..deviceName)
     elseif fibaro:getType(i) == "iOS_device" then -- Add iOS devices to Hometable
      if jsonHome.iOS == nil then -- Add iOS devices to the table
       jsonHome.iOS = {} 
      end
      jsonHome.iOS[deviceName]=i
      log("i="..i..", type="..fibaro:getType(i)..", device="..deviceName)
     else -- Add all other devices to the table
      roomID = fibaro:getRoomID(i)
      if roomID == 0 then
       roomname = "Unallocated"
      else
       roomname=string.gsub(fibaro:getRoomName(roomID), "%s+", "") -- eliminate spaces in roomname
      end
      if jsonHome[roomname] == nil then -- Add room to the table
       jsonHome[roomname] = {} 
      end
      jsonHome[roomname][deviceName]=i
      log("i="..i..", type="..fibaro:getType(i)..", device="..deviceName..", room="..roomname)
     end
    end
    jHomeTable = json.encode(jsonHome)    -- ENCODES THE DATA IN JSON FORMAT BEFORE STORING
    fibaro:setGlobal("HomeTable", jHomeTable)   -- THIS STORES THE DATA IN THE VARIABLE
    log("global jTable created:")     -- STANDARD DEBUG LINE TO DISPLAY A MESSAGE
    log(jHomeTable)
    -- I then like to read back a entry from the table to show that the table didnt get corrupt in the process.
    local jT = json.decode(fibaro:getGlobalValue("HomeTable"))  -- REFERENCE TO DECODE TABLE
    log(jT.scene.MainScene)      -- DISPLAY ONE VARIALE

     

     

    Link to comment
    Share on other sites

  • Topic Author
  • 12 minutes ago, robw said:
    Sorry, newbie here... It seems it does not populate the variable HomeTable for me, it just shows "Value 1"? I've removed and re-created the variable a couple of times before running the population scene, but without luck. Is there some scene names or VD's that must be created before running the scene?

    If I run the scene below (I've emptied the jsonHome in the beginning of the code), it throws error "[DEBUG] 13:51:04: line 60: attempt to index field 'scene' (a nil value). Indicating the line in the code "log(jT.scene.MainScene)". If I remove that line I get no error, but it still don't populate HomeTable.
     
    As it works for others, I miss/don't understand something here. Can you you help please? This is the code:
     
    --[[
    %% autostart
    %% properties
    %% events
    %% globals
    --]]
    local debug = true --set to false to stop debug messages
    -- HOME TABLE FOR ANYTHING IN ADDITION TO DEVICES, VDs, iOS DEVICES
    -- EDIT TO YOUR NEEDS OR KEEP BLANK: jsonHome = {}
    jsonHome = {}
    -- NO USER EDITS NEEDED BELOW
    local function log(str) if debug then fibaro:debug(str); end; end
    devices=fibaro:getDevicesId({visible = true, enabled = true}) -- get list of all visible and enabled devices
    log("Fill hometable with "..#devices.." devices")
    -- FILL THE HOMETABLE WITH ALL VDs, DEVICES AND iOS DEVICES
    for k,i in ipairs(devices) do
     deviceName=string.gsub(fibaro:getName(i), "%s+", "") -- eliminate spaces in devicename
     
     if fibaro:getType(i) == "virtual_device" then -- Add VDs to Hometable
      if jsonHome.VD == nil then -- Add VD to the table
       jsonHome.VD = {} 
      end
      jsonHome.VD[deviceName]=i
      log("i="..i..", type="..fibaro:getType(i)..", device="..deviceName)
     elseif fibaro:getType(i) == "iOS_device" then -- Add iOS devices to Hometable
      if jsonHome.iOS == nil then -- Add iOS devices to the table
       jsonHome.iOS = {} 
      end
      jsonHome.iOS[deviceName]=i
      log("i="..i..", type="..fibaro:getType(i)..", device="..deviceName)
     else -- Add all other devices to the table
      roomID = fibaro:getRoomID(i)
      if roomID == 0 then
       roomname = "Unallocated"
      else
       roomname=string.gsub(fibaro:getRoomName(roomID), "%s+", "") -- eliminate spaces in roomname
      end
      if jsonHome[roomname] == nil then -- Add room to the table
       jsonHome[roomname] = {} 
      end
      jsonHome[roomname][deviceName]=i
      log("i="..i..", type="..fibaro:getType(i)..", device="..deviceName..", room="..roomname)
     end
    end
    jHomeTable = json.encode(jsonHome)    -- ENCODES THE DATA IN JSON FORMAT BEFORE STORING
    fibaro:setGlobal("HomeTable", jHomeTable)   -- THIS STORES THE DATA IN THE VARIABLE
    log("global jTable created:")     -- STANDARD DEBUG LINE TO DISPLAY A MESSAGE
    log(jHomeTable)
    -- I then like to read back a entry from the table to show that the table didnt get corrupt in the process.
    local jT = json.decode(fibaro:getGlobalValue("HomeTable"))  -- REFERENCE TO DECODE TABLE
    log(jT.scene.MainScene)      -- DISPLAY ONE VARIALE

     

     

     

    Hi @robw

    In the predefined variable panel you wont see the data

     

    The read-back for Maine Scene will only run if you have a scene called "Main Scene"

    You could replace that with a scene that you know exist on your HC2

     

    If it runs successfully you should see the output in the console/debug window

     

    If you correct the scene it checks with a scene that exists on your system (remember its case sensitive)

     

    Could you send on a screen shot of the debug window after you run the scene 

    I suspect it is running successfully

     

    ( I can't log into my system to get a screenshot at the moment as they appear to have changed to the new login and I haven't run the wizard yet) 

    Link to comment
    Share on other sites

    Ok, so the HomeTable showing "Value 1" is correct?

    I tested doing an empty LUA scene named "MainScene" (Scene ID=106), and adding it to the jsonHome so it is like this:

    jsonHome = {MainScene=106}

    Then I have the last line in the scene:

    log(jT.scene.MainScene) 

    When running like above, the Debug windows says it fill HomeTable with 92 devices, and it lists devices and rooms, and on the last line I get error: "[DEBUG] 14:29:23: line 60: attempt to index field 'scene' (a nil value).

     

    If I remove the last line, log(jT.scene.MainScene), the debug gives no errors. It says it fills HomeTable with 92 devices like above. The HomeTable shows "Value 1". But I guess that is ok, then?

     

    Link to comment
    Share on other sites

  • Topic Author
  • 11 minutes ago, robw said:

    Ok, so the HomeTable showing "Value 1" is correct?

    I tested doing an empty LUA scene named "MainScene" (Scene ID=106), and adding it to the jsonHome so it is like this:

    jsonHome = {MainScene=106}

    Then I have the last line in the scene:

    log(jT.scene.MainScene) 

    When running like above, the Debug windows says it fill HomeTable with 92 devices, and it lists devices and rooms, and on the last line I get error: "[DEBUG] 14:29:23: line 60: attempt to index field 'scene' (a nil value).

     

    If I remove the last line, log(jT.scene.MainScene), the debug gives no errors. It says it fills HomeTable with 92 devices like above. The HomeTable shows "Value 1". But I guess that is ok, then?

     

     

    Okay - I think I may see what the problem might be 

     

    what room is the 'MainScene' located in on your system ?

    the scene (in bold) part of the  jT.scene.MainScene reference will be the room on your system where the MainSceneis saved. Since it is auto-generated (not unless you have room scalled scene that contains the MainScene scene)

     

    ... if that makes sense

     

     

     

     

     

    Edited by AutoFrank
    Link to comment
    Share on other sites

    So in my case, jT.System.MainScene? Then the Debugs last line is: [DEBUG] 15:02:27:nil

    Link to comment
    Share on other sites

  • Topic Author
  • 1 minute ago, robw said:

    So in my case, jT.System.MainScene? Then the Debugs last line is: [DEBUG] 15:02:27:nil

     

    getting closer... :-)

     

    Do the upper/lower cases match for whats  in your HC and what you have above ??

     

    Any other approach  - could you run it with put the line that is giving you the error

     

    The last line of debug should the table - it'll start with {{

    Copy from there to the end (I find it tricky so I press CRTL, select the test with a cursor and hit C quickly

     

    Open up 

    Please login or register to see this link.

     and paste into box and submit

    This gives a cleaner representation of the table that was created and stored

    Copy from the prettyprint result window and drop into this post

    This will help us understand what is actually being stored

     

    I know that @ReneNL code work as I ran it on my system on HomeTable1 (as I didn't want to overwrite my own table) and it worked first time

    It's probably something small at thispoint ..

    Link to comment
    Share on other sites

    ** EDIT**

    Please login or register to see this code.

     

    Please login or register to see this code.

     
    Edited by robw
    Link to comment
    Share on other sites

  • Topic Author
  • 4 minutes ago, robw said:

    Yes, it is probably something small and stupid I'm doing wrong :oops:, but glad you help!


    I've stored the "MainScene" and your populating scene, that I call "Make HomeTable" in the Room "System".

     

    Typical Debug line adding devices: [DEBUG] [time]: i=294, type=com.fibaro.FGWP101, device=SubwooferWP, room=USLivingroom

    After adding all devices it starts with the table:

    [DEBUG] [time]: global jTable created:

    [DEBUG] [time]: {GFComputerroom":{"Ceilinglamp":61},"GFBedroom":{"Alarmsensor":205 ...(and so on...)

    [DEBUG] [time]: nil

     

    I did copy & paste the whole debug log into jsonprettyprint.com and pressed the button, and then I just get:

    null

    in the result window.

     

    Well, my head feels like the result now :)

     

    no worries.. a lot of people helped me and continue too so nice to give back :-)

     

    The part to copy to prettyprint is the part in bold below

     

    [DEBUG] [time]: {GFComputerroom":{"Ceilinglamp":61},"GFBedroom":{"Alarmsensor":205 ...(and so on...)

    Correct ?

     

    I must admit the format looks a bit different ( I would have expected Ceilinglamp=61 and not Ceilinglamp:61)

    Could you paste what you got in the debug window directly here (instead of prettyprint) ?

    Am I correct in assuming that you didn't modify @ReneNL scene ?

     

    Could you also copy that and post that as well .. perhaps something went amuck there ?

     

     

     

     

    Link to comment
    Share on other sites

    If you have:

     

    Please login or register to see this code.

     

    in your home table, the ouput would be jT.GFComputerroom.Ceilinglamp which would return 61.

    Look at the logic of the json, then you know how to write the jT part.

     

    Your first example:

     

    jsonHome = {MainScene=106}

    Would be then jT.MainScene which would return 106.

     

    Just trying to show you the logic a bit behind it ;)

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