Messdaten mit RedMatic in einer InfluxDB speichern

Was die CCU3 von den Sensoren und Aktoren empfängt verschwindet schnell im Datennirvana. Natürlich kann man mit Bordmitteln ein Diagramm erstellen - möchte man jedoch alle Messdaten systematisch speichern, stösst man damit schnell an Grenzen. Besser geeignet sind Datenbanken, die auf diesen Zweck hin entworfen und optimiert wurden: sogenannte Timeseries-Datenbanken. IOT boomt und mit diesem Boom haben in den letzten Jahren diverse Timeseries-Datenbanken das Licht der IT-Welt erblickt. Im nachfolgenden Artikel werde ich die Speicherung in einer InfluxDB vorstellen.

InfluxDB

Wer bereits wie ich über einen Server verfügt - egal ob physisch oder virtuell, für den ist es ein leichtes, InfluxDB entweder per Docker oder klassisch aufzusetzen (Download hier). Die Installation der Version 2.0 ist wesentlich einfacher als 1.8, aber sie ist eben noch im Beta-Stadium.

Fast noch einfacher geht es per Cloud (hier anmelden): kleine Instanzen mit wenig Daten sind kostenlos zu haben, dafür ist die Retention period, d.h. die Länge der Historie auf 30 Tage beschränkt. Ein Upgrade auf die kostenpflichtige Version behebt diese und noch einige andere Beschränkungen und sollte die meisten Geldbeutel auch nur minimal belasten. Schlussendlich hängen die Kosten, wie bei den meisten Cloud-Diensten, von der sehr spezifischen Nutzung ab.

Da meine Installation schon länger läuft, verwende ich noch 1.8, weshalb ich den Weg für beide Versionen (1.x und 2.0) vorstellen werde.

Theoretisch könnte man die InfluxDB auch auf der CCU3 oder einem Raspberry PI installieren, da es eine ARM-Version gibt. Allerdings habe ich das nicht ausprobiert und bin auch eher skeptisch, was die Performance angeht. Ich lasse mich jedoch gerne überzeugen und würde mich freuen, Berichte über erfolgreiche oder auch gescheiterte Installationen zu bekommen.

Hat man die InfluxDB aufgesetzt oder sich im Cloud-Portal angemeldet, stellt sich die Fragen, wie die Daten dorthin gelangen. Dafür und für viele andere Aufgaben (siehe auch meinen Blog-Post "Klimadaten mit Trend auf dem E-Paperdisplay HM-Dis-EP-WM55 mit RedMatic") benutze ich Red-Matic.

RedMatic

RedMatic kommt standardmässig mit einer Anbindung an die CCU3. Mit dem Block "rpc event" werden die CCU3-Events eingefangen und als einzelne Node-Red-Messages ausgegeben.

Diese Event können noch nicht direkt in die Datenbank geschrieben werden, da man sich erst einmal für ein Mapping entscheiden und anschliessend die Message entsprechend umformen muss. Ich habe folgenden Ansatz gewählt: Alle Messages landen in einer InfluxDB-Datenbank (in 2.0 ist dies ein Bucket), meine Räume werden zu Measurements, die Signalnamen zu Fields. Zusatzinformationen oder Differenzierungen (Gewerke, HM-Serial, Gerätetypen und -namen, etc.) kann man als Tags ablegen.

Das Mapping habe ich in Javascript in einer function Node programmiert. Für InfluxDB 1.8 und 2.0 gibt es unterschiedliche Versionen.

Hier der Source-Code für 1.x

pl=msg.payload;
msg.payload = [{
    },
    {
        'function': msg.function,
        'device': msg.device,
        'name': msg.deviceName.replace(/ /g, '\ '),
        'deviceType': msg.deviceType
    }
];

msg.payload[0][msg.datapoint]=pl;
msg.measurement=msg.room ? msg.room.replace(/ /g, '\\ ') : 'undefined';
return msg;

und 2.0:

var pl = {
    bucket: 'Homematic',
    precision: 's',
    data: [{
        measurement: msg.room ? msg.room.replace(/ /g, '\\ ') : 'undefined',
        tags: {
         'function': msg.function ? msg.function.replace(/ /g, '\\ ') : 'undefined',
         'device': msg.device,
         'name': msg.deviceName.replace(/ /g, '\\ '),
         'deviceType': msg.deviceType
        },
        fields: {},
        timestamp: Math.round(msg.ts / 1000)
    }]
}
pl.data[0]['fields'][msg.datapoint] = msg.payload;
msg.payload = pl;
return msg;

