Scrivere script in Whistle

Questa guida fornisce indicazioni generali sulla scrittura di uno script Whistle per un parser. Per saperne di più sulla sintassi di Whistle e sulle funzioni disponibili, consulta il riferimento di Whistle.

Scrittura di script per fischi

Prima di iniziare a scrivere uno script Whistle, ti consigliamo di:

  1. Comprendere lo schema dei messaggi nella classe di messaggi di origine a cui è iscritto il parser. Per evitare errori di mappatura e, di conseguenza, l'inserimento dei messaggi nella coda dei messaggi non recapitabili, lo script Whistle deve essere in grado di mappare tutti i messaggi in arrivo. Se gli schemi dei messaggi differiscono da messaggio a messaggio, lo script Whistle deve gestire queste differenze.

    Conoscere lo schema dei messaggi di origine ti aiuta a capire quali campi esistono nei messaggi di origine e quali sono i loro tipi di dati, in modo da poter decidere come mappare i campi nei messaggi di origine allo schema del tipo di destinazione. È anche importante comprendere la semantica dei dati, in modo da poter decidere in modo efficace quali parti del messaggio di origine devono essere mappate agli attributi nello schema di destinazione.

    Ad esempio, conoscere la frequenza di modifica del valore dell'attributo ti aiuta a decidere quali dati devono essere mappati come metadati incorporati e quali come metadati cloud. Consulta le sezioni sulla modellazione delle classi di messaggi di origine e sulla modellazione dei dati.

  2. Comprendere lo schema della versione del tipo definita per il parser. Lo script Whistle nel parser mappa i messaggi di origine allo schema della versione del tipo definito per il parser. Per sapere come creare un record proto che soddisfi i requisiti della versione del tipo, devi cercare la specifica del tipo. In particolare, devi prendere nota dello schema del campo data e di eventuali associazioni di bucket di metadati. È particolarmente importante notare se le associazioni dei bucket di metadati sono contrassegnate come required: true. Se prevedi di cercare istanze di metadati in base al valore, devi prendere nota degli schemi dei bucket associati.

  3. Scrivi lo script di Whistle. Lo script Whistle esegue la trasformazione dall'origine alla destinazione. Il messaggio di origine viene caricato in un input denominato $root. Consulta il riferimento di Whistle per una panoramica della lingua e delle funzioni disponibili. Consulta anche le altre guide in questa sezione, ad esempio come collegare i record alle istanze di metadati.

Best practice

Questa sezione descrive le best practice per la scrittura di script Whistle.

Esegui controlli null quando accedi alle proprietà del messaggio

È consigliabile verificare la presenza di valori null quando si accede a una proprietà del messaggio, ogni volta che esiste la possibilità che la proprietà non sia definita.

//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;
        }
    }
}

Esempi

Le sezioni seguenti mostrano alcuni esempi di operazioni di base che utilizzano Whistle.

Mappatura Whistle semplice

Dato il seguente messaggio di origine…

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

E il seguente script di Whistle:

package mde

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

Il parser produrrà questo output del record proto:

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

Mappatura semplice di Whistle utilizzando le funzioni

Dato il seguente messaggio di origine:

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

E il seguente script di Whistle:

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;
}

Il parser produrrà questo output del record proto:

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

Emissione di più record proto da un parser 1

Dato il seguente messaggio di origine:

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

E il seguente script di Whistle:

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;
        };
}

Il parser produrrà questo output del record proto:

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

Emissione di diversi record proto da un parser 2

Dato il seguente messaggio di origine:

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

E il seguente script di Whistle:

package mde

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

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

Il parser produrrà questo output del record proto:

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