setTimeOfDay - Mein Versionsvorschlag

Hi Ändy,

klingt gut. Ich habe gestern aus zeitgründen die Szenen-Neustart Variante eingebaut. Hat heute Nacht ebenfalls funktioniert. Ich hoffe aber auch darauf, dass einer der begabteren Programmierer (Najib) sich das Script einmal ansieht. Auf jeden Fall werde ich am Wochenende mal versuchen es auf Deine Weise umzusetzen.
Gruß
Alex

Hallo Ändy,

ich habe nochmal etwas herumprobiert und musste festestellen, dass es mit dem Scene reboot nicht so richtig klappt. Die neue Szene läuft dann parallel und die beiden kommen sich ins Gehege. Also habe ich mich jetzt Deiner Idee angeschlossen und versucht die Initialisierung in eine eigene Funktion zu packen. Leider bekomme ich lauter Fehler, weil die Variablen aus der InitTimeOfDay Funktion nicht an die Hauptfunktion übergeben werden. Kannst Du vielleicht doch schon mal Deine Lösung hier posten? Ich stehe auf dem Schlauch.
Grüße
Alex

@lodi, geht klar. Bitte probieren…

Vielleicht sollte man noch explizit zu dem Skript sagen, dass man die Anzahl der Instanzen unbedingt auf 1 setzen sollte. Sonst kann es durchaus passieren, dass man durch Probieren usw. mehrere gleichzeitig am Laufen hat, was bestimmt nicht sinnvoll ist.

Hier also die Version, die Jahreszeiten und Sonnenstand zur Laufzeit berücksichtigt:


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

-- ------------- Skript setDayTime --------------------------------------------

-- Hier Debugmode auf true setzen und es wird ein Simulationstag (24 Std) durchlaufen, 
-- der dir die moeglichen Ergebnisse zeigt jedoch keine Globale Variable ändert 
-- und keinen Timeout setzt
local debugMode = false 

-- Name der Globalen Variable im Home Center
local timeOfDayGlobalName = "TimeOfDay"

-- Mapping der TimeOfDay Eintraege in beliebiger Sprache 
-- der globalen Variable TimeOfDay entsprechend
local timeOfDayLabelMap = {Morning="Morning", Day="Day", Evening="Evening", Night="Night"}

-- Name der Globalen Variable im Home Center
local SeasonGlobalName = "Jahreszeit"

-- Mapping der Jahreszeit Eintraege in beliebiger Sprache 
-- der globalen Variable Jahreszeit entsprechend
local SeasonLabelMap = {Fruehling="Fruehling", Sommer="Sommer", Herbst="Herbst", Winter="Winter"}

local sourceTrigger = fibaro:getSourceTrigger()

local dayTimeList

--Color debugging
function ExtraDebug( color, message )
	--if (debugMode) then 
    	fibaro:debug(string.format('<%s style="color:%s;">%s</%s>', "span", color, message, "span")); 
	--end
end

-- Berechnet Uhrzeit in Sekunden (Differenz) ab 0:00 Uhr
function getTimeSecsDiff(s)
  local hours, minutes = string.match(s, "(%d+):(%d+)")
  -- Sekunden = Stunden * 60 (mins) * 60 (secs) + Minuten * 60 (secs)
  local calcSecs = (hours-1) * 60 * 60 + minutes * 60 
  return calcSecs
end  

