Zum Inhalt springen

Abonnieren von Topics mit dem MQTT-Collector

Der MQTT-Collector kann Nachrichten von verschiedenen (beliebig vielen) Topics abonnieren, verarbeiten und dann in die InfluxDB schreiben. Dazu dienen Zuordnungen („Mappings”). Jedes Mapping legt drei Dinge fest:

  • Wo kommt der Wert her, also welches Topic muss abonniert werden?
  • Welche Verarbeitung ist notwendig (Vorzeichen-Behandlung, Datentyp-Konvertierung, JSON-Extraktion, Formelbildung)?
  • Wohin in der InfluxDB soll der ermittelte Wert geschrieben werden (Measurement und Field)?

Jedes Mapping wird durch mehrere Umgebungsvariablen definiert, die mit dem Präfix MAPPING_X_ beginnen. X ist eine Zahl, und alle Variablen mit derselben Zahl gehören zum selben Mapping. Die Nummerierung beginnt bei 0 und läuft lückenlos weiter.

Pflicht sind nur MAPPING_X_TOPIC und MAPPING_X_TYPE. Dazu kommt das Ziel in der InfluxDB, und dafür gibt es zwei Varianten:

  • Der Normalfall: MAPPING_X_MEASUREMENT und MAPPING_X_FIELD. Dort landet der Wert, ob positiv oder negativ.
  • Die Vorzeichen-Aufteilung: MAPPING_X_MEASUREMENT_POSITIVE, MAPPING_X_MEASUREMENT_NEGATIVE, MAPPING_X_FIELD_POSITIVE und MAPPING_X_FIELD_NEGATIVE. Der Wert landet je nach Vorzeichen in einem von zwei Feldern, etwa Netzbezug und Einspeisung.

Das Topic, das der Collector abonniert. Mehrere Mappings dürfen dasselbe Topic verwenden, etwa um aus einem JSON-Payload mehrere Werte zu gewinnen.

Beispiel
MAPPING_0_TOPIC=senec/0/ENERGY/GUI_INVERTER_POWER

Der Datentyp des Feldes. Erlaubt sind integer, float, string und boolean. Jeder andere Wert lässt den Collector beim Start abbrechen.

Bei boolean gelten true, ok, yes, on und 1 als wahr, unabhängig von Groß- und Kleinschreibung. Jeder andere Wert wird zu false.

Beispiel
MAPPING_0_TYPE=float

Pflicht, solange das Mapping die Werte nicht nach Vorzeichen aufteilt. Der Name des InfluxDB-Measurements, in das der Wert geschrieben werden soll (unabhängig davon, ob er positiv oder negativ ist).

Beispiel
MAPPING_0_MEASUREMENT=PV

Pflicht, solange das Mapping die Werte nicht nach Vorzeichen aufteilt. Der Name des InfluxDB-Feldes, in das der Wert geschrieben werden soll (unabhängig davon, ob er positiv oder negativ ist).

Beispiel
MAPPING_0_FIELD=inverter_power

Pflicht, sobald das Mapping die Werte nach Vorzeichen aufteilt. Name des InfluxDB-Measurements, in das der Wert geschrieben werden soll, wenn er positiv ist. Andernfalls (also wenn er negativ oder 0 ist) wird 0 geschrieben.

Beispiel
MAPPING_1_MEASUREMENT_POSITIVE=PV

Pflicht, sobald das Mapping die Werte nach Vorzeichen aufteilt. Der Name des InfluxDB-Measurements, in das der (absolute) Wert geschrieben werden soll, wenn er negativ ist. Andernfalls (also wenn er positiv oder 0 ist) wird 0 geschrieben.

Beispiel
MAPPING_1_MEASUREMENT_NEGATIVE=PV

Pflicht, sobald das Mapping die Werte nach Vorzeichen aufteilt. Name des InfluxDB-Feldes, in das der Wert geschrieben werden soll, wenn er positiv ist. Andernfalls (also wenn er negativ oder 0 ist) wird 0 geschrieben.

