Plugins erweitern den Logic Editor von kaenix um eigene Node-Typen.
Jedes Plugin ist eine einzelne JavaScript-Datei und wird beim Start automatisch geladen.
plugins/
└── mein-plugin/
└── mein-plugin-kaenix.js ← Dateiname endet auf -kaenix.js
Der Ordnername spielt keine Rolle – erkannt werden alle Dateien, die auf -kaenix.js enden.
module.exports = {
type: 'mein-plugin', // eindeutiger Typ-Bezeichner (kebab-case)
category: 'Eigene', // Gruppe im Node-Menü
label: 'Mein Plugin', // Anzeigename
description: 'Was dieses Plugin tut',
color: '#6366f1', // Header-Farbe der Node (Hex)
inputs: [{ handle: 'in', label: 'Eingang' }],
outputs: [{ handle: 'out', label: 'Ausgang' }],
config: [], // Konfigurationsfelder (siehe unten)
execute(inputs, data, context) {
// Logik hier
return inputs.in; // Einzelwert → geht an outputs.out
},
};
type (string, Pflicht)Eindeutiger Bezeichner in kebab-case. Darf nur einmal vorkommen.
category (string)Gruppenname im “Node hinzufügen”-Panel, z.B. 'Automatisierung', 'Mathematik', 'Benachrichtigung'.
label / descriptionlabel erscheint als Node-Titel im Logic-Editor.
description ist nur in der Detailansicht sichtbar (nicht auf der Node selbst).
color (CSS Hex-Farbe)Header-Farbe der Node, z.B. '#f59e0b'.
inputs / outputsArrays von Handle-Definitionen:
inputs: [
{ handle: 'trigger', label: 'Trigger' },
{ handle: 'wert', label: 'Wert' },
],
outputs: [
{ handle: 'out', label: 'Ergebnis' },
{ handle: 'error', label: 'Fehler' },
],
handle ist der interne Bezeichner (wird in inputs.* und return {} verwendet).
label ist der Anzeigetext neben dem Verbindungspunkt.
configFelder, die der Nutzer pro Node-Instanz konfigurieren kann:
config: [
{ key: 'zeitSekunden', label: 'Zeit in Sekunden', type: 'number', default: 60, placeholder: '60' },
{ key: 'modus', label: 'Modus', type: 'select',
options: [
{ value: 'auto', label: 'Automatisch' },
{ value: 'manuell', label: 'Manuell' },
]
},
{ key: 'text', label: 'Nachricht', type: 'text' },
{ key: 'token', label: 'API Token', type: 'password' },
]
Verfügbare type-Werte: text, number, password, select, checkbox.
Das optionale Feld default setzt den Startwert wenn eine neue Node-Instanz angelegt wird.
dynamicOutputs(data) (optional)Statt eines statischen outputs-Arrays kann eine Funktion definiert werden, die die Ausgänge
dynamisch aus den aktuellen Konfigurationswerten berechnet. Die Node im Logic-Editor
aktualisiert ihre Handles in Echtzeit wenn der Nutzer die Konfiguration ändert.
dynamicOutputs(data) {
const n = Math.max(1, parseInt(data?.count ?? 4, 10));
return Array.from({ length: n }, (_, i) => ({
handle: `out${i + 1}`,
label: `Ausgang ${i + 1}`,
}));
},
dynamicOutputsersetztoutputs. WirddynamicOutputsdefiniert, wirdoutputsignoriert.
globalSettingsEinstellungen, die einmalig pro Plugin-Typ gelten (z.B. API-Keys).
Syntax identisch zu config. Zugriff via context.globalSetting(key).
globalSettings: [
{ key: 'apiToken', label: 'API Token', type: 'password' },
],
execute(inputs, data, context)Wird aufgerufen, wenn ein Eingangssignal eintrifft.
| Parameter | Inhalt |
|---|---|
inputs |
Objekt mit den aktuellen Eingangs-Werten, z.B. inputs.trigger, inputs.in |
data |
Konfigurationswerte der Node (aus config), z.B. data.zeitSekunden |
context |
Helper-Objekt (siehe unten) |
// Einzelwert → geht an outputs.out
return 42;
// Mehrere Ausgänge explizit setzen
return { out: 42, error: null };
// Nichts ausgeben
return {};
context – Helper-Objektcontext.log('Wert empfangen:', inputs.in); // Eintrag im Script-Log-Panel
context.warn('Achtung:', inputs.in); // Wie log, aber mit [warn]-Präfix
context.nodeLog('⏱ 42s'); // Kurztext direkt auf der Node (max. 3 Zeilen)
Für Ausgaben nach einem Timer oder HTTP-Call (der Rückgabewert von execute ist dann {}):
context.emitOutput('status', 1); // handle-Name, Wert
const token = context.globalSetting('apiToken');
context.setGlobalSetting('letzterWert', 42);
const nodeId = context.nodeId; // Eindeutige ID der Node-Instanz (string)
execute kann asynchrone Operationen starten. Wichtig: return {} sofort, Ausgaben über context.emitOutput.
Timer-Beispiel:
execute(inputs, data, context) {
if (!inputs.trigger) return {};
setTimeout(() => {
context.emitOutput('out', 1);
context.nodeLog('✓ gesendet');
}, 2000);
return {};
},
HTTP-Fetch-Beispiel:
execute(inputs, data, context) {
fetch('https://api.example.com/data')
.then((res) => res.json())
.then((json) => {
context.emitOutput('out', json.value);
context.log('Antwort:', json.value);
})
.catch((e) => context.warn('Fehler:', e.message));
return {};
},
Damit Timers und Zustände pro Node-Instanz getrennt laufen:
const _states = {};
function getState(nodeId) {
if (!_states[nodeId]) _states[nodeId] = { timer: null };
return _states[nodeId];
}
module.exports = {
// ...
execute(inputs, data, context) {
const nodeId = context.nodeId || 'default';
const s = getState(nodeId);
clearTimeout(s.timer);
s.timer = setTimeout(() => {
context.emitOutput('out', 1);
}, 1000);
return {};
},
};
/**
* @plugin Scaler
* @version 1.0.0
* @author Dein Name
*/
module.exports = {
type: 'scaler',
category: 'Mathematik',
label: 'Scaler',
description: 'Skaliert einen Wert: (in × Faktor) + Offset',
color: '#0d9488',
inputs: [{ handle: 'in', label: 'Wert' }],
outputs: [{ handle: 'out', label: 'Ergebnis' }],
config: [
{ key: 'factor', label: 'Faktor', type: 'number' },
{ key: 'offset', label: 'Offset', type: 'number' },
{ key: 'digits', label: 'Nachkommastellen', type: 'number' },
],
execute(inputs, data, context) {
const val = parseFloat(inputs.in ?? 0);
const factor = parseFloat(data.factor ?? 1);
const offset = parseFloat(data.offset ?? 0);
const digits = parseInt(data.digits ?? 1, 10);
const result = parseFloat((val * factor + offset).toFixed(digits));
context.log(`${val} × ${factor} + ${offset} = ${result}`);
return result;
},
};
| Was | Konvention | Beispiel |
|---|---|---|
| Dateiname | <name>-kaenix.js |
mein-plugin-kaenix.js |
type |
kebab-case, eindeutig | mein-plugin |
handle-Namen |
lowercase, keine Leerzeichen | trigger, restzeit |
config-Keys |
camelCase | zeitSekunden, apiToken |
| Plugin | Typ | Kategorie | Beschreibung |
|---|---|---|---|
| Scaler | scaler |
Mathematik | Skaliert einen Wert: (in × Faktor) + Offset |
| Hysterese | hysteresis |
Logik | Zweipunktregelung mit Totband (Unter-/Obergrenze) |
| Treppenhauslicht | treppenhauslicht |
Automatisierung | Schaltet ein Licht für konfigurierbare Zeit nach Trigger |
| Lauflicht | lauflicht |
Automatisierung | Schaltet N Ausgänge nacheinander ein/aus mit einstellbarer Verzögerung |
| BWM | bwm |
Automatisierung | Bewegungsmelder mit Helligkeitsschwelle, Nachlaufzeit und Grundbeleuchtung |
| Heizstab | heizstab |
Energie | Steuert einen PV-Überschuss-Heizstab mit bis zu 3 Phasen, Boost und Temperaturüberwachung |
| Push | push |
Benachrichtigung | Sendet Web-Push-Benachrichtigungen |
| CallMeBot | callmebot |
Benachrichtigung | Sendet WhatsApp-Nachrichten via CallMeBot-API |
| Shelly | shelly |
Geräte | Steuert Shelly-Geräte Gen 1–4 (Relay, Dimmer, RGBW, Jalousie, Sensoren) |
| Philips Hue | philips-hue |
Geräte | Steuert Philips Hue Lampen und Gruppen über die Hue Bridge (API v1) |
| Parameter | Typ | Default | Beschreibung |
|---|---|---|---|
schwelleDefault |
number | 100 | Helligkeitsschwelle – nur unter diesem Wert wird eingeschaltet |
nachlaufzeitDefault |
number | 1 | Nachlaufzeit in Minuten |
freigabeDefault |
number | 1 | Freigabe beim Start (1 = aktiv, 0 = gesperrt) |
grundDefault |
number | 0 | Grundbeleuchtung nach Ablauf (1 = ja, 0 = nein) |
Eingänge:
| Handle | Beschreibung |
|---|---|
trigger |
Bewegungsmelder-Impuls (1 = Bewegung erkannt) |
helligkeit |
Aktueller Helligkeitswert |
schwelle |
Helligkeitsschwelle (überschreibt Konfiguration) |
nachlaufzeit |
Nachlaufzeit in Minuten (überschreibt Konfiguration) |
freigabe |
Freigabe (1 = aktiv, 0 = gesperrt) |
grundbeleuchtung |
Grundbeleuchtung nach Ablauf aktivieren (1 = ja) |
Ausgänge:
| Handle | Beschreibung |
|---|---|
an_aus |
Schalt-Telegramm (1 = ein, 0 = aus) |
an |
Impuls beim Einschalten |
aus |
Impuls beim Ausschalten |
grund |
Grundbeleuchtung aktiv (Impuls) |
aktiv |
Nachlauf läuft gerade (1 / 0) |
restzeit |
Verbleibende Nachlaufzeit in Sekunden |
Verhalten: Trigger + Freigabe aktiv + Helligkeit ≤ Schwelle → Licht ein, Nachlauftimer startet.
Kommt während des Nachlaufs ein erneuter Trigger, wird der Timer zurückgesetzt (verlängert).
Nach Ablauf: wenn Grundbeleuchtung aktiv und Helligkeit < Schwelle → grund-Ausgang, sonst aus.
| Parameter | Typ | Default | Beschreibung |
|---|---|---|---|
outputs |
number | 4 | Anzahl Ausgänge (beliebig viele, dynamisch) |
delay |
number | 200 | Verzögerung zwischen Ausgängen in ms |
direction |
select | forward |
Richtung beim Einschalten: forward (1→N) oder backward (N→1) |
reverseOnOff |
select | 0 |
Beim Ausschalten Richtung umkehren: 0 = nein, 1 = ja |
Die Ausgänge passen sich in der Node live an wenn die Anzahl geändert wird (dynamicOutputs).
| Parameter | Typ | Default | Beschreibung |
|---|---|---|---|
minTemp |
number | 0 | Unterhalb dieser Temperatur wird sofort geheizt |
maxTemp |
number | 60 | Oberhalb von maxTemp + 0,2 °C wird abgeschaltet |
phasen |
select | 3 |
Anzahl nutzbarer Phasen (1–3) |
phasePower |
number | 2000 | Leistung pro Phase in Watt |
warten |
select | 0 |
Bei fehlendem Überschuss: 0 = alternativ heizen, 1 = warten |
batterieLimit |
number | 20 | Ab diesem Batterieladezustand (%) wird Boost aktiviert wenn kein PV-Überschuss |
ueberschuss |
number | 0 | Überschussregel: Temp-Abweichung von maxTemp ab der PV-Heizung einsetzt (0 = aus) |
beobachtung |
number | 30 | Watchdog-Zeit in Sekunden: nach Ablauf wird abgeschaltet wenn Überschuss < 1 W |
aktiv |
select | 1 |
Steuerung aktiv (1) oder inaktiv (0) |
Eingänge: 15 KNX-Eingänge (alle optional, überschreiben die Node-Konfiguration).
Ausgänge: L1, L2, L3 (Phasen), Alternativ heizen, Leistung (%), Debug.
Unterstützt Shelly-Geräte Gen 1 (REST-API) und Gen 2 / 3 / 4 (RPC-API mit Digest-Auth SHA-256).
Die Gerätegeneraion wird beim ersten Verbindungsaufbau automatisch per GET /shelly erkannt.
| Parameter | Typ | Default | Beschreibung |
|---|---|---|---|
ip |
text | – | IP-Adresse des Shelly |
port |
number | 80 |
HTTP-Port |
channel |
number | 0 |
Kanal (0-basiert, z.B. 0 oder 1 beim Shelly 2.5) |
type |
select | relay |
Gerätetyp: relay, light, color, white, roller, sensor |
rgbwRange |
select | percent |
Wertebereich für RGBW-Ein-/Ausgänge: 0–100 % oder 0–255 |
interval |
number | 0 |
Status-Abfrage-Intervall in Sekunden (0 = deaktiviert) |
dimmOn |
select | 0 |
Bei Dim > 0 automatisch einschalten |
dimmOff |
select | 0 |
Bei Dim = 0 automatisch ausschalten |
autoFwUpdate |
select | 0 |
Firmware automatisch aktualisieren wenn ein Update verfügbar ist |
username |
text | – | Benutzername (nur wenn Auth aktiviert) |
password |
password | – | Passwort – Gen 1: Basic Auth · Gen 2+: Digest Auth (SHA-256) |
Eingänge:
| Handle | Beschreibung |
|---|---|
onOff |
Ein/Aus (1 = ein, 0 = aus) |
brightness |
Helligkeit 0–100 % (Dimmer/Light) |
triggerStatus |
Trigger: Status sofort abfragen |
fwUpdate |
Trigger: Firmware-Update starten |
reboot |
Trigger: Gerät neu starten |
openClose |
Jalousie: 1 = Auf, 0 = Zu |
stop |
Jalousie: Stop-Trigger |
position |
Jalousie: Zielposition 0–100 % |
red |
Rot (Bereich je nach rgbwRange) |
green |
Grün (Bereich je nach rgbwRange) |
blue |
Blau (Bereich je nach rgbwRange) |
white |
Weiß (Bereich je nach rgbwRange) |
gain |
Gain 0–100 % |
Ausgänge:
| Handle | Beschreibung |
|---|---|
connected |
Verbindungsstatus (1 = verbunden, 0 = getrennt) |
onOff |
Status Ein/Aus (1/0) |
brightness |
Helligkeit 0–100 % |
power |
Aktuelle Leistung in W |
energy |
Gesamtenergie in kWh |
overpower |
Überlast (1 = Überlast, 0 = OK) |
temp |
Gerätetemperatur in °C |
overtemp |
Übertemperatur-Alarm (1/0) |
fwAvailable |
Firmware-Update verfügbar (1/0) |
red |
Rot (Bereich je nach rgbwRange) |
green |
Grün (Bereich je nach rgbwRange) |
blue |
Blau (Bereich je nach rgbwRange) |
white |
Weiß (Bereich je nach rgbwRange) |
gain |
Gain 0–100 % |
extTemp1 |
Externer Temperaturfühler 1 (°C, Shelly AddOn) |
extTemp2 |
Externer Temperaturfühler 2 (°C, Shelly AddOn) |
extTemp3 |
Externer Temperaturfühler 3 (°C, Shelly AddOn) |
positionOut |
Aktuelle Jalousieposition 0–100 % |
inputState |
Eingang-Status (0/1) |
inputEvent |
Eingang-Event (z.B. S, L) |
humidity |
Relative Luftfeuchte in % |
battery |
Batterieladezustand in % |
flood |
Leckage erkannt (1/0) |
motion |
Bewegung erkannt (1/0) |
tamper |
Tamper / Alarm (1/0) |
API-Unterschiede je Generation:
| Gen 1 | Gen 2 / 3 / 4 | |
|---|---|---|
| Steuern | GET /relay/0?turn=on |
POST /rpc → Switch.Set |
| Dimmen | GET /light/0?brightness=80 |
POST /rpc → Light.Set |
| RGBW | GET /color/0?red=… |
POST /rpc → RGBW.Set |
| Jalousie | GET /roller/0?go=open |
POST /rpc → Cover.Open/Close/GoToPosition |
| Status | GET /status |
POST /rpc → Shelly.GetStatus |
| Auth | HTTP Basic Auth | Digest Auth (SHA-256, im JSON-Body) |
Steuert Philips Hue Lampen und Gruppen über die Hue Bridge API v1 (HTTP, kein HTTPS erforderlich).
Der Status-Punkt im Node-Titel zeigt grün (verbunden) / rot (getrennt) basierend auf dem letzten Status-Abruf.
Globale Einstellungen (gelten für alle Hue-Nodes):
| Parameter | Beschreibung |
|---|---|
ip |
IP-Adresse der Hue Bridge |
port |
HTTP-Port (Standard: 80) |
apiKey |
API Key / Bridge Username (aus der Bridge-Einrichtung) |
Node-Konfiguration:
| Parameter | Typ | Default | Beschreibung |
|---|---|---|---|
ip |
text | – | Überschreibt globale IP (optional) |
port |
number | – | Überschreibt globalen Port (optional) |
apiKey |
text | – | Überschreibt globalen API Key (optional) |
lightId |
number | 0 |
Lampen-ID (0 = deaktiviert) |
groupId |
number | 0 |
Gruppen-ID (0 = deaktiviert, hat Vorrang wenn lightId = 0) |
gamut |
select | B |
Farbgamut: A (LivingColors, Bloom), B (Hue A19, Standard), C (Hue Go, LightStrips+) |
intelliStart |
select | 0 |
Intelli Start: Szene beim Einschalten setzen (1 = ja) |
scene |
text | – | Szenen-ID die beim Einschalten gesetzt wird (nur bei Intelli Start) |
startBri |
number | 0 |
Starthelligkeit in % beim Einschalten (0 = deaktiviert) |
interval |
number | 0 |
Status-Polling-Intervall in Sekunden (0 = deaktiviert) |
Eingänge:
| Handle | Beschreibung |
|---|---|
onOff |
Ein/Aus (1 = ein, 0 = aus) |
brightness |
Helligkeit 0–100 % |
saturation |
Sättigung 0–100 % |
colorTemp |
Farbtemperatur 0 (kalt/6500 K) bis 100 (warm/2000 K) |
red |
Rot 0–100 |
green |
Grün 0–100 |
blue |
Blau 0–100 |
hsv |
Farbe als gepackter Dezimalwert (RRGGBB hex → integer, z.B. 0xFF8800) |
scene |
Szene aktivieren (ID-String) |
dim |
KNX 4-Bit Relativdimmer (DPT 3.007) |
triggerStatus |
Trigger: Status sofort abfragen |
Ausgänge:
| Handle | Beschreibung |
|---|---|
connected |
Verbindungsstatus (1 = verbunden, 0 = getrennt) |
onOff |
Status Ein/Aus (1/0) |
brightness |
Helligkeit 0–100 % |
saturation |
Sättigung 0–100 % |
colorTemp |
Farbtemperatur 0–100 |
red |
Rot 0–100 |
green |
Grün 0–100 |
blue |
Blau 0–100 |
hsv |
Farbe als gepackter Dezimalwert (RRGGBB) |
Farbmodi im Vergleich:
| Modus | Eingang | Hue-API intern |
|---|---|---|
| Farbtemperatur | colorTemp 0–100 % |
ct 153–500 Mired |
| RGB | red / green / blue 0–100 |
xy (CIE 1931, Gamut-korrigiert) |
| HSV / Hex | hsv (Dezimalwert) |
hue 0–65535 + sat + bri |
| Szene | scene (ID-String) |
scene direkt |
KNX 4-Bit Dimmer (DPT 3.007):
Bit 3 = Richtung (1 = heller, 0 = dunkler), Bits 0–2 = Schrittweite 1–7.
Byte 0x00 = Stopp-Telegramm (wird ignoriert).