smithtek-mako-rf 2.9.7 → 2.9.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
package/smithtek-mako-rf.js
CHANGED
|
@@ -117,7 +117,9 @@ module.exports = function (RED) {
|
|
|
117
117
|
try { port.removeListener("data", onData); } catch (_e2) {}
|
|
118
118
|
}
|
|
119
119
|
try { if (typeof port.flush === "function") port.flush(() => {}); } catch (_e) {}
|
|
120
|
+
if (state._rssiCleanup === cleanup) delete state._rssiCleanup;
|
|
120
121
|
}
|
|
122
|
+
state._rssiCleanup = cleanup;
|
|
121
123
|
|
|
122
124
|
function onData(chunk) {
|
|
123
125
|
rx = Buffer.concat([rx, Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)]);
|
|
@@ -225,7 +227,16 @@ module.exports = function (RED) {
|
|
|
225
227
|
const regIndex = Math.floor(byteOffset / 2);
|
|
226
228
|
|
|
227
229
|
const w = (i) => (regs[i] & 0xffff);
|
|
230
|
+
const isBoolArray = (Array.isArray(regs) && typeof regs[0] === "boolean");
|
|
228
231
|
|
|
232
|
+
function coilWord(wordIndex) {
|
|
233
|
+
let out = 0;
|
|
234
|
+
const base = wordIndex * 16;
|
|
235
|
+
for (let b = 0; b < 16; b++) {
|
|
236
|
+
if (regs[base + b]) out |= (1 << b);
|
|
237
|
+
}
|
|
238
|
+
return out >>> 0;
|
|
239
|
+
}
|
|
229
240
|
// 4 bytes from two 16-bit words in common Modbus orders
|
|
230
241
|
function bytesABCD(a, b) {
|
|
231
242
|
return Buffer.from([(a >> 8) & 0xff, a & 0xff, (b >> 8) & 0xff, b & 0xff]);
|
|
@@ -300,12 +311,25 @@ module.exports = function (RED) {
|
|
|
300
311
|
return buf.readFloatBE(0);
|
|
301
312
|
}
|
|
302
313
|
|
|
303
|
-
case "digital to unsigned binary encoder":
|
|
304
|
-
|
|
314
|
+
case "digital to unsigned binary encoder": {
|
|
315
|
+
const word = w(regIndex) >>> 0;
|
|
316
|
+
|
|
317
|
+
// If the UI provided a bit (0–15), return that bit as TRUE/FALSE
|
|
318
|
+
const bit = clampInt(offsetBit, 0, 15, 0);
|
|
319
|
+
return ((word >> bit) & 1) === 1;
|
|
320
|
+
}
|
|
321
|
+
|
|
305
322
|
|
|
306
|
-
// optional internal bool support
|
|
307
323
|
case "bool": {
|
|
308
324
|
const bit = clampInt(offsetBit, 0, 15, 0);
|
|
325
|
+
|
|
326
|
+
// If this is FC1/FC2 data (boolean array), read bit directly
|
|
327
|
+
if (isBoolArray) {
|
|
328
|
+
const idx = (regIndex * 16) + bit;
|
|
329
|
+
return !!regs[idx];
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Otherwise treat as 16-bit register
|
|
309
333
|
return ((w(regIndex) >> bit) & 1) === 1;
|
|
310
334
|
}
|
|
311
335
|
|
|
@@ -498,6 +522,7 @@ module.exports = function (RED) {
|
|
|
498
522
|
state.busy = true;
|
|
499
523
|
|
|
500
524
|
(async () => {
|
|
525
|
+
await sleep(20);
|
|
501
526
|
while (state.queue.length > 0) {
|
|
502
527
|
const item = state.queue.shift();
|
|
503
528
|
const { node, msg, send, done, req, items } = item;
|
|
@@ -548,8 +573,9 @@ module.exports = function (RED) {
|
|
|
548
573
|
// Force reconnect next attempt
|
|
549
574
|
state.connected = false;
|
|
550
575
|
try {
|
|
551
|
-
|
|
552
|
-
|
|
576
|
+
await new Promise((resolve) => state.client.close(() => resolve()));
|
|
577
|
+
} catch (_e) {}
|
|
578
|
+
|
|
553
579
|
|
|
554
580
|
if (attempt < totalTries && gap_s > 0) {
|
|
555
581
|
await sleep(Math.floor(gap_s * 1000));
|
|
@@ -598,8 +624,12 @@ module.exports = function (RED) {
|
|
|
598
624
|
|
|
599
625
|
|
|
600
626
|
const rssiDbm = await queryRssiOnSamePort(state, guardMs, timeoutMs);
|
|
627
|
+
await sleep(30);
|
|
601
628
|
state.connected = false;
|
|
602
|
-
|
|
629
|
+
try {
|
|
630
|
+
await new Promise((resolve) => state.client.close(() => resolve()));
|
|
631
|
+
} catch (_e) {}
|
|
632
|
+
|
|
603
633
|
|
|
604
634
|
|
|
605
635
|
const nodeKeyBase = sanitizeKey(node.name || busName || "mako_rf");
|
|
@@ -652,6 +682,7 @@ module.exports = function (RED) {
|
|
|
652
682
|
this.gap_s = toNum(n.gap_s, 0);
|
|
653
683
|
this.maxQueue = toNum(n.maxQueue, 50);
|
|
654
684
|
|
|
685
|
+
BUS.delete(this.id);
|
|
655
686
|
ensureBusState(this);
|
|
656
687
|
|
|
657
688
|
this.on("close", (removed, done) => {
|
|
@@ -769,9 +800,32 @@ module.exports = function (RED) {
|
|
|
769
800
|
});
|
|
770
801
|
|
|
771
802
|
node.on("close", function (_removed, done) {
|
|
803
|
+
try {
|
|
804
|
+
const busCfg = RED.nodes.getNode(config.bus);
|
|
805
|
+
if (busCfg) {
|
|
806
|
+
const s = BUS.get(busCfg.id);
|
|
807
|
+
if (s) {
|
|
808
|
+
// NEW: stop any in-flight queue processor from the old deploy
|
|
809
|
+
s.queue = [];
|
|
810
|
+
s.busy = false;
|
|
811
|
+
|
|
812
|
+
if (typeof s._rssiCleanup === "function") {
|
|
813
|
+
try { s._rssiCleanup(); } catch (_e) {}
|
|
814
|
+
}
|
|
815
|
+
if (s.client) {
|
|
816
|
+
try { s.client.close(() => {}); } catch (_e) {}
|
|
817
|
+
s.connected = false;
|
|
818
|
+
s.client = new (require("modbus-serial"))();
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
} catch (_e) {}
|
|
823
|
+
|
|
772
824
|
node.status({});
|
|
773
825
|
done();
|
|
774
826
|
});
|
|
827
|
+
|
|
828
|
+
|
|
775
829
|
}
|
|
776
830
|
|
|
777
831
|
RED.nodes.registerType("smithtek-mako-rf", SmithtekMakoRfNode);
|
|
Binary file
|