11ABOUT = {
22 NAME = " VeraBridge" ,
3- VERSION = " 2016.05.21 " ,
3+ VERSION = " 2016.06.01 " ,
44 DESCRIPTION = " VeraBridge plugin for openLuup!!" ,
55 AUTHOR = " @akbooer" ,
66 COPYRIGHT = " (c) 2013-2016 AKBooer" ,
@@ -34,6 +34,8 @@ ABOUT = {
3434-- 2016.05.14 settled on implementation of mirror devices using top-level openLuup.mirrors attribute
3535-- 2016.05.15 HouseMode variable to reflect status of bridged Vera (thanks @logread)
3636-- 2016.05.21 @explorer fix for missing Zwave device children when ZWaveOnly selected
37+ -- 2016.05.23 HouseModeMirror for mirroring either way (thanks @konradwalsh)
38+ -- 2016.06.01 Add GetVeraFiles action to replace openLuup_getfiles separate utility
3739
3840local devNo -- our device number
3941
@@ -43,6 +45,7 @@ local rooms = require "openLuup.rooms"
4345local scenes = require " openLuup.scenes"
4446local userdata = require " openLuup.userdata"
4547local url = require " socket.url"
48+ local lfs = require " lfs"
4649
4750-- local pretty = require "pretty" -- TODO: TESTING ONLY
4851
@@ -52,13 +55,24 @@ local POLL_DELAY = 5 -- number of seconds between remote polls
5255local local_room_index -- bi-directional index of our rooms
5356local remote_room_index -- bi-directional of remote rooms
5457
58+ local BuildVersion -- ...of remote machine
59+
5560local SID = {
61+ altui = " urn:upnp-org:serviceId:altui1" , -- Variables = 'DisplayLine1' and 'DisplayLine2'
5662 gateway = " urn:akbooer-com:serviceId:VeraBridge1" ,
57- altui = " urn:upnp-org :serviceId:altui1 " -- Variables = 'DisplayLine1' and 'DisplayLine2'
63+ hag = " urn:micasaverde-com :serviceId:HomeAutomationGateway1 " ,
5864}
5965
60- local Mirrored -- mirrors is a set of device IDs for 'reverse bridging', not to be cloned
61- local MirrorHash -- reverse lookup: local hash to remote device ID
66+ local Mirrored -- mirrors is a set of device IDs for 'reverse bridging', not to be cloned
67+ local MirrorHash -- reverse lookup: local hash to remote device ID
68+ local HouseModeMirror -- flag with one of the following options
69+ local HouseModeTime = 0 -- last time we checked
70+
71+ local HouseModeOptions = { -- 2016.05.23
72+ [' 0' ] = " 0 : no mirroring" ,
73+ [' 1' ] = " 1 : local mirrors remote" ,
74+ [' 2' ] = " 2 : remote mirrors local" ,
75+ }
6276
6377-- @explorer options for device filtering
6478
@@ -294,7 +308,6 @@ local function create_scenes (remote_scenes, room)
294308 luup .log " linking to remote scenes..."
295309
296310 local action = " RunScene"
297- local sid = " urn:micasaverde-com:serviceId:HomeAutomationGateway1"
298311 local wget = ' luup.inet.wget "http://%s:3480/data_request?id=action&serviceId=%s&action=%s&SceneNum=%d"'
299312
300313 for _ , s in pairs (remote_scenes ) do
@@ -307,7 +320,7 @@ local function create_scenes (remote_scenes, room)
307320 id = id ,
308321 name = s .name ,
309322 room = room ,
310- lua = wget :format (ip , sid , action , s .id ) -- trigger the remote scene
323+ lua = wget :format (ip , SID . hag , action , s .id ) -- trigger the remote scene
311324 }
312325 luup .scenes [new .id ] = scenes .create (new )
313326 luup .log ((" scene [%d] %s" ): format (new .id , new .name ))
@@ -328,6 +341,7 @@ local function GetUserData ()
328341 local url = table.concat {" http://" , ip , " :3480/data_request?id=user_data2&output_format=json" }
329342 local atr = url :match " =(%a+)"
330343 local status , j = luup .inet .wget (url )
344+ local version
331345 if status == 0 then Vera = json .decode (j ) end
332346 if Vera then
333347 luup .log " Vera info received!"
@@ -342,14 +356,17 @@ local function GetUserData ()
342356 local_room_index = index_rooms (luup .rooms or {})
343357 luup .log (" new room number: " .. (local_room_index [new_room_name ] or ' ?' ))
344358
359+ version = Vera .BuildVersion
360+ luup .log (" BuildVersion = " .. version )
361+
345362 Ndev = # Vera .devices
346363 luup .log (" number of remote devices = " .. Ndev )
347364 local roomNo = local_room_index [new_room_name ] or 0
348365 Ndev = create_children (Vera .devices , roomNo )
349366 Nscn = create_scenes (Vera .scenes , roomNo )
350367 end
351368 end
352- return Ndev , Nscn
369+ return Ndev , Nscn , version
353370end
354371
355372-- MONITOR variables
@@ -375,6 +392,30 @@ local function UpdateVariables(devices)
375392 end
376393end
377394
395+ -- update HouseMode variable and, possibly, the actual openLuup Mode
396+ local function UpdateHouseMode (Mode )
397+ Mode = tostring (Mode )
398+ setVar (" HouseMode" , Mode ) -- 2016.05.15, thanks @logread!
399+
400+ local current = userdata .attributes .Mode
401+ if current ~= Mode then
402+ if HouseModeMirror == ' 1' then
403+ luup .attr_set (" Mode" , Mode ) -- 2016.05.23, thanks @konradwalsh!
404+
405+ elseif HouseModeMirror == ' 2' then
406+ local now = os.time ()
407+ luup .log " remote HouseMode differs from that set..."
408+ if now > HouseModeTime + 60 then -- ensure a long delay between retries (Vera is slow to change)
409+ local switch = " remote HouseMode update, was: %s, switching to: %s"
410+ luup .log (switch : format (Mode , current ))
411+ HouseModeTime = now
412+ local request = " http://%s:3480/data_request?id=action&serviceId=%s&DeviceNum=0&action=SetHouseMode&Mode=%s"
413+ luup .inet .wget (request : format (ip , SID .hag , current ))
414+ end
415+ end
416+ end
417+ end
418+
378419-- poll remote Vera for changes
379420-- TODO: make callback use asynchronous I/O
380421local poll_count = 0
@@ -387,7 +428,7 @@ function VeraBridge_delay_callback (DataVersion)
387428 local status , j = luup .inet .wget (url )
388429 if status == 0 then s = json .decode (j ) end
389430 if s and s .devices then
390- setVar ( " HouseMode " , tonumber ( s .Mode ) or 1 ) -- 2016.05.15, thanks @logread!
431+ UpdateHouseMode ( s .Mode )
391432 UpdateVariables (s .devices )
392433 DataVersion = s .DataVersion
393434 luup .devices [devNo ]:variable_set (SID .gateway , " LastUpdate" , os.time (), true ) -- 2016.03.20 set without log entry
@@ -496,6 +537,86 @@ local function watch_mirror_variables (mirrored)
496537 return
497538end
498539
540+ --
541+ -- Bridge ACTION handler(s)
542+ --
543+
544+ -- copy all device files and icons from remote vera
545+ -- (previously performed by the openLuup_getfiles utility)
546+ function GetVeraFiles ()
547+
548+ local code = [[
549+
550+ local lfs = require "lfs"
551+ local f = io.open ("/www/directory.txt", 'w')
552+ for fname in lfs.dir ("%s") do
553+ if fname:match "lzo$" or fname: match "png$" then
554+ f:write (fname)
555+ f:write '\n'
556+ end
557+ end
558+ f:close ()
559+
560+ ]]
561+
562+ local function get_directory (path )
563+ local template = " http://%s:3480/data_request?id=action" ..
564+ " &serviceId=urn:micasaverde-com:serviceId:HomeAutomationGateway1" ..
565+ " &action=RunLua&Code=%s"
566+ local request = template :format (ip , url .escape (code : format (path )))
567+
568+ local status , info = luup .inet .wget (request )
569+ if status ~= 0 then luup .log (" error creating remote directory listing: " .. status ) return end
570+
571+ status , info = luup .inet .wget (" http://" .. ip .. " /directory.txt" )
572+ if status ~= 0 then luup .log (" error reading remote directory listing: " .. status ) return end
573+
574+ return info
575+ end
576+
577+ local function get_files_from (path , dest , url_prefix )
578+ dest = dest or ' .'
579+ url_prefix = url_prefix or " :3480/"
580+ luup .log (" getting files from " .. path )
581+ local info = get_directory (path )
582+ for x in info : gmatch " %C+" do
583+ local fname = x :gsub (" %.lzo" ,' ' ) -- remove unwanted extension for compressed files
584+ local status , content = luup .inet .wget (" http://" .. ip .. url_prefix .. fname )
585+ if status == 0 then
586+ luup .log (table.concat {# content , ' ' , fname })
587+
588+ local f = io.open (dest .. ' /' .. fname , ' wb' )
589+ f :write (content )
590+ f :close ()
591+ else
592+ luup .log (" error: " .. fname )
593+ end
594+ end
595+ end
596+
597+ -- device, service, lua, json, files...
598+ lfs .mkdir " files"
599+ get_files_from (" /etc/cmh-ludl/" , " files" , " :3480/" )
600+ get_files_from (" /etc/cmh-lu/" , " files" , " :3480/" )
601+ luup .log " ...end of device files"
602+
603+ -- icons
604+ lfs .mkdir " icons"
605+ local _ ,b ,_ = BuildVersion : match " (%d+)%.(%d+)%.(%d+)" -- branch, major minor
606+ local major = tonumber (b )
607+
608+ if major then
609+ if major > 5 then -- UI7
610+ get_files_from (" /www/cmh/skins/default/img/devices/device_states/" ,
611+ " icons" , " /cmh/skins/default/img/devices/device_states/" )
612+ else -- UI5
613+ get_files_from (" /www/cmh/skins/default/icons/" , " icons" , " /cmh/skins/default/icons/" )
614+ end
615+ luup .log " ...end of icon files"
616+ end
617+ end
618+
619+
499620--
500621-- GENERIC ACTION HANDLER
501622--
@@ -544,6 +665,10 @@ function init (lul_device)
544665 Excluded = uiVar (" ExcludeDevices" , ' ' ) -- list of devices to exclude from synchronization by VeraBridge,
545666 -- ...takes precedence over the first two.
546667
668+ local hmm = uiVar (" HouseModeMirror" ,HouseModeOptions [' 0' ]) -- 2016.05.23
669+ HouseModeMirror = hmm : match " ^([012])" or ' 0'
670+ setVar (" HouseModeMirror" , HouseModeOptions [HouseModeMirror ]) -- replace with full string
671+
547672 ZWaveOnly = ZWaveOnly == " true" -- convert to logical
548673 Included = convert_to_set (Included )
549674 Excluded = convert_to_set (Excluded )
@@ -559,7 +684,8 @@ function init (lul_device)
559684
560685 luup .devices [devNo ].action_callback (generic_action ) -- catch all undefined action calls
561686
562- local Ndev , Nscn = GetUserData ()
687+ local Ndev , Nscn
688+ Ndev , Nscn , BuildVersion = GetUserData ()
563689
564690 setVar (" Version" , ABOUT .VERSION )
565691 setVar (" DisplayLine1" , Ndev .. " devices, " .. Nscn .. " scenes" , SID .altui )
0 commit comments