Die 2.0er Version enthält noch zwei Besonderheiten. Zum einen muss hier der Bucket angegeben werden (Zeile 2) in dem die Daten auf der InfluxDB gespeichert werden. Zum anderen habe ich als Timestamp-Genauigkeit Sekunden gewählt (Zeile 3), da dies hoffentlich etwas Speicherplatz in der Cloud spart. Daher muss in Zeile 13 der Message-Timestamp von Millisekunden nach Sekunden umgerechnet werden. Möchte man mit Millisekunden arbeiten, muss Zeile 3 zu precision: 'ms', und Zeile 13 zu timestamp: msg.ts geändert werden.

In einem zweiten Schritt forme ich noch alle Boolean-Werte von true/false nach 1/0 um, da ich mit Influx 1.x Probleme mit Booleans hatte. Unter 2.0 scheinen sie sauber zu funktionieren. Daher ist dafür keine Umformung notwendig.

Nur 1.x:

for (var prop in msg.payload[0]) {
    val = msg.payload[0][prop];
    if (typeof(val) === "boolean") {
        msg.payload[0][prop]=(val?1:0);
    }
}
return msg;

Jetzt ist die Node-Red-Message im richtigen Format und kann an Influx gesendet werden. Wiedereinmal muss man für die zwei Versionen unterschiedliche Blöcke verwenden. Für die ältere Version wird muss das node-red-contrib-influxdb Plugin installiert werden (über Hamburger-Menu -> Palette verwalten -> installieren) und für die 2.0er das node-red-contrib-stackhero-influxdb-v2 Plugin über den gleichen Weg.

Das Setup für 1.x ist straight-forward, hier gibt es eigentlich nichts zu erklären. Für das 2.0er gilt es zu beachten, dass der Host ohne Protokoll (also ohne "https://") angegeben wird. Man bekommt den Hostnamen über das Cloud-Interface -> Data -> Client Libraries. Den Token erhält man auch über das Cloud-Interface -> Data -> Tokens, dann auf den Bucket klicken und er wird in einem Popup angezeigt. Schlussendlich, die Organization ist bei mir gleich dem Loginnamen.

Jetzt ist alles fertig und der RedMatic-Flow sollte so aussehen:

Datenmengen und Kosten

Meine Haus-Installation besteht derzeit aus 98 Homematic-, Homematic-IP- und CUxD -Geräten. Daraus resultieren 530 Fields (Signale) in der InfluxDB. Da viel Signalnamen gleich sind, fasst Influx sie zusammen, so dass die Anzahl der Series nur 213 ist. Für ca. 13 Monate benötigt meine InfluxDB rund 100MB Plattenplatz (Version 1.8), also 7.7MB pro Monat. Beeindruckend wenig, finde ich.

Für InfluxDB 2.0 habe ich noch nicht so lange Daten. Allerdings kann man aus obigen Angaben hochrechnen. Mit der aufgezeichneten Usage aus dem Cloud-Interface ergibt sich folgendes Bild:

  • Writes: 0.5MB/h (Free Plan: 5MB/5 min = 60MB/h)
  • Queries: kann nicht ermittelt werden, ich war aber auch noch nie am Limit (Free Plan: 300MB/5 min)
  • Cardinality: 213 (Free Plan: 10'000)
  • Storage: 7.7MB/Monat (Free Plan: unbegrenzt - Allerdings beschränkung auf 30 Tage!)

Auch bei einer grossen Installation kommt man also mit dem Free Plan aus, sofern man mit den 30 Tagen Retention leben kann. Möchte man mehr, muss man auf den "Usage-Based Plan" umsteigen. Die Hochrechnung der Kosten (ohne Gewähr!) sieht folgendermassen aus:

  • Writes: 360MB/month * $0.0015/MB = $0.54/month
  • Queries: sehr abhängig davon, wie man die Daten verwendet und visualisiert und wie oft man sie anschaut. Ich brauche pro Tag rund 10s Query Time, daraus ergeben sich 10*30*$0.0015/s = $0.45/month
  • Cardinality: Limit bei 1'000'000, es ist schwer vorstellbar, dass man diesen Wert mit einer privaten Hausinstallation sprengt, im professionellen Bereich ist es aber durchaus möglich
  • Storage: Die Menge steigt konstant, daher auch die Kosten. Gerechnet für ein Jahr Retention ergibt sich ein Storage-Bedarf von rund 0.1GB, vorausgesetzt, InfluxDB 2.0 ist ähnlich effizient wie 1.x. Die Kosten für einen Monat errechnen sich dann so: 24h*30d*0.1GB*$0.0015 = $0.11

Man bekommt also für rund einen Euro pro Monat eine InfluxDB-Cloud-Instanz für eine große Homematic-Installation, bei der man sich praktisch um nichts kümmern muss. Ganz ordentlich, finde ich.

2022-07-05: Hier gibt es noch einen Nachtrag: Fix für fehlenden „room“ in den RPC Events