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


AutoFrank

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

Recommended Posts

Ok, here is my full scene, "Make HomeTable".

 

--[[
%% 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 = {MainScene=106}
-- 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.System.MainScene)      -- DISPLAY ONE VARIALE
 
-------
 
Here is parts of Debug (not pasting every device):
 
[DEBUG] 15:02:26: i=304, type=com.fibaro.FGWP101, device=NVidiaShield WP, room=USLivingroom
[DEBUG] 15:02:27: i=305, type=virtual_device, device=Sunrise&Sunsetv1.2
[DEBUG] 15:02:27: global jTable created:
[DEBUG] 15:02:27: {"GFComputerroom":{"Ceilinglamp":61},"GFBedroom":{"Alarmsensor":205,"TemperatureSensor":206,   **** And so on ****
[DEBUG] 15:02:27: nil    **** The last line ****

Share this post


Link to post
Share on other sites

System is something that does not exist in above lua.

 

Try:  log(jT.GFComputerroom.Ceilinglamp)  

Edited by riemers
remove whitespace

Share this post


Link to post
Share on other sites
  • Topic Author
  • 4 minutes ago, robw said:

    Ok, here is my full scene, "Make HomeTable".

     

    --[[
    %% 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 = {MainScene=106}
    -- 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.System.MainScene)      -- DISPLAY ONE VARIALE
     
    -------
     
    Here is parts of Debug (not pasting every device):
     
    [DEBUG] 15:02:26: i=304, type=com.fibaro.FGWP101, device=NVidiaShield WP, room=USLivingroom
    [DEBUG] 15:02:27: i=305, type=virtual_device, device=Sunrise&Sunsetv1.2
    [DEBUG] 15:02:27: global jTable created:
    [DEBUG] 15:02:27: {"GFComputerroom":{"Ceilinglamp":61},"GFBedroom":{"Alarmsensor":205,"TemperatureSensor":206,   **** And so on ****
    [DEBUG] 15:02:27: nil    **** The last line ****

     

    okay try this, change only to second last line

     

    Please login or register to see this code.

     

    Share this post


    Link to post
    Share on other sites

    Ahhh... Then it gives result:

    [DEBUG] [time]: 61

    Which indeed is it's number :) Thank's!

    Share this post


    Link to post
    Share on other sites
  • Topic Author
  • Just now, robw said:

    Ahhh... Then it gives result:

    [DEBUG] [time]: 61

    Which indeed is it's number :) Thank's!

     

    Success !!! :-)

     

    So the table is being created and you can now use it.

     - Watch the case sensitivity when referencing table elements, it has to match exactly..

     

    It might be worth keeping a full copy of the table in something like Notepad++ or your editor of choice

    That will make it easier to reference when writing new code

     

    happy coding ..

    -f

     

     

     

    Share this post


    Link to post
    Share on other sites

    Thank's a lot @AutoFrank, @riemers

    Next step: node-sonos-api or HomeKit on my new Pi 3. That will have to wait til the weekend, though :)

    Share this post


    Link to post
    Share on other sites
  • Topic Author
  • Just now, robw said:

    Thank's a lot @AutoFrank, @riemers

    Next step: node-sonos-api or HomeKit on my new Pi 3. That will have to wait til the weekend, though :)

     

    that a great thing about HA.. never short of challenges .. just time :-)

     

    Share this post


    Link to post
    Share on other sites

    @robw Going bit offtopic, but might i suggest you use docker for that. Some nas systems include docker too (synology) from the gui. Using docker is easy and simple to give to someone else too, work on Pi3 too. For node-sonos-api there is a docker image 

    Please login or register to see this link.

     saves you the hassle of installing all dependency's, assuming you have some knowledge with linux.

    Share this post


    Link to post
    Share on other sites
  • Topic Author
  • 5 minutes ago, robw said:

    Thank's a lot @AutoFrank, @riemers

    Next step: node-sonos-api or HomeKit on my new Pi 3. That will have to wait til the weekend, though :)

     

    BTW - there is some info on Sonos-node-api here which may help

    Please login or register to see this link.

    Share this post


    Link to post
    Share on other sites
    2 hours ago, riemers said:

    @robw Going bit offtopic, but might i suggest you use docker for that. Some nas systems include docker too (synology) from the gui. Using docker is easy and simple to give to someone else too, work on Pi3 too. For node-sonos-api there is a docker image 

    Please login or register to see this link.

     saves you the hassle of installing all dependency's, assuming you have some knowledge with linux.

     

    Thank you! I will test the docker version :)

     

    Cheers,

    Share this post


    Link to post
    Share on other sites
    2 hours ago, AutoFrank said:

     

    BTW - there is some info on Sonos-node-api here which may help

    Please login or register to see this link.

     

    Thank's! I will spend time reading about it, and implementing it :)

     

    Cheers,

    Share this post


    Link to post
    Share on other sites
  • Topic Author
  • 3 hours ago, robw said:

     

    Thank's! I will spend time reading about it, and implementing it :)

     

    Cheers,

     

    Good luck with it :-)

     

    Share this post


    Link to post
    Share on other sites

    Please login or register to see this link.

    Wow, nice to see so much traction on this post/thread!

    @Momos, sorry have been away/busy, but your question to add section info triggered some more elaborate thoughts and suggestions, in addition to the comments from @AutoFrank

    9 hours ago, Momos said:

    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.

     

    1. Although it does not solve your ‘section’ request, there is also a nice new LUA function you can call to get the device ids for a filtered set of devices: fibaro:getDevicesId. These have nothing to do with this whole HomeTable concept, but may be an easy way to make some custom selections you need for your purpose. See the below code as an example of how you could use this:

      Please login or register to see this code.

      Be aware that the filters act as an AND operator, so you cannot select e.g. multiple rooms in one go (e.g. if you change the line to roomID = {4,5} you get an empty table as a return as no devices are in both rooms). So this does not help for your section challenge…
    2. The other option is to use the API command to extract the section information, as you indicated. See the post below for a python script which could be adapted to include section fields (through the <hc2>/api/sections commands)

      Please login or register to see this link.

    3. …But your ask was if one could do this in the LUA script. Not so easily…but I got there in the end :-). The only section related info you can extract with the fibaro LUA commands (i.e. not using the API) is to extract the section ID: fibaro:getsectionID(deviceID). So, some manual configuration is needed to map the sectionIDs to the section names you prefer in your hometable. I had a stab at it, see the code below, hope this is in line with your needs. The mapping is done in the sectionNames table which you need to update to your situation. Also you need to list all the deviceTypes in your system, it will throw an error if one is missing:

      Please login or register to see this code.

       

    4. As a further thought: nothing stops you to have the same device ID in multiple branches of your hometable. What I mean is that you can combine the ‘room-->devicename-->deviceID’ structure from my original script (in the first post) with the ‘section-->type-->dvicename-->deviceID’ structure from this script to get a more extended table to have the best of both worlds. Just combine the two scripts to get a more extended table with room-->devicename-->deviceID as well as section-->type-->deviceName-->deviceID

    Best, Rene.
     

    Share this post


    Link to post
    Share on other sites

    Rene, I think this is exactly what i was looking for. Thank you.  Will try it and confirm in about 10 days when i get back home.

     

     

    Share this post


    Link to post
    Share on other sites

    Good to hear, and thanks for the challenge/request ;-). Indeed, please let me know if this work well for you.

    Share this post


    Link to post
    Share on other sites

    Hmm.  Is there a length restriction on a global variable?  The jHomeTable looks right (see below, I have added line breaks for ease of reading. I have inspected it in Visual Studio and it is syntactically correct LUA), but jT=nil in the second last line.  No variable gets created in the Variables Panel.

     

    EEDIT:  Solved it (I think) the problem is in having rooms or devices like "Boy's Room".  The apostrophe (') is maybe treated as the end of the string?

    Please login or register to see this code.

     

    Edited by codowd
    Formatting code block

    Share this post


    Link to post
    Share on other sites
  • Topic Author
  • 11 minutes ago, codowd said:

    Hmm.  Is there a length restriction on a global variable?  The jHomeTable looks right (see below, I have added line breaks for ease of reading. I have inspected it in Visual Studio and it is syntactically correct LUA), but jT=nil in the second last line.  No variable gets created in the Variables Panel.

     

    Please login or register to see this code.

     

     

    It looks like there is something wrong with the formating that may be related to the spacing you added.

    I dropped you string into a json pretify site that makes it a bit more readable and it didn't recognise it as json)

    I'll take a closer look...

    one moment..

     

     

     

     

    Share this post


    Link to post
    Share on other sites
  • Topic Author
  • 43 minutes ago, codowd said:

    Hmm.  Is there a length restriction on a global variable?  The jHomeTable looks right (see below, I have added line breaks for ease of reading. I have inspected it in Visual Studio and it is syntactically correct LUA), but jT=nil in the second last line.  No variable gets created in the Variables Panel.

     

    EEDIT:  Solved it (I think) the problem is in having rooms or devices like "Boy's Room".  The apostrophe (') is maybe treated as the end of the string?

    Please login or register to see this code.

     

     

    I was thinking the same and you could try and remove them but I don't think that's the issue as they are enclosed in quotes.

    Was this generated using ReneNL code ?

     

    EDIT - just saw you thought you solved it

    Did removing the quote solve the problem ?

     

     

    Edited by AutoFrank

    Share this post


    Link to post
    Share on other sites

    I wonder, is it possible to create a function in a json table? In theory you could put a function you use in more then 1 place in the json. Then read it out, just don't know how to make a function based on that. You cant just say "function jT.function.something" perhaps you can with (), but you would want the have the name and the function in the json.

    Share this post


    Link to post
    Share on other sites

    I can confirm that the code in the first post will not work if the name of any device or room contains an apostrophe (') even though it encloses the apostrophe in quotes (").  You can see this if you just type the following line into the HC2 LUA editor:

    Please login or register to see this code.

     

    The syntax colour changes after the second apostrophe, indicating the quote finishes there, understandably.  This line is correct LUA:

    Please login or register to see this code.

    So each string needs to be searched and replaced for apostrophes. The function required is 

    Please login or register to see this code.

    The following line changes will work (just replace the single string.gsubs with the nested versions

    Please login or register to see this code.

     

    Edited by codowd

    Share this post


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