# Inhalt
- [Beschreibung](#beschreibung)
- [Getting started](#getting-started)
- [Beispiel 1](#beispiel-1)
- [Beispiel 2](#beispiel-2)
- [Beispiel 3](#beispiel-3)
- [Blöcke](#blocks)
- [Systemblöcke](#systemblöcke)
- [Debug Ausgabe](#debug-ausgabe)
- [Kommentar](#kommentar)
- [Steuere State](#steuere-state)
- [Aktualisiere State](#aktualisiere-state)
- [Bind states](#bind-states)
- [Write states](#write-states)
- [Create state](#create-state)
- [Get value of state](#get-value-of-state)
- [Get Object ID](#get-object-id)
- [Aktionsblöcke](#aktionsblöcke)
- [Exec - Kommando](#exec---kommando)
- [request URL](#request-url)
- [SendTo Blöcke](#sendTo-blöcke)
- [Send to telegram](#send-to-telegram)
- [Send to SayIt](#send-to-sayit)
- [Send to pushover](#send-to-pushover)
- [Send email](#send-email)
- [Custom sendTo block](#custom-sendto-block)
- [Datum und Zeit Blöcke](#datum-und-zeit-blöcke)
- [Time comparision](#time-comparision)
- [Actual time comparision](#actual-time-comparision)
- [Get actual time im specific format](#get-actual-time-im-specific-format)
- [Get time of astro events for today](#get-time-of-astro-events-for-today)
- [Convert blocks](#convert-blocks)
- [Convert to number](#convert-to-number)
- [Convert to boolean](#convert-to-boolean)
- [Get type of variable](#get-type-of-variable)
- [Convert to date/time object](#convert-to-datetime-object)
- [Convert date/time object to string](#convert-datetime-object-to-string)
- [Convert JSON to object](#convert-json-to-object)
- [Convert object to JSON](#convert-object-to-json)
- [Convert by JSONata Expression](#convert-by-jsonata-expression)
- [Trigger](#trigger)
- [Trigger on states change](#trigger-on-states-change)
- [Trigger on state change](#trigger-on-state-change)
- [Trigger info](#trigger-info)
- [Schedule](#schedule)
- [Trigger on astro event](#trigger-on-astro-event)
- [Named schedule](#named-schedule)
- [Clear schedule](#clear-schedule)
- [CRON dialog](#cron-dialog)
- [CRON rule](#cron-rule)
- [Trigger auf Dateiaktualisierung](#trigger-auf-dateiaktualisierung)
- [Ereignis bei Dateiaktualisierung abbrechen](#ereignis-bei-dateiaktualisierung-abbrechen)
- [Timeouts](#timeouts)
- [Delayed execution](#delayed-execution)
- [Clear delayed execution](#clear-delayed-execution)
- [Execution by interval](#execution-by-interval)
- [Stop execution by interval](#stop-execution-by-interval)
- [Logic](#logic)
- [If else block](#if-else-block)
- [Comparision block](#comparision-block)
- [Logical AND/OR block](#logical-and-or-block)
- [Negation block](#negation-block)
- [Logical value TRUE/FALSE](#logical-value-true-false)
- [null block](#null-block)
- [Test block](#test-block)
- [Loops](#loops)
- [Repeat N times](#repeat-n-times)
- [Repeat while](#repeat-while)
- [Count](#count)
- [For each](#for-each)
- [Break out of loop](#break-out-of-loop)
- [Math](#math)
- [Number value](#number-value)
- [Arithmetical operations +-\*/^](#arithmetical-operations--)
- [Square root, Abs, -, ln, log10, e^, 10^](#square-root-abs---ln-log10-e-10)
- [sin, cos, tan, asin, acos, atan](#sin-cos-tan-asin-acos-atan)
- [Math constants: pi, e, phi, sqrt(2), sqrt(1/2), infinity](#math-constants-pi-e-phi-sqrt2-sqrt12-infinity)
- [Is even, odd, prime, whole, positive, negative, divisibly by](#is-even-odd-prime-whole-positive-negative-divisibly-by)
- [Modify variably by value plus or minus](#modify-variably-by-value-plus-or-minus)
- [Round, floor, ceil value](#round-floor-ceil-value)
- [Operations on the list of values: sum, min, max, average, median, modes, deviation, random item](#operations-on-the-list-of-values-sum-min-max-average-median-modes-deviation-random-item)
- [Modulus](#modulus)
- [Limit some value by min and max](#limit-some-value-by-min-and-max)
- [Random value from 0 to 1](#random-value-from-0-to-1)
- [Random value between min and max](#random-value-between-min-and-max)
- [Text](#text)
- [String value](#string-value)
- [Concatenate strings](#concatenate-strings)
- [Append string to variable](#append-string-to-variable)
- [Length of string](#length-of-string)
- [Is string empty](#is-string-empty)
- [Find position in string](#find-position-in-string)
- [Get symbol in string on specific position](#get-symbol-in-string-on-specific-position)
- [Get substring](#get-substring)
- [Convert to upper case or to lower case](#Convert-to-upper-case-or-to-lower-case)
- [Trim string](#trim-string)
- [Lists](#lists)
- [Create empty list](#create-empty-list)
- [Create list with values](#create-list-with-values)
- [Create list with same value N times](#create-list-with-same-value-n-times)
- [Get length of list](#get-length-of-list)
- [Is list empty](#is-list-empty)
- [Find position of item in list](#Find-position-of-item-in-list)
- [Get item in list](#get-item-in-list)
- [Set item in list](#set-item-in-list)
- [Get sublist of list](#get-sublist-of-list)
- [Convert text to list and vice versa](#convert-text-to-list-and-vice-versa)
- [Colour](#colour)
- [Colour value](#colour-value)
- [Random colour](#random-colour)
- [RGB colour](#rgb-colour)
- [Mix colours](#mix-colours)
- [Variables](#variables)
- [Set variable's value](#set-variables-value)
- [Get variable's value](#get-variables-value)
- [Functions](#functions)
- [Create function from blocks with no return value](#create-function-from-blocks-with-no-return-value)
- [Create function from blocks with return value](#create-function-from-blocks-with-return-value)
- [Return value in function ](#return-value-in-function)
- [Create custom function with no return value](#create-custom-function-with-no-return-value)
- [Create custom function with return value](#create-custom-function-with-return-value)
- [Call function](#call-function)
# Beschreibung
Blockly ist ein grafischer Editor, der es Nutzern erlaubt Skripte durch zusammenfügen von Blöcken zu erzeugen.
Er wurde für Nutzer entwickelt, die keine Erfahrung in Programmierung von Computern besitzen.
# Getting started
## Beispiel 1
**Zustand eines Datenpunkts bei Änderung eines anderen Datenpunkts ändern**

Dies ist das klassische Beispiel bei Änderung eines Datenpunktes etwas anderes zu schalten.
Hier wird das Licht an oder ausgeschaltet wenn Bewegung bzw. keine Bewegung erkannt wird.
Zuerst den Block "Triggers=>Falls Objekt" einfügen. Die Objekt ID auswählen um den Zustand des Objekts als Trigger für dieses Skript zu benutzen.
Einen anderen Block - "System=>Steuere" hinzufügen und im Dialog den anderen Zustand der durch den Trigger geändert werden soll auswählen.
In diesen Steuerungsblock einen Block "System=>Wert von Objekt ID" einfügen und im Dialog das Objekt "Bewegung" auswählen, um dessen Zustand in "Licht": zu schreiben.
**Es gibt bei den Trigger Blöcken eine spezielle Variable "Wert". Diese wird immer hier definiert und kann für verschiedene Zwecke verwendet werden. Sie enthält den aktuellen Wert des triggernden Objekts und man kann daher einfacherer Skripte erzeugen indem man den Block "Variable=>Objekt ID" benutzt und ihn in "Wert" umbenennt.**

Beispiel zum importieren:
```xml
Switch light ON or OFF it motion detected or IDLE
ne
javascript.0.Motion
javascript.0.Light
FALSE
val
javascript.0.Motion
```
## Beispiel 2
**Licht bei Bewegung anschalten und ausschalten wenn 10 Minuten keine Bewegung.**

Wenn der Zustand "Bewegung" mit dem Wert "wahr" aktualisiert wird, mache:
- schalte "Licht" an
- starte die Verzögerung von 10 Minuten um "Licht" auszuschalten und lösche alle bisherigen Verzögerungen für diesen Datenpunkt.
Wie man sieht wird der Flag "lösche Verzögerung" durch den letzten Befehl gelöscht. Dieses löscht alle Timer für diesen Datenpunkt und startet einen neuen Timer
Beispiel zum importieren:
Switch light ON and OFF in 10 minutes of IDLE
true
true
javascript.0.Motion
javascript.0.Light
FALSE
TRUE
javascript.0.Light
TRUE
600000
TRUE
FALSE
```
## Beispiel 3
**Verschicke eine E-Mail, wenn die Außentemperatur höher als 25 Grad Celsius ist.**

Erklärung:
Zuerst müssen wir eine Variable definieren um zu speichern, dass die E-Mail für den aktuellen Temperaturalarm bereits gesendet wurde und diese Variable auf "falsch" setzen.
Dann beobachten wir die Veränderungen der Temperatur. Wir könnten dieses Skript auch periodisch ausführen, aber das ist nicht so effektiv.
Wenn sich die Temperatur ändert vergleichen wir den aktuellen Wert mit 25 und prüfen, ob die E-Mail bereits verschickt wurde oder nicht.
Wenn die E-Mail noch nicht versendet war, speichern wir, dass wir sie jetzt senden und senden sie auch. Natürlich muss der E-Mail-Adapter vorher installiert und konfiguriert worden sein.
Wenn die Temperatur unter 23 Grad fällt setzen wir die Variable "emailSent" zurück, damit beim nächsten Temperaturalarm wieder eine E-Mail gesendet wird.
Dazu wird die aktuelle Temperatur mit 23 verglichen und es werden keine E-Mails geschickt, solange die Temperatur um 25 Grad schwankt.
Um den "falls ... sonst falls ..." Block zu erstellen klickt man auf das Zahnrad und fügt die zusätzlich benötigten Elemente dem "falls" Block hinzu.

Man kann zu jedem Block einen Kommentar hinterlegen, indem man "Kommentar hinzufügen" im Kontextmenü des Blocks anklickt. Diesen Kommentar kann man später durch anklicken des Fragezeichens ansehen.

Man kann größere Blöcke einklappen, um eine bessere Übersicht zu erhalten, indem man im Kontextmenü den Punkt "Block einklappen" auswählt.

Beispiel zum importieren:
```xml
Send email if outside temperature is more than 25 grad Celsius.
emailSent
FALSE
ne
true
javascript.0.Outside_temperature
AND
EQ
emailSent
FALSE
emailSent
Remember, that email was sent
FALSE
FALSE
log
myaddress@domain.com
Temperature is over 25°C
Temperature alert
LT
value
23
emailSent
FALSE
```
# Blöcke
## Systemblöcke
### Debug Ausgabe

Dieser Block macht nichts, außer eine Zeile ins log zu schreiben. Man kann ihn zum debuggen des Scripts nutzen, wie diesen hier:

Beispiel zum Importieren:
```xml
Print time into log every second
interval
1000
log
test
hh:mm:ss
```
Man kann 4 verschiedene Schweregrade für die Nachrichten definieren:
- debug (dazu muss der debug-Level der Javascript Instanz aktiviert sein.)
- info (default, zumindest der info log level muss in der Javascript Instanz aktiviert sein.)
- warning
- error (wird immer angezeigt. Die anderen Level können ignoriert werden, wenn es entsprechend in der Javascript Instanz eingestellt ist.)
### Kommentar

Einen Kommentar zum Skript hinzufügen um es später besser verstehen zu können.
Der Block macht gar nichts, es ist nur ein Kommentar.
### Steuere State

Man kann einen Zustand auf zwei verschiedene Arten schreiben:
- Um etwas zu steuern und den Wert an die Hardware zu schicken (Dieser Block)
- Einen neuen Wert schreiben, der nur der Information dient, z.B. Temperaturänderung ([nächster Block](#update-state))
Typische Anwendung dieses Blocks:

Die Object ID wird im Dialog ausgewählt der zu sendende Wert muss angegeben werden. Abhängig vom Typ des Datenpunkts kann der Wert vom Typ [string](#string-value), [number](#number-value) oder [boolean](#ogical-value-trueflase) sein.
Weitere Erklärungen gibt es [hier](https://github.com/ioBroker/ioBroker/wiki/Adapter-Development-Documentation#commands-and-statuses).
Dieser Block schreibt den Befehl in den Datenpunkt mit (ack=false). Zusätzlich kann eine Verzögerung angegeben werden.
Wenn die Verzögerung nicht 0 ist, wird der Zustand nicht sofort, sondern erst nach der angegebenen Zeit in Millisekunden gesetzt.
Man kann alle anderen Verzögerungen für diesen Datenpunkt löschen, indem man die Checkbox anhakt.
So wird in dem folgenden Beispiel der Datenpunkt "Licht" nur einmal geschaltet (nach 2 Sekunden):

Beispiel zum Importieren:
```xml
Will be executed only once
javascript.0.Light
TRUE
1000
FALSE
TRUE
javascript.0.Light
TRUE
2000
TRUE
TRUE
```
Im Gegensatz zu dem vorherigen Beispiel wird der Zustand von "Licht" in dem folgenden Beispiel zweimal geschaltet(nach 1 Sekunde und nach 2 Sekunden):

```xml
Will be executed twice
javascript.0.Light
TRUE
1000
FALSE
TRUE
javascript.0.Light
TRUE
2000
FALSE
FALSE
```
### State umschalten

Dieser Block ähnelt dem [Steuere-State-Block](#steuere-state), schaltet den Wert aber jeweils um — von `true` auf `false` und umgekehrt.
### Aktualisiere State

Dieser Block ist ähnlich dem [Steuere Block](#steuere-state), aber er setzt nur den aktuellen Wert. Es wird kein Befehl zum Steuern der Hardware gesendet.
Typische Anwendung dieses Blocks:

### Bind States

Dieser Block bindet zwei Zustände aneinander.
Man kann das Gleiche mit diesen Blöcken erreichen:

Man kann auswählen, ob der Wert nur weitergeleitet wird, wenn sich die Quelle ändert, oder bei jeder Aktualisierung.
Beispiel zum Importieren:
```xml
ne
javascript.0.Motion
javascript.0.Light
FALSE
value
```
### Write states

Universal write block that can do the same as ["Update state"](#update-state) and ["Control state"](#control-state) together.
But in compare with them, you can define Object ID and delay with other blocks to make your script more universal.
### Create state

There are two types of variables that can be created in scripts:
- local [variables](#set-variables-value)
- global variables or states.
Global states are visible in all scripts, but local are visible only in this current script.
Global states can be used in vis, mobile and all other logic or visualisation modules, can be logged into db or whatever.
This block creates global state and if the state yet exist, the command will be ignored. You can safely call this block by every start of the script.
Dieser Block erzeugt globale Zustände und wenn dieser bereits existiert wird der Befehl ignoriert. Daher kann dieser Block ohne Risiko zu jedem Skriptstart verwendet werden.
Typische Anwendung dieses Blocks:

```xml
Create state and subscribe on it changes
myState
ne
javascript.0.myState
log
test
Value of my state is
value
```
Man kann den neu erzeugten State bereits in dem Block selber nutzen.
Der folgende Code gibt bei der ersten Ausführung einen Fehler aus, weil 'subscribe' für "myState" das Objekt nicht finden kann:

Bei der zweiten Ausführung wird keine Fehler ausgegeben, weil der Datenpunkt jetzt existiert.
### Wert von Objekt ID

Dieser Block dient dazu den Wert eines Datenpunktes auszulesen. Folgende Attribute des Datenpunktes können ausgelesen werden:
- Wert
- Acknowledge - Befehl = falsch oder update = wahr
- Timestamp in ms seit dem 01.01.1970 (Hat den Typ "Datumsobjekt")
- Letzte Änderung des Wertes in ms seit dem 01.01.1970 (Hat den Typ "Datumsobjekt")
- Qualität
- Quelle - Name der Instanz, die den letzten Wert geschrieben hat, wie z.B. `system.adapter.javascript.0`
Beispiel um die Zeit der letzten Änderung des Wertes auszugeben:

```xml
Print time of last change for myState
log
test
Last change of myState was at
hh:mm:ss
lc
javascript.0.myState
```
### Objekt ID

Dieses ist ein einfacher Hilfsblock um komfortabel die Objekt-ID zum triggern des Blocks auszuwählen.
Der ID Auswahldialog wird durch Anklicken von "Objekt ID" geöffnet.
Typische Anwendung dieses Blocks:

```xml
Typical usage of Object ID selector
ne
default
javascript.0.myState
log
Changed
```
### Datenpunkt vorhanden
Dieser Block liefert einen Boolean (`true` / `false`) und gibt zurück, ob der angegebene Datenpunkt aktuell überhaupt einen Wertdatensatz in der State-DB besitzt. Die OID wird über einen Value-Input geliefert — sie kann aus dem OID-Auswahlblock (`Objekt ID`), einer String-Variable oder jedem anderen Block kommen, der eine State-ID liefert.
**Wozu das Ganze?** ioBroker speichert **Objekte** (Metadaten) und **States** (Werte) getrennt. Ein Adapter kann das *Objekt* eines Datenpunkts anlegen — die ID erscheint dann im OID-Auswahldialog —, ohne jemals einen *Wert* zu schreiben. In diesem Fall führt `getState(...)` zu einer Warnung im Log:
```
warn getState "zigbee.0.187a3efffee9e4e8.load_power" not found (3)
```
Auch eine Prüfung wie `Wert von Objekt-ID … != null` löst diese Warnung aus, weil sie bereits *während* des `getState`-Aufrufs entsteht — also bevor der Vergleich überhaupt ausgewertet wird.
Der Block **Datenpunkt vorhanden** verwendet intern `existsStateAsync(...)`. Diese Funktion prüft den Cache stillschweigend und schreibt nichts ins Log, falls der State fehlt. Das ist der saubere Weg, einen `getState`-Aufruf abzusichern, wenn ein Adapter Datenpunkte vorab anlegt, aber nicht sofort befüllt (z. B. Zigbee, Tuya).
Typische Anwendung — einen Lese-Vorgang gegen fehlende State-Datensätze absichern:
```
wenn [Datenpunkt vorhanden [Objekt ID "zigbee.0.…load_power"]]
setze [leistung] auf [Wert von Objekt-ID "zigbee.0.…load_power"]
log [leistung]
```
Der erzeugte JavaScript-Code:
```javascript
if ((await existsStateAsync('zigbee.0.187a3efffee9e4e8.load_power'))) {
let leistung = getState('zigbee.0.187a3efffee9e4e8.load_power').val;
console.log(leistung);
}
```
**Hinweis:** Mit der Adapter-Einstellung *„Beim Start nicht alle Zustände abonnieren"* lässt sich `existsState` nicht synchron auswerten. Der Block erzeugt deshalb die asynchrone Form (`await existsStateAsync(...)`), die in beiden Modi korrekt funktioniert.
## Aktionsblöcke
### Exec - Kommando

Dieser Block führt das eingegebene Kommando im System aus, so als ob man es auf der Kommandozeile via SSH eingegeben hätte.
Der Befehl wird mit den rechten des Users ausgeführt unter dem ioBroker gestartet wurde.
Wenn keine Ausgabe gewünscht ist, kann diese unterdrückt werden:

Wenn eine Ausgabe erfolgen soll:

```xml
Execute some system command
TRUE
ls /opt/
log
result
result
```
Zur Analyse der Ausgabe werden 3 besondere Variable erzeugt:
- Ergebnis, enthält die reguläre Ausgabe auf die Konsole (z.B. für den Befehl "ls /opt" lautet die Ausgabe "iobroker nodejs")
- Fehlerobjekt, wenn der Befehl vom JavaScript Modul nicht ausgeführt werden konnte
- stderr, die Fehlerausgabe des ausgeführten Programms
Zusätzlich wird die selbe Ausgabe auch im Log erscheinen, wenn der loglevel nicht auf 'none' steht.
### request URL

Ruft eine URL auf und gibt das Ergebnis zurück.
Beispiel:

Zur Analyse der Ausgabe werden 3 besondere Variable erzeugt:
- Ergebnis, enthält den body der angeforderten Seite
- Fehler, enthält eine Fehlerbeschreibung
- Antwort (nur für Fortgeschrittene), Spezialobjekt vom Typ [http.IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage)
Wenn keine Ausgabe gewünscht ist, kann diese unterdrückt werden. Dazu die Option "mit Ergebnis" abhaken.
## SendTo Blöcke
### Send to telegram

Dieser Block dient dazu eine Nachricht über telegram mit Hilfe des telegram-Adapters zu senden.
Selbstverständlich muss dafür vorher der telegram-Adapter installiert und konfiguriert werden.
Um die Nachricht über eine bestimmte Instanz zu senden, muss die gewünschte Instanz des Adapters (üblicherweise telegram.0) ausgewählt werden, ansonsten wird die Nachricht über alle verfügbaren Instanzen verschickt.
Das Feld *Meldung* ist zwingend notwendig und der dort enthaltene Text wird exakt so an den Klienten gesendet.
User name ID is optional and this is ID from [telegram](https://core.telegram.org/bots/api#user) (Unique identifier for user or bot).
Additionally, if the log level is not "none", the same message will be sent to log.
### Send to SayIt

This block is used to send text to `sayit` instance to pronounce this text.
Of course the `sayit` adapter must be installed and configured.
To send message to some specific instance, you should select the installed adapter instance (Normally `sayit.0`), elsewise message will be sent to all existing instances.
Property *message* is mandatory and exactly this text will be pronounced.
You must check the language property. This will be used for text2speech engine.
Volume is optional (normally from 0 to 100).
Additionally, if the log level is not "none", the same message will be sent to log.
### Send to pushover

This block is used to send text to pushover client. You can read about pushover driver [here](https://github.com/ioBroker/ioBroker.pushover).
Of course the pushover adapter must be installed and configured.
To send message to some specific instance, you should select the installed adapter instance (Normally pushover.0), elsewise message will be sent to all existing instances.
Property *message* is mandatory and exactly this text will be sent to client.
All other properties are optional, and you can read bout them [here](https://pushover.net/api):
- *device ID* - your user's device name to send the message directly to that device, rather than all the user's devices (multiple devices may be separated by a comma)
- *title* - your message's title, otherwise your app's name is used
- *URL* - a supplementary URL to show with your message
- *URL title* - a title for your supplementary URL, otherwise just the URL is shown
- *priority* - send as -2 to generate no notification/alert, -1 to always send as a quiet notification, 1 to display as high-priority and bypass the user's quiet hours, or 2 to also require confirmation from the user
- *time in ms* - a Unix timestamp of your message's date and time to display to the user, rather than the time your message is received by our API
- *sound* - the name of one of the sounds supported by device clients to override the user's default sound choice
Additionally, if the log level is not "none", the same message will be sent to log.
### Send email

This block is used to send text as email.
Of course the email adapter must be installed, configured and tested.
To send message to some specific instance, you should select the installed adapter instance (Normally email.0), elsewise message will be sent to all existing instances.
Property *text* is mandatory and exactly this text will be sent to client.
Of course the destination (*to*) must be filled with valid email address.
You can attach up to files (normally images) to email. To use images in the text, you must change format to HTML (check "Send as HTML" option) and text could look like:
```html
Embedded image 1: 
Embedded image 2: 
```
You can refer to files as ```
```. "file1" and "file2" are reserved IDs and cannot be changed.
"file name" must consist full path to image on disk.

```xml
FALSE
user@myemail.com
<p>Embedded image 1: <img src='cid:file1'/></p>
From Sweet Home
/opt/video/imageCam.png
```
Additionally, if the log level is not "none", the same message will be sent to log.
### Custom sendTo block

This is just a help block to send internal system message (sendTo) to any adapter.
Of course, you can use custom function block to do anything crazy, and to send messages too.
You can define your own parameters for sendTo command:

Read more [here](https://github.com/ioBroker/ioBroker.javascript#sendto) about "sendTo".
Example how to send SQL query to sql adapter:

```xml
-->
Send query to SQL adapter
sql.0
query
TRUE
log
SELECT * FROM datapoints
log
test
result
JSON.stringify
cmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaik7
Describe this function...
```
If you use only one parameter with empty name, so no structure will be created, like here:
```javascript
var obj, result;
/**
* Describe this function...
*/
function JSON_stringify(obj) {
return JSON.stringify(obj);
}
// Send query to SQL adapter
sendTo("sql.0", "query", 'SELECT * FROM datapoints', function (result) {
console.log((JSON_stringify(result)));
});
console.log("sql.0: " + "");
```
Or how to request history from SQL adapter:

```XML
Get history from SQL adapter
end
object
sql.0
getHistory
TRUE
system.adapter.admin.0.memRss
{start: end - 3600000, end: end, aggregate: "minmax"}
log
test
result
JSON.stringify
cmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaik7
JSON.stringify object
```
Generated javascript code:
```javascript
var obj, end, result;
/**
* JSON.stringify object
*/
function JSON_stringify(obj) {
return JSON.stringify(obj);
}
// Get history from SQL adapter
end = (new Date().getTime());
sendTo("sql.0", "getHistory", {
"id": 'system.adapter.admin.0.memRss',
"options": {start: end - 3600000, end: end, aggregate: "minmax"}
}, function (result) {
console.log((JSON_stringify(result)));
});
```
If you start value with "{" it will be interpreted as JSON string. Use double quotes in string.
### An anderes Skript senden

Mit diesem Block kannst du eine Nachricht an ein anderes Skript senden. Die Nachricht kann dort durch den Block [Ereignis – Nachricht empfangen](#trigger-on-script-event) verarbeitet werden.
## Date and Time blocks
### Time comparison

If used operator "between" or "not between", the block looks like this:

You can specify a time, which must be compared. Block expects the time as "Date object".

There are following compare modes:
- less than, check if actual time less than specified time.
- equal to or less than
- greater than
- equal to or greater than
- equal to
- between, check if the time between some day times.
- E.g. if time must be between 12:00 and 20:00. It will be checked if actual time grater or equal than 12:00 and less than 20:00. 20:00 will return false.
- or for instance between 21:00 and 8:00. In the last case it will be checked if time greater or equal to 21:00 or less than 8:00.
- not between, if the time is not in the given period of the daytime. If the time less than start and greater or equal to end. (if start time is greater than end time, it will be checked if the time greater or equal than end and smaller than start)
Following time formats are valid:
- YYYY-MM-DD hh:mm:ss
- YYYY-MM-DD hh:mm
- hh:mm:ss
- hh:mm
### Actual time comparision

This block is used to compare the day time with actual time. It has the same logic as [Time comparision](#time-comparision), but limits cannot be a blocks, and it compares only actual time. (for compatibility with old versions)
### Get actual time im specific format

Returns the actual time in some specified format.
Following formats are supported:
- milliseconds - returns only milliseconds of current second from 0 to 999 (not epoch milliseconds). To get epoch milliseconds use "Date object";
- seconds - returns only seconds of current minute from 0 to 59,
- seconds in day - returns number of seconds from start of the day (0 to 24 * 3600 - 1),
- minutes - returns minutes of current hour from 0 to 59,
- minutes in day - returns number of minutes from the day start (0 to 24 * 60 - 1),
- hours - returns hours of current day from 0 to 23,
- day of month - get day of month from 1 to 31,
- month as number - get month as number from 1 to 12,
- month as text - get month as text. Language must be specified.
- month as short text - get month as text: Jan, Feb, Mar, Apr, May, June, July, Aug, Sept, Oct, Nov, Dec. Language must be specified.
- short year - Year from 0 to 99, e.g. for 2016 the result will be 16.
- full year - Full year: 2016
- week day text - Get day of week as text.
- short week day - Get day of week as short text: Su, Mo, Tu, We, Th, Fr, Sa.
- week day as number - Day of week as number from 1 (monday) to 7 (sunday).
- custom format - You can specify your own [format](https://github.com/ioBroker/ioBroker.javascript#formatdate).
- Date object - Returns date and time as number of milliseconds from start of epoch (1970.1.1 00:00:00.000Z GMT). This is always GMT.
- yyyy.mm.dd - 2016.09.14
- yyyy/mm/dd - 2016/09/14
- yy.mm.dd - 16.09.14
- yy/mm/dd - 16/09/14
- dd.mm.yyyy - 14.09.2016
- dd/mm/yyyy - 14/09/2016
- dd.mm.yy - 14.09.16
- dd/mm/yy - 14/09/16
- mm/dd/yyyy - 09/14/2016
- mm/dd/yy - 09/14/16
- dd.mm. - 14.09.
- dd/mm - 14/09
- mm.dd - 09.14
- mm/dd - 09/14
- hh:mm - 12:00
- hh:mm:ss - 12:00:00
- hh:mm:ss.sss - 12:00:00.000
### Get time of astro events for today

Returns the time in current day of some specific astrological event.
The attribute "offset" is the offset in minutes. It can be negative too, to define time before astro event.
Following values can be used as attribute in astro-function:
- sunrise: sunrise (top edge of the sun appears on the horizon)
- sunriseEnd: sunrise ends (bottom edge of the sun touches the horizon)
- goldenHourEnd: morning golden hour (soft light, best time for photography) ends
- solarNoon: solar noon (sun is in the highest position)
- goldenHour: evening golden hour starts
- sunsetStart: sunset starts (bottom edge of the sun touches the horizon)
- sunset: sunset (sun disappears below the horizon, evening civil twilight starts)
- dusk: dusk (evening nautical twilight starts)
- nauticalDusk: nautical dusk (evening astronomical twilight starts)
- night: night starts (dark enough for astronomical observations)
- nightEnd: night ends (morning astronomical twilight starts)
- nauticalDawn: nautical dawn (morning nautical twilight starts)
- dawn: dawn (morning nautical twilight ends, morning civil twilight starts)
- nadir: nadir (the darkest moment of the night, sun is in the lowest position)
The return value has type "Date Object", what is just the number of milliseconds from 1970.01.01.
**Note:** to use "astro"-function the "latitude" and "longitude" must be defined in javascript adapter settings.
## Convert blocks
Sometimes it is required to convert value into other type. Following blocks allow converting value into specific types.
### Convert to number

Convert value to number (float).
### Convert to boolean

Convert value to boolean (true or false).
### Convert to string

Convert value to string.
### Get type of variable

Get type of value. Type can be: boolean, number, string, object.
### Convert to date/time object

Convert value to "Date object". Read [here](#get-actual-time-im-specific-format), what the "Date object" is.
### Convert date/time object to string

Convert "Date object" into string. It has the same format options as [Get actual time im specific format](#get-actual-time-im-specific-format).
### Convert JSON to object

Convert JSON string into javascript object. If an error occurs, the empty object will be returned. (only for experts)
### Convert object to JSON

Convert Javascript object to JSON string. If prettify option is selected the result string looks like:
```json
{
"a": 1,
"b": 2
}
```
if not:
```
{"a": 1, "b": 2}
```
### Convert by JSONata Expression

Convert Javascript object by JSONata expression. You can read more about it here: [https://jsonata.org/](https://jsonata.org/)
Example payload:
```
{"example": [{"value": 4},{"value": 7},{"value": 13}]}
```
Result:
```
[{"value": 4},{"value": 7},{"value": 13}]
24
4
13
```
## Trigger
### Trigger on states change

This block executes some action if state of given objects changed or updated. This is the main block to build interactions between different states and accordingly systems.
With this block you can bind different states together or send message or email on value change.
Typical usage of block:

```xml
Switch light on if motion detected
ne
javascript.0.Motion
javascript.0.Light
FALSE
TRUE
```
You can define as many ObjectIDs as you want via extension dialog:

If only one object ID is used so special variables are available in the statement block:
- value - actual value of state
- oldValue - old value of state

```xml
ne
javascript.0.Motion
log
test
Actual value is
value
Old value was
oldValue
```
elsewise if more than one object ID is used for trigger, you can access value and old value via [Trigger info](#trigger-info).
### Trigger on state change

This is the same block as "Trigger on states change", but with no possibility to use multiple object IDs for triggering (for versions compatibility).
### Trigger info

Get information about value, timestamp or ID of the state, that triggered the trigger.
This block can be used only inside of ["Trigger on states change"](#trigger-on-states-change) or ["Trigger on state change"](#trigger-on-state-change) blocks.
Following information can be accessed:
- object ID - ID of state, that fired the trigger
- name - name of state from common.name
- description - description of state from common.desc
- channel ID - ID of channel to which belongs the state. If not channel there, it will be null
- channel name - name of channel to which belongs the state. If not channel there, it will be null
- device ID - ID of device to which belongs the state. If not channel there, it will be null
- device name - name of device to which belongs the state. If not channel there, it will be null
- state value - actual value of fired state
- state timestamp - actual timestamp as Date object
- state quality - actual quality code of value
- origin of value - name of instance that cause the change
- is command or update - is it command (ack=false) or update (ack=true)
- last change of state - timestamp of last change of this value
- previous value - previous value of this state, before the trigger fired
- previous timestamp - previous timestamp of this state, before the trigger fired
- previous quality - previous quality of this state, before the trigger fired
- previous origin - previous origin of this state, before the trigger fired
- previous command or update - previous type of this value, before the trigger fired
- previous last change - previous "last changed value" of this state, before the trigger fired
Typical usage:

```xml
ne
javascript.0.Motion
log
test
Actual value is
state.val
Old value was
oldState.val
```
### Schedule

This is second main block for automation after ["Trigger on states change"](#trigger-on-states-change). This block lets execute some actions periodically.
The definition of schedule rule will be done in very well documented CRON [format](https://en.wikipedia.org/wiki/Cron). With extension, that seconds can be defined too.
If seconds should be used they must be defined as very first parameter of CRON rule and rule will have 6 parts.
Generally CRON rule consist of 5 or 6 parts:
- seconds rules (optional)
- minutes rules
- hours rules
- day of month rules
- month's rules
- and day of week rules.
For every part following formats are allowed:
- \* - fire every (second, minute, hour, ...)
- X (e.g. 5) - fire only in this second, minute, hour...
- from-to (e.g 1-9) - fire only in this interval
- \*/X (e.g. \*/5) - fire every X seconds, minutes... In case of "\*/5" for hours the trigger will fire on 0, 5, 10, 15 and on 20 hours.
- numbers and intervals can be combined by comma (e.g 1,3,4-6). Do not make spaces between numbers, because space is delimiter for rule's parts.
\*/10 \* \* \* 6,7 - fire every 10 minutes on saturday and sunday.
\*/30 \* \* \* \* \* - fire every 30 seconds.
```
┌───────────── min (0 - 59)
│ ┌────────────── hour (0 - 23)
│ │ ┌─────────────── day of month (1 - 31)
│ │ │ ┌──────────────── month (1 - 12)
│ │ │ │ ┌───────────────── day of week (0 - 6) (0 to 6 are Sunday to Saturday; 7 is also Sunday)
│ │ │ │ │
│ │ │ │ │
│ │ │ │ │
* * * * * schedule
```
or if seconds used:
```
┌───────────── seconds (0 - 59)
│ ┌───────────── min (0 - 59)
│ │ ┌────────────── hour (0 - 23)
│ │ │ ┌─────────────── day of month (1 - 31)
│ │ │ │ ┌──────────────── month (1 - 12)
│ │ │ │ │ ┌───────────────── day of week (0 - 6) (0 to 6 are Sunday to Saturday; 7 is also Sunday)
│ │ │ │ │ │
│ │ │ │ │ │
│ │ │ │ │ │
* * * * * * schedule
```
But there is a good help for you to build such a rules. By clicking on rule the CRON dialog will be opened and you can specify by mouse your rule.

### Trigger on astro event

Execute some action on astrological event. Following events are possible:
- sunrise: sunrise (top edge of the sun appears on the horizon)
- sunriseEnd: sunrise ends (bottom edge of the sun touches the horizon)
- goldenHourEnd: morning golden hour (soft light, best time for photography) ends
- solarNoon: solar noon (sun is in the highest position)
- goldenHour: evening golden hour starts
- sunsetStart: sunset starts (bottom edge of the sun touches the horizon)
- sunset: sunset (sun disappears below the horizon, evening civil twilight starts)
- dusk: dusk (evening nautical twilight starts)
- nauticalDusk: nautical dusk (evening astronomical twilight starts)
- night: night starts (dark enough for astronomical observations)
- nightEnd: night ends (morning astronomical twilight starts)
- nauticalDawn: nautical dawn (morning nautical twilight starts)
- dawn: dawn (morning nautical twilight ends, morning civil twilight starts)
- nadir: nadir (the darkest moment of the night, sun is in the lowest position)
**Note:** to use "astro"-function the "latitude" and "longitude" must be defined in javascript adapter settings.
Additionally, you can set the offset in minutes to astrological event, e.g. to fire the trigger 1 hour before down:

As you can see the offset can be negative too to specify time before astrological events.
### Named schedule

This block is the same as [Schedule](#schedule), but with possibility to set CRON rule by string and with possibility to stop the schedule.
You can specify unique name of this schedule block and then later to clear it with [Clear schedule](#clear-schedule).
Here is an example of configurable alarm clock:

```xml
Configurable alarm. Set time as: hh:mm
alarmTime
ne
javascript.0.alarmTime
alarm
alarm
* * * * *
state.val
log
Wake up!
time to CRON
dmFyIHBhcnRzID0gdGltZS5zcGxpdCgnOicpOwovLyBpZiBpdCBpcyBDUk9OCmlmIChwYXJ0cy5sZW5ndGggPT09IDEpIHJldHVybiB0aW1lOwpyZXR1cm4gcGFydHNbMV0gKyAnICcgKyBwYXJ0c1swXSArICcgKiAqIConOw==
Describe this function...
```
### Clear schedule

With this function block you can clear named schedule. If you define named one more time without clearing it, the old one will still active.
See an example in [Named schedule](#named-schedule)
### CRON dialog

Create CRON rule from dialog. This block can be connected with [Named schedule](#named-schedule).

```xml
Every 0th minute every hour
schedule
* * * * *
0 * * * *
log
It is exactly
It is exactly
h
o'clock
```
### CRON rule

Combine CRON rule from different parts.
You can display rule as block or as line:

With additional parameter "with seconds" you can specify seconds for CRON rule too

This block can be used (like [CRON dialog](#cron-dialog)) only with [Named schedule](#named-schedule) block.
### Trigger auf Dateiaktualisierung

Sie können Dateiaktualisierungen abonnieren und einige Aktionen ausführen. Z.B. hier wird der Inhalt von `vis´ bei jeder Projektaktualisierung ausgedruckt:
```
data
TRUE
vis.0
main/*
log
test
data
```
**Wichtig**: Diese Funktionalität ist nur mit js-controller@4.1.x oder neuer verfügbar.
### Ereignis bei Dateiaktualisierung abbrechen

Mit diesem Block können Sie Veranstaltungen per Dateiaktualisierung abbestellen.
**Wichtig**: Diese Funktionalität ist nur mit js-controller@4.1.x oder neuer verfügbar.
### Trigger auf Skript-Ereignis

Mit diesem Block kannst du dich auf skriptübergreifende Ereignisse abonnieren und beim Empfang eine Aktion ausführen.
## Timeouts
### Warten/Pause
Mit diesem einfachen Block lässt sich die Ausführung von Blöcken pausieren.
Achtung: Wird `pause` innerhalb einer Block-Kette verwendet, werden alle in diesem Skript darunter liegenden Blöcke ebenfalls verzögert:

Generierter Code:
```
console.log('"Independent" block'); // Wird nicht verzögert
console.log('Before pause');
await wait(5000);
console.log('After pause');
```
Log-Ausgabe:
```
15:48:21.807 info javascript.0 (7304) script.js.Skript_1: "Independent" block
15:48:21.807 info javascript.0 (7304) script.js.Skript_1: Before pause
15:48:21.807 info javascript.0 (7304) script.js.Skript_1: registered 0 subscriptions and 0 schedules
15:48:26.810 info javascript.0 (7304) script.js.Skript_1: After pause
```

Generierter Code:
```
console.log('Before pause');
await wait(5000);
console.log('After pause');
console.log('"Independent" block'); // Wird um 5 Sekunden verzögert
```
Ausgabe:
```
15:52:03.289 info javascript.0 (7304) script.js.Skript_1: Before pause
15:52:03.290 info javascript.0 (7304) script.js.Skript_1: registered 0 subscriptions and 0 schedules
15:52:08.296 info javascript.0 (7304) script.js.Skript_1: After pause
15:52:08.297 info javascript.0 (7304) script.js.Skript_1: "Independent" block
```
### Delayed execution

With this block you can execute other blocks delayed by some time specified in milliseconds.
if you know Javascript it is the same function as setTimeout.
There is no "pause" in blockly, but you can use this block to simulate pause. If you place all blocks, that must be executed after the pause you will achieve the same effect as with pause.
An additional feature is to set the interval by using a variable, just replace the "ms" with a predefined variable:

Every delayed execution can have unique name. It can be canceled by other block. [Clear delayed execution](#clear-delayed-execution)

```xml
log
Make a pause 5 seconds
timeout
5000
log
After pause
```
### Clear delayed execution

This block is used to cancel running delay by name. Typical usage is simulation of motion detection scenario.
By first motion the light should go on and after the last motion after 30 seconds the light should go off.

```xml
ne
node-red.0.javascript.0.Motion
EQ
value
TRUE
log
Motion detected
Switch light ON
javascript.0.Light
FALSE
TRUE
Stop timer, even if it not running
lightOff
lightOff
5000
log
Light OFF
javascript.0.Light
FALSE
FALSE
```
### Execution by interval

This block allows you to execute some action periodically. Of course there is a CRON block, but CRON block has the smallest interval one second.
This block can execute actions in milliseconds periods.
If you set the interval too small (under 100ms) it can be, that intervals will be bigger.
Similar to timeout block you can set unique interval name too.
### Stop execution by interval

With the help of this block you can cancel periodically execution of interval block by its name.
## Logic
### If else block
### Comparision block
### Logical AND/OR block
### Negation block
### Logical value TRUE/FALSE
### null block
### Test block
## Loops
### Repeat N times
### Repeat while
### Count
### For each
### Break out of loop
## Math
### Number value
### Arithmetical operations +-*/^
### Square root, Abs, -, ln, log10, e^, 10^
### sin, cos, tan, asin, acos, atan
### Math constants: pi, e, phi, sqrt(2), sqrt(1/2), infinity
### Is even, odd, prime, whole, positive, negative, divisibly by
### Modify variably by value (plus or minus)
### Round, floor, ceil value
### Operations on the list of values: sum, min, max, average, median, modes, deviation, random item
### Modulus
### Limit some value by min and max
### Random value from 0 to 1
### Random value between min and max
## Text
### String value
### Concatenate strings
### Append string to variable
### Length of string
### Is string empty
### Find position in string
### Get symbol in string on specific position
### Get substring
### Convert to upper case or to lower case
### Trim string
## Lists
### Create empty list
### Create list with values
### Create list with same value N times
### Get length of list
### Is list empty
### Find position of item in list
### Get item in list
### Set item in list
### Get sublist of list
### Convert text to list and vice versa
## Colour
### Colour value
### Random colour
### RGB colour
### Mix colours
## Variables
### Set variable's value

To use this block you should understand basic programming rules: how to use variables.
With this block you can write into global (visible everywhere in this script) variable and use it to store some values. If variable does not exist, it will be declared automatically.
This block can create new variable or use existing one.

This code:

```xml
item
0
```
does only this:
```javascript
var item;
item = 0;
```
### Get variable's value

This block gets the value of variable. You can create a new one or use existing one.

There is one exception with trigger blocks [Trigger on states change](#trigger-on-states-change) and [Trigger on state change](#trigger-on-state-change).
Inside these blocks variable "value" yet exist, but anyway to read their values you must rename variable into value and then use it.

## Funktionen
### Funktion aus Blöcken erstellen (ohne Rückgabewert)

Mit diesem Block kannst du wiederkehrende Block-Sequenzen zu einer Funktion zusammenfassen und diese Funktion anschließend an beliebigen Stellen im aktuellen Blockly-Skript verwenden.
Hier ein Beispiel für eine Funktion, die nur die aktuelle Uhrzeit ins Log schreibt:

```xml
Print current time
printTime
Describe this function...
log
test
hh:mm:ss.sss
```
Nachdem die Funktion erstellt wurde, kann sie folgendermaßen verwendet werden:

```xml
interval
1000
```
Die neu erstellte Funktion erscheint im Block-Menü:

Zusätzlich lassen sich über den Konfigurationsdialog Argumente für die Funktion festlegen. Im selben Dialog können auch die Namen der Argumente bearbeitet werden.

Hier ein Beispiel für eine Funktion, die die Summe des ersten und des zweiten Arguments ausgibt:

```xml
Print sum of a and b
printSum
Describe this function...
log
test
ADD
1
a
1
b
```
Die Argumente erscheinen im Variablen-Menü:

Die Funktion lässt sich dann so verwenden:

```xml
5
6
```
### Funktion aus Blöcken erstellen (mit Rückgabewert)

Dieser Block funktioniert wie der vorherige, kann aber zusätzlich ein Ergebnis zurückgeben, das anschließend in anderen Blöcken weiterverwendet werden kann.

```xml
do something
Return sum of a and b
ADD
1
a
1
b
```
Die Verwendung ist analog zu den anderen Funktionsblöcken:

```xml
log
test
5
6
sum
Return sum of a and b
ADD
1
a
1
b
```
Für jede Funktion lässt sich ein Kommentar bzw. eine Beschreibung hinzufügen.

Im Funktionsblock kann zusätzlich ein spezielles Return-Element verwendet werden:


```xml
log
test
5
log
test
wd
numberToDay
Return sum of a and b
EQ
day
0
Sunday
EQ
day
1
Monday
EQ
day
2
Tuesday
EQ
day
3
Wednesday
EQ
day
4
Thursday
EQ
day
5
Friday
EQ
day
6
Saturday
EQ
day
7
Sunday
Invalid day
```
### Wert in Funktion zurückgeben

Siehe Verwendung dieses Blocks unter [Funktion aus Blöcken erstellen (mit Rückgabewert)](#funktion-aus-blöcken-erstellen-mit-rückgabewert).
Dieser Block ist nur dort verwendbar und dient dazu, mitten in der Funktion einen Wert zurückzugeben.
### Eigene Funktion erstellen (ohne Rückgabewert)

Manchmal reichen die vorhandenen Blöcke nicht aus, um eine bestimmte Aufgabe zu lösen. Mit diesem Block kannst du einen eigenen Block als Funktion definieren, der Parameter entgegennimmt und beliebige Aktionen ausführt.
Um eine solche Funktion zu schreiben, sind JavaScript-Kenntnisse nötig. Innerhalb der Funktion stehen alle Funktionen zur Verfügung, die auch im normalen JavaScript-Skript verfügbar sind.
Um den Code zu schreiben, klickst du auf das `...` am Ende des Blocks, woraufhin sich der Editor-Dialog öffnet.

Ansonsten ist die Verwendung dieses Blocks analog zu den Standard-Funktionsblöcken, etwa [Funktion aus Blöcken erstellen (mit Rückgabewert)](#funktion-aus-blöcken-erstellen-mit-rückgabewert) oder [Funktion aus Blöcken erstellen (ohne Rückgabewert)](#funktion-aus-blöcken-erstellen-ohne-rückgabewert).
### Eigene Funktion erstellen (mit Rückgabewert)

Dieser eigene Funktionsblock kann Werte zurückgeben. Um ein Ergebnis aus der Funktion zurückzugeben, schreibst du:
```
return 'dein Ergebnis';
```
Wie hier:

```xml
sum
cmV0dXJuIGEgKyBiOw==
Summarise a and b
log
test
5
6
```
### Funktion aufrufen


Für jede angelegte Funktion erscheint im Menü ein zusätzlicher Block mit dem Namen dieser Funktion.
Du kannst ihn wie jeden anderen Block in deinen Skripten verwenden.
## AI Chat für Blockly
Das AI-Chat-Panel ist jetzt auch für Blockly-Scripts verfügbar. Klicke auf den AI-Button (Zauberstab-Symbol) in der Toolbar, um das Chat-Panel neben dem Blockly-Editor zu öffnen.
### Funktionsumfang
- **Chat-Modus**: Stelle Fragen zu deinem Blockly-Script. Die KI sieht den generierten JavaScript-Code als Kontext.
- **Code-Modus**: Beschreibe eine Automatisierungsaufgabe und die KI generiert Blockly-XML-Blöcke in einem Zwei-Schritt-Prozess (Plan, dann Blöcke).
- **Visuelle Vorschau**: KI-generierte Blöcke werden als grafische Blockly-Vorschau direkt im Chat dargestellt statt als rohes XML.
- **Blöcke einfügen**: Klicke auf "Blöcke einfügen", um die KI-generierten Blöcke in deinen Blockly-Workspace einzufügen.
- **Diff-Ansicht**: Klicke auf "Als Diff anzeigen" für einen Side-by-Side-Vergleich deiner aktuellen Blöcke mit den KI-vorgeschlagenen Blöcken, mit Akzeptieren/Ablehnen-Buttons.
### Unterstützte Block-Typen
Die KI kann folgende ioBroker-Blockly-Blocktypen generieren:
- **on_ext** – Trigger (auf Zustandsänderungen reagieren)
- **schedule** – Cron-basierte Zeitpläne
- **control** – Zustand setzen (setState)
- **get_value** – Zustandswert lesen (getState)
- **debug** – Log-Ausgabe
- **sendto_custom** – Nachrichten senden (z.B. Telegram)
- **timeouts_settimeout** – Verzögerte Aktionen
- **controls_if** – Wenn/Dann-Bedingungen
- **logic_compare** – Vergleiche (EQ, NEQ, LT, GT, etc.)
- **math_number**, **text**, **logic_boolean** – Wert-Blöcke
### Tipps
- Verwende den **Code-Modus** zum Generieren neuer Blöcke aus einer Aufgabenbeschreibung.
- Verwende den **Chat-Modus** (oder Agent-Modus) für Fragen zu bestehenden Blöcken.
- Die KI funktioniert am besten, wenn du deine Automatisierung in einfacher Sprache beschreibst, z.B. "Schalte das Wohnzimmerlicht ein, wenn der Bewegungssensor auslöst".
- Du kannst `@geräte` verwenden, um deine Smart-Home-Geräte in den Kontext einzubeziehen.