Node-RED系列(十二):定制化节点教程
Node-RED系列文章目前已经写了11篇,介绍了Node-RED的安装以及默认安装的一些基本节点的使用,作为物联网的一个可视化拖动的流程,Node-RED的确实很容易上手。还没开始学习的同学可以先看下我以前的文章
看了我的Node-RED系列文章后,很多同学都问我能不能出一篇详细的定制节点的教程,于是今天我抽点时间,将定制Node-RED的节点的相关教程整理一下,分享给大家,
如果大家还没有用过Node-RED不建议先看本篇文章,可以从第一篇看起,安装一个Node-RED玩玩。
好了下面让我们进入主题。
由于Node-RED是开源的,你可以在github找到项目的所有代码,所以我们有里有相信,我们可以基于Node-RED为原型,进行各种集成,开发。
比较简单的一种就是做一些的定制的节点来满足自己的日常需求。如果做的好,拿来卖钱也不是不可能的。
好了让我们言归正传。如何进行自定义节点?如何将自定义的节点发布,部署?
首先让我们了解下Node-RED的节点到底是什么?
我们从github上下载源码后,可以在这个模块找到Node-RED的默认安装的节点,
其中一个html
节点的代码
大致我们清楚了节点需要什么内容。
环境准备
要制作一个定制的节点
首先要准备这几个文件
- 定制节点的html 用于显示配置节点
- 定制节点的JavaScript 用于处理Node-RED流中的数据
- package.json文件(可选,如果需要npm安装才必须要)
下面我们来做一个简单的demo,来演示一下,如何定制一个node
定制节点的作用是将payload转化为小写。
首先我们创建一个文件夹 名字为node-red-contrib-example-lower-case
然后在其中创建二个文件
一个是lower-case.js
另一个是lower-case.html
文件lower-case.js
是将msg.payload
转化为消息,使用
js文件解析
lower-case.js
module.exports = function(RED) {
function LowerCaseNode(config) {
RED.nodes.createNode(this,config);
var node = this;
node.on('input', function(msg) {
msg.payload = msg.payload.toLowerCase();
node.send(msg);
});
}
RED.nodes.registerType("lower-case",LowerCaseNode);
}
下面详细讲解一下这段代码,首先使用module.exports
导出一个函数这个函数有一个参数, 定义为叫做RED
其实就是Node-RED的上下文。
然后其中定义一个方法叫做LowerCaseNode
这个方法就是将一个单纯的将payload转化的函数。
方法体内有一句
RED.nodes.createNode(this,config);
这一句是一个闭包,直接使用父作用域的RED参数,创建一个Node。 那么this是什么那? this就是上下文,就是flow。 config是该节点的配置项。
紧接着是一个事件监听
node.on('input', function(msg) {})
由于node是基于事件驱动,所以在flow的上下文中,都是用过一系列的监听和触发来进行传递上下文的.
每个节点中都会有这样一个监听函数 有的是这样写的
this.on("input", function(msg, send, done) {})
这里的this其实就是node。
toLowerCase()
将payload
转化,再次赋值给msg.payload
那么这个事件监听函数输出的是什么那,在最后一行给出了答案
node.send(msg);
将msg传递出去,向下流转。
还有最后一句代码
RED.nodes.registerType("lower-case",LowerCaseNode);
这行代码就是注册一个节点。 第一个参数是节点的名称,第二是一个函数。
这里还有一个inject节点的源码,大家可以看一下,相信稍微学过一些js的同学都能看懂
module.exports = function(RED) {
"use strict";
var cron = require("cron");
function InjectNode(n) {
RED.nodes.createNode(this,n);
/* Handle legacy */
if(!Array.isArray(n.props)){
n.props = [];
n.props.push({
p:'payload',
v:n.payload,
vt:n.payloadType
});
n.props.push({
p:'topic',
v:n.topic,
vt:'str'
});
} else {
for (var i=0,l=n.props.length; i<l; i++) {
if (n.props[i].p === 'payload' && !n.props[i].hasOwnProperty('v')) {
n.props[i].v = n.payload;
n.props[i].vt = n.payloadType;
} else if (n.props[i].p === 'topic' && n.props[i].vt === 'str' && !n.props[i].hasOwnProperty('v')) {
n.props[i].v = n.topic;
}
}
}
this.props = n.props;
this.repeat = n.repeat;
this.crontab = n.crontab;
this.once = n.once;
this.onceDelay = (n.onceDelay || 0.1) * 1000;
this.interval_id = null;
this.cronjob = null;
var node = this;
node.props.forEach(function (prop) {
if (prop.vt === "jsonata") {
try {
var val = prop.v ? prop.v : "";
prop.exp = RED.util.prepareJSONataExpression(val, node);
}
catch (err) {
node.error(RED._("inject.errors.invalid-expr", {error:err.message}));
prop.exp = null;
}
}
});
if (node.repeat > 2147483) {
node.error(RED._("inject.errors.toolong", this));
delete node.repeat;
}
node.repeaterSetup = function () {
if (this.repeat && !isNaN(this.repeat) && this.repeat > 0) {
this.repeat = this.repeat * 1000;
if (RED.settings.verbose) {
this.log(RED._("inject.repeat", this));
}
this.interval_id = setInterval(function() {
node.emit("input", {});
}, this.repeat);
} else if (this.crontab) {
if (RED.settings.verbose) {
this.log(RED._("inject.crontab", this));
}
this.cronjob = new cron.CronJob(this.crontab, function() { node.emit("input", {}); }, null, true);
}
};
if (this.once) {
this.onceTimeout = setTimeout( function() {
node.emit("input",{});
node.repeaterSetup();
}, this.onceDelay);
} else {
node.repeaterSetup();
}
this.on("input", function(msg, send, done) {
var errors = [];
this.props.forEach(p => {
var property = p.p;
var value = p.v ? p.v : '';
var valueType = p.vt ? p.vt : 'str';
if (!property) return;
if (valueType === "jsonata") {
if (p.exp) {
try {
var val = RED.util.evaluateJSONataExpression(p.exp, msg);
RED.util.setMessageProperty(msg, property, val, true);
}
catch (err) {
errors.push(err.message);
}
}
return;
}
try {
RED.util.setMessageProperty(msg,property,RED.util.evaluateNodeProperty(value, valueType, this, msg),true);
} catch (err) {
errors.push(err.toString());
}
});
if (errors.length) {
done(errors.join('; '));
} else {
send(msg);
done();
}
});
}
RED.nodes.registerType("inject",InjectNode);
InjectNode.prototype.close = function() {
if (this.onceTimeout) {
clearTimeout(this.onceTimeout);
}
if (this.interval_id != null) {
clearInterval(this.interval_id);
if (RED.settings.verbose) { this.log(RED._("inject.stopped")); }
} else if (this.cronjob != null) {
this.cronjob.stop();
if (RED.settings.verbose) { this.log(RED._("inject.stopped")); }
delete this.cronjob;
}
};
RED.httpAdmin.post("/inject/:id", RED.auth.needsPermission("inject.write"), function(req,res) {
var node = RED.nodes.getNode(req.params.id);
if (node != null) {
try {
node.receive();
res.sendStatus(200);
} catch(err) {
res.sendStatus(500);
node.error(RED._("inject.failed",{error:err.toString()}));
}
} else {
res.sendStatus(404);
}
});
}
html解析
lower-case.html
<script type="text/javascript">
RED.nodes.registerType('lower-case',{
category: 'function',
color: '#a6bbcf',
defaults: {
name: {value:""}
},
inputs:1,
outputs:1,
icon: "file.png",
label: function() {
return this.name||"lower-case";
}
});
</script>
<script type="text/html" data-template-name="lower-case">
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
</script>
<script type="text/html" data-help-name="lower-case">
<p>A simple node that converts the message payloads into all lower-case characters</p>
</script>
html的内容是用于配置节点以及节点的备注解释。
RED.nodes.registerType('lower-case',{ // 注册一个节点,当拖动节点到编辑区域中
category: 'function', // 节点归属于哪一个分类
color: '#a6bbcf', // 颜色
defaults: {
name: {value:""} // 输入框的值
},
inputs:1, // 能否输入 1是,0 否
outputs:1, // 能否输出 1是,0 否
icon: "file.png", // 节点的图标
label: function() {
return this.name||"lower-case"; // label 的默认值
}
});
标签<script type="text/html" data-template-name="lower-case">
中的内容是用于显示在节点抽屉中的,
点击节点即可以显示
标签<script type="text/html" data-help-name="lower-case">
中的内容是用于显示在帮助文档中的。
package.json
{
"name" : "node-red-contrib-example-lower-case",
"node-red" : {
"nodes": {
"lower-case": "lower-case.js"
}
}
}
如何安装改节点那
在node-red项目根目录中执行
npm install <location of node module>
如果是要在本地安装,linux下
cd ~/.node-red
npm install ~/dev/node-red-contrib-example-lower-case
windows下安装
cd C:\Users\my_name\.node_red
npm install C:\Users\my_name\Documents\GitHub\node-red-contrib-example-lower-case
- 分享
- 举报
-
浏览量:22842次2021-03-15 15:40:13
-
浏览量:26757次2021-01-25 17:57:21
-
浏览量:19266次2021-01-22 19:13:39
-
浏览量:34791次2021-02-08 11:42:45
-
浏览量:32689次2021-02-07 17:30:47
-
浏览量:15719次2021-02-08 15:04:50
-
浏览量:14162次2021-01-14 18:10:48
-
浏览量:18434次2021-01-06 19:08:06
-
浏览量:22847次2021-01-04 10:25:54
-
浏览量:30017次2021-01-05 15:11:35
-
浏览量:15210次2021-07-29 17:28:08
-
2021-04-28 15:04:42
-
浏览量:14181次2021-03-16 10:46:12
-
浏览量:13891次2021-03-24 16:14:07
-
浏览量:13006次2021-02-20 17:52:54
-
2021-04-12 20:00:58
-
浏览量:19015次2021-03-22 17:45:29
-
浏览量:25377次2020-12-31 14:58:17
-
浏览量:80878次2020-12-28 16:39:38
-
广告/SPAM
-
恶意灌水
-
违规内容
-
文不对题
-
重复发帖
这把我C
感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明