mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Compare commits
50 Commits
0.18.4
...
runnable-p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c256e27a83 | ||
|
|
3f41036919 | ||
|
|
95753ce5cd | ||
|
|
1906818c87 | ||
|
|
02765f8aad | ||
|
|
89f1dedf20 | ||
|
|
7a8906535e | ||
|
|
499d22daca | ||
|
|
838c7a5e89 | ||
|
|
89bfc90f40 | ||
|
|
acad9f57f9 | ||
|
|
0d08dc410e | ||
|
|
ebb3fb96cd | ||
|
|
f31f23ff07 | ||
|
|
8b0e76dd55 | ||
|
|
884618adfe | ||
|
|
98f7271ac8 | ||
|
|
087cd121b8 | ||
|
|
2d52527fb4 | ||
|
|
fe289e62b5 | ||
|
|
2845475e3f | ||
|
|
b307492487 | ||
|
|
d48284f7ea | ||
|
|
7e416797e9 | ||
|
|
5d54ca7477 | ||
|
|
b979b4e61a | ||
|
|
2527f7984a | ||
|
|
d9350b2362 | ||
|
|
bd0b903f1a | ||
|
|
f243c0df19 | ||
|
|
7482978953 | ||
|
|
77966689d4 | ||
|
|
cf43939d65 | ||
|
|
391ac4b351 | ||
|
|
e1e48aadd9 | ||
|
|
0681f206c4 | ||
|
|
d257c6f3d3 | ||
|
|
fa45c82cdc | ||
|
|
e805b58da6 | ||
|
|
943976d207 | ||
|
|
3a2e5a6ccd | ||
|
|
35ef036246 | ||
|
|
e09c3bbdd3 | ||
|
|
3b12076d4b | ||
|
|
cfcf78ae28 | ||
|
|
341ff9bf5c | ||
|
|
4ebb5d099e | ||
|
|
1e82b66bf0 | ||
|
|
06a5e4273b | ||
|
|
e123e7b0b0 |
@@ -229,10 +229,12 @@ RED.history = (function() {
|
||||
}
|
||||
});
|
||||
}
|
||||
RED.editor.validateNode(ev.node);
|
||||
RED.nodes.filterNodes({type:"subflow:"+ev.node.id}).forEach(function(n) {
|
||||
n.inputs = ev.node.in.length;
|
||||
n.outputs = ev.node.out.length;
|
||||
RED.editor.updateNodeProperties(n);
|
||||
RED.editor.validateNode(n);
|
||||
});
|
||||
} else {
|
||||
var outputMap;
|
||||
|
||||
@@ -355,7 +355,7 @@ RED.nodes = (function() {
|
||||
RED.nodes.registerType("subflow:"+sf.id, {
|
||||
defaults:{name:{value:""}},
|
||||
info: sf.info,
|
||||
icon:"subflow.png",
|
||||
icon: function() { return sf.icon||"subflow.png" },
|
||||
category: "subflows",
|
||||
inputs: sf.in.length,
|
||||
outputs: sf.out.length,
|
||||
@@ -550,7 +550,11 @@ RED.nodes = (function() {
|
||||
if (node.out.length > 0 && n.outputLabels && !/^\s*$/.test(n.outputLabels.join(""))) {
|
||||
node.outputLabels = n.outputLabels.slice();
|
||||
}
|
||||
|
||||
if (n.icon) {
|
||||
if (n.icon !== "node-red/subflow.png") {
|
||||
node.icon = n.icon;
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -116,7 +116,9 @@
|
||||
this.options.types = this.options.types||Object.keys(allOptions);
|
||||
|
||||
this.selectTrigger = $('<button tabindex="0"></button>').prependTo(this.uiSelect);
|
||||
$('<i class="fa fa-sort-desc"></i>').appendTo(this.selectTrigger);
|
||||
if (this.options.types.length > 1) {
|
||||
$('<i class="fa fa-sort-desc"></i>').appendTo(this.selectTrigger);
|
||||
}
|
||||
this.selectLabel = $('<span></span>').appendTo(this.selectTrigger);
|
||||
|
||||
this.types(this.options.types);
|
||||
|
||||
@@ -408,9 +408,12 @@ RED.deploy = (function() {
|
||||
delete confNode.credentials;
|
||||
}
|
||||
});
|
||||
RED.nodes.eachSubflow(function(subflow) {
|
||||
subflow.changed = false;
|
||||
});
|
||||
RED.nodes.eachWorkspace(function(ws) {
|
||||
ws.changed = false;
|
||||
})
|
||||
});
|
||||
// Once deployed, cannot undo back to a clean state
|
||||
RED.history.markAllDirty();
|
||||
RED.view.redraw();
|
||||
|
||||
@@ -48,7 +48,7 @@ RED.editor = (function() {
|
||||
isValid = validateNode(subflow);
|
||||
hasChanged = subflow.changed;
|
||||
}
|
||||
node.valid = isValid;
|
||||
node.valid = isValid && validateNodeProperties(node, node._def.defaults, node);
|
||||
node.changed = node.changed || hasChanged;
|
||||
} else if (node._def) {
|
||||
node.valid = validateNodeProperties(node, node._def.defaults, node);
|
||||
@@ -170,6 +170,10 @@ RED.editor = (function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
validateIcon(node);
|
||||
}
|
||||
|
||||
function validateIcon(node) {
|
||||
if (node._def.hasOwnProperty("defaults") && !node._def.defaults.hasOwnProperty("icon") && node.icon) {
|
||||
var iconPath = RED.utils.separateIconPath(node.icon);
|
||||
var iconSets = RED.nodes.getIconSets();
|
||||
@@ -188,6 +192,7 @@ RED.editor = (function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function validateNodeEditorProperty(node,defaults,property,prefix) {
|
||||
var input = $("#"+prefix+"-"+property);
|
||||
if (input.length > 0) {
|
||||
@@ -742,7 +747,7 @@ RED.editor = (function() {
|
||||
buildLabelRow().appendTo(outputsDiv);
|
||||
}
|
||||
|
||||
if ((!node._def.defaults || !node._def.defaults.hasOwnProperty("icon")) && node.type !== "subflow") {
|
||||
if ((!node._def.defaults || !node._def.defaults.hasOwnProperty("icon"))) {
|
||||
$('<div class="form-row"><div id="node-settings-icon"></div></div>').appendTo(dialogForm);
|
||||
var iconDiv = $("#node-settings-icon");
|
||||
$('<label data-i18n="editor.settingIcon">').appendTo(iconDiv);
|
||||
@@ -816,9 +821,51 @@ RED.editor = (function() {
|
||||
});
|
||||
}
|
||||
selectIconFile.prop("disabled", !iconFileList);
|
||||
selectIconFile.removeClass("input-error");
|
||||
selectIconModule.removeClass("input-error");
|
||||
}
|
||||
|
||||
function updateLabels(editing_node, changes, outputMap) {
|
||||
var inputLabels = $("#node-label-form-inputs").children().find("input");
|
||||
var outputLabels = $("#node-label-form-outputs").children().find("input");
|
||||
|
||||
var hasNonBlankLabel = false;
|
||||
var changed = false;
|
||||
var newValue = inputLabels.map(function() {
|
||||
var v = $(this).val();
|
||||
hasNonBlankLabel = hasNonBlankLabel || v!== "";
|
||||
return v;
|
||||
}).toArray().slice(0,editing_node.inputs);
|
||||
if ((editing_node.inputLabels === undefined && hasNonBlankLabel) ||
|
||||
(editing_node.inputLabels !== undefined && JSON.stringify(newValue) !== JSON.stringify(editing_node.inputLabels))) {
|
||||
changes.inputLabels = editing_node.inputLabels;
|
||||
editing_node.inputLabels = newValue;
|
||||
changed = true;
|
||||
}
|
||||
hasNonBlankLabel = false;
|
||||
newValue = new Array(editing_node.outputs);
|
||||
outputLabels.each(function() {
|
||||
var index = $(this).attr('id').substring(23); // node-label-form-output-<index>
|
||||
if (outputMap && outputMap.hasOwnProperty(index)) {
|
||||
index = parseInt(outputMap[index]);
|
||||
if (index === -1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
var v = $(this).val();
|
||||
hasNonBlankLabel = hasNonBlankLabel || v!== "";
|
||||
newValue[index] = v;
|
||||
});
|
||||
|
||||
if ((editing_node.outputLabels === undefined && hasNonBlankLabel) ||
|
||||
(editing_node.outputLabels !== undefined && JSON.stringify(newValue) !== JSON.stringify(editing_node.outputLabels))) {
|
||||
changes.outputLabels = editing_node.outputLabels;
|
||||
editing_node.outputLabels = newValue;
|
||||
changed = true;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
function showEditDialog(node) {
|
||||
var editing_node = node;
|
||||
var isDefaultIcon;
|
||||
@@ -1034,40 +1081,7 @@ RED.editor = (function() {
|
||||
// }
|
||||
var removedLinks = updateNodeProperties(editing_node,outputMap);
|
||||
|
||||
var inputLabels = $("#node-label-form-inputs").children().find("input");
|
||||
var outputLabels = $("#node-label-form-outputs").children().find("input");
|
||||
|
||||
var hasNonBlankLabel = false;
|
||||
newValue = inputLabels.map(function() {
|
||||
var v = $(this).val();
|
||||
hasNonBlankLabel = hasNonBlankLabel || v!== "";
|
||||
return v;
|
||||
}).toArray().slice(0,editing_node.inputs);
|
||||
if ((editing_node.inputLabels === undefined && hasNonBlankLabel) ||
|
||||
(editing_node.inputLabels !== undefined && JSON.stringify(newValue) !== JSON.stringify(editing_node.inputLabels))) {
|
||||
changes.inputLabels = editing_node.inputLabels;
|
||||
editing_node.inputLabels = newValue;
|
||||
changed = true;
|
||||
}
|
||||
hasNonBlankLabel = false;
|
||||
newValue = new Array(editing_node.outputs);
|
||||
outputLabels.each(function() {
|
||||
var index = $(this).attr('id').substring(23); // node-label-form-output-<index>
|
||||
if (outputMap && outputMap.hasOwnProperty(index)) {
|
||||
index = parseInt(outputMap[index]);
|
||||
if (index === -1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
var v = $(this).val();
|
||||
hasNonBlankLabel = hasNonBlankLabel || v!== "";
|
||||
newValue[index] = v;
|
||||
})
|
||||
|
||||
if ((editing_node.outputLabels === undefined && hasNonBlankLabel) ||
|
||||
(editing_node.outputLabels !== undefined && JSON.stringify(newValue) !== JSON.stringify(editing_node.outputLabels))) {
|
||||
changes.outputLabels = editing_node.outputLabels;
|
||||
editing_node.outputLabels = newValue;
|
||||
if (updateLabels(editing_node, changes, outputMap)) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
@@ -1675,25 +1689,25 @@ RED.editor = (function() {
|
||||
editing_node.info = newDescription;
|
||||
changed = true;
|
||||
}
|
||||
var inputLabels = $("#node-label-form-inputs").children().find("input");
|
||||
var outputLabels = $("#node-label-form-outputs").children().find("input");
|
||||
|
||||
var newValue = inputLabels.map(function() { return $(this).val();}).toArray().slice(0,editing_node.inputs);
|
||||
if (JSON.stringify(newValue) !== JSON.stringify(editing_node.inputLabels)) {
|
||||
changes.inputLabels = editing_node.inputLabels;
|
||||
editing_node.inputLabels = newValue;
|
||||
if (updateLabels(editing_node, changes, null)) {
|
||||
changed = true;
|
||||
}
|
||||
newValue = outputLabels.map(function() { return $(this).val();}).toArray().slice(0,editing_node.outputs);
|
||||
if (JSON.stringify(newValue) !== JSON.stringify(editing_node.outputLabels)) {
|
||||
changes.outputLabels = editing_node.outputLabels;
|
||||
editing_node.outputLabels = newValue;
|
||||
var iconModule = $("#node-settings-icon-module-hidden").val();
|
||||
var iconFile = $("#node-settings-icon-file-hidden").val();
|
||||
var icon = (iconModule && iconFile) ? iconModule+"/"+iconFile : "";
|
||||
if ((editing_node.icon === undefined && icon !== "node-red/subflow.png") ||
|
||||
(editing_node.icon !== undefined && editing_node.icon !== icon)) {
|
||||
changes.icon = editing_node.icon;
|
||||
editing_node.icon = icon;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
RED.palette.refresh();
|
||||
|
||||
if (changed) {
|
||||
var wasChanged = editing_node.changed;
|
||||
editing_node.changed = true;
|
||||
validateNode(editing_node);
|
||||
var subflowInstances = [];
|
||||
RED.nodes.eachNode(function(n) {
|
||||
if (n.type == "subflow:"+editing_node.id) {
|
||||
@@ -1704,10 +1718,9 @@ RED.editor = (function() {
|
||||
n.changed = true;
|
||||
n.dirty = true;
|
||||
updateNodeProperties(n);
|
||||
validateNode(n);
|
||||
}
|
||||
});
|
||||
var wasChanged = editing_node.changed;
|
||||
editing_node.changed = true;
|
||||
RED.nodes.dirty(true);
|
||||
var historyEvent = {
|
||||
t:'edit',
|
||||
@@ -1786,6 +1799,7 @@ RED.editor = (function() {
|
||||
$("#subflow-dialog-user-count").html(RED._("subflow.subflowInstances", {count:userCount})).show();
|
||||
|
||||
buildLabelForm(portLabels.content,subflow);
|
||||
validateIcon(subflow);
|
||||
trayBody.i18n();
|
||||
},
|
||||
close: function() {
|
||||
|
||||
@@ -116,6 +116,12 @@ RED.palette = (function() {
|
||||
el.data('popover').setContent(popOverContent);
|
||||
}
|
||||
|
||||
function setIcon(element,sf) {
|
||||
var iconElement = element.find(".palette_icon");
|
||||
var icon_url = RED.utils.getNodeIcon(sf._def,sf);
|
||||
iconElement.attr("style", "background-image: url("+icon_url+")");
|
||||
}
|
||||
|
||||
function escapeNodeType(nt) {
|
||||
return nt.replace(" ","_").replace(".","_").replace(":","_");
|
||||
}
|
||||
@@ -375,6 +381,7 @@ RED.palette = (function() {
|
||||
portOutput.remove();
|
||||
}
|
||||
setLabel(sf.type+":"+sf.id,paletteNode,sf.name,marked(sf.info||""));
|
||||
setIcon(paletteNode,sf);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -352,6 +352,7 @@ RED.projects.settings = (function() {
|
||||
}
|
||||
},{dependencies:dependencies});
|
||||
}
|
||||
|
||||
function editDependencies(activeProject,depsJSON,container,depsList) {
|
||||
var json = depsJSON||JSON.stringify(activeProject.dependencies||{},"",4);
|
||||
if (json === "{}") {
|
||||
@@ -380,6 +381,7 @@ RED.projects.settings = (function() {
|
||||
|
||||
function createDependenciesPane(activeProject) {
|
||||
var pane = $('<div id="project-settings-tab-deps" class="project-settings-tab-pane node-help"></div>');
|
||||
var nrDepButton;
|
||||
if (RED.user.hasPermission("projects.write")) {
|
||||
$('<button class="editor-button editor-button-small" style="margin-top:10px;float: right;">edit</button>')
|
||||
.appendTo(pane)
|
||||
@@ -387,6 +389,16 @@ RED.projects.settings = (function() {
|
||||
evt.preventDefault();
|
||||
editDependencies(activeProject,null,pane,depsList)
|
||||
});
|
||||
|
||||
nrDepButton = $('<button class="editor-button editor-button-small" style="margin-top:10px;">add Node-RED core</button>')
|
||||
.appendTo(pane)
|
||||
.click(function(evt) {
|
||||
evt.preventDefault();
|
||||
activeProject.dependencies["node-red"] = "~"+RED.settings.version;
|
||||
updateProjectDependencies(activeProject,depsList);
|
||||
$(this).hide();
|
||||
});
|
||||
if (activeProject.dependencies.hasOwnProperty("node-red")) { nrDepButton.hide(); }
|
||||
}
|
||||
var depsList = $("<ol>",{style:"position: absolute;top: 60px;bottom: 20px;left: 20px;right: 20px;"}).appendTo(pane);
|
||||
depsList.editableList({
|
||||
@@ -473,6 +485,7 @@ RED.projects.settings = (function() {
|
||||
evt.preventDefault();
|
||||
var deps = $.extend(true, {}, activeProject.dependencies);
|
||||
delete deps[entry.id];
|
||||
if (entry.id === "node-red") { nrDepButton.show(); }
|
||||
saveDependencies(depsList,row,deps,function(err) {
|
||||
if (!err) {
|
||||
row.fadeOut(200,function() {
|
||||
@@ -519,7 +532,6 @@ RED.projects.settings = (function() {
|
||||
|
||||
updateProjectDependencies(activeProject,depsList);
|
||||
return pane;
|
||||
|
||||
}
|
||||
|
||||
function showProjectFileListing(row,activeProject,current,filter,done) {
|
||||
|
||||
@@ -708,7 +708,9 @@ RED.utils = (function() {
|
||||
|
||||
function getDefaultNodeIcon(def,node) {
|
||||
var icon_url;
|
||||
if (typeof def.icon === "function") {
|
||||
if (node && node.type === "subflow") {
|
||||
icon_url = "node-red/subflow.png";
|
||||
} else if (typeof def.icon === "function") {
|
||||
try {
|
||||
icon_url = def.icon.call(node);
|
||||
} catch(err) {
|
||||
@@ -731,6 +733,16 @@ RED.utils = (function() {
|
||||
return iconPath;
|
||||
}
|
||||
|
||||
function isIconExists(iconPath) {
|
||||
var iconSets = RED.nodes.getIconSets();
|
||||
var iconFileList = iconSets[iconPath.module];
|
||||
if (iconFileList && iconFileList.indexOf(iconPath.file) !== -1) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function getNodeIcon(def,node) {
|
||||
if (def.category === 'config') {
|
||||
return "icons/node-red/cog.png"
|
||||
@@ -738,18 +750,19 @@ RED.utils = (function() {
|
||||
return "icons/node-red/subflow.png"
|
||||
} else if (node && node.type === 'unknown') {
|
||||
return "icons/node-red/alert.png"
|
||||
} else if (node && node.type === 'subflow') {
|
||||
return "icons/node-red/subflow.png"
|
||||
} else if (node && node.icon) {
|
||||
var iconPath = separateIconPath(node.icon);
|
||||
var iconSets = RED.nodes.getIconSets();
|
||||
var iconFileList = iconSets[iconPath.module];
|
||||
if (iconFileList && iconFileList.indexOf(iconPath.file) !== -1) {
|
||||
if (isIconExists(iconPath)) {
|
||||
return "icons/" + node.icon;
|
||||
}
|
||||
}
|
||||
|
||||
var iconPath = getDefaultNodeIcon(def, node);
|
||||
if (def.category === 'subflows') {
|
||||
if (!isIconExists(iconPath)) {
|
||||
return "icons/node-red/subflow.png";
|
||||
}
|
||||
}
|
||||
return "icons/"+iconPath.module+"/"+iconPath.file;
|
||||
}
|
||||
|
||||
|
||||
@@ -490,6 +490,7 @@ RED.view = (function() {
|
||||
}
|
||||
} else {
|
||||
var subflow = RED.nodes.subflow(m[1]);
|
||||
nn.name = "";
|
||||
nn.inputs = subflow.in.length;
|
||||
nn.outputs = subflow.out.length;
|
||||
}
|
||||
|
||||
@@ -113,8 +113,8 @@
|
||||
|
||||
.debug-message-meta {
|
||||
background: #fff;
|
||||
font-size: 10px;
|
||||
color: #777;
|
||||
font-size: 11px;
|
||||
color: #707070;
|
||||
}
|
||||
.debug-message-date {
|
||||
padding: 1px 5px 1px 1px;
|
||||
@@ -125,7 +125,7 @@
|
||||
}
|
||||
.debug-message-name {
|
||||
padding: 1px 5px;
|
||||
color: #777;
|
||||
color: #707070;
|
||||
}
|
||||
.debug-message-tools {
|
||||
position: absolute;
|
||||
@@ -159,7 +159,7 @@
|
||||
.debug-message-element {
|
||||
color: #333;
|
||||
font-family: Menlo, monospace;
|
||||
font-size: 12px !important;
|
||||
font-size: 13px !important;
|
||||
line-height: 1.3em;
|
||||
}
|
||||
.debug-message-object-key {
|
||||
@@ -188,11 +188,9 @@
|
||||
.debug-message-element.collapsed>span>.debug-message-object-handle {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
.debug-message-object-entry.collapsed > .debug-message-object-entry {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.debug-message-element.collapsed .debug-message-object-entry {
|
||||
display:none;
|
||||
}
|
||||
@@ -202,14 +200,13 @@
|
||||
.debug-message-element.collapsed .debug-message-buffer-opts {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.debug-message-element.collapsed .debug-message-object-type-header {
|
||||
display:none;
|
||||
}
|
||||
.debug-message-object-entry pre {
|
||||
font-family: Menlo, monospace;
|
||||
font-size: 12px;
|
||||
line-height: 1.4em;
|
||||
font-size: 13px;
|
||||
line-height: 1.2em;
|
||||
margin: 0 0 0 -1em;
|
||||
}
|
||||
|
||||
|
||||
@@ -64,9 +64,10 @@
|
||||
vertical-align: middle;
|
||||
color: #555;
|
||||
i {
|
||||
position:relative;
|
||||
top:-3px;
|
||||
margin-right:4px;
|
||||
position: relative;
|
||||
top: -3px;
|
||||
margin-left: 1px;
|
||||
margin-right: 2px;
|
||||
margin-top: 1px;
|
||||
vertical-align: middle;
|
||||
&.fa-ellipsis-h {
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
icon: "arrow-in.png",
|
||||
align: "right",
|
||||
label: function() {
|
||||
return this.name||this.command;
|
||||
return this.name||this.command||(this.useSpawn=="true"?this._("exec.spawn"):this._("exec.exec"));
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
|
||||
@@ -65,6 +65,8 @@ module.exports = function(RED) {
|
||||
"log:__node__.log,"+
|
||||
"error:__node__.error,"+
|
||||
"warn:__node__.warn,"+
|
||||
"debug:__node__.debug,"+
|
||||
"trace:__node__.trace,"+
|
||||
"on:__node__.on,"+
|
||||
"status:__node__.status,"+
|
||||
"send:function(msgs){ __node__.send(__msgid__,msgs);}"+
|
||||
@@ -91,6 +93,12 @@ module.exports = function(RED) {
|
||||
warn: function() {
|
||||
node.warn.apply(node, arguments);
|
||||
},
|
||||
debug: function() {
|
||||
node.debug.apply(node, arguments);
|
||||
},
|
||||
trace: function() {
|
||||
node.trace.apply(node, arguments);
|
||||
},
|
||||
send: function(id, msgs) {
|
||||
sendResults(node, id, msgs);
|
||||
},
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
outputs:1,
|
||||
icon: "template.png",
|
||||
label: function() {
|
||||
return this.name;
|
||||
return this.name||this._("template.template");;
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
|
||||
@@ -50,6 +50,7 @@ module.exports = function(RED) {
|
||||
|
||||
// try node context:
|
||||
var dot = name.indexOf(".");
|
||||
/* istanbul ignore else */
|
||||
if (dot > 0) {
|
||||
var contextName = name.substr(0, dot);
|
||||
var variableName = name.substr(dot + 1);
|
||||
@@ -61,7 +62,8 @@ module.exports = function(RED) {
|
||||
return this.nodeContext.global.get(variableName);
|
||||
}
|
||||
}
|
||||
}catch(err) {
|
||||
}
|
||||
catch(err) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
@@ -87,24 +89,27 @@ module.exports = function(RED) {
|
||||
* Allow template contents to be defined externally
|
||||
* through inbound msg.template IFF node.template empty
|
||||
*/
|
||||
var template = node.template;
|
||||
if (msg.hasOwnProperty("template")) {
|
||||
if (node.template == "" || node.template === null) {
|
||||
node.template = msg.template;
|
||||
if (template == "" || template === null) {
|
||||
template = msg.template;
|
||||
}
|
||||
}
|
||||
|
||||
if (node.syntax === "mustache") {
|
||||
if (node.outputFormat === "json") {
|
||||
value = mustache.render(node.template,new NodeContext(msg, node.context(), null, true));
|
||||
value = mustache.render(template,new NodeContext(msg, node.context(), null, true));
|
||||
} else {
|
||||
value = mustache.render(node.template,new NodeContext(msg, node.context(), null, false));
|
||||
value = mustache.render(template,new NodeContext(msg, node.context(), null, false));
|
||||
}
|
||||
} else {
|
||||
value = node.template;
|
||||
value = template;
|
||||
}
|
||||
/* istanbul ignore else */
|
||||
if (node.outputFormat === "json") {
|
||||
value = JSON.parse(value);
|
||||
}
|
||||
/* istanbul ignore else */
|
||||
if (node.outputFormat === "yaml") {
|
||||
value = yaml.load(value);
|
||||
}
|
||||
@@ -117,7 +122,8 @@ module.exports = function(RED) {
|
||||
node.context().global.set(node.field,value);
|
||||
}
|
||||
node.send(msg);
|
||||
} catch(err) {
|
||||
}
|
||||
catch(err) {
|
||||
node.error(err.message);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
outputs:0,
|
||||
icon: "comment.png",
|
||||
label: function() {
|
||||
return this.name||"";
|
||||
return this.name||this._("comment.comment");
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
|
||||
@@ -222,7 +222,6 @@ RED.debug = (function() {
|
||||
clearMessageList(false);
|
||||
});
|
||||
|
||||
|
||||
return {
|
||||
content: content,
|
||||
footer: footerToolbar
|
||||
@@ -238,6 +237,9 @@ RED.debug = (function() {
|
||||
workspaceOrder.forEach(function(ws,i) {
|
||||
workspaceOrderMap[ws] = i;
|
||||
});
|
||||
candidateNodes = candidateNodes.filter(function(node) {
|
||||
return workspaceOrderMap.hasOwnProperty(node.z);
|
||||
})
|
||||
candidateNodes.sort(function(A,B) {
|
||||
var wsA = workspaceOrderMap[A.z];
|
||||
var wsB = workspaceOrderMap[B.z];
|
||||
@@ -339,7 +341,7 @@ RED.debug = (function() {
|
||||
activeMenuMessage.clearPinned();
|
||||
}},
|
||||
null,
|
||||
{id:"debug-message-menu-item-filter",label:RED._("node-red:debug.messageMenu.filterNode"),onselect:function(){
|
||||
{id:"debug-message-menu-item-filter", label:RED._("node-red:debug.messageMenu.filterNode"),onselect:function(){
|
||||
var candidateNodes = RED.nodes.filterNodes({type:'debug'});
|
||||
candidateNodes.forEach(function(n) {
|
||||
filteredNodes[n.id] = true;
|
||||
@@ -361,6 +363,15 @@ RED.debug = (function() {
|
||||
menuOptionMenu.on('mouseup', function() { $(this).hide() });
|
||||
menuOptionMenu.appendTo("body");
|
||||
}
|
||||
|
||||
var filterOptionDisabled = false;
|
||||
var sourceNode = RED.nodes.node(sourceId);
|
||||
if (sourceNode && sourceNode.type !== 'debug') {
|
||||
filterOptionDisabled = true;
|
||||
}
|
||||
RED.menu.setDisabled('debug-message-menu-item-filter',filterOptionDisabled);
|
||||
RED.menu.setDisabled('debug-message-menu-item-clear-filter',filterOptionDisabled);
|
||||
|
||||
var elementPos = button.offset();
|
||||
menuOptionMenu.css({
|
||||
top: elementPos.top+"px",
|
||||
|
||||
@@ -142,9 +142,9 @@ module.exports = function(RED) {
|
||||
var limit = 1;
|
||||
if (node.out === "pwm") { limit = 100; }
|
||||
if ((out >= 0) && (out <= limit)) {
|
||||
if (RED.settings.verbose) { node.log("out: "+msg.payload); }
|
||||
if (RED.settings.verbose) { node.log("out: "+out); }
|
||||
if (node.child !== null) {
|
||||
node.child.stdin.write(msg.payload+"\n");
|
||||
node.child.stdin.write(out+"\n");
|
||||
node.status({fill:"green",shape:"dot",text:msg.payload.toString()});
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -88,6 +88,8 @@
|
||||
<dt class="optional">rejectUnauthorized</dt>
|
||||
<dd>If set to <code>true</code>, allows requests to be made to https sites that use
|
||||
self signed certificates.</dd>
|
||||
<dt class="optional">followRedirects</dt>
|
||||
<dd>If set to <code>false</code> prevent following Redirect (HTTP 301).<code>true</code> by default</dd>
|
||||
</dl>
|
||||
<h3>Outputs</h3>
|
||||
<dl class="message-properties">
|
||||
|
||||
@@ -108,6 +108,9 @@ module.exports = function(RED) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (msg.hasOwnProperty('followRedirects')) {
|
||||
opts.followRedirects = msg.followRedirects;
|
||||
}
|
||||
if (msg.cookies) {
|
||||
var cookies = [];
|
||||
if (opts.headers.hasOwnProperty('cookie')) {
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
outputs:1,
|
||||
icon: "watch.png",
|
||||
label: function() {
|
||||
return this.name||this.files;
|
||||
return this.name||this.files||this._("watch.watch");
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
|
||||
@@ -70,8 +70,8 @@
|
||||
}
|
||||
},
|
||||
"catch": {
|
||||
"catch": "catch all",
|
||||
"catchNodes": "catch (__number__)",
|
||||
"catch": "catch: all",
|
||||
"catchNodes": "catch: __number__",
|
||||
"label": {
|
||||
"source": "Catch errors from",
|
||||
"node": "node",
|
||||
@@ -86,8 +86,8 @@
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
"status": "status (all)",
|
||||
"statusNodes": "status (__number__)",
|
||||
"status": "status: all",
|
||||
"statusNodes": "status: __number__",
|
||||
"label": {
|
||||
"source": "Report status from",
|
||||
"node": "node",
|
||||
@@ -166,6 +166,8 @@
|
||||
}
|
||||
},
|
||||
"exec": {
|
||||
"exec": "exec",
|
||||
"spawn": "spawn",
|
||||
"label": {
|
||||
"command": "Command",
|
||||
"append": "Append",
|
||||
@@ -195,6 +197,7 @@
|
||||
"tip": "See the Info tab for help writing functions."
|
||||
},
|
||||
"template": {
|
||||
"template": "template",
|
||||
"label": {
|
||||
"template": "Template",
|
||||
"property": "Set property",
|
||||
@@ -301,6 +304,7 @@
|
||||
}
|
||||
},
|
||||
"comment": {
|
||||
"comment": "comment",
|
||||
"label": {
|
||||
"title": "Title",
|
||||
"body": "Body"
|
||||
@@ -416,6 +420,7 @@
|
||||
}
|
||||
},
|
||||
"watch": {
|
||||
"watch": "watch",
|
||||
"label": {
|
||||
"files": "File(s)",
|
||||
"recursive": "Watch sub-directories recursively"
|
||||
@@ -542,6 +547,7 @@
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"switch": "switch",
|
||||
"label": {
|
||||
"property": "Property",
|
||||
"rule": "rule",
|
||||
@@ -597,6 +603,7 @@
|
||||
}
|
||||
},
|
||||
"range": {
|
||||
"range": "range",
|
||||
"label": {
|
||||
"action": "Action",
|
||||
"inputrange": "Map the input range",
|
||||
@@ -763,7 +770,9 @@
|
||||
"status": {
|
||||
"stopped": "stopped",
|
||||
"closed": "closed",
|
||||
"not-running": "not running"
|
||||
"not-running": "not running",
|
||||
"not-available": "not available",
|
||||
"na": "N/A : __value__"
|
||||
},
|
||||
"errors": {
|
||||
"ignorenode": "Ignoring Raspberry Pi specific node",
|
||||
@@ -782,6 +791,7 @@
|
||||
}
|
||||
},
|
||||
"tail": {
|
||||
"tail": "tail",
|
||||
"label": {
|
||||
"filename": "Filename",
|
||||
"type": "File type",
|
||||
@@ -835,6 +845,7 @@
|
||||
"tip": "Tip: The filename should be an absolute path, otherwise it will be relative to the working directory of the Node-RED process."
|
||||
},
|
||||
"split": {
|
||||
"split": "split",
|
||||
"intro":"Split <code>msg.payload</code> based on type:",
|
||||
"object":"<b>Object</b>",
|
||||
"objectSend":"Send a message for each key/value pair",
|
||||
@@ -846,6 +857,7 @@
|
||||
"addname":" Copy key to "
|
||||
},
|
||||
"join":{
|
||||
"join": "join",
|
||||
"mode":{
|
||||
"mode":"Mode",
|
||||
"auto":"automatic",
|
||||
@@ -892,6 +904,7 @@
|
||||
}
|
||||
},
|
||||
"sort" : {
|
||||
"sort": "sort",
|
||||
"target" : "Sort",
|
||||
"seq" : "message sequence",
|
||||
"key" : "Key",
|
||||
@@ -905,6 +918,7 @@
|
||||
"clear" : "clear pending message in sort node"
|
||||
},
|
||||
"batch" : {
|
||||
"batch": "batch",
|
||||
"mode": {
|
||||
"label" : "Mode",
|
||||
"num-msgs" : "Group by number of messages",
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>injectノードを用いることで、指定したペイロード値を用いてフローを開始できます。デフォルトのペイロード値は現在時刻のタイムスタンプを1970年1月1日からの経過ミリ秒で表現した値です。</p>
|
||||
<p>文字列、数値、論理値、JavaScriptオブジェクト、フロー/グローバルコンテクストの値などの送出も可能です。</p>
|
||||
<p>文字列、数値、論理値、JavaScriptオブジェクト、フロー/グローバルコンテキストの値などの送出も可能です。</p>
|
||||
<p> デフォルト設定では、エディタ内に表示されるボタンをクリックすることで、ノードを手動で起動できます。指定間隔もしくはスケジュールに従ってメッセージを送出するように設定することも可能です。</p>
|
||||
<p>また、フロー開始の際に一度だけメッセージを送出させることもできます。</p>
|
||||
<p>「<i>時間間隔</i>」に指定可能な値の最大値は、約596時間(もしくは24日)です。一日より長い間隔を扱いたい場合は、電源停止や再起動にも対応可能なスケジューラノードの利用を検討すると良いでしょう。</p>
|
||||
@@ -21,7 +21,6 @@
|
||||
<p>JavaScriptオブジェクトと配列は必要に応じて折り畳んだり展開したりできます。バッファオブジェクトを生データとして表示したり、表現可能な場合に文字列として表示することも可能です。</p>
|
||||
<p>メッセージを受信した時刻、送信ノード、メッセージの型に関する情報を「デバッグ」サイドバーに表示されたメッセージに付随して表示します。送信元ノードのIDを選択すると、ワークスペース内の対応ノードを確認できます。</p>
|
||||
<p>出力の有効/無効はノード上のボタンで切り替えられます。フロー上で未使用のdebugノードは、無効化するか削除することを推奨します。</p>
|
||||
<p>全てのメッセージをランタイムログに送付、もしくは、(32文字の)短いデータを
|
||||
debugノードの下のステータステキストに表示することも可能です。</p>
|
||||
<p>全てのメッセージをランタイムログに送付、もしくは、(32文字の)短いデータをdebugノードの下のステータステキストに表示することも可能です。</p>
|
||||
</script>
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
</dl>
|
||||
<dl class="message-properties">
|
||||
<dt>rc <span class="property-type">オブジェクト</span></dt>
|
||||
<dd>返却コードオブジェクト(3番ポートでも受取り可能)のコピー(execモードのみ)</dd>
|
||||
<dd>返却コードオブジェクト(3番目の端子でも受取り可能)のコピー(execモードのみ)</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li>標準エラー出力(stderr)
|
||||
@@ -48,7 +48,7 @@
|
||||
</dl>
|
||||
<dl class="message-properties">
|
||||
<dt>rc <span class="property-type">オブジェクト</span></dt>
|
||||
<dd>返却コードオブジェクト(3番ポートでも受取り可能)のコピー(execモードのみ)</dd>
|
||||
<dd>返却コードオブジェクト(3番目の端子でも受取り可能)のコピー(execモードのみ)</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li>返却コード(return code)
|
||||
@@ -61,8 +61,8 @@
|
||||
<h3>詳細</h3>
|
||||
<p>デフォルトでは、<code>exec</code>システムコールを用いてコマンドを呼び出してその完了を待ち、出力を返します。例えば、コマンドの実行が成功した場合には、<code>{ code: 0 }</code>と言う返却値を返します。</p>
|
||||
<p><code>spawn</code>を使ってコマンドを実行し、
|
||||
標準出力および標準エラー出力へ出力を返すようにすることもできます。この場合、通常1行毎に値を返します。コマンドの実行が完了すると、3番目のポートにオブジェクトを出力します。例えば、コマンドの実行が成功した場合には、<code>{ code: 0 }</code>と言う返却値を返します。</p>
|
||||
<p>エラー発生時には、3番目のポートの<code>msg.payload</code>に<code>message</code>、<code>signal</code>など付加情報を返します。</p>
|
||||
標準出力および標準エラー出力へ出力を返すようにすることもできます。この場合、通常1行毎に値を返します。コマンドの実行が完了すると、3番目の端子にオブジェクトを出力します。例えば、コマンドの実行が成功した場合には、<code>{ code: 0 }</code>と言う返却値を返します。</p>
|
||||
<p>エラー発生時には、3番目の端子の<code>msg.payload</code>に<code>message</code>、<code>signal</code>など付加情報を返します。</p>
|
||||
<p>実行対象のコマンドはノード設定で定義します。<code>msg.payload</code>や追加引数をコマンドに追加することもできます。</p>
|
||||
<p>コマンドもしくはパラメータが空白を含む場合には、引用符で囲みます。- <code>"This is a single parameter"</code></p>
|
||||
<p>返却する<code>payload</code>は通常<i>文字列</i>ですが、UTF8文字以外が存在すると<i>バッファ</i>となります。</p>
|
||||
@@ -24,11 +24,8 @@
|
||||
</dl>
|
||||
|
||||
<h3>詳細</h3>
|
||||
<p>フロー内でタイムアウトを作成するのに利用します。メッセージを受け取ると、
|
||||
デフォルトでは<code>payload</code>に<code>1</code>を設定して送信します。送信後250ms待機し、<code>payload</code>を<code>0</code>に設定した2つ目のメッセージを送信します。この機能は、例えばRaspberry PIのGPIOピンに接続したLEDを点滅させるために活用できます。</p>
|
||||
<p>各送信メッセージのペイロードはさまざまな種類の値に設定できます。再送信デ
|
||||
ータなしとすることも可能です。例えば、再送信データを「<i>なし</i>」とし、
|
||||
メッセージを受け取った時に遅延を延長することを選択した場合、triggerノードは監視タイマとして動作します。すなわち、指定間隔内にメッセージを受信しない場合にメッセージを送信します。</p>
|
||||
<p>フロー内でタイムアウトを作成するのに利用します。メッセージを受け取ると、デフォルトでは<code>payload</code>に<code>1</code>を設定して送信します。送信後250ms待機し、<code>payload</code>を<code>0</code>に設定した2つ目のメッセージを送信します。この機能は、例えばRaspberry PIのGPIOピンに接続したLEDを点滅させるために活用できます。</p>
|
||||
<p>各送信メッセージのペイロードはさまざまな種類の値に設定できます。再送信データなしとすることも可能です。例えば、再送信データを「<i>なし</i>」とし、メッセージを受け取った時に遅延を延長することを選択した場合、triggerノードは監視タイマとして動作します。すなわち、指定間隔内にメッセージを受信しない場合にメッセージを送信します。</p>
|
||||
<p>ペイロードに<i>文字列</i>を指定する場合、mustache形式のテンプレートが利用できます。</p>
|
||||
<p><code>reset</code>プロパティを持つメッセージを受信した場合、もしくは、<code>payload</code>が設定した値にマッチする場合、仕掛かり中の待機や繰り返しをクリアしメッセージの送信は行いません。</p>
|
||||
<p>受信メッセージでリセットするまで一定間隔でメッセージを再送するように指定することもできます。</p>
|
||||
71
nodes/core/locales/ja/hardware/36-rpi-gpio.html
Normal file
71
nodes/core/locales/ja/hardware/36-rpi-gpio.html
Normal file
@@ -0,0 +1,71 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="rpi-gpio in">
|
||||
<p>Raspberry Piの入力ノード。入力ピンの状態に応じて、0 または 1 の値を持つ<code>msg.payload</code>を生成します。</p>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">数値</span></dt>
|
||||
<dd>ペイロードには、0 または 1 が設定されます。</dd>
|
||||
<dt>topic <span class="property-type">文字列</span></dt>
|
||||
<dd>トピックには、<code>pi/{ピン番号}</code>が設定されます。</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>入力のプルアップ抵抗またはプルダウン抵抗を有効にすることもできます。</p>
|
||||
<p>動作にはRPi.GPIO pythonライブラリのバージョン 0.5.10 (またはそれ以上)が必要です。</p>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="rpi-gpio out">
|
||||
<p>Raspberry Piの出力ノード。デジタルモードまたはPWMモードで利用できます。
|
||||
<h3>入力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">数値 | 文字列 | 真偽値</span></dt>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>デジタルモード - <code>msg.payload</code>に 0 または 1 (あるいは true または false ) を指定すると、入力値に応じて選択された物理ピンにハイまたはローを設定します。</p>
|
||||
<p>デプロイ時にピンの初期値として 0 または 1 を設定することもできます。</p>
|
||||
<p>PWMモード - 入力値に 0 から 100 の数値を指定でき。小数値の指定も可能です。</p>
|
||||
<p>サーボの制御にPWMモードが利用でき、入力に小数値も含む 10 から 20 の値が指定可能です。
|
||||
PWMを行うハードウェアを利用していることから、PWMモードの指定にはGPIO2ピンが最も適しています。
|
||||
より良くサーボの制御を行いたい場合は、node-red-node-pi-gpiod ノードの利用も検討してください。</p>
|
||||
<p>動作にはRPi.GPIO pythonライブラリのバージョン 0.5.10 (またはそれ以上)が必要です。</p>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="rpi-mouse">
|
||||
<p>Raspberry Pi のマウスボタンノード。USBマウスが必要です。</p>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">数値</span></dt>
|
||||
<dd>選択されたマウスのボタンが押された、または離された場合に 1 または 0 が設定されます。</dd>
|
||||
<dt>button <span class="property-type">数値</span></dt>
|
||||
<dd>左、右、真ん中のボタンに応じて 1, 2, 4 が設定され、ボタンあるいはボタンの組み合わせに応じた処理ができます。</dd>
|
||||
<dt>topic <span class="property-type">文字列</span></dt>
|
||||
<dd><code>pi/mouse</code>が設定されます。</dd>
|
||||
</dl>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="rpi-keyboard">
|
||||
<p>Raspberry Pi のキーボードを制御するノード。USBキーボードが必要です。</p>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">数値</span></dt>
|
||||
<dd>キーコードを含みます。</dd>
|
||||
<dt>action <span class="property-type">文字列</span></dt>
|
||||
<dd>"up", "down", または "repeat" が設定されます。</dd>
|
||||
<dt>topic <span class="property-type">文字列</span></dt>
|
||||
<dd><code>pi/key</code>が設定されます。</dd>
|
||||
</dl>
|
||||
</script>
|
||||
@@ -16,14 +16,12 @@
|
||||
|
||||
<script type="text/x-red" data-help-name="websocket in">
|
||||
<p>WebSocket入力ノード</p>
|
||||
<p>デフォルトでは、WebSocketにより受信したデータは<code>msg.payload</code>に格納します。
|
||||
ソケットはJSON形式の文字列を待ち受けるように設定することができます。JSON形式の文字列を受け付けると、オブジェクトへの変換を行い、メッセージ全体として送信します。</p>
|
||||
<p>デフォルトでは、WebSocketにより受信したデータは<code>msg.payload</code>に格納します。ソケットはJSON形式の文字列を待ち受けるように設定することができます。JSON形式の文字列を受け付けると、オブジェクトへの変換を行い、メッセージ全体として送信します。</p>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="websocket out">
|
||||
<p>WebSocket出力ノード</p>
|
||||
<p>デフォルトでは、<code>msg.payload</code>をWebSocket経由で送信します。
|
||||
ソケットは<code>msg</code>全体をJSON文字列にエンコードしてWebSocketを介して送信することもできます。</p>
|
||||
<p>デフォルトでは、<code>msg.payload</code>をWebSocket経由で送信します。ソケットは<code>msg</code>全体をJSON文字列にエンコードしてWebSocketを介して送信することもできます。</p>
|
||||
|
||||
<p>このノードが受信したメッセージがWebSocket Inノードが生成したものである場合、メッセージはフローを起動したクライアントに送り返されます。それ以外の場合、メッセージは接続している全てのクライアントにブロードキャストされます。</p>
|
||||
<p>WebSocket Inノードが生成したメッセージをブロードキャストしたい場合には、フロー中で<code>msg._session</code>プロパティを削除します。</p>
|
||||
@@ -34,5 +32,5 @@
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="websocket-client">
|
||||
<p>この設定ノードは指定したURLにWebSocketクライアントを接続します。</p>
|
||||
<p>この設定ノードは指定したURLにWebSocketクライアントを接続します。</p>
|
||||
</script>
|
||||
@@ -18,8 +18,7 @@
|
||||
<p>ディレクトリもしくはファイルの変化を検知します。</p>
|
||||
<p>カンマ区切りでディレクトリおよびファイルのリストを指定します。空白を含む場合は、引用符で"..."のように囲んでください。</p>
|
||||
<p>Windowsでは、2重バックスラッシュ\\をディレクトリ名に使用します。</p>
|
||||
<p>実際に変化したファイルのフルパス名を<code>msg.payload</code>に、
|
||||
、検知対象リストの文字列を<code>msg.topic</code>に返します。</p>
|
||||
<p>実際に変化したファイルのフルパス名を<code>msg.payload</code>に、検知対象リストの文字列を<code>msg.topic</code>に返します。</p>
|
||||
<p><code>msg.file</code>は変化したファイルのファイル名表します。<code>msg.type</code>は変化した対象の種別(<i>file</i>もしくは<i>directory</i>)を、<code>msg.size</code>はファイルサイズ(バイト数)を表します。</p>
|
||||
<p>Linuxではファイルとして表されるもの<i>全て</i>が、検知対象にできます。</p>
|
||||
<p><b>注: </b>検知対象のディレクトリもしくはファイルは存在していなくてはなりません。対象ファイルもしくはディレクトリが削除された場合、再作成されても検知対象から外れたままです。</p>
|
||||
@@ -16,22 +16,20 @@
|
||||
|
||||
<script type="text/x-red" data-help-name="tcp in">
|
||||
<p>TCPからの入力を行います。リモートTCPポートに接続するか、外部らからのコネクションを受け付けます。</p>
|
||||
<p><b>注: </b>1024番より小さな番号のポートをアクセスするにはroodもしくはadministrator権限が必要なシステムもあります。</p>
|
||||
<p><b>注: </b>1024番より小さな番号のポートをアクセスするにはrootもしくはadministrator権限が必要なシステムもあります。</p>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="tcp out">
|
||||
<p>TCPへの出力を行います。リモートTCPポートへ接続、外部からのコネクションの受け付け、もしくは、TCP Inノードで受け付けたメッセージへのリプライを行います。</p>
|
||||
<p><code>msg.payload</code>のみが送信対象となります。</p>
|
||||
<p><code>msg.payload</code>がバイナリデータをBase64エンコーディングの文字列に変換したものの場合、Base64デコードオプションを指定するとデータをバイナリに変化んして送信します。</p>
|
||||
<p><code>msg.payload</code>がバイナリデータをBase64エンコーディングの文字列に変換したものの場合、Base64デコードオプションを指定するとデータをバイナリに変換して送信します。</p>
|
||||
<p><code>msg._session</code>が存在しない場合、接続している<b>全ての</b>クライアントに送信します。</p>
|
||||
<p><b>注: </b>1024番より小さな番号のポートをアクセスするにはroodもしくはadministrator権限が必要なシステムもあります。</p>
|
||||
<p><b>注: </b>1024番より小さな番号のポートをアクセスするにはrootもしくはadministrator権限が必要なシステムもあります。</p>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="tcp request">
|
||||
<p>シンプルなTCPリクエストノード。<code>msg.payload</code>をサーバのTCPポートに送信し、レスポンスを待ちます。</p>
|
||||
<p>
|
||||
サーバに接続、"リクエスト"送信、"レスポンス"受信を行います。固定長の文字数、指定文字へのマッチ、最初のリプライの到着から指定した時間待つ、データの到着待ち、データ送信を行いリプライを待たず接続を即時解除、などから動作を選択できます。</p>
|
||||
<p>
|
||||
レスポンスはバッファ形式で<code>msg.payload</code>に出力されます。文字列として扱いには、toString()を使用してください。</p>
|
||||
<p>サーバに接続、"リクエスト"送信、"レスポンス"受信を行います。固定長の文字数、指定文字へのマッチ、最初のリプライの到着から指定した時間待つ、データの到着待ち、データ送信を行いリプライを待たず接続を即時解除、などから動作を選択できます。</p>
|
||||
<p>レスポンスはバッファ形式で<code>msg.payload</code>に出力されます。文字列として扱いには、toString()を使用してください。</p>
|
||||
<p>TCPホストのポート番号設定を空にした場合、<code>msg.host</code>および<code>msg.port</code>プロパティを設定しなくてはなりません。</p>
|
||||
</script>
|
||||
@@ -17,13 +17,12 @@
|
||||
<script type="text/x-red" data-help-name="udp in">
|
||||
<p>UDP入力ノード。<code>msg.payload</code>にバッファ、文字列、もしくは、Base64エンコーディング文字列を生成します。マルチキャストをサポートしています。</p>
|
||||
<p><code>msg.ip</code>と<code>msg.port</code>に受信したメッセージのIPアドレスとポートを設定します。</p>
|
||||
<p><b>注</b>: 1024番より小さな番号のポートへのアクセス、ブロードキャストを行うにはroodもしくはadministrator権限が必要なシステムもあります。</p>
|
||||
<p><b>注</b>: 1024番より小さな番号のポートへのアクセス、ブロードキャストを行うにはrootもしくはadministrator権限が必要なシステムもあります。</p>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="udp out">
|
||||
<p><code>msg.payload</code>を指定したUDPのホストとポートに送信します。マルチキャストをサポートします。</p>
|
||||
<p><code>msg.ip</code>と<code>msg.port</code>に接続先を設定できますが、ノード設定の方が優先されます。</p>
|
||||
<p>
|
||||
ブロードキャストを行うには、アドレスをローカルブロードキャストIPアドレスに設定するか、グローバルブロードキャストアドレスである255.255.255.255を試してください。</p>
|
||||
<p><b>注</b>: 1024番より小さな番号のポートへのアクセス、ブロードキャストを行うにはroodもしくはadministrator権限が必要なシステムもあります。</p>
|
||||
<p>ブロードキャストを行うには、アドレスをローカルブロードキャストIPアドレスに設定するか、グローバルブロードキャストアドレスである255.255.255.255を試してください。</p>
|
||||
<p><b>注</b>: 1024番より小さな番号のポートへのアクセス、ブロードキャストを行うにはrootもしくはadministrator権限が必要なシステムもあります。</p>
|
||||
</script>
|
||||
@@ -32,5 +32,4 @@
|
||||
<h3>メッセージ列の扱い</h3>
|
||||
<p>switchノードは入力メッセージの列に関する情報を保持する<code>msg.parts</code>をデフォルトでは変更しません。</p>
|
||||
<p>「<b>メッセージ列の補正</b>」オプションを指定すると、マッチした各ルールに対して新しいメッセージ列を生成します。このモードでは、switchノードは新たなメッセージ列を送信する前に、入力メッセージ列全体を内部に蓄積します。<code>nodeMessageBufferMaxLength</code>を設定すると、蓄積するメッセージ数を制限できます。</p>
|
||||
|
||||
</script>
|
||||
@@ -29,6 +29,5 @@
|
||||
<dt>移動</dt>
|
||||
<dd>プロパティの移動または名前の変更を行います。</dd>
|
||||
</dl>
|
||||
<p>「expression」には<a href="http://jsonata.org/" target="_new">JSONata</a>言語を指定できます。
|
||||
</p>
|
||||
<p>「expression」には<a href="http://jsonata.org/" target="_new">JSONata</a>言語を指定できます。</p>
|
||||
</script>
|
||||
@@ -49,7 +49,7 @@
|
||||
<p><code>msg.parts</code>プロパティを用いて元のメッセージとメッセージ列との対応関係を記憶します。</p>
|
||||
<h4>ストリームモード</h4>
|
||||
<p>このノードはメッセージ列を再構成して送信する際にも有用です。例えば、改行終端のコマンドを送信するようなシリアルデバイスでは、メッセージの最後のコマンド部分が途切れたメッセージを送出する場合があります。「ストリームモード」を用いることで、完結した個別コマンドにメッセージを分割することができます。入力メッセージの最後に未完部分がある場合、<b>split</b>ノードは未完部分を記憶しておいて、次に受信したメッセージの先頭に付加します。</p>
|
||||
<p>このモードで処理する際には、メッセージ数を予め知ることができないため、<code>msg.parts.count</code>プロパティは設定されません。従って、<b>join</b>ノードの「自動モード」と組みわせることはできません。</p>
|
||||
<p>このモードで処理する際には、メッセージ数を予め知ることができないため、<code>msg.parts.count</code>プロパティは設定されません。従って、<b>join</b>ノードの「自動モード」と組み合わせることはできません。</p>
|
||||
</script>
|
||||
|
||||
|
||||
@@ -38,8 +38,7 @@
|
||||
<p>「列名」にカラム名のリストを指定することができます。CSVからオブジェクトに変換を行う際、カラム名をプロパティ名として使用します。「列名」の代わりに、CSVデータの1行目にカラム名を含めることもできます。</p>
|
||||
<p>CSVへの変換を行う際には、オブジェクトから取り出すべきプロパティとその順序を「列名」を参照して決めます。</p>
|
||||
<p>入力が配列の場合には、「列名」はカラム名を表す行の出力指定がされた場合だけ用います。</p>
|
||||
<p>
|
||||
<code>parts</code>プロパティが正しく設定されている場合、メッセージ列を入力として受け付けます。</p>
|
||||
<p><code>parts</code>プロパティが正しく設定されている場合、メッセージ列を入力として受け付けます。</p>
|
||||
<p>CSVを複数のメッセージに変換して出力する場合、出力がメッセージ列となるよう<code>parts</code>プロパティを設定します。</p>
|
||||
<p><b>注:</b> カンマ以外の区切り文字を設定した場合であっても、「列名」はカンマ区切りとしてください。</p>
|
||||
</script>
|
||||
@@ -20,9 +20,9 @@
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">文字列</span></dt>
|
||||
<dd>要素を取り出すHTML文字列</dd>
|
||||
<dt class="optional">select <span class="property-type">string</span></dt>
|
||||
<dt class="optional">select <span class="property-type">文字列</span></dt>
|
||||
<dd>編集パネルでセレクタを指定していない場合、メッセージのプロパティとして設定できます</dd>
|
||||
</dl>
|
||||
</dl>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">配列 | 文字列</span></dt>
|
||||
@@ -15,7 +15,7 @@
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="json">
|
||||
<p>Converts between a JSON string and its JavaScript object representation, in either direction.</p>
|
||||
<p>JSON文字列とJavaScriptオブジェクトとの間で相互変換を行います。</p>
|
||||
<h3>入力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload<span class="property-type">オブジェクト | 文字列</span></dt>
|
||||
@@ -33,6 +33,6 @@
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>デフォルトの変換対象は<code>msg.payload</code>ですが、他のメッセージプロパティを変換対象とすることも可能です。</p>
|
||||
<p>双方向の変換を自動選択するのではなく、特定の変換のみ行うように設定できます。この機能は、例えば、<code>HTTP In</code>ノードに対するリクエストがcontent-typeを正しく設定していないであっても、JSONノードによる変換結果がJavaScriptオブジェクトであることを保証するために利用します。</p>
|
||||
<p>双方向の変換を自動選択するのではなく、特定の変換のみ行うように設定できます。この機能は、例えば、<code>HTTP In</code>ノードに対するリクエストがcontent-typeを正しく設定していない場合であっても、JSONノードによる変換結果がJavaScriptオブジェクトであることを保証するために利用します。</p>
|
||||
<p>JSON文字列への変換が指定されている場合、受信した文字列に対してさらなるチェックは行いません。すなわち、文字列がJSONとして正しいかどうかの検査や、整形オプションを指定していたとしても整形処理を実施しません。</p>
|
||||
</script>
|
||||
@@ -15,9 +15,7 @@
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-help-name="file">
|
||||
<p><code>msg.payload</code>をファイルに書き出します。書き出しは、ファイルの
|
||||
最後に追記もしくは既存の内容の置き換えを選択できます。
|
||||
この他、ファイルの削除を行うことも可能です。</p>
|
||||
<p><code>msg.payload</code>をファイルに書き出します。書き出しは、ファイルの最後に追記もしくは既存の内容の置き換えを選択できます。この他、ファイルの削除を行うことも可能です。</p>
|
||||
<h3>入力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt class="optional">filename <span class="property-type">文字列</span></dt>
|
||||
@@ -5,7 +5,8 @@
|
||||
"topic": "主题",
|
||||
"name": "名称",
|
||||
"username": "用户名",
|
||||
"password": "密码"
|
||||
"password": "密码",
|
||||
"property": "属性"
|
||||
},
|
||||
"status": {
|
||||
"connected": "已连接",
|
||||
@@ -13,7 +14,7 @@
|
||||
"disconnected": "已断开",
|
||||
"connecting": "连接中",
|
||||
"error": "错误",
|
||||
"ok": "确认"
|
||||
"ok": "确定"
|
||||
},
|
||||
"notification": {
|
||||
"error": "<strong>错误</strong>: __message__",
|
||||
@@ -37,17 +38,17 @@
|
||||
"repeat": "重复"
|
||||
},
|
||||
"timestamp": "时间戳",
|
||||
"none": "空白",
|
||||
"interval": "间隔",
|
||||
"interval-time": "特定时间内间隔",
|
||||
"time": "特定时间",
|
||||
"none": "无",
|
||||
"interval": "周期性执行",
|
||||
"interval-time": "指定时间段周期性执行",
|
||||
"time": "指定时间",
|
||||
"seconds": "秒",
|
||||
"minutes": "分钟",
|
||||
"hours": "小时",
|
||||
"between": "介于",
|
||||
"previous": "之前数值",
|
||||
"at": "在",
|
||||
"and": "之间",
|
||||
"and": "至",
|
||||
"every": "每隔",
|
||||
"days": [
|
||||
"星期一",
|
||||
@@ -59,18 +60,20 @@
|
||||
"星期天"
|
||||
],
|
||||
"on": "在",
|
||||
"onstart": "运行时注入?",
|
||||
"tip": "<b>注意:</b> \"特定时间内间隔\" 和 \"特定时间\" 会使用cron系统.<br/> 详情查看信息页.",
|
||||
"onstart": "立刻执行于",
|
||||
"onceDelay": "秒后, 此后",
|
||||
"tip": "<b>注意:</b> \"指定时间段周期性执行\" 和 \"指定时间\" 会使用cron系统.<br/> 详情查看信息页.",
|
||||
"success": "成功注入: __label__",
|
||||
"errors": {
|
||||
"failed": "注入失败, 请查看日志"
|
||||
"failed": "注入失败, 请查看日志",
|
||||
"toolong": "周期过长"
|
||||
}
|
||||
},
|
||||
"catch": {
|
||||
"catch": "检测异常",
|
||||
"catchNodes": "检测到 (__number__)",
|
||||
"catch": "监测所有节点",
|
||||
"catchNodes": "监测__number__个节点",
|
||||
"label": {
|
||||
"source": "检测错误来自",
|
||||
"source": "监测范围",
|
||||
"node": "节点",
|
||||
"type": "类型",
|
||||
"selectAll": "全选",
|
||||
@@ -79,14 +82,14 @@
|
||||
},
|
||||
"scope": {
|
||||
"all": "所有节点",
|
||||
"selected": "已选节点"
|
||||
"selected": "指定节点"
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
"status": "状态 (所有)",
|
||||
"statusNodes": "状态显示 (__number__)",
|
||||
"status": "报告所有节点状态",
|
||||
"statusNodes": "报告__number__个节点状态",
|
||||
"label": {
|
||||
"source": "状态报告来自",
|
||||
"source": "报告状态范围",
|
||||
"node": "节点",
|
||||
"type": "类型",
|
||||
"selectAll": "全选",
|
||||
@@ -95,7 +98,7 @@
|
||||
},
|
||||
"scope": {
|
||||
"all": "所有节点",
|
||||
"selected": "已选节点"
|
||||
"selected": "指定节点"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
@@ -104,7 +107,11 @@
|
||||
"msgobj": "完整信息",
|
||||
"to": "目标",
|
||||
"debtab": "调试窗口",
|
||||
"tabcon": "调试窗口及终端控制台",
|
||||
"tabcon": "调试窗口及Console",
|
||||
"toSidebar": "调试窗口",
|
||||
"toConsole": "Console",
|
||||
"toStatus": "节点状态 (32位字符)",
|
||||
"severity": "级别",
|
||||
"notification": {
|
||||
"activated": "成功激活: __label__",
|
||||
"deactivated": "成功取消: __label__"
|
||||
@@ -114,21 +121,21 @@
|
||||
"name": "名称",
|
||||
"filterAll": "所有节点",
|
||||
"filterSelected": "已选节点",
|
||||
"filterCurrent": "目前流程",
|
||||
"filterCurrent": "当前流程",
|
||||
"debugNodes": "调试节点",
|
||||
"clearLog": "清理日志",
|
||||
"clearLog": "清空日志",
|
||||
"openWindow": "在新窗口打开"
|
||||
},
|
||||
"messageMenu": {
|
||||
"collapseAll": "折叠所有路径",
|
||||
"clearPinned": "清理已固定路径",
|
||||
"clearPinned": "清空已固定路径",
|
||||
"filterNode": "过滤此节点",
|
||||
"clearFilter": "清除已设过滤"
|
||||
"clearFilter": "清空过滤条件"
|
||||
}
|
||||
},
|
||||
"link": {
|
||||
"linkIn": "连接入口",
|
||||
"linkOut": "连接出口",
|
||||
"linkIn": "输入",
|
||||
"linkOut": "输出",
|
||||
"label": {
|
||||
"event": "事件名称",
|
||||
"node": "节点名称",
|
||||
@@ -144,16 +151,18 @@
|
||||
"upload": "上传",
|
||||
"cert": "证书",
|
||||
"key": "私钥",
|
||||
"passphrase": "密码",
|
||||
"ca": "CA证书",
|
||||
"verify-server-cert":"验证服务器证书"
|
||||
},
|
||||
"placeholder": {
|
||||
"cert":"证书路径 (PEM 格式)",
|
||||
"key":"私匙路径 (PEM 格式)",
|
||||
"ca":"CA证书路径 (PEM 格式)"
|
||||
"key":"私钥路径 (PEM 格式)",
|
||||
"ca":"CA证书路径 (PEM 格式)",
|
||||
"passphrase":"私钥密码 (可选)"
|
||||
},
|
||||
"error": {
|
||||
"missing-file": "无证书/密匙文件提供"
|
||||
"missing-file": "未提供证书/密钥文件"
|
||||
}
|
||||
},
|
||||
"exec": {
|
||||
@@ -169,10 +178,10 @@
|
||||
"extraparams": "额外的输入参数"
|
||||
},
|
||||
"opt": {
|
||||
"exec": "当命令任务完成时 - exec 模式",
|
||||
"spawn": "当命令任务进行时 - spawn 模式"
|
||||
"exec": "当命令完成时 - exec模式",
|
||||
"spawn": "当命令进行时 - spawn模式"
|
||||
},
|
||||
"oldrc": "使用旧式输出模式 (传统模式)"
|
||||
"oldrc": "使用旧式输出 (兼容模式)"
|
||||
},
|
||||
"function": {
|
||||
"label": {
|
||||
@@ -180,7 +189,7 @@
|
||||
"outputs": "输出"
|
||||
},
|
||||
"error": {
|
||||
"inputListener":"无法在函数里面加入对‘注入’事件的监视",
|
||||
"inputListener":"无法在函数中监听对'注入'事件",
|
||||
"non-message-returned":"函数节点尝试返回类型为 __type__ 的信息"
|
||||
},
|
||||
"tip": "可从信息页面查看更多关于如何编写函数的帮助"
|
||||
@@ -194,7 +203,8 @@
|
||||
"output": "输出为",
|
||||
"mustache": "Mustache 模版",
|
||||
"plain": "纯文本",
|
||||
"json": "解析JSON",
|
||||
"json": "JSON",
|
||||
"yaml": "YAML",
|
||||
"none": "无"
|
||||
},
|
||||
"templatevalue": "This is the payload: {{payload}} !"
|
||||
@@ -204,13 +214,13 @@
|
||||
"for": "时长",
|
||||
"delaymsg": "延迟每一条信息",
|
||||
"delayfixed": "固定延迟时间",
|
||||
"delayvarmsg": "用 msg.delay 改写延迟时长",
|
||||
"delayvarmsg": "允许msg.delay复写延迟时长",
|
||||
"randomdelay": "随机延迟",
|
||||
"limitrate": "信息速度限制",
|
||||
"limitrate": "限制信息速率",
|
||||
"limitall": "所有信息",
|
||||
"limittopic": "每一个 msg.topic",
|
||||
"fairqueue": "轮流发每一个主题",
|
||||
"timedqueue": "发所有主题",
|
||||
"limittopic": "每一个msg.topic",
|
||||
"fairqueue": "依次发送每一个topic",
|
||||
"timedqueue": "发所有topic",
|
||||
"milisecs": "毫秒",
|
||||
"secs": "秒",
|
||||
"sec": "秒",
|
||||
@@ -218,10 +228,10 @@
|
||||
"min": "分",
|
||||
"hours": "小时",
|
||||
"hour": "小时",
|
||||
"days": "日",
|
||||
"day": "日",
|
||||
"days": "天",
|
||||
"day": "天",
|
||||
"between": "介于",
|
||||
"and": "和",
|
||||
"and": "至",
|
||||
"rate": "速度",
|
||||
"msgper": "信息 每",
|
||||
"dropmsg": "不传输中间信息",
|
||||
@@ -245,14 +255,14 @@
|
||||
"singular": "小时"
|
||||
},
|
||||
"day": {
|
||||
"plural" : "日",
|
||||
"singular": "日"
|
||||
"plural" : "天",
|
||||
"singular": "天"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"buffer": "缓冲超过了 1000 条信息",
|
||||
"buffer1": "缓冲超过了 10000 条信息"
|
||||
"buffer": "缓冲了超过 1000 条信息",
|
||||
"buffer1": "缓冲了超过 10000 条信息"
|
||||
}
|
||||
},
|
||||
"trigger": {
|
||||
@@ -267,9 +277,9 @@
|
||||
"latest": "最新信息对象",
|
||||
"nothing": "无"
|
||||
},
|
||||
"wait-reset": "等待至重置",
|
||||
"wait-reset": "等待被重置",
|
||||
"wait-for": "等待",
|
||||
"wait-loop": "重发每",
|
||||
"wait-loop": "周期性重发",
|
||||
"duration": {
|
||||
"ms": "毫秒",
|
||||
"s": "秒",
|
||||
@@ -279,11 +289,11 @@
|
||||
"extend": " 如有新信息,延长延迟",
|
||||
"label": {
|
||||
"trigger": "触发",
|
||||
"trigger-block": "出发并阻止",
|
||||
"trigger-loop": "重发每",
|
||||
"trigger-block": "触发并阻止",
|
||||
"trigger-loop": "周期性重发",
|
||||
"reset": "重置触发节点条件 如果:",
|
||||
"resetMessage":"msg.reset 已设置",
|
||||
"resetPayload":"msg.payload 等于",
|
||||
"resetMessage":"msg.reset已设置",
|
||||
"resetPayload":"msg.payload等于",
|
||||
"resetprompt": "可选填"
|
||||
}
|
||||
},
|
||||
@@ -292,7 +302,7 @@
|
||||
"title": "标题",
|
||||
"body": "主体"
|
||||
},
|
||||
"tip": "提示: 主题内容可以添加格式化为 <a href=\"https://help.github.com/articles/markdown-basics/\" target=\"_blank\">Github 风格 Markdown</a>"
|
||||
"tip": "提示: 主题内容可被格式化为 <a href=\"https://help.github.com/articles/markdown-basics/\" target=\"_blank\">Github风格的Markdown</a>"
|
||||
},
|
||||
"unknown": {
|
||||
"label": {
|
||||
@@ -307,24 +317,24 @@
|
||||
"qos": "QoS",
|
||||
"clientid": "客户端ID",
|
||||
"port": "端口",
|
||||
"keepalive": "存货定时器(秒)",
|
||||
"keepalive": "Keepalive计时(秒)",
|
||||
"cleansession": "使用新的会话",
|
||||
"use-tls": "使用安全连接 (SSL/TLS)",
|
||||
"tls-config":"TLS 设置",
|
||||
"verify-server-cert":"验证服务器证书",
|
||||
"compatmode": "使用旧式 MQTT 3.1 支持"
|
||||
"compatmode": "使用旧式MQTT 3.1支持"
|
||||
},
|
||||
"tabs-label": {
|
||||
"connection": "连接",
|
||||
"security": "安全",
|
||||
"will": "终结信息",
|
||||
"birth": "初始信息"
|
||||
"will": "Will信息",
|
||||
"birth": "Birth信息"
|
||||
},
|
||||
"placeholder": {
|
||||
"clientid": "留空白将会自动生成",
|
||||
"clientid": "留白则自动生成",
|
||||
"clientid-nonclean":"如非新会话,必须设置客户端ID",
|
||||
"will-topic": "留空白将禁止终止信息",
|
||||
"birth-topic": "留空白将禁止初始信息"
|
||||
"will-topic": "留白将禁止Will信息",
|
||||
"birth-topic": "留白将禁止Birth信息"
|
||||
},
|
||||
"state": {
|
||||
"connected": "已连接到服务端: __broker__",
|
||||
@@ -334,7 +344,7 @@
|
||||
"retain": "保留",
|
||||
"true": "是",
|
||||
"false": "否",
|
||||
"tip": "提示: 如果你想用msg属性来设置主题,qos 或者是否保存,请将这几个区域留空",
|
||||
"tip": "提示: 若希望通过msg属性对topic(信息), qos及retain(保留)进行设置, 则将上述项留白",
|
||||
"errors": {
|
||||
"not-defined": "主题未设置",
|
||||
"missing-config": "未设置服务端",
|
||||
@@ -344,13 +354,13 @@
|
||||
},
|
||||
"httpin": {
|
||||
"label": {
|
||||
"method": "方法",
|
||||
"method": "请求方式",
|
||||
"url": "URL",
|
||||
"doc": "文档",
|
||||
"return": "返回",
|
||||
"upload": "接受文件上传?",
|
||||
"status": "状态码",
|
||||
"headers": "头子段",
|
||||
"headers": "Header",
|
||||
"other": "其他"
|
||||
},
|
||||
"setby": "- 用 msg.method 设定 -",
|
||||
@@ -358,21 +368,21 @@
|
||||
"use-tls": "使用安全连接 (SSL/TLS) ",
|
||||
"tls-config":"TLS 设置",
|
||||
"utf8": "UTF-8 字符串",
|
||||
"binary": "二进制缓冲模块",
|
||||
"json": "解析JSON对象",
|
||||
"binary": "二进制数据",
|
||||
"json": "JSON对象",
|
||||
"tip": {
|
||||
"in": "相对URL",
|
||||
"res": "发送到此节点的消息<b>必须</b>来自 <i>http input</i> 节点",
|
||||
"res": "发送到此节点的消息<b>必须</b>来自<i>http input</i>节点",
|
||||
"req": "提示:如果JSON解析失败,则获取的字符串将按原样返回."
|
||||
},
|
||||
"httpreq": "http 请求",
|
||||
"errors": {
|
||||
"not-created": "当httpNodeRoot为否时,无法创建 http-in 节点",
|
||||
"not-created": "当httpNodeRoot为否时,无法创建http-in节点",
|
||||
"missing-path": "无路径",
|
||||
"no-response": "无响应对象",
|
||||
"json-error": "JSON 解析错误",
|
||||
"no-url": "未设定 URL",
|
||||
"deprecated-call":"__method__ 方法已弃用",
|
||||
"deprecated-call":"__method__方法已弃用",
|
||||
"invalid-transport":"非HTTP传输请求"
|
||||
},
|
||||
"status": {
|
||||
@@ -387,13 +397,14 @@
|
||||
},
|
||||
"listenon": "监听",
|
||||
"connectto": "连接",
|
||||
"payload": "发送/接受 有效载荷",
|
||||
"message": "发送/接受 完整信息",
|
||||
"sendrec": "发送/接受",
|
||||
"payload": "有效载荷",
|
||||
"message": "完整信息",
|
||||
"tip": {
|
||||
"path1": "默认情况下,<code> payload </code>将包含要发送或从Websocket接收的数据。侦听器可以配置为以JSON格式的字符串发送或接收整个消息对象.",
|
||||
"path1": "默认情况下,<code>payload</code>将包含要发送或从Websocket接收的数据。侦听器可以配置为以JSON格式的字符串发送或接收整个消息对象.",
|
||||
"path2": "这条路径将相对于 ",
|
||||
"url1": "URL 应该使用 ws:// 或者 wss:// 方案并指向现有的websocket侦听器.",
|
||||
"url2": "默认情况下,<code> payload </code>将包含要发送或从Websocket接收的数据。可以将客户端配置为以JSON格式的字符串发送或接收整个消息对象."
|
||||
"url1": "URL 应该使用ws://或者wss://方案并指向现有的websocket侦听器.",
|
||||
"url2": "默认情况下,<code>payload</code> 将包含要发送或从Websocket接收的数据。可以将客户端配置为以JSON格式的字符串发送或接收整个消息对象."
|
||||
},
|
||||
"errors": {
|
||||
"connect-error": "ws连接发生了错误: ",
|
||||
@@ -403,8 +414,8 @@
|
||||
},
|
||||
"watch": {
|
||||
"label": {
|
||||
"files": "文件(s)",
|
||||
"recursive": "递归查看文件夹"
|
||||
"files": "文件",
|
||||
"recursive": "递归所有子文件夹"
|
||||
},
|
||||
"placeholder": {
|
||||
"files": "逗号分开文件或文件夹"
|
||||
@@ -416,8 +427,8 @@
|
||||
"type": "类型",
|
||||
"output": "输出",
|
||||
"port": "端口",
|
||||
"host": "主服务器",
|
||||
"payload": "有效载荷(s)",
|
||||
"host": "主机地址",
|
||||
"payload": "的有效载荷",
|
||||
"delimited": "分隔符号",
|
||||
"close-connection": "是否在成功发送每条信息后断开连接?",
|
||||
"decode-base64": "用 Base64 解码信息?",
|
||||
@@ -429,19 +440,19 @@
|
||||
"type": {
|
||||
"listen": "监听",
|
||||
"connect": "连接",
|
||||
"reply": "回应到 TCP"
|
||||
"reply": "响应 TCP"
|
||||
},
|
||||
"output": {
|
||||
"stream": "字串流",
|
||||
"single": "单一",
|
||||
"buffer": "缓冲模块",
|
||||
"buffer": "Buffer",
|
||||
"string": "字符串",
|
||||
"base64": "Base64 字符串"
|
||||
},
|
||||
"return": {
|
||||
"timeout": "在固定时间超时后",
|
||||
"character": "当收到某个字符时",
|
||||
"number": "固定数目的字符",
|
||||
"timeout": "指定时间后",
|
||||
"character": "当收到某个字符为",
|
||||
"number": "指定字符数",
|
||||
"never": "永不 - 保持连接",
|
||||
"immed": "马上 - 不需要等待回复"
|
||||
},
|
||||
@@ -452,8 +463,8 @@
|
||||
"stopped-listening": "已停止监听端口",
|
||||
"connection-from": "连接来自 __host__:__port__",
|
||||
"connection-closed": "连接已关闭 __host__:__port__",
|
||||
"connections": "__count__ 段连接",
|
||||
"connections_plural": "__count__ 段连接"
|
||||
"connections": "__count__ 个连接",
|
||||
"connections_plural": "__count__ 个连接"
|
||||
|
||||
},
|
||||
"errors": {
|
||||
@@ -463,7 +474,7 @@
|
||||
"error": "错误: __error__",
|
||||
|
||||
"socket-error": "套接字连接错误来自 __host__:__port__",
|
||||
"no-host": "主服务器和/或者端口未设定",
|
||||
"no-host": "主机地址或端口未设定",
|
||||
"connect-timeout": "连接超时",
|
||||
"connect-fail": "连接失败"
|
||||
}
|
||||
@@ -476,23 +487,23 @@
|
||||
"output": "输出",
|
||||
"group": "组",
|
||||
"interface": "本地IP",
|
||||
"interfaceprompt": "(可选填)本地 IP 绑定到",
|
||||
"interfaceprompt": "(可选)本地 IP 绑定到",
|
||||
"send": "发送一个",
|
||||
"toport": "到端口",
|
||||
"address": "地址",
|
||||
"decode-base64": "是否解码编码为Base64的信息?"
|
||||
"decode-base64": "是否解码Base64编码的信息?"
|
||||
},
|
||||
"placeholder": {
|
||||
"interface": "(可选填)eth0 的 ip 地址",
|
||||
"address": "目的地 ip 地址"
|
||||
"interface": "(可选)eth0的IP地址",
|
||||
"address": "目标IP地址"
|
||||
},
|
||||
"udpmsgs": "udp 信息",
|
||||
"udpmsgs": "udp信息",
|
||||
"mcmsgs": "组播信息",
|
||||
"udpmsg": "udp 信息",
|
||||
"udpmsg": "udp信息",
|
||||
"bcmsg": "广播信息",
|
||||
"mcmsg": "组播信息",
|
||||
"output": {
|
||||
"buffer": "缓冲模块",
|
||||
"buffer": "Buffer",
|
||||
"string": "字符串",
|
||||
"base64": "Base64编码字符串"
|
||||
},
|
||||
@@ -503,8 +514,8 @@
|
||||
},
|
||||
"tip": {
|
||||
"in": "提示:确保您的防火墙将允许数据进入",
|
||||
"out": "提示:如果要使用<code> msg.ip </code>和<code> msg.port </code>设置,请将地址和端口留空",
|
||||
"port": "端口已在使用: "
|
||||
"out": "提示:如果要使用<code>msg.ip</code>和<code>msg.port</code>设置,请将地址和端口留空",
|
||||
"port": "正在使用端口: "
|
||||
},
|
||||
"status": {
|
||||
"listener-at": "udp 监听器正在监听 __host__:__port__",
|
||||
@@ -520,66 +531,72 @@
|
||||
"access-error": "UDP 访问错误, 你可能需要root权限才能接入1024以下的端口",
|
||||
"error": "错误: __error__",
|
||||
"bad-mcaddress": "无效的组播地址",
|
||||
"interface": "必须是需要接口的 ip 地址",
|
||||
"ip-notset": "udp: ip 地址未设定",
|
||||
"interface": "必须是指定接口的IP地址",
|
||||
"ip-notset": "udp: IP地址未设定",
|
||||
"port-notset": "udp: 端口未设定",
|
||||
"port-invalid": "udp: 无效端口号码",
|
||||
"alreadyused": "udp: 端口已经在使用"
|
||||
"alreadyused": "udp: 端口已被占用"
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"label": {
|
||||
"property": "属性",
|
||||
"rule": "规矩"
|
||||
"rule": "规则",
|
||||
"repair" : "重建信息队列"
|
||||
},
|
||||
"and": "和",
|
||||
"and": "与",
|
||||
"checkall": "全选所有规则",
|
||||
"stopfirst": "接受第一条匹配信息后停止",
|
||||
"ignorecase": "忽视大小写",
|
||||
"ignorecase": "忽略大小写",
|
||||
"rules": {
|
||||
"btwn":"在之间",
|
||||
"cont":"包含",
|
||||
"regex":"匹配正则表达式",
|
||||
"true":"为真",
|
||||
"false":"为假",
|
||||
"null":"为空值",
|
||||
"nnull":"非空值",
|
||||
"null":"为空",
|
||||
"nnull":"非空",
|
||||
"head":"head",
|
||||
"tail":"tail",
|
||||
"index":"index between",
|
||||
"exp":"JSONata表达式",
|
||||
"else":"除此以外"
|
||||
},
|
||||
"errors": {
|
||||
"invalid-expr": "无效 JSONata 表达: __error__"
|
||||
"invalid-expr": "无效的JSONata表达式: __error__",
|
||||
"too-many" : "Switch节点中有太多待定信息"
|
||||
}
|
||||
},
|
||||
"change": {
|
||||
"label": {
|
||||
"rules": "规矩",
|
||||
"rule": "规矩",
|
||||
"rules": "规则",
|
||||
"rule": "规则",
|
||||
"set": "设定 __property__",
|
||||
"change": "改变 __property__",
|
||||
"change": "修改 __property__",
|
||||
"delete": "删除 __property__",
|
||||
"move": "移动 __property__",
|
||||
"changeCount": "改变: __count__ 条规矩",
|
||||
"regex": "用正则表达式"
|
||||
"changeCount": "修改: __count__条规矩",
|
||||
"regex": "使用正则表达式"
|
||||
},
|
||||
"action": {
|
||||
"set": "设定",
|
||||
"change": "更改",
|
||||
"change": "修改",
|
||||
"delete": "删除",
|
||||
"move": "转移",
|
||||
"to": "到",
|
||||
"search": "搜索",
|
||||
"replace": "更改为"
|
||||
"replace": "替代为"
|
||||
},
|
||||
"errors": {
|
||||
"invalid-from": "无效来源 ‘from’ 属性: __error__",
|
||||
"invalid-json": "无效 ‘to’ 属性",
|
||||
"invalid-expr": "无效 JSONata 表示: __error__"
|
||||
"invalid-from": "无效的'from'属性: __error__",
|
||||
"invalid-json": "无效的'to'JSON 属性",
|
||||
"invalid-expr": "无效的JSONata表达式: __error__"
|
||||
}
|
||||
},
|
||||
"range": {
|
||||
"label": {
|
||||
"action": "行为作用",
|
||||
"inputrange": "映射输入数据范围",
|
||||
"action": "操作",
|
||||
"inputrange": "映射输入数据",
|
||||
"resultrange": "至目标范围",
|
||||
"from": "从",
|
||||
"to": "到",
|
||||
@@ -591,26 +608,28 @@
|
||||
"maxout": "e.g. 255"
|
||||
},
|
||||
"scale": {
|
||||
"payload": "按比例 msg.payload",
|
||||
"payload": "按比例msg.payload",
|
||||
"limit": "按比例并设定界限至目标范围",
|
||||
"wrap": "按比例并包含在目标范围内"
|
||||
},
|
||||
"tip": "提示: 此节点仅对数字有效",
|
||||
"errors": {
|
||||
"notnumber": "不是一个数"
|
||||
"notnumber": "不是一个数字"
|
||||
}
|
||||
},
|
||||
"csv": {
|
||||
"label": {
|
||||
"columns": "列",
|
||||
"separator": "分隔符号",
|
||||
"c2o": "CSV 至对象选项",
|
||||
"o2c": "对象至 to CSV 选项",
|
||||
"separator": "分隔符",
|
||||
"c2o": "CSV至对象",
|
||||
"o2c": "对象至CSV",
|
||||
"input": "输入",
|
||||
"skip-s": "忽略前",
|
||||
"skip-e": "行",
|
||||
"firstrow": "第一行包含列名",
|
||||
"output": "输出",
|
||||
"includerow": "包含列名行",
|
||||
"newline": "新的一行"
|
||||
"newline": "换行符"
|
||||
},
|
||||
"placeholder": {
|
||||
"columns": "用逗号分割列名"
|
||||
@@ -625,8 +644,8 @@
|
||||
"other": "其他..."
|
||||
},
|
||||
"output": {
|
||||
"row": "每行包含一条信息",
|
||||
"array": "一条单独信息 [数组]"
|
||||
"row": "每行一条信息",
|
||||
"array": "仅一条信息 [数组]"
|
||||
},
|
||||
"newline": {
|
||||
"linux": "Linux (\\n)",
|
||||
@@ -634,8 +653,8 @@
|
||||
"windows": "Windows (\\r\\n)"
|
||||
},
|
||||
"errors": {
|
||||
"csv_js": "此节点仅处理 CSV 字符串或 js 对象",
|
||||
"obj_csv": "对象 -> CSV 转换未设定列模版"
|
||||
"csv_js": "此节点仅处理CSV字符串或JS对象",
|
||||
"obj_csv": "对象->CSV转换未设定列模版"
|
||||
}
|
||||
},
|
||||
"html": {
|
||||
@@ -644,13 +663,13 @@
|
||||
"output": "输出"
|
||||
},
|
||||
"output": {
|
||||
"html": "选定元素的 html 内容",
|
||||
"html": "选定元素的html内容",
|
||||
"text": "选定元素的纯文本内容",
|
||||
"attr": "选定元素的所有属性对象"
|
||||
"attr": "包含选定元素的所有属性的对象"
|
||||
},
|
||||
"format": {
|
||||
"single": "由一个单独信息包含一个数组",
|
||||
"multi": "由多条信息,每一条包含一个元素"
|
||||
"single": "一条信息 [数组]",
|
||||
"multi": "多条信息,每条一个元素"
|
||||
}
|
||||
},
|
||||
"json": {
|
||||
@@ -660,8 +679,15 @@
|
||||
"dropped-error": "转换有效负载失败"
|
||||
},
|
||||
"label": {
|
||||
"o2j": "对象至 JSON 选项",
|
||||
"pretty": "格式化 JSON 字符串"
|
||||
"o2j": "对象至JSON",
|
||||
"pretty": "格式化JSON字符串",
|
||||
"action": "操作",
|
||||
"property": "属性",
|
||||
"actions": {
|
||||
"toggle": "JSON字符串与对象互转",
|
||||
"str":"总是转为JSON字符串",
|
||||
"obj":"总是转为JS对象"
|
||||
}
|
||||
}
|
||||
},
|
||||
"yaml": {
|
||||
@@ -687,14 +713,14 @@
|
||||
"gpiopin": "GPIO",
|
||||
"selectpin": "选择引脚",
|
||||
"resistor": "电阻?",
|
||||
"readinitial": "在部署/重新启动时读取引脚的初始状态?",
|
||||
"readinitial": "在部署/重启时读取引脚的初始状态?",
|
||||
"type": "类型",
|
||||
"initpin": "初始化引脚状态?",
|
||||
"debounce": "去抖动",
|
||||
"freq": "频率",
|
||||
"button": "按钮",
|
||||
"pimouse": "Pi 鼠标",
|
||||
"pikeyboard": "Pi 键盘",
|
||||
"pimouse": "Pi鼠标",
|
||||
"pikeyboard": "Pi键盘",
|
||||
"left": "左",
|
||||
"right": "右",
|
||||
"middle": "中"
|
||||
@@ -705,21 +731,21 @@
|
||||
"pulldown": "下拉电阻"
|
||||
},
|
||||
"digout": "数字输出",
|
||||
"pwmout": "PWM 输出",
|
||||
"pwmout": "PWM输出",
|
||||
"servo": "伺服输出",
|
||||
"initpin0": "初始引脚电平 - 低 (0)",
|
||||
"initpin1": "初始引脚电平 - 高 (1)",
|
||||
"initpin0": "初始引脚电平 - 低(0)",
|
||||
"initpin1": "初始引脚电平 - 高(1)",
|
||||
"left": "左",
|
||||
"right": "右",
|
||||
"middle": "中",
|
||||
"any": "任何",
|
||||
"pinname": "引脚",
|
||||
"alreadyuse": "已经在用",
|
||||
"alreadyset": "已经设定为",
|
||||
"alreadyuse": "已被使用",
|
||||
"alreadyset": "已被设为",
|
||||
"tip": {
|
||||
"pin": "<b>引脚在使用</b>: ",
|
||||
"in": "提示: 仅接受数字输入 - 输出必须为 0 或 1.",
|
||||
"dig": "提示: 如用数字输出 - 输入必须为 0 或 1.",
|
||||
"pin": "<b>正在使用引脚</b>: ",
|
||||
"in": "提示: 仅接受数字输入 - 输出必须为0或1.",
|
||||
"dig": "提示: 如用数字输出 - 输入必须为0或1.",
|
||||
"pwm": "提示: 如用PWM输出 - 输入必须为0至100之间; 如用高频率可能会比预期占用更多CPU资源.",
|
||||
"ser": "<b>提示</b>: 如用伺服输出 - 输入必须为0至100之间. 50为中间值."
|
||||
},
|
||||
@@ -728,7 +754,7 @@
|
||||
"input": "输入",
|
||||
"pullup": "含有上拉电阻的输入",
|
||||
"pulldown": "含有下拉电阻的输入",
|
||||
"pwmout": "PWM 输出",
|
||||
"pwmout": "PWM输出",
|
||||
"servo": "伺服输出"
|
||||
},
|
||||
"status": {
|
||||
@@ -740,27 +766,27 @@
|
||||
"ignorenode": "忽略树莓派的特定节点",
|
||||
"version": "版本命令失败",
|
||||
"sawpitype": "查看Pi类型",
|
||||
"libnotfound": "找不到树莓派 RPi.GPIO python库",
|
||||
"alreadyset": "GPIO 引脚 __pin__ 已经被设定为类型: __type__",
|
||||
"invalidpin": "无效 GPIO 引脚",
|
||||
"libnotfound": "找不到树莓派RPi.GPIO的python库",
|
||||
"alreadyset": "GPIO引脚 __pin__ 已经被设定为类型: __type__",
|
||||
"invalidpin": "无效GPIO引脚",
|
||||
"invalidinput": "无效输入",
|
||||
"needtobeexecutable": "__command__ 需要为可运行命令",
|
||||
"mustbeexecutable": "nrgpio 需要为可运行",
|
||||
"commandnotfound": "nrgpio 命令不存在",
|
||||
"commandnotexecutable": "nrgpio 命令无法运行",
|
||||
"needtobeexecutable": "__command__须为可运行命令",
|
||||
"mustbeexecutable": "nrgpio须为可运行",
|
||||
"commandnotfound": "nrgpio命令不存在",
|
||||
"commandnotexecutable": "nrgpio命令不可运行",
|
||||
"error": "错误: __error__",
|
||||
"pythoncommandnotfound": "nrpgio python 命令不运行"
|
||||
"pythoncommandnotfound": "nrpgio python命令未处于运行状态"
|
||||
}
|
||||
},
|
||||
"tail": {
|
||||
"label": {
|
||||
"filename": "文件名",
|
||||
"type": "文件类型",
|
||||
"splitlines": "拆分线 \\n?"
|
||||
"splitlines": "以\\n来拆分行?"
|
||||
},
|
||||
"action": {
|
||||
"text": "文本 - 返回字符串",
|
||||
"binary": "二进制 - 返回缓冲区"
|
||||
"binary": "二进制 - 返回Buffer"
|
||||
},
|
||||
"errors": {
|
||||
"windowsnotsupport": "Windows目前不支持."
|
||||
@@ -770,7 +796,7 @@
|
||||
"label": {
|
||||
"filename": "文件名",
|
||||
"action": "行为",
|
||||
"addnewline": "向每个有效载荷添加换行符(\\ n)?",
|
||||
"addnewline": "向每个有效载荷添加换行符(\\n)?",
|
||||
"createdir": "创建目录(如果不存在)?",
|
||||
"outputas": "输出",
|
||||
"breakchunks": "分拆成块",
|
||||
@@ -781,14 +807,14 @@
|
||||
},
|
||||
"action": {
|
||||
"append": "追加至文件",
|
||||
"overwrite": "改写文件",
|
||||
"overwrite": "复写文件",
|
||||
"delete": "删除文件"
|
||||
},
|
||||
"output": {
|
||||
"utf8": "一条单独 utf8 字符串",
|
||||
"buffer": "一条单独缓冲区对象",
|
||||
"utf8": "一个utf8字符串",
|
||||
"buffer": "一个Buffer对象",
|
||||
"lines": "每行一条信息",
|
||||
"stream": "缓冲区流"
|
||||
"stream": "一个Buffer流"
|
||||
},
|
||||
"status": {
|
||||
"wrotefile": "写入至文件: __file__",
|
||||
@@ -806,41 +832,99 @@
|
||||
"tip": "提示: 文件名应该是绝对路径,否则它将相对于Node-RED进程的工作目录。"
|
||||
},
|
||||
"split": {
|
||||
"intro":"分裂 <code>msg.payload</code> 基于类型:",
|
||||
"intro":"基于以下类型拆分<code>msg.payload</code>:",
|
||||
"object":"<b>对象</b>",
|
||||
"objectSend":"发送每个键/值对的消息",
|
||||
"strBuff":"<b>字符串</b> / <b>缓冲区</b>",
|
||||
"objectSend":"每个键值对作为单个消息发送",
|
||||
"strBuff":"<b>字符串</b> / <b>Buffer</b>",
|
||||
"array":"<b>数组</b>",
|
||||
"splitUsing":"拆分使用",
|
||||
"splitLength":"固定长度",
|
||||
"stream":"处理为消息流",
|
||||
"stream":"作为消息流处理",
|
||||
"addname":" 复制键到 "
|
||||
},
|
||||
"join":{
|
||||
"mode":{
|
||||
"mode":"模式",
|
||||
"auto":"自动",
|
||||
"merge":"合并序列",
|
||||
"reduce":"缩减序列",
|
||||
"custom":"手动"
|
||||
},
|
||||
"combine":"结合每一个",
|
||||
"create":"创建输出",
|
||||
"combine":"合并每个",
|
||||
"create":"输出为",
|
||||
"type":{
|
||||
"string":"字符串",
|
||||
"array":"数组",
|
||||
"buffer":"缓冲区",
|
||||
"object":"键/值对象",
|
||||
"buffer":"Buffer",
|
||||
"object":"键值对对象",
|
||||
"merged":"合并对象"
|
||||
},
|
||||
"using":"使用数值",
|
||||
"key":"当作键",
|
||||
"using":"使用此值",
|
||||
"key":"作为键",
|
||||
"joinedUsing":"合并符号",
|
||||
"send":"发送信息:",
|
||||
"afterCount":"当达到一定数目的信息部件时",
|
||||
"count":"数目",
|
||||
"afterCount":"达到一定数量的信息时",
|
||||
"count":"数量",
|
||||
"subsequent":"和每个后续的消息",
|
||||
"afterTimeout":"第一条消息的超时后",
|
||||
"afterTimeout":"第一条消息的若干时间后",
|
||||
"seconds":"秒",
|
||||
"complete":"在使用<code> msg.complete </ code>属性设置的消息后",
|
||||
"tip":"此模式假定此节点与 <i>split</i> 或者接收到的消息将具有正确配置的 <code>msg.parts</code> 属性."
|
||||
"complete":"在收到存在<code>msg.complete</code>的消息后",
|
||||
"tip":"此模式假定此节点与<i>split</i>相连, 或者接收到的消息有正确配置的<code>msg.parts</code>属性.",
|
||||
"too-many" : "join节点中有太多待定信息",
|
||||
"merge": {
|
||||
"topics-label":"合并主题",
|
||||
"topics":"主题",
|
||||
"topic" : "主题",
|
||||
"on-change":"当收到一个新主题时发送已合并信息"
|
||||
},
|
||||
"reduce": {
|
||||
"exp": "Reduce表达式",
|
||||
"exp-value": "exp",
|
||||
"init": "初始值",
|
||||
"right": "反向求值(从后往前)",
|
||||
"fixup": "Fix-up exp"
|
||||
},
|
||||
"errors": {
|
||||
"invalid-expr": "无效的JSONata表达式: __error__"
|
||||
}
|
||||
},
|
||||
"sort" : {
|
||||
"target" : "排序属性",
|
||||
"seq" : "信息队列",
|
||||
"key" : "键值",
|
||||
"elem" : "元素值",
|
||||
"order" : "顺序",
|
||||
"ascending" : "升序",
|
||||
"descending" : "降序",
|
||||
"as-number" : "作为数值",
|
||||
"invalid-exp" : "sort节点中存在无效的JSONata表达式",
|
||||
"too-many" : "sort节点中有太多待定信息",
|
||||
"clear" : "清空sort节点中的待定信息"
|
||||
},
|
||||
"batch" : {
|
||||
"mode": {
|
||||
"label" : "模式",
|
||||
"num-msgs" : "按指定数量分组",
|
||||
"interval" : "按时间间隔分组",
|
||||
"concat" : "按主题分组"
|
||||
},
|
||||
"count": {
|
||||
"label" : "分组数量",
|
||||
"overlap" : "队末队首重叠数量",
|
||||
"count" : "数量",
|
||||
"invalid" : "无效的分组数量或重叠数量"
|
||||
},
|
||||
"interval": {
|
||||
"label" : "时间间隔",
|
||||
"seconds" : "秒",
|
||||
"empty" : "无数据到达时发送空信息"
|
||||
},
|
||||
"concat": {
|
||||
"topics-label": "主题",
|
||||
"topic" : "主题"
|
||||
},
|
||||
"too-many" : "batch节点中有太多待定信息",
|
||||
"unexpected" : "未知模式",
|
||||
"no-parts" : "信息中没有parts属性"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@
|
||||
},
|
||||
icon: "switch.png",
|
||||
label: function() {
|
||||
return this.name||"switch";
|
||||
return this.name||this._("swicth.switch");
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
@@ -199,7 +199,7 @@
|
||||
rule.t = 'eq';
|
||||
}
|
||||
if (!opt.hasOwnProperty('i')) {
|
||||
opt._i = Math.floor((0x99999-0x10000)*Math.random()).toString(16);
|
||||
opt._i = Math.floor((0x99999-0x10000)*Math.random()).toString();
|
||||
}
|
||||
container.css({
|
||||
overflow: 'hidden',
|
||||
|
||||
@@ -76,7 +76,8 @@
|
||||
outputs: 1,
|
||||
icon: "range.png",
|
||||
label: function() {
|
||||
return this.name || "range";
|
||||
if (this.minout !== "" && this.maxout !== "") { return this.name||this.minout + " - " + this.maxout; }
|
||||
else { return this.name||this._("range.range"); }
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name ? "node_label_italic" : "";
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
outputs:1,
|
||||
icon: "split.png",
|
||||
label: function() {
|
||||
return this.name||"split";
|
||||
return this.name||this._("split.split");
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
@@ -367,7 +367,7 @@
|
||||
outputs:1,
|
||||
icon: "join.png",
|
||||
label: function() {
|
||||
return this.name||"join";
|
||||
return this.name||this._("join.join");
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
outputs:1,
|
||||
icon: "sort.png",
|
||||
label: function() {
|
||||
return this.name || "sort";
|
||||
return this.name||this._("sort.sort");
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name ? "node_label_italic" : "";
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
outputs:1,
|
||||
icon: "batch.png",
|
||||
label: function() {
|
||||
return this.name || "batch";
|
||||
return this.name||this._("batch.batch");;
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name ? "node_label_italic" : "";
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
outputs:1,
|
||||
icon: "file.png",
|
||||
label: function() {
|
||||
return this.name||this.filename||"tail";
|
||||
return this.name||this.filename||this._("tail.tail");
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
|
||||
26
red.js
26
red.js
@@ -31,8 +31,10 @@ var app = express();
|
||||
|
||||
var settingsFile;
|
||||
var flowFile;
|
||||
var readonly;
|
||||
|
||||
var knownOpts = {
|
||||
"credentialSecret": String,
|
||||
"help": Boolean,
|
||||
"port": Number,
|
||||
"settings": [path],
|
||||
@@ -41,6 +43,7 @@ var knownOpts = {
|
||||
"verbose": Boolean
|
||||
};
|
||||
var shortHands = {
|
||||
"k":["--credentialSecret"],
|
||||
"?":["--help"],
|
||||
"p":["--port"],
|
||||
"s":["--settings"],
|
||||
@@ -59,9 +62,11 @@ var parsedArgs = nopt(knownOpts,shortHands,process.argv,2)
|
||||
if (parsedArgs.help) {
|
||||
console.log("Node-RED v"+RED.version());
|
||||
console.log("Usage: node-red [-v] [-?] [--settings settings.js] [--userDir DIR]");
|
||||
console.log(" [--port PORT] [--title TITLE] [flows.json]");
|
||||
console.log(" [--port PORT] [--credentialSecret SECRET_KEY]");
|
||||
console.log(" [--title TITLE] [flows.json]");
|
||||
console.log("");
|
||||
console.log("Options:");
|
||||
console.log(" -k, --credentialSecret SECRET_KEY key to unlock credentials file");
|
||||
console.log(" -p, --port PORT port to listen on");
|
||||
console.log(" -s, --settings FILE use specified settings file");
|
||||
console.log(" --title TITLE process window title");
|
||||
@@ -101,8 +106,15 @@ if (parsedArgs.settings) {
|
||||
var settingsStat = fs.statSync(defaultSettings);
|
||||
if (settingsStat.mtime.getTime() <= settingsStat.ctime.getTime()) {
|
||||
// Default settings file has not been modified - safe to copy
|
||||
fs.copySync(defaultSettings,userSettingsFile);
|
||||
settingsFile = userSettingsFile;
|
||||
try {
|
||||
fs.copySync(defaultSettings,userSettingsFile);
|
||||
settingsFile = userSettingsFile;
|
||||
}
|
||||
catch (err) {
|
||||
console.log("Can't copy settings file.");
|
||||
settingsFile = defaultSettings;
|
||||
readonly = true;
|
||||
}
|
||||
} else {
|
||||
// Use default settings.js as it has been modified
|
||||
settingsFile = defaultSettings;
|
||||
@@ -114,6 +126,10 @@ if (parsedArgs.settings) {
|
||||
try {
|
||||
var settings = require(settingsFile);
|
||||
settings.settingsFile = settingsFile;
|
||||
if (readonly === true) {
|
||||
console.log("Setting to read Only mode.");
|
||||
settings.readOnly = true;
|
||||
}
|
||||
} catch(err) {
|
||||
console.log("Error loading settings file: "+settingsFile)
|
||||
if (err.code == 'MODULE_NOT_FOUND') {
|
||||
@@ -126,6 +142,10 @@ try {
|
||||
process.exit();
|
||||
}
|
||||
|
||||
if (parsedArgs.credentialSecret) {
|
||||
settings.credentialSecret = parsedArgs.credentialSecret;
|
||||
}
|
||||
|
||||
if (parsedArgs.verbose) {
|
||||
settings.verbose = true;
|
||||
}
|
||||
|
||||
@@ -16,11 +16,9 @@
|
||||
|
||||
var log;
|
||||
var redNodes;
|
||||
var settings;
|
||||
|
||||
module.exports = {
|
||||
init: function(runtime) {
|
||||
settings = runtime.settings;
|
||||
redNodes = runtime.nodes;
|
||||
log = runtime.log;
|
||||
},
|
||||
|
||||
@@ -16,11 +16,9 @@
|
||||
|
||||
var log;
|
||||
var redNodes;
|
||||
var settings;
|
||||
|
||||
module.exports = {
|
||||
init: function(runtime) {
|
||||
settings = runtime.settings;
|
||||
redNodes = runtime.nodes;
|
||||
log = runtime.log;
|
||||
},
|
||||
|
||||
@@ -18,17 +18,13 @@ var when = require("when");
|
||||
var apiUtils = require("../util");
|
||||
var redNodes;
|
||||
var log;
|
||||
var i18n;
|
||||
var settings;
|
||||
var events;
|
||||
|
||||
module.exports = {
|
||||
init: function(runtime) {
|
||||
redNodes = runtime.nodes;
|
||||
log = runtime.log;
|
||||
i18n = runtime.i18n;
|
||||
settings = runtime.settings;
|
||||
events = runtime.events;
|
||||
},
|
||||
getAll: function(req,res) {
|
||||
if (req.get("accept") == "application/json") {
|
||||
@@ -72,11 +68,6 @@ module.exports = {
|
||||
return;
|
||||
}
|
||||
promise.then(function(info) {
|
||||
if (isUpgrade) {
|
||||
events.emit("runtime-event",{id:"node/upgraded",retain:false,payload:{module:node.module,version:node.version}});
|
||||
} else {
|
||||
events.emit("runtime-event",{id:"node/added",retain:false,payload:info.nodes});
|
||||
}
|
||||
if (node.module) {
|
||||
log.audit({event: "nodes.install",module:node.module,version:node.version},req);
|
||||
res.json(info);
|
||||
@@ -114,7 +105,6 @@ module.exports = {
|
||||
}
|
||||
|
||||
promise.then(function(list) {
|
||||
events.emit("runtime-event",{id:"node/removed",retain:false,payload:list});
|
||||
log.audit({event: "nodes.remove",module:mod},req);
|
||||
res.status(204).end();
|
||||
}).catch(function(err) {
|
||||
@@ -248,21 +238,6 @@ function putNode(node, enabled) {
|
||||
} else {
|
||||
promise = redNodes.disableNode(node.id);
|
||||
}
|
||||
|
||||
return promise.then(function(info) {
|
||||
if (info.enabled === enabled && !info.err) {
|
||||
events.emit("runtime-event",{id:"node/"+(enabled?"enabled":"disabled"),retain:false,payload:info});
|
||||
log.info(" "+log._("api.nodes."+(enabled?"enabled":"disabled")));
|
||||
for (var i=0;i<info.types.length;i++) {
|
||||
log.info(" - "+info.types[i]);
|
||||
}
|
||||
} else if (enabled && info.err) {
|
||||
log.warn(log._("api.nodes.error-enable"));
|
||||
log.warn(" - "+info.name+" : "+info.err);
|
||||
}
|
||||
return info;
|
||||
});
|
||||
}
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@
|
||||
"managePalette": "管理面板"
|
||||
},
|
||||
"library": {
|
||||
"openLibrary": "“打开库...",
|
||||
"openLibrary": "打开库...",
|
||||
"saveToLibrary": "保存到库...",
|
||||
"typeLibrary": "__type__类型库",
|
||||
"unnamedType": "无名__type__",
|
||||
|
||||
@@ -194,5 +194,25 @@
|
||||
"$globalContext": {
|
||||
"args": "string",
|
||||
"desc": "获取全局上下文的属性。"
|
||||
},
|
||||
"$pad": {
|
||||
"args": "string, width [, char]",
|
||||
"desc": "根据需要,向字符串`string`的副本中填充文字使该字符串的字数达到`width`的绝对值并返回填充文字后的字符串。\n\n如果`width`的值为正,则向字符串`string`的右侧填充文字,如果`width`为负,则向字符串`string`的左侧填充文字。\n\n可选参数`char`用来指定填充的文字。如果未指定该参数,则填充空白文字。"
|
||||
},
|
||||
"$fromMillis": {
|
||||
"args": "number",
|
||||
"desc": "将表示从UNIX时间 (1970年1月1日 UTC/GMT的午夜)开始到现在的毫秒数的数值转换成ISO 8601形式时间戳的字符串。"
|
||||
},
|
||||
"$formatNumber": {
|
||||
"args": "number, picture [, options]",
|
||||
"desc": "将`number`转换成具有`picture`所指定的数值格式的字符串。\n\n此函数的功能与XPath F&O 3.1规格中定义的XPath/XQuery函数的fn:format-number功能相一致。参数`picture`用于指定数值的转换格式,其语法与fn:format-number中的定义一致。\n\n可选的第三参数`options`用来覆盖默认的局部环境格式,如小数点分隔符。如果指定该参数,那么该参数必须是包含name/value对的对象,并且name/value对必须符合XPath F&O 3.1规格中记述的数值格式。"
|
||||
},
|
||||
"$formatBase": {
|
||||
"args": "number [, radix]",
|
||||
"desc": "将`number`变换为以参数`radix`的值为基数形式的字符串。如果不指定`radix`的值,则默认基数为10。指定的`radix`值必须在2~36之间,否则抛出错误。"
|
||||
},
|
||||
"$toMillis": {
|
||||
"args": "timestamp",
|
||||
"desc": "将ISO 8601格式的字符串`timestamp`转换为从UNIX时间 (1970年1月1日 UTC/GMT的午夜)开始到现在的毫秒数。如果该字符串的格式不正确,则抛出错误。"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,13 +16,11 @@
|
||||
|
||||
var express = require("express");
|
||||
var runtime;
|
||||
var settings;
|
||||
var needsPermission = require("../../auth").needsPermission;
|
||||
|
||||
module.exports = {
|
||||
init: function(_runtime) {
|
||||
runtime = _runtime;
|
||||
settings = runtime.settings;
|
||||
},
|
||||
app: function() {
|
||||
var app = express();
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
var express = require("express");
|
||||
var os = require("os");
|
||||
var runtime;
|
||||
var settings;
|
||||
var needsPermission = require("../auth").needsPermission;
|
||||
|
||||
function getUsername(userObj) {
|
||||
@@ -31,7 +30,6 @@ function getUsername(userObj) {
|
||||
module.exports = {
|
||||
init: function(_runtime) {
|
||||
runtime = _runtime;
|
||||
settings = runtime.settings;
|
||||
},
|
||||
app: function() {
|
||||
var app = express();
|
||||
|
||||
@@ -24,8 +24,6 @@ var cors = require('cors');
|
||||
var auth = require("./auth");
|
||||
var apiUtil = require("./util");
|
||||
|
||||
var i18n;
|
||||
var log;
|
||||
var adminApp;
|
||||
var server;
|
||||
var runtime;
|
||||
@@ -35,8 +33,6 @@ function init(_server,_runtime) {
|
||||
server = _server;
|
||||
runtime = _runtime;
|
||||
var settings = runtime.settings;
|
||||
i18n = runtime.i18n;
|
||||
log = runtime.log;
|
||||
if (settings.httpAdminRoot !== false) {
|
||||
apiUtil.init(runtime);
|
||||
adminApp = express();
|
||||
|
||||
@@ -83,7 +83,8 @@
|
||||
"credentials": {
|
||||
"error":"Error loading credentials: __message__",
|
||||
"error-saving":"Error saving credentials: __message__",
|
||||
"not-registered": "Credential type '__type__' is not registered"
|
||||
"not-registered": "Credential type '__type__' is not registered",
|
||||
"system-key-warning": "\n\n---------------------------------------------------------------------\nYour flow credentials file is encrypted using a system-generated key.\n\nIf the system-generated key is lost for any reason, your credentials\nfile will not be recoverable, you will have to delete it and re-enter\nyour credentials.\n\nYou should set your own key using the 'credentialSecret' option in\nyour settings file. Node-RED will then re-encrypt your credentials\nfile using your chosen key the next time you deploy a change.\n---------------------------------------------------------------------\n"
|
||||
},
|
||||
"flows": {
|
||||
"registered-missing": "Missing type registered: __type__",
|
||||
|
||||
@@ -201,6 +201,9 @@ var api = module.exports = {
|
||||
encryptedCredentials = credentials;
|
||||
}
|
||||
log.debug("red/runtime/nodes/credentials.load : keyType="+encryptionKeyType);
|
||||
if (encryptionKeyType === 'system') {
|
||||
log.warn(log._("nodes.credentials.system-key-warning"));
|
||||
}
|
||||
return setupEncryptionPromise.then(function() {
|
||||
var clearInvalidFlag = false;
|
||||
if (credentials.hasOwnProperty("$")) {
|
||||
|
||||
@@ -104,7 +104,43 @@ function init(runtime) {
|
||||
|
||||
function disableNode(id) {
|
||||
flows.checkTypeInUse(id);
|
||||
return registry.disableNode(id);
|
||||
return registry.disableNode(id).then(function(info) {
|
||||
reportNodeStateChange(info,false);
|
||||
return info;
|
||||
});
|
||||
}
|
||||
|
||||
function enableNode(id) {
|
||||
return registry.enableNode(id).then(function(info) {
|
||||
reportNodeStateChange(info,true);
|
||||
return info;
|
||||
});
|
||||
}
|
||||
|
||||
function reportNodeStateChange(info,enabled) {
|
||||
if (info.enabled === enabled && !info.err) {
|
||||
events.emit("runtime-event",{id:"node/"+(enabled?"enabled":"disabled"),retain:false,payload:info});
|
||||
log.info(" "+log._("api.nodes."+(enabled?"enabled":"disabled")));
|
||||
for (var i=0;i<info.types.length;i++) {
|
||||
log.info(" - "+info.types[i]);
|
||||
}
|
||||
} else if (enabled && info.err) {
|
||||
log.warn(log._("api.nodes.error-enable"));
|
||||
log.warn(" - "+info.name+" : "+info.err);
|
||||
}
|
||||
}
|
||||
|
||||
function installModule(module,version) {
|
||||
var ex_module = registry.getModuleInfo(module);
|
||||
var isUpgrade = !!ex_module;
|
||||
return registry.installModule(module,version).then(function(info) {
|
||||
if (isUpgrade) {
|
||||
events.emit("runtime-event",{id:"node/upgraded",retain:false,payload:{module:module,version:version}});
|
||||
} else {
|
||||
events.emit("runtime-event",{id:"node/added",retain:false,payload:info.nodes});
|
||||
}
|
||||
return info;
|
||||
});
|
||||
}
|
||||
|
||||
function uninstallModule(module) {
|
||||
@@ -115,7 +151,10 @@ function uninstallModule(module) {
|
||||
for (var i=0;i<info.nodes.length;i++) {
|
||||
flows.checkTypeInUse(module+"/"+info.nodes[i].name);
|
||||
}
|
||||
return registry.uninstallModule(module);
|
||||
return registry.uninstallModule(module).then(function(list) {
|
||||
events.emit("runtime-event",{id:"node/removed",retain:false,payload:list});
|
||||
return list;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,10 +169,10 @@ module.exports = {
|
||||
eachNode: flows.eachNode,
|
||||
|
||||
paletteEditorEnabled: registry.paletteEditorEnabled,
|
||||
installModule: registry.installModule,
|
||||
installModule: installModule,
|
||||
uninstallModule: uninstallModule,
|
||||
|
||||
enableNode: registry.enableNode,
|
||||
enableNode: enableNode,
|
||||
disableNode: disableNode,
|
||||
|
||||
// Node type registry
|
||||
|
||||
@@ -376,9 +376,18 @@ function addModule(module) {
|
||||
}
|
||||
|
||||
function loadNodeHelp(node,lang) {
|
||||
var dir = path.dirname(node.template);
|
||||
var base = path.basename(node.template);
|
||||
var localePath = path.join(dir,"locales",lang,base);
|
||||
var localePath = undefined;
|
||||
if (node.module === 'node-red') {
|
||||
var cat_dir = path.dirname(node.template);
|
||||
var cat = path.basename(cat_dir);
|
||||
var dir = path.dirname(cat_dir);
|
||||
localePath = path.join(dir, "locales", lang, cat, base)
|
||||
}
|
||||
else {
|
||||
var dir = path.dirname(node.template);
|
||||
localePath = path.join(dir,"locales",lang,base);
|
||||
}
|
||||
try {
|
||||
// TODO: make this async
|
||||
var content = fs.readFileSync(localePath, "utf8")
|
||||
|
||||
@@ -276,10 +276,12 @@ Project.prototype.update = function (user, data) {
|
||||
saveREADME = true;
|
||||
this.description = data.description;
|
||||
}
|
||||
|
||||
if (data.hasOwnProperty('dependencies')) {
|
||||
savePackage = true;
|
||||
this.package.dependencies = data.dependencies;
|
||||
}
|
||||
|
||||
if (data.hasOwnProperty('summary')) {
|
||||
savePackage = true;
|
||||
this.package.description = data.summary;
|
||||
@@ -332,6 +334,7 @@ Project.prototype.update = function (user, data) {
|
||||
if (data.files.hasOwnProperty('flow') && this.package['node-red'].settings.flowFile !== data.files.flow) {
|
||||
this.paths.flowFile = data.files.flow;
|
||||
this.package['node-red'].settings.flowFile = data.files.flow;
|
||||
this.package.scripts = {"start":"node-red -u . " + data.files.flow};
|
||||
savePackage = true;
|
||||
flowFilesChanged = true;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,8 @@ module.exports = {
|
||||
"node-red": {
|
||||
"settings": {
|
||||
}
|
||||
}
|
||||
},
|
||||
"scripts": {}
|
||||
};
|
||||
if (project.files) {
|
||||
if (project.files.flow) {
|
||||
@@ -43,5 +44,5 @@ module.exports = {
|
||||
|
||||
return content;
|
||||
},
|
||||
".gitignore": function() { return "*.backup" ;}
|
||||
".gitignore": function() { return "*.backup\n.config.json\n" ;}
|
||||
}
|
||||
|
||||
@@ -514,11 +514,6 @@ function saveFlows(flows) {
|
||||
}
|
||||
|
||||
flowsFileExists = true;
|
||||
|
||||
try {
|
||||
fs.renameSync(flowsFullPath,flowsFileBackup);
|
||||
} catch(err) {
|
||||
}
|
||||
|
||||
var flowData;
|
||||
|
||||
@@ -527,7 +522,7 @@ function saveFlows(flows) {
|
||||
} else {
|
||||
flowData = JSON.stringify(flows);
|
||||
}
|
||||
return util.writeFile(flowsFullPath, flowData);
|
||||
return util.writeFile(flowsFullPath, flowData, flowsFileBackup);
|
||||
}
|
||||
|
||||
function getCredentials() {
|
||||
@@ -539,17 +534,13 @@ function saveCredentials(credentials) {
|
||||
return when.resolve();
|
||||
}
|
||||
|
||||
try {
|
||||
fs.renameSync(credentialsFile,credentialsFileBackup);
|
||||
} catch(err) {
|
||||
}
|
||||
var credentialData;
|
||||
if (settings.flowFilePretty) {
|
||||
credentialData = JSON.stringify(credentials,null,4);
|
||||
} else {
|
||||
credentialData = JSON.stringify(credentials);
|
||||
}
|
||||
return util.writeFile(credentialsFile, credentialData);
|
||||
return util.writeFile(credentialsFile, credentialData, credentialsFileBackup);
|
||||
}
|
||||
|
||||
function getFlowFilename() {
|
||||
|
||||
@@ -22,12 +22,14 @@ var log = require("../../log");
|
||||
var util = require("./util");
|
||||
|
||||
var globalSettingsFile;
|
||||
var globalSettingsBackup;
|
||||
var settings;
|
||||
|
||||
module.exports = {
|
||||
init: function(_settings) {
|
||||
settings = _settings;
|
||||
globalSettingsFile = fspath.join(settings.userDir,".config.json");
|
||||
globalSettingsBackup = fspath.join(settings.userDir,".config.json.backup");
|
||||
},
|
||||
getSettings: function() {
|
||||
return when.promise(function(resolve,reject) {
|
||||
@@ -47,6 +49,6 @@ module.exports = {
|
||||
if (settings.readOnly) {
|
||||
return when.resolve();
|
||||
}
|
||||
return util.writeFile(globalSettingsFile,JSON.stringify(newSettings,null,1));
|
||||
return util.writeFile(globalSettingsFile,JSON.stringify(newSettings,null,1),globalSettingsBackup);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,16 @@ module.exports = {
|
||||
* This forces a fsync before completing to ensure
|
||||
* the write hits disk.
|
||||
*/
|
||||
writeFile: function(path,content) {
|
||||
writeFile: function(path,content,backupPath) {
|
||||
if (backupPath) {
|
||||
try {
|
||||
// console.log(path);
|
||||
// console.log(backupPath);
|
||||
fs.renameSync(path,backupPath);
|
||||
} catch(err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
return when.promise(function(resolve,reject) {
|
||||
var stream = fs.createWriteStream(path);
|
||||
stream.on('open',function(fd) {
|
||||
|
||||
@@ -204,7 +204,6 @@ module.exports = {
|
||||
|
||||
functionGlobalContext: {
|
||||
// os:require('os'),
|
||||
// octalbonescript:require('octalbonescript'),
|
||||
// jfive:require("johnny-five"),
|
||||
// j5board:require("johnny-five").Board({repl:false})
|
||||
},
|
||||
|
||||
@@ -527,6 +527,50 @@ describe('function node', function() {
|
||||
}
|
||||
});
|
||||
});
|
||||
it('should log a Debug Message', function (done) {
|
||||
var flow = [{id: "n1", type: "function", wires: [["n2"]], func: "node.debug('test');"}];
|
||||
helper.load(functionNode, flow, function () {
|
||||
var n1 = helper.getNode("n1");
|
||||
n1.receive({payload: "foo", topic: "bar"});
|
||||
try {
|
||||
helper.log().called.should.be.true();
|
||||
var logEvents = helper.log().args.filter(function (evt) {
|
||||
return evt[0].type == "function";
|
||||
});
|
||||
logEvents.should.have.length(1);
|
||||
var msg = logEvents[0][0];
|
||||
msg.should.have.property('level', helper.log().DEBUG);
|
||||
msg.should.have.property('id', 'n1');
|
||||
msg.should.have.property('type', 'function');
|
||||
msg.should.have.property('msg', 'test');
|
||||
done();
|
||||
} catch (err) {
|
||||
done(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
it('should log a Trace Message', function (done) {
|
||||
var flow = [{id: "n1", type: "function", wires: [["n2"]], func: "node.trace('test');"}];
|
||||
helper.load(functionNode, flow, function () {
|
||||
var n1 = helper.getNode("n1");
|
||||
n1.receive({payload: "foo", topic: "bar"});
|
||||
try {
|
||||
helper.log().called.should.be.true();
|
||||
var logEvents = helper.log().args.filter(function (evt) {
|
||||
return evt[0].type == "function";
|
||||
});
|
||||
logEvents.should.have.length(1);
|
||||
var msg = logEvents[0][0];
|
||||
msg.should.have.property('level', helper.log().TRACE);
|
||||
msg.should.have.property('id', 'n1');
|
||||
msg.should.have.property('type', 'function');
|
||||
msg.should.have.property('msg', 'test');
|
||||
done();
|
||||
} catch (err) {
|
||||
done(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
it('should log a Warning Message', function (done) {
|
||||
var flow = [{id: "n1", type: "function", wires: [["n2"]], func: "node.warn('test');"}];
|
||||
helper.load(functionNode, flow, function () {
|
||||
|
||||
@@ -29,37 +29,42 @@ describe('template node', function() {
|
||||
});
|
||||
|
||||
|
||||
it('should modify payload', function(done) {
|
||||
it('should modify payload using node-configured template', function(done) {
|
||||
var flow = [{id:"n1", type:"template", field:"payload", template:"payload={{payload}}",wires:[["n2"]]},{id:"n2",type:"helper"}];
|
||||
helper.load(templateNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
msg.should.have.property('topic', 'bar');
|
||||
msg.should.have.property('payload', 'payload=foo');
|
||||
msg.should.have.property('template', '{{payload}}');
|
||||
done();
|
||||
try {
|
||||
msg.should.have.property('topic', 'bar');
|
||||
msg.should.have.property('payload', 'payload=foo');
|
||||
msg.should.have.property('template', 'this should be ignored as the node has its own template {{payload}}');
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err);
|
||||
}
|
||||
});
|
||||
n1.receive({payload:"foo",topic: "bar", template: "{{payload}}"});
|
||||
n1.receive({payload:"foo",topic: "bar", template: "this should be ignored as the node has its own template {{payload}}"});
|
||||
});
|
||||
});
|
||||
|
||||
it('should modify template from msg.template', function(done) {
|
||||
var flow = [{id:"n1", type:"template", field:"template", template:"",wires:[["n2"]]},{id:"n2",type:"helper"}];
|
||||
it('should modify the configured property using msg.template', function(done) {
|
||||
var flow = [{id:"n1", type:"template", field:"randomProperty", template:"",wires:[["n2"]]},{id:"n2",type:"helper"}];
|
||||
helper.load(templateNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
msg.should.have.property('topic', 'bar');
|
||||
msg.should.have.property('payload', 'foo');
|
||||
msg.should.have.property('template', 'payload=foo');
|
||||
msg.should.have.property('template', 'payload={{payload}}');
|
||||
msg.should.have.property('randomProperty', 'payload=foo');
|
||||
done();
|
||||
});
|
||||
n1.receive({payload:"foo", topic: "bar", template: "payload={{payload}}"});
|
||||
});
|
||||
});
|
||||
|
||||
it('should modify payload from msg.template', function(done) {
|
||||
it('should be able to overwrite msg.template using the template from msg.template', function(done) {
|
||||
var flow = [{id:"n1", type:"template", field:"payload", template:"",wires:[["n2"]]},{id:"n2",type:"helper"}];
|
||||
helper.load(templateNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
@@ -74,6 +79,40 @@ describe('template node', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should modify payload from msg.template', function(done) {
|
||||
var flow = [{id:"n1", type:"template", field:"payload", template:"",wires:[["n2"]]},{id:"n2",type:"helper"}];
|
||||
helper.load(templateNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
var received = [];
|
||||
n2.on("input", function(msg) {
|
||||
try {
|
||||
received.push(msg);
|
||||
if (received.length === 3) {
|
||||
received[0].should.have.property('topic', 'bar');
|
||||
received[0].should.have.property('payload', 'topic=bar');
|
||||
received[0].should.have.property('template', 'topic={{topic}}');
|
||||
|
||||
received[1].should.have.property('topic', 'another bar');
|
||||
received[1].should.have.property('payload', 'topic=another bar');
|
||||
received[1].should.have.property('template', 'topic={{topic}}');
|
||||
|
||||
received[2].should.have.property('topic', 'bar');
|
||||
received[2].should.have.property('payload', 'payload=foo');
|
||||
received[2].should.have.property('template', 'payload={{payload}}');
|
||||
done();
|
||||
}
|
||||
} catch(err) {
|
||||
done(err);
|
||||
}
|
||||
});
|
||||
n1.receive({payload:"foo", topic: "bar", template: "topic={{topic}}"});
|
||||
n1.receive({payload:"foo", topic: "another bar", template: "topic={{topic}}"});
|
||||
n1.receive({payload:"foo", topic: "bar", template: "payload={{payload}}"});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should modify payload from flow context', function(done) {
|
||||
var flow = [{id:"n1",z:"t1", type:"template", field:"payload", template:"payload={{flow.value}}",wires:[["n2"]]},{id:"n2",z:"t1",type:"helper"}];
|
||||
helper.load(templateNode, flow, function() {
|
||||
|
||||
@@ -355,6 +355,34 @@ describe('trigger node', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to reset correctly having not output anything on second edge', function(done) {
|
||||
var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", op2type:"nul", op1:"true",op1type:"val", op2:"false", duration:"35", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(triggerNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
var c = 0;
|
||||
n2.on("input", function(msg) {
|
||||
try {
|
||||
msg.should.have.a.property("payload", true);
|
||||
c += 1;
|
||||
}
|
||||
catch(err) { done(err); }
|
||||
});
|
||||
setTimeout( function() {
|
||||
c.should.equal(3); // should only have had one output.
|
||||
done();
|
||||
},300);
|
||||
n1.emit("input", {payload:1});
|
||||
setTimeout( function() {
|
||||
n1.emit("input", {payload:2});
|
||||
},100);
|
||||
setTimeout( function() {
|
||||
n1.emit("input", {payload:3});
|
||||
},200);
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to extend the delay', function(done) {
|
||||
var spy = sinon.stub(RED.util, 'evaluateNodeProperty',
|
||||
function(arg1, arg2, arg3, arg4) { return arg1; }
|
||||
@@ -422,8 +450,8 @@ describe('trigger node', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to extend the delay and output the 2nd payload', function(done) {
|
||||
var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", extend:"true", op1type:"nul", op2type:"payl", op1:"false", op2:"true", duration:"50", wires:[["n2"]] },
|
||||
it('should be able to extend the delay and output the most recent payload', function(done) {
|
||||
var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", extend:"true", op1type:"nul", op2type:"payl", op1:"false", op2:"true", duration:"60", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(triggerNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
@@ -431,15 +459,9 @@ describe('trigger node', function() {
|
||||
var c = 0;
|
||||
n2.on("input", function(msg) {
|
||||
try {
|
||||
if (c === 0) {
|
||||
msg.should.have.a.property("payload", "Goodbye");
|
||||
c += 1;
|
||||
}
|
||||
else {
|
||||
msg.should.have.a.property("payload", "World");
|
||||
(Date.now() - ss).should.be.greaterThan(70);
|
||||
done();
|
||||
}
|
||||
msg.should.have.a.property("payload", "World");
|
||||
(Date.now() - ss).should.be.greaterThan(120);
|
||||
done();
|
||||
}
|
||||
catch(err) { done(err); }
|
||||
});
|
||||
@@ -447,7 +469,7 @@ describe('trigger node', function() {
|
||||
n1.emit("input", {payload:"Hello"});
|
||||
setTimeout( function() {
|
||||
n1.emit("input", {payload:"Goodbye"});
|
||||
},20);
|
||||
},40);
|
||||
setTimeout( function() {
|
||||
n1.emit("input", {payload:"World"});
|
||||
},80);
|
||||
|
||||
@@ -240,7 +240,7 @@ describe("red/nodes/index", function() {
|
||||
}
|
||||
});
|
||||
sinon.stub(registry,"disableNode",function(id) {
|
||||
return randomNodeInfo;
|
||||
return when.resolve(randomNodeInfo);
|
||||
});
|
||||
});
|
||||
afterEach(function() {
|
||||
@@ -252,11 +252,12 @@ describe("red/nodes/index", function() {
|
||||
index.init(runtime);
|
||||
index.registerType('test-node-set','test', TestNode);
|
||||
index.loadFlows().then(function() {
|
||||
var info = index.disableNode("5678");
|
||||
registry.disableNode.calledOnce.should.be.true();
|
||||
registry.disableNode.calledWith("5678").should.be.true();
|
||||
info.should.eql(randomNodeInfo);
|
||||
done();
|
||||
return index.disableNode("5678").then(function(info) {
|
||||
registry.disableNode.calledOnce.should.be.true();
|
||||
registry.disableNode.calledWith("5678").should.be.true();
|
||||
info.should.eql(randomNodeInfo);
|
||||
done();
|
||||
});
|
||||
}).otherwise(function(err) {
|
||||
done(err);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user