mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Merge branch 'master' into fix-include-label-themeSettings-config
This commit is contained in:
commit
cbc91a9ac8
26
CHANGELOG.md
26
CHANGELOG.md
@ -1,3 +1,29 @@
|
|||||||
|
#### 4.0.9: Maintenance Release
|
||||||
|
|
||||||
|
Editor
|
||||||
|
|
||||||
|
- Add details for the dynamic subscription to match the English docs (#5050) @aikitori
|
||||||
|
- Fix tooltip snapping based on `typedInput` type (#5051) @GogoVega
|
||||||
|
- Prevent symbol usage warning in monaco (#5049) @Steve-Mcl
|
||||||
|
- Show subflow flow context under node section of sidebar (#5025) @knolleary
|
||||||
|
- feat: Add custom label for default deploy button in settings.editorTheme (#5030) @matiseni51
|
||||||
|
- Handle long auto-complete suggests (#5042) @knolleary
|
||||||
|
- Handle undefined username when generating user icon (#5043) @knolleary
|
||||||
|
- Handle dragging node into group and splicing link at same time (#5027) @knolleary
|
||||||
|
- Remember context sidebar tree state when refreshing (#5021) @knolleary
|
||||||
|
- Update sf instance env vars when removed from template (#5023) @knolleary
|
||||||
|
- Do not select group when triggering quick-add within it (#5022) @knolleary
|
||||||
|
- Fix library icon handling within library browser component (#5017) @knolleary
|
||||||
|
|
||||||
|
Runtime
|
||||||
|
- Allow env var access to context (#5016) @knolleary
|
||||||
|
- fix debug status reporting if null (#5018) @dceejay
|
||||||
|
- Fix grunt dev via better ndoemon ignore rules (#5015) @knolleary
|
||||||
|
- Fix typo in CHANGELOG (4.0.7-->4.0.8) (#5007) @natcl
|
||||||
|
|
||||||
|
Nodes
|
||||||
|
- Switch: Avoid exceeding call stack when draining message group in Switch (#5014) @knolleary
|
||||||
|
|
||||||
#### 4.0.8: Maintenance Release
|
#### 4.0.8: Maintenance Release
|
||||||
|
|
||||||
Editor
|
Editor
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "node-red",
|
"name": "node-red",
|
||||||
"version": "4.0.8",
|
"version": "4.0.9",
|
||||||
"description": "Low-code programming for event-driven applications",
|
"description": "Low-code programming for event-driven applications",
|
||||||
"homepage": "https://nodered.org",
|
"homepage": "https://nodered.org",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@node-red/editor-api",
|
"name": "@node-red/editor-api",
|
||||||
"version": "4.0.8",
|
"version": "4.0.9",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
@ -16,8 +16,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@node-red/util": "4.0.8",
|
"@node-red/util": "4.0.9",
|
||||||
"@node-red/editor-client": "4.0.8",
|
"@node-red/editor-client": "4.0.9",
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
"body-parser": "1.20.3",
|
"body-parser": "1.20.3",
|
||||||
"clone": "2.1.2",
|
"clone": "2.1.2",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@node-red/editor-client",
|
"name": "@node-red/editor-client",
|
||||||
"version": "4.0.8",
|
"version": "4.0.9",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -398,14 +398,13 @@ RED.multiplayer = (function () {
|
|||||||
anonIconBody.setAttribute("d",`M ${radius/2} ${radius/2 + 5} h -2.5 c -2 1 -2 -5 0.5 -4.5 c 2 1 2 1 4 0 c 2.5 -0.5 2.5 5.5 0 4.5 z`);
|
anonIconBody.setAttribute("d",`M ${radius/2} ${radius/2 + 5} h -2.5 c -2 1 -2 -5 0.5 -4.5 c 2 1 2 1 4 0 c 2.5 -0.5 2.5 5.5 0 4.5 z`);
|
||||||
group.appendChild(anonIconBody)
|
group.appendChild(anonIconBody)
|
||||||
} else {
|
} else {
|
||||||
const labelText = user.username ? user.username.substring(0,2) : user
|
|
||||||
const label = document.createElementNS("http://www.w3.org/2000/svg","text");
|
const label = document.createElementNS("http://www.w3.org/2000/svg","text");
|
||||||
if (user.username) {
|
if (user.username || user.email) {
|
||||||
label.setAttribute("class","red-ui-multiplayer-annotation-label");
|
label.setAttribute("class","red-ui-multiplayer-annotation-label");
|
||||||
label.textContent = user.username.substring(0,2)
|
label.textContent = (user.username || user.email).substring(0,2)
|
||||||
} else {
|
} else {
|
||||||
label.setAttribute("class","red-ui-multiplayer-annotation-label red-ui-multiplayer-user-count")
|
label.setAttribute("class","red-ui-multiplayer-annotation-label red-ui-multiplayer-user-count")
|
||||||
label.textContent = user
|
label.textContent = 'nr'
|
||||||
}
|
}
|
||||||
label.setAttribute("text-anchor", "middle")
|
label.setAttribute("text-anchor", "middle")
|
||||||
label.setAttribute("x",radius/2);
|
label.setAttribute("x",radius/2);
|
||||||
|
@ -61,7 +61,7 @@
|
|||||||
}
|
}
|
||||||
this.menu = RED.popover.menu({
|
this.menu = RED.popover.menu({
|
||||||
tabSelect: true,
|
tabSelect: true,
|
||||||
width: 300,
|
width: Math.max(300, this.element.width()),
|
||||||
maxHeight: 200,
|
maxHeight: 200,
|
||||||
class: "red-ui-autoComplete-container",
|
class: "red-ui-autoComplete-container",
|
||||||
options: completions,
|
options: completions,
|
||||||
|
@ -63,6 +63,7 @@
|
|||||||
pre: value.substring(0,idx),
|
pre: value.substring(0,idx),
|
||||||
match: value.substring(idx,idx+len),
|
match: value.substring(idx,idx+len),
|
||||||
post: value.substring(idx+len),
|
post: value.substring(idx+len),
|
||||||
|
exact: idx === 0 && value.length === searchValue.length
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function generateSpans(match) {
|
function generateSpans(match) {
|
||||||
@ -83,7 +84,7 @@
|
|||||||
const srcMatch = getMatch(optSrc, val);
|
const srcMatch = getMatch(optSrc, val);
|
||||||
if (valMatch.found || srcMatch.found) {
|
if (valMatch.found || srcMatch.found) {
|
||||||
const element = $('<div>',{style: "display: flex"});
|
const element = $('<div>',{style: "display: flex"});
|
||||||
const valEl = $('<div/>',{style:"font-family: var(--red-ui-monospace-font); white-space:nowrap; overflow: hidden; flex-grow:1"});
|
const valEl = $('<div/>',{ class: "red-ui-autoComplete-completion" });
|
||||||
valEl.append(generateSpans(valMatch));
|
valEl.append(generateSpans(valMatch));
|
||||||
valEl.appendTo(element);
|
valEl.appendTo(element);
|
||||||
if (optSrc) {
|
if (optSrc) {
|
||||||
@ -159,7 +160,7 @@
|
|||||||
if (valMatch.found) {
|
if (valMatch.found) {
|
||||||
const optSrc = envVarsMap[v]
|
const optSrc = envVarsMap[v]
|
||||||
const element = $('<div>',{style: "display: flex"});
|
const element = $('<div>',{style: "display: flex"});
|
||||||
const valEl = $('<div/>',{style:"font-family: var(--red-ui-monospace-font); white-space:nowrap; overflow: hidden; flex-grow:1"});
|
const valEl = $('<div/>',{ class: "red-ui-autoComplete-completion" });
|
||||||
valEl.append(generateSpans(valMatch))
|
valEl.append(generateSpans(valMatch))
|
||||||
valEl.appendTo(element)
|
valEl.appendTo(element)
|
||||||
|
|
||||||
@ -201,7 +202,7 @@
|
|||||||
const that = this
|
const that = this
|
||||||
const getContextKeysFromRuntime = function(scope, store, searchKey, done) {
|
const getContextKeysFromRuntime = function(scope, store, searchKey, done) {
|
||||||
contextKnownKeys[scope] = contextKnownKeys[scope] || {}
|
contextKnownKeys[scope] = contextKnownKeys[scope] || {}
|
||||||
contextKnownKeys[scope][store] = contextKnownKeys[scope][store] || new Set()
|
contextKnownKeys[scope][store] = contextKnownKeys[scope][store] || new Map()
|
||||||
if (searchKey.length > 0) {
|
if (searchKey.length > 0) {
|
||||||
try {
|
try {
|
||||||
RED.utils.normalisePropertyExpression(searchKey)
|
RED.utils.normalisePropertyExpression(searchKey)
|
||||||
@ -223,11 +224,12 @@
|
|||||||
const result = data[store] || {}
|
const result = data[store] || {}
|
||||||
const keys = result.keys || []
|
const keys = result.keys || []
|
||||||
const keyPrefix = searchKey + (searchKey.length > 0 ? '.' : '')
|
const keyPrefix = searchKey + (searchKey.length > 0 ? '.' : '')
|
||||||
keys.forEach(key => {
|
keys.forEach(keyInfo => {
|
||||||
|
const key = keyInfo.key
|
||||||
if (/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(key)) {
|
if (/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(key)) {
|
||||||
contextKnownKeys[scope][store].add(keyPrefix + key)
|
contextKnownKeys[scope][store].set(keyPrefix + key, keyInfo)
|
||||||
} else {
|
} else {
|
||||||
contextKnownKeys[scope][store].add(searchKey + "[\""+key.replace(/"/,"\\\"")+"\"]")
|
contextKnownKeys[scope][store].set(searchKey + "[\""+key.replace(/"/,"\\\"")+"\"]", keyInfo)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
done()
|
done()
|
||||||
@ -242,14 +244,14 @@
|
|||||||
// Get the flow id of the node we're editing
|
// Get the flow id of the node we're editing
|
||||||
const editStack = RED.editor.getEditStack()
|
const editStack = RED.editor.getEditStack()
|
||||||
if (editStack.length === 0) {
|
if (editStack.length === 0) {
|
||||||
done([])
|
done(new Map())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const editingNode = editStack.pop()
|
const editingNode = editStack.pop()
|
||||||
if (editingNode.z) {
|
if (editingNode.z) {
|
||||||
scope = `${scope}/${editingNode.z}`
|
scope = `${scope}/${editingNode.z}`
|
||||||
} else {
|
} else {
|
||||||
done([])
|
done(new Map())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -269,17 +271,29 @@
|
|||||||
return function(val, done) {
|
return function(val, done) {
|
||||||
getContextKeys(val, function (keys) {
|
getContextKeys(val, function (keys) {
|
||||||
const matches = []
|
const matches = []
|
||||||
keys.forEach(v => {
|
keys.forEach((keyInfo, v) => {
|
||||||
let optVal = v
|
let optVal = v
|
||||||
let valMatch = getMatch(optVal, val);
|
let valMatch = getMatch(optVal, val);
|
||||||
if (!valMatch.found && val.length > 0 && val.endsWith('.')) {
|
if (!valMatch.found && val.length > 0) {
|
||||||
// Search key ends in '.' - but doesn't match. Check again
|
if (val.endsWith('.')) {
|
||||||
// with [" at the end instead so we match bracket notation
|
// Search key ends in '.' - but doesn't match. Check again
|
||||||
valMatch = getMatch(optVal, val.substring(0, val.length - 1) + '["')
|
// with [" at the end instead so we match bracket notation
|
||||||
|
valMatch = getMatch(optVal, val.substring(0, val.length - 1) + '["')
|
||||||
|
// } else if (val.endsWith('[') && /^array/.test(keyInfo.format)) {
|
||||||
|
// console.log('this case')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (valMatch.found) {
|
if (valMatch.found) {
|
||||||
const element = $('<div>',{style: "display: flex"});
|
const element = $('<div>',{style: "display: flex"});
|
||||||
const valEl = $('<div/>',{style:"font-family: var(--red-ui-monospace-font); white-space:nowrap; overflow: hidden; flex-grow:1"});
|
const valEl = $('<div/>',{ class: "red-ui-autoComplete-completion" });
|
||||||
|
// if (keyInfo.format) {
|
||||||
|
// valMatch.post += ' ' + keyInfo.format
|
||||||
|
// }
|
||||||
|
if (valMatch.exact && /^array/.test(keyInfo.format)) {
|
||||||
|
valMatch.post += `[0-${keyInfo.length}]`
|
||||||
|
optVal += '['
|
||||||
|
|
||||||
|
}
|
||||||
valEl.append(generateSpans(valMatch))
|
valEl.append(generateSpans(valMatch))
|
||||||
valEl.appendTo(element)
|
valEl.appendTo(element)
|
||||||
matches.push({
|
matches.push({
|
||||||
@ -1567,7 +1581,8 @@
|
|||||||
if (tooltip) {
|
if (tooltip) {
|
||||||
tooltip.setContent(valid);
|
tooltip.setContent(valid);
|
||||||
} else {
|
} else {
|
||||||
tooltip = RED.popover.tooltip(this.elementDiv, valid);
|
const target = this.typeMap[type]?.options ? this.optionSelectLabel : this.elementDiv;
|
||||||
|
tooltip = RED.popover.tooltip(target, valid);
|
||||||
this.element.data("tooltip", tooltip);
|
this.element.data("tooltip", tooltip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@ RED.deploy = (function() {
|
|||||||
/**
|
/**
|
||||||
* options:
|
* options:
|
||||||
* type: "default" - Button with drop-down options - no further customisation available
|
* type: "default" - Button with drop-down options - no further customisation available
|
||||||
|
* label: the text to display - default: "Deploy"
|
||||||
* type: "simple" - Button without dropdown. Customisations:
|
* type: "simple" - Button without dropdown. Customisations:
|
||||||
* label: the text to display - default: "Deploy"
|
* label: the text to display - default: "Deploy"
|
||||||
* icon : the icon to use. Null removes the icon. default: "red/images/deploy-full-o.svg"
|
* icon : the icon to use. Null removes the icon. default: "red/images/deploy-full-o.svg"
|
||||||
@ -51,13 +52,14 @@ RED.deploy = (function() {
|
|||||||
function init(options) {
|
function init(options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
var type = options.type || "default";
|
var type = options.type || "default";
|
||||||
|
var label = options.label || RED._("deploy.deploy");
|
||||||
|
|
||||||
if (type == "default") {
|
if (type == "default") {
|
||||||
$('<li><span class="red-ui-deploy-button-group button-group">'+
|
$('<li><span class="red-ui-deploy-button-group button-group">'+
|
||||||
'<a id="red-ui-header-button-deploy" class="red-ui-deploy-button disabled" href="#">'+
|
'<a id="red-ui-header-button-deploy" class="red-ui-deploy-button disabled" href="#">'+
|
||||||
'<span class="red-ui-deploy-button-content">'+
|
'<span class="red-ui-deploy-button-content">'+
|
||||||
'<img id="red-ui-header-button-deploy-icon" src="red/images/deploy-full-o.svg"> '+
|
'<img id="red-ui-header-button-deploy-icon" src="red/images/deploy-full-o.svg"> '+
|
||||||
'<span>'+RED._("deploy.deploy")+'</span>'+
|
'<span>'+label+'</span>'+
|
||||||
'</span>'+
|
'</span>'+
|
||||||
'<span class="red-ui-deploy-button-spinner hide">'+
|
'<span class="red-ui-deploy-button-spinner hide">'+
|
||||||
'<img src="red/images/spin.svg"/>'+
|
'<img src="red/images/spin.svg"/>'+
|
||||||
@ -78,7 +80,6 @@ RED.deploy = (function() {
|
|||||||
mainMenuItems.push({id:"deploymenu-item-reload", icon:"red/images/deploy-reload.svg",label:RED._("deploy.restartFlows"),sublabel:RED._("deploy.restartFlowsDesc"),onselect:"core:restart-flows"})
|
mainMenuItems.push({id:"deploymenu-item-reload", icon:"red/images/deploy-reload.svg",label:RED._("deploy.restartFlows"),sublabel:RED._("deploy.restartFlowsDesc"),onselect:"core:restart-flows"})
|
||||||
RED.menu.init({id:"red-ui-header-button-deploy-options", options: mainMenuItems });
|
RED.menu.init({id:"red-ui-header-button-deploy-options", options: mainMenuItems });
|
||||||
} else if (type == "simple") {
|
} else if (type == "simple") {
|
||||||
var label = options.label || RED._("deploy.deploy");
|
|
||||||
var icon = 'red/images/deploy-full-o.svg';
|
var icon = 'red/images/deploy-full-o.svg';
|
||||||
if (options.hasOwnProperty('icon')) {
|
if (options.hasOwnProperty('icon')) {
|
||||||
icon = options.icon;
|
icon = options.icon;
|
||||||
|
@ -691,6 +691,7 @@ RED.editor.codeEditor.monaco = (function() {
|
|||||||
2322, //Type 'unknown' is not assignable to type 'string'
|
2322, //Type 'unknown' is not assignable to type 'string'
|
||||||
2339, //property does not exist on
|
2339, //property does not exist on
|
||||||
2345, //Argument of type xxx is not assignable to parameter of type 'DateTimeFormatOptions'
|
2345, //Argument of type xxx is not assignable to parameter of type 'DateTimeFormatOptions'
|
||||||
|
2538, //Ignore symbols as index property error.
|
||||||
7043, //i forget what this one is,
|
7043, //i forget what this one is,
|
||||||
80001, //Convert to ES6 module
|
80001, //Convert to ES6 module
|
||||||
80004, //JSDoc types may be moved to TypeScript types.
|
80004, //JSDoc types may be moved to TypeScript types.
|
||||||
|
@ -2170,19 +2170,24 @@ RED.view = (function() {
|
|||||||
n.n.moved = true;
|
n.n.moved = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// If a node has moved and ends up being spliced into a link, keep
|
||||||
// Check to see if we need to splice a link
|
// track of which historyEvent to add the splice info to
|
||||||
|
let targetSpliceEvent = null
|
||||||
if (moveEvent.nodes.length > 0) {
|
if (moveEvent.nodes.length > 0) {
|
||||||
historyEvent.events.push(moveEvent)
|
historyEvent.events.push(moveEvent)
|
||||||
if (activeSpliceLink) {
|
targetSpliceEvent = moveEvent
|
||||||
var linkToSplice = d3.select(activeSpliceLink).data()[0];
|
|
||||||
spliceLink(linkToSplice, movingSet.get(0).n, moveEvent)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (moveAndChangedGroupEvent.nodes.length > 0) {
|
if (moveAndChangedGroupEvent.nodes.length > 0) {
|
||||||
historyEvent.events.push(moveAndChangedGroupEvent)
|
historyEvent.events.push(moveAndChangedGroupEvent)
|
||||||
|
targetSpliceEvent = moveAndChangedGroupEvent
|
||||||
}
|
}
|
||||||
|
// activeSpliceLink will only be set if the movingSet has a single
|
||||||
|
// node that is able to splice.
|
||||||
|
if (targetSpliceEvent && activeSpliceLink) {
|
||||||
|
var linkToSplice = d3.select(activeSpliceLink).data()[0];
|
||||||
|
spliceLink(linkToSplice, movingSet.get(0).n, targetSpliceEvent)
|
||||||
|
}
|
||||||
|
|
||||||
// Only continue if something has moved
|
// Only continue if something has moved
|
||||||
if (historyEvent.events.length > 0) {
|
if (historyEvent.events.length > 0) {
|
||||||
RED.nodes.dirty(true);
|
RED.nodes.dirty(true);
|
||||||
|
@ -351,10 +351,10 @@ RED.user = (function() {
|
|||||||
userIcon.css({
|
userIcon.css({
|
||||||
backgroundImage: "url("+user.image+")",
|
backgroundImage: "url("+user.image+")",
|
||||||
})
|
})
|
||||||
} else if (user.anonymous) {
|
} else if (user.anonymous || (!user.username && !user.email)) {
|
||||||
$('<i class="fa fa-user"></i>').appendTo(userIcon);
|
$('<i class="fa fa-user"></i>').appendTo(userIcon);
|
||||||
} else {
|
} else {
|
||||||
$('<span>').text(user.username.substring(0,2)).appendTo(userIcon);
|
$('<span>').text((user.username || user.email).substring(0,2)).appendTo(userIcon);
|
||||||
}
|
}
|
||||||
if (user.profileColor !== undefined) {
|
if (user.profileColor !== undefined) {
|
||||||
userIcon.addClass('red-ui-user-profile-color-' + user.profileColor)
|
userIcon.addClass('red-ui-user-profile-color-' + user.profileColor)
|
||||||
|
@ -2,4 +2,15 @@
|
|||||||
&.red-ui-popover-panel {
|
&.red-ui-popover-panel {
|
||||||
border-top: none;
|
border-top: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
.red-ui-autoComplete-completion {
|
||||||
|
font-family: var(--red-ui-monospace-font);
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
flex-grow: 1;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
direction: rtl;
|
||||||
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
@ -39,10 +39,36 @@
|
|||||||
<dd><b>MQTTv5</b>: Ablaufzeit der Nachricht in Sekunden.</dd>
|
<dd><b>MQTTv5</b>: Ablaufzeit der Nachricht in Sekunden.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<h3>Details</h3>
|
<h3>Details</h3>
|
||||||
<p>Das abonnierte Topic darf MQTT-Platzhalterzeichen (wildcards) enthalten (+ für eine Ebene und # für mehrere Ebenen).</p>
|
<p>Das abonnierte Topic darf MQTT-Platzhalterzeichen (wildcards) enthalten (+ für eine Ebene und # für mehrere Ebenen).</p>
|
||||||
<p>Dieser Node erfordert eine Verbindung zu einem MQTT-Broker, der über die Auswahlliste selektiert werden kann.
|
<p>Diese Node erfordert eine Verbindung zu einem MQTT-Broker, der über die Auswahlliste selektiert werden kann. Eine neue Verbindung wird durch Klicken auf das Stiftsymbol erstellt.</p>
|
||||||
Eine neue Verbindung wird durch Klicken auf das Stiftsymbol erstellt.</p>
|
|
||||||
<p>Mehrere MQTT-Nodes (in oder out) können bei Bedarf dieselbe Broker-Verbindung nutzen.</p>
|
<p>Mehrere MQTT-Nodes (in oder out) können bei Bedarf dieselbe Broker-Verbindung nutzen.</p>
|
||||||
|
<h4>Dynamische Steuerung</h4>
|
||||||
|
Die von der Node genutzte Verbindung kann dynamisch gesteuert werden, wenn die MQTT-Node eine der folgenden Nachrichten erhält. Die Payload dieser Nachrichten werden nicht veröffentlicht.
|
||||||
|
<h4>Eingangsdaten</h4>
|
||||||
|
<p>Nur Verfügbar, wenn die Node für dynamische Abonnements konfiguriert wurde.</p>
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>action <span class="property-type">string</span></dt>
|
||||||
|
<dd>Der Name der Aktion, die die MQTT-Node ausführen soll. Verfügbare Aktionen sind: <code>"connect"</code>, <code>"disconnect"</code>, <code>"getSubscriptions"</code>, <code>"subscribe"</code> und <code>"unsubscribe"</code>.</dd>
|
||||||
|
<dt class="optional">topic <span class="property-type">string|object|array</span></dt>
|
||||||
|
<dd>Bei den Aktionen <code>"subscribe"</code> und <code>"unsubscribe"</code> gibt diese Eigenschaft die MQTT-Topic an. Dabei kann es sich um Folgendes handeln:
|
||||||
|
<ul>
|
||||||
|
<li>eine Zeichenfolge, die den Topic-Filter enthält</li>
|
||||||
|
<li>ein Objekt mit den Eigenschaften <code>topic</code> und <code>qos</code></li>
|
||||||
|
<li>ein Array aus Zeichenfolgen oder Objekten, um mehrere Topics gleichzeitig zu verwalten</li>
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
<dt class="optional">broker <span class="property-type">broker</span> </dt>
|
||||||
|
<dd>Für die Aktion <code>"connect"</code> kann diese Eigenschaft jede der einzelnen Broker-Konfigurationseinstellungen überschreiben, einschließlich: <ul>
|
||||||
|
<li><code>broker</code></li>
|
||||||
|
<li><code>port</code></li>
|
||||||
|
<li><code>url</code> - überschreibt Broker/Port, um eine vollständige Verbindungs-URL bereitzustellen</li>
|
||||||
|
<li><code>username</code></li>
|
||||||
|
<li><code>password</code></li>
|
||||||
|
</ul>
|
||||||
|
<p>Wenn diese Eigenschaft gesetzt ist und der Broker bereits verbunden ist, wird ein Fehler protokolliert, es sei denn, die Eigenschaft <code>force</code> gesetzt - in diesem Fall wird die Verbindung zum Broker getrennt, die neuen Einstellungen angewendet und erneut verbunden.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/html" data-help-name="mqtt out">
|
<script type="text/html" data-help-name="mqtt out">
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@node-red/nodes",
|
"name": "@node-red/nodes",
|
||||||
"version": "4.0.8",
|
"version": "4.0.9",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@node-red/registry",
|
"name": "@node-red/registry",
|
||||||
"version": "4.0.8",
|
"version": "4.0.9",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
@ -16,7 +16,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@node-red/util": "4.0.8",
|
"@node-red/util": "4.0.9",
|
||||||
"clone": "2.1.2",
|
"clone": "2.1.2",
|
||||||
"fs-extra": "11.2.0",
|
"fs-extra": "11.2.0",
|
||||||
"semver": "7.6.3",
|
"semver": "7.6.3",
|
||||||
|
@ -96,7 +96,11 @@ var api = module.exports = {
|
|||||||
} else if (scope === 'node') {
|
} else if (scope === 'node') {
|
||||||
var node = runtime.nodes.getNode(id);
|
var node = runtime.nodes.getNode(id);
|
||||||
if (node) {
|
if (node) {
|
||||||
ctx = node.context();
|
if (/^subflow:/.test(node.type)) {
|
||||||
|
ctx = runtime.nodes.getContext(node.id);
|
||||||
|
} else {
|
||||||
|
ctx = node.context();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
@ -104,13 +108,25 @@ var api = module.exports = {
|
|||||||
store = store || availableStores.default;
|
store = store || availableStores.default;
|
||||||
ctx.get(key,store,function(err, v) {
|
ctx.get(key,store,function(err, v) {
|
||||||
if (opts.keysOnly) {
|
if (opts.keysOnly) {
|
||||||
|
const result = {}
|
||||||
if (Array.isArray(v)) {
|
if (Array.isArray(v)) {
|
||||||
resolve({ [store]: { format: `array[${v.length}]`}})
|
result.format = `array[${v.length}]`
|
||||||
} else if (typeof v === 'object') {
|
} else if (typeof v === 'object') {
|
||||||
resolve({ [store]: { keys: Object.keys(v), format: 'Object' } })
|
result.keys = Object.keys(v).map(k => {
|
||||||
|
if (Array.isArray(v[k])) {
|
||||||
|
return { key: k, format: `array[${v[k].length}]`, length: v[k].length }
|
||||||
|
} else if (typeof v[k] === 'object') {
|
||||||
|
return { key: k, format: 'object' }
|
||||||
|
} else {
|
||||||
|
return { key: k }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
result.format = 'object'
|
||||||
} else {
|
} else {
|
||||||
resolve({ [store]: { keys: [] }})
|
result.keys = []
|
||||||
}
|
}
|
||||||
|
resolve({ [store]: result })
|
||||||
|
return
|
||||||
}
|
}
|
||||||
var encoded = util.encodeObject({msg:v});
|
var encoded = util.encodeObject({msg:v});
|
||||||
if (store !== availableStores.default) {
|
if (store !== availableStores.default) {
|
||||||
@ -147,7 +163,7 @@ var api = module.exports = {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
result[store] = { keys }
|
result[store] = { keys: keys.map(key => { return { key }}) }
|
||||||
c--;
|
c--;
|
||||||
if (c === 0) {
|
if (c === 0) {
|
||||||
if (!errorReported) {
|
if (!errorReported) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@node-red/runtime",
|
"name": "@node-red/runtime",
|
||||||
"version": "4.0.8",
|
"version": "4.0.9",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
@ -16,8 +16,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@node-red/registry": "4.0.8",
|
"@node-red/registry": "4.0.9",
|
||||||
"@node-red/util": "4.0.8",
|
"@node-red/util": "4.0.9",
|
||||||
"async-mutex": "0.5.0",
|
"async-mutex": "0.5.0",
|
||||||
"clone": "2.1.2",
|
"clone": "2.1.2",
|
||||||
"express": "4.21.2",
|
"express": "4.21.2",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@node-red/util",
|
"name": "@node-red/util",
|
||||||
"version": "4.0.8",
|
"version": "4.0.9",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
10
packages/node_modules/node-red/package.json
vendored
10
packages/node_modules/node-red/package.json
vendored
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "node-red",
|
"name": "node-red",
|
||||||
"version": "4.0.8",
|
"version": "4.0.9",
|
||||||
"description": "Low-code programming for event-driven applications",
|
"description": "Low-code programming for event-driven applications",
|
||||||
"homepage": "https://nodered.org",
|
"homepage": "https://nodered.org",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
@ -31,10 +31,10 @@
|
|||||||
"flow"
|
"flow"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@node-red/editor-api": "4.0.8",
|
"@node-red/editor-api": "4.0.9",
|
||||||
"@node-red/runtime": "4.0.8",
|
"@node-red/runtime": "4.0.9",
|
||||||
"@node-red/util": "4.0.8",
|
"@node-red/util": "4.0.9",
|
||||||
"@node-red/nodes": "4.0.8",
|
"@node-red/nodes": "4.0.9",
|
||||||
"basic-auth": "2.0.1",
|
"basic-auth": "2.0.1",
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
"cors": "2.8.5",
|
"cors": "2.8.5",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user