Archiv des Autors: Stephan

Über Stephan

Als Kind der 90er Jahre wuchs ich in einer Übergangs-Ära von analog zu digital auf. Vorteil: man kennt analog und stieg direkt in's Digitale ein. Auch heute begeistert mich die digitale Welt noch - wenn nicht sogar mehr denn je. Heutzutage sind die kleinen Nullen und Einsen gar nicht mehr wegzudenken ...

Batterie Status der ZigBee Geräte abfragen und per WhatsApp zuschicken lassen

Dieses Skript dient der Abfrage des Batteriestandes Deiner ZigBee Geräte. Es läuft in Standardeinstellung nachts um 1 Uhr und stellt alle wesentlichen Informationen wie Gerätename, Raum und Batteriestand (in Volt und Prozent) bereit und schickt sie Dir per WhatsApp zu.

Vorbereitung

Damit dieses Skript zuverlässig funktioniert, benötigst Du mein Skript für den WhatsAppBot. Nebenbei erwähnt kannst Du das Skript auch verwenden, um die Mitteilungen per E-Mail zu versenden. Dazu sind ein paar Anpassungen notwendig.

Skript

Zuerst erstellst du ein neues Javascript im Bereich common.

/*
 * @copyright 2021 Stephan Kreyenborg <stephan@kreyenborg.koeln>
 *
 * @author 2021 Stephan Kreyenborg <stephan@kreyenborg.koeln>
 *
 * Dieses Skript dient zur freien Verwendung in ioBroker zur Verbrauchserfassung der Shelly Geräte.
 * Jegliche Verantwortung liegt beim Benutzer. Das Skript wurde unter Berücksichtigung der bestmöglichen Nutzung
 * und Performance entwickelt.
 * Der Entwickler versichert, das keine böswilligen Systemeingriffe im originalen Skript vorhanden sind.
 *
 * Sollte das Skript wider Erwarten nicht korrekt funktionieren, so hast Du jederzeit die Möglichkeit, Dich auf
 * https://www.kreyenborg.koeln
 * für Unterstützung zu melden. Jedes Skript besitzt seine eigene Kommentarseite, auf der,
 * nach zeitlicher Möglichkeit des Autors, Hilfe angeboten wird. Ein Anrecht hierauf besteht nicht!
 * 
 * Ansprüche gegenüber Dritten bestehen nicht. 
 * 
 * Skript Name:		ZigBee Batterie Status
 * Skript Version:	1.1
 * Erstell-Datum:	25. April 2021
 * 
 */

// Datenpunkt der ZigBee Geräte (Standard: zigbee.0)
var zigbee_dp = "zigbee.0";

// Datenpunkte der ZigBee (!!! Bitte nicht ändern !!!)
const zigbeeDpsBattery = $('state[id=' + zigbee_dp + '.*.battery]');

function zigbeeBatterieStatus() {
    // Anzahl gefundene ZigBee Geräte
    var gefundene_geraete = new Array();

    // Namen der ZigBee Geräte
    var geraete_namen = new Array();

    // Batteriestand der ZigBee Geräte
    var batterie_stand = new Array();

    // Batteriestand in Volt der ZigBee Geräte
    var batterie_volt = new Array();

    // Räume der ZigBee Geräte - falls angegeben
    var raeume = new Array();

    // Batterie Status des ZigBee Gerät
    var status = new Array();
    log("ZigBee Batterie Status: Batterie Status wird abgefragt!");
    zigbeeDpsBattery.each(function (id) {
        let tmp_id = id.split(".");
        var tmp_id_g = tmp_id[0] + "." + tmp_id[1] + "." + tmp_id[2];
        gefundene_geraete.push(tmp_id_g);
        // Speichere Namen ab
        var name = getObject(tmp_id_g).common.name;
        if (name != "") {
            geraete_namen.push(name);
        } else {
            geraete_namen.push("");
        }

        // Hole Batteriestand
        var tmp_batterie_stand = getState(tmp_id_g + ".battery").val;
        if (tmp_batterie_stand != null) {
            batterie_stand.push(tmp_batterie_stand + "%");

            // Status der Batterie
            if (tmp_batterie_stand > 75) {
                status.push("voll");
            }
            if (tmp_batterie_stand <= 50) {
                status.push("");
            }
            if (tmp_batterie_stand <= 25) {
                status.push("kritisch");
            }
            if (tmp_batterie_stand < 25) {
                status.push("fast leer");
            }
        } else {
            batterie_stand.push("-%");
            status.push("keine Information");
        }

        // Hole Batterie %
        var tmp_batterie_volt = getState(tmp_id_g + ".voltage").val;
        if (tmp_batterie_volt != null) {
            batterie_volt.push(tmp_batterie_volt + "V");
        } else {
            batterie_volt.push("-V");
        }

        // Hole Raum
        var tmp_raum = getObject(tmp_id_g, 'rooms').enumNames[0];
        if (tmp_raum != undefined) {
            if (tmp_raum.de != undefined) {
                raeume.push(tmp_raum.de);
            } else {
                raeume.push(tmp_raum);
            }
        } else {
            raeume.push("kein Raum");
        }
    });
    // Generiere String
    var text = '*ZigBee Batteriestatus von ' + gefundene_geraete.length;
    if (gefundene_geraete.length > 1) {
        text += ' Geräten*<br><br>';
    } else {
        text += ' Gerät*<br><br>';
    }
    for (let i = 0; i < gefundene_geraete.length; i++) {
        text += "*" + geraete_namen[i] + ":* " + status[i] + "<br>Raum: " + raeume[i] + " | Batterie: " + batterie_stand[i] + " | Volt: " + batterie_volt[i] + "<br><br>";
    }

    log("ZigBee Batterie Status: Batterie Status abgefragt!");
    // Sende Nachricht
    WhatsAppBot(0, text);
}
zigbeeBatterieStatus();

// Nachts um 1 Uhr den Batteriestand abfragen
schedule('0 1 * * *', zigbeeBatterieStatus);

Skript anpassen

In Zeile 117 musst du den Namen des WhatsAppBot Skriptes anpassen, wenn dieses von Dir anders benannt wurde, als in der Anleitung angegeben. Außerdem wird der jeweilige Empfänger benötigt – aber dies ist ja schon in der Anleitung zum WhatsAppBot erwähnt 😉

Solltest Du das Skript verwenden wollen, um die Nachrichten per E-Mail zu erhalten, so musst Du in Zeile 117 das “WhatsAppBot” gegen “sendTo” austauschen und ggf. den Text etwas anpassen, da dieser für die Verwendung in WhatsApp formatiert ist (* für Fettschrift).

Status Mitteilung per WhatsApp empfangen

Die Statusmitteilung erscheint wie folgt auf Deinem Mobiltelefon.

ZigBee Batterie Status in WhatsApp

Sonoff/Tasmota Verbrauchs-Historie für Tag, Woche, Monat, Jahr

Dieses Skript ist eine Abwandlung des Skriptes, welches bereits für die Shelly Adapter zur Verfügung steht. Hier werden die Tasmota und Sonoff Geräte unterstützt.

Übersicht der Funktionen

Folgende Verbrauchswerte stehen in der Historie für jeden der Sonoff Geräte zur Verfügung:

FunktionBeschreibung
Verbrauch heuteabgefragter Verbrauch heute
Verbrauch gesternabgefragter Verbrauch gestern
Verbrauch diese Wocheabgefragter Verbrauch für die gesamte Woche
Verbrauch letzte Wocheabgefragter Verbrauch für die gesamte letzte Woche
Verbrauch dieser Monatabgefragter Verbrauch für den gesamten Monat
Verbrauch letzter Monatabgefragter Verbrauch für den gesamten letzten Monat
Verbrauch dieses Jahrabgefragter Verbrauch für das gesamte Jahr
Verbrauch letztes Jahrabgefragter Verbrauch für das gesamte letzte Jahr
Verbrauch Gesamtabgefragter Verbrauch gesamt
NameZugewiesener Name des Sonoff zum einfachen Wiederfinden
Übersicht über die einzelnen Datenpunkte

Screenshot der verfügbaren Variablen

Screenshot der verfügbaren Variablen
Screenshot der verfügbaren Variablen

Installation des Sonoff Adapter

Installation des Sonoff Adapter

Nach kurzer Zeit stehen die Datenpunkte aller gefundenen Sonoff Geräte unter sonoff.0 zur Verfügung.

Skript

/*
 * @copyright 2020 Stephan Kreyenborg <stephan@kreyenborg.koeln>
 *
 * @author 2020 Stephan Kreyenborg <stephan@kreyenborg.koeln>
 *
 * Dieses Skript dient zur freien Verwendung in ioBroker zur Verbrauchserfassung der Tasmota Geräte.
 * Jegliche Verantwortung liegt beim Benutzer. Das Skript wurde unter Berücksichtigung der bestmöglichen Nutzung
 * und Performance entwickelt.
 * Der Entwickler versichert, das keine böswilligen Systemeingriffe im originalen Skript vorhanden sind.
 *
 * Sollte das Skript wider Erwarten nicht korrekt funktionieren, so hast Du jederzeit die Möglichkeit, Dich auf
 * https://www.kreyenborg.koeln
 * für Unterstützung zu melden. Jedes Skript besitzt seine eigene Kommentarseite, auf der,
 * nach zeitlicher Möglichkeit des Autors, Hilfe angeboten wird. Ein Anrecht hierauf besteht nicht!
 * 
 * Ansprüche gegenüber Dritten bestehen nicht. 
 * 
 * Skript Name:		Tasmota-Verbrauch
 * Skript Version:	1.1
 * Erstell-Datum:	19. März 2021
 * 
 */

// Datenpunkte neu erstellen
var ueberschreiben = false;

