module.exports = function (RED) { function buildNamesFromList(targets) { 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 = []; if (startIndex > endIndex) { const tmp = startIndex; 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) { const suffixes = buildNamesFromList(targets); 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; } for (let i = startIndex; i <= endIndex; i += 1) { names.push(prefix + i + suffix); } }); return names; } function buildControlNames(mode, targets, startIndex, endIndex) { 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) { const a = (action || "").toString().toLowerCase(); if (a === "unsubscribe" || a === "unsub") { return "UNSUBSCRIBE"; } return "SUBSCRIBE"; } function XilicaSubscribe(config) { RED.nodes.createNode(this, config); const node = this; node.action = config.action || "subscribe"; node.mode = config.mode || "list"; 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.on("input", (msg, send, done) => { send = send || function () { node.send.apply(node, arguments); }; done = done || function () {}; const action = normaliseAction(msg.action || node.action); const mode = (msg.mode || node.mode || "list").toString(); 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 = typeof msg.transport === "string" && msg.transport.trim().length ? msg.transport.trim() : node.transport; const names = buildControlNames(mode, targets || "", startIndex, endIndex); if (!names.length) { node.warn("xilica-subscribe: no targets defined"); send(msg); done(); return; } const lines = names.map( (name) => action + " " + name + ' "' + transport + '"', ); msg.payload = lines.join("\r"); send(msg); done(); }); } RED.nodes.registerType("xilica-subscribe", XilicaSubscribe); };