Abwesenheitscheck per LUA

Hallo zusammen,

da ich keine funktionierende Block-Szene hinbekommen habe, habe ich mich mal an LUA versucht. Ziel: Eine Szene soll zyklisch checken, ob alle Motionsensoren safe sind und dann schauen, ob der Zustand seit Zeit x nicht mehr verändert wurde. Falls beides zutrifft soll die globale Variable Away gesetzt werden.

Habe aber jetzt das Problem, dass das Skript beim 2 Druchlauf auf ein NIL läuft, aber ich nicht weiß wo oder wieso. Vielleicht findet von euch einer den Fehler?

Skript:

--[[
%% autostart
%% properties
%% globals
--]]

if fibaro:countScenes() > 1 then
  fibaro:debug("stop scene");
  fibaro:abort();
end

local sourceTrigger = fibaro:getSourceTrigger();

function checkAway()

motionSensors = {23,89,106} -- IDs of the Motionsensors
noMotionTime = 600 -- Time in seconds that Sensors are safe 
  
function checkNoMotion()
  noMotion = true
  for i = 1, #motionSensors do
    if (noMotion) then
      --fibaro:debug("Value of "..i.." is "..tonumber(fibaro:getValue(motionSensors[i]), "value"))
      if ( tonumber(fibaro:getValue(motionSensors[i], "value")) > 0 ) then
        noMotion = false;
      end
    end
  end   
  fibaro:debug("checkNoMotion returned: "..tostring(noMotion))  
  return noMotion  
end

function checkLastModified()
  timeElapsed = true
  for i = 1, #motionSensors do
    if (timeElapsed) then
      --fibaro:debug("LastMotion of "..i.." is "..tonumber(fibaro:getValue(motionSensors[i], "value")))
      if (tonumber(fibaro:getModificationTime(motionSensors[i], "value")) >= noMotionTime ) then
        timeElapsed = false;  
      end    
  	end
  end 
  fibaro:debug("checkLastModified returned: "..tostring(timeElapsed))
  return timeElapsed     
end

motioncheckReturn = checkNoMotion()
lastModifiedReturn = checkLastModified()

if (motioncheckReturn  and  lastModifiedReturn) then
    fibaro:debug("No Motion since "..noMotionTime)
    fibaro:debug("Setting PresenceState: Away")
  	--fibaro:setGlobal("PresentState", "Away")
end
setTimeout(varTime, 60*1000);
end  
  
if (sourceTrigger["type"] == "autostart") then
 checkAway();
elseif 
  (sourceTrigger["type"] == "other") then
  --fibaro:setGlobal("PresentState", "Away")
  fibaro:debug("Setting PresenceState: Away")
end

Output:
Lua Error: Attempt to call a NIL Value

Hi,

witzig, hab letztens was ähnliches gemacht :wink: mach es aber nicht zyklisch, sondern lass die Szene Triggern. Macht meiner Einschätzung nach mehr Sinn.

Artikel dazu kommt heute Abend :slight_smile: Kannst dir ja mal anschauen.

Gruß

Das klingt gut. Trotzdem wurmt mich der Fehler… Will ja auch was lernen :wink:

So, Fehler gefunden. War diese Zeile, da der Name der Funktion falsch, also nicht definiert = NIL ist…
setTimeout(varTime, 60*1000);

Und hier das überarbeite Endergebnis, das es nun tun sollte:


--[[
%% autostart
%% properties
%% globals
--]]
----------- Limit Scene to 1 instance ----------------
if fibaro:countScenes() > 1 then
  fibaro:debug("stop scene");
  fibaro:abort();
end
----------- Local Variables --------------------------
local sourceTrigger = fibaro:getSourceTrigger();
local motioncheckReturn = false
local lastModifiedReturn = false
local awayReturn = false
------------------ Individual variables - Change Here ----------------
local motionSensors = {23,62,89,106} -- IDs of the Motionsensors
local noMotionTime = 600 -- Time in seconds that Sensors are safe 

local extraDebug = true -- More Debug-Infos
------------------ Do not change below unless skilled ;-) ------------
function checkAway()
  
function checkNoMotion()
  noMotion = true
  for i = 1, #motionSensors do
    if (noMotion) then
      fibaro:debug("Value of "..motionSensors[i].." is "..fibaro:getValue(motionSensors[i], "value"))
      if ( tonumber(fibaro:getValue(motionSensors[i], "value")) > 0 ) then
        noMotion = false;
      end
    end
  end   
  fibaro:debug("checkNoMotion returned: "..tostring(noMotion))  
  return noMotion  
end

function checkLastModified()
  timeElapsed = true
  for i = 1, #motionSensors do
    if (timeElapsed) then
      if (extraDebug) then 
          fibaro:debug("LastMotion of "..motionSensors[i].." is "..os.time()-fibaro:getModificationTime(motionSensors[i], "value"))
      end    
      if (os.time() - tonumber(fibaro:getModificationTime(motionSensors[i], "value")) <= noMotionTime ) then
        timeElapsed = false;  
      end    
  	end
  end 
  if (extraDebug) then 
  	fibaro:debug("checkLastModified returned: "..tostring(timeElapsed))
  end
  return timeElapsed     
end

function checkAwake()
  awake = false 
  if (fibaro:getGlobalValue("SleepState") == "Awake" and fibaro:getGlobalValue("BedroomState") == "Awake") then
      awake = true
  else awake = false      
  end
  if (extraDebug) then 
  	fibaro:debug("checkAwake returned: "..tostring(awake))
  end
  return timeElapsed     
end  
  
motioncheckReturn = checkNoMotion()
lastModifiedReturn = checkLastModified()
awakeReturn = checkAwake()

if (motioncheckReturn  and  lastModifiedReturn and awakeReturn) then
    fibaro:debug("Nobody Sleeping. No Motion since "..noMotionTime)
    fibaro:debug("Setting PresenceState: Away")
    if fibaro:getGlobalValue("PresentState") == "Home" then
  		fibaro:setGlobal("PresentState", "Away")
    end
else
    fibaro:debug("Somebody Sleeping or Motion detected")
    fibaro:debug("Not Changing PresentState")    
end
setTimeout(checkAway, 60*1000);
end  
  
if (sourceTrigger["type"] == "autostart") then
 checkAway();
elseif 
  (sourceTrigger["type"] == "other") then
  fibaro:debug("Setting PresenceState: Away")
  if fibaro:getGlobalValue("PresentState") == "Home" then
  		fibaro:setGlobal("PresentState", "Away")
  end
end

Nehme gern Verbesserungsvorschläge und Style-Tips entgegen.

Gruß
Markus