mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Compare commits
8 Commits
2.1.5
...
add-tls-op
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c9f03f1ac5 | ||
|
|
02bd292b8c | ||
|
|
e5f1029d0c | ||
|
|
cae247160f | ||
|
|
6692b1992c | ||
|
|
0937837b7f | ||
|
|
7cd3e49f04 | ||
|
|
720a163273 |
32
CHANGELOG.md
32
CHANGELOG.md
@@ -1,35 +1,5 @@
|
||||
#### 2.1.5: Maintenance Release
|
||||
#### 2.2.0-beta.1: Beta Release
|
||||
|
||||
Runtime
|
||||
|
||||
- Handle reporting error location when stack is truncated (#3346) @knolleary
|
||||
- Initialize passport when only adminAuth.tokens is set (#3343) @knolleary
|
||||
- Add log logging (#3342) @knolleary
|
||||
|
||||
Editor
|
||||
|
||||
- Fix copy buttons on the debug window (another method) (#3331) @kazuhitoyokoi
|
||||
- Add Japanese translations for hidden flow (#3302) @kazuhitoyokoi
|
||||
- Improve jsonata legacy mode detection regex (#3345) @knolleary
|
||||
- Fix generating flow name with incrementing number (#3347) @knolleary
|
||||
- resume focus after import/export dialog close (#3337) @HiroyasuNishiyama
|
||||
- Fix findPreviousVisibleTab action (#3321) @knolleary
|
||||
- Fix storing hidden tab state when not hidden via action (#3312) @knolleary
|
||||
- Avoid adding empty env properties to tabs/groups (#3311) @knolleary
|
||||
- Fix hide icon in tour guide (#3301) @kazuhitoyokoi
|
||||
|
||||
Nodes
|
||||
|
||||
- File: Update file node examples according to node name change (#3335) @HiroyasuNishiyama
|
||||
- Filter (RBE): Fix for filter node narrrowbandEq mode start condition failure (#3339) @dceejay
|
||||
- Function: Prevent function scrollbar from obscuring expand button (#3348) @knolleary
|
||||
- Function: load extralibs when expanding monaco. fixes #3319 (#3334) @Steve-Mcl
|
||||
- Function: Update Function to use correct api to access env vars (#3310) @knolleary
|
||||
- HTTP Request: Fix basic auth with empty username or password (#3325) @hardillb
|
||||
- Inject: Fix incorrect clearing of blank payload property in Inject node (#3322) @knolleary
|
||||
- Link Call: add link call example (#3336) @HiroyasuNishiyama
|
||||
- WebSocket: Only setup ws client heartbeat once it is connected (#3344) @knolleary
|
||||
- Update Japanese translations in node help (#3332) @kazuhitoyokoi
|
||||
|
||||
|
||||
#### 2.1.4: Maintenance Release
|
||||
|
||||
22
package.json
22
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "node-red",
|
||||
"version": "2.1.5",
|
||||
"version": "2.2.0-beta.1",
|
||||
"description": "Low-code programming for event-driven applications",
|
||||
"homepage": "http://nodered.org",
|
||||
"license": "Apache-2.0",
|
||||
@@ -26,13 +26,13 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"acorn": "8.7.0",
|
||||
"acorn": "8.6.0",
|
||||
"acorn-walk": "8.2.0",
|
||||
"ajv": "8.8.2",
|
||||
"async-mutex": "0.3.2",
|
||||
"basic-auth": "2.0.1",
|
||||
"bcryptjs": "2.4.3",
|
||||
"body-parser": "1.19.1",
|
||||
"body-parser": "1.19.0",
|
||||
"cheerio": "1.0.0-rc.10",
|
||||
"clone": "2.1.2",
|
||||
"content-type": "1.0.4",
|
||||
@@ -41,7 +41,7 @@
|
||||
"cors": "2.8.5",
|
||||
"cronosjs": "1.7.1",
|
||||
"denque": "2.0.1",
|
||||
"express": "4.17.2",
|
||||
"express": "4.17.1",
|
||||
"express-session": "1.17.2",
|
||||
"form-data": "4.0.0",
|
||||
"fs-extra": "10.0.0",
|
||||
@@ -50,7 +50,7 @@
|
||||
"hash-sum": "2.0.0",
|
||||
"hpagent": "0.1.2",
|
||||
"https-proxy-agent": "5.0.0",
|
||||
"i18next": "21.6.6",
|
||||
"i18next": "21.5.4",
|
||||
"iconv-lite": "0.6.3",
|
||||
"is-utf8": "0.2.1",
|
||||
"js-yaml": "3.14.1",
|
||||
@@ -61,21 +61,21 @@
|
||||
"memorystore": "1.6.6",
|
||||
"mime": "2.5.2",
|
||||
"moment-timezone": "0.5.34",
|
||||
"mqtt": "4.3.4",
|
||||
"mqtt": "4.2.8",
|
||||
"multer": "1.4.3",
|
||||
"mustache": "4.2.0",
|
||||
"node-red-admin": "^2.2.1",
|
||||
"nopt": "5.0.0",
|
||||
"oauth2orize": "1.11.1",
|
||||
"on-headers": "1.0.2",
|
||||
"passport": "0.5.2",
|
||||
"passport": "0.5.0",
|
||||
"passport-http-bearer": "1.0.1",
|
||||
"passport-oauth2-client-password": "0.1.2",
|
||||
"raw-body": "2.4.2",
|
||||
"semver": "7.3.5",
|
||||
"tar": "6.1.11",
|
||||
"tough-cookie": "4.0.0",
|
||||
"uglify-js": "3.14.5",
|
||||
"uglify-js": "3.14.4",
|
||||
"uuid": "8.3.2",
|
||||
"ws": "7.5.1",
|
||||
"xml2js": "0.4.23"
|
||||
@@ -84,7 +84,7 @@
|
||||
"bcrypt": "5.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"dompurify": "2.3.4",
|
||||
"dompurify": "2.3.3",
|
||||
"grunt": "1.4.1",
|
||||
"grunt-chmod": "~1.1.1",
|
||||
"grunt-cli": "~1.4.3",
|
||||
@@ -113,11 +113,11 @@
|
||||
"node-red-node-test-helper": "^0.2.7",
|
||||
"nodemon": "2.0.15",
|
||||
"proxy": "^1.0.2",
|
||||
"sass": "1.48.0",
|
||||
"sass": "1.44.0",
|
||||
"should": "13.2.3",
|
||||
"sinon": "11.1.2",
|
||||
"stoppable": "^1.1.0",
|
||||
"supertest": "6.2.1"
|
||||
"supertest": "6.1.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
|
||||
@@ -146,7 +146,7 @@ function authenticateUserToken(req) {
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
}).catch(reject);
|
||||
});
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
@@ -163,9 +163,6 @@ TokensStrategy.prototype.authenticate = function(req) {
|
||||
authenticateUserToken(req).then(user => {
|
||||
this.success(user,{scope:user.permissions});
|
||||
}).catch(err => {
|
||||
if (err) {
|
||||
log.trace("token authentication failure: "+err.stack?err.stack:err)
|
||||
}
|
||||
this.fail(401);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -90,8 +90,6 @@ function init(settings,_server,storage,runtimeAPI) {
|
||||
auth.getToken,
|
||||
auth.errorHandler
|
||||
);
|
||||
} else if (settings.adminAuth.tokens) {
|
||||
adminApp.use(passport.initialize());
|
||||
}
|
||||
adminApp.post("/auth/revoke",auth.needsPermission(""),auth.revoke,apiUtil.errorHandler);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/editor-api",
|
||||
"version": "2.1.5",
|
||||
"version": "2.2.0-beta.1",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
@@ -16,14 +16,14 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/util": "2.1.5",
|
||||
"@node-red/editor-client": "2.1.5",
|
||||
"@node-red/util": "2.2.0-beta.1",
|
||||
"@node-red/editor-client": "2.2.0-beta.1",
|
||||
"bcryptjs": "2.4.3",
|
||||
"body-parser": "1.19.1",
|
||||
"body-parser": "1.19.0",
|
||||
"clone": "2.1.2",
|
||||
"cors": "2.8.5",
|
||||
"express-session": "1.17.2",
|
||||
"express": "4.17.2",
|
||||
"express": "4.17.1",
|
||||
"memorystore": "1.6.6",
|
||||
"mime": "2.5.2",
|
||||
"multer": "1.4.3",
|
||||
@@ -31,7 +31,7 @@
|
||||
"oauth2orize": "1.11.1",
|
||||
"passport-http-bearer": "1.0.1",
|
||||
"passport-oauth2-client-password": "0.1.2",
|
||||
"passport": "0.5.2",
|
||||
"passport": "0.5.0",
|
||||
"ws": "7.5.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
|
||||
@@ -59,8 +59,6 @@
|
||||
"hideOtherFlows": "他のフローを非表示",
|
||||
"showAllFlows": "全てのフローを表示",
|
||||
"hideAllFlows": "全てのフローを非表示",
|
||||
"hiddenFlows": "__count__ 個の非表示のフロー一覧",
|
||||
"hiddenFlows_plural": "__count__ 個の非表示のフロー一覧",
|
||||
"showLastHiddenFlow": "最後に非表示にしたフローを表示",
|
||||
"listFlows": "フロー一覧",
|
||||
"listSubflows": "サブフロー一覧",
|
||||
@@ -671,8 +669,7 @@
|
||||
"unusedConfigNodes": "未使用の設定ノード",
|
||||
"invalidNodes": "不正なノード",
|
||||
"uknownNodes": "未知のノード",
|
||||
"unusedSubflows": "未使用のサブフロー",
|
||||
"hiddenFlows": "非表示のフロー"
|
||||
"unusedSubflows": "未使用のサブフロー"
|
||||
}
|
||||
},
|
||||
"help": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/editor-client",
|
||||
"version": "2.1.5",
|
||||
"version": "2.2.0-beta.1",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -71,7 +71,6 @@ RED.clipboard = (function() {
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
$( this ).dialog( "close" );
|
||||
RED.view.focus();
|
||||
}
|
||||
},
|
||||
{ // red-ui-clipboard-dialog-download
|
||||
@@ -82,7 +81,6 @@ RED.clipboard = (function() {
|
||||
var data = $("#red-ui-clipboard-dialog-export-text").val();
|
||||
downloadData("flows.json", data);
|
||||
$( this ).dialog( "close" );
|
||||
RED.view.focus();
|
||||
}
|
||||
},
|
||||
{ // red-ui-clipboard-dialog-export
|
||||
@@ -97,7 +95,6 @@ RED.clipboard = (function() {
|
||||
$( this ).dialog( "close" );
|
||||
copyText(flowData);
|
||||
RED.notify(RED._("clipboard.nodesExported"),{id:"clipboard"});
|
||||
RED.view.focus();
|
||||
} else {
|
||||
var flowToExport = $("#red-ui-clipboard-dialog-export-text").val();
|
||||
var selectedPath = activeLibraries[activeTab].getSelected();
|
||||
@@ -113,7 +110,6 @@ RED.clipboard = (function() {
|
||||
contentType: "application/json; charset=utf-8"
|
||||
}).done(function() {
|
||||
$(dialog).dialog( "close" );
|
||||
RED.view.focus();
|
||||
RED.notify(RED._("library.exportedToLibrary"),"success");
|
||||
}).fail(function(xhr,textStatus,err) {
|
||||
if (xhr.status === 401) {
|
||||
@@ -175,7 +171,6 @@ RED.clipboard = (function() {
|
||||
}
|
||||
}
|
||||
$( this ).dialog( "close" );
|
||||
RED.view.focus();
|
||||
}
|
||||
},
|
||||
{ // red-ui-clipboard-dialog-import-conflict
|
||||
@@ -208,7 +203,6 @@ RED.clipboard = (function() {
|
||||
// console.table(pendingImportConfig.importNodes.map(function(n) { return {id:n.id,type:n.type,result:importMap[n.id]}}))
|
||||
RED.view.importNodes(newNodes, pendingImportConfig.importOptions);
|
||||
$( this ).dialog( "close" );
|
||||
RED.view.focus();
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -946,25 +940,28 @@ RED.clipboard = (function() {
|
||||
if (truncated) {
|
||||
msg += "_truncated";
|
||||
}
|
||||
navigator.clipboard.writeText(value).then(function () {
|
||||
if (element) {
|
||||
var popover = RED.popover.create({
|
||||
target: element,
|
||||
direction: 'left',
|
||||
size: 'small',
|
||||
content: RED._(msg)
|
||||
});
|
||||
setTimeout(function() {
|
||||
popover.close();
|
||||
},1000);
|
||||
popover.open();
|
||||
}
|
||||
if (currentFocus) {
|
||||
$(currentFocus).focus();
|
||||
}
|
||||
}).catch(err => { console.error("Failed to copy:",err) });
|
||||
$("#red-ui-clipboard-hidden").val(value).focus().select();
|
||||
var result = document.execCommand("copy");
|
||||
if (result && element) {
|
||||
var popover = RED.popover.create({
|
||||
target: element,
|
||||
direction: 'left',
|
||||
size: 'small',
|
||||
content: RED._(msg)
|
||||
});
|
||||
setTimeout(function() {
|
||||
popover.close();
|
||||
},1000);
|
||||
popover.open();
|
||||
}
|
||||
$("#red-ui-clipboard-hidden").val("");
|
||||
if (currentFocus) {
|
||||
$(currentFocus).focus();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
function importNodes(nodesStr,addFlow) {
|
||||
var newNodes = nodesStr;
|
||||
if (typeof nodesStr === 'string') {
|
||||
@@ -1239,6 +1236,8 @@ RED.clipboard = (function() {
|
||||
init: function() {
|
||||
setupDialogs();
|
||||
|
||||
$('<textarea type="text" id="red-ui-clipboard-hidden" tabIndex="-1">').appendTo("#red-ui-editor");
|
||||
|
||||
RED.actions.add("core:show-export-dialog",showExportNodes);
|
||||
RED.actions.add("core:show-import-dialog",showImportNodes);
|
||||
|
||||
|
||||
@@ -578,7 +578,7 @@ RED.tabs = (function() {
|
||||
|
||||
function findPreviousVisibleTab(li) {
|
||||
if (!li) {
|
||||
li = ul.find("li.active");
|
||||
li = ul.find("li.active").parent();
|
||||
}
|
||||
var previous = li.prev();
|
||||
while(previous.length > 0 && previous.hasClass("hide-tab")) {
|
||||
@@ -588,9 +588,9 @@ RED.tabs = (function() {
|
||||
}
|
||||
function findNextVisibleTab(li) {
|
||||
if (!li) {
|
||||
li = ul.find("li.active");
|
||||
li = ul.find("li.active").parent();
|
||||
}
|
||||
var next = li.next();
|
||||
var next = ul.find("li.active").next();
|
||||
while(next.length > 0 && next.hasClass("hide-tab")) {
|
||||
next = next.next();
|
||||
}
|
||||
|
||||
@@ -247,7 +247,7 @@
|
||||
var currentExpression = expressionEditor.getValue();
|
||||
var expr;
|
||||
var usesContext = false;
|
||||
var legacyMode = /(^|[^a-zA-Z0-9_'".])msg([^a-zA-Z0-9_'"]|$)/.test(currentExpression);
|
||||
var legacyMode = /(^|[^a-zA-Z0-9_'"])msg([^a-zA-Z0-9_'"]|$)/.test(currentExpression);
|
||||
$(".red-ui-editor-type-expression-legacy").toggle(legacyMode);
|
||||
try {
|
||||
expr = jsonata(currentExpression);
|
||||
|
||||
@@ -81,8 +81,7 @@
|
||||
clearTimeout: true,
|
||||
setInterval: true,
|
||||
clearInterval: true
|
||||
},
|
||||
extraLibs: options.extraLibs
|
||||
}
|
||||
});
|
||||
if (options.cursor) {
|
||||
expressionEditor.gotoLine(options.cursor.row+1,options.cursor.column,false);
|
||||
|
||||
@@ -55,9 +55,7 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!old_env && new_env.length === 0) {
|
||||
delete node.env;
|
||||
} else if (!isSameObj(old_env, new_env)) {
|
||||
if (!isSameObj(old_env, new_env)) {
|
||||
editState.changes.env = node.env;
|
||||
if (new_env.length === 0) {
|
||||
delete node.env;
|
||||
|
||||
@@ -66,7 +66,7 @@ RED.workspaces = (function() {
|
||||
var tabId = RED.nodes.id();
|
||||
do {
|
||||
workspaceIndex += 1;
|
||||
} while ($("#red-ui-workspace-tabs li[flowname='"+RED._('workspace.defaultName',{number:workspaceIndex})+"']").size() !== 0);
|
||||
} while ($("#red-ui-workspace-tabs a[title='"+RED._('workspace.defaultName',{number:workspaceIndex})+"']").size() !== 0);
|
||||
|
||||
ws = {
|
||||
type: "tab",
|
||||
@@ -79,15 +79,12 @@ RED.workspaces = (function() {
|
||||
};
|
||||
RED.nodes.addWorkspace(ws,targetIndex);
|
||||
workspace_tabs.addTab(ws,targetIndex);
|
||||
|
||||
workspace_tabs.activateTab(tabId);
|
||||
if (!skipHistoryEntry) {
|
||||
RED.history.push({t:'add',workspaces:[ws],dirty:RED.nodes.dirty()});
|
||||
RED.nodes.dirty(true);
|
||||
}
|
||||
}
|
||||
$("#red-ui-tab-"+(ws.id.replace(".","-"))).attr("flowname",ws.label)
|
||||
|
||||
RED.view.focus();
|
||||
return ws;
|
||||
}
|
||||
@@ -211,20 +208,10 @@ RED.workspaces = (function() {
|
||||
},
|
||||
onhide: function(tab) {
|
||||
hideStack.push(tab.id);
|
||||
|
||||
var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}");
|
||||
hiddenTabs[tab.id] = true;
|
||||
RED.settings.setLocal("hiddenTabs",JSON.stringify(hiddenTabs));
|
||||
|
||||
RED.events.emit("workspace:hide",{workspace: tab.id})
|
||||
},
|
||||
onshow: function(tab) {
|
||||
removeFromHideStack(tab.id);
|
||||
|
||||
var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}");
|
||||
delete hiddenTabs[tab.id];
|
||||
RED.settings.setLocal("hiddenTabs",JSON.stringify(hiddenTabs));
|
||||
|
||||
RED.events.emit("workspace:show",{workspace: tab.id})
|
||||
},
|
||||
minimumActiveTabWidth: 150,
|
||||
@@ -555,6 +542,9 @@ RED.workspaces = (function() {
|
||||
}
|
||||
if (workspace_tabs.contains(id)) {
|
||||
workspace_tabs.hideTab(id);
|
||||
var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}");
|
||||
hiddenTabs[id] = true;
|
||||
RED.settings.setLocal("hiddenTabs",JSON.stringify(hiddenTabs));
|
||||
}
|
||||
},
|
||||
isHidden: function(id) {
|
||||
@@ -582,11 +572,14 @@ RED.workspaces = (function() {
|
||||
}
|
||||
workspace_tabs.activateTab(id);
|
||||
}
|
||||
var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}");
|
||||
delete hiddenTabs[id];
|
||||
RED.settings.setLocal("hiddenTabs",JSON.stringify(hiddenTabs));
|
||||
},
|
||||
refresh: function() {
|
||||
RED.nodes.eachWorkspace(function(ws) {
|
||||
workspace_tabs.renameTab(ws.id,ws.label);
|
||||
$("#red-ui-tab-"+(ws.id.replace(".","-"))).attr("flowname",ws.label)
|
||||
|
||||
})
|
||||
RED.nodes.eachSubflow(function(sf) {
|
||||
if (workspace_tabs.contains(sf.id)) {
|
||||
|
||||
@@ -356,6 +356,10 @@ button.red-ui-button-small
|
||||
background: $secondary-background;
|
||||
}
|
||||
|
||||
#red-ui-clipboard-hidden {
|
||||
position: absolute;
|
||||
top: -3000px;
|
||||
}
|
||||
.form-row .red-ui-editor-node-label-form-row {
|
||||
margin: 5px 0 0 50px;
|
||||
label {
|
||||
|
||||
@@ -73,8 +73,8 @@ export default {
|
||||
},
|
||||
element: "#red-ui-workspace-tabs > li.active",
|
||||
description: {
|
||||
"en-US": '<p>Tabs can now be hidden by clicking their <i class="fa fa-eye-slash"></i> icon.</p><p>The Info Sidebar will still list all of your tabs, and tell you which ones are currently hidden.',
|
||||
"ja": '<p><i class="fa fa-eye-slash"></i> アイコンをクリックすることで、タブを非表示にできます。</p><p>情報サイドバーには、全てのタブが一覧表示されており、現在非表示になっているタブを確認できます。'
|
||||
"en-US": '<p>Tabs can now be hidden by clicking their <i class="fa fa-times"></i> icon.</p><p>The Info Sidebar will still list all of your tabs, and tell you which ones are currently hidden.',
|
||||
"ja": '<p><i class="fa fa-times"></i> アイコンをクリックすることで、タブを非表示にできます。</p><p>情報サイドバーには、全てのタブが一覧表示されており、現在非表示になっているタブを確認できます。'
|
||||
},
|
||||
interactive: false,
|
||||
prepare() {
|
||||
|
||||
@@ -690,9 +690,9 @@
|
||||
this.topic = "";
|
||||
var result = getProps(items, true);
|
||||
this.props = result.props;
|
||||
if(result.hasOwnProperty('payloadType')) { this.payloadType = result.payloadType; };
|
||||
if(result.hasOwnProperty('payload')) { this.payload = result.payload; };
|
||||
if(result.hasOwnProperty('topic')) { this.topic = result.topic; };
|
||||
if(result.payloadType) { this.payloadType = result.payloadType; };
|
||||
if(result.payload) { this.payload = result.payload; };
|
||||
if(result.topic) { this.topic = result.topic; };
|
||||
},
|
||||
button: {
|
||||
enabled: function() {
|
||||
|
||||
@@ -91,21 +91,21 @@
|
||||
<div id="func-tab-init" style="display:none">
|
||||
<div class="form-row node-text-editor-row" style="position:relative">
|
||||
<div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-init-editor" ></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button id="node-init-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 5;"><button id="node-init-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="func-tab-body" style="display:none">
|
||||
<div class="form-row node-text-editor-row" style="position:relative">
|
||||
<div style="height: 220px; min-height:150px;" class="node-text-editor" id="node-input-func-editor" ></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button id="node-function-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 5;"><button id="node-function-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="func-tab-finalize" style="display:none">
|
||||
<div class="form-row node-text-editor-row" style="position:relative">
|
||||
<div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-finalize-editor" ></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button id="node-finalize-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 5;"><button id="node-finalize-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -512,7 +512,6 @@
|
||||
return function(e) {
|
||||
e.preventDefault();
|
||||
var value = editor.getValue();
|
||||
var extraLibs = that.libs || [];
|
||||
RED.editor.editJavaScript({
|
||||
value: value,
|
||||
width: "Infinity",
|
||||
@@ -524,8 +523,7 @@
|
||||
setTimeout(function() {
|
||||
editor.focus();
|
||||
},300);
|
||||
},
|
||||
extraLibs: extraLibs
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,7 +234,8 @@ module.exports = function(RED) {
|
||||
},
|
||||
env: {
|
||||
get: function(envVar) {
|
||||
return RED.util.getSetting(node, envVar);
|
||||
var flow = node._flow;
|
||||
return flow.getSetting(envVar);
|
||||
}
|
||||
},
|
||||
setTimeout: function () {
|
||||
|
||||
@@ -58,7 +58,7 @@ module.exports = function(RED) {
|
||||
else {
|
||||
var n = parseFloat(value);
|
||||
if (!isNaN(n)) {
|
||||
if ((typeof node.previous[t] === 'undefined') && (this.func === "narrowband" || this.func === "narrowbandEq")) {
|
||||
if ((typeof node.previous[t] === 'undefined') && (this.func === "narrowband")) {
|
||||
if (node.start === '') { node.previous[t] = n; }
|
||||
else { node.previous[t] = node.start; }
|
||||
}
|
||||
|
||||
@@ -302,8 +302,6 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
||||
// var cred = ""
|
||||
if (this.credentials.user || this.credentials.password) {
|
||||
// cred = `${this.credentials.user}:${this.credentials.password}`;
|
||||
if (this.credentials.user === undefined) { this.credentials.user = ""}
|
||||
if (this.credentials.password === undefined) { this.credentials.password = ""}
|
||||
opts.headers.Authorization = "Basic " + Buffer.from(`${this.credentials.user}:${this.credentials.password}`).toString("base64");
|
||||
}
|
||||
// build own basic auth header
|
||||
|
||||
@@ -105,24 +105,22 @@ module.exports = function(RED) {
|
||||
if (node.isServer) {
|
||||
node._clients[id] = socket;
|
||||
node.emit('opened',{count:Object.keys(node._clients).length,id:id});
|
||||
} else {
|
||||
if (node.heartbeat) {
|
||||
node.heartbeatInterval = setInterval(function() {
|
||||
if (socket.nrPendingHeartbeat) {
|
||||
// No pong received
|
||||
socket.terminate();
|
||||
socket.nrErrorHandler(new Error("timeout"));
|
||||
return;
|
||||
}
|
||||
socket.nrPendingHeartbeat = true;
|
||||
socket.ping();
|
||||
},node.heartbeat);
|
||||
}
|
||||
}
|
||||
socket.on('open',function() {
|
||||
if (!node.isServer) {
|
||||
if (node.heartbeat) {
|
||||
clearInterval(node.heartbeatInterval);
|
||||
node.heartbeatInterval = setInterval(function() {
|
||||
if (socket.nrPendingHeartbeat) {
|
||||
// No pong received
|
||||
socket.terminate();
|
||||
socket.nrErrorHandler(new Error("timeout"));
|
||||
return;
|
||||
}
|
||||
socket.nrPendingHeartbeat = true;
|
||||
try {
|
||||
socket.ping();
|
||||
} catch(err) {}
|
||||
},node.heartbeat);
|
||||
}
|
||||
node.emit('opened',{count:'',id:id});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -23,9 +23,17 @@
|
||||
</select>
|
||||
<span data-i18n="tcpin.label.port"></span> <input type="text" id="node-input-port" style="width:65px">
|
||||
</div>
|
||||
<div class="form-row hidden" id="node-input-host-row" style="padding-left: 110px;">
|
||||
<div class="form-row hidden" id="node-input-host-row" style="padding-left:110px;">
|
||||
<span data-i18n="tcpin.label.host"></span> <input type="text" id="node-input-host" placeholder="localhost" style="width: 60%;">
|
||||
</div>
|
||||
<div class="form-row" id="node-input-tls-enable">
|
||||
<label> </label>
|
||||
<input type="checkbox" id="node-input-usetls" style="display: inline-block; width:auto; vertical-align:top;">
|
||||
<label for="node-input-usetls" style="width:auto" data-i18n="httpin.use-tls"></label>
|
||||
<div id="node-row-tls" class="hide">
|
||||
<label style="width:auto; margin-left:20px; margin-right:10px;" for="node-input-tls"><span data-i18n="httpin.tls-config"></span></label><input type="text" style="width: 300px" id="node-input-tls">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label><i class="fa fa-sign-out"></i> <span data-i18n="tcpin.label.output"></span></label>
|
||||
@@ -42,7 +50,7 @@
|
||||
</div>
|
||||
|
||||
<div id="node-row-newline" class="form-row hidden" style="padding-left:110px;">
|
||||
<span data-i18n="tcpin.label.delimited"></span> <input type="text" id="node-input-newline" style="width:110px;">
|
||||
<span data-i18n="tcpin.label.delimited"></span> <input type="text" id="node-input-newline" style="width:110px;" data-i18n="[placeholder]tcpin.label.optional">
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
@@ -58,17 +66,18 @@
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('tcp in',{
|
||||
category: 'network',
|
||||
color:"Silver",
|
||||
color: "Silver",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
server: {value:"server",required:true},
|
||||
host: {value:"",validate:function(v) { return (this.server == "server")||v.length > 0;} },
|
||||
port: {value:"",required:true,validate:RED.validators.number()},
|
||||
server: {value:"server", required:true},
|
||||
host: {value:"", validate:function(v) { return (this.server == "server")||v.length > 0;} },
|
||||
port: {value:"", required:true, validate:RED.validators.number()},
|
||||
datamode:{value:"stream"},
|
||||
datatype:{value:"buffer"},
|
||||
newline:{value:""},
|
||||
topic: {value:""},
|
||||
base64: {/*deprecated*/ value:false,required:true}
|
||||
base64: {/*deprecated*/ value:false, required:true},
|
||||
tls: {type:"tls-config", value:'', required:false}
|
||||
},
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
@@ -77,7 +86,7 @@
|
||||
return this.name || "tcp:"+(this.host?this.host+":":"")+this.port;
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
return this.name ? "node_label_italic" : "";
|
||||
},
|
||||
oneditprepare: function() {
|
||||
var updateOptions = function() {
|
||||
@@ -103,6 +112,27 @@
|
||||
$("#node-input-server").change(updateOptions);
|
||||
$("#node-input-datatype").change(updateOptions);
|
||||
$("#node-input-datamode").change(updateOptions);
|
||||
function updateTLSOptions() {
|
||||
if ($("#node-input-usetls").is(':checked')) {
|
||||
$("#node-row-tls").show();
|
||||
} else {
|
||||
$("#node-row-tls").hide();
|
||||
}
|
||||
}
|
||||
if (this.tls) {
|
||||
$('#node-input-usetls').prop('checked', true);
|
||||
} else {
|
||||
$('#node-input-usetls').prop('checked', false);
|
||||
}
|
||||
updateTLSOptions();
|
||||
$("#node-input-usetls").on("click",function() {
|
||||
updateTLSOptions();
|
||||
});
|
||||
},
|
||||
oneditsave: function() {
|
||||
if (!$("#node-input-usetls").is(':checked')) {
|
||||
$("#node-input-tls").val("_ADD_");
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -123,6 +153,15 @@
|
||||
<span data-i18n="tcpin.label.host"></span> <input type="text" id="node-input-host" style="width: 60%;">
|
||||
</div>
|
||||
|
||||
<div class="form-row" id="node-input-tls-enable">
|
||||
<label> </label>
|
||||
<input type="checkbox" id="node-input-usetls" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-input-usetls" style="width: auto" data-i18n="httpin.use-tls"></label>
|
||||
<div id="node-row-tls" class="hide">
|
||||
<label style="width: auto; margin-left: 20px; margin-right: 10px;" for="node-input-tls"><span data-i18n="httpin.tls-config"></span></label><input type="text" style="width: 300px" id="node-input-tls">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row hidden" id="node-input-end-row">
|
||||
<label> </label>
|
||||
<input type="checkbox" id="node-input-end" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
@@ -144,14 +183,15 @@
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('tcp out',{
|
||||
category: 'network',
|
||||
color:"Silver",
|
||||
color: "Silver",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
host: {value:"",validate:function(v) { return (this.beserver != "client")||v.length > 0;} },
|
||||
port: {value:"",validate:function(v) { return (this.beserver == "reply")||RED.validators.number()(v); } },
|
||||
beserver: {value:"client",required:true},
|
||||
base64: {value:false,required:true},
|
||||
end: {value:false,required:true},
|
||||
name: {value:""}
|
||||
beserver: {value:"client", required:true},
|
||||
base64: {value:false, required:true},
|
||||
end: {value:false, required:true},
|
||||
tls: {type:"tls-config", value:'', required:false}
|
||||
},
|
||||
inputs:1,
|
||||
outputs:0,
|
||||
@@ -170,18 +210,42 @@
|
||||
$("#node-input-port-row").hide();
|
||||
$("#node-input-host-row").hide();
|
||||
$("#node-input-end-row").hide();
|
||||
$("#node-input-tls-enable").hide();
|
||||
} else if (sockettype == "client"){
|
||||
$("#node-input-port-row").show();
|
||||
$("#node-input-host-row").show();
|
||||
$("#node-input-end-row").show();
|
||||
$("#node-input-tls-enable").show();
|
||||
} else {
|
||||
$("#node-input-port-row").show();
|
||||
$("#node-input-host-row").hide();
|
||||
$("#node-input-end-row").show();
|
||||
$("#node-input-tls-enable").show();
|
||||
}
|
||||
};
|
||||
updateOptions();
|
||||
$("#node-input-beserver").change(updateOptions);
|
||||
function updateTLSOptions() {
|
||||
if ($("#node-input-usetls").is(':checked')) {
|
||||
$("#node-row-tls").show();
|
||||
} else {
|
||||
$("#node-row-tls").hide();
|
||||
}
|
||||
}
|
||||
if (this.tls) {
|
||||
$('#node-input-usetls').prop('checked', true);
|
||||
} else {
|
||||
$('#node-input-usetls').prop('checked', false);
|
||||
}
|
||||
updateTLSOptions();
|
||||
$("#node-input-usetls").on("click",function() {
|
||||
updateTLSOptions();
|
||||
});
|
||||
},
|
||||
oneditsave: function() {
|
||||
if (!$("#node-input-usetls").is(':checked')) {
|
||||
$("#node-input-tls").val("_ADD_");
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -194,15 +258,23 @@
|
||||
<span data-i18n="tcpin.label.port"></span>
|
||||
<input type="text" id="node-input-port" style="width:60px">
|
||||
</div>
|
||||
<div class="form-row" id="node-input-tls-enable">
|
||||
<label> </label>
|
||||
<input type="checkbox" id="node-input-usetls" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-input-usetls" style="width: auto" data-i18n="httpin.use-tls"></label>
|
||||
<div id="node-row-tls" class="hide">
|
||||
<label style="width: auto; margin-left: 20px; margin-right: 10px;" for="node-input-tls"><span data-i18n="httpin.tls-config"></span></label><input type="text" style="width: 300px" id="node-input-tls">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-out"><i class="fa fa-sign-out"></i> <span data-i18n="tcpin.label.return"></span></label>
|
||||
<label for="node-input-ret"><i class="fa fa-sign-out"></i> <span data-i18n="tcpin.label.return"></span></label>
|
||||
<select type="text" id="node-input-ret" style="width:54%;">
|
||||
<option value="buffer" data-i18n="tcpin.output.buffer"></option>
|
||||
<option value="string" data-i18n="tcpin.output.string"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-out"> </label>
|
||||
<label for="node-input-out"><i class="fa fa-sign-out fa-rotate-90"></i> <span data-i18n="tcpin.label.close"></span></label>
|
||||
<select type="text" id="node-input-out" style="width:54%;">
|
||||
<option value="time" data-i18n="tcpin.return.timeout"></option>
|
||||
<option value="char" data-i18n="tcpin.return.character"></option>
|
||||
@@ -213,6 +285,9 @@
|
||||
<input type="text" id="node-input-splitc" style="width:50px;">
|
||||
<span id="node-units"></span>
|
||||
</div>
|
||||
<div id="node-row-newline" class="form-row hidden" style="padding-left:162px;">
|
||||
<span data-i18n="tcpin.label.delimited"></span> <input type="text" id="node-input-newline" style="width:110px;" data-i18n="[placeholder]tcpin.label.optional">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
|
||||
@@ -222,14 +297,16 @@
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('tcp request',{
|
||||
category: 'network',
|
||||
color:"Silver",
|
||||
color: "Silver",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
server: {value:""},
|
||||
port: {value:"",validate:RED.validators.regex(/^(\d*|)$/)},
|
||||
out: {value:"time",required:true},
|
||||
port: {value:"", validate:RED.validators.regex(/^(\d*|)$/)},
|
||||
out: {value:"time", required:true},
|
||||
ret: {value:"buffer"},
|
||||
splitc: {value:"0",required:true},
|
||||
name: {value:""}
|
||||
splitc: {value:"0", required:true},
|
||||
newline: {value:""},
|
||||
tls: {type:"tls-config", value:'', required:false}
|
||||
},
|
||||
inputs:1,
|
||||
outputs:1,
|
||||
@@ -246,6 +323,14 @@
|
||||
$("#node-input-ret").val("buffer");
|
||||
this.ret = "buffer";
|
||||
}
|
||||
$("#node-input-ret").on("change", function() {
|
||||
if ($("#node-input-ret").val() === "string" && $("#node-input-out").val() === "sit") { $("#node-row-newline").show(); }
|
||||
else { $("#node-row-newline").hide(); }
|
||||
});
|
||||
$("#node-input-out").on("change", function() {
|
||||
if ($("#node-input-ret").val() === "string" && $("#node-input-out").val() === "sit") { $("#node-row-newline").show(); }
|
||||
else { $("#node-row-newline").hide(); }
|
||||
});
|
||||
$("#node-input-out").on('focus', function () { previous = this.value; }).on("change", function() {
|
||||
$("#node-input-splitc").show();
|
||||
if (previous === null) { previous = $("#node-input-out").val(); }
|
||||
@@ -272,6 +357,27 @@
|
||||
$("#node-input-splitc").hide();
|
||||
}
|
||||
});
|
||||
function updateTLSOptions() {
|
||||
if ($("#node-input-usetls").is(':checked')) {
|
||||
$("#node-row-tls").show();
|
||||
} else {
|
||||
$("#node-row-tls").hide();
|
||||
}
|
||||
}
|
||||
if (this.tls) {
|
||||
$('#node-input-usetls').prop('checked', true);
|
||||
} else {
|
||||
$('#node-input-usetls').prop('checked', false);
|
||||
}
|
||||
updateTLSOptions();
|
||||
$("#node-input-usetls").on("click",function() {
|
||||
updateTLSOptions();
|
||||
});
|
||||
},
|
||||
oneditsave: function() {
|
||||
if (!$("#node-input-usetls").is(':checked')) {
|
||||
$("#node-input-tls").val("_ADD_");
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -16,13 +16,46 @@
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var reconnectTime = RED.settings.socketReconnectTime||10000;
|
||||
var socketTimeout = RED.settings.socketTimeout||null;
|
||||
let reconnectTime = RED.settings.socketReconnectTime || 10000;
|
||||
let socketTimeout = RED.settings.socketTimeout || null;
|
||||
const msgQueueSize = RED.settings.tcpMsgQueueSize || 1000;
|
||||
const Denque = require('denque');
|
||||
var net = require('net');
|
||||
const net = require('net');
|
||||
const tls = require('tls');
|
||||
|
||||
var connectionPool = {};
|
||||
let connectionPool = {};
|
||||
|
||||
function normalizeConnectArgs(listArgs) {
|
||||
const args = net._normalizeArgs(listArgs);
|
||||
const options = args[0];
|
||||
const cb = args[1];
|
||||
|
||||
// If args[0] was options, then normalize dealt with it.
|
||||
// If args[0] is port, or args[0], args[1] is host, port, we need to
|
||||
// find the options and merge them in, normalize's options has only
|
||||
// the host/port/path args that it knows about, not the tls options.
|
||||
// This means that options.host overrides a host arg.
|
||||
if (listArgs[1] !== null && typeof listArgs[1] === 'object') {
|
||||
ObjectAssign(options, listArgs[1]);
|
||||
} else if (listArgs[2] !== null && typeof listArgs[2] === 'object') {
|
||||
ObjectAssign(options, listArgs[2]);
|
||||
}
|
||||
|
||||
return cb ? [options, cb] : [options];
|
||||
}
|
||||
|
||||
function getAllowUnauthorized() {
|
||||
const allowUnauthorized = process.env.NODE_TLS_REJECT_UNAUTHORIZED === '0';
|
||||
|
||||
if (allowUnauthorized) {
|
||||
process.emitWarning(
|
||||
'Setting the NODE_TLS_REJECT_UNAUTHORIZED ' +
|
||||
'environment variable to \'0\' makes TLS connections ' +
|
||||
'and HTTPS requests insecure by disabling ' +
|
||||
'certificate verification.');
|
||||
}
|
||||
return allowUnauthorized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue `item` in `queue`
|
||||
@@ -53,13 +86,14 @@ module.exports = function(RED) {
|
||||
this.topic = n.topic;
|
||||
this.stream = (!n.datamode||n.datamode=='stream'); /* stream,single*/
|
||||
this.datatype = n.datatype||'buffer'; /* buffer,utf8,base64 */
|
||||
this.newline = (n.newline||"").replace("\\n","\n").replace("\\r","\r");
|
||||
this.newline = (n.newline||"").replace("\\n","\n").replace("\\r","\r").replace("\\t","\t");
|
||||
this.base64 = n.base64;
|
||||
this.server = (typeof n.server == 'boolean')?n.server:(n.server == "server");
|
||||
this.closing = false;
|
||||
this.connected = false;
|
||||
var node = this;
|
||||
var count = 0;
|
||||
if (n.tls) { var tlsNode = RED.nodes.getNode(n.tls); }
|
||||
|
||||
if (!node.server) {
|
||||
var buffer = null;
|
||||
@@ -70,13 +104,25 @@ module.exports = function(RED) {
|
||||
node.log(RED._("tcpin.status.connecting",{host:node.host,port:node.port}));
|
||||
node.status({fill:"grey",shape:"dot",text:"common.status.connecting"});
|
||||
var id = RED.util.generateId();
|
||||
client = net.connect(node.port, node.host, function() {
|
||||
buffer = (node.datatype == 'buffer') ? Buffer.alloc(0) : "";
|
||||
node.connected = true;
|
||||
node.log(RED._("tcpin.status.connected",{host:node.host,port:node.port}));
|
||||
node.status({fill:"green",shape:"dot",text:"common.status.connected",_session:{type:"tcp",id:id}});
|
||||
});
|
||||
client.setKeepAlive(true,120000);
|
||||
var connOpts = {host: node.host};
|
||||
if (n.tls) {
|
||||
var connOpts = tlsNode.addTLSOptions({host: node.host});
|
||||
client = tls.connect(node.port, connOpts, function() {
|
||||
buffer = (node.datatype == 'buffer') ? Buffer.alloc(0) : "";
|
||||
node.connected = true;
|
||||
node.log(RED._("status.connected", {host: node.host, port: node.port}));
|
||||
node.status({fill:"green",shape:"dot",text:"common.status.connected",_session:{type:"tcp",id:id}});
|
||||
});
|
||||
}
|
||||
else {
|
||||
client = net.connect(node.port, node.host, function() {
|
||||
buffer = (node.datatype == 'buffer') ? Buffer.alloc(0) : "";
|
||||
node.connected = true;
|
||||
node.log(RED._("tcpin.status.connected",{host:node.host,port:node.port}));
|
||||
node.status({fill:"green",shape:"dot",text:"common.status.connected",_session:{type:"tcp",id:id}});
|
||||
});
|
||||
}
|
||||
client.setKeepAlive(true, 120000);
|
||||
connectionPool[id] = client;
|
||||
|
||||
client.on('data', function (data) {
|
||||
@@ -89,7 +135,7 @@ module.exports = function(RED) {
|
||||
buffer = buffer+data;
|
||||
var parts = buffer.split(node.newline);
|
||||
for (var i = 0; i<parts.length-1; i+=1) {
|
||||
msg = {topic:node.topic, payload:parts[i]};
|
||||
msg = {topic:node.topic, payload:parts[i] + node.newline.trimEnd()};
|
||||
msg._session = {type:"tcp",id:id};
|
||||
node.send(msg);
|
||||
}
|
||||
@@ -150,7 +196,13 @@ module.exports = function(RED) {
|
||||
});
|
||||
}
|
||||
else {
|
||||
var server = net.createServer(function (socket) {
|
||||
let srv = net;
|
||||
let connOpts;
|
||||
if (n.tls) {
|
||||
srv = tls;
|
||||
connOpts = tlsNode.addTLSOptions({});
|
||||
}
|
||||
var server = srv.createServer(connOpts, function (socket) {
|
||||
socket.setKeepAlive(true,120000);
|
||||
if (socketTimeout !== null) { socket.setTimeout(socketTimeout); }
|
||||
var id = RED.util.generateId();
|
||||
@@ -177,7 +229,7 @@ module.exports = function(RED) {
|
||||
buffer = buffer+data;
|
||||
var parts = buffer.split(node.newline);
|
||||
for (var i = 0; i<parts.length-1; i+=1) {
|
||||
msg = {topic:node.topic, payload:parts[i], ip:socket.remoteAddress, port:socket.remotePort};
|
||||
msg = {topic:node.topic, payload:parts[i] + node.newline.trimEnd(), ip:socket.remoteAddress, port:socket.remotePort};
|
||||
msg._session = {type:"tcp",id:id};
|
||||
node.send(msg);
|
||||
}
|
||||
@@ -269,8 +321,9 @@ module.exports = function(RED) {
|
||||
this.closing = false;
|
||||
this.connected = false;
|
||||
var node = this;
|
||||
if (n.tls) { var tlsNode = RED.nodes.getNode(n.tls); }
|
||||
|
||||
if (!node.beserver||node.beserver=="client") {
|
||||
if (!node.beserver || node.beserver == "client") {
|
||||
var reconnectTimeout;
|
||||
var client = null;
|
||||
var end = false;
|
||||
@@ -278,11 +331,24 @@ module.exports = function(RED) {
|
||||
var setupTcpClient = function() {
|
||||
node.log(RED._("tcpin.status.connecting",{host:node.host,port:node.port}));
|
||||
node.status({fill:"grey",shape:"dot",text:"common.status.connecting"});
|
||||
client = net.connect(node.port, node.host, function() {
|
||||
node.connected = true;
|
||||
node.log(RED._("tcpin.status.connected",{host:node.host,port:node.port}));
|
||||
node.status({fill:"green",shape:"dot",text:"common.status.connected"});
|
||||
});
|
||||
if (n.tls) {
|
||||
// connOpts = tlsNode.addTLSOptions(connOpts);
|
||||
// client = tls.connect(connOpts, function() {
|
||||
var connOpts = tlsNode.addTLSOptions({host: node.host});
|
||||
client = tls.connect(node.port, connOpts, function() {
|
||||
// buffer = (node.datatype == 'buffer') ? Buffer.alloc(0) : "";
|
||||
node.connected = true;
|
||||
node.log(RED._("status.connected", {host: node.host, port: node.port}));
|
||||
node.status({fill:"green",shape:"dot",text:"common.status.connected"});
|
||||
});
|
||||
}
|
||||
else {
|
||||
client = net.connect(node.port, node.host, function() {
|
||||
node.connected = true;
|
||||
node.log(RED._("tcpin.status.connected",{host:node.host,port:node.port}));
|
||||
node.status({fill:"green",shape:"dot",text:"common.status.connected"});
|
||||
});
|
||||
}
|
||||
client.setKeepAlive(true,120000);
|
||||
client.on('error', function (err) {
|
||||
node.log(RED._("tcpin.errors.error",{error:err.toString()}));
|
||||
@@ -368,7 +434,13 @@ module.exports = function(RED) {
|
||||
else {
|
||||
var connectedSockets = [];
|
||||
node.status({text:RED._("tcpin.status.connections",{count:0})});
|
||||
var server = net.createServer(function (socket) {
|
||||
let srv = net;
|
||||
let connOpts;
|
||||
if (n.tls) {
|
||||
srv = tls;
|
||||
connOpts = tlsNode.addTLSOptions({});
|
||||
}
|
||||
var server = srv.createServer(connOpts, function (socket) {
|
||||
socket.setKeepAlive(true,120000);
|
||||
if (socketTimeout !== null) { socket.setTimeout(socketTimeout); }
|
||||
node.log(RED._("tcpin.status.connection-from",{host:socket.remoteAddress, port:socket.remotePort}));
|
||||
@@ -445,7 +517,11 @@ module.exports = function(RED) {
|
||||
this.port = Number(n.port);
|
||||
this.out = n.out;
|
||||
this.ret = n.ret || "buffer";
|
||||
this.newline = (n.newline||"").replace("\\n","\n").replace("\\r","\r").replace("\\t","\t");
|
||||
this.splitc = n.splitc;
|
||||
if (n.tls) {
|
||||
var tlsNode = RED.nodes.getNode(n.tls);
|
||||
}
|
||||
|
||||
if (this.out === "immed") { this.splitc = -1; this.out = "time"; }
|
||||
if (this.out !== "char") { this.splitc = Number(this.splitc); }
|
||||
@@ -500,12 +576,48 @@ module.exports = function(RED) {
|
||||
}
|
||||
else { buf = Buffer.alloc(65536); } // set it to 64k... hopefully big enough for most TCP packets.... but only hopefully
|
||||
|
||||
clients[connection_id].client = net.Socket();
|
||||
var connOpts = {host:host, port:port};
|
||||
if (n.tls) {
|
||||
connOpts = tlsNode.addTLSOptions(connOpts);
|
||||
const allowUnauthorized = getAllowUnauthorized();
|
||||
|
||||
let options = {
|
||||
rejectUnauthorized: !allowUnauthorized,
|
||||
ciphers: tls.DEFAULT_CIPHERS,
|
||||
checkServerIdentity: tls.checkServerIdentity,
|
||||
minDHSize: 1024,
|
||||
...connOpts
|
||||
};
|
||||
|
||||
if (!options.keepAlive) { options.singleUse = true; }
|
||||
|
||||
const context = options.secureContext || tls.createSecureContext(options);
|
||||
|
||||
clients[connection_id].client = new tls.TLSSocket(options.socket, {
|
||||
allowHalfOpen: options.allowHalfOpen,
|
||||
pipe: !!options.path,
|
||||
secureContext: context,
|
||||
isServer: false,
|
||||
requestCert: false, // true,
|
||||
rejectUnauthorized: false, // options.rejectUnauthorized !== false,
|
||||
session: options.session,
|
||||
ALPNProtocols: options.ALPNProtocols,
|
||||
requestOCSP: options.requestOCSP,
|
||||
enableTrace: options.enableTrace,
|
||||
pskCallback: options.pskCallback,
|
||||
highWaterMark: options.highWaterMark,
|
||||
onread: options.onread,
|
||||
signal: options.signal,
|
||||
});
|
||||
}
|
||||
else {
|
||||
clients[connection_id].client = net.Socket();
|
||||
}
|
||||
if (socketTimeout !== null) { clients[connection_id].client.setTimeout(socketTimeout);}
|
||||
|
||||
if (host && port) {
|
||||
clients[connection_id].connecting = true;
|
||||
clients[connection_id].client.connect(port, host, function() {
|
||||
clients[connection_id].client.connect(connOpts, function() {
|
||||
//node.log(RED._("tcpin.errors.client-connected"));
|
||||
node.status({fill:"green",shape:"dot",text:"common.status.connected"});
|
||||
if (clients[connection_id] && clients[connection_id].client) {
|
||||
@@ -528,17 +640,32 @@ module.exports = function(RED) {
|
||||
else {
|
||||
node.warn(RED._("tcpin.errors.no-host"));
|
||||
}
|
||||
|
||||
var chunk = "";
|
||||
clients[connection_id].client.on('data', function(data) {
|
||||
if (node.out === "sit") { // if we are staying connected just send the buffer
|
||||
if (clients[connection_id]) {
|
||||
const msg = clients[connection_id].lastMsg || {};
|
||||
msg.payload = RED.util.cloneMessage(data);
|
||||
if (node.ret === "string") {
|
||||
try { msg.payload = msg.payload.toString(); }
|
||||
catch(e) { node.error("Failed to create string", msg); }
|
||||
try {
|
||||
if (node.newline && node.newline !== "" ) {
|
||||
chunk += msg.payload.toString();
|
||||
let parts = chunk.split(node.newline);
|
||||
for (var p=0; p<parts.length-1; p+=1) {
|
||||
let m = RED.util.cloneMessage(msg);
|
||||
m.payload = parts[p] + node.newline.trimEnd();
|
||||
nodeSend(m);
|
||||
}
|
||||
chunk = parts[parts.length-1];
|
||||
}
|
||||
else {
|
||||
msg.payload = msg.payload.toString();
|
||||
nodeSend(msg);
|
||||
}
|
||||
}
|
||||
catch(e) { node.error(RED._("tcpin.errors.bad-string"), msg); }
|
||||
}
|
||||
nodeSend(msg);
|
||||
else { nodeSend(msg); }
|
||||
}
|
||||
}
|
||||
// else if (node.splitc === 0) {
|
||||
@@ -675,7 +802,13 @@ module.exports = function(RED) {
|
||||
//node.warn(RED._("tcpin.errors.connect-timeout"));
|
||||
if (clients[connection_id].client) {
|
||||
clients[connection_id].connecting = true;
|
||||
clients[connection_id].client.connect(port, host, function() {
|
||||
|
||||
var connOpts = {host:host, port:port};
|
||||
if (n.tls) {
|
||||
connOpts = tlsNode.addTLSOptions(connOpts);
|
||||
}
|
||||
|
||||
clients[connection_id].client.connect(connOpts, function() {
|
||||
clients[connection_id].connected = true;
|
||||
clients[connection_id].connecting = false;
|
||||
node.status({fill:"green",shape:"dot",text:"common.status.connected"});
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
[
|
||||
{
|
||||
"id": "62ea32aa.d73aac",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"name": "Example: Link Call Node",
|
||||
"info": "Link call node can call link in node then get result from link out node.",
|
||||
"x": 230,
|
||||
"y": 180,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "c588bc36.87fec",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"name": "↓ call link in node",
|
||||
"info": "",
|
||||
"x": 440,
|
||||
"y": 220,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "cd31efb4d2c6967e",
|
||||
"type": "link call",
|
||||
"z": "6312c0588348b2d4",
|
||||
"name": "",
|
||||
"links": [
|
||||
"dbc46892c8d14c37"
|
||||
],
|
||||
"timeout": "30",
|
||||
"x": 420,
|
||||
"y": 260,
|
||||
"wires": [
|
||||
[
|
||||
"c3db64d1d2260340"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "dbc46892c8d14c37",
|
||||
"type": "link in",
|
||||
"z": "6312c0588348b2d4",
|
||||
"name": "",
|
||||
"links": [],
|
||||
"x": 315,
|
||||
"y": 340,
|
||||
"wires": [
|
||||
[
|
||||
"e10575d73f2e5352"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "6b61792143b3b0a3",
|
||||
"type": "inject",
|
||||
"z": "6312c0588348b2d4",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 240,
|
||||
"y": 260,
|
||||
"wires": [
|
||||
[
|
||||
"cd31efb4d2c6967e"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "e10575d73f2e5352",
|
||||
"type": "change",
|
||||
"z": "6312c0588348b2d4",
|
||||
"name": "",
|
||||
"rules": [
|
||||
{
|
||||
"t": "set",
|
||||
"p": "payload",
|
||||
"pt": "msg",
|
||||
"to": "Hello, World!",
|
||||
"tot": "str"
|
||||
}
|
||||
],
|
||||
"action": "",
|
||||
"property": "",
|
||||
"from": "",
|
||||
"to": "",
|
||||
"reg": false,
|
||||
"x": 450,
|
||||
"y": 340,
|
||||
"wires": [
|
||||
[
|
||||
"cf8438e7137bc0f0"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cf8438e7137bc0f0",
|
||||
"type": "link out",
|
||||
"z": "6312c0588348b2d4",
|
||||
"name": "",
|
||||
"mode": "return",
|
||||
"links": [],
|
||||
"x": 595,
|
||||
"y": 340,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "c3db64d1d2260340",
|
||||
"type": "debug",
|
||||
"z": "6312c0588348b2d4",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 600,
|
||||
"y": 260,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "6d077dfa0987febb",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"name": "↑called from link call node",
|
||||
"info": "",
|
||||
"x": 410,
|
||||
"y": 380,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "53b9a0adfd8c4217",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"name": "↑return to link call node",
|
||||
"info": "",
|
||||
"x": 680,
|
||||
"y": 380,
|
||||
"wires": []
|
||||
}
|
||||
]
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"id": "84222b92.d65d18",
|
||||
"type": "inject",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
@@ -20,8 +20,8 @@
|
||||
"topic": "",
|
||||
"payload": "Hello, World!",
|
||||
"payloadType": "str",
|
||||
"x": 190,
|
||||
"y": 180,
|
||||
"x": 230,
|
||||
"y": 220,
|
||||
"wires": [
|
||||
[
|
||||
"b4b9f603.739598"
|
||||
@@ -31,25 +31,25 @@
|
||||
{
|
||||
"id": "7b014430.dfd94c",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "Write string to a file, then read from the file",
|
||||
"info": "Read file node can read string from a file.",
|
||||
"x": 220,
|
||||
"y": 100,
|
||||
"info": "File-in node can read string from a file.",
|
||||
"x": 260,
|
||||
"y": 140,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "b4b9f603.739598",
|
||||
"type": "file",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"appendNewline": true,
|
||||
"createDir": false,
|
||||
"overwriteFile": "true",
|
||||
"encoding": "none",
|
||||
"x": 380,
|
||||
"y": 180,
|
||||
"x": 420,
|
||||
"y": 220,
|
||||
"wires": [
|
||||
[
|
||||
"6dc01cac.5c4bf4"
|
||||
@@ -59,7 +59,7 @@
|
||||
{
|
||||
"id": "2587adb9.7e60f2",
|
||||
"type": "debug",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
@@ -68,22 +68,22 @@
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 770,
|
||||
"y": 180,
|
||||
"x": 810,
|
||||
"y": 220,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "6dc01cac.5c4bf4",
|
||||
"type": "file in",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"format": "utf8",
|
||||
"chunk": false,
|
||||
"sendError": false,
|
||||
"encoding": "none",
|
||||
"x": 580,
|
||||
"y": 180,
|
||||
"x": 620,
|
||||
"y": 220,
|
||||
"wires": [
|
||||
[
|
||||
"2587adb9.7e60f2"
|
||||
@@ -93,21 +93,21 @@
|
||||
{
|
||||
"id": "f4b4309a.3b78a",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "↑read result from file",
|
||||
"info": "",
|
||||
"x": 590,
|
||||
"y": 220,
|
||||
"x": 630,
|
||||
"y": 260,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "672d3693.3cabd8",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "↓write to /tmp/hello.txt",
|
||||
"info": "",
|
||||
"x": 400,
|
||||
"y": 140,
|
||||
"x": 440,
|
||||
"y": 180,
|
||||
"wires": []
|
||||
}
|
||||
]
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"id": "8997398f.c5d628",
|
||||
"type": "inject",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
@@ -20,8 +20,8 @@
|
||||
"topic": "",
|
||||
"payload": "😀",
|
||||
"payloadType": "str",
|
||||
"x": 170,
|
||||
"y": 260,
|
||||
"x": 210,
|
||||
"y": 480,
|
||||
"wires": [
|
||||
[
|
||||
"56e32d23.050f44"
|
||||
@@ -31,25 +31,25 @@
|
||||
{
|
||||
"id": "4e598e65.1799d",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "Read data in specified encoding",
|
||||
"info": "Read file node can specify encoding of data read from a file.",
|
||||
"x": 190,
|
||||
"y": 180,
|
||||
"info": "File-in node can specify encoding of data read from a file.",
|
||||
"x": 230,
|
||||
"y": 400,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "56e32d23.050f44",
|
||||
"type": "file",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"appendNewline": true,
|
||||
"createDir": false,
|
||||
"overwriteFile": "true",
|
||||
"encoding": "none",
|
||||
"x": 340,
|
||||
"y": 260,
|
||||
"x": 380,
|
||||
"y": 480,
|
||||
"wires": [
|
||||
[
|
||||
"38fa0579.f2cd8a"
|
||||
@@ -59,7 +59,7 @@
|
||||
{
|
||||
"id": "d28c8994.99c0a8",
|
||||
"type": "debug",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
@@ -68,23 +68,22 @@
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 730,
|
||||
"y": 260,
|
||||
"x": 770,
|
||||
"y": 480,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "38fa0579.f2cd8a",
|
||||
"type": "file in",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"format": "utf8",
|
||||
"chunk": false,
|
||||
"sendError": false,
|
||||
"encoding": "base64",
|
||||
"allProps": false,
|
||||
"x": 540,
|
||||
"y": 260,
|
||||
"x": 580,
|
||||
"y": 480,
|
||||
"wires": [
|
||||
[
|
||||
"d28c8994.99c0a8"
|
||||
@@ -94,21 +93,21 @@
|
||||
{
|
||||
"id": "fa22ca20.ae4528",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "↑read data from file as base64 string",
|
||||
"info": "",
|
||||
"x": 600,
|
||||
"y": 300,
|
||||
"x": 640,
|
||||
"y": 520,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "148e25ad.98891a",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "↓write to /tmp/hello.txt",
|
||||
"info": "",
|
||||
"x": 360,
|
||||
"y": 220,
|
||||
"x": 400,
|
||||
"y": 440,
|
||||
"wires": []
|
||||
}
|
||||
]
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"id": "6a0b1d03.d4cee4",
|
||||
"type": "inject",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
@@ -20,8 +20,8 @@
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 160,
|
||||
"y": 220,
|
||||
"x": 220,
|
||||
"y": 740,
|
||||
"wires": [
|
||||
[
|
||||
"d4b00cb7.a5a23"
|
||||
@@ -31,25 +31,25 @@
|
||||
{
|
||||
"id": "f17ea1d1.8ecc3",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "Read data breaking lines into individual messages",
|
||||
"info": "Read file node can break read text into messages with individual lines",
|
||||
"x": 230,
|
||||
"y": 140,
|
||||
"info": "File-in node can break read text into messages with individual lines",
|
||||
"x": 290,
|
||||
"y": 660,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "99ae7806.1d6428",
|
||||
"type": "file",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"appendNewline": true,
|
||||
"createDir": false,
|
||||
"overwriteFile": "true",
|
||||
"encoding": "none",
|
||||
"x": 480,
|
||||
"y": 220,
|
||||
"x": 540,
|
||||
"y": 740,
|
||||
"wires": [
|
||||
[
|
||||
"70d7892f.d27db8"
|
||||
@@ -59,7 +59,7 @@
|
||||
{
|
||||
"id": "7ed8282c.92b338",
|
||||
"type": "debug",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
@@ -68,22 +68,22 @@
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 750,
|
||||
"y": 280,
|
||||
"x": 810,
|
||||
"y": 800,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "70d7892f.d27db8",
|
||||
"type": "file in",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"format": "lines",
|
||||
"chunk": false,
|
||||
"sendError": false,
|
||||
"encoding": "none",
|
||||
"x": 560,
|
||||
"y": 280,
|
||||
"x": 620,
|
||||
"y": 800,
|
||||
"wires": [
|
||||
[
|
||||
"7ed8282c.92b338"
|
||||
@@ -93,27 +93,27 @@
|
||||
{
|
||||
"id": "c1b7e05.1d94b2",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "↑read data from file breaking lines into messages",
|
||||
"info": "",
|
||||
"x": 660,
|
||||
"y": 320,
|
||||
"x": 720,
|
||||
"y": 840,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "a5f647b2.cf27a8",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "↓write to /tmp/hello.txt",
|
||||
"info": "",
|
||||
"x": 500,
|
||||
"y": 180,
|
||||
"x": 560,
|
||||
"y": 700,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "d4b00cb7.a5a23",
|
||||
"type": "template",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "data",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
@@ -121,8 +121,8 @@
|
||||
"syntax": "plain",
|
||||
"template": "one\ntwo\nthree!",
|
||||
"output": "str",
|
||||
"x": 310,
|
||||
"y": 220,
|
||||
"x": 370,
|
||||
"y": 740,
|
||||
"wires": [
|
||||
[
|
||||
"99ae7806.1d6428"
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"id": "bdd57acc.2edc48",
|
||||
"type": "inject",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
@@ -20,8 +20,8 @@
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 180,
|
||||
"y": 220,
|
||||
"x": 220,
|
||||
"y": 1040,
|
||||
"wires": [
|
||||
[
|
||||
"7a069b01.0c2324"
|
||||
@@ -31,25 +31,25 @@
|
||||
{
|
||||
"id": "1fd12220.33953e",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "Creating a message stream from lines of data",
|
||||
"info": "Read file node can break read text into messages with individual lines. The messages creates a stream of messages.",
|
||||
"x": 230,
|
||||
"y": 140,
|
||||
"info": "File-in node can break read text into messages with individual lines. The messages creates a stream of messages.",
|
||||
"x": 270,
|
||||
"y": 960,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "ab6eb213.2a08d",
|
||||
"type": "file",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"appendNewline": true,
|
||||
"createDir": false,
|
||||
"overwriteFile": "true",
|
||||
"encoding": "none",
|
||||
"x": 500,
|
||||
"y": 220,
|
||||
"x": 540,
|
||||
"y": 1040,
|
||||
"wires": [
|
||||
[
|
||||
"b7ed49b0.649fb8"
|
||||
@@ -59,7 +59,7 @@
|
||||
{
|
||||
"id": "c48d8ae0.9ff3a8",
|
||||
"type": "debug",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
@@ -68,22 +68,22 @@
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 770,
|
||||
"y": 320,
|
||||
"x": 810,
|
||||
"y": 1140,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "b7ed49b0.649fb8",
|
||||
"type": "file in",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"format": "lines",
|
||||
"chunk": false,
|
||||
"sendError": false,
|
||||
"encoding": "none",
|
||||
"x": 240,
|
||||
"y": 320,
|
||||
"x": 280,
|
||||
"y": 1140,
|
||||
"wires": [
|
||||
[
|
||||
"83073ebe.fcce4"
|
||||
@@ -93,27 +93,27 @@
|
||||
{
|
||||
"id": "3c33e69f.6a04ba",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "↑read data from file breaking lines into messages",
|
||||
"info": "",
|
||||
"x": 340,
|
||||
"y": 360,
|
||||
"x": 380,
|
||||
"y": 1180,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "3598bf7d.5712a",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "↓write to /tmp/hello.txt",
|
||||
"info": "",
|
||||
"x": 520,
|
||||
"y": 180,
|
||||
"x": 560,
|
||||
"y": 1000,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "7a069b01.0c2324",
|
||||
"type": "template",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "data",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
@@ -121,8 +121,8 @@
|
||||
"syntax": "plain",
|
||||
"template": "Apple\nBanana\nGrape\nOrange",
|
||||
"output": "str",
|
||||
"x": 330,
|
||||
"y": 220,
|
||||
"x": 370,
|
||||
"y": 1040,
|
||||
"wires": [
|
||||
[
|
||||
"ab6eb213.2a08d"
|
||||
@@ -132,7 +132,7 @@
|
||||
{
|
||||
"id": "8d4ed1d0.821fe",
|
||||
"type": "join",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"mode": "auto",
|
||||
"build": "string",
|
||||
@@ -145,8 +145,8 @@
|
||||
"timeout": "",
|
||||
"count": "",
|
||||
"reduceRight": false,
|
||||
"x": 590,
|
||||
"y": 320,
|
||||
"x": 630,
|
||||
"y": 1140,
|
||||
"wires": [
|
||||
[
|
||||
"c48d8ae0.9ff3a8"
|
||||
@@ -156,7 +156,7 @@
|
||||
{
|
||||
"id": "83073ebe.fcce4",
|
||||
"type": "switch",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "< D",
|
||||
"property": "payload",
|
||||
"propertyType": "msg",
|
||||
@@ -170,8 +170,8 @@
|
||||
"checkall": "true",
|
||||
"repair": true,
|
||||
"outputs": 1,
|
||||
"x": 430,
|
||||
"y": 320,
|
||||
"x": 470,
|
||||
"y": 1140,
|
||||
"wires": [
|
||||
[
|
||||
"8d4ed1d0.821fe"
|
||||
@@ -181,21 +181,21 @@
|
||||
{
|
||||
"id": "2088e195.f7aebe",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "↓filter data before \"D\"",
|
||||
"info": "",
|
||||
"x": 480,
|
||||
"y": 280,
|
||||
"x": 520,
|
||||
"y": 1100,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "b848cdc7.61e06",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "↑join to single string",
|
||||
"info": "",
|
||||
"x": 630,
|
||||
"y": 360,
|
||||
"x": 670,
|
||||
"y": 1180,
|
||||
"wires": []
|
||||
}
|
||||
]
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"id": "84222b92.d65d18",
|
||||
"type": "inject",
|
||||
"z": "5132b95f037524f9",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
@@ -20,8 +20,8 @@
|
||||
"topic": "",
|
||||
"payload": "Hello, World!",
|
||||
"payloadType": "str",
|
||||
"x": 150,
|
||||
"y": 220,
|
||||
"x": 230,
|
||||
"y": 200,
|
||||
"wires": [
|
||||
[
|
||||
"b4b9f603.739598"
|
||||
@@ -31,25 +31,25 @@
|
||||
{
|
||||
"id": "7b014430.dfd94c",
|
||||
"type": "comment",
|
||||
"z": "5132b95f037524f9",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Write string to a file, then read from the file",
|
||||
"info": "Write file node can write string from a file.",
|
||||
"x": 180,
|
||||
"y": 140,
|
||||
"info": "File node can write string to a file.",
|
||||
"x": 260,
|
||||
"y": 120,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "b4b9f603.739598",
|
||||
"type": "file",
|
||||
"z": "5132b95f037524f9",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"appendNewline": true,
|
||||
"createDir": false,
|
||||
"overwriteFile": "true",
|
||||
"encoding": "none",
|
||||
"x": 340,
|
||||
"y": 220,
|
||||
"x": 420,
|
||||
"y": 200,
|
||||
"wires": [
|
||||
[
|
||||
"6dc01cac.5c4bf4"
|
||||
@@ -59,7 +59,7 @@
|
||||
{
|
||||
"id": "2587adb9.7e60f2",
|
||||
"type": "debug",
|
||||
"z": "5132b95f037524f9",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
@@ -68,22 +68,22 @@
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 730,
|
||||
"y": 220,
|
||||
"x": 810,
|
||||
"y": 200,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "6dc01cac.5c4bf4",
|
||||
"type": "file in",
|
||||
"z": "5132b95f037524f9",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"format": "utf8",
|
||||
"chunk": false,
|
||||
"sendError": false,
|
||||
"encoding": "none",
|
||||
"x": 540,
|
||||
"y": 220,
|
||||
"x": 620,
|
||||
"y": 200,
|
||||
"wires": [
|
||||
[
|
||||
"2587adb9.7e60f2"
|
||||
@@ -93,21 +93,21 @@
|
||||
{
|
||||
"id": "f4b4309a.3b78a",
|
||||
"type": "comment",
|
||||
"z": "5132b95f037524f9",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "↑read result from file",
|
||||
"info": "",
|
||||
"x": 550,
|
||||
"y": 260,
|
||||
"x": 630,
|
||||
"y": 240,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "672d3693.3cabd8",
|
||||
"type": "comment",
|
||||
"z": "5132b95f037524f9",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "↓write to /tmp/hello.txt",
|
||||
"info": "",
|
||||
"x": 360,
|
||||
"y": 180,
|
||||
"x": 440,
|
||||
"y": 160,
|
||||
"wires": []
|
||||
}
|
||||
]
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"id": "704479e1.399388",
|
||||
"type": "inject",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
@@ -25,8 +25,8 @@
|
||||
"topic": "",
|
||||
"payload": "Hello, World!",
|
||||
"payloadType": "str",
|
||||
"x": 190,
|
||||
"y": 260,
|
||||
"x": 230,
|
||||
"y": 400,
|
||||
"wires": [
|
||||
[
|
||||
"402f3b7e.988014"
|
||||
@@ -36,25 +36,25 @@
|
||||
{
|
||||
"id": "8e876a75.e9beb8",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Write string to a file specied by filename property, the read from the file",
|
||||
"info": "Write file node can target file using `filename` property.",
|
||||
"x": 310,
|
||||
"y": 180,
|
||||
"info": "File node can target file using `filename` property.",
|
||||
"x": 350,
|
||||
"y": 320,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "402f3b7e.988014",
|
||||
"type": "file",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"filename": "",
|
||||
"appendNewline": true,
|
||||
"createDir": false,
|
||||
"overwriteFile": "true",
|
||||
"encoding": "none",
|
||||
"x": 350,
|
||||
"y": 260,
|
||||
"x": 390,
|
||||
"y": 400,
|
||||
"wires": [
|
||||
[
|
||||
"26e077d6.bbcd98"
|
||||
@@ -64,7 +64,7 @@
|
||||
{
|
||||
"id": "97b6b6b2.a54b38",
|
||||
"type": "debug",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
@@ -73,22 +73,22 @@
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 730,
|
||||
"y": 260,
|
||||
"x": 770,
|
||||
"y": 400,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "26e077d6.bbcd98",
|
||||
"type": "file in",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"format": "utf8",
|
||||
"chunk": false,
|
||||
"sendError": false,
|
||||
"encoding": "none",
|
||||
"x": 540,
|
||||
"y": 260,
|
||||
"x": 580,
|
||||
"y": 400,
|
||||
"wires": [
|
||||
[
|
||||
"97b6b6b2.a54b38"
|
||||
@@ -98,21 +98,21 @@
|
||||
{
|
||||
"id": "85062297.da79",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "↑read result from file",
|
||||
"info": "",
|
||||
"x": 550,
|
||||
"y": 300,
|
||||
"x": 590,
|
||||
"y": 440,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "7316c4fc.b1dcdc",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "↓write to file specified by filename property",
|
||||
"info": "",
|
||||
"x": 460,
|
||||
"y": 220,
|
||||
"x": 500,
|
||||
"y": 360,
|
||||
"wires": []
|
||||
}
|
||||
]
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"id": "4ac00fb0.d5f52",
|
||||
"type": "inject",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
@@ -20,8 +20,8 @@
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 180,
|
||||
"y": 220,
|
||||
"x": 220,
|
||||
"y": 600,
|
||||
"wires": [
|
||||
[
|
||||
"542cc2f4.92857c"
|
||||
@@ -31,25 +31,25 @@
|
||||
{
|
||||
"id": "671f8295.0e6f6c",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Delete a file",
|
||||
"info": "Write file node can delete a file.",
|
||||
"x": 130,
|
||||
"y": 160,
|
||||
"info": "File node can delete a file.",
|
||||
"x": 170,
|
||||
"y": 540,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "542cc2f4.92857c",
|
||||
"type": "file",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"appendNewline": true,
|
||||
"createDir": false,
|
||||
"overwriteFile": "delete",
|
||||
"encoding": "none",
|
||||
"x": 380,
|
||||
"y": 220,
|
||||
"x": 420,
|
||||
"y": 600,
|
||||
"wires": [
|
||||
[
|
||||
"a24da523.5babe8"
|
||||
@@ -59,7 +59,7 @@
|
||||
{
|
||||
"id": "a24da523.5babe8",
|
||||
"type": "debug",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
@@ -68,18 +68,18 @@
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 590,
|
||||
"y": 220,
|
||||
"x": 630,
|
||||
"y": 600,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "51157051.2f62",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "↓delete a file",
|
||||
"info": "",
|
||||
"x": 350,
|
||||
"y": 180,
|
||||
"x": 390,
|
||||
"y": 560,
|
||||
"wires": []
|
||||
}
|
||||
]
|
||||
@@ -2,8 +2,8 @@
|
||||
{
|
||||
"id": "e4ef1f5e.7cd82",
|
||||
"type": "inject",
|
||||
"z": "6312c0588348b2d4",
|
||||
"name": "Base64 encoded string",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
@@ -20,8 +20,8 @@
|
||||
"topic": "",
|
||||
"payload": "8J+YgA==",
|
||||
"payloadType": "str",
|
||||
"x": 200,
|
||||
"y": 220,
|
||||
"x": 220,
|
||||
"y": 820,
|
||||
"wires": [
|
||||
[
|
||||
"72b37cc8.177054"
|
||||
@@ -31,25 +31,25 @@
|
||||
{
|
||||
"id": "f5997af4.5a9298",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Specify encoding of written data",
|
||||
"info": "Write file node can specify encoding of data.",
|
||||
"x": 170,
|
||||
"y": 140,
|
||||
"info": "File node can specify encoding of data.",
|
||||
"x": 230,
|
||||
"y": 740,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "72b37cc8.177054",
|
||||
"type": "file",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"appendNewline": true,
|
||||
"createDir": false,
|
||||
"overwriteFile": "true",
|
||||
"encoding": "base64",
|
||||
"x": 420,
|
||||
"y": 220,
|
||||
"x": 400,
|
||||
"y": 820,
|
||||
"wires": [
|
||||
[
|
||||
"2da33ec.f45cac2"
|
||||
@@ -59,7 +59,7 @@
|
||||
{
|
||||
"id": "2e814354.278c8c",
|
||||
"type": "debug",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
@@ -68,22 +68,22 @@
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 810,
|
||||
"y": 220,
|
||||
"x": 790,
|
||||
"y": 820,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "2da33ec.f45cac2",
|
||||
"type": "file in",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"format": "utf8",
|
||||
"chunk": false,
|
||||
"sendError": false,
|
||||
"encoding": "none",
|
||||
"x": 620,
|
||||
"y": 220,
|
||||
"x": 600,
|
||||
"y": 820,
|
||||
"wires": [
|
||||
[
|
||||
"2e814354.278c8c"
|
||||
@@ -93,21 +93,21 @@
|
||||
{
|
||||
"id": "ec754c99.84bfd",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "↓write string with base64 encoding",
|
||||
"info": "",
|
||||
"x": 480,
|
||||
"y": 180,
|
||||
"x": 460,
|
||||
"y": 780,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "3e6704ff.4ce25c",
|
||||
"type": "comment",
|
||||
"z": "6312c0588348b2d4",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "↑read result from file",
|
||||
"info": "",
|
||||
"x": 630,
|
||||
"y": 260,
|
||||
"x": 610,
|
||||
"y": 860,
|
||||
"wires": []
|
||||
}
|
||||
]
|
||||
@@ -21,7 +21,7 @@
|
||||
<dt>msg <span class="property-type">object</span></dt>
|
||||
<dd>A msg object containing information to populate the template.</dd>
|
||||
<dt class="optional">template <span class="property-type">string</span></dt>
|
||||
<dd>A template to be populated from <code>msg.payload</code>. If not configured in the edit panel,
|
||||
<dd>A template to be populated from msg.payload. If not configured in the edit panel,
|
||||
this can be set as a property of msg.</dd>
|
||||
</dl>
|
||||
<h3>Outputs</h3>
|
||||
|
||||
@@ -60,5 +60,5 @@
|
||||
for the next topic.
|
||||
</p>
|
||||
<p><b>Note</b>: In rate limit mode the maximum queue depth can be set by a property in your
|
||||
<i>settings.js</i> file. For example <code>nodeMessageBufferMaxLength: 1000,</code></p>
|
||||
<i>settings.js</i> file. For example <code>nodeMessageBufferMaxLength: 1000,</code>
|
||||
</script>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<h3>Details</h3>
|
||||
<p>In RBE mode this node will block until the <code>msg.payload</code>,
|
||||
(or selected property) value is different to the previous one.
|
||||
If required it can ignore the initial value, so as not to send anything at start.</p>
|
||||
If required it can ignore the intial value, so as not to send anything at start.</p>
|
||||
<p>The <a href="https://en.wikipedia.org/wiki/Deadband" target="_blank">Deadband</a> modes will block the incoming value
|
||||
<i>unless</i> its change is greater or greater-equal than ± the band gap away from a previous value.</p>
|
||||
<p>The Narrowband modes will block the incoming value,
|
||||
@@ -37,5 +37,5 @@
|
||||
ignoring any values out of range, or the previous input value, which resets the set point, thus allowing
|
||||
gradual drift (deadband), or a step change (narrowband).</p>
|
||||
<p><b>Note:</b> This works on a per <code>msg.topic</code> basis, though this can be changed to another property if desired.
|
||||
This means that a single filter node can handle multiple different topics at the same time.</p>
|
||||
This means that a single rbe node can handle multiple different topics at the same time.</p>
|
||||
</script>
|
||||
|
||||
@@ -579,7 +579,9 @@
|
||||
"server": "Server",
|
||||
"return": "Return",
|
||||
"ms": "ms",
|
||||
"chars": "chars"
|
||||
"chars": "chars",
|
||||
"close": "Close",
|
||||
"optional": "(optional)"
|
||||
},
|
||||
"type": {
|
||||
"listen": "Listen on",
|
||||
@@ -596,7 +598,7 @@
|
||||
"return": {
|
||||
"timeout": "after a fixed timeout of",
|
||||
"character": "when character received is",
|
||||
"number": "a fixed number of chars",
|
||||
"number": "after a fixed number of characters",
|
||||
"never": "never - keep connection open",
|
||||
"immed": "immediately - don't wait for reply"
|
||||
},
|
||||
@@ -616,11 +618,11 @@
|
||||
"timeout": "timeout closed socket port __port__",
|
||||
"cannot-listen": "unable to listen on port __port__, error: __error__",
|
||||
"error": "error: __error__",
|
||||
|
||||
"socket-error": "socket error from __host__:__port__",
|
||||
"no-host": "Host and/or port not set",
|
||||
"connect-timeout": "connect timeout",
|
||||
"connect-fail": "connect failed"
|
||||
"connect-fail": "connect failed",
|
||||
"bad-string": "failed to convert to string"
|
||||
}
|
||||
},
|
||||
"udp": {
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
<dt class="optional">topic <span class="property-type">string|object|array</span></dt>
|
||||
<dd>For the <code>"subscribe"</code> and <code>"unsubscribe"</code> actions, this property
|
||||
provides the topic. It can be set as either:<ul>
|
||||
<li>a String containing the topic filter</li>
|
||||
<li>a String continaing the topic filter</li>
|
||||
<li>an Object containing <code>topic</code> and <code>qos</code> properties</li>
|
||||
<li>an array of either strings or objects to handle multiple topics in one</li>
|
||||
</ul>
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
<dd>In case any redirects occurred while processing the request, this property is the final redirected url.
|
||||
Otherwise, the url of the original request.</dd>
|
||||
<dt>responseCookies <span class="property-type">object</span></dt>
|
||||
<dd>If the response includes cookies, this property is an object of name/value pairs for each cookie.</dd>
|
||||
<dd>If the response includes cookies, this propery is an object of name/value pairs for each cookie.</dd>
|
||||
<dt>redirectList <span class="property-type">array</span></dt>
|
||||
<dd>If the request was redirected one or more times, the accumulated information will be added to this property. `location` is the next redirect destination. `cookies` is the cookies returned from the redirect source.</dd>
|
||||
</dl>
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
</p>
|
||||
<p>When operating in this mode, the node will not set the <code>msg.parts.count</code>
|
||||
property as it does not know how many messages to expect in the stream. This
|
||||
means it cannot be used with the <b>join</b> node in its automatic mode.</p>
|
||||
means it cannot be used with the <b>join</b> node in its automatic mode</p>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="join">
|
||||
|
||||
@@ -46,6 +46,4 @@
|
||||
<code>{{global[store].名前}}</code>を用います。
|
||||
</p>
|
||||
<p><b>注: </b>デフォルトでは、<i>mustache</i>形式は置換対象のHTML要素をエスケープします。これを抑止するには<code>{{{三重}}}</code>括弧形式を使います。</p>
|
||||
<p>もし、コンテンツの中で<code>{{ }}</code>を出力する必要がある場合は、テンプレートで使われる記号文字を変えることもできます。例えば、<code>[[ ]]</code>を代わりに用いるには、テンプレートの先頭に以下の行を追加します。</p>
|
||||
<pre>{{=[[ ]]=}}</pre>
|
||||
</script>
|
||||
|
||||
@@ -25,14 +25,11 @@
|
||||
<dt class="optional">reset</dt>
|
||||
<dd>受信メッセージでこのプロパティを任意の値に設定すると、ノードが保持する全ての未送信メッセージをクリアします。</dd>
|
||||
<dt class="optional">flush</dt>
|
||||
<dd>本プロパティに数値が設定されたメッセージを受信すると、直ちに指定された数のメッセージを送信します。もし他の型(例えば真偽型)が設定されている場合は、ノードが保持している全ての未送信メッセージを直ちに送信します。</dd>
|
||||
<dt class="optional">toFront</dt>
|
||||
<dd>流量制御モードにおいて、本プロパティに真偽型<code>true</code>が設定されたメッセージを受け取ると、キューの先頭に追加され、その後に送信されます。<code>msg.flush=1</code>と組み合わせて用いると、すぐに再送信できます。</dd>
|
||||
<dd>受信メッセージでこのプロパティを任意の値に設定すると、ノードが保持する全ての未送信メッセージを直ちに送信します。</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>メッセージを遅延させるように設定する場合、遅延時間は固定値、範囲内の乱数値、メッセージ毎の動的な指定値のいずれかを指定できます。各メッセージは、到着時刻に基づいて、他のメッセージとは独立して遅延されます。</p>
|
||||
<p>メッセージを遅延させるように設定する場合、遅延時間は固定値、範囲内の乱数値、メッセージ毎の動的な指定値のいずれかを指定できます。</p>
|
||||
<p>流量制御する場合、メッセージは指定した時間間隔内に分散して送信します。キューに残っているメッセージ数はノードのステータスに表示されます。受け取った中間メッセージを破棄することも可能です。</p>
|
||||
<p>流量値を上書きできるように設定されている場合、新しい流量値はすぐに適用されます。この流量値は、再度変更されるまで、本ノードがリセットされるまで、またはフローが再実行されるまで有効です。</p>
|
||||
<p>流量制御は全てのメッセージに適用することも、<code>msg.topic</code>値でグループ化して適用することも可能です。グループ化すると、中間メッセージは自動的に破棄されます。時間間隔毎に全てのトピックの最新メッセージを送信するか、次のトピックの最新メッセージを送信するかを指定できます。</p>
|
||||
<p><b>注</b>: 流量制御モードでは、キューの大きさの最大値を<i>settings.js</i>ファイルのプロパティに設定できます。例えば、次の様な設定です。<code>nodeMessageBufferMaxLength: 1000,</code></p>
|
||||
</script>
|
||||
|
||||
@@ -27,5 +27,5 @@
|
||||
<p>不感帯モードでは%による指定もサポートしています。入力と前の値の差分がX%より大きな場合に出力を行います。</p>
|
||||
<p>狭帯域(narrowband)モードでは、前の値に対する差分が一定値より大きな場合に入力ペイロードをブロックします。このモードは、故障したセンサから発生する外れ値を無視する時などに有用です。</p>
|
||||
<p>不感帯モードと狭帯域モードでは、以前の有効出力値、もしくは、以前の入力値との比較ができます。有効出力値を用いると範囲外の値を無視することが、入力値を用いると設定点がリセットされるため漸次的変化(不感帯モード)もしくは段階的変化(狭帯域モード)が可能です。</p>
|
||||
<p><b>注:</b> このノードは<code>msg.topic</code>毎に動作します。そのため、ひとつのfilterノードで複数の異なるトピックを同時に扱うことができます。</p>
|
||||
<p><b>注:</b> このノードは<code>msg.topic</code>毎に動作します。そのため、ひとつのrbeノードで複数の異なるトピックを同時に扱うことができます。</p>
|
||||
</script>
|
||||
|
||||
@@ -26,46 +26,11 @@
|
||||
<dd>0: 最大1度到着, 1: 一度以上到着, 2: 1度のみ到着</dd>
|
||||
<dt>retain <span class="property-type">真偽値</span></dt>
|
||||
<dd>真の場合、メッセージを保持。メッセージが古い値の場合があります。</dd>
|
||||
<dt class="optional">responseTopic <span class="property-type">文字列</span></dt>
|
||||
<dd><b>MQTTv5</b>: メッセージのMQTT応答トピック</dd>
|
||||
<dt class="optional">correlationData <span class="property-type">バッファ</span></dt>
|
||||
<dd><b>MQTTv5</b>: メッセージの相関データ</dd>
|
||||
<dt class="optional">contentType <span class="property-type">文字列</span></dt>
|
||||
<dd><b>MQTTv5</b>: ペイロードのコンテントタイプ</dd>
|
||||
<dt class="optional">userProperties <span class="property-type">オブジェクト</span></dt>
|
||||
<dd><b>MQTTv5</b>: メッセージのユーザプロパティ</dd>
|
||||
<dt class="optional">messageExpiryInterval <span class="property-type">数値</span></dt>
|
||||
<dd><b>MQTTv5</b>: 秒単位のメッセージの有効期限</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>購読トピックにはMQTTのワイルドカード(+: 1レベル, #: 複数レベル)を含めることができます。</p>
|
||||
<p>このノードの利用のためには、MQTTブローカへの接続設定が必要です。この設定は鉛筆アイコンをクリックすることで行えます。</p>
|
||||
<p>MQTT(inおよびout)ノードはブローカへの接続設定を必要に応じて共有できます。</p>
|
||||
<h4>動的購読</h4>
|
||||
本ノードは、MQTTの接続と購読を動的に制御するよう設定できます。有効にすると、本ノードの入力にメッセージを渡すことで制御できます。
|
||||
<h3>入力</h3>
|
||||
<p>これらは、動的購読が設定されている場合のみ適用されます。</p>
|
||||
<dl class="message-properties">
|
||||
<dt>action <span class="property-type">文字列</span></dt>
|
||||
<dd>本ノードが行う動作の名前。利用可能な動作は<code>"connect"</code>、<code>"disconnect"</code>、<code>"subscribe"</code>、<code>"unsubscribe"</code>です。</dd>
|
||||
<dt class="optional">topic <span class="property-type">文字列|オブジェクト|配列</span></dt>
|
||||
<dd><code>"subscribe"</code>と<code>"unsubscribe"</code>の動作に対して、本プロパティはトピックを提供します。次のいずれかを設定できます:<ul>
|
||||
<li>トピックフィルターを含む文字列</li>
|
||||
<li><code>topic</code>と<code>qos</code>プロパティを持つオブジェクト</li>
|
||||
<li>複数のトピックを扱う文字列やオブジェクトの配列</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt class="optional">broker <span class="property-type">broker</span> </dt>
|
||||
<dd><code>"connect"</code>の動作に対して、本プロパティは次の様な個々のブローカ設定を上書きします: <ul>
|
||||
<li><code>broker</code></li>
|
||||
<li><code>port</code></li>
|
||||
<li><code>url</code> - 完全な接続URLを提供するために、brokerとportを上書き</li>
|
||||
<li><code>username</code></li>
|
||||
<li><code>password</code></li>
|
||||
</ul>
|
||||
<p>本プロパティが設定され既にブローカが接続されている場合、<code>force</code>プロパティを設定しない限り、エラーがログに記録されます。設定された場合はブローカから切断され、新しい設定を適用して再接続します。</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="mqtt out">
|
||||
@@ -74,24 +39,15 @@
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">文字列 | バッファ</span></dt>
|
||||
<dd>発行するペイロード。プロパティが設定されていない場合には、メッセージは送信されません。空のメッセージを送信するには、プロパティに空文字列を設定します。</dd>
|
||||
|
||||
<dt class="optional">topic <span class="property-type">文字列</span></dt>
|
||||
<dd>発行対象のMQTTトピック</dd>
|
||||
|
||||
<dt class="optional">qos <span class="property-type">数値</span></dt>
|
||||
<dd>0: 最大一度到着, 1: 一度以上到着, 2: 一度のみ到着。デフォルトは0です。</dd>
|
||||
|
||||
<dt class="optional">retain <span class="property-type">真偽値</span></dt>
|
||||
<dd>真の場合、メッセージをブローカに保持します。デフォルトは偽です。</dd>
|
||||
<dt class="optional">responseTopic <span class="property-type">文字列</span></dt>
|
||||
<dd><b>MQTTv5</b>: メッセージのMQTT応答トピック</dd>
|
||||
<dt class="optional">correlationData <span class="property-type">バッファ</span></dt>
|
||||
<dd><b>MQTTv5</b>: メッセージの相関データ</dd>
|
||||
<dt class="optional">contentType <span class="property-type">文字列</span></dt>
|
||||
<dd><b>MQTTv5</b>: ペイロードのコンテントタイプ</dd>
|
||||
<dt class="optional">userProperties <span class="property-type">オブジェクト</span></dt>
|
||||
<dd><b>MQTTv5</b>: メッセージのユーザプロパティ</dd>
|
||||
<dt class="optional">messageExpiryInterval <span class="property-type">数値</span></dt>
|
||||
<dd><b>MQTTv5</b>: 秒単位のメッセージの有効期限</dd>
|
||||
<dt class="optional">topicAlias <span class="property-type">数値</span></dt>
|
||||
<dd><b>MQTTv5</b>: 使用するMQTTトピックエイリアス</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p><code>msg.payload</code>を発行するメッセージのペイロードとして用います。ペイロードがオブジェクトの場合、送信の際にJSON文字列に変換します。ペイロードがバイナリバッファの場合、そのまま送信します。</p>
|
||||
@@ -99,24 +55,6 @@
|
||||
<p>同様に、QoSとretainもノードの設定、もしくは、ノードの設定が空の場合には、それぞれ<code>msg.qos</code>および<code>msg.retain</code>で指定できます。以前ブローカに保存したトピックをクリアするには、retainフラグを設定して当該トピックに空のメッセージを発行します。</p>
|
||||
<p>このノードの利用のためには、MQTTブローカへの接続設定が必要です。この設定は鉛筆アイコンをクリックすることで行えます。</p>
|
||||
<p>MQTT(inおよびout)ノードはブローカへの接続設定を必要に応じて共有できます。</p>
|
||||
|
||||
<h4>動的制御</h4>
|
||||
本ノードによって接続を動的に制御できます。本ノードが以下の制御メッセージのいずれかを受け取った際は、ペイロードと同じ様にパブリッシュされることはありません。
|
||||
<h3>入力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>action <span class="property-type">文字列</span></dt>
|
||||
<dd>本ノードが行う動作の名前。利用可能な動作は<code>"connect"</code>、<code>"disconnect"</code>、<code>"subscribe"</code>、<code>"unsubscribe"</code>です。</dd>
|
||||
<dt class="optional">broker <span class="property-type">broker</span> </dt>
|
||||
<dd><code>"connect"</code>の動作に対して、本プロパティは次の様な個々のブローカ設定を上書きします: <ul>
|
||||
<li><code>broker</code></li>
|
||||
<li><code>port</code></li>
|
||||
<li><code>url</code> - 完全な接続URLを提供するために、brokerとportを上書き</li>
|
||||
<li><code>username</code></li>
|
||||
<li><code>password</code></li>
|
||||
</ul>
|
||||
<p>本プロパティが設定され既にブローカが接続されている場合、<code>force</code>プロパティを設定しない限り、エラーがログに記録されます。設定された場合はブローカから切断され、新しい設定を適用して再接続します。</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="mqtt-broker">
|
||||
@@ -132,4 +70,5 @@
|
||||
<h4>WebSocket</h4>
|
||||
<p>WebSocketによる接続を行うように設定できます。WebSocketを利用するには、サーバフィールドに接続先のURIを完全な形式で記述します。以下に例を示します。</p>
|
||||
<pre>ws://example.com:4000/mqtt</pre>
|
||||
|
||||
</script>
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
<h3>詳細</h3>
|
||||
<p>「列名」にカラム名のリストを指定することができます。CSVからオブジェクトに変換を行う際、カラム名をプロパティ名として使用します。「列名」の代わりに、CSVデータの1行目にカラム名を含めることもできます。</p>
|
||||
<p>CSVへの変換を行う際には、オブジェクトから取り出すべきプロパティとその順序を「列名」を参照して決めます。</p>
|
||||
<p>列名がない場合、本ノードは<code>msg.columns</code>プロパティの単純なコンマ区切りリストを使用して、何をどの順序で抽出するかを決定します。もし存在しない場合、すべてのオブジェクトプロパティを見つけた順序で出力します。</p>
|
||||
<p>列名がない場合、本ノードは<code>msg.columns</code>プロパティの単純なコンマ区切りリストを使用して、何を抽出するかを決定します。もしそれが存在しない場合、すべてのオブジェクトプロパティを見つけた順序で出力します。</p>
|
||||
<p>入力が配列の場合には、「列名」はカラム名を表す行の出力指定がされた場合だけ用います。</p>
|
||||
<p>「数値を変換する」オプションがチェックされている場合、文字列型の数値が数値として返されます。つまり「1,"1.5",2」の真ん中の値が数値になります。</p>
|
||||
<p>「空の文字を含む」オプションがチェックされている場合、空の文字列が結果に返されます。つまり「"1","",3」の真ん中の値が空の文字列になります。</p>
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
<p>このモードで処理する際には、メッセージ数を予め知ることができないため、<code>msg.parts.count</code>プロパティは設定されません。従って、<b>join</b>ノードの「自動モード」と組み合わせることはできません。</p>
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/html" data-help-name="join">
|
||||
<p>メッセージ列を結合して一つのメッセージにします。</p>
|
||||
<p>メッセージの結合には次の3つのモードが利用できます。</p>
|
||||
@@ -79,10 +80,6 @@
|
||||
</dd>
|
||||
<dt class="optional">complete</dt>
|
||||
<dd>設定されている場合、本ノードはペイロードを追加し、保持しているメッセージを送信します。ペイロードを追加したくない場合は、msgから削除してください。</dd>
|
||||
<dt class="optional">reset</dt>
|
||||
<dd>設定されている場合、本ノードは部分的に完成したメッセージを送信せず、削除します。</dd>
|
||||
<dt class="optional">restartTimeout</dt>
|
||||
<dd>設定されている場合、本ノードにタイムアウトが設定され、そのタイムアウトを用いて処理が再開されます。</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
|
||||
@@ -99,7 +96,7 @@
|
||||
</ul>
|
||||
<p>出力メッセージのその他のプロパティはメッセージを送信する直前のメッセージをコピーします。</p>
|
||||
<p>「<i>合計値</i>」には出力メッセージを送信する前に受信すべきメッセージ数を指定します。オブジェクト出力の場合、この合計値に達すると後続メッセージの到着毎にメッセージを出力するように設定することもできます。</p>
|
||||
<p>「<i>秒</i>」には新規メッセージを送信するまでの経過時間を設定します。<code>msg.restartTimeout</code>プロパティを設定したメッセージを渡すことで、指定した時間で再開できます。</p>
|
||||
<p>「<i>秒</i>」には新規メッセージを送信するまでの経過時間を設定します。</p>
|
||||
<p><code>msg.complete</code>プロパティを設定したメッセージを受信すると、出力メッセージを送信します。この時、メッセージ列の数をリセットします。</p>
|
||||
<p><code>msg.reset</code>プロパティを設定したメッセージを受信すると、部分的に受信済みのメッセージを破棄します。これらのメッセージは送信されません。この時、メッセージ列の数をリセットします。</p>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/nodes",
|
||||
"version": "2.1.5",
|
||||
"version": "2.2.0-beta.1",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -15,10 +15,10 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"acorn": "8.7.0",
|
||||
"acorn": "8.6.0",
|
||||
"acorn-walk": "8.2.0",
|
||||
"ajv": "8.8.2",
|
||||
"body-parser": "1.19.1",
|
||||
"body-parser": "1.19.0",
|
||||
"cheerio": "1.0.0-rc.10",
|
||||
"content-type": "1.0.4",
|
||||
"cookie-parser": "1.4.6",
|
||||
@@ -36,7 +36,7 @@
|
||||
"is-utf8": "0.2.1",
|
||||
"js-yaml": "3.14.1",
|
||||
"media-typer": "1.1.0",
|
||||
"mqtt": "4.3.4",
|
||||
"mqtt": "4.2.8",
|
||||
"multer": "1.4.3",
|
||||
"mustache": "4.2.0",
|
||||
"on-headers": "1.0.2",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/registry",
|
||||
"version": "2.1.5",
|
||||
"version": "2.2.0-beta.1",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
@@ -16,11 +16,11 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/util": "2.1.5",
|
||||
"@node-red/util": "2.2.0-beta.1",
|
||||
"clone": "2.1.2",
|
||||
"fs-extra": "10.0.0",
|
||||
"semver": "7.3.5",
|
||||
"tar": "6.1.11",
|
||||
"uglify-js": "3.14.5"
|
||||
"uglify-js": "3.14.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,6 @@ function createNode(flow,config) {
|
||||
}
|
||||
}
|
||||
try {
|
||||
Object.defineProperty(conf,'_module', {value: typeRegistry.getNodeInfo(type), enumerable: false, writable: true })
|
||||
Object.defineProperty(conf,'_flow', {value: flow, enumerable: false, writable: true })
|
||||
newNode = new nodeTypeConstructor(conf);
|
||||
} catch (err) {
|
||||
|
||||
@@ -59,9 +59,6 @@ function Node(n) {
|
||||
// which we can tolerate as they are the same object.
|
||||
Object.defineProperty(this,'_flow', {value: n._flow, enumerable: false, writable: true })
|
||||
}
|
||||
if (n._module) {
|
||||
Object.defineProperty(this,'_module', {value: n._module, enumerable: false, writable: true })
|
||||
}
|
||||
this.updateWires(n.wires);
|
||||
}
|
||||
|
||||
@@ -499,12 +496,7 @@ function log_helper(self, level, msg) {
|
||||
if (self.name) {
|
||||
o.name = self.name;
|
||||
}
|
||||
// See https://github.com/node-red/node-red/issues/3327
|
||||
try {
|
||||
self._flow.log(o);
|
||||
} catch(err) {
|
||||
logUnexpectedError(self, err)
|
||||
}
|
||||
self._flow.log(o);
|
||||
}
|
||||
/**
|
||||
* Log an INFO level message
|
||||
@@ -584,59 +576,4 @@ Node.prototype.status = function(status) {
|
||||
this._flow.handleStatus(this,status);
|
||||
};
|
||||
|
||||
|
||||
function inspectObject(flow) {
|
||||
try {
|
||||
let properties = new Set()
|
||||
let currentObj = flow
|
||||
do {
|
||||
if (!Object.getPrototypeOf(currentObj)) { break }
|
||||
Object.getOwnPropertyNames(currentObj).map(item => properties.add(item))
|
||||
} while ((currentObj = Object.getPrototypeOf(currentObj)))
|
||||
let propList = [...properties.keys()].map(item => `${item}[${(typeof flow[item])[0]}]`)
|
||||
propList.sort();
|
||||
let result = [];
|
||||
let line = "";
|
||||
while (propList.length > 0) {
|
||||
let prop = propList.shift()
|
||||
if (line.length+prop.length > 80) {
|
||||
result.push(line)
|
||||
line = "";
|
||||
} else {
|
||||
line += " "+prop
|
||||
}
|
||||
}
|
||||
if (line.length > 0) {
|
||||
result.push(line);
|
||||
}
|
||||
return result.join("\n ")
|
||||
|
||||
} catch(err) {
|
||||
return "Failed to capture object properties: "+err.toString()
|
||||
}
|
||||
}
|
||||
|
||||
function logUnexpectedError(node, error) {
|
||||
let moduleInfo = node._module?`${node._module.module}@${node._module.version}`:"undefined"
|
||||
Log.error(`
|
||||
********************************************************************
|
||||
Unexpected Node Error
|
||||
${error.stack}
|
||||
Node:
|
||||
Type: ${node.type}
|
||||
Module: ${moduleInfo}
|
||||
ID: ${node._alias||node.id}
|
||||
Properties:
|
||||
${inspectObject(node)}
|
||||
Flow: ${node._flow?node._flow.path:'undefined'}
|
||||
Type: ${node._flow?node._flow.TYPE:'undefined'}
|
||||
Properties:
|
||||
${node._flow?inspectObject(node._flow):'undefined'}
|
||||
|
||||
Please report this issue, including the information logged above:
|
||||
https://github.com/node-red/node-red/issues/
|
||||
********************************************************************
|
||||
`)
|
||||
}
|
||||
|
||||
module.exports = Node;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/runtime",
|
||||
"version": "2.1.5",
|
||||
"version": "2.2.0-beta.1",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
@@ -16,11 +16,11 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/registry": "2.1.5",
|
||||
"@node-red/util": "2.1.5",
|
||||
"@node-red/registry": "2.2.0-beta.1",
|
||||
"@node-red/util": "2.2.0-beta.1",
|
||||
"async-mutex": "0.3.2",
|
||||
"clone": "2.1.2",
|
||||
"express": "4.17.2",
|
||||
"express": "4.17.1",
|
||||
"fs-extra": "10.0.0",
|
||||
"json-stringify-safe": "5.0.1"
|
||||
}
|
||||
|
||||
@@ -32,14 +32,8 @@ function wrapEventFunction(obj,func) {
|
||||
return function(eventName, listener) {
|
||||
if (deprecatedEvents.hasOwnProperty(eventName)) {
|
||||
const log = require("@node-red/util").log;
|
||||
|
||||
const stack = (new Error().stack).split("\n");
|
||||
let location = "(unknown)"
|
||||
// See https://github.com/node-red/node-red/issues/3292
|
||||
if (stack.length > 2) {
|
||||
location = stack[2].split("(")[1].slice(0,-1);
|
||||
}
|
||||
log.warn(`[RED.events] Deprecated use of "${eventName}" event from "${location}". Use "${deprecatedEvents[eventName]}" instead.`)
|
||||
const stack = (new Error().stack).split("\n")[2].split("(")[1].slice(0,-1);
|
||||
log.warn(`[RED.events] Deprecated use of "${eventName}" event from "${stack}". Use "${deprecatedEvents[eventName]}" instead.`)
|
||||
}
|
||||
return events["_"+func].call(events,eventName,listener)
|
||||
}
|
||||
|
||||
@@ -686,7 +686,7 @@ function prepareJSONataExpression(value,node) {
|
||||
return moment(arg1, arg2, arg3, arg4);
|
||||
});
|
||||
expr.registerFunction('clone', cloneMessage, '<(oa)-:o>');
|
||||
expr._legacyMode = /(^|[^a-zA-Z0-9_'".])msg([^a-zA-Z0-9_'"]|$)/.test(value);
|
||||
expr._legacyMode = /(^|[^a-zA-Z0-9_'"])msg([^a-zA-Z0-9_'"]|$)/.test(value);
|
||||
expr._node = node;
|
||||
return expr;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/util",
|
||||
"version": "2.1.5",
|
||||
"version": "2.2.0-beta.1",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -16,7 +16,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"fs-extra": "10.0.0",
|
||||
"i18next": "21.6.6",
|
||||
"i18next": "21.5.4",
|
||||
"json-stringify-safe": "5.0.1",
|
||||
"jsonata": "1.8.5",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
|
||||
12
packages/node_modules/node-red/package.json
vendored
12
packages/node_modules/node-red/package.json
vendored
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "node-red",
|
||||
"version": "2.1.5",
|
||||
"version": "2.2.0-beta.1",
|
||||
"description": "Low-code programming for event-driven applications",
|
||||
"homepage": "http://nodered.org",
|
||||
"license": "Apache-2.0",
|
||||
@@ -31,13 +31,13 @@
|
||||
"flow"
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/editor-api": "2.1.5",
|
||||
"@node-red/runtime": "2.1.5",
|
||||
"@node-red/util": "2.1.5",
|
||||
"@node-red/nodes": "2.1.5",
|
||||
"@node-red/editor-api": "2.2.0-beta.1",
|
||||
"@node-red/runtime": "2.2.0-beta.1",
|
||||
"@node-red/util": "2.2.0-beta.1",
|
||||
"@node-red/nodes": "2.2.0-beta.1",
|
||||
"basic-auth": "2.0.1",
|
||||
"bcryptjs": "2.4.3",
|
||||
"express": "4.17.2",
|
||||
"express": "4.17.1",
|
||||
"fs-extra": "10.0.0",
|
||||
"node-red-admin": "^2.2.1",
|
||||
"nopt": "5.0.0",
|
||||
|
||||
@@ -425,7 +425,7 @@ describe('rbe node', function() {
|
||||
});
|
||||
|
||||
it('should not send output if x away or greater from original value (narrowbandEq)', function(done) {
|
||||
var flow = [{"id":"n1", "type":"rbe", func:"narrowbandEq", gap:"10", inout:"out", start:"1", wires:[["n2"]] },
|
||||
var flow = [{"id":"n1", "type":"rbe", func:"narrowbandEq", gap:"10", inout:"out", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(testNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
@@ -445,7 +445,6 @@ describe('rbe node', function() {
|
||||
done();
|
||||
}
|
||||
});
|
||||
n1.emit("input", {payload:100});
|
||||
n1.emit("input", {payload:0});
|
||||
n1.emit("input", {payload:10});
|
||||
n1.emit("input", {payload:5});
|
||||
|
||||
@@ -84,9 +84,17 @@ describe('TCP Request Node', function() {
|
||||
n2.on("input", msg => {
|
||||
try {
|
||||
if (typeof result === 'object') {
|
||||
msg.should.have.properties(Object.assign({}, result, {payload: Buffer.from(result.payload)}));
|
||||
if (flow[0].ret === "string") {
|
||||
msg.should.have.properties(Object.assign({}, result, {payload: result.payload}));
|
||||
} else {
|
||||
msg.should.have.properties(Object.assign({}, result, {payload: Buffer.from(result.payload)}));
|
||||
}
|
||||
} else {
|
||||
msg.should.have.property('payload', Buffer.from(result));
|
||||
if (flow[0].ret === "string") {
|
||||
msg.should.have.property('payload', result);
|
||||
} else {
|
||||
msg.should.have.property('payload', Buffer.from(result));
|
||||
}
|
||||
}
|
||||
done();
|
||||
} catch(err) {
|
||||
@@ -245,10 +253,41 @@ describe('TCP Request Node', function() {
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('should send & receive, then keep connection, and not split return strings', function(done) {
|
||||
var flow = [{id:"n1", type:"tcp request", server:"localhost", port:port, out:"sit", ret:"string", newline:"", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"}];
|
||||
testTCPMany(flow, [{
|
||||
payload: "foo",
|
||||
topic: 'boo'
|
||||
}, {
|
||||
payload: "bar<A>\nfoo",
|
||||
topic: 'boo'
|
||||
}], {
|
||||
payload: "ACK:foobar<A>\nfoo",
|
||||
topic: 'boo'
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('should send & receive, then keep connection, and split return strings', function(done) {
|
||||
var flow = [{id:"n1", type:"tcp request", server:"localhost", port:port, out:"sit", ret:"string", newline:"<A>\\n", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"}];
|
||||
testTCPMany(flow, [{
|
||||
payload: "foo",
|
||||
topic: 'boo'
|
||||
}, {
|
||||
payload: "bar<A>\nfoo",
|
||||
topic: 'boo'
|
||||
}], {
|
||||
payload: "ACK:foobar<A>",
|
||||
topic: 'boo'
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('should send & recv data to/from server:port from msg', function(done) {
|
||||
var flow = [{id:"n1", type:"tcp request", server:"", port:"", out:"time", splitc: "0", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"}];
|
||||
testTCPMany(flow, [{
|
||||
testTCPMany(flow, [
|
||||
{
|
||||
payload: "f",
|
||||
host: "localhost",
|
||||
port: port
|
||||
|
||||
Reference in New Issue
Block a user