// Hauptdatenpunkt unterhalb javascript
var datenpunkt = "TasmotaVerbrauch.";

// Verbrauchs Objekte der einzelnen Tasmota
const objekt = ["gesamt", "dieses_jahr", "letztes_jahr", "letzter_monat", "dieser_monat", "letzte_woche",
    "diese_woche", "gestern", "heute", "alter_wert", "aktueller_wert"];

// Beschreibung der Objekte
const beschreibung = ["Gesamter Vebrauch des Tasmota", "Verbrauch aktuelles Jahr", "Verbrauch letztes Jahr",
    "Verbrauch letzten Monat", "Verbrauch aktueller Monat", "Verbrauch letzte Woche", "Verbrauch diese Woche",
    "Verbrauch gestern", "Verbrauch heute", "Messwert alt", "Messwert neu"];

// Datenpunkt der Tasmota Geräte (Standard: sonoff.0)
var tasmota_dp = "sonoff.0";

// Datenpunkte der Tasmota (!!! Bitte nicht ändern !!!)
const tasmotaDps = $('state[id=' + tasmota_dp + '.*.ENERGY_Total]');

// Datenpunkte der Tasmota Namen (!!! Bitte nicht ändern !!!)
const tasmotaDpsName = $('state[id=' + tasmota_dp + '.*.DeviceName]');

// Tasmota Verbrauch aktualisieren - nachts um 00:00 Uhr
function tasmota_vebrauch_tag() {
    // Nochmals das Tagesupdate durchlaufen, damit die restlichen Werte gelesen werden
    tasmota_verbrauch_update();

    // Datumsvariable
    var heute = new Date();

    // Heute zu Gestern verschieben. Täglich um 00:00 Uhr
    verschiebe_verbrauch_objekt("heute", "gestern");
    log ("Tasmota Verbrauch: Werte für gestern und heute aktualisiert!");

    // aktuelle Woche in letzte Woche verschieben. Am Montag um 00:00 Uhr
    if (heute.getDay() === 1) {
        verschiebe_verbrauch_objekt("diese_woche", "letzte_woche");
        log ("Tasmota Verbrauch: Werte für diese und letzte Woche aktualisiert!");
    }

    // aktueller Monat in letzten Monat verschieben. Am 1. des Monats um 00:00 Uhr
    if (heute.getDate() === 1) {
        verschiebe_verbrauch_objekt("dieser_monat", "letzter_monat");
        log ("Tasmota Verbrauch: Werte für diesen und letzten Monat aktualisiert!");
    }

    // aktuelles Jahr in letztes Jahr verschieben. Am 1. des Monats am 1. Monat um 00:00 Uhr
    if (heute.getDate() === 1 && heute.getMonth() === 0) {
        verschiebe_verbrauch_objekt("dieses_jahr", "letztes_jahr");
        log ("Tasmota Verbrauch: Werte für dieses und letztes Jahr aktualisiert!");
    }
}

// Tagesverbrauch alle 15 Min von der Original Variable des Tasmota in eigene Variable kopieren
function tasmota_verbrauch_update() {
    var anzahl_updates = 0;
    var anzahl_reboots = 0;
    var anzahl_gleich = 0;
    tasmotaDps.each(function (id, i) {
        var tasmota_verbrauch = getState(id).val;
        // Einige Tasmota haben keine Verbrauchswerte (noch nicht)
        if (tasmota_verbrauch != null) {
            // Hole aktuellen Wert, um zu kontrollieren, ob ein Reboot stattgefunden hat
            var aktueller_wert = getState(tasmota_DP(id) + "aktueller_wert").val;
            var alter_wert = 0;
            // Prüfe alten und neuen Wert
            if (tasmota_verbrauch > aktueller_wert) {
                // Verbrauchswert ist größer als alter Wert -> es wurde kein Reboot durchgeführt
                setState(tasmota_DP(id) + "alter_wert", aktueller_wert,true);
                alter_wert = aktueller_wert;
                anzahl_updates++;
            }
            if (aktueller_wert > tasmota_verbrauch) {
                // Verbrauchswert ist kleiner als alter Wert -> es wurde ein Reboot durchgeführt
                setState(tasmota_DP(id) + "alter_wert", 0,true);
                alter_wert = tasmota_verbrauch;
                anzahl_reboots++;
            }
            if (tasmota_verbrauch == aktueller_wert) {
                // Verbrauchswert ist gleich wie alter Wert -> kein Update notwendig
                alter_wert = aktueller_wert;
                anzahl_gleich++;
            }

            setState(tasmota_DP(id) + "aktueller_wert", tasmota_verbrauch);
            // Alter und neuer Wert -> aktuelle Differenz

            var verbrauch = parseFloat(tasmota_verbrauch) - alter_wert;
            // Tagesverbrauch aktualisieren
            aktualisiere_vebrauch_objekt(id, "heute", verbrauch);

            // Wochenverbrauch aktualisieren
            aktualisiere_vebrauch_objekt(id, "diese_woche", verbrauch);

            // Monatsverbrauch aktualisieren
            aktualisiere_vebrauch_objekt(id, "dieser_monat", verbrauch);

            // Jahresverbrauch aktualisieren
            aktualisiere_vebrauch_objekt(id, "dieses_jahr", verbrauch);

            // Gesamten Vebrauch aktualisieren
            aktualisiere_vebrauch_objekt(id, "gesamt", verbrauch);
        }
    });
    aktualisiere_namen();
    log("Tasmota Verbrauch: Verbrauchswerte aktualisiert: " + anzahl_updates + " | Reboots korrigiert: " + anzahl_reboots + " | Unveränderte Werte: " + anzahl_gleich);
}

// aktualisiert das jeweilige Verbrauchs-Objekt und addiert den Verbrauch dazu
function aktualisiere_vebrauch_objekt(dp, objekt, wert) {
    var verbrauch = parseFloat(getState(tasmota_DP(dp) + objekt).val) + parseFloat(wert);
    verbrauch = parseFloat(verbrauch.toFixed(3));
    setState(tasmota_DP(dp) + objekt, verbrauch,true);
}

// Verschiebt das jeweilige Verbrauchs-Objekt und nullt den Ursprung (Tag, Woche, Monat, Jahr)
function verschiebe_verbrauch_objekt(von, nach) {
    $('state[id=*.' + datenpunkt + '*.' + von + ']').each(function (id, i) {
        // Temporärer Gruppen-Datenpunkt
        var tmp_dp = id.slice(0, -(von.length));
        var verbrauch = getState(id).val;
        if (verbrauch != null) {
            setState(tmp_dp + nach, verbrauch,true);
        }
        // Setze heute zurück
        setState(id, 0,true);
    });
}

// Funktion um die aktuellen Namen der Tasmota abzuholen
function aktualisiere_namen() {
    tasmotaDpsName.each(function (id, i) {
        setState(tasmota_DP_Name(id),String(getState(id).val),true);
    });
}

// Erstelle die benötigten Datenpunkte
function datenpunkte_erstellen() {
    // Anzahl der gefundenen Tasmota
    var anzahl = tasmotaDps.length;

    tasmotaDps.each(function (id, j) {
        var initial_wert = 0;
        for (var i = 0; i < objekt.length; i++) {
            // Startwerte werden nur bei alter_wert und aktueller_wert eingetragen
            if (i > 8) {
                initial_wert = getState(id).val;
            }
            createState(tasmota_DP(id) + objekt[i], initial_wert, ueberschreiben, {
                name: beschreibung[i],
                desc: beschreibung[i],
                type: "number",
                role: "value.power",
                unit: "kWh"
            });
        }
    });
    
    // Alle Datenpunkte erstellt. Frage ersten Verbrauch ab!
    log("Tasmota Verbrauch: Datenpunkte erstellt! Erster Verbrauch steht nach 1 Minute zur Verfügung! Anzahl gefundener Tasmota Datenpunkte: " + anzahl);
    setTimeout(tasmota_verbrauch_update, 20000);
    
    // Datenpunkte für die Namen der Tasmota erstellen
    tasmotaDpsName.each(function(id, j) {
        createState(tasmota_DP_Name(id), "", ueberschreiben, {
            name: "Name des Tasmota",
            desc: "Name des Tasmota",
            type: "string",
            role: "value",
            unit: ""
        });
    });
}

function tasmota_DP(dp) {
    dp = dp.split(".");
    dp = datenpunkt + dp[2] + ".";
    return dp;
}

function tasmota_DP_Name(dp) {
    dp = dp.split(".");
    dp = datenpunkt + dp[2] + "." + dp[3];
    return dp;
}

function tasmota_verbrauch_erster_start() {
    log("Tasmota Verbrauch: Erster Start des Skriptes! Datenpunkte werden erstellt!");
    // Datenpunkte werden erstellt
    datenpunkte_erstellen();
}

// Erster Start und Initialisierung
tasmota_verbrauch_erster_start();

// Alle 15 Minuten das Skript für den Tagesverbrauch ausführen
schedule('*/15 * * * *', tasmota_verbrauch_update);

// Nachts um 24 Uhr werden die Werte in andere Variablen gespeichert, um den Verlauf zu erstellen
schedule('0 0 * * *', tasmota_vebrauch_tag);

Speedtest für ioBroker

Für ioBroker gibt es aktuell 2 Speedtest Adapter, die bei vielen funktionieren – jedoch bei vielen eben auch nicht. Das ist besonders der Fall, wenn man einen Vodafone Cable Max 1000 (ehemals Unitymedia) Tarif hat. Ich habe noch nicht herausgefunden, wieso diese Speedtests nicht richtig laufen – jedoch habe ich mir selbst Abhilfe geschaffen, um hier auch selbst vernünftige Werte zu erhalten.