Beispiel
MAPPING_1_FIELD_POSITIVE=grid_import_power

Pflicht, sobald das Mapping die Werte nach Vorzeichen aufteilt. Der Name des InfluxDB-Feldes, in das der (absolute) Wert geschrieben werden soll, wenn er negativ ist. Andernfalls (also wenn er positiv oder 0 ist) wird 0 geschrieben.

Beispiel
MAPPING_1_FIELD_NEGATIVE=grid_export_power

Der Schlüssel, aus dem der Wert extrahiert wird, falls das Topic einen JSON-Payload enthält (mit nicht verschachtelten Key/Value-Paaren). Ein Schlüssel ist immer ein String, z.B. inverter_power. Ohne die Variable verarbeitet der Collector den Payload als nackten Wert.

Beispiel
MAPPING_2_JSON_KEY=radiation_level

Der JSONPath, mit dem der Wert extrahiert wird, falls das Topic einen komplexen (z.B. verschachtelten) JSON-Payload enthält. Ein JSONPath beginnt immer mit $., z.B. $.example.foo.bar[2].

Sind JSON_PATH und JSON_KEY gleichzeitig gesetzt, gewinnt JSON_PATH. Der Collector meldet das nicht, deshalb gehört immer nur eines von beiden ins Mapping.

Beispiel
MAPPING_3_JSON_PATH=$.ccp[2]

Eine Formel, die aus einem JSON-Payload den zu speichernden Messwert berechnet. Sie darf einige mathematische Operationen enthalten, z.B. round({radiation_level} * 1.5).

Die geschweiften Klammern {} dienen dazu, Werte aus dem JSON-Payload zu referenzieren. Es können dabei einfache Schlüssel oder JSONPath verwendet werden. Die Formel wirkt nur, wenn weder JSON_KEY noch JSON_PATH gesetzt ist. Diese beiden haben Vorrang.

Beispiel
MAPPING_4_JSON_FORMULA=round({reactivity} * {radiation_level}) + 42

Eine Formel für Topics ohne JSON, also mit nacktem Wert. Verfügbar ab Version 0.5.0. Der empfangene Wert wird über den Platzhalter {value} referenziert, z.B. round({value} * 1000). Es gelten dieselben Operationen wie bei JSON_FORMULA.

Die Formel wirkt nur, wenn weder JSON_KEY noch JSON_PATH noch JSON_FORMULA gesetzt ist. Alle drei haben Vorrang.

Beispiel
MAPPING_4_FORMULA=round({value} * 1000)

Unterer Grenzwert für Messwerte, verfügbar ab Version 0.3.0. Wird ein Wert unterhalb dieses Grenzwerts empfangen, wird er ignoriert und nicht in die InfluxDB geschrieben. Damit lassen sich Ausreißer ausfiltern, die sonst die Statistik verfälschen. Ohne die Variable gibt es keine untere Grenze.

Der Grenzwert greift erst nach JSON-Extraktion und Formel, also auf dem Wert, der tatsächlich gespeichert würde.

Beispiel
MAPPING_0_MIN=5

Oberer Grenzwert für Messwerte, verfügbar ab Version 0.3.0. Wird ein Wert oberhalb dieses Grenzwerts empfangen, wird er ignoriert und nicht in die InfluxDB geschrieben. Ohne die Variable gibt es keine obere Grenze.

Beide Grenzwerte wirken nur bei den Typen float und integer. Bei string und boolean bleiben sie ohne Effekt.

Beispiel
MAPPING_0_MAX=15000

Wandelt einen Messwert von NULL in die Zahl 0 um und schreibt ihn nach InfluxDB. Verfügbar ab Version 0.7.0. Erlaubt sind true und false, jeder andere Wert lässt den Collector beim Start abbrechen. Standardwert ist false.

Bei false wird ein Messwert von NULL ignoriert, also nicht nach InfluxDB geschrieben. Das gilt auch, wenn zwar ein Payload ankommt, der konfigurierte JSON-Schlüssel darin aber fehlt.

Beispiel
MAPPING_3_NULL_TO_ZERO=true

