在 Whistle 中編寫指令碼
本指南提供撰寫剖析器 Whistle 指令碼的一般指引。如要進一步瞭解 Whistle 語法和可用函式,請參閱 Whistle 參考資料。
撰寫哨聲腳本
開始編寫 Whistle 指令碼前,建議您先:
瞭解剖析器訂閱的來源訊息類別中訊息的結構定義。 為避免對應失敗,導致訊息進入無效信件佇列,Whistle 指令碼必須能夠對應所有傳入訊息。如果訊息結構定義因訊息而異,Whistle 指令碼就必須處理這些差異。
瞭解來源訊息結構定義有助於掌握來源訊息中的欄位及其資料類型,進而決定如何將來源訊息中的欄位對應至目標類型結構定義。瞭解資料的語意也很重要,這樣才能有效決定來源訊息的哪些部分應對應至目標架構中的屬性。
舉例來說,瞭解屬性值變更的頻率,有助於判斷應將哪些資料對應為內嵌中繼資料,哪些資料應對應為雲端中繼資料。請參閱「建立來源訊息類別模型」和「建立資料模型」一節。
瞭解為剖析器定義的類型版本結構定義。剖析器中的 Whistle 指令碼會將來源訊息對應至為剖析器定義的類型版本結構定義。如要瞭解如何建構符合類型版本需求的 Proto 記錄,請查詢類型規格。請特別注意
data欄位的結構定義,以及任何中繼資料值區關聯。請特別注意是否有任何中繼資料儲存區關聯標示為required: true。如果您打算依值查詢中繼資料執行個體,請記下相關聯的 bucket 的結構定義。編寫 Whistle 指令碼。Whistle 指令碼會執行實際的來源到目標轉換作業。來源訊息會載入名為
$root的輸入內容。如要瞭解語言和可用函式,請參閱 Whistle 參考資料。另請參閱本節的其他指南,例如如何將記錄連結至中繼資料執行個體。
最佳做法
本節概述撰寫 Whistle 指令碼的最佳做法。
存取訊息屬性時執行空值檢查
建議您在存取訊息屬性時檢查空值,因為屬性可能未定義。
//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;
}
}
}
範例
以下各節列舉使用 Whistle 的基本作業範例。
簡單的 Whistle 對應
假設有下列來源訊息...
{
"sensor": "rotation-speed-sensor",
"machine": "m-234",
"timestamp": "1687973092857",
"value": 1200
}
以及下列 Whistle 指令碼:
package mde
[
{
tagName: $root.machine + " - " + $root.sensor;
data: {
numeric: $root.value;
};
timestamps: {
eventTimestamp: $root.timestamp;
}
}
]
剖析器會產生下列 proto 記錄輸出內容:
[
{
"tagName": "m-234-rotation-speed-sensor",
"data": {
"numeric": 1200
},
"timestamps": {
"eventTimestamp": "1687973092857"
}
}
]
使用函式進行簡單的 Whistle 對應
假設有下列來源訊息:
{
"sensor": "rotation-speed-sensor",
"machine": "m-234",
"timestamp": "1687973092857",
"value": 1200
}
以及下列 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;
}
剖析器會產生下列 proto 記錄輸出內容:
[
{
"tagName": "m-234-rotation-speed-sensor",
"data": {
"numeric": 1200
},
"timestamps": {
"eventTimestamp": "1687973092857"
}
}
]
從剖析器 1 發出多筆 proto 記錄
假設有下列來源訊息:
{
"tag": "plc-34",
"machine": "controller",
"timestamp": "1687973092857",
"values": [200, 499]
}
以及下列 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;
};
}
剖析器會產生下列 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"
}
}
]
從剖析器 2 發出多筆 proto 記錄
假設有下列來源訊息:
{
"machine": "controller",
"timestamp": "1687973092857",
"sensors": [
{
"tag": "plc-34",
"value": 200
},
{
"tag": "plc-35",
"value": 499
}
]
}
以及下列 Whistle 指令碼:
package mde
[$$
getProtoRecords($root.sensors[], $root)
]
def getProtoRecords(sensor, input) {
tagName: input.machine + "-" + sensor.tag;
data: {
numeric: sensor.value;
};
timestamps: {
eventTimestamp: input.timestamp;
};
}
剖析器會產生下列 proto 記錄輸出內容:
[
{
"tagName": "controller-plc-34",
"timestamps": {
"eventTimestamp": "1687973092857"
},
"data": {
"numeric": 200
}
},
{
"tagName": "controller-plc-35",
"timestamps": {
"eventTimestamp": "1687973092857"
},
"data": {
"numeric": 499
}
}
]