Vorbereitung

Damit der Speedtest richtig funktioniert, muss das Paket von Ookla (Speedtest.net) installiert werden. Dazu loggen wir uns auf dem Pi ein und führen folgende Befehle aus. Solltest Du bereits einen Speedtest installiert haben, der bspw. mit “speedtest-cli” aufgerufen wird, so ist dieser vorher zu entfernen.

Speedtest-CLI entfernen:

sudo apt-get remove speedtest-cli

Ookla Speedtest installieren

sudo apt-get install gnupg1 apt-transport-https dirmngr
export INSTALL_KEY=379CE192D401AB61
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys $INSTALL_KEY
echo "deb https://ookla.bintray.com/debian generic main" | sudo tee  /etc/apt/sources.list.d/speedtest.list
sudo apt-get update
sudo apt-get install speedtest

Datenpunkte

Das Skript füllt die eigenen Datenpunkte mit allen verfügbaren Rückgabewerten, die dieser Test zur Verfügung stellt. Des Weiteren sind die Datenpunkte strukturiert aufgebaut. Das heißt, der Datenpunkt Ergebnisse enthält alle Daten eines Test, wohingegen der Datenpunkt Test (mit Unterpunkten: Server und Daten) Informationen zu dem eigentlichen Test enthält. Auch gibt es einen Datenpunkt Server, welcher die Informationen zur Gegenstelle vorhält.

DatenpunktBeschreibung
JSON_OutputAusgabe der Konsole
PingPing in ms
JitterJitter in ms
Download_MBitDownload Geschwindigkeit in MBit/s
Upload_MBitUpload Geschwindigkeit in MBit/s
Download_MBDownload Geschwindigkeit in MB/s
Upload_MBUpload Geschwindigkeit in MB/s
OriginalDownloadDownload Geschwindigkeit in Byte/s
OriginalUploadUpload Geschwindigkeit in Byte/s
ISPInternet Service Provider
IPexterne IP
URLAdresse der Ergebnisse
IDID der Ergebnisse
ServerIDID des getesteten Servers
ServerIPIP des getesteten Servers
NameAnbieter des getesteten Servers
StadtStadt des getesteten Servers
LandLand des getesteten Servers
AdresseURL des getesteten Servers
DownloadDownload Daten in MB
UploadUpload Daten in MB
OriginalDownloadDownload Daten in Byte
OriginalUploadUpload Daten in Byte
DauerDownloadDauer des Download Test in Sekunden
DauerUploadDauer des Upload Test in Sekunden
Verfügbare Datenpunkte des Skripts

Skript

Nun erstellen wir in ioBroker ein neues Skript im common Bereich. Es bekommt den Namen “Speedtest”.

Der Aufruf erfolgt alle 30 Minuten und kann in der letzten Zeile angepasst werden. Auch lässt sich zur besseren Diagnose der eigenen Leitung ein fester Server in Zeile 32 eintragen. Eine Liste mit Servern in Deiner Umgebung gibt es hier:
https://www.speedtest.net/speedtest-servers.php

Soll das Skript immer den besten Server nehmen und automatisch entscheiden, so lasse diesen bei 0.

/*
 * @copyright 2020 Stephan Kreyenborg <stephan@kreyenborg.koeln>
 *
 * @author 2020 Stephan Kreyenborg <stephan@kreyenborg.koeln>
 *
 * Dieses Skript dient zur freien Verwendung in ioBroker zur Verbrauchserfassung der Shelly Geräte.
 * Jegliche Verantwortung liegt beim Benutzer. Das Skript wurde unter Berücksichtigung der bestmöglichen Nutzung
 * und Performance entwickelt.
 * Der Entwickler versichert, das keine böswilligen Systemeingriffe im originalen Skript vorhanden sind.
 *
 * Sollte das Skript wider Erwarten nicht korrekt funktionieren, so hast Du jederzeit die Möglichkeit, Dich auf
 * https://www.kreyenborg.koeln
 * für Unterstützung zu melden. Jedes Skript besitzt seine eigene Kommentarseite, auf der,
 * nach zeitlicher Möglichkeit des Autors, Hilfe angeboten wird. Ein Anrecht hierauf besteht nicht!
 * 
 * Ansprüche gegenüber Dritten bestehen nicht. 
 * 
 * Skript Name:		Speedtest
 * Skript Version:	1.1
 * Erstell-Datum:	11. März 2021
 * 
 */

// Datenpunkte neu erstellen
var ueberschreiben = false;

// Hauptdatenpunkt unterhalb javascript
var datenpunkt = "Speedtest.";

// Favorisierter Server
// Liste: https://www.speedtest.net/speedtest-servers-static.php
var fav_server = 0;

// Speedtest Objekte
var objekt = ["JSON_Output",
    "Ergebnisse.Ping",
    "Ergebnisse.Jitter",
    "Ergebnisse.Download_MBit",
    "Ergebnisse.Upload_MBit",
    "Ergebnisse.Download_MB",
    "Ergebnisse.Upload_MB",
    "Ergebnisse.OriginalDownload",
    "Ergebnisse.OriginalUpload",
    "ISP",
    "IP",
    "Ergebnisse.URL",
    "Ergebnisse.ID",
    "Test.Server.ServerID",
    "Test.Server.ServerIP",
    "Test.Server.Name",
    "Test.Server.Stadt",
    "Test.Server.Land",
    "Test.Server.Adresse",
    "Test.Daten.Download",
    "Test.Daten.Upload",
    "Test.Daten.OriginalDownload",
    "Test.Daten.OriginalUpload",
    "Test.Daten.DauerDownload",
    "Test.Daten.DauerUpload"
];

// Beschreibung der Objekte
var beschreibung = ["JSON Ausgabe der Konsole",
    "Ping in ms",
    "Jitter in ms",
    "Download Geschwindigkeit in MBit/s",
    "Upload Geschwindigkeit in MBit/s",
    "Download Geschwindigkeit in MB/s",
    "Upload Geschwindigkeit in MB/s",
    "Download Geschwindigkeit in Byte/s",
    "Upload Geschwindigkeit in Byte/s",
    "Internet Service Provider",
    "externe IP",
    "Adresse der Ergebnisse",
    "ID der Ergebnisse",
    "ID des getesteten Servers",
    "IP des getesteten Servers",
    "Anbieter des getesteten Servers",
    "Stadt des getesteten Servers",
    "Land des getesteten Servers",
    "URL des getesteten Servers",
    "Download Daten in MB",
    "Upload Daten in MB",
    "Download Daten in Byte",
    "Upload Daten in Byte",
    "Dauer des Download Test",
    "Dauer des Upload Test"
];

// Einheiten der Objekte
var einheiten = ["",
    "ms",
    "ms",
    "MBit/s",
    "MBit/s",
    "MB/s",
    "MB/s",
    "Byte/s",
    "Byte/s",
    "",
    "",
    "",
    "",
    "",
    "",
    "",
    "",
    "",
    "",
    "MB",
    "MB",
    "Byte",
    "Byte",
    "s",
    "s"
];

// Typen der Objekte
var typen = ["string",
    "number",
    "number",
    "number",
    "number",
    "number",
    "number",
    "number",
    "number",
    "string",
    "string",
    "string",
    "string",
    "number",
    "string",
    "string",
    "string",
    "string",
    "string",
    "number",
    "number",
    "number",
    "number",
    "number",
    "number"
];

// Rollen der Objekte
var rolle = ["json",
    "value",
    "value",
    "value",
    "value",
    "value",
    "value",
    "value",
    "value",
    "text",
    "text",
    "text",
    "text",
    "value",
    "text",
    "text",
    "text",
    "text",
    "text",
    "value",
    "value",
    "value",
    "value",
    "value",
    "value"
];

// Schreibe Werte des JSON String in ein Array
function generiere_array(json_array) {
    var j = JSON.parse(json_array);
    var array_werte = [json_array,
        j.ping.latency,
        j.ping.jitter,
        parseFloat((j.download.bandwidth / 125000).toFixed(2)),
        parseFloat((j.upload.bandwidth / 125000).toFixed(2)),
        parseFloat((j.download.bandwidth / (1024 * 1024)).toFixed(2)),
        parseFloat((j.upload.bandwidth / (1024 * 1024)).toFixed(2)),
        j.download.bandwidth,
        j.upload.bandwidth,
        j.isp,
        j.interface.externalIp,
        j.result.url,
        j.result.id,
        j.server.id,
        j.server.ip,
        j.server.name,
        j.server.location,
        j.server.country,
        j.server.host,
        parseFloat((j.download.bytes / (1024 * 1024)).toFixed(2)),
        parseFloat((j.upload.bytes / (1024 * 1024)).toFixed(2)),
        j.download.bytes,
        j.upload.bytes,
        parseFloat((j.download.elapsed / 1000).toFixed(2)),
        parseFloat((j.upload.elapsed / 1000).toFixed(2)),
    ];
    return array_werte;
}

function speedtest() {
    // temporäre Variable für das Array
    var tmp_json;
    // Kommando für den Speedtest
    var kommando = "speedtest -f json --accept-license --accept-gdpr";
    if (fav_server > 0) {
        kommando = kommando + " -s " + fav_server;
        log("Speedtest mit Server " + fav_server + " gestartet! Der Test dauert zwischen 10 - 20 Sekunden!");
    } else {
        log("Speedtest gestartet! Der Test dauert zwischen 10 - 20 Sekunden!");
    }
    exec(kommando,
        function (error, stdout) {
            if (error) {
                log('Speedtest konnte nicht ausgeführt werden! ' + error, 'error');
                return;
            } else {
                tmp_json = generiere_array(stdout);
                aktualisiere_datenpunkt(tmp_json);
                log('Speedtest durchgeführt. Ergebisse: Download: ' + tmp_json[5] + ' MB/s | Upload: ' + tmp_json[6] + ' MB/s | Ping: ' + tmp_json[1] + 'ms');
            }
        });
}

