Skripts in Whistle schreiben

Dieser Leitfaden enthält allgemeine Informationen zum Schreiben eines Whistle-Skripts für einen Parser. Weitere Informationen zur Whistle-Syntax und zu den verfügbaren Funktionen finden Sie in der Whistle-Referenz.

Whistle-Scripts schreiben

Bevor Sie mit dem Schreiben eines Whistle-Skripts beginnen, sollten Sie Folgendes tun:

  1. Schema der Nachrichten in der Quellnachrichtenklasse verstehen, die vom Parser abonniert wird. Damit keine Zuordnungsfehler auftreten und Nachrichten nicht in der Dead-Letter-Warteschlange landen, muss das Whistle-Script alle eingehenden Nachrichten zuordnen können. Wenn sich Nachrichtenschemas von Nachricht zu Nachricht unterscheiden, muss Ihr Whistle-Script diese Unterschiede berücksichtigen.

    Wenn Sie das Quellnachrichtenschema kennen, wissen Sie, welche Felder in den Quellnachrichten vorhanden sind und welche Datentypen sie haben. So können Sie entscheiden, wie Sie Felder in den Quellnachrichten dem Zieltypschema zuordnen. Es ist auch wichtig, die Semantik der Daten zu verstehen, damit Sie effektiv entscheiden können, welche Teile der Quellnachricht Attributen im Zielschema zugeordnet werden sollen.

    Wenn Sie beispielsweise wissen, wie oft sich der Attributwert ändert, können Sie entscheiden, welche Daten als eingebettete Metadaten und welche als Cloud-Metadaten zugeordnet werden sollen. Weitere Informationen finden Sie in den Abschnitten Quellnachricht-Klassen modellieren und Daten modellieren.

  2. Schema der für den Parser definierten Typversion verstehen: Im Whistle-Script des Parsers werden Quellnachrichten dem Typversionsschema zugeordnet, das für den Parser definiert ist. Informationen dazu, wie Sie einen Proto-Datensatz erstellen, der den Anforderungen der Typversion entspricht, finden Sie in der Typspezifikation. Achten Sie insbesondere auf das Schema des Felds data sowie auf alle Zuordnungen von Metadaten-Buckets. Achten Sie besonders darauf, ob Metadaten-Bucket-Zuordnungen als required: true gekennzeichnet sind. Wenn Sie Metadateninstanzen nach Wert suchen möchten, sollten Sie sich die Schemas der zugehörigen Buckets notieren.

  3. Whistle-Script schreiben Das Whistle-Skript führt die eigentliche Transformation von der Quelle zum Ziel aus. Die Quellnachricht wird in eine Eingabe namens $root geladen. Eine Übersicht über die Sprache und die verfügbaren Funktionen finden Sie in der Whistle-Referenz. Weitere Informationen finden Sie in den anderen Anleitungen in diesem Abschnitt, z. B. Datensätze mit Metadateninstanzen verknüpfen.

Best Practices

In diesem Abschnitt werden die Best Practices für das Schreiben von Whistle-Scripts beschrieben.

Nullprüfungen beim Zugriff auf Nachrichteneigenschaften durchführen

Es wird empfohlen, beim Zugriff auf ein Nachrichtenattribut auf „null“ zu prüfen, wenn die Möglichkeit besteht, dass das Attribut nicht definiert ist.

//Add metadata from source bucket if metadata.source attribute is present
if(isNotNil(input.metadata) and isNotNil(input.metadata.source)) then {
{
    var metadataArray[]: {
        bucketReference: {
            bucketName: "source";
            version: 1;
        };
            naturalKey: input.metadata.source;
        }
    }
}

Beispiele

In den folgenden Abschnitten finden Sie einige Beispiele für grundlegende Vorgänge mit Whistle.

Einfache Whistle-Zuordnung

Angenommen, Sie haben die folgende Quellnachricht:

{
  "sensor": "rotation-speed-sensor",
  "machine": "m-234",
  "timestamp": "1687973092857",
  "value": 1200
}

Und das folgende Whistle-Skript:

package mde

[
    {
        tagName: $root.machine + " - " + $root.sensor;
        data: {
            numeric: $root.value;
        };
        timestamps: {
            eventTimestamp: $root.timestamp;
        }
    }
]

Der Parser gibt diesen Proto-Datensatz aus:

[
  {
    "tagName": "m-234-rotation-speed-sensor",
    "data": {
      "numeric": 1200
    },
    "timestamps": {
      "eventTimestamp": "1687973092857"
    }
  }
]

Einfache Whistle-Zuordnung mit Funktionen

Ausgangspunkt ist die folgende Quellnachricht:

{
  "sensor": "rotation-speed-sensor",
  "machine": "m-234",
  "timestamp": "1687973092857",
  "value": 1200
}

Und das folgende Whistle-Skript:

package mde

[
    {
        tagName: getTagName($root);
        data: getValue($root);
        timestamps: getTimestamp($root)
    }
]

def getTagName(input) {
    input.machine + "-" + input.sensor;
}

def getTimestamp(input) {
    eventTimestamp: input.timestamp;
}

def getValue(input) {
    numeric: input.value;
}

Der Parser gibt diesen Proto-Datensatz aus:

[
  {
    "tagName": "m-234-rotation-speed-sensor",
    "data": {
      "numeric": 1200
    },
    "timestamps": {
      "eventTimestamp": "1687973092857"
    }
  }
]

Mehrere Proto-Datensätze aus Parser 1 ausgeben

Ausgangspunkt ist die folgende Quellnachricht:

{
  "tag": "plc-34",
  "machine": "controller",
  "timestamp": "1687973092857",
  "values": [200, 499]
}

Und das folgende Whistle-Skript:

package mde

var valueLen: listLen($root.values);
var indexes: range(0, valueLen);

[
    getProtoRecords($root.values[], indexes[], $root)
]

def getProtoRecords(value, index, input) {
        tagName: input.machine + "-" + input.tag + "-" + index;
        data: {
            numeric: value;
        };
        timestamps: {
            eventTimestamp: input.timestamp;
        };
}

Der Parser gibt diesen Proto-Datensatz aus:

[
  {
    "tagName": "controller-plc-34-0",
    "data": {
      "value": 200.0
    },
    "timestamps": {
      "eventTimestamp": "1687973092857"
    }
  },
  {
    "tagName": "controller-plc-34-1",
    "data": {
      "value": 499.0
    },
    "timestamps": {
      "eventTimestamp": "1687973092857"
    }
  }
]

Mehrere Proto-Datensätze aus einem Parser 2 ausgeben

Ausgangspunkt ist die folgende Quellnachricht:

{
  "machine": "controller",
  "timestamp": "1687973092857",
  "sensors": [
    {
      "tag": "plc-34",
      "value": 200
    },
    {
      "tag": "plc-35",
      "value": 499
    }
  ]
}

Und das folgende Whistle-Skript:

package mde

[$$
    getProtoRecords($root.sensors[], $root)
]

def getProtoRecords(sensor, input) {
        tagName: input.machine + "-" + sensor.tag;
        data: {
            numeric: sensor.value;
        };
        timestamps: {
            eventTimestamp: input.timestamp;
        };
}

Der Parser gibt diesen Proto-Datensatz aus:

[
  {
    "tagName": "controller-plc-34",
    "timestamps": {
      "eventTimestamp": "1687973092857"
    },
    "data": {
      "numeric": 200
    }
  },
  {
    "tagName": "controller-plc-35",
    "timestamps": {
      "eventTimestamp": "1687973092857"
    },
    "data": {
      "numeric": 499
    }
  }
]