1. Develop Tool
- Nodejs
- Git
2. Code
-
拉代碼
git clone https://github.com/node-red/node-red.git -
啟動
cd node-rednpm installnpm run buildnpm start -
訪問服務
http://127.0.0.1:1880
3. Develop
3.1 Create File
| 序号 | 文件 | 说明 |
|---|---|---|
| 1 | package.json | package.json文件是一个标准的用于描述NodeJs模块的文件,用于将其打包为一个npm模块 |
| 2 | lower-case.js | 用于定义节点的功能 |
| 3 | lower-case.html | 用于定义节点的属性、编辑对话窗口和帮助内容 |
3.1.1 package.json
- 進入開發的node目錄下面,我的叫demo
cd xxxx/NODE-RED/packages/node_modules/@node-red/nodes/core/demo
npm init
- 如果開發多個節點
{
"name" : "node-red-contrib-example-lower-case",
...
"node-red" : {
"nodes": {
"lower-case": "lower-case.js",
"demo": "demo.js"
}
}
}
3.1.2 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);
}
3.1.3 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.svg",
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>
3.1.4 Install && run
1.安裝node
npm install E:\xxxx\NodeRed\node-red\packages\node_modules\@node-red\nodes\core\demo
2.啟動
npm run dev
3.2 Document
3.2.1 Status
this.status({fill:"red",shape:"ring",text:"disconnected"});
this.status({fill:"green",shape:"dot",text:"connected"});
3.2.2 ICON
只修改前面的就行,不用把png修改
3.2.3 Label
從左側工具欄拉下來後,顯示的名字
3.2.4 Node Name
修改下面兩處
- js中需要註冊的頁面和Function
- html中需要註冊的頁面,label,以及頁面的name
3.2.5 Node Attribute
- category: (string) 节点出现的调色板类别
- defaults: (object) 节点的可编辑属性。
- credentials: (object) 节点的凭证属性。
- inputs: (number) 节点有多少输入,要么0要么1。
- outputs: (number) 节点有多少个输出。可以0或更多。
- color: (string) 要使用的背景颜色。
- paletteLabel: (string|function)调色板中使用的标签。
- label: (string|function) 在工作区中使用的标签。
- labelStyle: (string|function)应用于标签的样式。
- inputLabels: (string|function)在悬停时添加到节点输入端口的可选标签。
- outputLabels: (string|function)在悬停时添加到节点输出端口的可选标签。
- icon:(字符串)要使用的图标。
- align:(字符串)图标和标签的对齐方式。
- button: (object)在节点的边缘添加一个按钮。
- oneditprepare: (函数)在构建编辑对话框时调用。
- oneditsave: (函数)在编辑对话框正常时调用。
- oneditcancel: (函数)在取消编辑对话框时调用。
- oneditdelete: (函数)在配置节点的编辑对话框中的删除按钮被按下时调用。
- oneditresize: (函数)在调整编辑对话框大小时调用。
- onpaletteadd: (函数)在将节点类型添加到调色板时调用。
- onpaletteremove: (函数)从调色板中删除节点类型时调用。
3.2.6 Object Attribute
節點中對象的屬性
- value:(任何类型)属性采用的默认值
- required: (boolean)可选属性是否是必需的。如果设置为 true,则如果其值为 null 或空字符串,则该属性将无效。
- validate: (function) optional可用于验证属性值的函数。
- type: (string)可选,如果此属性是指向 配置节点的指针,则它标识节点的类型。
<script type="text/javascript">
RED.nodes.registerType('Nolan',{
category: 'function',
color: '#a6bbcf',
defaults: {
name: {value:"",required:true},
prefix: {value:"Demo_"}
},
credentials: {
username: {type:"text"},
password: {type:"password"}
},
inputs:1,
outputs:1,
icon: "cog.png",
label: function() {
return this.name||"Nolan";
}
});
</script>
<script type="text/x-red" data-template-name="Nolan">
<style>
.title-form{
margin: 10px auto;
}
</style>
<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>
<div class="title-form"><b>Show:</b></div>
<div class="form-row">
<label for="node-input-prefis"><i class="fa fa-tag"></i> Prefix</label>
<input type="text" id="node-input-prefix">
</div>
<div class="title-form"><b>Login:</b> </div>
<div class="form-row">
<label for="node-input-username"><i class="fa fa-tag"></i> Username</label>
<input type="text" id="node-input-username">
</div>
<div class="form-row">
<label for="node-input-password"><i class="fa fa-tag"></i> Password</label>
<input type="password" id="node-input-password">
</div>
</script>
輸入值得校驗
3.2.7 Custom Edit Action
- oneditprepare在显示对话框之前立即调用。常用
- oneditsave当编辑对话框被确定时被调用。
- oneditcancel在取消编辑对话框时调用。
- oneditdelete当按下配置节点的编辑对话框中的删除按钮时调用。
- oneditresize在调整编辑对话框的大小时调用。
3.3 Credentials
Node節點中輸入用戶名和密碼
1.html文件
<script type="text/javascript">
RED.nodes.registerType('Nolan',{
category: 'function',
color: '#a6bbcf',
defaults: {
name: {value:"",required:true},
prefix: {value:"Demo_"}
},
credentials: {
username: {type:"text"},
password: {type:"password"}
},
inputs:1,
outputs:1,
icon: "cog.png",
label: function() {
return this.name||"Nolan";
}
});
</script>
<script type="text/x-red" data-template-name="Nolan">
<style>
.title-form{
margin: 10px auto;
}
</style>
<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>
<div class="title-form"><b>Show:</b></div>
<div class="form-row">
<label for="node-input-prefis"><i class="fa fa-tag"></i> Prefix</label>
<input type="text" id="node-input-prefix">
</div>
<div class="title-form"><b>Login:</b> </div>
<div class="form-row">
<label for="node-input-username"><i class="fa fa-tag"></i> Username</label>
<input type="text" id="node-input-username">
</div>
<div class="form-row">
<label for="node-input-password"><i class="fa fa-tag"></i> Password</label>
<input type="password" id="node-input-password">
</div>
</script>
<script type="text/x-red" data-help-name="Nolan">
<p>A simple node that converts the message payloads into all lower-case characters</p>
<p>Some useful help text to introduce the node.</p>
<h3>Outputs</h3>
<dl class="message-properties">
<dt>payload
<span class="property-type">string | buffer</span>
</dt>
<h3>Details</h3>
<p>Some more information about the node.</p>
</script>
2.js文件
module.exports = function(RED) {
function LowerCaseNode(config) {
RED.nodes.createNode(this,config);
var node = this;
var username001 = this.credentials.username;
var password001 = this.credentials.password;
var prefix = config.prefix;
//通过input接收上游节点的消息
this.on('input', function(msg) {
msg.payload = msg.payload.toLowerCase();
node.send(msg);
var params = [];
params.push({"prefix":prefix,"username":username001,"password":password001});
var json = JSON.stringify(params);
var msg1 = { payload:json}
this.send(msg1);
this.status({fill:"green",shape:"dot",text:"connected"});
});
}
RED.nodes.registerType("Nolan",LowerCaseNode,{
credentials: {
username: {type:"text"},
password: {type:"password"}
}
});
}
3.4 Button
3.5 API
| RED | API entry point returned by require('node-red'); |
| .init(server,settings) | Initialises Node-RED |
| .start() | Start Node-RED |
| .stop() | Stop Node-RED |
| .version() | Returns the version |
| .httpAdmin | The admin express application |
| .httpNode | The node express application |
| .server | The http server instance |
| RED.auth | Authentication middleware |
| .needsPermission(permission) | Middleware used to ensure a user has a specific permission |
| RED.comms | |
| .publish(msg) | Send a message to the editor |
| RED.library | |
| .register(type) | Register a type to the library |
| RED.log | Logging services |
| .addHandler(func) | Add a log handler |
| .log(msg) | Log a message |
| .info(msg) | Log an info-level message |
| .warn(msg) | Log a warning-level message |
| .error(msg) | Log an error-level message |
| .trace(msg) | Log a trace-level message |
| .debug(msg) | Log a debug-level message |
| .metric() | Check if metrics are enabled in the runtime |
| .audit(msg,req) | Log an audit event |
| ._(msg,options) | Lookup NLS message |
| RED.nodes | Core runtime api |
| .getType(type) | Get a type definition |
| .getNode(id) | Get a node configuration |
| .eachNode(callback) | Iterate over all ndoes |
| .installModule(module) | Install a new node module |
| .uninstallModule(module) | Remove a node module |
| .enableNode(id) | Enable a node set |
| .disableNode(id) | Disabled a node set |
| .getNodeInfo(id) | Get a node set’s information |
| .getNodeList() | Get the list of all available nodes |
| .getModuleInfo(id) | Get a node module’s information |
| .getNodeConfigs() | Get the HTML configurations of all active node sets |
| .getNodeConfig(id) | Get the HTML configuration of a specific node set |
| .loadFlows() | Load the active flow configuration |
| .startFlows() | Start the active flow configuration |
| .stopFlows() | Stop the active flow configuration |
| .setFlows(flows,type) | Set the active flow configuration |
| .getFlows() | Get the active flow configuration |
| .addFlow(flow) | Add a new flow to the active configuration |
| .getFlow(id) | Get a flow within the active configuration |
| .updateFlow(id,flow) | Update an existing flow in the active configuration |
| .removeFlow(id) | Remove a flow from the active configuration |
| .addCredentials(id,credentials) | Add a credentials entry for a node |
| .getCredentials(id) | Get the credentials entry for a node |
| .deleteCredentials(id) | Remove the credentials entry for a node |
| RED.settings | Runtime settings |
| .available() | Check if settings are available |
| .get(key) | Get a setting value |
| .set(key,value) | Set a value in settings |
| RED.util | Common utilities |
| .cloneMessage(msg) | Clone a message object |
| .compareObjects(objA,objB) | Compare two javascript objects |
| .ensureBuffer(value) | Ensure a value is a Buffer type |
| .ensureString(value) | Ensure a value is a String type |
| .evaluateNodeProperty(value,type,node,msg) | Evaluate a typed node property |
| .generateId() | Generate a new id value |
| .getMessageProperty(msg,expr) | Get a message property |
| .setMessageProperty(msg,prop,value,createMissing) | Set a message property |
- RED.init(server,settings)
- RED.start()
- RED.stop()
- RED.version()
- RED.httpAdmin
- RED.httpNode
- RED.server
- RED.auth.needsPermission(permission)
- RED.comms.publish(msg)
- RED.library.register(type)
- RED.log.addHandler(func)
- RED.log.log(msg)
- RED.log.info(msg)
- RED.log.warn(msg)
- RED.log.error(msg)
- RED.log.trace(msg)
- RED.log.debug(msg)
- RED.log.metric()
- RED.log.audit(msg,req)
- RED.log._(msg,options)
- RED.nodes.getType(type)
- RED.nodes.getNode(id)
- RED.nodes.eachNode(callback)
- RED.nodes.installModule(module)
- RED.nodes.uninstallModule(module)
- RED.nodes.enableNode(id)
- RED.nodes.disableNode(id)
- RED.nodes.getNodeInfo(id)
- RED.nodes.getNodeList()
- RED.nodes.getModuleInfo(id)
- RED.nodes.getNodeConfigs()
- RED.nodes.getNodeConfig(id)
- RED.nodes.loadFlows()
- RED.nodes.startFlows()
- RED.nodes.stopFlows()
- RED.nodes.setFlows(flows,type)
- RED.nodes.getFlows()
- RED.nodes.addFlow(flow)
- RED.nodes.getFlow(id)
- RED.nodes.updateFlow(id,flow)
- RED.nodes.removeFlow(id)
- RED.nodes.addCredentials(id,credentials)
- RED.nodes.getCredentials(id)
- RED.nodes.deleteCredentials(id)
- RED.settings.available()
- RED.settings.get(key)
- RED.settings.set(key,value)
- RED.util.cloneMessage(msg)
- RED.util.compareObjects(objA,objB)
- RED.util.ensureBuffer(value)
- RED.util.ensureString(value)
- RED.util.evaluateNodeProperty(value,type,node,msg)
- RED.util.generateId()
- RED.util.getMessageProperty(msg,expr)
- RED.util.setMessageProperty(msg,prop,value,createMissing)
3.6 Html
3.6.1 Disabled or Readonly
<input type="text" name="name" value="sss" disabled>
<input type="text" name="name" value="sss" readonly>
3.6.2 Json Convert
var jsonStr = '{"userName": "Nolan","userAge": 26,"isMale": true}';
var json = JSON.parse(jsonStr);
var str = JSON.stringify(json);
3.6.3 Click Event
<button type="submit" id="btn">btn</button>
第一种:
$("#btn").click(function(event){})
第二种:
document.getElementById('#btn').addEventListener('click', function(){});
第三种:
$('#btn').bind('click', function();
第四种:
$("btn").on("click",function(){});
<button type="submit" id="btn" onclick="btn()">btn</button>
function btn(){}
3.7 JSON
JSON.parse
JSON.parse() 用来解析JSON字符串,得到对应的JavaScript值或对象
語法: JSON.parse(text[, reviver])
JSON.parse('5', function (key, value) {
console.log(`key:${key}, value:${value}`)
})
// key:, value:5
JSON.parse('null', function (key, value) {
console.log(`key:${key}, value:${value}`)
})
// key:, value:null
JSON.parse('{}', function (key, value) {
console.log(`key:${key}, value:`, value)
})
// key:, value:{}
JSON.parse('[1, 2]', function (key, value) {
console.log(`key:${key}, value:`, value)
})
JSON.stringify
JSON.stringify() 将一个JavaScript对象或值转换为JSON格式字符串。
語法: JSON.stringify(value[, replacer [, space]])
- value:将要序列化成 一个JSON字符串的JavaScript对象或值。
- replacer 可选,用于处理将要序列化的值。
- space 可选,指定缩进用的空白字符串,用于美化输出。
const obj = {
json: 'JSON',
parse: 'PARSE',
stringify: 'STRINGIFY'
}
JSON.stringify(obj, ['parse', 'stringify'])
// '{"parse":"PARSE","stringify":"STRINGIFY"}'
JSON.stringify({ json: 1, stringify: { val: 'rr'} }, (key, value) => {
console.log(`key:${key},value:`, value)
return value
})
// key:,value: {json: 1, stringify: {…}}
// key:json,value: 1
// key:stringify,value: {val: 'rr'}
// key:val,value: rr
// '{"json":1,"stringify":{"val":"rr"}}'
JSON.stringify({ json: 1, stringify: 'rr' }, (key, value) => {
if (typeof value === 'number') {
return 'ss'
}
return value
})
// '{"json":"ss","stringify":"rr"}'
JSON.stringify({ json: 1, stringify: 'rr' }, (key, value) => {
if (typeof value === 'number') {
value = undefined
}
return value
})
// '{"stringify":"rr"}'
測試
// 定义一个JSON对象
var person = {
"name": "张三",
"age": 20,
"gender": "男",
"address": { "city": "北京", "street": "朝阳区" },
"hobbies": ["篮球", "游泳", "音乐"]
};
// 使用JSON.stringify方法将JSON对象转换为JSON字符串
var personJsonString = JSON.stringify(person);
// 输出JSON字符串
console.log(personJsonString);
// 使用JSON.parse方法将JSON字符串转换为JSON对象
var personJson = JSON.parse(personJsonString);
// 输出JSON对象
console.log(personJson);
3.8 Context
Context scope levels:
- Node - only visible to the node that set the value
- Flow - visible to all nodes on the same flow (or tab in the editor)
- Global - visible to all nodes
JS中如何使用的語法
3.8.1 Settings.js
啟動的時候,查看控制台log
3.8.2 synchronous or asynchronous
synchronous
var count = context.get('count')||0;
count += 1;
context.set('count',count);
msg.count = count;
return msg;
var values = flow.get(["count", "colour", "temperature"]);
flow.set(["count", "colour", "temperature"], [123, "red", "12.5"]);
asynchronous
// Get single value
flow.get("count", function(err, myCount) { ... });
// Get multiple values
flow.get(["count", "colour"], function(err, count, colour) { ... })
// Set single value
flow.set("count", 123, function(err) { ... })
// Set multiple values
flow.set(["count", "colour"], [123, "red"], function(err) { ... })
context.get('count', function(err, count) {
if (err) {
node.error(err, msg);
} else {
// initialise the counter to 0 if it doesn't exist already
count = count || 0;
count += 1;
// store the value back
context.set('count',count, function(err) {
if (err) {
node.error(err, msg);
} else {
// make it part of the outgoing msg object
msg.count = count;
// send the message
node.send(msg);
}
});
}
});
3.8.3 FunctionGlobalContext
4. Error
4.1 [object Object]
JSON.stringify(payload, (key, value) => {
console.log(value)
});