function aktualisiere_datenpunkt(werte) {
    for (let i = 0; i < objekt.length; i++) {
        setState(datenpunkt + objekt[i], werte[i], true);
    }
}

// Erstelle die benötigten Datenpunkte
function datenpunkte_erstellen() {
    for (var i = 0; i < objekt.length; i++) {
        createState(datenpunkt + objekt[i], "", ueberschreiben, {
            name: beschreibung[i],
            desc: beschreibung[i],
            type: typen[i],
            role: rolle[i],
            unit: einheiten[i]
        });
    }

    // Alle Datenpunkte erstellt. Führe ersten Speedtest aus!
    log('Speedtest: Datenpunkte erstellt! Erster Speedtest wird in 30 Sekunden ausgeführt!');
    setTimeout(speedtest, 30000);
}

function speedtest_erster_start() {
    log("Speedtest: Erster Start des Skriptes! Datenpunkte werden erstellt!");
    // Datenpunkte werden erstellt
    datenpunkte_erstellen();
}

// Erster Start und Initialisierung
speedtest_erster_start();

// Alle 30 Minuten einen Speedtest ausführen
schedule('*/30 * * * *', speedtest);

Shelly Schalter mit Xiaomi Aqara Bewegungsmelder in ioBroker schalten

Wer einen Xiaomi Aqara sein Eigen nennt, kann in Verbindung mit dem ioBroker auch andere Geräte schalten. Ich habe bei mir so eine Schaltung mit einem Aqara und einem Shelly gekoppelt. Wie das geht, zeige ich Dir in diesem Beitrag.

Sobald der Aqara Sensor über den ZigBee Adapter eingebunden ist, erscheint er unterhalb des Datenpunkt zigbee.0 . Wie dies funktioniert, habe ich in diesem Beitrag beschrieben.

Damit Du nun Deinen Shelly per Bewegungsmelder schalten kannst und dieser automatisch ausschaltet, musst Du in deinem Shelly Datenpunkt den AutoTimerOff auf die entsprechenden Sekunden einstellen.

Shelly Timer

Ich habe bei mir 300 Sekunden – also 5 Minuten – gewählt. Diese Einstellung kannst natürlich an deine Bedürfnisse anpassen.

Im Weiteren Schritt erstellst Du dir nun ein Skript im common Bereich.

on({ id: "zigbee.0.00158d000659f68c.occupancy", change: "any" }, function (obj) {
    if (getState("zigbee.0.00158d0006XXXXXX.illuminance").val < 35) {
        // Helligkeit bei unter 35 Lux, Licht einschalten
        setState("shelly.0.SHSW-PM#XXXXXX#1.Relay0.Switch", true);
    }
    // Wenn Lampe an, dann Lampe erneut an, dadurch Timer restart
    if (getState("shelly.0.SHSW-PM#XXXXXX#1.Relay0.Switch").val == true) {
        setState("shelly.0.SHSW-PM#XXXXXX#1.Relay0.Switch", true);
    }
});

Hier ist es notwendig, deine Datenpunkte in den markierten Zeilen entsprechend anzupassen. Ich habe die Schaltung so eingestellt, das der Sensor unterhalb von 35 Lux den Shelly einschaltet. Sollte während dieser Zeit erneut eine Bewegung erkannt werden, so wird der Shelly erneut mit einem Schaltbefehl versorgt, sodass der integrierte AutTimerOff erneut gestartet wird.

System Updates für den Raspberry PI über VIS installieren

Normalerweise nutzt man die VIS Oberfläche um den Status von Geräten oder Aktoren darzustellen oder mit ihnen zu interagieren.
Warum aber sollte man sie nicht auch zur Interaktion von Befehlen nutzen?
Ich stelle Dir hier die Möglichkeit vor, die System Updates, welche für den Raspberry Pi vorliegen, mit einem Klick zu installieren und dies auch in einem Statusfenster zu verfolgen.

Skript

Zuerst erstellst Du ein neues Javascript im Bereich common.
Dieses Skript bitte nicht starten.

/*
 * @copyright 2020 Stephan Kreyenborg <stephan@kreyenborg.koeln>
 *
 * @author 2020 Stephan Kreyenborg <stephan@kreyenborg.koeln>
 *
 * Dieses Skript dient zur freien Verwendung in ioBroker zur Verbrauchserfassung der Shelly Geräte.
 * Jegliche Verantwortung liegt beim Benutzer. Das Skript wurde unter Berücksichtigung der bestmöglichen Nutzung
 * und Performance entwickelt.
 * Der Entwickler versichert, das keine böswilligen Systemeingriffe im originalen Skript vorhanden sind.
 *
 * Sollte das Skript wider Erwarten nicht korrekt funktionieren, so hast Du jederzeit die Möglichkeit, Dich auf
 * https://www.kreyenborg.koeln
 * für Unterstützung zu melden. Jedes Skript besitzt seine eigene Kommentarseite, auf der,
 * nach zeitlicher Möglichkeit des Autors, Hilfe angeboten wird. Ein Anrecht hierauf besteht nicht!
 * 
 * Ansprüche gegenüber Dritten bestehen nicht. 
 * 
 * Skript Name:		APT Update installieren
 * Skript Version:	1.2
 * Erstell-Datum:	02. April 2021
 * 
 */

// Kommandos
var command_update = "sudo apt update";
var command_anzahl_updates = "apt list --upgradable 2>/dev/null | wc -l | awk '{print $S1-1}'";
var command_upgrade = "sudo apt-get -y upgrade";
var anzahl_updates = 0;

// Datenpunkt anlegen
var DataPoint = 'Systeminfos.ioBroker.raspi_updates_ausgabe';
createState(DataPoint, "", true, {
    name: 'Raspi Updates Ausgabe',
    desc: 'Ausgabe Systemupdates für den Raspi',
    type: 'string',
    unit: '',
    role: 'value'
},
    function () {
        installiere_updates();
    }
);

function installiere_updates() {
    // Paket-Update
    exec(command_update);
    update_datenpunkt("Prüfe auf neue Updates ...");

    // Anzahl neuer Updates
    exec(command_anzahl_updates,
        function (error, stdout, stderr) {
            if (stdout == '0') {
                anzahl_updates = 0;
            } else {
                anzahl_updates = parseInt(stdout);
            }
            if (anzahl_updates > 0) {
                log("Neue Updates: " + anzahl_updates + "<br>Neue Updates werden installiert. Bitte warten ...");
                update_datenpunkt("Neue Updates: " + anzahl_updates + "<br>Neue Updates werden installiert. Bitte warten ...");
                exec(command_upgrade, function (error, stdout, stderr) {
                    if (stdout.includes("autoremove")) {
                        update_datenpunkt("Alle Updates wurden installiert!<br>Es wurden nicht benötigte Pakete gefunden!<br><br>Fenster kann geschlossen werden!");
                    } else {
                        update_datenpunkt("Alle Updates wurden installiert!<br><br>Fenster kann geschlossen werden!");
                    }

                    // Beende Skript
                    setState("javascript.0.Systeminfos.ioBroker.raspi_updates", "0");
                    setState("javascript.0.scriptEnabled.common.APT_Update_installieren", false);
                });
            } else {
                update_datenpunkt("Keine neuen Updates zum Installieren!<br><br>Fenster kann geschlossen werden!");
                // Beende Skript
                setState("javascript.0.Systeminfos.ioBroker.raspi_updates", "0");
                setState("javascript.0.scriptEnabled.common.APT_Update_installieren", false);
            }
        });
}

function update_datenpunkt(text) {
    var tmp_text = getState(DataPoint).val;
    var neuer_text = tmp_text + "<br>" + text;
    setState(DataPoint, neuer_text, true);
}

Nachdem Du das Skript erstellt hast, musst Du die Zeile 68 im Skript auf den Namen anpassen, da dies für die Beendigung notwendig ist. Schaue dazu bitte in den Datenpunkt:

javascript.0.scriptEnabled.common

und kopiere Dir den Namen des Datenpunkt in die Zwischenablage.

Skript Datenpunkt
Skript Datenpunkt

Diesen Datenpunkt fügst Du nun in Zeile 68 ein. Standardmäßig ist dieser auf den Namen de Skripts gesetzt.

setState("javascript.0.scriptEnabled.common.APT_Update_installieren", false);

Dieses Skript dient im weiteren Verlauf zur Darstellung in VIS und beinhaltet das Prüfen auf Updates und das Installieren von Updates.

Integration in VIS

Vorbereitung

Zuerst erstellst Du eine eigene View mit dem Namen “APT_Update”. In diese View ziehst Du ein HTML Widget. Dieses HTML Widget bekommt als Text den Datenpunkt aus Zeile 34. Solltest Du diesen Datenpunkt angepasst haben, so musst Du ihn in VIS auch entsprechend anpassen. Die geschweiften Klammern vorne und hinten müssen zwingend angegeben werden, da sonst nur der Text und nicht der Datenpunkt ausgegeben wird.

{javascript.0.Systeminfos.ioBroker.raspi_updates_ausgabe}
Neue View APT_Update mit HTML Widget
Neue View APT_Update mit HTML Widget

Eigentlicher Aufruf

Damit Du nun diese View aufrufen kannst, benötigst Du in deiner “Haupt”-View ein “jqui – container – Button – view” Widget. Dieses ziehst Du an die Position, von wo aus Du das Update gerne starten wollen würdest.

Folgende Werte habe ich in meinem Widget gesetzt:

