Jump to content

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


Recommended Posts

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

  1. I implemented this over christmas and and found it very useful and much easier than I thought
  2. 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.

  1. The home table itself where the data is stored. - this is held in a predefined variable (lower part of variables panel)
  2. 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.

 

hometable.PNG

 

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

 

debug.PNG

 

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 by AutoFrank
updated
  • Like 2
Link to post
Share on other sites
  • Replies 154
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Popular Posts

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

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 additi

Here's another version that automatically adds users and scenes too. All room/device/scene/etc names are converted to lowercase (except the mobile device name so it can be copy/pasted from the Access

Posted Images

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 by ReneNL
Made referance to LUA script in first post instead of the python script
Link to post
Share on other sites
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 ?

Link to post
Share on other sites
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.

 

Link to post
Share on other sites
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...

Link to post
Share on other sites
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.

Link to post
Share on other sites

 

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

Link to post
Share on other sites

@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 by andyp
Link to post
Share on other sites
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 ?

Link to post
Share on other sites

@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
Link to post
Share on other sites

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.

 

Link to post
Share on other sites
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...

Link to post
Share on other sites

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

 

Link to post
Share on other sites
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

 

 

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