Eigentlich solltest Du mit der Suchfunktion hier und im Netz allgemein eine dreistellige Anzahl an Treffern zu diesem Thema finden können.
Alles, was einen Neustart von openHAB überleben soll, muss über einen Persistence Service gespeichert werden. Dabei wird der Status eines Items gespeichert. Dieser wird dann beim Neustart wiederhergestellt, falls das erwünscht ist. Du musst also das/die Item(s) in einer passenden Persistence eintragen. Wenn Du ohnehin Persistence nutzt (z.B. um Temperaturverläufe zu visualisieren) kannst Du diesen Dienst mit nutzen. Ansonsten bietet sich die mapdb Persistence an, die imer den aktuellen Wert speichert. Es wird also nur exakt ein Wert gespeichert, dafür braucht die Datenbank auch nur sehr wenig Platz. Natürlich kann auch nur der letzte Wert wiederhergestellt werden, nämlich wenn openHAB startet.
Wie Du schon gemerkt hast, ist in openHAB eine Funktion "Zeitschaltuhr" nicht vorgesehen. der Grund hierfür ist leicht erklärbar: Zeitschaltuhren sind eine Krücke, um ein Problem zu lösen. In den letzten Jahren wurde beispielsweise in vielen Rollladensteuerungen die Zeitschaltuhr durch eine Sonnenstandssteuerung ersetzt, was dem eigentlichen Wunsch wesentlich näher kommt, nämlich Läden, die bei über/unterschreiten einer bestimmten Helligkeit automatisch in eine vorgegebene Position fahren.
In openHAB geht das sehr bequem über das Astro Binding, wobei hier zusätzlich noch Grenzen definiert werden können, also der früheste und/oder späteste Zeitpunkt, zu dem ein Befehl erfolgen soll, beispielsweise "Öffne 10 Minuten nach Sonnenaufgang, frühestens um 6 Uhr, spätestens um 8 Uhr die Rollläden".
Wenn Du trotzdem mit fixen Zeiten arbeiten willst, kommt gleich die nächste Frage: Wie oft änderst Du die Zeit tatsächlich? In den meisten Fällen ist es das einfachste, eine Rule mittels Time cron Trigger aufzurufen, wobei die Zeit dann natürlich fix ist, es sei denn, man bearbeitet die Rule.
Soll es auf jeden Fall eine über die Oberfläche wählbare Zeit sein?
Überlege gut, ob Du tatsächlich Stunden und Minuten einstellen willst. Ich arbeite z.B. im Schichtdienst. Ich habe lange Zeit in der Größenordnung 20 verschiedene mögliche "Weckzeiten" gehabt, was wohl eher viel ist.
Wenn ich diese Zeiten über die Oberfläche wählbar hätte haben wollen, hätte ich ein Setpoint Item mit Klartextnamen für die verschiedenen Dienste eingerichtet, ich hab doch keine Lust, immer Minuten und Stunden auszuwählen...
Trotzdem kannst Du natürlich Stunden und Minuten einstellbar machen, so wie von Dir angedeutet.
Allerdings möchtest Du keinen String, um diese Information zu speichern, allenfalls für die Anzeige taugt ein String, wobei auch das ...
Zum Ausführen des Timers benötigst Du auf jeden Fall eine Zahl, am besten die Anzahl Minuten ab Mitternacht (also Stunde * 60 + Minute), dann kannst Du eine Rule so gestalten, dass sie einen entsprechenden Timer anlegt. Alternativ kannst Du auch das Format DateTime verwenden, aber es ist nicht trivial, aus DateTime passende Timer zu bauen. Die meisten im Netz kursierenden Lösungen verwenden deshalb eine Rule, die regelmäßig gestartet wird und überprüft, ob die Zeit schon erreicht wurde. Das ist natürlich ineffizient, auch wenn eine entsprechende Rule nicht allzusehr aufträgt.
Für die Darstellung in der Sitemap brauchst Du die Zeit in Stunden und Minuten, entweder erzeugst Du einen String passend, oder Du nutzt ein DateTime Item (dort kann man auch die Anzeige so manipulieren, dass nur Stunden und Minuten angezeigt werden.)
Wenn Du innerhalb eine Rule auf den Status eines Items zugreifen willst, passiert das immer über die Eigenschaft .state. Falls es sich um ein Number Item handelt und Du den Status als Zahl verwenden willst, solltest Du den Wert explizit zum Typ Number casten.
Wenn Du den Status eines Items ändern möchtest (z.B. um eine Anzeige in der UI zu setzen) geht das über die Action postUpdate(Item as String, Value as String) bzw. über die Methode Item.postUpdate(Value), wobei letztere Variante grundsätzlich zu bevorzugen ist.
Soll das Item an ein Binding gesendet werden (sei es als Befehl oder als Anzeige) heißen die entsprechende Action bzw. Methode sendCommand. Auf Deine Rule aufsetzend sähe das dann so aus:
Code: Alles auswählen
// globale Variablen werden ganz zu Beginn des *.rules Files definiert
var Timer myTimer = null
rule "Test1"
when
Item S_Zeit changed to ON
then
if(!(N_Stunde.state instanceof Number)) {
logWarn("Test1","Stunde ungültig! Abbruch!")
return;
}
if(!(N_Minute.state instanceof Number)) {
logWarn("Test1","Minute ungültig! Abbruch!")
return;
}
var String sZeit
if((N_Stunde.state as Number) < 10)
sZeit="0"
sZeit = sZeit + N_Stunde.state.toString + ":"
if((N_Minute.state as Number) < 10)
sZeit = sZeit + "0"
sZeit = sZeit + N_Minute.state.toString
T_Zeit.postUpdate(sZeit)
val Number myTime = (N_Stunde.state as Number) * 60 + (N_Minute.state as Number)
myTimer?.cancel
myTimer = createTimer(now.withTimeAtStartOfDay.plusMinutes(myTime).plusDays(if(now.getMinuteOfDay < myTime) 0 else 1), [ |
mySwitchedItem.sendCommand(ON)
myTimer.reschedule(now.plusDays(1))
])
end
Der obere Teil der Rule prüft, ob alle Voraussetzungen für das Anlegen des Timers gegeben sind (also sowohl Stunde als auch Minute einen gültigen Wert haben).
Im nächsten Block wird der String für die Anzeige berechnet. Falls Stunde oder Minute einstellig sind, wird jeweils eine 0 ergänzt. Zum Abschluss wird der errechnete String an das Item geschickt.
Zuletzt wird die Startzeit berechnet, ein eventuell bestehender Timer gelöscht und abschließend erzeugt, wobei der Timer automatisch für den nächsten Tag geplant wird, falls die Schaltzeit am aktuellen Tag schon vergangen ist.
Der Timer selbst wird vom Scheduler zur geplanten Zeit ausgeführt, das Item wird angesteuert, anschließend wird der Timer für den nächsten Tag neu geplant.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet