一、目錄
1. 實驗目的
掌握函數(shù)節(jié)點的使用
2. 知識要點
- 函數(shù)節(jié)點在 node-red 中表示一個 JavaScript 函數(shù)塊,用來處理節(jié)點接收到的消息。
- 這些消息作為一個名為 msg 的 JavaScript 對象傳入。
- 通常有一個 msg.payload 屬性,包含消息正文。
- 函數(shù)被期望返回一個 message 對象(或多個消息對象),但是可以選擇不返回任何東西以阻止流。
- 發(fā)送消息:函數(shù)既可以使用“return”向流中的下一個節(jié)點傳遞消息,也可以調用 node.send(messages)。它可以返回或是發(fā)送
一個單一的消息對象——傳遞給連接到第一個輸出的節(jié)點
一組消息對象——傳遞給連接到相應輸出的節(jié)點
如果數(shù)組的任何元素本身都是一組消息,那么多條消息就會被發(fā)送到相應的輸出。如果返回 null,無論是單獨還是作為數(shù)組的元素,都不會傳遞任何消息。要記錄任何信息或報告錯誤,可以使用以下功能:
node.log("Log message")
node.warn("Warning")
node.error("Error")
3. 實驗步驟
3.1 使用函數(shù)節(jié)點創(chuàng)建并返回多個信息
1. step1: 按照下圖組建流

1.實現(xiàn)
1.1 拖拽出四個節(jié)點。

2. step2: 修改其中的函數(shù)節(jié)點,使其具有兩個輸出口

2.實現(xiàn)
2.1 設置兩個輸出口

2.2 然后把節(jié)點連接起來

3. step3: 將以下代碼添加到函數(shù)節(jié)點

3.實現(xiàn)
3.1代碼添加到函數(shù)節(jié)點

代碼
var msg1 = {payload:"first out of output 1"};
var msg2 = {payload:"second out of output 1" };
var msg3 = {payload:"third out of output 1"} ;
var msg4 = { payload: "only message from output 2"} ;
return[[msg1, msg2, msg3],msg4] ;
4. step4: 部署,你在調試窗口看到了什么?
4.實現(xiàn)
4.1部署

4.2運行

5.實驗總結 第一個調試節(jié)點一口氣收到了 3 條消息,而第二個調試節(jié)點收到了一條消息,消息的內容跟剛剛輸入的代碼有關系,跟輸入的消息沒有任何關系,因為輸入的是時間戳。對比分析:
return msg ; //一 個 返 回 值
return [ [ msg1 , msg2 , msg3 ] , msg4 ] ; //一 組 返 回 值
3.2 通過判斷語句進行數(shù)據(jù)分類
Switch 控件可以進行數(shù)據(jù)的分流,它屬于功能控件。函數(shù)控件是功能控件里,功能最強的,它可以實現(xiàn)switch 控件的功能。
1. step1: 按下圖組裝組件

注意這里 inject 節(jié)點輸入的是數(shù)字而不是時間戳,分別為 100,10,1
實現(xiàn)
1.拖拽節(jié)點

2.設置參數(shù)

剩余2個,重復以上操作即可
2. step2: 修改函數(shù)節(jié)點使其有 3 個輸出口

實現(xiàn)
1.設置參數(shù),設置3 個輸出口

2.將所有的節(jié)點連接起來,如下圖

3. step3: 修改函數(shù)節(jié)點相關代碼,使其能夠進行分類判斷
if(msg.payload > 10)
{
return [msg, null, null];
} else if(msg.payload === 10)
{
return [null, msg, null];
} else
{
return [null, null, msg];
}
實現(xiàn)
1.設置代碼

4. step4: 部署并調試,查看調試窗口
實現(xiàn)

5. step5: 試一試,按照字符串分類也是可以的

如果要求當檢測到第一個字符串”apple”,讓數(shù)據(jù)輸出在第一個輸出口 OUT1,當檢測到第二個字符串”banana”,讓數(shù)據(jù)輸出在第一個輸出口 OUT2,當檢測到第三個字符串”orange”,讓數(shù)據(jù)輸出在第一個輸出口 OUT3。您該如何修改程序?
實現(xiàn)
1.拖拽節(jié)點

2.設置節(jié)點

其余2個節(jié)點重復以上操作。
-
設置另一個節(jié)點配置,以及代碼
- 設置代碼如下圖
if (msg.payload == "apple") {
return [msg, null, null];
} else if (msg.payload == "banana") {
return [null, msg, null];
} else if (msg.payload == "orange") {
return [null, null, msg];
}

