Cómo escribir secuencias de comandos en Whistle

En esta guía, se proporciona orientación general para escribir un script de Whistle para un analizador. Para obtener más información sobre la sintaxis de Whistle y las funciones disponibles, consulta la referencia de Whistle.

Redacción de guiones de silbidos

Antes de comenzar a escribir un guion de Whistle, te recomendamos que hagas lo siguiente:

  1. Comprende el esquema de los mensajes en la clase de mensajes fuente a la que se suscribe el analizador. Para evitar errores de asignación y, como resultado, que los mensajes lleguen a la cola de mensajes no entregados, la secuencia de comandos de Whistle debe poder asignar todos los mensajes entrantes. Si los esquemas de los mensajes difieren de un mensaje a otro, tu secuencia de comandos de Whistle debe controlar estas diferencias.

    Conocer el esquema del mensaje fuente te ayuda a comprender qué campos existen en los mensajes fuente y cuáles son sus tipos de datos, de modo que puedas decidir cómo asignar los campos de los mensajes fuente al esquema de tipo de destino. También es importante comprender la semántica de los datos para que puedas decidir de manera eficaz qué partes del mensaje fuente se deben asignar a los atributos del esquema de destino.

    Por ejemplo, conocer la frecuencia de cambio del valor del atributo te ayuda a decidir qué datos se deben asignar como metadatos incorporados en lugar de metadatos de la nube. Consulta las secciones sobre cómo modelar clases de mensajes fuente y cómo modelar datos.

  2. Comprende el esquema de la versión del tipo definida para el analizador. El script de Whistle en el analizador asigna mensajes fuente al esquema de versión de tipo que se define para el analizador. Para saber cómo construir un registro .proto que cumpla con los requisitos de la versión del tipo, debes consultar la especificación del tipo. En particular, debes tener en cuenta el esquema del campo data, así como las asociaciones de bucket de metadatos. Es especialmente importante tener en cuenta si alguna asociación de bucket de metadatos está marcada como required: true. Si planeas buscar instancias de metadatos por valor, debes tomar nota de los esquemas de los buckets asociados.

  3. Escribe el guion de Whistle. El script de Whistle realiza la transformación real de la fuente al destino. El mensaje fuente se carga en una entrada llamada $root. Consulta la referencia de Whistle para obtener una descripción general del lenguaje y las funciones disponibles. Además, consulta las otras guías de esta sección, como cómo vincular registros a instancias de metadatos.

Prácticas recomendadas

En esta sección, se describen las prácticas recomendadas para escribir secuencias de comandos de Whistle.

Realiza verificaciones de valores nulos cuando accedas a las propiedades del mensaje

Se recomienda verificar si hay valores nulos cuando se accede a una propiedad del mensaje, siempre que exista la posibilidad de que la propiedad no esté definida.

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

Ejemplos

En las siguientes secciones, se muestran algunos ejemplos de operaciones básicas con Whistle.

Asignación de Whistle simple

Dado el siguiente mensaje fuente…

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

Y la siguiente secuencia de comandos de Whistle:

package mde

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

El analizador producirá este registro proto como resultado:

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

Asignación de Whistle simple con funciones

Dado el siguiente mensaje fuente:

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

Y la siguiente secuencia de comandos de 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;
}

El analizador producirá este registro proto como resultado:

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

Emisión de varios registros de .proto desde un analizador 1

Dado el siguiente mensaje fuente:

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

Y la siguiente secuencia de comandos de 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;
        };
}

El analizador producirá este registro proto como resultado:

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

Emisión de varios registros de .proto desde un analizador 2

Dado el siguiente mensaje fuente:

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

Y la siguiente secuencia de comandos de Whistle:

package mde

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

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

El analizador producirá este registro proto como resultado:

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