Skript minütlich starten

Hallo,

ich habe ein kleines Problem mit einer Szene, die bei einer bestimmten Uhrzeit ausgeführt werden soll. Die Uhrzeit ist in einer GV abgelegt. Leider wird die Szene nicht ausgeführt. Das Einstellen der Uhrzeit geschieht über ein VD. Stelle ich genau die Systemzeit ein, dann wird die Szene ausgeführt. Stelle ich aber eine Uhrzeit in der Zukunft ein, wird die Szene zu dieser Zeit nicht ausgeführt.
Gibt es eine Möglichkeit eine Szene z.B. jede Minute zu starten. Dann müßte es eigentlich klappen.

Hallo SteMo,

das HC hat keinen Scheduler im eigentlichen Sinne. Zeitgesteuerte Szenen werden immer in Dauerschleife gestartet und prüfen bei jedem Durchlauf in einer Bedingung, ob die gewünschte Uhrzeit erreicht ist. Ist die Zeit erreicht wird der Code ausgeführt, wenn nicht mittels einer sleep-Funktion wieder eine Minute gewartet und dann erneut geprüft.

Danke für die Info.
Aber irgend etwas mache ich falsch. Ich habe es jetzt mal so versucht, läuft aber nicht. Kannst Du da einen Fehler entdecken?

local sourceTrigger = fibaro:getSourceTrigger();
if (sourceTrigger["type"] == "autostart") then
    while true do
        fibaro:debug('Start der Heizungstimerszene.')

        local currentDate = os.date("*t");

			local std_h = fibaro:getGlobalValue('std_heizung')
			local min_h = fibaro:getGlobalValue('min_heizung')

			if ( tonumber(fibaro:getGlobalValue("heizung_aktiv")) == tonumber("1") ) and  ( string.format("%02d:%02d", currentDate.hour, currentDate.min) == string.format("%02d:%02d", std_h, min_h) )
			then
				fibaro:call(89, "turnOn");
				setTimeout(function()
				fibaro:call(89, "turnOff");
				end, 70000)
			end
	end

 fibaro:sleep(1*60000); -- läuft jede Minute 1 x

end

Moin SteMo,

wenn ich den Code richtig interpretiere, möchtest Du zu der in den globalen Variablen definierten Zeit die ein Gerät (Heizung vermutlich) einschalten und sie nach 70000 Millisekunden wieder ausschalten, richtig?

Aber im Einzelnen:
Mit while true do erreichst Du, dass die Schleife ewig läuft, also nie beendet wird. Ist hier ja auch sinnvoll, da die Aktion ja bei jedem erreichen der eingestellten Zeit ausgeführt werden soll. Allerdings wird die Sleep-Funktion nie erreicht, denn diese liegt ausserhalb der while-Schleife. Auch würde ich nicht auf setTimeout zurückgreifen, sondern auch hier Sleep benutzen.

Versuche es mal so:

local sourceTrigger = fibaro:getSourceTrigger();
if (sourceTrigger["type"] == "autostart") then
    while true do
        fibaro:debug('Start der Heizungstimerszene.')
        local currentDate = os.date("*t");
		local std_h = fibaro:getGlobalValue('std_heizung')
		local min_h = fibaro:getGlobalValue('min_heizung')
		
		if ( tonumber(fibaro:getGlobalValue("heizung_aktiv")) == tonumber("1") ) and  ( string.format("%02d:%02d", currentDate.hour, currentDate.min) == string.format("%02d:%02d", std_h, min_h) )
		then
			fibaro:debug("Zeit erreicht, einschalten")
			fibaro:call(89, "turnOn");
			fibaro:debug("70 Sekunden warten")
			fibaro:sleep(70000)
			fibaro:debug("ausschalten")
			fibaro:call(89, "turnOff");
		end
		fibaro:debug("1 Minute warten...")
		fibaro:sleep(1*60000); -- läuft jede Minute 1 x
		
	end
end

Also an sich ist dieses ausführen aller X sekunden schon möglich, aber ich glaube das “setTimeout” wird falsch verwendet SteMo. Du kannst die funktion rekursiv ausführen, zb mit