再把所有節(jié)點連接起來,并部署,如下圖

3.3 單個數(shù)據(jù)計算
1. step1: 新建對象返回 拖入 inject 節(jié)點,并把輸入的內容改為數(shù)字;拖入 debug 節(jié)點用來觀察現(xiàn)象,拖入函數(shù)節(jié)點并做如下修改:
- 名稱設置為乘以 2
- 函數(shù)部分添加如下代碼:
var newMsg = {payload: msg.payload*2};
return newMsg;
其中,var newMsg = {payload: msg.payload * 2 } 語句的意思是,新建一個對象,名為 newMsg,它有 payload 屬性,并且 payload 的值為 msg.payload 的兩倍。最后返回的是 newMsg,也就是新建的這個對象。部署并運行,可以看到現(xiàn)象是,調試窗口顯示的數(shù)值是輸入的兩倍。說明函數(shù)節(jié)點的功能實現(xiàn)了。消息是通過 msg 對象傳過來的,可不可以不新建一個對象,直接修改 msg.payload 呢?
實現(xiàn)
1.拖入 inject 節(jié)點、并把輸入的內容改為數(shù)字

2.拖入 debug 節(jié)點用來觀察現(xiàn)象

3.拖入函數(shù)節(jié)點并做如下修改

4.部署并觀察數(shù)據(jù)變化

2. step2: 修改原有對象模式 將 step1 中的函數(shù)修改一下:
msg.payload = msg.payload*2;
return msg;
部署,可以發(fā)現(xiàn)結果一樣正確。
實現(xiàn)

1.部署與對比

3.4 使用數(shù)組進行數(shù)據(jù)截取與組裝
通常,在實際通信的時候不會只傳遞一個數(shù)組,信息的傳遞依賴于數(shù)組,數(shù)組中不同位置的數(shù)字也會有不同的含義,例如,第一個數(shù)字表示 ID,第二個數(shù)字表示數(shù)組長度,第三個數(shù)字表示溫度等等,一般會有一個通信協(xié)議來規(guī)定。所以,如何取出有用的數(shù)據(jù),或者按要求把數(shù)據(jù)進行組裝很重要?,F(xiàn)在,假如收到了一串數(shù)據(jù),數(shù)據(jù)共 16 位,我們只用到后 8 位,前邊的 8 位都不要了,如何來操作?
1. step1: 編輯 inject 節(jié)點 編輯 inject 節(jié)點使其輸入一組數(shù)組

實現(xiàn)
1.拖入節(jié)點,并連接

2.設置節(jié)點參數(shù)
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]

2. step2: function 節(jié)點接入 inject 節(jié)點實現(xiàn)數(shù)據(jù)截斷

var temp = new Buffer([0, 0, 0, 0, 0, 0, 0, 0]);
for( var i = 0; i < 8; i++)
temp[i] = msg.payload[i + 8];
msg.payload = temp;
return msg;
實現(xiàn)
1.設置函數(shù)節(jié)點參數(shù)

3. step3: 部署運行,查看截斷的效果
實現(xiàn)
1.效果

3.5 模擬溫度數(shù)值計算
由于通信方式的限制,數(shù)據(jù)在發(fā)送時,常常要轉換為 8 位的字符來發(fā)送。在數(shù)字電路里,只有高電平和低電平兩種情況,所以數(shù)據(jù)在發(fā)送時,就只能使用 1 和 0 個數(shù)字。這個 1 或 0,稱之為 1 位。通常,8 位可以傳輸一個字符。2 的 8 次方是 256,所以小于 256 的數(shù)字,可以用 8 位來傳輸。而大于或等于 256 的數(shù)字,就要分成 2 個 8 位傳輸了。另外,8 位的數(shù)據(jù)可以用兩個十六進制的數(shù)來表示,比如 0101 1010 可以表示為 0x5a,所以通常會用十六進制來表示通信協(xié)議中的數(shù)。
例如,我們現(xiàn)在想傳輸十進制的數(shù)字 14859,大于 256,所以要分包傳送。十進制轉化為二進制是0011 1010 0000 1011,在通過硬件發(fā)送數(shù)據(jù)時,如果不考慮校驗或者起始位以及高位還是地位在前,就只考慮數(shù)字的發(fā)送,那么總線上的電平可能是低低高高,高低高低,低低低低,高低高高。把這個數(shù)字寫成十六進制,是 0x3a 與 0x0b,或 0x3a0b,0x 用來表示這是個十六進制的數(shù)字。0x3049 可以通過這種方式換算成 10 進制:數(shù)字拆成單個字符來分析,a 到 f 的數(shù)對應 10 到 15,在第幾位上,就乘以幾個 16。0x3a0b =3×16×16×16 + 10×16×16 + 11=14859?;蛘咧苯邮褂?16 進制進行計算,0x3a0b=0x3a×256+0x0b
當然,通信協(xié)議是可以進行特殊的規(guī)定,例如表示 4 位的溫度,34.56°C,要通過十六進制的數(shù)字進行分包發(fā)送,就是 0Xd80/100。我們現(xiàn)在規(guī)定,十六進制的溫度高位 ×256+ 低位 = 溫度 ×100。接下來嘗試解析溫度的數(shù)據(jù)。
我們使用 inject 節(jié)點輸入數(shù)組 [0xd,0x80],由于 inject 節(jié)點里不支持直接輸入十六進制的數(shù)字,所以輸入 [13,128]。這兩個數(shù)組的值是一樣的。
1. step1: 使用 inject 節(jié)點模擬溫度數(shù)據(jù)輸入

