xilica-subscribe node rules and text box changed
This commit is contained in:
@@ -5,10 +5,7 @@ RED.nodes.registerType('xilica-subscribe', {
|
|||||||
defaults: {
|
defaults: {
|
||||||
name: { value: "" },
|
name: { value: "" },
|
||||||
action: { value: "subscribe" },
|
action: { value: "subscribe" },
|
||||||
mode: { value: "list" },
|
rules: { value: [] },
|
||||||
targets: { value: "" },
|
|
||||||
startIndex: { value: 1 },
|
|
||||||
endIndex: { value: 1 },
|
|
||||||
transport: { value: "TCP" }
|
transport: { value: "TCP" }
|
||||||
},
|
},
|
||||||
inputs: 1,
|
inputs: 1,
|
||||||
@@ -20,6 +17,100 @@ RED.nodes.registerType('xilica-subscribe', {
|
|||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
return "xilica " + act;
|
return "xilica " + act;
|
||||||
|
},
|
||||||
|
oneditprepare: function () {
|
||||||
|
var node = this;
|
||||||
|
var rules = node.rules || [];
|
||||||
|
|
||||||
|
$("#node-input-rules").editableList({
|
||||||
|
addItem: function (container, index, rule) {
|
||||||
|
rule = rule || {};
|
||||||
|
|
||||||
|
var row = $('<div/>').appendTo(container);
|
||||||
|
|
||||||
|
var typeField = $('<select/>', {
|
||||||
|
class: "node-input-rule-type",
|
||||||
|
style: "width: 120px; margin-right: 5px;"
|
||||||
|
}).appendTo(row);
|
||||||
|
$('<option/>', { value: "eq", text: "==" }).appendTo(typeField);
|
||||||
|
$('<option/>', { value: "idx", text: "Indexed" }).appendTo(typeField);
|
||||||
|
|
||||||
|
var valueField = $('<input/>', {
|
||||||
|
class: "node-input-rule-value",
|
||||||
|
type: "text",
|
||||||
|
style: "width: 180px; margin-right: 5px;"
|
||||||
|
}).appendTo(row);
|
||||||
|
|
||||||
|
var fromField = $('<input/>', {
|
||||||
|
class: "node-input-rule-from",
|
||||||
|
type: "number",
|
||||||
|
style: "width: 80px; margin-right: 5px;",
|
||||||
|
placeholder: "From"
|
||||||
|
}).appendTo(row);
|
||||||
|
|
||||||
|
var toField = $('<input/>', {
|
||||||
|
class: "node-input-rule-to",
|
||||||
|
type: "number",
|
||||||
|
style: "width: 80px;",
|
||||||
|
placeholder: "To"
|
||||||
|
}).appendTo(row);
|
||||||
|
|
||||||
|
function updateVisibility() {
|
||||||
|
var t = typeField.val();
|
||||||
|
if (t === "idx") {
|
||||||
|
fromField.show();
|
||||||
|
toField.show();
|
||||||
|
} else {
|
||||||
|
fromField.hide();
|
||||||
|
toField.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typeField.on("change", updateVisibility);
|
||||||
|
|
||||||
|
typeField.val(rule.t || "eq");
|
||||||
|
valueField.val(rule.v || "");
|
||||||
|
if (rule.from !== undefined) {
|
||||||
|
fromField.val(rule.from);
|
||||||
|
}
|
||||||
|
if (rule.to !== undefined) {
|
||||||
|
toField.val(rule.to);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateVisibility();
|
||||||
|
},
|
||||||
|
removable: true,
|
||||||
|
sortable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
(rules || []).forEach(function (r) {
|
||||||
|
$("#node-input-rules").editableList('addItem', r);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
oneditsave: function () {
|
||||||
|
var rules = [];
|
||||||
|
$("#node-input-rules").editableList('items').each(function () {
|
||||||
|
var row = $(this);
|
||||||
|
var type = $(".node-input-rule-type", row).val() || "eq";
|
||||||
|
var value = $(".node-input-rule-value", row).val() || "";
|
||||||
|
var from = $(".node-input-rule-from", row).val();
|
||||||
|
var to = $(".node-input-rule-to", row).val();
|
||||||
|
|
||||||
|
var rule = { t: type, v: value };
|
||||||
|
|
||||||
|
if (type === "idx") {
|
||||||
|
if (from !== "") {
|
||||||
|
rule.from = parseInt(from, 10);
|
||||||
|
}
|
||||||
|
if (to !== "") {
|
||||||
|
rule.to = parseInt(to, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rules.push(rule);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.rules = rules;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@@ -37,25 +128,8 @@ RED.nodes.registerType('xilica-subscribe', {
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<label for="node-input-mode">Mode</label>
|
<label>Rules</label>
|
||||||
<select id="node-input-mode">
|
<ol id="node-input-rules"></ol>
|
||||||
<option value="list">Explicit list</option>
|
|
||||||
<option value="startsWith">Starts with</option>
|
|
||||||
<option value="endsWith">Ends with</option>
|
|
||||||
<option value="startsAndEnds">Starts with and ends with</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="form-row">
|
|
||||||
<label for="node-input-targets">Targets</label>
|
|
||||||
<textarea id="node-input-targets" rows="5" style="width: 100%;"></textarea>
|
|
||||||
</div>
|
|
||||||
<div class="form-row">
|
|
||||||
<label for="node-input-startIndex">Start index</label>
|
|
||||||
<input type="number" id="node-input-startIndex" min="0">
|
|
||||||
</div>
|
|
||||||
<div class="form-row">
|
|
||||||
<label for="node-input-endIndex">End index</label>
|
|
||||||
<input type="number" id="node-input-endIndex" min="0">
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<label for="node-input-transport">Transport</label>
|
<label for="node-input-transport">Transport</label>
|
||||||
@@ -67,13 +141,10 @@ RED.nodes.registerType('xilica-subscribe', {
|
|||||||
<p>Builds <code>SUBSCRIBE</code> or <code>UNSUBSCRIBE</code> commands for a Xilica Solaro processor.</p>
|
<p>Builds <code>SUBSCRIBE</code> or <code>UNSUBSCRIBE</code> commands for a Xilica Solaro processor.</p>
|
||||||
<p>On each input message, the node sets <code>msg.payload</code> to one or more commands separated by carriage returns. Wire the output into a <code>xilica-command</code> node to send them over TCP.</p>
|
<p>On each input message, the node sets <code>msg.payload</code> to one or more commands separated by carriage returns. Wire the output into a <code>xilica-command</code> node to send them over TCP.</p>
|
||||||
<p><strong>Action</strong> selects whether to generate <code>SUBSCRIBE</code> or <code>UNSUBSCRIBE</code> commands.</p>
|
<p><strong>Action</strong> selects whether to generate <code>SUBSCRIBE</code> or <code>UNSUBSCRIBE</code> commands.</p>
|
||||||
<p><strong>Mode</strong> controls how the Targets field is interpreted:</p>
|
<p><strong>Rules</strong> define which control names to generate, similar to the Switch node's rule list:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><strong>Explicit list</strong>: each non-empty line in Targets is used as a full control name (e.g. <code>MASTER_GAIN</code>).</li>
|
<li><strong>Type ==</strong>: the Value field is used as a full control name (e.g. <code>MASTER_GAIN</code>).</li>
|
||||||
<li><strong>Starts with</strong>: each line in Targets is treated as a prefix (e.g. <code>CH</code>), and Start/End index define the numeric range (e.g. 1–48 → <code>CH1</code>…<code>CH48</code>).</li>
|
<li><strong>Type Indexed</strong>: the Value field is a base string (e.g. <code>CH</code>), and the From/To fields define a numeric range (e.g. 1–48 → <code>CH1</code>…<code>CH48</code>).</li>
|
||||||
<li><strong>Ends with</strong>: each line in Targets is treated as a suffix (e.g. <code>_OUT</code>), and Start/End index define the numeric range (e.g. 1–4 → <code>1_OUT</code>…<code>4_OUT</code>).</li>
|
|
||||||
<li><strong>Starts with and ends with</strong>: each line in Targets is interpreted as <code>prefix|suffix</code> (for example <code>CH|OUT</code>), and Start/End index define the numeric range (e.g. 4–28 → <code>CH4OUT</code>…<code>CH28OUT</code>).</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<p>The Transport field controls the subscription transport string, typically <code>TCP</code>. The node generates commands like <code>SUBSCRIBE CH1 "TCP"</code>.</p>
|
<p>The Transport field controls the subscription transport string, typically <code>TCP</code>. The node generates commands like <code>SUBSCRIBE CH1 "TCP"</code>.</p>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,76 +1,53 @@
|
|||||||
module.exports = function (RED) {
|
module.exports = function (RED) {
|
||||||
function buildNamesFromList(targets) {
|
function buildControlNamesFromRules(rules) {
|
||||||
return targets
|
|
||||||
.split(/\r?\n/)
|
|
||||||
.map((l) => l.trim())
|
|
||||||
.filter((l) => l.length > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildNamesStartsWith(targets, startIndex, endIndex) {
|
|
||||||
const prefixes = buildNamesFromList(targets);
|
|
||||||
const names = [];
|
const names = [];
|
||||||
if (startIndex > endIndex) {
|
if (!Array.isArray(rules)) {
|
||||||
const tmp = startIndex;
|
return names;
|
||||||
startIndex = endIndex;
|
|
||||||
endIndex = tmp;
|
|
||||||
}
|
}
|
||||||
prefixes.forEach((prefix) => {
|
|
||||||
for (let i = startIndex; i <= endIndex; i += 1) {
|
|
||||||
names.push(prefix + i);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return names;
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildNamesEndsWith(targets, startIndex, endIndex) {
|
rules.forEach((rule) => {
|
||||||
const suffixes = buildNamesFromList(targets);
|
if (!rule) {
|
||||||
const names = [];
|
|
||||||
if (startIndex > endIndex) {
|
|
||||||
const tmp = startIndex;
|
|
||||||
startIndex = endIndex;
|
|
||||||
endIndex = tmp;
|
|
||||||
}
|
|
||||||
suffixes.forEach((suffix) => {
|
|
||||||
for (let i = startIndex; i <= endIndex; i += 1) {
|
|
||||||
names.push(String(i) + suffix);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return names;
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildNamesStartsAndEnds(targets, startIndex, endIndex) {
|
|
||||||
const patterns = buildNamesFromList(targets);
|
|
||||||
const names = [];
|
|
||||||
if (startIndex > endIndex) {
|
|
||||||
const tmp = startIndex;
|
|
||||||
startIndex = endIndex;
|
|
||||||
endIndex = tmp;
|
|
||||||
}
|
|
||||||
patterns.forEach((pattern) => {
|
|
||||||
const parts = pattern.split("|");
|
|
||||||
const prefix = (parts[0] || "").trim();
|
|
||||||
const suffix = (parts[1] || "").trim();
|
|
||||||
if (!prefix && !suffix) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (let i = startIndex; i <= endIndex; i += 1) {
|
|
||||||
names.push(prefix + i + suffix);
|
const type = (rule.t || rule.type || "eq").toString();
|
||||||
|
|
||||||
|
if (type === "idx") {
|
||||||
|
const base = (rule.v || rule.base || "").trim();
|
||||||
|
if (!base) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let from = parseInt(rule.from, 10);
|
||||||
|
let to = parseInt(rule.to, 10);
|
||||||
|
|
||||||
|
if (Number.isNaN(from) && Number.isNaN(to)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Number.isNaN(from)) {
|
||||||
|
from = to;
|
||||||
|
}
|
||||||
|
if (Number.isNaN(to)) {
|
||||||
|
to = from;
|
||||||
|
}
|
||||||
|
if (from > to) {
|
||||||
|
const tmp = from;
|
||||||
|
from = to;
|
||||||
|
to = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = from; i <= to; i += 1) {
|
||||||
|
names.push(base + i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const name = (rule.v || rule.value || "").trim();
|
||||||
|
if (name) {
|
||||||
|
names.push(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return names;
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildControlNames(mode, targets, startIndex, endIndex) {
|
return names;
|
||||||
if (mode === "startsWith") {
|
|
||||||
return buildNamesStartsWith(targets, startIndex, endIndex);
|
|
||||||
}
|
|
||||||
if (mode === "endsWith") {
|
|
||||||
return buildNamesEndsWith(targets, startIndex, endIndex);
|
|
||||||
}
|
|
||||||
if (mode === "startsAndEnds") {
|
|
||||||
return buildNamesStartsAndEnds(targets, startIndex, endIndex);
|
|
||||||
}
|
|
||||||
return buildNamesFromList(targets);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function normaliseAction(action) {
|
function normaliseAction(action) {
|
||||||
@@ -86,10 +63,7 @@ module.exports = function (RED) {
|
|||||||
const node = this;
|
const node = this;
|
||||||
|
|
||||||
node.action = config.action || "subscribe";
|
node.action = config.action || "subscribe";
|
||||||
node.mode = config.mode || "list";
|
node.rules = Array.isArray(config.rules) ? config.rules : [];
|
||||||
node.targets = config.targets || "";
|
|
||||||
node.startIndex = parseInt(config.startIndex, 10) || 1;
|
|
||||||
node.endIndex = parseInt(config.endIndex, 10) || node.startIndex;
|
|
||||||
node.transport = config.transport || "TCP";
|
node.transport = config.transport || "TCP";
|
||||||
|
|
||||||
node.on("input", (msg, send, done) => {
|
node.on("input", (msg, send, done) => {
|
||||||
@@ -101,37 +75,17 @@ module.exports = function (RED) {
|
|||||||
done = done || function () {};
|
done = done || function () {};
|
||||||
|
|
||||||
const action = normaliseAction(msg.action || node.action);
|
const action = normaliseAction(msg.action || node.action);
|
||||||
const mode = (msg.mode || node.mode || "list").toString();
|
const rules = Array.isArray(msg.rules) ? msg.rules : node.rules;
|
||||||
|
|
||||||
const targets =
|
|
||||||
typeof msg.targets === "string" && msg.targets.trim().length
|
|
||||||
? msg.targets
|
|
||||||
: node.targets;
|
|
||||||
|
|
||||||
let startIndex = node.startIndex;
|
|
||||||
let endIndex = node.endIndex;
|
|
||||||
if (Object.prototype.hasOwnProperty.call(msg, "startIndex")) {
|
|
||||||
const v = parseInt(msg.startIndex, 10);
|
|
||||||
if (!Number.isNaN(v)) {
|
|
||||||
startIndex = v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Object.prototype.hasOwnProperty.call(msg, "endIndex")) {
|
|
||||||
const v = parseInt(msg.endIndex, 10);
|
|
||||||
if (!Number.isNaN(v)) {
|
|
||||||
endIndex = v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const transport =
|
const transport =
|
||||||
typeof msg.transport === "string" && msg.transport.trim().length
|
typeof msg.transport === "string" && msg.transport.trim().length
|
||||||
? msg.transport.trim()
|
? msg.transport.trim()
|
||||||
: node.transport;
|
: node.transport;
|
||||||
|
|
||||||
const names = buildControlNames(mode, targets || "", startIndex, endIndex);
|
const names = buildControlNamesFromRules(rules);
|
||||||
|
|
||||||
if (!names.length) {
|
if (!names.length) {
|
||||||
node.warn("xilica-subscribe: no targets defined");
|
node.warn("xilica-subscribe: no rules defined");
|
||||||
send(msg);
|
send(msg);
|
||||||
done();
|
done();
|
||||||
return;
|
return;
|
||||||
@@ -150,4 +104,3 @@ module.exports = function (RED) {
|
|||||||
|
|
||||||
RED.nodes.registerType("xilica-subscribe", XilicaSubscribe);
|
RED.nodes.registerType("xilica-subscribe", XilicaSubscribe);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user