Widget Einstellungen

Als Objekt ID gibst Du den Datenpunkt aus Zeile 68 des Skriptes an und als Viewname verwendest Du den Namen der eigentlichen View. In meinem Beispielt ist dies “APT_Update”. Der Knopftext ist frei wählbar und kann heissen, wie Du gerne möchtest 😉

Wenn Du nun deine View aufrufst, kannst mit einem Klick auf den Button den Update Prozess in der VIS Oberfläche auslösen und in der Statusausgabe des Widget verfolgen, was passiert.

APT Update Ausgabe
APT Update Ausgabe

WhatsApp Nachrichten mit ioBroker versenden

In ioBroker gibt es so gut wie für jede Funktion einen eigenen Adapter. Diese verbrauchen jedoch Arbeitsspeicher, der auf einem Raspberry Pi leider nicht erweitert werden kann. Viele Dinge lassen sich mit Hilfe eines Skriptes ähnlich oder genauso gut implementieren, wie es der Adapter selbst kann. Wer also schon verschiedene Skripte laufen hat, der benötigt nicht unbedingt den WhatsApp Adapter, sondern kann sich mit meinem Skript genauso gut helfen – wenn nicht sogar noch besser, da mein Skript die Versendung an viele Empfänger bietet 😉

Update: Es werden nun auch Zeilenumbrüche “<br> unterstützt!

Hinweis

Aktuell ist die Versendung auf 25 Nachrichten pro 4 Stunden begrenzt!

Vorbereitung

Zuerst musst Du den WhatsApp Service für deine eigene Telefonnummer freischalten. Dazu nimmst Du den sogenannten WhatsApp Bot in dein Telefonbuch auf.

Nummer: +34 644 59 71 67

Nachdem Du dies erledigt hast, schickst du via WhatsApp folgenden Text an den neuen Kontakt:

I allow callmebot to send me messages

Da sich der Service aktuell noch in einer Art Testphase befindet, kommen die Nachrichten leicht verzögert (max. 1 Minute) an. Nach etwa dieser Zeit bekommst Du eine Bestätigung, das Deine Nummer für den Service aktiviert wurde. Hierin enthalten ist der sogenannte API-Key. Dieser ist zwingend für die Versendung der Nachrichten notwendig.

Skript

Zuerst erstellst Du ein neues Javascript im Bereich global.

/*
 * @copyright 2021 Stephan Kreyenborg <stephan@kreyenborg.koeln>
 *
 * @author 2021 Stephan Kreyenborg <stephan@kreyenborg.koeln>
 *
 * Dieses Skript dient zur freien Verwendung in ioBroker zur Verbrauchserfassung der Shelly Geräte.
 * Jegliche Verantwortung liegt beim Benutzer. Das Skript wurde unter Berücksichtigung der bestmöglichen Nutzung
 * und Performance entwickelt.
 * Der Entwickler versichert, das keine böswilligen Systemeingriffe im originalen Skript vorhanden sind.
 *
 * Sollte das Skript wider Erwarten nicht korrekt funktionieren, so hast Du jederzeit die Möglichkeit, Dich auf
 * https://www.kreyenborg.koeln
 * für Unterstützung zu melden. Jedes Skript besitzt seine eigene Kommentarseite, auf der,
 * nach zeitlicher Möglichkeit des Autors, Hilfe angeboten wird. Ein Anrecht hierauf besteht nicht!
 * 
 * Ansprüche gegenüber Dritten bestehen nicht. 
 * 
 * Skript Name:		WhatsAppBot
 * Skript Version:	1.1
 * Erstell-Datum:	19. April 2021
 * 
 */
function WhatsAppBot(empfaenger, text) {
    // Hier kommen Deine API Keys rein
    var api_keys = ["283786", "xxxxxx"];

    // Hier kommen die zughörigen Telefonnummern rein
    var telephone_nummer = ["+491729887930", "+4915254733234"];

    // Textnachricht bereinigen
    var nachricht = text.replace(/\s/g, "+");
    nachricht = nachricht.replace(/<br>/g,"%0A");

    // An alle oder nur an einen bestimmten Empfänger
    if (Array.isArray(empfaenger)) {
        for (let i = 0; i < empfaenger.length; i++) {
            sendeWhatsApp(telephone_nummer[empfaenger[i]], api_keys[empfaenger[i]], nachricht);
        }
    }
    if (empfaenger == "alle") {
        for (let i = 0; i < telephone_nummer.length; i++) {
            sendeWhatsApp(telephone_nummer[i], api_keys[i], nachricht);
        }
    }

    if (Number.isInteger(empfaenger)) {
        sendeWhatsApp(telephone_nummer[empfaenger], api_keys[empfaenger], nachricht);
    }
}

function sendeWhatsApp(empfaenger, api_key, nachricht) {
    if (empfaenger != "" && api_key != "" && empfaenger != undefined && api_key != undefined) {
        exec("curl -X GET 'https://api.callmebot.com/whatsapp.php?phone=" + empfaenger + "&text=" + nachricht + "&apikey=" + api_key + "'",
            function (error, stdout, stderr) {
                if (stdout.includes("Message queued") || stdout.includes("invalid") || stdout.includes("currently a limit")) {
                    if (stdout.includes("Message queued")) {
                        log("WhatsAppBot: Erfolg: Nachricht an " + empfaenger + " verschickt!");
                    }
                    if (stdout.includes("invalid")) {
                        log("WhatsAppBot: Fehler: API Key für " + empfaenger + " ist ungültig!");
                    }
                    if (stdout.includes("currently a limit")) {
                        log("WhatsAppBot: Fehler: 25 Nachrichten pro 4 Stunden Limit erreicht für " + empfaenger + "!");
                    }
                } else {
                    log("WhatsAppBot: Fehler: Nachricht an " + empfaenger + " konnte nicht verschickt werden! Error: " + error);
                }
            });
    } else {
        log("WhatsAppBot: Fehler: Empfänger oder API Key für diese Position ungültig!");
    }
}

Skript anpassen

Sobald du das Skript angelegt hast, musst Du es noch etwas anpassen.

Hierzu benötigst Du den empfangenen API Key und deine Telefonnummer.

Verwendung mit einer Telefonnummer und einem API Key

Wenn Du nur eine Telefonnummer in dem Skript verwenden möchtest, brauchst Du nur die “x”-Zeichen in den Zeilen 25 und 28 mit deinen Daten ersetzen. Denke bitte an das internationale Format der Telefonnummer.

// Hier kommen Deine API Keys rein
var api_keys = ["xxxxxx"];

// Hier kommen die zughörigen Telefonnummern rein
var telephone_nummer = ["+49171xxxxxxx"];

Verwendung mit mehreren Telefonnummern und mehreren API Key’s

Solltest Du mehrere Telefonnummern ablegen wollen, so geht dies natürlich auch. Hier bitte darauf achten, das die Position der API Keys und Telefonnummern an den gleichen Positionen im Array stehen.
Position 1: Telefonnummer 1, API Key 1
Position 2: Telefonnummer 2, API Key 2

Die Nachrichten können dann an alle oder einzelne Telefonnummern geschickt werden. Dazu kommen wir im nächsten Abschnitt.

// Hier kommen Deine API Keys rein
var api_keys = ["xxxxxx","xxxxxx","xxxxxx"];

// Hier kommen die zughörigen Telefonnummern rein
var telephone_nummer = ["+49171xxxxxxx","+49151xxxxxxx","+49150xxxxxxx"];

Skript verwenden

Sobald Du das Skript angepasst und abgespeichert hast, steht die Funktion “WhatsAppBot” in allen Skripten im “common” Bereich zur Verfügung.

Mit einer Telefonnummer

Möchtest Du nun eine Nachricht an eine Telefonnummer versenden und hast auch nur eine Nummer hinterlegt, so ist dies mit folgendem Code möglich:

WhatsAppBot(0, "Dies ist eine Testnachricht!");

Mit mehreren Telefonnummern

Verwendest Du das Skript mit mehreren Telefonnummern, so kannst Du beim Aufruf entscheiden, ob Du die Nachricht nun an alle Nummern oder nur bestimmte Nummern versenden möchtest.

An alle Nummern
WhatsAppBot("alle", "Dies ist eine Testnachricht!");
An bestimmte Nummern

Um eine Nachricht an mehrere, bestimmte hinterlegte Nummern zu versenden, musst Du den Aufruf ein klein wenig abändern und auf die Zählweise achten. In der Programmierung startet das 1. Element immer bei 0 – somit hat die erste Nummer, die gespeichert ist, die Nummer 0.
Im folgenden Beispiel wird es deutlicher.

Nehmen wir an, Du hast 4 Nummern gespeichert, es sollen aber nur die erste und letzte Nummer diese Nachricht erhalten. In dem Falle wäre der Aufruf wie folgt:

WhatsAppBot([0,3], "Dies ist eine Testnachricht!");

Natürlich lassen sich auch alle 4 Nummern eintragen. Entweder mit “alle” oder mit dem Wert [0,1,2,3].

Nachrichten formatieren

In WhatsApp gibt es auch die Möglichkeit, Nachrichten zu formatieren.

Kursiv

Um deine Nachricht kursiv zu formatieren, schreibe einen Unterstrich auf beide Seiten des Textes:

_Text_

Fett

Um deine Nachricht fett zu formatieren, schreibe ein Sternchen auf beide Seiten des Textes:

*Text*

Durchgestrichen

Um deine Nachricht durchgestrichen zu formatieren, schreibe ein Tilde-Zeichen auf beide Seiten des Textes:

~Text~

Monospace

Um deine Nachricht in Monospace zu formatieren, schreibe drei Hochkomma auf beide Seiten des Textes:

“`Text“`