var wechselschalter = 0
funktion ()
  if (wechselschalter == 0) then
    licht an
    wechselschalter = 1
  else
    licht aus
    wechselschalter = 0
  end
  setTimeout(funktion ,60*1000)
end

Das setTimeout am ende führt die Funktion erneut nach X Sekunden aus und wird hier am ende der Funktion selbst aufgerufen. Ich hoffe, das hilft dir weiter.

Grüße

Daniel

Danke Euch beiden,

ich habe es jetzt fast hin. Scheinbar gibt es Probleme mir der GV ‘heizung_aktiv’. Bei 1 soll die Szene ausgeführt werden, bei 2 nicht. Beim Skript von Bastian startet die Szene nie. Wieso nicht, keine Ahnung.

Ich habe das Skript jetzt so umgeschrieben:

--[[
%% autostart
%% properties
%% events
%% globals
heizung_aktiv
min_heizung
std_heizung
--]]

local sourceTrigger = fibaro:getSourceTrigger();
if ( tonumber(fibaro:getGlobalValue("heizung_aktiv")) == tonumber("1")) then
    while true do
 --       fibaro:debug('Start der Heizungstimerszene.')
        local currentDate = os.date("*t");
 local std_h = fibaro:getGlobalValue('std_heizung')
 local min_h = fibaro:getGlobalValue('min_heizung')
 
 if (string.format("%02d:%02d", currentDate.hour, currentDate.min) == string.format("%02d:%02d", std_h, min_h) )
 then
 fibaro:debug("Zeit erreicht, einschalten")
 fibaro:call(89, "turnOn");
 fibaro:debug("70 Sekunden warten")
 fibaro:sleep(70000)
 fibaro:debug("ausschalten")
 fibaro:call(89, "turnOff");
 fibaro:sleep(7000)
 fibaro:setGlobal("heizung_aktiv", 2);
 end
 fibaro:debug("1 Minute warten...")
 fibaro:sleep(1*60000); -- läuft jede Minute 1 x
 
 end
end

Jetzt startet die Szene wie gewünscht. Wenn ich mit dem GD die GV ‘heizung_aktiv’ auf aus, also 2 stelle, startet das Skript auch nicht mehr. Wenn ich die GV aber per
fibaro:setGlobal(“heizung_aktiv”, 2);
auf aus stelle, registriert das Skript es nicht und schaltet die Heizung trotzdem an.

Wißt Ihr weshalb das so ist?

By the way, die Heizdauer mit 70 sec habe ich nur um testen so kurz eingestellt. Wenn das Skript läuft sollen es 30 Minuten sein.

sorry kleiner Schreibfehler. GD soll natürlich VD (virtual device) heißen.

Hi,

ändere mal

tonumber(fibaro:getGlobalValue("heizung_aktiv")) == tonumber("1")

in

fibaro:getGlobal('heizung_aktiv') == 1

Und entferne die %globals aus dem Header.

Gruß

Hallo,
ich habe wie vorgeschlagen die 3 Einträge bei %%globals gelöscht.
Das Problem ist aber immer noch da. Wenn ich in der GV die ‘heizung_aktiv’ auf 1 stelle läuft die Szene. Am Ende der Szene wird ‘heizung_aktiv’ auf 2 gestellt, aber wenn ich jetzt eine neue Uhrzeit einstelle springt die Heizung wieder an. Scheinbar wird
tonumber(fibaro:getGlobalValue(“heizung_aktiv”)) == tonumber(“1”)
nicht mehr abgefragt. Nur wenn ich an der GV auf aus, also 2 schalte funktioniert es. Dann steht das Skript wie gewünscht.

fibaro:getGlobal('heizung_aktiv') == 1
wird gar leider nicht ausgeführt!

Noch eine Idee?

… und schon wieder verschrieben. Es war wohl zu spät am Abend. Also noch einmal …

