Hallo zusammen,
ich möchte hier ein kurzes Skript vorstellen, mit dem sich die Daten einer Ambientika-Lüftungsanlage (Smart-Geräte von Ambientika) in ioBroker auslesen lassen. Das Skript basiert auf Code, der in diesem GitHub-Repository dokumentiert ist. Es authentifiziert sich zunächst bei der Ambientika-API, ruft den Status der Lüftungsanlage ab und schreibt die Messwerte bzw. Geräteeinstellungen in einzelne ioBroker-Datenpunkte.
Voraussetzungen
ioBroker mit installiertem JavaScript-Adapter
axios als npm-Paket in der JavaScript-Adapter-Umgebung Zugangsdaten für die Ambientika-Cloud (Benutzername und Passwort)
Seriennummer des jeweiligen Ambientika-Geräts
Funktionsweise des Skripts
Authentifizierung:
Über die Methode authenticate() wird ein POST-Request an die Ambientika-API gesendet. Bei erfolgreicher Anmeldung liefert die API einen JWT‑Token zurück.
Gerätestatus abrufen:
Nach der Authentifizierung wird über getDeviceStatus() ein GET-Request an /device/device-status geschickt, um den aktuellen Status des Lüftungsgeräts (Temperatur, Luftfeuchtigkeit, Lüftergeschwindigkeit etc.) zu erhalten.
Datenpunkte in ioBroker:
Die empfangenen Werte werden in separate Datenpunkte geschrieben (z. B. ambientika.temperature für die Temperatur). Damit lässt sich jeder Messwert in ioBroker individuell weiterverarbeiten oder visualisieren.
Automatischer Ablauf:
Ein setInterval(updateAmbientikaData, 60000) ruft alle 60 Sekunden die Aktualisierung auf. So bleiben die Datenpunkte in ioBroker immer auf dem neuesten Stand.
Skript-Code
Das folgende Skript wird im ioBroker-JavaScript-Adapter (als JavaScript-Datei oder direkt im Skript-Editor) hinterlegt und ausgeführt. Achtet darauf, die Platzhalter (DEIN_BENUTZERNAME, DEIN_PASSWORT, DEINE_DEVICE_SERIAL_NUMBER) durch eure echten Werte zu ersetzen. Außerdem muss die Konstante host ggf. an eure Instanz angepasst werden, falls sich an der API-URL etwas ändert.
// Ambientika-Integration in ioBroker mittels axios (muss in Deiner ioBroker-Umgebung installiert sein)
const axios = require('axios');
// Konfiguration (bitte anpassen)
const host = "https://app.ambientika.eu:4521";
const username = "DEIN_BENUTZERNAME";
const password = "DEIN_PASSWORT";
const deviceSerialNumber = "DEINE_DEVICE_SERIAL_NUMBER";
// Mapping für fanSpeed: "Low" -> 0, "Medium" -> 1, "High" -> 2
const fanSpeedMapping = {
"Low": 0,
"Medium": 1,
"High": 2
};
// Datenpunkte anlegen
createState("ambientika.authStatus", { name: "Authentifizierungsstatus", type: "string", role: "state" }, "", true);
createState("ambientika.operatingMode", { name: "Betriebsmodus", type: "string", role: "state" }, "", true);
createState("ambientika.fanSpeed", { name: "Lüftergeschwindigkeit", type: "number", role: "value" }, 0, true);
createState("ambientika.humidityLevel", { name: "Luftfeuchtigkeitsstufe", type: "string", role: "state" }, "", true);
createState("ambientika.lightSensorLevel", { name: "Licht-Sensor-Level", type: "string", role: "state" }, "", true);
createState("ambientika.temperature", { name: "Temperatur", type: "number", role: "value", unit: "°C" }, 0, true);
createState("ambientika.humidity", { name: "Luftfeuchtigkeit", type: "number", role: "value", unit: "%" }, 0, true);
createState("ambientika.airQuality", { name: "Luftqualität", type: "string", role: "state" }, "", true);
createState("ambientika.humidityAlarm", { name: "Feuchtigkeitsalarm", type: "boolean", role: "indicator" }, false, true);
createState("ambientika.filtersStatus", { name: "Filterstatus", type: "string", role: "state" }, "", true);
createState("ambientika.nightAlarm", { name: "Nachtalarm", type: "boolean", role: "indicator" }, false, true);
createState("ambientika.deviceRole", { name: "Geräterolle", type: "string", role: "state" }, "", true);
createState("ambientika.lastOperatingMode", { name: "Letzter Betriebsmodus", type: "string", role: "state" }, "", true);
createState("ambientika.packetType", { name: "Pakettyp", type: "string", role: "state" }, "", true);
createState("ambientika.deviceType", { name: "Gerätetyp", type: "string", role: "state" }, "", true);
createState("ambientika.deviceSerialNumber", { name: "Geräteseriennummer", type: "string", role: "state" }, "", true);
// Funktion zur Authentifizierung
async function authenticate() {
try {
const response = await axios.post(`${host}/users/authenticate`, {
username: username,
password: password
});
if (response.status === 200) {
setState("ambientika.authStatus", "Authentifiziert", true);
return { id: response.data.id, token: response.data.jwtToken };
} else {
setState("ambientika.authStatus", "Authentifizierung fehlgeschlagen", true);
throw new Error("Authentifizierung fehlgeschlagen, Status: " + response.status);
}
} catch (error) {
setState("ambientika.authStatus", "Fehler: " + error.message, true);
throw error;
}
}
// Funktion zum Abrufen des Gerätestatus
async function getDeviceStatus(authData) {
try {
const response = await axios.get(`${host}/device/device-status`, {
headers: { "Authorization": "Bearer " + authData.token },
params: { deviceSerialNumber: deviceSerialNumber }
});
if (response.status === 200) {
return response.data;
} else {
throw new Error("Statusabfrage fehlgeschlagen, Status: " + response.status);
}
} catch (error) {
throw error;
}
}
// Hauptfunktion zur Aktualisierung der Ambientika-Daten
async function updateAmbientikaData() {
try {
const authData = await authenticate();
const statusData = await getDeviceStatus(authData);
// Setzen der einzelnen Datenpunkte, ggf. Umwandlung der Werte
setState("ambientika.operatingMode", statusData.operatingMode, true);
// Umwandlung des fanSpeed-Werts von String in Zahl
let fanSpeedValue = fanSpeedMapping[statusData.fanSpeed] !== undefined ? fanSpeedMapping[statusData.fanSpeed] : 0;
setState("ambientika.fanSpeed", fanSpeedValue, true);
setState("ambientika.humidityLevel", statusData.humidityLevel, true);
setState("ambientika.lightSensorLevel", statusData.lightSensorLevel, true);
setState("ambientika.temperature", statusData.temperature, true);
setState("ambientika.humidity", statusData.humidity, true);
setState("ambientika.airQuality", statusData.airQuality, true);
setState("ambientika.humidityAlarm", statusData.humidityAlarm, true);
setState("ambientika.filtersStatus", statusData.filtersStatus, true);
setState("ambientika.nightAlarm", statusData.nightAlarm, true);
setState("ambientika.deviceRole", statusData.deviceRole, true);
setState("ambientika.lastOperatingMode", statusData.lastOperatingMode, true);
setState("ambientika.packetType", statusData.packetType, true);
setState("ambientika.deviceType", statusData.deviceType, true);
setState("ambientika.deviceSerialNumber", statusData.deviceSerialNumber, true);
log("Ambientika-Daten aktualisiert: " + JSON.stringify(statusData));
} catch (error) {
log("Fehler beim Aktualisieren der Ambientika-Daten: " + error.message, "error");
}
}
// Aktualisierung alle 60 Sekunden; initialer Abruf erfolgt sofort
setInterval(updateAmbientikaData, 60000);
updateAmbientikaData();
Hinweise & Tipps
Fehlermeldungen: Sollten Warnungen bzgl. falscher Typen im ioBroker-Log erscheinen, prüft, ob alle Datenpunkte (z. B. „fanSpeed“) den passenden Typ haben. Im Skript erfolgt bereits eine Umwandlung von String zu Zahl über das fanSpeedMapping.
Zusätzliche Anpassungen: Wer weitere Werte benötigt oder bestimmte Betriebsmodi (z. B. „change-mode“) ansteuern möchte, kann den Code leicht erweitern. Die Ambientika-API bietet weitere Endpunkte, die über axios aufgerufen werden können.
Intervall anpassen: Falls ein 60‑Sekunden-Intervall zu hoch oder zu niedrig ist, lässt sich das in der letzten Zeile mit setInterval(...) ändern.
Ich hoffe, das Skript hilft euch, Ambientika-Geräte problemlos in ioBroker einzubinden. Solltet ihr Fragen oder Ergänzungen haben, meldet euch gerne!
Viel Erfolg beim Ausprobieren!
edit: Github Repo