Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

checkall [03.03.2017 17:05] (Version actuelle)
Steven Piccand créée
Ligne 1: Ligne 1:
 +====== LUA / checkAll ======
 +Essaie de trouver des soucis d'ID dans les scénarios et VD
  
 +\\ 
 +\\ 
 +<code lua>
 +--[[
 +%% autostart
 +--]]
 +
 +
 +-- ===========================================
 +-- ANALYSEUR DE CODE pour relevé les problèmes d'ID
 +-- ===========================================
 +
 +local receivePush = true -- true pour recevoir une notification en cas de problème éventuel
 +local receiveEmail = true -- true pour recevoir le rapport d'​exécution par email
 +local checkDisabled = false -- true pour vérifier aussi les scènes et VD désactivés
 +
 +-- Tableau contenant les id des smartphones devant recevoir une notification en cas de problème
 +-- par défaut, ce script envoi un message à tout les smartphones
 +local portables_for_notification = {}
 +
 +-- Tableau contenant les id des utilisateurs devant recevoir un e-mail résumant
 +-- l'​analyse
 +local users_for_mail = {2}
 +
 +-- Va executer cette scène toutes les X heures
 +-- mettre cette ligne en commentaire pour désactiver
 +--local run_every = 24
 +
 +-- Tableau permettant d'​ajuster les warnings à ignorer
 +-- Exemple
 +-- {id=141} ​ -- tous les warning du VD ou de la scène 141 seront ignoré
 +-- {id=141, field="​id"​} ​ -- tous les warning du VD ou de la scène 141 seront ignoré s'il concerne une variable "​id"​
 +-- {id=141, field="​id",​ value="​2000"​} ​ -- tous les warning du VD ou de la scène 141 seront ignoré s'il concerne une variable "​id"​ et la valeur est 2000
 +local ignored = {
 + {id=163}
 +}
 +
 +-- Tableau contenant les noms de variables habituellement utilisés pour identifiant
 +-- un ID fibaro
 +local mostUseVariables = {"​id",​ "​deviceid",​ "​device_id",​ "​module",​ "​identifiant"​}
 +
 +-- Si vous avez un tableau d'ID a tester
 +local ids = {
 +    PLUIE = 104, VACSCOLAIRE = 77, DEVANT_LA_PORTE = 48, DETECTEUR_PORTE = 53, PLAFONNIER_ENTREE = 73,
 +    DETECTEUR_GARAGE = 67, OPENKAROTZ = 140, NOTIFICATION_CENTER = 105, PLAFONNIER_LOCAL = 24,
 +    PLAFONNIER_NOLAN = 28, PLAFONNIER_NORA = 26, PLAFONNIER_KENDRA = 30, POELE = 10, 
 +    ROMBA = 36, TV = 35, VD_FREE_PLAYER = 90, SECHE_SERVIETTE = 58, TEMPERATURE_SALON = 98, 
 +}
 +
 +
 +--[[ ===========================================
 +NE PAS TOUCHER
 +--=========================================== ]]
 +-- toolbox c.f. https://​gea.piccand.me/​doku.php/​minifier
 +local mailmsg = ""​
 +if not tools then tools={log=function(a,​b,​c)a=tools.tostring(a) mailmsg = mailmsg .. a .. "​\n"​ for d,e in string.gmatch(a,"​(#​spaces(%d+)#​)"​)do local f=""​for g=1,e do f=f.."​."​end;​a=string.gsub(a,​d,"<​span style=\"​color:​black;​\">"​..f.."</​span>"​)end;​if debug or c then fibaro:​debug("<​span style=\"​color:"​..(b or"​white"​)..";​\">"​..a.."</​span>"​)end end,​error=function(a,​b)tools.log(a,​b or"​red",​true)end,​warning=function(a,​b)tools.log(a,​b or"​orange",​true)end,​info=function(a,​b)tools.log(a,​b or"​white",​true)end,​debug=function(a,​b)tools.log(a,​b or"​gray",​false)end,​tostring=function(h)if type(h)=="​boolean"​then if h then return"​true"​else return"​false"​end elseif type(h)=="​table"​then if json then return json.encode(h)else return"​table found"​end else return tostring(h)end end,​split=function(i,​j)local j,k=j or":",​{}local l=string.format("​([^%s]+)",​j)i:​gsub(l,​function(m)k[#​k+1]=m end)return k end,​trim=function(n)return n:​gsub("​^%s*(.-)%s*$","​%1"​)end,​deep_print=function(o)for g,p in pairs(o)do if type(p)=="​table"​then deep_print(p)else print(g,​p)end end end,​getStringTime=function(q)if q then return os.date("​%H:​%M:​%S"​)end;​return os.date("​%H:​%M"​)end,​toTime=function(r)local s,​t=string.match(r,"​(%d+):​(%d+)"​)local u=os.date("​*t"​)local v=os.time{year=u.year,​month=u.month,​day=u.day,​hour=s,​min=t,​sec=0}if v<​os.time()then v=os.time{year=u.year,​month=u.month,​day=u.day+1,​hour=s,​min=t,​sec=0}end;​return v end,​getStringDate=function()return os.date("​%d/​%m/​%Y"​)end,​isNil=function(w)return type(w)=="​nil"​end,​isNotNil=function(w)return not tools.isNil(w)end}end
 +
 +local version = "​3.6"​
 +local scene_id = nil
 +local scene_name = nil
 +
 +
 +
 +--[[ ===========================================
 +      Cherche si l'ID existe sur la HC2 (device ou scène)
 + paramètres :
 + device: l'​identifiant trouvé
 + message : le message a afficher
 + color : la couleur du message
 +      ===========================================]]
 +function exist(device,​ message, color)
 +  if (tools.isNil(__fibaro_get_device(tonumber(device))) and tools.isNil(__fibaro_get_scene(tonumber(device)))) then
 +    tools.log(message,​ color or "​red",​ true)
 +    return false
 +  end
 +  return true
 +end
 +
 +--[[ ===========================================
 +     ​Vérifie s'il faut afficher un warning ou non
 + paramètres :
 + id = id du module ou de la scene
 + field : nom du code à tester ou id du module
 + value : valeur a ignorer
 +      ===========================================]]
 +function shouldCheck(id,​ field, value)
 +  for k,v in ipairs(ignored) do
 +    if (v.id == id and (tools.isNil(v.field) or tools.isNil(field) or v.field == field) and (tools.isNil(v.value) or tools.isNil(value) or v.value==value) ) then
 +      return false
 +    end
 +  end
 +  return true
 +end
 +
 +--[[ ===========================================
 +      Tente de trouver la valeur d'une variable ​
 + paramètres :
 + code : le code a analyser
 + device : la variable ou l'ID à traiter
 +      ===========================================]]
 +function findId(code,​ variable, posInCode)
 +  if (tonumber(variable) ~= nil) then return variable, true end
 +  local position = 1
 +  local id = nil
 +  for deviceid in string.gmatch(code,​ variable.."​[ ]?=[ ]?​(%d+)"​) do
 +    start, stop = string.find(code,​ variable.."​[ ]?=[ ]?​(%d+)",​ position)
 +    position = stop + 1
 +    if (start <= posInCode) then
 +      id = deviceid
 +    end
 +  end
 +  if (tonumber(id) ~= nil) then return id, false end
 +end
 +
 +--[[ ===========================================
 +      Cherche une erreur dans le header d'une scène
 + paramètres :
 + scene : la scène à analyser
 +      ===========================================]]
 +function checkheader(scene)
 +  local problem = false
 +  local firstonly = true
 +  for header in string.gmatch(scene.lua,​ "​%-%-%[%[(.-)%-%-%]%]"​) do
 +    if (firstonly) then
 +      for w, device in string.gmatch(header,​ "(%a+) (%d+)"​) do
 +        if (w ~= "​CentralSceneEvent"​) then
 +        if (not(exist(device,​ " ​     --> contient une référence erronée dans l'​entête : ID " .. device))) then
 +          problem = true
 +        end
 +        end
 +      end
 +      firstonly = false
 +    end
 +  end
 +  return problem
 +end
 +
 +
 +--[[ ===========================================
 +      Cherche une erreur dans le code sur les appels : fibaro:​XXXXXX
 + paramètres :
 + code : le code a analyser
 + part : la partie analysée (pour le log)
 +      ===========================================]]
 +function checkfibaro(code,​ part, device_id)
 +  local problem = false
 +  for func, content, _ in string.gmatch(code,​ "​fibaro:​(.-)%((.-)%)"​) do
 +    func = string.lower(func)
 +    local position = 0
 +    if (func ~= "​sleep"​ and func ~= "​setglobal"​ and func ~= "​debug"​) then
 +      for variable in string.gmatch(tools.trim(content),​ "​(.-),​.*"​) do
 +        local pos, stop = string.find(string.lower(code),​ string.lower("​fibaro:"​..func.."​("​..content.."​)"​),​ position, true)
 +        position = stop
 +        local id, direct = findId(code,​ variable, pos)
 +        if (id) then
 +          if (not shouldCheck(device_id,​ variable, id)) then
 +            -- avertissement inutile
 +          else          ​
 +            local message =  " ​     " .. part .. " --> contient une référence erronée dans fibaro:"​..func .. "​("​ .. content.."​) <span style=\"​color:​gray\">​[ignored = {id="​..device_id..",​ field=\""​..id.."​\"​}]</​span>"​
 +            local color = "​red"​
 +            if (not direct) then
 +              message = " ​     " .. part .. " --> contient une référence probablement erronée dans fibaro:"​..func .. "​("​ .. content.."​) " .. variable .. "​="​ .. id .. " ? <span style=\"​color:​gray\">​[ignored = {id="​..device_id..",​ field=\""​..variable.."​\",​ value=\""​..id.."​\"​}]</​span>" ​
 +              color = "​orange"​
 +            end
 +            if (not(exist(id,​ message, color))) then
 +              problem = true
 +            end
 +          end
 +        end
 +      end
 +    end
 +  end
 +  return problem
 +end
 +
 +--[[ ===========================================
 +      Cherche une erreur dans le code sur les appels : id, deviceid
 + voir mostUseVariables = {}
 + paramètres :
 + code : le code a analyser
 + part : la partie analysée (pour le log)
 +      ===========================================]]
 +function checkVariables(code,​ part, device_id)
 +  local problem = false
 +  local position = 0
 +  if (mostUseVariables) then
 +    for _,v in ipairs(mostUseVariables) do
 +      for deviceid in string.gmatch(code,​ "​%f[%a]"​..v.."​%f[%A][ ]?=[ ]?​(%d+)"​) do
 +        if shouldCheck(device_id,​ v, deviceid) then
 +          local message = " found " .. v.."​="​ .. deviceid .. " in ".. part.. " and " .. deviceid .. " is not a device, please check <span style=\"​color:​gray\">​[ignored = {id="​..device_id..",​ field=\""​..v.."​\",​ value=\""​..deviceid.."​\"​}]</​span>" ​
 +          if (not(exist(deviceid,​ message, "​orange"​))) then
 +            problem = true
 +          end
 +        end
 +      end
 +    end
 +  end
 +  return problem
 +end
 +
 +--[[ ===========================================
 +      Analyse les scénarios
 +      ===========================================]]
 +function findErrorsInScenes() ​
 +  local problem = false
 +  tools.log("​--------------------------------------------",​ "​lightblue",​ true)
 +  tools.log("​Checking scenes ... ", "​lightblue",​ true)
 +  tools.log("​--------------------------------------------",​ "​lightblue",​ true)
 +  local scenes = api.get("/​scenes"​)
 +  for k,v in ipairs(scenes) do
 +    local scene = __fibaro_get_scene(v.id)
 +    if (tools.isNotNil(scene) and (scene.runConfig ~= "​DISABLED"​ or checkDisabled)) then
 +      tools.log("​checking scene : [" .. scene.id .. "] " .. scene.name, "​gray",​ true)
 +      if (string.find(scene.lua,​ "​GEA.add"​)) then
 +        table.insert(ignored,​ {id=scene.id,​ field="​id",​ value="​0"​})
 +      end  ​
 +      if (string.find(scene.lua,​ "​findErrorsInScenes()"​)) then
 +        scene_id = scene.id
 +        scene_name = scene.name
 +        table.insert(ignored,​ {id=scene.id})
 +      end
 +      if (checkheader(scene)) then problem = true end
 +      if (checkfibaro(scene.lua,​ "​code",​ scene.id)) then problem = true end
 +      if (checkVariables(scene.lua,​ "​code",​ scene.id)) then problem = true end
 +    end
 +  end
 +  tools.log("​... done ", "​lightblue",​ true)
 +  return problem
 +end
 +
 +--[[ ===========================================
 +      Analyse les virtual devices
 +      ===========================================]]
 +function findErrorsInVirtual() ​
 +  local problem = false
 +  tools.log("​--------------------------------------------",​ "​lightblue",​ true)
 +  tools.log("​Checking virtual devices ... ", "​lightblue",​ true)
 +  tools.log("​--------------------------------------------",​ "​lightblue",​ true)
 +  local filter = {type="​virtual_device",​ enabled = true}
 +  if (checkDisabled) then
 +    filter = {type="​virtual_device"​}
 +  end
 +  local ids = fibaro:​getDevicesId(filter)
 +  for k,v in ipairs(ids) do
 +    vd = __fibaro_get_device(v)
 +    if (tools.isNotNil(vd)) then
 +      tools.log("​checking vd : [" .. vd.id .. "] " .. vd.name, "​gray",​ true)
 +      if (tools.isNotNil(vd.properties.mainLoop)) then 
 +        tools.log("​ --> checking mainLoop",​ "​gray"​)
 +        if (checkfibaro(vd.properties.mainLoop,​ "​mainloop",​ vd.id)) then problem = true end
 +        if (checkVariables(vd.properties.mainLoop,​ "​mainloop",​ vd.id)) then problem = true end
 +        for l,w in ipairs(vd.properties.rows) do
 +          if (w.type=="​button"​) then
 +            for m,x in ipairs(w.elements) do
 +              if (x.lua) then
 +                tools.log("​ --> checking " .. x.caption .. " ["​..x.name.."​]",​ "​gray"​)
 +                if (checkfibaro(x.msg,​ x.caption .. " ["​..x.name.."​]",​ vd.id) ) then problem = true end
 +                if (checkVariables(x.msg,​ x.caption .. " ["​..x.name.."​]",​ vd.id) ) then problem = true end
 +              end
 +            end
 +          end
 +        end
 +      end
 +    end
 +  end
 +  tools.log("​... done ", "​lightblue",​ true)
 +  return problem
 +end
 +
 +--[[ ===========================================
 +      Analyse le tableau d'ID
 +      ===========================================]]
 +function findErrorsInTable()
 +  if (type(ids) ~= "​table"​) then return false end
 +  tools.log("​--------------------------------------------",​ "​lightblue",​ true)
 +  tools.log("​Checking table [ids] ... ", "​lightblue",​ true)
 +  tools.log("​--------------------------------------------",​ "​lightblue",​ true)
 +  local problem = false
 +  for k,v in pairs(ids) do
 +    if (not(exist(v,​ " ​     --> " .. k .. " contient une référence erronée le table : " .. v))) then
 +      problem = true
 +    end
 +  end
 +  tools.log("​... done ", "​lightblue",​ true)
 +  return problem
 +end
 +
 +--[[ ===========================================
 +   ​  ​ Lancement du code
 +   ​ ===========================================]]
 +function run()
 +  mailmsg = ""​
 +  tools.log("​======================",​ "​lightblue",​ true)
 +  tools.log("​ Starting checker v."​..version,​ "​lightblue",​ true)
 +  tools.log("​ Cet outil ESSAIE de trouver des erreurs d'ID dans le code LUA", "​lightblue",​ true)
 +  tools.log("​ En aucun cas il est exaustif et peux indiquer des warning qui n'ont pas de raison d'​être",​ "​lightblue",​ true)
 +  tools.log("​ A vous d'​ajuster le tableau \"​ignored\"",​ "​lightblue",​ true)
 +  tools.log("​======================",​ "​lightblue",​ true)
 +  tools.log("​code couleur : ", "​gray",​ true)
 +  tools.log("#​spaces5#​orange = a vérifier ", "​orange",​ true)
 +  tools.log("#​spaces5#​rouge ​  = erreur ", "​red",​ true)
 +  tools.log("",​ "​gray",​ true)
 +
 +  local message = ""​
 +  if (findErrorsInScenes()) then
 +    message = message .. " Error(s) in scene"
 +  end
 +  if (findErrorsInVirtual()) then
 +    message = message .. " Error(s) in VD"
 +  end
 +  if (findErrorsInTable()) then
 +    message = message .. " Error(s) in Table"
 +  end
 +  if (string.len(message)>​0 and receivePush) then
 +    local ids = portables_for_notification or fibaro:​getDevicesId({type="​iOS_device",​ enabled=true})
 +    for _,v in ipairs(ids) do
 +      tools.log("​Message d'​avertissement envoyé à " .. fibaro:​getName(v),​ "​lightblue",​ true)
 +      fibaro:​call(v,​ "​sendPush",​ "​["​..v .. "] : " .. message)
 +    end
 +    HomeCenter.PopupService.publish({
 +        title = "​Scénario " .. scene_name .. " v." .. version,
 +        subtitle = os.date("​%I:​%M:​%S %p | %B %d, %Y"),
 +        contentTitle = "​Problème éventuel veuillez vérifier le scénario",​
 +        contentBody = message,
 +        img = "​../​img/​topDashboard/​warnings.png",​
 +        type = "​Warning",​
 +        buttons = {{ caption = "​Quitter",​ sceneId = 0 }}
 +      })  ​
 +    fibaro:​setGlobal("​Notification",​ message)
 +    fibaro:​call(105,​ "​pressButton",​ 2)
 +  end
 +  tools.log("​--- Terminé ---", "​lightblue",​ true)
 +  if (type(users_for_mail) ~= "​nil"​ and receiveEmail) then
 +    for _,v in ipairs(users_for_mail) do
 +      fibaro:​call(v,​ "​sendEmail",​ "HC2 Scénario " .. scene_name .. " v." .. version, mailmsg)
 +      --fibaro:​setGlobal("​Pushbullet",​ mailmsg)
 +    end
 +  end
 +end
 +
 +function boucle()
 +  setTimeout(function() boucle() end, run_every*60*60*1000)
 +  run()
 +end
 +
 +if (tools.isNotNil(run_every)) then
 +  boucle()
 +  tools.info("​will restart every " .. run_every .. " hours",​ "​lightblue"​)
 +else
 +  run()
 +end
 +</​code>​