Hallo,
ich habe wie vorgeschlagen die 3 Einträge bei %%globals gelöscht.
Das Problem ist aber immer noch da. Wenn ich im VD die ‚heizung_aktiv‘ auf 1 stelle läuft die Szene. Am Ende der Szene wird ‚heizung_aktiv‘ auf 2 gestellt, aber wenn ich jetzt eine neue Uhrzeit einstelle springt die Heizung wieder an. Scheinbar wird
tonumber(fibaro:getGlobalValue("heizung_aktiv")) == tonumber("1")
nicht mehr abgefragt. Nur wenn ich nun im VD auf aus, also 2 schalte funktioniert es. Die Heizung springt nicht mehr an.

Warum funktioniert alles wenn ich die GV (1 oder 2) direkt über das VD eingebe, aber nicht wenn es im LUA Skript gesetzt wird? Die GV wird doch immer über ‘fibaro:getGlobalValue’ ausgelesen. Oder habe ich da einen Denkfehler?

fibaro:getGlobal('heizung_aktiv') == 1
wird gar leider nicht ausgeführt!

Noch eine Idee?

Hallo SteMo,

zuerst einmal sehe ich Dein Anliegen nicht als Problem. Viel mehr machst Du in meinen Augen einen logischen Fehler.
Wenn Du Dir Deine Szene einmal aufmalst und anschaust, dann wirst Du es sehen:

Die Abfrage nach heizung_aktiv erfolgt ausserhalb der while-Schleife. Beim Ändern der Variable befindet sich die Szene “nach” der Prüfung heizung_aktiv == 1 und somit wird nur noch die Uhrzeit geprüft und nicht mehr der Status der Variable.

Wenn Du die while-Schleife immer startest, also unabhängig von heizung_aktiv, und innerhalb der Schleife heizung_aktiv prüfst, dann funktioniert es.

In etwa so:

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

local sourceTrigger = fibaro:getSourceTrigger();
    while true do
		if ( tonumber(fibaro:getGlobalValue("heizung_aktiv")) == tonumber("1")) then
			--       fibaro:debug('Start der Heizungstimerszene.')
			local currentDate = os.date("*t");
			local std_h = fibaro:getGlobalValue('std_heizung')
			local min_h = fibaro:getGlobalValue('min_heizung')
	 
			 if (string.format("%02d:%02d", currentDate.hour, currentDate.min) == string.format("%02d:%02d", std_h, min_h) )
			 then
				 fibaro:debug("Zeit erreicht, einschalten")
				 fibaro:call(89, "turnOn");
				 fibaro:debug("70 Sekunden warten")
				 fibaro:sleep(70000)
				 fibaro:debug("ausschalten")
				 fibaro:call(89, "turnOff");
				 fibaro:sleep(7000)
				 fibaro:setGlobal("heizung_aktiv", 2);
			 end
	 fibaro:debug("1 Minute warten...")
	 fibaro:sleep(1*60000); -- läuft jede Minute 1 x
 
		end
	end

Das nächste “Problem” was auf Dich zukommt ist, dass die Szene im Autostart läuft und keine Änderungen Variable mitbekommt. Diese solltest Du ebenfalls in der while-Schleife auslesen, so wie Du es mit der Uhrzeit schon tust, aber alles VOR der Prüfung auf die heizung_aktiv + Uhrzeit und INNERHALB der while-Schleife.

Auch verstehe ich nicht, was Du mit heizung_aktiv == 2 erreichen möchtest. Dies führt dazu, dass die Szene genau einmal einschaltet, aber weiter läuft. Ohne Änderungen an heizung_aktiv wird die Bedinung nie wieder erfüllt. Dann kannst Du die while-Schleife auch nach dem Erfüllen der Bedinung beenden und sie durch die Änderung der Variable neustarten. Hier dann natürlich darauf achten, dass sie immer nur einmal läuft.

vielen, vielen Dank,
jetzt klappe es endlich.

heizung_aktiv == 2 bewirkt das die Heizung nicht einschaltet. Bei heizung_aktiv == 1 und erreichen der Uhrzeit schaltet sie ein.