一、目录
1. 实验目的
掌握函数节点的使用
2. 知识要点
- 函数节点在 node-red 中表示一个 JavaScript 函数块,用来处理节点接收到的消息。
- 这些消息作为一个名为 msg 的 JavaScript 对象传入。
- 通常有一个 msg.payload 属性,包含消息正文。
- 函数被期望返回一个 message 对象(或多个消息对象),但是可以选择不返回任何东西以阻止流。
- 发送消息:函数既可以使用“return”向流中的下一个节点传递消息,也可以调用 node.send(messages)。它可以返回或是发送
一个单一的消息对象——传递给连接到第一个输出的节点
一组消息对象——传递给连接到相应输出的节点
如果数组的任何元素本身都是一组消息,那么多条消息就会被发送到相应的输出。如果返回 null,无论是单独还是作为数组的元素,都不会传递任何消息。要记录任何信息或报告错误,可以使用以下功能:
node.log("Log message")
node.warn("Warning")
node.error("Error")
3. 实验步骤
3.1 使用函数节点创建并返回多个信息
1. step1: 按照下图组建流
1.实现
1.1 拖拽出四个节点。
2. step2: 修改其中的函数节点,使其具有两个输出口
2.实现
2.1 设置两个输出口
2.2 然后把节点连接起来
3. step3: 将以下代码添加到函数节点
3.实现
3.1代码添加到函数节点
代码
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.实现
4.1部署
4.2运行
5.实验总结 第一个调试节点一口气收到了 3 条消息,而第二个调试节点收到了一条消息,消息的内容跟刚刚输入的代码有关系,跟输入的消息没有任何关系,因为输入的是时间戳。对比分析:
return msg ; //一 个 返 回 值
return [ [ msg1 , msg2 , msg3 ] , msg4 ] ; //一 组 返 回 值
3.2 通过判断语句进行数据分类
Switch 控件可以进行数据的分流,它属于功能控件。函数控件是功能控件里,功能最强的,它可以实现switch 控件的功能。
1. step1: 按下图组装组件
注意这里 inject 节点输入的是数字而不是时间戳,分别为 100,10,1
实现
1.拖拽节点
2.设置参数
剩余2个,重复以上操作即可
2. step2: 修改函数节点使其有 3 个输出口
实现
1.设置参数,设置3 个输出口
2.将所有的节点连接起来,如下图
3. step3: 修改函数节点相关代码,使其能够进行分类判断
if(msg.payload > 10)
{
return [msg, null, null];
} else if(msg.payload === 10)
{
return [null, msg, null];
} else
{
return [null, null, msg];
}
实现
1.设置代码
4. step4: 部署并调试,查看调试窗口
实现
5. step5: 试一试,按照字符串分类也是可以的
如果要求当检测到第一个字符串”apple”,让数据输出在第一个输出口 OUT1,当检测到第二个字符串”banana”,让数据输出在第一个输出口 OUT2,当检测到第三个字符串”orange”,让数据输出在第一个输出口 OUT3。您该如何修改程序?
实现
1.拖拽节点
2.设置节点
其余2个节点重复以上操作。
-
设置另一个节点配置,以及代码
- 设置代码如下图
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];
}
再把所有节点连接起来,并部署,如下图
3.3 单个数据计算
1. step1: 新建对象返回 拖入 inject 节点,并把输入的内容改为数字;拖入 debug 节点用来观察现象,拖入函数节点并做如下修改:
- 名称设置为乘以 2
- 函数部分添加如下代码:
var newMsg = {payload: msg.payload*2};
return newMsg;
其中,var newMsg = {payload: msg.payload * 2 } 语句的意思是,新建一个对象,名为 newMsg,它有 payload 属性,并且 payload 的值为 msg.payload 的两倍。最后返回的是 newMsg,也就是新建的这个对象。部署并运行,可以看到现象是,调试窗口显示的数值是输入的两倍。说明函数节点的功能实现了。消息是通过 msg 对象传过来的,可不可以不新建一个对象,直接修改 msg.payload 呢?
实现
1.拖入 inject 节点、并把输入的内容改为数字
2.拖入 debug 节点用来观察现象
3.拖入函数节点并做如下修改
4.部署并观察数据变化
2. step2: 修改原有对象模式 将 step1 中的函数修改一下:
msg.payload = msg.payload*2;
return msg;
部署,可以发现结果一样正确。
实现
1.部署与对比
3.4 使用数组进行数据截取与组装
通常,在实际通信的时候不会只传递一个数组,信息的传递依赖于数组,数组中不同位置的数字也会有不同的含义,例如,第一个数字表示 ID,第二个数字表示数组长度,第三个数字表示温度等等,一般会有一个通信协议来规定。所以,如何取出有用的数据,或者按要求把数据进行组装很重要。现在,假如收到了一串数据,数据共 16 位,我们只用到后 8 位,前边的 8 位都不要了,如何来操作?
1. step1: 编辑 inject 节点 编辑 inject 节点使其输入一组数组
实现
1.拖入节点,并连接
2.设置节点参数
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
2. step2: function 节点接入 inject 节点实现数据截断
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;
实现
1.设置函数节点参数
3. step3: 部署运行,查看截断的效果
实现
1.效果
3.5 模拟温度数值计算
由于通信方式的限制,数据在发送时,常常要转换为 8 位的字符来发送。在数字电路里,只有高电平和低电平两种情况,所以数据在发送时,就只能使用 1 和 0 个数字。这个 1 或 0,称之为 1 位。通常,8 位可以传输一个字符。2 的 8 次方是 256,所以小于 256 的数字,可以用 8 位来传输。而大于或等于 256 的数字,就要分成 2 个 8 位传输了。另外,8 位的数据可以用两个十六进制的数来表示,比如 0101 1010 可以表示为 0x5a,所以通常会用十六进制来表示通信协议中的数。
例如,我们现在想传输十进制的数字 14859,大于 256,所以要分包传送。十进制转化为二进制是0011 1010 0000 1011,在通过硬件发送数据时,如果不考虑校验或者起始位以及高位还是地位在前,就只考虑数字的发送,那么总线上的电平可能是低低高高,高低高低,低低低低,高低高高。把这个数字写成十六进制,是 0x3a 与 0x0b,或 0x3a0b,0x 用来表示这是个十六进制的数字。0x3049 可以通过这种方式换算成 10 进制:数字拆成单个字符来分析,a 到 f 的数对应 10 到 15,在第几位上,就乘以几个 16。0x3a0b =3×16×16×16 + 10×16×16 + 11=14859。或者直接使用 16 进制进行计算,0x3a0b=0x3a×256+0x0b
当然,通信协议是可以进行特殊的规定,例如表示 4 位的温度,34.56°C,要通过十六进制的数字进行分包发送,就是 0Xd80/100。我们现在规定,十六进制的温度高位 ×256+ 低位 = 温度 ×100。接下来尝试解析温度的数据。
我们使用 inject 节点输入数组 [0xd,0x80],由于 inject 节点里不支持直接输入十六进制的数字,所以输入 [13,128]。这两个数组的值是一样的。
1. step1: 使用 inject 节点模拟温度数据输入
实现
1.拖入节点,并连接
2.设置 inject 节点,参数
2. step2: 接入 function 节点并计算显示的温度数据值
实现
1.设置function 节点,参数代码
var temp = (msg.payload[0] * 256 + msg.payload[1]) / 100;
msg.payload = temp;
return msg;
3. step3: 部署,运行,查看输出
实现效果
全部代码
[
{
"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": []
}
]