--Start
function InitTimeOfDay()
	-- Strings Sonnenauf/-untergang im Format Stunde:Minute von fibaro geliefert
	local sunrise = fibaro:getValue(1, "sunriseHour")   -- Sonnenaufgang
	local sunset  = fibaro:getValue(1, "sunsetHour")    -- Sonnenuntergang

	-- Auslesen der aktuellen Jahreszeit (Globale Variable)
	local season = fibaro:getGlobal(SeasonGlobalName)
	fibaro:debug(string.format("Globale Variable '%s' aktueller Wert: '%s'", "Jahreszeit", season))

	-- Angaben der Bereichsgrenzen:
	--
	-- Hier koennen die Grenzen angeben werden, ab wann ein neuer Tagesbereich anfaengt.
	-- Der Erste Wert ist die Uhrzeit im Format Stunde:Minute, der zweite Wert  
	-- entspricht einem Offset (Verzoegerung) in Minuten bezogen auf den ersten Wert.
	-- Als ersten Wert koennen auch die Variablen sunset/sunrise genommen werden.
	--
	-- Beispiele:
	-- 
	-- globalMorning = { sunrise,  30 }  => Morgen beginnt 30 Minuten nach Sonnenaufgang
	-- globalMorning = { sunrise, -30 }  => Morgen beginnt 30 Minuten vor Sonnenaufgang
	-- globalEvening = { "18:00",   0 }  => Abend beginnt um genau 18:00 Uhr
	-- globalEvening = { sunset,   80 }  => Abend beginnt 80 Minuten nach Sonnenaufgang

	-- Allgemeine Zeiten; Gelten immer falls keine Zeiten angegeben wurden fuer die aktuelle Jahreszeit (Uebersteuerung)
	local globalMorning = { sunrise, 0 }
	local globalDay     = { "10:00", 0 }
	local globalEvening = { sunset, 0 }  
	local globalNight   = { "22:00", 0 }

	-- Hier koennen beliebige Zeiten eingegebn werden fuer die aktuelle Jahreszeit. 
	-- Der nil Wert bedeutet hier, das die globale Einstellung uebernommen werden soll
	-- Die Werte muessen der Reihenfolge Morgen Tag Abend und Nacht entsprechen.
	local seasonTimeTable = { Fruehling = { { sunrise, 0 }, 
	                                        { "10:00", 0 }, 
	                                        { sunset, 0 },
	                                        { "23:00", 0 } },
	                       
	                          Sommer    = { { sunrise, 0 }, 
	                                        { "09:00", 0 }, 
	                                        { sunset, 0 },
	                                        { "23:00", 0 } },                       
	                       
	                          Herbst    = { { sunrise, 0 }, 
	                                        { "10:00", 0 }, 
	                                        { sunset, 0 },
	                                        { "23:00", 0 } },
	                       
	                          Winter    = { { sunrise, 0 }, 
	                                        { "11:00", 0 }, 
	                                        { sunset, 0 },
	                                        { "23:00", 0 } }
	                        }
	
	--
	-- =========> Ab hier sind keine Einstellungen noetig  
	--

	-- hier werden die Werte der Jahreszeit entsprechend (falls angegeben) uebernommen
	-- ansonsten gelten die globalen Angaben
	morning = globalMorning          
	if (seasonTimeTable[season][1]) then
	  morning = seasonTimeTable[season][1]
	end

	day = globalDay          
	if (seasonTimeTable[season][2]) then
	  day = seasonTimeTable[season][2]
	end

	evening = globalEvening          
	if (seasonTimeTable[season][3]) then
	  evening = seasonTimeTable[season][3]
	end

	night = globalNight          
	if (seasonTimeTable[season][4]) then
	  night = seasonTimeTable[season][4]
	end

	-- Umrechnung der Bereichsgrenze in Sekunden ab 0:00 Uhr (Differenz)
	morning = getTimeSecsDiff(morning[1]) + morning[2] * 60
	day     = getTimeSecsDiff(day[1]) + day[2] * 60
	evening = getTimeSecsDiff(evening[1]) + evening[2] * 60                
	night   = getTimeSecsDiff(night[1]) + night[2] * 60

	if (debugMode) then
	  fibaro:debug("---------------- Voreinstellungen -----------------")
	  fibaro:debug(string.format("Es ist die Jahreszeit %s",season))
	  fibaro:debug(string.format("%s Uhr Sonnenaufgang",sunrise))
	  fibaro:debug(string.format("%s Uhr Sonnenuntergang",sunset))                                                                              
	  fibaro:debug(string.format("%s Uhr Morgen",os.date("%H:%M", morning)))
	  fibaro:debug(string.format("%s Uhr Tag",os.date("%H:%M", day)))
	  fibaro:debug(string.format("%s Uhr Abend",os.date("%H:%M", evening)))
	  fibaro:debug(string.format("%s Uhr Nacht",os.date("%H:%M", night)))
	end

	-- Table der Bereichsgrenzen
	dayTimeList = {
	                      {label = timeOfDayLabelMap.Morning, secs = morning},
	                      {label = timeOfDayLabelMap.Day,     secs = day},
	                      {label = timeOfDayLabelMap.Evening, secs = evening},
	                      {label = timeOfDayLabelMap.Night,   secs = night},
	                    }
                    
	-- Sortierung der Bereichsgrenzen nach Zeit (secs)                    
	local sort_func = function( a,b ) return a.secs < b.secs end
	table.sort(dayTimeList, sort_func)

