--[[ V2.1 Scene functionality: 1. Display all system's devices/scenes and their attributes. 2. By pressing twice within 2 seconds on "Start" button, scan battery levels only. 3. Extarnal exectuion with parameter | fibaro:startScene('sceneID',{""}) | will scan battery levels and if found levels below low limit 'batMin', notification will send according to user setup [eMail,popupNote and pushNote] ======================== User configurable parameters =============================== ------------------------------------------------------------------------------------------]] plainList = false --- false=Devices list per sections and rooms. true=plaint list by device IDs batMin = 40 --- Battery level low limit. eMailId = 2 --- user ID to send email eMail = true --- if true email will send popupNote = true --- if true popup notification will send pushNote = true --- if true interactive push notification will send mdl2str= --- Fibaro model type conversion table to human readable description {["multilevelSwitch"]="FGD211 FGRGBW441M",["multilevelSensor"]="FGCD001 FGDW002", ["motionSensor"]="FGMS001",["smokeSensor"]="FGSS001 FGSD002", ["remoteController"]="FGGC001 FGBS321 FGKF601 FGRM222 FGR221 FGR223 FGD212 FGPB101", ["floodSensor"]="FGFS101",["setPoint"]="FGT001", ["binarySwitch"]="FGP111 FGS211 FGS212 FGS213 FGS222 FGS223 FGWP101 FGWP102 FGWPE102 FGWPB111 FGWPB121 FGWPG121 FGWPI121" } function sendNote(subject,body) local fStatus = "" if eMail then fibaro:call(eMailId,"sendEmail",subject,body) fStatus="[eMail: "..api.get("/devices/"..eMailId)["properties"]["Email"].."]" end if popupNote then HomeCenter.PopupService.publish({title=subject,contentBody=body,type = "Critical", buttons = {{ caption = 'OK', sceneId = 0 }} }) fStatus=fStatus.." [Popup: all users]" end if pushNote then fStatus=fStatus .. " [Push" for _,j in ipairs(fibaro:getDevicesId({roomID=0,type="iOS_device",properties={Push=true}})) do api.post('/mobile/push',{["mobileDevices"]={j},["message"]=body,["title"]=subject, ["category"]='RUN_CANCEL', ["data"]={["sceneId"]=__fibaroSceneId}}); fStatus=fStatus..": "..fibaro:getName(j) end fStatus=fStatus.."]" end return fStatus end --function =================================================================================== function checkBattery(batTotal) local singleDev,dList,foundLow,bList,subject={},"
",false,"Device(s) with battery level below "..batMin.."%\n --------------------------------------------------\n","🔋 Low Battery" ids=fibaro:getDevicesId({interfaces={"battery"},enabled=true,visible=true}) table.sort(ids,function(a,b) local nodeA=tonumber(fibaro:getValue(a, "nodeId")) local nodeB=tonumber(fibaro:getValue(b, "nodeId")) if nodeA==nodeB then return a:"..fibaro:getRoomNameByDeviceID(dID).."]\t battery level = "..tmpLvl.."%\n" end end dList=dList.."____________ Found total of ".. #singleDev .." battery operated devices ____________
" if foundLow then dList=dList.."
"..string.gsub(bList,"\n","
") if fibaro:args()~=nil then dList=dList.."Notification sent "..sendNote(subject,bList).."" end end fibaro:debug(os.date("%c")..dList) end --function =================================================================================== function devType(fType,dID) if fType:find("FG") then for i,j in pairs(mdl2str) do if j:find(fType) then fType=i end end if fType:find("FG") then fType=string.gsub(dID.baseType,"com.fibaro.","") end end if json.encode(dType):find(fType) and dType[fType] then dType[fType][#dType[fType]+1]=dID.id..":"..dID.name..dID.roomName typeLen[fType]=math.max(typeLen[fType],dType[fType][#dType[fType]]:len()+6) else dType[fType]={};dType[fType][1]=dID.id..":"..dID.name..dID.roomName; typeLen[fType]=dType[fType][1]:len()+6 end return fType end --function =================================================================================== function progMeter(k) scanNum=scanNum+1 if scanNum % 10 ~=0 and scanNum~=scanTotal then return end api.delete("/scenes/".. __fibaroSceneId.."/debugMessages") fibaro:debug(""..fibaro:countScenes()..""..codeVer.." Scanning "..scanTotal.." elements. ".. ''.." "..math.min(math.ceil(scanNum/scanTotal*100),100).."%") end --function =================================================================================== function getUnit(dID) if dID.properties.unit then return dID.properties.unit else return "" end end --function =================================================================================== function getUserData(dID) local mStr = "" progMeter() for _,uIds in ipairs(api.get("/users")) do if uIds.id==dID then mStr=mStr..uIds.type.." : "..uIds.email if uIds.hasGPS==true then mStr=mStr.." : hasGPS="..json.encode(uIds.tracking.."min") end mStr=mStr.." : deviceRights="..json.encode(uIds.deviceRights).."".." : sceneRights="..json.encode(uIds.sceneRights) .. "" break end end return mStr end --function =================================================================================== function getSceneData(sData,lType) local mStr,parentId,fontColor,header="",0,"",sData.name progMeter() if lType~=nil then header=header..sData.roomName end mStr=mStr..""..sData.id..": "..fontColor..header.." [ "..devType(string.gsub(sData.type,"com.fibaro.",""),sData) mStr=mStr.." : Max Instances="..sData.maxRunningInstances.." : Instances=".. sData.runningInstances if sData.visible==false then mStr=mStr.." : Hidden" end if sData.alexaProhibited==false then mStr=mStr.." : Alexa enable" end if sData.autostart==true then mStr=mStr.." : Autostart" end mStr=mStr.." : "..sData.runConfig.." ]
" return mStr end --function =================================================================================== function getDeviceData(dData,lType) if type(dData)=="number" then dData=api.get("/devices/"..dData);dData.roomName=findRoom(dData.roomID) end if dData.id==1 then return "" end local mStr,fontColor,bLvl="","",0 local header,r,g,b=dData.name,255,0,0 progMeter() if dData.type=="HC_user" then return ""..dData.id..": " .. header .. " [ " .. getUserData(dData.id).. " ]
" end if dData.type~="iOS_device" then devTotal=devTotal+1 end;if not dData.parentId then dData.parentId=0 end if (lType ~= nil) then header=dData.name..dData.roomName end if dData.type=="com.fibaro.zwaveDevice" or dData.visible==false then fontColor="" end mStr=mStr..""..dData.id..": "..fontColor..header.." [ "..devType(string.gsub(dData.type,"com.fibaro.",""),dData) if dData.parentId==1 then phDev=phDev+1; mStr=mStr.." : Parent of "..json.encode(fibaro:getDevicesId({parentId=dData.id})) elseif dData.parentId>1 then mStr=mStr.." : ParentID="..dData.parentId end if dData.type=="com.fibaro.zwaveDevice" and dData.properties.lastWorkingRoute then mStr=mStr.." : zwaveRoute "..json.encode(dData.properties.lastWorkingRoute) end if dData.properties.zwaveCompany and dData.properties.zwaveCompany~="" then mStr=mStr.." : "..dData.properties.zwaveCompany end if dData.properties.batteryLevel and dData.type~="com.fibaro.zwaveDevice" then bLvl=dData.properties.batteryLevel if not (bLvl) then bLvl=100 elseif bLvl==255 then bLvl=0 end if (tonumber(fibaro:getValue(dData.id,"batteryLevel"))"..bLvl.."%" end if dData.properties.Push~=nil then mStr=mStr.." : Push="..tostring(dData.properties.Push) end if string.find(json.encode(api.get("/installer/mobileDevicesToNotify")["mobileDevicesToNotify"]),tostring(dData.id)) then mStr=mStr.." : Installer Access=true" end if dData.properties.lastLoggedUser and tonumber(dData.properties.lastLoggedUser)>0 then mStr=mStr.." : last Logged User="..fibaro:getName(tonumber(dData.properties.lastLoggedUser)) mStr=mStr.." at "..os.date("%c",api.get("/devices/"..dData.id.."/properties/lastLoggedUser")["modified"]) end -- if dData.properties.DeviceUID then mStr=mStr.." : UID="..dData.properties.DeviceUID.."" end if dData.visible==false then mStr=mStr.." : Hidden" end if dData.enabled==false then mStr=mStr.." : Disabled" end mStr=mStr.." ]" if dData.properties.value~=nil then mStr=mStr.." [ value="..tostring(dData.properties.value)..getUnit(dData).." ]" end if dData.properties.power then mStr=mStr.." [ power="..tostring(dData.properties.power).."w ]" end return mStr.."

" end -- function =================================================================================== function findRoom(rId) for _,i in ipairs(gRooms) do if rId==i.id then return ":>:"..i.name end end return "" end -- function =================================================================================== -----------------------------===### Main ###===---------------------------- dType={};typeLen={};codeVer="🎬V2.1";scanNum=0;devTotal=0;phDev=0 api.delete("/scenes/".. __fibaroSceneId.."/debugMessages") local endStr,dList,perLine,dTypeNum,zBuffer={"
","",""},"
",0,0,{} gRooms=api.get("/rooms") if fibaro:args()~=nil then checkBattery(false);fibaro:abort() end if fibaro:countScenes()==1 then fibaro:debug("Elements data collection is about to start. Press \"Start\" again to check batteries level.") x=os.time(); while fibaro:countScenes()==1 and os.time()-x < 3 do end if fibaro:countScenes()>1 then fibaro:abort() end fibaro:debug("Gathering system information.....") elseif fibaro:countScenes()==2 then print("in second instance") x=os.time();while fibaro:countScenes()==2 and os.time()-x < 6 do end if fibaro:countScenes()>1 then fibaro:debug("Too many scenes.. aborting");fibaro:abort() else fibaro:debug("Start to check batteries level...");checkBattery(false);fibaro:abort() end else fibaro:debug("Scene's running instances ("..fibaor:countSCenes()..") out of limit. Aborting scene....");fibaro:abort() end gRooms=api.get("/rooms");devData=api.get("/devices");scData=api.get("/scenes");scanTotal=#devData+#scData if not plainList then for _,section in ipairs(api.get("/sections")) do dList=dList.."______________________ " .. section.name .. " section ______________________
" for _,room in ipairs(gRooms) do if room.sectionID==section.id then dList=dList.."--~~== "..room.name.." room ==~~--
" for _,dID in ipairs(devData) do if dID.roomID==room.id then dID.roomName=":>:"..room.name;dList=dList..getDeviceData(dID) end end for _,scene in ipairs(scData) do if scene.roomID==room.id then scene.roomName=":>:"..room.name;dList=dList..getSceneData(scene) end end end -- for _,room in ipairs(api.get("/rooms")) do end -- if room.sectionID == section.id then end -- for _,section in ipairs(api.get("/sections")) do dList=dList.."_________________________ End of section _________________________
" dList=dList.."--~~== Unassigned room ==~~--
" for _,dID in ipairs(devData) do if dID.roomID==0 and json.encode(dID.interfaces):find("zwave") then dID.roomName="";dList=dList..getDeviceData(dID) end end for _,dIds in ipairs(scData) do if dIds.roomID==0 then dIds.roomName="";dList=dList..getSceneData(dIds) end end dList=dList.."--~~== System Users ==~~--
" for _,dID in ipairs(devData) do if dID.type=="HC_user" then dID.roomName="";dList=dList..getDeviceData(dID) end end dList=dList.."--~~== Mobile devices list ==~~--
" for _,dID in ipairs(devData) do if dID.roomID==0 and dID.type=="iOS_device" then dID.roomName="";dList=dList..getDeviceData(dID) end end elseif (plainList and fibaro:countScenes()==1) then --if not (plainList================== dList=dList.."--~~== Devices list ==~~--
";for i,dID in ipairs(devData) do dID.roomName=findRoom(dID.roomID);dList=dList..getDeviceData(dID,1) end dList=dList.."--~~== Scenes list ==~~--
";for _,dIds in ipairs(scData) do dIds.roomName=findRoom(dIds.roomID);dList=dList..getSceneData(dIds,1) end end --if not (plainList zBuffer[1] ="".. "
"..api.get("/settings/info/")["hcName"].." ("..api.get("/settings/info/")["serialNumber"]..") system inventory.
" for i,_ in pairs(dType) do dTypeNum=dTypeNum+1 if #dType[i]>25 then for j=1,#dType[i] do dType[i][j]=string.format("%"..typeLen[i] .."s",dType[i][j]..endStr[(j % 3)+1]) end else for j=1,#dType[i] do dType[i][j]=" "..dType[i][j].."
" end end end dTypeNum=math.min(math.ceil(dTypeNum/10),3) for j=1,dTypeNum do zBuffer[#zBuffer+1]="" end --..dHeader[i].."" end end zBuffer[#zBuffer+1]="" for i,j in pairs(dType) do perLine=perLine+1 zBuffer[#zBuffer+1]="" zBuffer[#zBuffer+1]="" if perLine % dTypeNum ==0 then zBuffer[#zBuffer+1]="" end end print(""..os.date("%c")..dList.."
"..table.concat(zBuffer).."
Type Total
"..#j.."
".. "
Total physical devces = "..phDev.."
Total Zwave/Virtual devices = "..devTotal.."
Battery operated = "..checkBattery(true).."
")