Zeilenumbruch

Ein Zeilenumbruch ist mit dem Kürzel <br> möglich.

So ergibt: Hallo Du,<br>wie geht es Dir?
Hallo Du,
wie geht es Dir?

Die Formartierungen lassen sich natürlich auch kombinieren. So ergibt:

*_Hallo_* -> Hallo (fett und kursiv)

Viel Spaß mit dem Skript!

ZigBee Stick in ioBroker einbinden

Da ioBroker nun seit längerer Zeit den ZigBee Stick unterstützt, wollte ich Euch hier einmal zeigen, wie einfach dieser Stick inzwischen zu installieren ist.

Ich persönlich verwende den Stick von Sascha Sturn. Dieser ist bei eBay erhältlich.
CC2531  ZigBee USB-Sick zigbee2mqtt ioBroker FHEM openHAB SMA Antenne + Firmware

Zigbee Adapter installieren

Installation des ZigBee Adapter
Installation des ZigBee Adapter

Nach kurzer Zeit ist der Adapter installiert und kann verwendet werden. Hierzu stecken wir den ZigBee USB Stick in einen freien Port im Raspberry und rufen die Einstellungen des Adapters auf. Instanzen -> ZigBee Adapter -> Einstellungen.

ZigBee Adapter Einstellungen aufrufen
ZigBee Adapter Einstellungen aufrufen

ZigBee Adapter einrichten

In den Einstellungen des Adapters wählen wir nun “Einstellungen” aus.

ZigBee Dapter Einstellungen
ZigBee Dapter Einstellungen

COM – Anschluss

Hier ist es für die Kommunikation zwischen USB Stick und ioBroker wichtig, den richtigen COM-Anschluss auszuwählen. “ttyACM0” wird hier vom System schon richtig erkannt.

ZigBee Adapter Einstellungen - COM Anschluss
ZigBee Adapter Einstellungen – COM Anschluss

Damit sich Dein ZigBee Stick nicht mit dem Deines Nachbarn stört, empfehle ich, die Network Kennung zu verändern. Hier kannst Du 16 zufällige Zeichen von a-f und 0-9 eingeben.

Network ID

ZigBee Adapter Einstellungen - Network
ZigBee Adapter Einstellungen – Network

Kanal

Zusätzlich macht es Sinn, einmal einen Kanal-Scan auszuführen. Hier wählst Du dann den Kanal mit der geringsten Prozentangabe als deinen Kanal aus.

ZigBee Adapter Einstellungen - Kanaltabelle
ZigBee Adapter Einstellungen – Kanaltabelle
ZigBee Adapter Einstellungen - Kanal
ZigBee Adapter Einstellungen – Kanal

Zusätzlich kannst Du die LED, die auf dem USB Stick verbaut ist, bei Bedarf ausschalten.

ZigBee Adapter Einstellungen - LED
ZigBee Adapter Einstellungen – LED

Abschluss

Mit einem Klick auf “Speichern und Schließen” ist die Einrichtung des Adapters abgeschlossen. Der Adapter startet dann neu. Nachdem dies geschehen ist, kannst Du erneut in die Einstellungen des Adapters gehen und über die doppelte Funkwelle den Stick in den Kopplungs-Modus bringen.

ZigBee Adapter - Kopplung
ZigBee Adapter – Kopplung

Nun hast du 60 Sekunden Zeit, Dein ZigBee Gerät anzumelden. Wie dies im Einzelnen funktioniert, berichte ich in einem späteren Beitrag!

Shelly Verbrauchs-Historie für Tag, Woche, Monat, Jahr

Hinweis: für dieses Skript steht ein Update zur Verfügung!
Es wird nun auch der Shelly 3EM unterstützt.

In der Shelly Cloud App für iOS oder Android sieht man natürlich immer auf einen Blick, wie der Verbrauch der einzelnen oder aller Shelly ist.
Was ist aber, wenn man diese Daten auch gerne Offline zur weiteren Verarbeitung speichern möchte?
Hier stößt man leider schnell auf ein Problem, das der Verbrauch des Shelly zwar abgelesen werden kann – jedoch nur der Verbrauch seit dem letzten Neustart.

Somit würde sich der Verbrauch immer verändern, wenn der Shelly aufgrund von Stromausfall oder Software-Update neugestartet wurde.

Hierzu habe ich mir lange Gedanken gemacht und ein Skript entwickelt, welches die Werte aus den einzelnen Shelly in einer einstellbaren Zeit abfragt und in eigene Datenpunkte speichert. Auch ist eine Korrektur von Reboot Werten vorhanden. Somit werden die Zähler der temporären Berechnung genullt, sobald festgestellt wurde, das der Shelly neu gestartet wurde. Dies hat keinen Einfluss auf die gesamte Berechnung des Verbrauchs – im Gegenteil: Die Berechnung des Verbrauchs wird genauer!

Übersicht der Funktionen

Folgende Verbrauchswerte stehen in der Historie für jeden der Shelly zur Verfügung:

FunktionBeschreibung
Verbrauch heuteabgefragter Verbrauch heute
Verbrauch gesternabgefragter Verbrauch gestern
Verbrauch diese Wocheabgefragter Verbrauch für die gesamte Woche
Verbrauch letzte Wocheabgefragter Verbrauch für die gesamte letzte Woche
Verbrauch dieser Monatabgefragter Verbrauch für den gesamten Monat
Verbrauch letzter Monatabgefragter Verbrauch für den gesamten letzten Monat
Verbrauch dieses Jahrabgefragter Verbrauch für das gesamte Jahr
Verbrauch letztes Jahrabgefragter Verbrauch für das gesamte letzte Jahr
Verbrauch Gesamtabgefragter Verbrauch gesamt
NameZugewiesener Name des Shelly zum einfachen Wiederfinden
Übersicht über die einzelnen Datenpunkte

Screenshot der verfügbaren Variablen

Screenshot der verfügbaren Variablen
Screenshot der verfügbaren Variablen

Installation des Shelly Adapter

Installation des Shelly Adapter
Installation des Shelly Adapter

Nach kurzer Zeit stehen die Datenpunkte aller gefundenen Shellys unter shelly.0 zur Verfügung.

Skript

/*
 * @copyright 2020 Stephan Kreyenborg <stephan@kreyenborg.koeln>
 *
 * @author 2020 Stephan Kreyenborg <stephan@kreyenborg.koeln>
 *
 * Dieses Skript dient zur freien Verwendung in ioBroker zur Verbrauchserfassung der Shelly Geräte.
 * Jegliche Verantwortung liegt beim Benutzer. Das Skript wurde unter Berücksichtigung der bestmöglichen Nutzung
 * und Performance entwickelt.
 * Der Entwickler versichert, das keine böswilligen Systemeingriffe im originalen Skript vorhanden sind.
 *
 * Sollte das Skript wider Erwarten nicht korrekt funktionieren, so hast Du jederzeit die Möglichkeit, Dich auf
 * https://www.kreyenborg.koeln
 * für Unterstützung zu melden. Jedes Skript besitzt seine eigene Kommentarseite, auf der,
 * nach zeitlicher Möglichkeit des Autors, Hilfe angeboten wird. Ein Anrecht hierauf besteht nicht!
 * 
 * Ansprüche gegenüber Dritten bestehen nicht. 
 * 
 * Skript Name:		Shelly-Verbrauch
 * Skript Version:	1.40
 * Erstell-Datum:	05. Mai 2021
 * 
 */

// Datenpunkte neu erstellen
var ueberschreiben = false;

// Hauptdatenpunkt unterhalb javascript
var datenpunkt = "ShellyVerbrauch.";

// Verbrauchs Objekte der einzelnen Shelly
const objekt = ["gesamt", "dieses_jahr", "letztes_jahr", "letzter_monat", "dieser_monat", "letzte_woche",
    "diese_woche", "gestern", "heute", "alter_wert", "aktueller_wert"];

// Beschreibung der Objekte
const beschreibung = ["Gesamter Vebrauch des Shelly", "Verbrauch aktuelles Jahr", "Verbrauch letztes Jahr",
    "Verbrauch letzten Monat", "Verbrauch aktueller Monat", "Verbrauch letzte Woche", "Verbrauch diese Woche",
    "Verbrauch gestern", "Verbrauch heute", "Messwert alt", "Messwert neu"];

// Datenpunkt der Shelly (Standard: shelly.0)
var shelly_dp = "shelly.0";

// Datenpunkte der Shelly (!!! Bitte nicht ändern !!!)
const shellyDps = $('state[id=' + shelly_dp + '.*.*.Energy]');

// Datenpunkte der Shelly 3EM DP
const shelly3EMDps = $('state[id=' + shelly_dp + '.*.*.Total]');

// Datenpunkte der Shelly Namen (!!! Bitte nicht ändern !!!)
const shellyDpsName = $('state[id=' + shelly_dp + '.*.name]');

// Shelly Verbrauch aktualisieren - nachts um 00:00 Uhr
function shelly_vebrauch_tag() {
    // Nochmals das Tagesupdate durchlaufen, damit die restlichen Werte gelesen werden
    shelly_verbrauch_update();

    // Datumsvariable
    var heute = new Date();

    // Heute zu Gestern verschieben. Täglich um 00:00 Uhr
    verschiebe_verbrauch_objekt("heute", "gestern");
    log("Shelly Verbrauch: Werte für gestern und heute aktualisiert!");

    // aktuelle Woche in letzte Woche verschieben. Am Montag um 00:00 Uhr
    if (heute.getDay() === 1) {
        verschiebe_verbrauch_objekt("diese_woche", "letzte_woche");
        log("Shelly Verbrauch: Werte für diese und letzte Woche aktualisiert!");
    }

    // aktueller Monat in letzten Monat verschieben. Am 1. des Monats um 00:00 Uhr
    if (heute.getDate() === 1) {
        verschiebe_verbrauch_objekt("dieser_monat", "letzter_monat");
        log("Shelly Verbrauch: Werte für diesen und letzten Monat aktualisiert!");
    }

    // aktuelles Jahr in letztes Jahr verschieben. Am 1. des Monats am 1. Monat um 00:00 Uhr
    if (heute.getDate() === 1 && heute.getMonth() === 0) {
        verschiebe_verbrauch_objekt("dieses_jahr", "letztes_jahr");
        log("Shelly Verbrauch: Werte für dieses und letztes Jahr aktualisiert!");
    }
}