Topic wird abonniert, der erhaltene Wert wird unverändert als Fließkommazahl in die InfluxDB geschrieben:

MAPPING_0_TOPIC=senec/0/ENERGY/GUI_INVERTER_POWER
MAPPING_0_MEASUREMENT=PV
MAPPING_0_FIELD=inverter_power
MAPPING_0_TYPE=float

Wenn die Werte des Topics positiv oder negativ sein können, erfolgt hier eine Aufteilung. Positive Werte werden in grid_import_power geschrieben, negative Werte in grid_export_power.

MAPPING_1_TOPIC=senec/0/ENERGY/GUI_GRID_POW
MAPPING_1_MEASUREMENT_POSITIVE=PV
MAPPING_1_MEASUREMENT_NEGATIVE=PV
MAPPING_1_FIELD_POSITIVE=grid_import_power
MAPPING_1_FIELD_NEGATIVE=grid_export_power
MAPPING_1_TYPE=float
  • Falls der empfangene Wert positiv ist (z.B. 1000): grid_import_power wird auf 1000 gesetzt, grid_export_power auf 0.
  • Falls der empfangene Wert negativ ist (z.B. -500): grid_import_power wird auf 0 gesetzt, grid_export_power auf 500.
  • Falls der empfangene Wert 0 ist: grid_import_power und grid_export_power werden beide auf 0 gesetzt.

Verwendung von JSON_KEY:

MAPPING_2_TOPIC=my/little/nuclear/plant
MAPPING_2_JSON_KEY=radiation_level
MAPPING_2_MEASUREMENT=nuclear_power_plant
MAPPING_2_FIELD=radiation_level
MAPPING_2_TYPE=float

Aus einem JSON von beispielsweise {"radiation_level": 90.5, "reactivity": 0.7} resultiert der Wert 90.5.

Verwendung von JSON_PATH:

MAPPING_3_TOPIC=go-e/ATTR
MAPPING_3_JSON_PATH=$.ccp[2]
MAPPING_3_MEASUREMENT=WALLBOX
MAPPING_3_FIELD=power
MAPPING_3_TYPE=float
MAPPING_3_NULL_TO_ZERO=true

Dies extrahiert den Wert aus einem Payload wie {"ccp": [1,2,42,3]}. Im Beispiel liefert das den Wert an Position 2 (drittes Element) des Arrays ccp, also 42.

Sollte der Wert null sein (z.B. bei {"ccp": [1,2,null,3]}), wird er als 0 geschrieben.

Es gibt zwei Möglichkeiten, eine Formel zu verwenden:

MAPPING_4_TOPIC=my/little/nuclear/plant
MAPPING_4_JSON_FORMULA="round({reactivity} * {radiation_level}) + 42"
MAPPING_4_MEASUREMENT=nuclear_power_plant
MAPPING_4_FIELD=danger_level
MAPPING_4_TYPE=float

Aus einem JSON von z.B. {"radiation_level": 90.5, "reactivity": 0.7} entsteht danger_level mit round(0.7 * 90.5) + 42, also 105.

MAPPING_4_TOPIC=my/little/nuclear/plant/powerInKwH
MAPPING_4_FORMULA="round({value} * 1000)"
MAPPING_4_MEASUREMENT=nuclear_power_plant
MAPPING_4_FIELD=power
MAPPING_4_TYPE=integer

Im Gegensatz zum JSON-Fall wird hier der Wert über {value} referenziert und die Variable heißt MAPPING_X_FORMULA.

Aus einem Payload von z.B. 42.5 entsteht power mit round(42.5 * 1000), also 42500.

MAPPING_0_TOPIC=senec/0/ENERGY/GUI_INVERTER_POWER
MAPPING_0_MEASUREMENT=PV
MAPPING_0_FIELD=inverter_power
MAPPING_0_TYPE=float
MAPPING_0_MIN=5
MAPPING_0_MAX=15000

Werte unter 5 oder über 15000 werden ignoriert und nicht in die InfluxDB geschrieben.