實現(xiàn)
1.拖入節(jié)點,并連接

2.設置 inject 節(jié)點,參數(shù)

2. step2: 接入 function 節(jié)點并計算顯示的溫度數(shù)據(jù)值

實現(xiàn)
1.設置function 節(jié)點,參數(shù)代碼
var temp = (msg.payload[0] * 256 + msg.payload[1]) / 100;
msg.payload = temp;
return msg;

3. step3: 部署,運行,查看輸出

實現(xiàn)效果

全部代碼
[
{
"id": "2285f598968b299e",
"type": "tab",
"label": "流程 3",
"disabled": false,
"info": "",
"env": []
},
{
"id": "fa937b8668055899",
"type": "inject",
"z": "2285f598968b299e",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 110,
"y": 40,
"wires": [
[
"7bddb6dd44a1f495"
]
]
},
{
"id": "7bddb6dd44a1f495",
"type": "function",
"z": "2285f598968b299e",
"name": "function 2",
"func": "var msg1 = {payload:\"first out of output 1\"};\nvar msg2 = {payload:\"second out of output 1\" };\nvar msg3 = {payload:\"third out of output 1\"} ;\nvar msg4 = { payload: \"only message from output 2\"} ;\nreturn[[msg1, msg2, msg3],msg4] ;\n\n",
"outputs": 2,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 280,
"y": 40,
"wires": [
[
"65d5e74df22c54e2"
],
[
"b593fe3dbbd92174"
]
]
},
{
"id": "65d5e74df22c54e2",
"type": "debug",
"z": "2285f598968b299e",
"name": "debug 9",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 440,
"y": 20,
"wires": []
},
{
"id": "b593fe3dbbd92174",
"type": "debug",
"z": "2285f598968b299e",
"name": "debug 10",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 440,
"y": 60,
"wires": []
},
{
"id": "621d5293fa63f6e1",
"type": "function",
"z": "2285f598968b299e",
"name": "function 3",
"func": "if(msg.payload > 10)\n{\n return [msg, null, null];\n} else if(msg.payload === 10)\n{\n return [null, msg, null];\n} else\n{\n return [null, null, msg];\n}\n",
"outputs": 3,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 260,
"y": 260,
"wires": [
[
"4639173c87098450"
],
[
"ef253b64ec25fa55"
],
[
"fb9da972c119ccdb"
]
]
},
{
"id": "4639173c87098450",
"type": "debug",
"z": "2285f598968b299e",
"name": "debug 11",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 460,
"y": 180,
"wires": []
},
{
"id": "ef253b64ec25fa55",
"type": "debug",
"z": "2285f598968b299e",
"name": "debug 12",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 460,
"y": 260,
"wires": []
},
{
"id": "fb9da972c119ccdb",
"type": "debug",
"z": "2285f598968b299e",
"name": "debug 13",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 460,
"y": 320,
"wires": []
},
{
"id": "e833aa26a5885270",
"type": "inject",
"z": "2285f598968b299e",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "100",
"payloadType": "num",
"x": 110,
"y": 200,
"wires": [
[
"621d5293fa63f6e1"
]
]
},
{
"id": "8380dd33dda6db06",
"type": "inject",
"z": "2285f598968b299e",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "10",
"payloadType": "num",
"x": 110,
"y": 260,
"wires": [
[
"621d5293fa63f6e1"
]
]
},
{
"id": "367ebcc185265f41",
"type": "inject",
"z": "2285f598968b299e",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "1",
"payloadType": "num",
"x": 110,
"y": 300,
"wires": [
[
"621d5293fa63f6e1"
]
]
},
{
"id": "827ba21a6ff429fc",
"type": "inject",
"z": "2285f598968b299e",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "apple",
"payloadType": "str",
"x": 110,
"y": 440,
"wires": [
[
"e55b0d9c5e4a1dbf"
]
]
},
{
"id": "08ff10bdf4cef0df",
"type": "inject",
"z": "2285f598968b299e",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "banana",
"payloadType": "str",
"x": 110,
"y": 480,
"wires": [
[
"e55b0d9c5e4a1dbf"
]
]
},
{
"id": "05a89fc7b88cbf50",
"type": "inject",
"z": "2285f598968b299e",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "orange",
"payloadType": "str",
"x": 110,
"y": 540,
"wires": [
[
"e55b0d9c5e4a1dbf"
]
]
},
{
"id": "e55b0d9c5e4a1dbf",
"type": "function",
"z": "2285f598968b299e",
"name": "function 4",
"func": "if (msg.payload == \"apple\") {\n return [msg, null, null];\n} else if (msg.payload == \"banana\") {\n return [null, msg, null];\n} else if (msg.payload == \"orange\") {\n return [null, null, msg];\n}\n",
"outputs": 3,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 260,
"y": 480,
"wires": [
[
"761f58e1183ae2b9"
],
[
"5d93c6a18efeb657"
],
[
"565963cd11a03d53"
]
]
},
{
"id": "761f58e1183ae2b9",
"type": "debug",
"z": "2285f598968b299e",
"name": "debug 14",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 440,
"y": 440,
"wires": []
},
{
"id": "5d93c6a18efeb657",
"type": "debug",
"z": "2285f598968b299e",
"name": "debug 15",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 440,
"y": 480,
"wires": []
},
{
"id": "565963cd11a03d53",
"type": "debug",
"z": "2285f598968b299e",
"name": "debug 16",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 440,
"y": 540,
"wires": []
},
{
"id": "8b16f36974053654",
"type": "inject",
"z": "2285f598968b299e",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "10",
"payloadType": "num",
"x": 110,
"y": 660,
"wires": [
[
"a89933ec35aa53f2"
]
]
},
{
"id": "e480658147d8c7b7",
"type": "debug",
"z": "2285f598968b299e",
"name": "debug 17",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 440,
"y": 660,
"wires": []
},
{
"id": "a89933ec35aa53f2",
"type": "function",
"z": "2285f598968b299e",
"name": "function 5",
"func": "msg.payload = msg.payload*2;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 280,
"y": 660,
"wires": [
[
"e480658147d8c7b7"
]
]
},
{
"id": "f8e4cd626c04bcd5",
"type": "inject",
"z": "2285f598968b299e",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]",
"payloadType": "bin",
"x": 110,
"y": 760,
"wires": [
[
"85107ae0ccdbccf1"
]
]
},
{
"id": "85107ae0ccdbccf1",
"type": "function",
"z": "2285f598968b299e",
"name": "function 6",
"func": "var temp = new Buffer([0, 0, 0, 0, 0, 0, 0, 0]);\nfor( var i = 0; i < 8; i++)\ntemp[i] = msg.payload[i + 8];\nmsg.payload = temp;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 280,
"y": 760,
"wires": [
[
"dea8aaae03f6492d"
]
]
},
{
"id": "dea8aaae03f6492d",
"type": "debug",
"z": "2285f598968b299e",
"name": "debug 18",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 480,
"y": 780,
"wires": []
},
{
"id": "458cec50b66a1164",
"type": "inject",
"z": "2285f598968b299e",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "[13,128]",
"payloadType": "bin",
"x": 110,
"y": 920,
"wires": [
[
"c7cfb7dc54312a34"
]
]
},
{
"id": "c7cfb7dc54312a34",
"type": "function",
"z": "2285f598968b299e",
"name": "function 7",
"func": "var temp = (msg.payload[0] * 256 + msg.payload[1]) / 100;\nmsg.payload = temp;\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 280,
"y": 920,
"wires": [
[
"0a627ee0471128d2"
]
]
},
{
"id": "0a627ee0471128d2",
"type": "debug",
"z": "2285f598968b299e",
"name": "debug 19",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 480,
"y": 920,
"wires": []
}
]