// Tagesverbrauch alle 15 Min von der Original Variable des Shelly in eigene Variable kopieren
function shelly_verbrauch_update() {
    var anzahl_updates = 0;
    var anzahl_reboots = 0;
    var anzahl_gleich = 0;
    shellyDps.each(function (id, i) {
        var shelly_verbrauch = getState(id).val;
        // Einige Shelly haben keine Verbrauchswerte (noch nicht)
        if (shelly_verbrauch != null) {
            // Hole aktuellen Wert, um zu kontrollieren, ob ein Reboot stattgefunden hat
            var aktueller_wert = getState(shelly_DP(id) + "aktueller_wert").val;
            var alter_wert = 0;
            // Prüfe alten und neuen Wert
            if (shelly_verbrauch > aktueller_wert) {
                // Verbrauchswert ist größer als alter Wert -> es wurde kein Reboot durchgeführt
                setState(shelly_DP(id) + "alter_wert", aktueller_wert, true);
                alter_wert = aktueller_wert;
                anzahl_updates++;
            }
            if (aktueller_wert > shelly_verbrauch) {
                // Verbrauchswert ist kleiner als alter Wert -> es wurde ein Reboot durchgeführt
                setState(shelly_DP(id) + "alter_wert", 0, true);
                alter_wert = 0;
                anzahl_reboots++;
            }
            if (shelly_verbrauch == aktueller_wert) {
                // Verbrauchswert ist gleich wie alter Wert -> kein Update notwendig
                alter_wert = aktueller_wert;
                anzahl_gleich++;
            }

            setState(shelly_DP(id) + "aktueller_wert", shelly_verbrauch, true);
            // Alter und neuer Wert -> aktuelle Differenz

            var verbrauch = parseFloat(shelly_verbrauch) - alter_wert;
            // Tagesverbrauch aktualisieren
            aktualisiere_vebrauch_objekt(id, "heute", verbrauch);

            // Wochenverbrauch aktualisieren
            aktualisiere_vebrauch_objekt(id, "diese_woche", verbrauch);

            // Monatsverbrauch aktualisieren
            aktualisiere_vebrauch_objekt(id, "dieser_monat", verbrauch);

            // Jahresverbrauch aktualisieren
            aktualisiere_vebrauch_objekt(id, "dieses_jahr", verbrauch);

            // Gesamten Vebrauch aktualisieren
            aktualisiere_vebrauch_objekt(id, "gesamt", verbrauch);
        }
    });
    shelly3EMDps.each(function (id, i) {
        var shelly_verbrauch = getState(id).val;
        // Einige Shelly haben keine Verbrauchswerte (noch nicht)
        if (shelly_verbrauch != null) {
            // Hole aktuellen Wert, um zu kontrollieren, ob ein Reboot stattgefunden hat
            var aktueller_wert = getState(shelly_DP(id) + "aktueller_wert").val;
            var alter_wert = 0;
            // Prüfe alten und neuen Wert
            if (shelly_verbrauch > aktueller_wert) {
                // Verbrauchswert ist größer als alter Wert -> es wurde kein Reboot durchgeführt
                setState(shelly_DP(id) + "alter_wert", aktueller_wert, true);
                alter_wert = aktueller_wert;
                anzahl_updates++;
            }
            if (aktueller_wert > shelly_verbrauch) {
                // Verbrauchswert ist kleiner als alter Wert -> es wurde ein Reboot durchgeführt
                setState(shelly_DP(id) + "alter_wert", 0, true);
                alter_wert = 0;
                anzahl_reboots++;
            }
            if (shelly_verbrauch == aktueller_wert) {
                // Verbrauchswert ist gleich wie alter Wert -> kein Update notwendig
                alter_wert = aktueller_wert;
                anzahl_gleich++;
            }

            setState(shelly_DP(id) + "aktueller_wert", shelly_verbrauch, true);
            // Alter und neuer Wert -> aktuelle Differenz

            var verbrauch = parseFloat(shelly_verbrauch) - alter_wert;
            // Tagesverbrauch aktualisieren
            aktualisiere_vebrauch_objekt(id, "heute", verbrauch);

            // Wochenverbrauch aktualisieren
            aktualisiere_vebrauch_objekt(id, "diese_woche", verbrauch);

            // Monatsverbrauch aktualisieren
            aktualisiere_vebrauch_objekt(id, "dieser_monat", verbrauch);

            // Jahresverbrauch aktualisieren
            aktualisiere_vebrauch_objekt(id, "dieses_jahr", verbrauch);

            // Gesamten Vebrauch aktualisieren
            aktualisiere_vebrauch_objekt(id, "gesamt", verbrauch);
        }
    });
    aktualisiere_namen();
    log("Shelly Verbrauch: Verbrauchswerte aktualisiert: " + anzahl_updates + " | Reboots korrigiert: " + anzahl_reboots + " | Unveränderte Werte: " + anzahl_gleich);
}

// aktualisiert das jeweilige Verbrauchs-Objekt und addiert den Verbrauch dazu
function aktualisiere_vebrauch_objekt(dp, objekt, wert) {
    var verbrauch = parseFloat(getState(shelly_DP(dp) + objekt).val) + parseFloat(wert);
    verbrauch = parseFloat(verbrauch.toFixed(2));
    setState(shelly_DP(dp) + objekt, verbrauch, true);
}

// Verschiebt das jeweilige Verbrauchs-Objekt und nullt den Ursprung (Tag, Woche, Monat, Jahr)
function verschiebe_verbrauch_objekt(von, nach) {
    $('state[id=*.' + datenpunkt + '*.*.' + von + ']').each(function (id, i) {
        // Temporärer Gruppen-Datenpunkt
        var tmp_dp = id.slice(0, -(von.length));
        var verbrauch = getState(id).val;
        if (verbrauch != null) {
            setState(tmp_dp + nach, verbrauch, true);
        }
        // Setze heute zurück
        setState(id, 0, true);
    });
}

// Funktion um die aktuellen Namen des Shelly abzuholen
function aktualisiere_namen() {
    shellyDpsName.each(function (id, i) {
        setState(shelly_DP_Name(id), String(getState(id).val), true);
        extendObject("javascript.0." + shelly_DP_Name_Main(id), {
            common: {
                name: String(getState(id).val),
                desc: String(getState(id).val)
            }, type: "channel"
        });
    });
    shelly3EMDps.each(function (id, i) {
        setState(shelly_DP_Name(id), String(getState(id).val), true);
        extendObject("javascript.0." + shelly_DP_Name_Main(id), {
            common: {
                name: String(getState(id).val),
                desc: String(getState(id).val)
            }, type: "channel"
        });
    });
}

// Erstelle die benötigten Datenpunkte
function datenpunkte_erstellen() {
    // Anzahl der gefundenen Shelly
    var anzahl = shellyDps.length;

    shellyDps.each(function (id, j) {
        var initial_wert = 0;
        for (var i = 0; i < objekt.length; i++) {
            // Startwerte werden nur bei alter_wert und aktueller_wert eingetragen
            if (i > 8) {
                initial_wert = getState(id).val;
            }
            createState(shelly_DP(id) + objekt[i], initial_wert, ueberschreiben, {
                name: beschreibung[i],
                desc: beschreibung[i],
                type: "number",
                role: "value.power",
                unit: "Wh"
            });
        }
    });

    // Anzahl der gefundenen Shelly 3EM
    var anzahl_3em = shelly3EMDps.length;

    shelly3EMDps.each(function (id, j) {
        var initial_wert = 0;
        for (var i = 0; i < objekt.length; i++) {
            // Startwerte werden nur bei alter_wert und aktueller_wert eingetragen
            if (i > 8) {
                initial_wert = getState(id).val;
            }
            createState(shelly_DP(id) + objekt[i], initial_wert, ueberschreiben, {
                name: beschreibung[i],
                desc: beschreibung[i],
                type: "number",
                role: "value.power",
                unit: "Wh"
            });
        }
    });

    // Alle Datenpunkte erstellt. Frage ersten Verbrauch ab!
    log("Shelly Verbrauch: Datenpunkte erstellt! Erster Verbrauch steht nach 30 Sekunden zur Verfügung! Anzahl gefundener Shelly Datenpunkte: " + (anzahl_3em + anzahl));
    setTimeout(shelly_verbrauch_update, 30000);

    // Datenpunkte für die Namen der Shelly erstellen
    shellyDpsName.each(function (id, j) {
        createState(shelly_DP_Name(id), "", ueberschreiben, {
            name: "Name des Shelly",
            desc: "Name des Shelly",
            type: "string",
            role: "value",
            unit: ""
        });
    });
    // Datenpunkte für die Namen der Shelly 3EM erstellen
    shelly3EMDps.each(function (id, j) {
        createState(shelly_DP_Name(id), "", ueberschreiben, {
            name: "Name des Shelly",
            desc: "Name des Shelly",
            type: "string",
            role: "value",
            unit: ""
        });
    });
}