end
  

-- Hauptfunktion zum setzen der Globalen Variable TimeOfDay 
function setTimeOfDay() 

  InitTimeOfDay() --Initialisierung in die Hauptfunktion mit rein! Sonst wird sunset, sunrise, season nicht aktualisiert.
  
  local aktTime = 0;
  local doLoop = true;
  local loopHour = 0; 
  local timeout = 0
  local setDayTime = nil

  if (debugMode) then
    fibaro:debug("---------------- Beginne Auswertung --------------")
  end 
        
  repeat

    local timeOfDayCur = fibaro:getGlobalValue(timeOfDayGlobalName)
    fibaro:debug(string.format("Globale Variable '%s' aktueller Wert: '%s'", timeOfDayGlobalName, timeOfDayCur))
    
    if (debugMode) then
      -- Testzeit zur Simulation         
      aktTime = getTimeSecsDiff(string.format("%02d:00",loopHour)) 
      if (loopHour == 24)then
        doLoop = false
      end
      loopHour = loopHour + 1
    else  
      -- aktuelle Zeit in Sekunden (Differenz)
      aktTime = getTimeSecsDiff(os.date("%H:%M"))
      doLoop = false
    end
    
    for i, record in ipairs( dayTimeList ) do
      
      if (aktTime < record.secs) then
        if (i == 1) then
          -- falls match beim ersten Element nehme 
          -- den letzte Zeitbereich in der Liste
          setDayTime = dayTimeList[#dayTimeList].label
        else  
          setDayTime = dayTimeList[i-1].label
        end   
        timeout = record.secs - aktTime;
        break;
      else
        setDayTime = nil  
      end  
      
      lastDayTime = record.label 
      
      if (i == 1) then
        firstSec = record.secs
      end  
    end
    
    -- Falls Zeitgrenze ueber Datumswechsel muss der Timeout extra berechnet werden
    if ( setDayTime == nil ) then
      setDayTime = lastDayTime
      timeout = 86400 - aktTime + firstSec 
    end  
    fibaro:debug(string.format("Es ist '%s' Uhr => setze Globale Variable '%s' auf '%s'", os.date("%H:%M", aktTime), timeOfDayGlobalName, setDayTime))
    
    -- setze globale Variable
    if (not debugMode) then
      fibaro:debug(string.format("Globale Variable '%s' auf den Wert '%s' gesetzt", timeOfDayGlobalName, setDayTime))
      fibaro:setGlobal(timeOfDayGlobalName, setDayTime)
    end; 
    
    -- Die Szene pausiert bis zum Wechsel in den naechsten Tagesbereich
    fibaro:debug(string.format("Timeout für %.2f Minuten", timeout/60))

  until not doLoop   
    
  if (not debugMode) then
    -- Setze Timeout
    --fibaro:debug( string.format("vor Timeeout:"));
    setTimeout(setTimeOfDay, timeout*1000)
  end;
     
end

--
-- ================ Main ( Aufruf Verarbeitung ) ==============================             
--

setTimeOfDay()

Hi Ändy,

super, vielen Dank. Hatte jetzt auch noch eine Lösung mit einer zweiten Szene, welche die Hauptszene täglich neu startet erfolgreich getestet. Aber so ist es dann doch noch eleganter.
Grüße
Alex