Das erwartet dich in diesem Artikel
Timer mit einem Datenpunkt steuern
Neuen Datenpunkt erstellen
Für einen einfachen Timer, den du über einen einzigen Datenpunkt steuern, starten und stoppen kannst, benötigst du erstmal einen neuen Datenpunkt vom Typ Zahl
:
In diesen Datenpunkt wird die Dauer des Timers als Sekundenwert geschrieben. Gleichzeitig überwacht ein Script, ob in diesen Datenpunkt geschrieben wurde und startet dadurch den Timer.
Blockly-Script aufbauen
Ziehe dir einen Trigger
-Block in den Editor und stelle ihn auf wurde geändert
. Als Objekt ID wählst du den eben angelegten Datenpunkt. In den Aktionsbereich fügst du einen falls
-Block aus dem Bereich Logik ein und stellst diesen über das blaue Zahnrad auf falls — sonst
. An den Eingang steckst du den Objekt ID
-Block aus dem Bereich Trigger und wählst die Option Wert
:
Als Nächstes benötigst du einen timeout
-Block sowie einen stop timeout
-Block darüber (warum dieser Block hier sinnvoll ist und was er macht, erfährst du in diesem Artikel):
Füge anschließend einen aktualisiere
-Block aus dem Bereich System in den „mache“-Bereich und wähle für die Objekt ID den oben erstellten Datenpunkt „Timer“ aus. Setze dann in das Feld „mit“ den Mathematik-Block 1+1
, stelle den Operator auf -
und setze statt der ersten Zahl den Objekt ID
-Block aus dem Bereich „Trigger“ mit der Option Wert
:
Durch diesen Block wird der Datenpunkt mit seinem eigenen Wert, der jede Sekunde um 1 weniger wird, aktualisiert.
Setze in den „sonst“-Bereich eine neue falls
-Logik, die abfragt, ob der Countdown vorher manuell gestoppt wurde. Denn wenn du den Countdown manuell (durch eine „0“ – siehe unten) stoppst, war der vorherige Wert sicher größer als „1“ und du erhältst keine Benachrichtigung. Falls dies nicht der Fall ist, erhältst du nach Ablauf des Timers eine Benachrichtigung. Dafür ziehst du an den Eingang des falls
-Block einen =
-Block aus dem Bereich Logik. In das erste Feld fügst du den Objekt ID
-Block aus dem Bereich Trigger und wählst die Option vorheriger Wert
. In das zweite Feld setzt du die Zahl 1
aus dem Bereich Mathematik:
In den „mache“-Bereich setzt du die Aktion, die ausgeführt werden soll, wenn der Timer abgelaufen ist. Zum Beispiel einen sendto
-Block oder eine Sprachausgabe über Alexa:
Starten und Stoppen des Timers
Sobald du den Datenpunkt mit einem Wert befüllst, startet der Timer automatisch und zählt von dem eingegebenen Wert rückwärts bis „0“ und führt dann deine Aktion aus.
Zum Stoppen des Timers schreibst du einfach eine „0“ in den Datenpunkt. Dadurch ist die Bedingung der Logik negativ — Intervall und der Timer werden gestoppt. Mehr über Kurzformen im Logikblock kannst du in diesem Artikel nachlesen.
Timer mit 2. Datenpunkt starten und stoppen
Weiteren Datenpunkt erstellen
Damit der Timer über einen zweiten Datenpunkt gestartet und gestoppt werden kann, benötigst du natürlich einen 2. Datenpunkt vom Typ Logikwert
:
Blockly-Script aufbauen
Ziehe dir einen Trigger-Block mit einem externen Eingang in den Editor und stelle ihn auf wurde geändert
. Stelle ihn über das blaue Zahnrad auf 2 Eingänge. Als erste Objekt ID wählst du den eben angelegten Datenpunkt. Als zweite Objekt ID wählst du den Datenpunkt „Timer“ aus dem ersten Beispiel.
In den Aktionsbereich fügst du einen falls
-Block aus dem Bereich Logik ein und stellst diesen über das blaue Zahnrad auf falls — sonst
. An den Eingang steckst du den Wert von Objekt ID
-Block aus dem Bereich System mit der Objekt ID des Datenpunkts „Timer-Steuerung“:
Dann benötigst du einen weiteren falls
-Block aus dem Bereich Logik. Ziehe ihn dir in den „mache“-Bereich und stecke an den Eingang des Blocks einen Wert von Objekt ID
-Block aus dem Bereich System mit der Objekt ID des Datenpunkts „Timer“:
Füge anschließend einen aktualisiere
-Block aus dem Bereich System in den „mache“-Bereich und wähle für die Objekt ID den im ersten Beispiel erstellten Datenpunkt „Timer“ aus. Setze dann in das Feld „mit“ den Mathematik-Block 1+1
, Stelle den Operator auf -
und statt der ersten Zahl einen Wert von Objekt ID
-Block aus dem Bereich System mit der Objekt ID des Datenpunkts „Timer“:
Durch diesen Block wird der Datenpunkt „Timer“ mit seinem eigenen Wert, der jede Sekunde um 1 weniger wird, aktualisiert.
In den „sonst“-Bereich steckst du einen umschalten
-Block aus dem Bereich System mit der Objekt ID des Datenpunkts „Timer-Steuerung“. Dadurch wird der Datenpunkt „Timer-Steuerung“ automatisch auf „falsch“ gesetzt, wenn der Countdown abgelaufen ist.
Zusätzlich kannst du in den „sonst“-Bereich die Aktion, die ausgeführt werden soll, wenn der Timer abgelaufen ist, einstecken. Zum Beispiel einen sendto
-Block oder eine Sprachausgabe über Alexa:
Zuletzt fügst du einen stop timeout
-Block in den „sonst“-Bereich des übergeordneten „falls“-Block ein:
Optionale Einstellungen
Möchtest du zusätzlich wissen, ob der Timer abgebrochen wurde oder den Datenpunkt „Timer“ nach Abbruch auf „0“ setzen, fügst du eine weitere falls
-Logik in den „sonst“-Bereich des übergeordneten „falls“-Block ein. An den Eingang dieses Blocks steckst du einen Wert von Objekt ID
-Block aus dem Bereich System mit der Objekt ID des Datenpunkts „Timer“:
Anschließend setzt du eine Aktion ein, die bei Abbruch gestartet werden soll. Zusätzlich kannst du mit dem System-Block steuere
den Datenpunkt „Timer“ zurücksetzen, indem du eine 0
aus dem Bereich Mathematik in das Feld einsetzt:
Starten und Stoppen des Timers
Sobald du den Datenpunkt „Timer-Steuerung“ auf „wahr“ stellst, startet der Timer automatisch und zählt von dem eingegebenen Wert rückwärts bis „0“ und führt dann deine Aktion aus.
Zum Stoppen des Timers stellst du den Datenpunkt einfach wieder auf „falsch“ — Intervall und der Timer werden gestoppt. Mehr über Kurzformen im Logikblock kannst du in diesem Artikel nachlesen.
Fertiges Script
Blockly
<xml xmlns="https://developers.google.com/blockly/xml">
<variables>
<variable type="timeout" id="timeout">timeout</variable>
</variables>
<block type="on_ext" id="oeda!u0}8(qt14v+zBAq" x="88" y="38">
<mutation xmlns="http://www.w3.org/1999/xhtml" items="2"></mutation>
<field name="CONDITION">ne</field>
<field name="ACK_CONDITION"></field>
<value name="OID0">
<shadow type="field_oid" id="VfQYDmTUmKT!IoRs|p*_">
<field name="oid">0_userdata.0.Timer</field>
</shadow>
</value>
<value name="OID1">
<shadow type="field_oid" id="Wj=)GF2RzpY0gd8gl_f7">
<field name="oid">Eigene.0.Timer-Steuerung</field>
</shadow>
</value>
<statement name="STATEMENT">
<block type="controls_if" id="~3yv9G5%M8{mu8Jb#5-H">
<mutation else="1"></mutation>
<value name="IF0">
<block type="get_value" id="Q(J=,|.c*Mzf-o.FLqkq">
<field name="ATTR">val</field>
<field name="OID">Eigene.0.Timer-Steuerung</field>
</block>
</value>
<statement name="DO0">
<block type="controls_if" id="XdEgOM9cLt/UgPuX*2PS">
<mutation else="1"></mutation>
<value name="IF0">
<block type="get_value" id="),I!o==XH)ALF3??67m.">
<field name="ATTR">val</field>
<field name="OID">0_userdata.0.Timer</field>
</block>
</value>
<statement name="DO0">
<block type="timeouts_cleartimeout" id="Ix1oxVIMw/6InEOx*J1v">
<field name="NAME">timeout</field>
<next>
<block type="timeouts_settimeout" id="l@}3.P=,2vKmio0`zLBU">
<field name="NAME">timeout</field>
<field name="DELAY">1000</field>
<field name="UNIT">ms</field>
<statement name="STATEMENT">
<block type="update" id="Ro;pf)L}Y53/I@ojBH~A">
<mutation xmlns="http://www.w3.org/1999/xhtml" delay_input="false"></mutation>
<field name="OID">0_userdata.0.Timer</field>
<field name="WITH_DELAY">FALSE</field>
<value name="VALUE">
<block type="math_arithmetic" id="}QY!Vqv.wC{OGY6siZeY">
<field name="OP">MINUS</field>
<value name="A">
<shadow type="math_number" id="))QJ!OPuyKRR]?YWn.3c">
<field name="NUM">1</field>
</shadow>
<block type="get_value" id="V$ZG03{6.7~(m2rW~NBl">
<field name="ATTR">val</field>
<field name="OID">0_userdata.0.Timer</field>
</block>
</value>
<value name="B">
<shadow type="math_number" id="?Ia}=S/fr0dA|Q`iE)x`">
<field name="NUM">1</field>
</shadow>
</value>
</block>
</value>
</block>
</statement>
</block>
</next>
</block>
</statement>
<statement name="ELSE">
<block type="toggle" id="A%Z%`xgauVNXhZ7JUmh]">
<mutation xmlns="http://www.w3.org/1999/xhtml" delay_input="false"></mutation>
<field name="OID">Eigene.0.Timer-Steuerung</field>
<field name="WITH_DELAY">FALSE</field>
</block>
</statement>
</block>
</statement>
<statement name="ELSE">
<block type="timeouts_cleartimeout" id="YF/%*Srl3X[v-?h2~]R~">
<field name="NAME">timeout</field>
<next>
<block type="controls_if" id="uKjC@4wN,B?dDeB4V1E,">
<value name="IF0">
<block type="get_value" id="[yS#c^Q./ZSPmC-wgGa^">
<field name="ATTR">val</field>
<field name="OID">0_userdata.0.Timer</field>
</block>
</value>
<statement name="DO0">
<block type="control" id="9?ORg0`fdc`;SF{,1F=S">
<mutation xmlns="http://www.w3.org/1999/xhtml" delay_input="false"></mutation>
<field name="OID">0_userdata.0.Timer</field>
<field name="WITH_DELAY">FALSE</field>
<value name="VALUE">
<block type="math_number" id="@tG|2S;P!fa,R^C`m~?%">
<field name="NUM">0</field>
</block>
</value>
</block>
</statement>
</block>
</next>
</block>
</statement>
</block>
</statement>
</block>
</xml>
Javascript
let timeout;
on({id: new RegExp('0_userdata\\.0\\.Timer' + "|" + 'Eigene\\.0\\.Timer-Steuerung'), change: "ne"}, function (obj) {
if (getState("Eigene.0.Timer-Steuerung").val) {
if (getState("0_userdata.0.Timer").val) {
(function () {if (timeout) {clearTimeout(timeout); timeout = null;}})();
timeout = setTimeout(function () {
setState("0_userdata.0.Timer"/*Timer*/, (getState("0_userdata.0.Timer").val - 1), true);
}, 1000);
} else {
getState("Eigene.0.Timer-Steuerung", function (err, state) {
setState("Eigene.0.Timer-Steuerung"/*Timer-Steuerung*/, state ? !state.val : true);
});
}
} else {
(function () {if (timeout) {clearTimeout(timeout); timeout = null;}})();
if (getState("0_userdata.0.Timer").val) {
setState("0_userdata.0.Timer"/*Timer*/, 0);
}
}
});
Ausgabe in einer Visualisierung
Möchtest du den Timer in deiner Visualisierung anzeigen, kannst du das über ein Binding machen. Mehr zu Bindngs erfährst du in diesem Artikel. Folgende Codes kannst du in einem HTML-Widget nutzen:
Gesamtausgabe im Format „X:XX Minuten“
{time:Eigene.0.Timer;Math.floor((time % 3600)/(60))+':'+Math.floor(time % 60)+' Minuten'}
Minutenausgabe
{time:Eigene.0.Timer;Math.floor((time % 3600)/(60))}
Sekundenausgabe
{time:Eigene.0.Timer;Math.floor(time % 60)}
6 Kommentare
Kommentieren[…] Hier erfährst du, wie du mithilfe des “timeout”-Blocks einen einfachen Timer selber ers… […]
Ich muss mich schon schwer täuschen, aber gibt es nicht zwischenzeitlich für den iobroker einen Adapter Countdown mit dem entsprechenden Blockly Baustein?
Es ist aktuell einer als Beta verfügbar und kommt hoffentlich bald ins Stable-Repository. Bei der obigen Anleitung geht es darum, Verständnis für die Blöcke zu vermitteln. Viele Grüße
Alles gut, funktioniert auch – aber:
Ich möchte den Timer ( sleep ) auf 40 Sekunden setzen. So lange braucht mein Raspi mit Volumio um zu booten.
Dann möchte ich die Instanz Volumio restarten und ein Play absetzen.
Scheinbar läuft der Timer ( sleep) nicht so lange. Muss ich das Systemweit in ioBroker einstellen?
Gruss
Reinhard
Es gibt seit einiger Zeit neue Timerbasierte Blöcke. Es wäre super, wenn die Verwendung dieser Blöcke hier auch erklärt werden könnte.
Ich habe auch eine solche Lösung mir erstellt. Zwar sehr umständlich, aber sie geht immer! Ich habe einen timerDP und einen aliasDP der via boolean abfragt oder der timerDP >0 ist und dann true bzw bei = 0 false ist. Der aliasDP gibt beim manuellen stellen den Wert 29 in den timerDP und bei false sendet er auch den Wert 0 in den timerDP. Mein Script läuft jede Minute ab und fragt ob der aliasDP true ist. Wenn ja dann ziehe vom timerDP eins ab. Solange bis der timerDP = 0 ist. Denn dann springt der aliasDP auf false um.
Warum so kompliziert? Mein ioB hat manchmal Aussetzer und dann würde das Timerscript unterbrochen. So wird immer jede Minute abgefragt ja oder nein und das passt für mich so jetzt perfekt.
Verbesserungsvorschläge?