function shelly_DP(dp) {
    dp = dp.split(".");
    dp = datenpunkt + dp[2] + "." + dp[3] + ".";
    return dp;
}

function shelly_DP_Name(dp) {
    dp = dp.split(".");
    dp = datenpunkt + dp[2] + "." + dp[3];
    return dp;
}

function shelly_DP_Name_Main(dp) {
    dp = dp.split(".");
    dp = datenpunkt + dp[2];
    return dp;
}

function shelly_verbrauch_erster_start() {
    log("Shelly Verbrauch: Erster Start des Skriptes! Datenpunkte werden erstellt!");
    // Datenpunkte werden erstellt
    datenpunkte_erstellen();
}

// Erster Start und Initialisierung
shelly_verbrauch_erster_start();

// Alle 15 Minuten das Skript für den Tagesverbrauch ausführen
schedule('*/15 * * * *', shelly_verbrauch_update);

// Nachts um 24 Uhr werden die Werte in andere Variablen gespeichert, um den Verlauf zu erstellen
schedule('0 0 * * *', shelly_vebrauch_tag);

Datenpunkte

Nachdem das Skript angelaufen ist und regelmäßig die Verbräuche der Shelly abgefragt wurden, findest Du diese im Datenpunkt: javascript.0.ShellyVerbrauch

Neue Shelly eingebunden, das Skript liest die Daten nicht aus!

Solltest Du zur Laufzeit des Skripts neue Shelly eingebunden haben, so kannst du das Skript einmal stoppen und erneut starten. Dann werden auch die passenden Datenpunkte für die neuen Shelly gefunden und ausgelesen.

Radiowelle

Shelly mit Hilfe eines NFC Tag schalten

Du hast für Dein Schlafzimmer einen Shelly 1 oder gar Shelly 2.5 (für Decken- und Stehleuchte) eingebaut? Dann stellt sich beim Schlafen gehen meistens die Frage: “Licht aus? Handy-Taschenlampe an!”, damit Du nicht über Dinge, die am Boden liegen, stolperst? Oder gar: Nachttischlampe an, wieder zurück zum Schalter, diesen ausschalten und erneut den Weg Richtung Bett antreten.

Das geht auch einfacher!

Benötigt werden:

Einrichtung des Makros in MacroDroid

Als Auslöser stellst Du NFC Sticker ein und als Aktion den Aufruf als HTTP GET (Ohne Web Browser). Beim Auswählen des NFC Sticker muss dieser bereitliegen, da er gescannt wird. Ein Name “Licht Schlafzimmer” o.ä. ist hier hilfreich, damit man die Sticker später auseinander halten kann. MacroDroid schreibt nun nur den Namen auf den Sticker und speichert diesen ab.

Die Adresse für den Aufruf über MacroDroid stellst Du wie folgt ein:

http://IP-DEINES-SHELLY/relay/0?turn=toggle

Die Variable “turn” steht hier auf toggle. Das heißt, das bei jedem Aufruf der Status geändert wird: An -> Aus, Aus -> An. Diese kannst Du auch verwenden, um das Licht immer nur aus oder nur an zuschalten.

Für an:
http://IP-DEINES-SHELLY/relay/0?turn=on

Für aus:
http://IP-DEINES-SHELLY/relay/0?turn=off

Nach dem Speichern des Makros kannst Du den NFC Tag direkt testen.

E-Mail

E-Mail aus der HomeMatic heraus senden

Wenn alle Schaltungen oder Timer in Deiner HomeMatic Installation reibungslos laufen, ist dies ein beruhigendes Gefühl. Doch, was ist, wenn plötzlich ein Fehler auftritt und du unterwegs bist? Oder, Du möchtest benachrichtigt werden, wenn ein gewisses Ereignis eintritt? In solchen Fällen benötigst Du, um eine E-Mail Benachrichtigung aus der HomeMatic heraus senden zu können, das E-Mail Plugin, welches Du hier herunterladen kannst.
Bitte die tar.gz-Datei nicht entpacken.

Installation auf der HomeMatic

Die Installation des Plugin läuft genauso ab, wie die Installation der anderen Plugins.

HomeMatic WebUI über Einstellungen -> Systemsteuerung -> Zusatzsoftware

Installation des E-Mail Plugin
Installation des E-Mail Plugin

Konfiguration des Plugin

Um das Plugin einzustellen, gehst Du nach der Installation auf Einstellen.

Einstellung des E-Mail Plugin
Einstellung des E-Mail Plugin

E-Mails

In diesem Bereich richtest Du zuerst eine Testmail unter der Vorlage 01 ein. Diese einhält eine funktionierende Adresse, einen Betreff und einen Test-Text.

E-Mail Vorlage erstellen
E-Mail Vorlage erstellen

Account

Danach wechselst Du in den Reiter Account. Dort kannst Du die Einstellungen deines E-Mail Kontos angeben.

Account Einstellungen
Account Einstellungen

Nach einem Klick auf Übernehmen. Kannst Du in der Karteikarte Hilfe einsehen, ob die Einstellungen korrekt sind. Für gmail, web.de oder o.ä. muss ggf. der Versand über SMTP noch im Kundenkonto aktiviert werden.

Tcl

Tcl Einstellungen
Tcl Einstellungen

Die Tcl Einstellungen (Tool command language) kannst Du verwenden, um Variablen in einer E-Mail zu übergeben. Ich verwende hier einen kleinen Code, der den Betreff (Subject) und E-Mail Text (Body) aus HomeMatic Variablen ausliest und diese entsprechend formatiert einfügt.

load tclrega.so

array set values [rega_script {

var subject = dom.GetObject("E-Mail.Subject").Value();
var body = dom.GetObject("E-Mail.Body").Value();

} ]

set subject $values(subject)
set body [encoding convertto $values(body)]

Hinweis: Mittels der im Tcl-Skript definierten Platzhalter können nicht nur Werte und Zustände von HomeMatic Geräten oder Variablen in den Email-Text oder den Betreff übergeben werden, sondern auch die Empfänger Email-Adresse oder einen Pfad für den Dateianhang.

Hilfe

In diesem Bereich kannst du nun eine Testmail versenden, um Deine Konfiguration zu testen.

Testmail versenden
Testmail versenden

Nachdem nun der Versand der Mails problemlos funktioniert, können wir uns an die Einrichtung der Vorlagen machen.

E-Mail Vorlagen erstellen

In diesem Bereich kannst Du Vorlagen für verschiedene Ereignisse anlegen. Ich benutze bei mir 4 Vorlagen (Fehler, Status, Abgeschlossen und Alarm). Diese kannst Du natürlich an Deine Bedürfnisse anpassen. Im weiteren Verlauf werden wir diese in HomeMatic einrichten. Hier sind die 2 ersten Vorlagen, die ich verwende:

Hier kannst Du direkt sehen, das die Variablen $subject und $body von oben erneut auftauchen. So lässt sich das Layout der Mail schon festlegen und später über die HomeMatic Variablen befüllen.

Mit der Einrichtung des Plugins sind wir nun fertig. Mit einem Klick auf Übernehmen werden die Vorlagen gespeichert und das Plugin ist einsatzbereit.

Einrichtung auf der HomeMatic

Anlegen der Systemvariablen

Insgesamt benötigst Du 3 Systemvariablen. 2 vom Typ Zeichenkette und 1 vom Typ Werteliste.

Name:Typ:
E-Mail.BodyZeichenkette
E-Mail.SubjectZeichenkette
E-Mail.VersandWerteliste
Folgende Systemvariablen müssen angelegt werden
HomeMatic Variablen anlegen
HomeMatic Variablen anlegen

Die Werteliste beinhaltet kein Versand;Fehler;Status;Abgeschlossen;Alarm als Werte. Somit baut sich die Vorlagenliste von oben wir folgt auf:

Werteliste-Element:Vorlage:
0
101
202
303
404
Vorlage und Werteliste-Element

Nachdem wir nun alle Variablen angelegt haben, erstellen wir das Herzstück: das Programm.

E-Mail Programm erstellen

Damit das Versenden von E-Mails zentral gesteuert wird, legst Du ein Programm an, welches den Zustand der Werteliste E-Mail.Versand überwacht.

E-Mail Programm auf der HomeMatic
E-Mail Programm auf der HomeMatic

Skript:

! Servicemeldungen versenden ####################################
object subject = dom.GetObject ("E-Mail.Subject");
object body = dom.GetObject ("E-Mail.Body");
object versand = dom.GetObject ("E-Mail.Versand");

if ((subject.Value() != "") && (body.Value() != "") && (versand.Value() > 0)) {
	system.Exec ("/etc/config/addons/email/email 0" # versand.Value());
	
	subject.State ("");
	body.State ("");
	versand.State (0);
}

Damit Du nun endlich eine E-Mail beim Eintreten eines Ereignisses versenden kannst, zeige ich Dir nun die Einrichtung.

Du kannst zum Beispiel ein Programm erstellen, welches Dich benachrichtigt, sobald die Waschmaschine fertig ist. Dies ist bei mir eine “Abgeschlossen” Meldung.

E-Mail beim Eintreten eines Ereignisses versenden
E-Mail beim Eintreten eines Ereignisses versenden

Implementierung per Skript

Eine Implementierung per Skript lässt sich wie folgt durchführen. Das Skript lässt sich so schnell kopieren und erneut ans Ende eines Programms einfügen, als jedes Mal 5 zusätzliche Felder anzuklicken.

Skript:

! Servicemeldungen versenden ####################################
object subject = dom.GetObject ("E-Mail.Subject");
object body = dom.GetObject ("E-Mail.Body");
object versand = dom.GetObject ("E-Mail.Versand");

subject.State ("Waschmaschine");
body.State ("Die Waschmaschine ist fertig!");
versand.State (3);