AutoFrank 363 Share Posted January 6, 2017 (edited) Hi, This tutorial is based on an idea that i believe originated to @cag014 some time back and has been adopted by many. So well deserved kudos to @cag014 and others that helped originate and develop the concept. I am merely a scribe that has benefited from this and wanted to share the process I used. Special thanks to @ReneNL who provided the part of the scene that searches through you HC and parses/formats the table before saving. I decided to write a quick tutorial for two reasons... I implemented this over christmas and and found it very useful and much easier than I thought It would appear that we have some new forum members that got HC2 devices from Santa The core of this approach is to store all the reference ID's to your devices, virtual devices, scenes, etc in a json encoded table. The references like jT.kitchen.light are used in the scene or vd and device ID can easily be changed in the table. One important benefit is that it you need to exclude/include a device the device ID will change. With this approach you simple change the reference in the Home table and your done. Without this approach you wll need to go through your code and change the device ID where appropriate. ** This doesn't get over the need to enter ID as triggers in the scene headers as fibaro doesn't allow variable in the header ** The solution has two parts to it. The home table itself where the data is stored. - this is held in a predefined variable (lower part of variables panel) The references in your scenes and virtual devices use this table HOME TABLE This can be created and maintained through either a scene or a virtual device. Edit: I use a scene with %% autostart. This allows the table to be reloaded after a HC2 restart in addition to saving the scene. (thanks @Sankotronic ) Go to Panel, Variables Panel and create a new predefined variable (lower part of panel) called HomeTable. When you create a predefined variable it has two values. Name the variable and save. Edit the variable and simply delete the second value. When working with the variables panel please DON'T use the save button on the right side. It can corrupt other variables. Using either a scene or a vd create your table with your data and store it. This is lua from the scene. The top part shows the format of the table. I opted to place each element I am looking to store into rooms and/or other natural groupings but you can choose any way to structure. I'll attached a copy of my full table at the end of this to show what I use it for. The next part encodes and stores the data The last part is where I read back one entry to show the table stored okay. --[[ %% 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 = { scene = { MainScene=614,AlarmControl=598,rebootHC2=593,goodMorning=463,goodNight=331,LeavingHome=483,welcomeHome=488,quietMorning=499,kidsToBed=490,plaroomTvOn=580,firstFloorMusicOn=579,firstFloorAllOff=578, hallSceneControl=519,StairsLight30=556,GateOpen5=526,GateOpenHold=361,GateOpenClose=425,DumpEventLog=565,PlayroomOff=617 }, users = { admin=2,frank=1564,sylvia=1565 }, } -- 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 -- Uncomment this to eliminate all non-alphanumeric characters in devicename -- deviceName=string.gsub(fibaro:getName(i), "%W", "") 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 -- Uncomment this to eliminate all non-alphanumeric characters in roomname -- roomname=string.gsub(fibaro:getRoomName(roomID), "%W", "") 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) When I run the scene, it reads back the ID (1548) stored for Motion under the kitchen grouping. This allows me to verify that the table saved correctly. I would recommend using an external editor like Notepad++ or Zerobrane to edit/manage the code in the vd and then copy back to the vd when ready to update as the HC2 lua editor is very small @ReneNL has rewritten the scene so it eliminates the need for both the py script and manually create the data yourself. When you run the scene it'll dump out the table but can be difficult to read. To make it easier to see the table and the structure copy the lower part of the debug window Head over to http://jsonprettyprint.com/ and paste the data into the windows and it presents the json in a more readable format. REFERENCING THE TABLE CONTENTS IN YOUR SCENES AND VIRTUAL DEVICES For this you need to place the following line of code in each scene or vd local jT = json.decode(fibaro:getGlobalValue("HomeTable")) and then use references instead of device ID's in the scene code. The easiest way to explain this is with an example. This scene switches on a light in my kitchen if it is dark, motion is detected and no light is on already --[[ %% properties 1548 value %% events %% global --]] local jT = json.decode(fibaro:getGlobalValue("HomeTable")) -- KITCHEN AUTOLIGHTS if (tonumber(fibaro:getGlobalValue("Darkness")) == 1 ) and (tonumber(fibaro:getValue(jT.kitchen.Motion, "value")) > 0 ) and (tonumber(fibaro:getValue(jT.kitchen.Spotlights, "value")) == 0 ) and (tonumber(fibaro:getValue(jT.kitchen.Pendant, "value")) == 0 ) and (tonumber(fibaro:getValue(jT.kitchen.Table, "value")) == 0 ) and (tonumber(fibaro:getValue(jT.sunroom.Light, "value")) == 0 ) and (tonumber(fibaro:getValue(jT.sunroom.Lamp, "value")) == 0 ) then fibaro:call(jT.kitchen.Pendant, "setValue", "40") UpdateEventLog("kitchen lights auto on") end It's easy enough to see how the references are built up if you examine the scene v the table n the pre-defined variableat the top of this post I also like to read back a entry in the table to make sure it saved correctly and use the following code -- 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 You will need to change the last line jT.scene.MainScene to jT.section.entry where 'section' and 'entry' exist in your HomeTable Slight addition for folks from the international community (special chars in the names or labels) thanks @FredrikKarlsson Therefore, your scene "Start på morgonen" will be encoded as ""Startpåmorgonen" in the table. You will need to use square brackets log(jT.VD.["Startpåmorgonen"]) jt["Köket"]["Läckagediskmaskinen"] AMENDING A SINGLE PARAMETER IN THE TABLE This can be useful if you don't want to adjust one value in the table -- NEW PARAMETER VALUE jT.kitchen.Motion=2000 -- TO SAVE THE CHANGE jSonosTable = json.encode(jT) fibaro:setGlobal("SonosTable", jSonosTable) fibaro:debug("global jTable created") Hopefully this will help some users If you have any suggestions as to how to improve this please let me know and I'll edit @AutoFrank & @ReneNL Copy of my table to show what I use it for Sample HomeTable.json Edited January 26, 2017 by AutoFrank updated 2 Quote Link to post Share on other sites
Jamie mccrostie 81 Share Posted January 7, 2017 Cool tutorial. For a newbie it fills all the gaps. I could do with more of these. Thankyou Auto Frank Quote Link to post Share on other sites
jimicr 78 Share Posted January 7, 2017 Very good @AutoFrank been using the HomeTable a while now and surely gonna look into your VD. Quote Link to post Share on other sites
ReneNL 47 Share Posted January 7, 2017 (edited) Thank you @AutoFrank. I had the same experience as you: very easy and convenient way to store device/IDs. Initially I wrote a python script to do the hard work and to generate the table for you. The python script is still attached to this post, but on several requests I wrote a LUA script instead which is now integrated into the first post/overall script of this thread by AutoFrank. Hope this helps. fill_HomeTable_clean.py Edited January 25, 2017 by ReneNL Made referance to LUA script in first post instead of the python script Quote Link to post Share on other sites
AutoFrank 363 Author Share Posted January 7, 2017 47 minutes ago, ReneNL said: Thank you @AutoFrank. I had the same experience as you: very easy and convenient way to store device/IDs. For large networks, typing up the list/json with all the device names/IDs is a bit cumbersome, so I wrote a little python script to do the hard work (see my other post here). For convenience I attach the python script below: Hope this helps. fill_HomeTable_clean.py That seems like a great addition Would you mind if I added your script to the first post when I edit it to improve the methodology ? Quote Link to post Share on other sites
Sankotronic 1,330 Share Posted January 7, 2017 Quote HOME TABLE This can be created and maintained through either a scene or a virtual device. I chose a VD but there is no advantage I can thing of using one way or the other. Go to Panel, Variables Panel and create a new predefined variable (lower part of panel) called HomeTable. When you create a predefined variable it has two values. Name the variable and save. Edit the variable and simply delete the second value. Hi @AutoFrank, Very nice tutorial! I will add links to it from my posts. Thank you! BTW I use scene with %% autostart in scene header so that it is run immediately after rebooting the system or saving after changing table. Quote Link to post Share on other sites
AutoFrank 363 Author Share Posted January 7, 2017 8 minutes ago, Sankotronic said: Hi @AutoFrank, Very nice tutorial! I will add links to it from my posts. Thank you! BTW I use scene with %% autostart in scene header so that it is run immediately after rebooting the system or saving after changing table. @Sankotronic thats a good idea .. I didn't think about making sure it gets reloaded after a restart. If it's okay I'll include this idea when I edit the post to refine it... Quote Link to post Share on other sites
Sankotronic 1,330 Share Posted January 7, 2017 4 minutes ago, AutoFrank said: @Sankotronic thats a good idea .. I didn't think about making sure it gets reloaded after a restart. If it's okay I'll include this idea when I edit the post to refine it... @AutoFrank, yes please include it in your first post. Quote Link to post Share on other sites
AutoFrank 363 Author Share Posted January 7, 2017 edited first post to include two refinements... - Outline benefits of using a scene instead of a virtual device (thanks @Sankotronic ) - Added py script to help gather the data (thanks @ReneNL ) Quote Link to post Share on other sites
twanve 6 Share Posted January 7, 2017 I try to create the HomeTable with you python script, but not works for me. Can you explain in more detail how to use it. Where insert the code exactly ...? Maybe its possible to write only a lua script to generate the full Json Table. Twan Quote Link to post Share on other sites
andyp 6 Share Posted January 7, 2017 (edited) @AutoFrank Excellent Tutorial @ReneNL As Twanve said - is it possible to expand you note and walk us through the process to use the python script. I tried running python fill_HomeTable_clean.py on my mac and get error: File "fill_HomeTable_clean.py", line 2, in <module> import requests ImportError: No module named requests So clearly I am doing something wrong Thanks Andy Edited January 7, 2017 by andyp Quote Link to post Share on other sites
AutoFrank 363 Author Share Posted January 7, 2017 3 minutes ago, andyp said: @AutoFrank Excellent Tutorial @ReneNL As Twanve said - is it possible to expand you note and walk us through the process to use the python script. Thanks Andy Thanks Andy @ReneNL - has added extra detail at https://forum.fibaro.com/index.php?/topic/20634-sunset-and-sunrise-why-doesnt-this-work/&page=3#comment-107142 Will this help ? Quote Link to post Share on other sites
andyp 6 Share Posted January 7, 2017 @AutoFrank Thanks for the pointer - this was the way I was trying to run it albeit on a mac - and I get an error. iMac:downloads andypayne$ python fill_HomeTable_clean.py Traceback (most recent call last): File "fill_HomeTable_clean.py", line 2, in <module> import requests ImportError: No module named requests iMac:downloads andypayne$ Andy Quote Link to post Share on other sites
andyp 6 Share Posted January 7, 2017 For anyone else who reads this tutorial which is excellent and hits the same issue with the python script I did this is how I fixed it on my Mac: brew install python and then pip install requests then python fill_HomeTable_clean.py got there in the end. Saved lots of time building file manually. Quote Link to post Share on other sites
AutoFrank 363 Author Share Posted January 7, 2017 8 minutes ago, andyp said: For anyone else who reads this tutorial which is excellent and hits the same issue with the python script I did this is how I fixed it on my Mac: brew install python and then pip install requests then python fill_HomeTable_clean.py got there in the end. Saved lots of time building file manually. Thanks Andy. That'll save time for the Mac folks... Quote Link to post Share on other sites
AutoFrank 363 Author Share Posted January 14, 2017 Updated with some clarificaitons Quote Link to post Share on other sites
ReneNL 47 Share Posted January 16, 2017 I have spent some time to code an automatic hometable generation in LUA, so that the python script is not needed anymore @AutoFrank, can you update the first post if you like this? --[[ %% 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 = { scene = { MainScene=614,AlarmControl=598,rebootHC2=593,goodMorning=463,goodNight=331,LeavingHome=483,welcomeHome=488,quietMorning=499,kidsToBed=490,plaroomTvOn=580,firstFloorMusicOn=579,firstFloorAllOff=578, hallSceneControl=519,StairsLight30=556,GateOpen5=526,GateOpenHold=361,GateOpenClose=425,DumpEventLog=565,PlayroomOff=617 }, users = { admin=2,frank=1564,sylvia=1565 }, } -- 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 Quote Link to post Share on other sites
AutoFrank 363 Author Share Posted January 16, 2017 1 hour ago, ReneNL said: I have spent some time to code an automatic hometable generation in LUA, so that the python script is not needed anymore @AutoFrank, can you update the first post if you like this? --[[ %% 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 = { scene = { MainScene=614,AlarmControl=598,rebootHC2=593,goodMorning=463,goodNight=331,LeavingHome=483,welcomeHome=488,quietMorning=499,kidsToBed=490,plaroomTvOn=580,firstFloorMusicOn=579,firstFloorAllOff=578, hallSceneControl=519,StairsLight30=556,GateOpen5=526,GateOpenHold=361,GateOpenClose=425,DumpEventLog=565,PlayroomOff=617 }, users = { admin=2,frank=1564,sylvia=1565 }, } -- 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 @ReneNL That's a great addition The post is mor eyours than mine now I just ran it across my system and it created quite a table one suggestion - could you eliminate the allocated devices ? I'll update the first post thanks again -f Quote Link to post Share on other sites
AutoFrank 363 Author Share Posted January 16, 2017 First post updated with modified scene to automatically read all the devices Thanks @ReneNL Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.