secs4js 0.1.0

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.
Files changed (129) hide show
  1. package/LICENSE.md +20 -0
  2. package/README.md +442 -0
  3. package/lib/core/AbstractSecsCommunicator.d.ts +76 -0
  4. package/lib/core/AbstractSecsCommunicator.d.ts.map +1 -0
  5. package/lib/core/AbstractSecsCommunicator.js +85 -0
  6. package/lib/core/AbstractSecsCommunicator.js.map +1 -0
  7. package/lib/core/AbstractSecsMessage.d.ts +36 -0
  8. package/lib/core/AbstractSecsMessage.d.ts.map +1 -0
  9. package/lib/core/AbstractSecsMessage.js +66 -0
  10. package/lib/core/AbstractSecsMessage.js.map +1 -0
  11. package/lib/core/enums/HsmsSsControlType.d.ts +59 -0
  12. package/lib/core/enums/HsmsSsControlType.d.ts.map +1 -0
  13. package/lib/core/enums/HsmsSsControlType.js +105 -0
  14. package/lib/core/enums/HsmsSsControlType.js.map +1 -0
  15. package/lib/core/enums/RejectReason.d.ts +11 -0
  16. package/lib/core/enums/RejectReason.d.ts.map +1 -0
  17. package/lib/core/enums/RejectReason.js +13 -0
  18. package/lib/core/enums/RejectReason.js.map +1 -0
  19. package/lib/core/enums/SecsItemType.d.ts +33 -0
  20. package/lib/core/enums/SecsItemType.d.ts.map +1 -0
  21. package/lib/core/enums/SecsItemType.js +22 -0
  22. package/lib/core/enums/SecsItemType.js.map +1 -0
  23. package/lib/core/enums/SelectStatus.d.ts +11 -0
  24. package/lib/core/enums/SelectStatus.d.ts.map +1 -0
  25. package/lib/core/enums/SelectStatus.js +13 -0
  26. package/lib/core/enums/SelectStatus.js.map +1 -0
  27. package/lib/core/secs2item/AbstractSecs2Item.d.ts +34 -0
  28. package/lib/core/secs2item/AbstractSecs2Item.d.ts.map +1 -0
  29. package/lib/core/secs2item/AbstractSecs2Item.js +59 -0
  30. package/lib/core/secs2item/AbstractSecs2Item.js.map +1 -0
  31. package/lib/core/secs2item/Secs2ItemAscii.d.ts +18 -0
  32. package/lib/core/secs2item/Secs2ItemAscii.d.ts.map +1 -0
  33. package/lib/core/secs2item/Secs2ItemAscii.js +27 -0
  34. package/lib/core/secs2item/Secs2ItemAscii.js.map +1 -0
  35. package/lib/core/secs2item/Secs2ItemBinary.d.ts +11 -0
  36. package/lib/core/secs2item/Secs2ItemBinary.d.ts.map +1 -0
  37. package/lib/core/secs2item/Secs2ItemBinary.js +22 -0
  38. package/lib/core/secs2item/Secs2ItemBinary.js.map +1 -0
  39. package/lib/core/secs2item/Secs2ItemBoolean.d.ts +12 -0
  40. package/lib/core/secs2item/Secs2ItemBoolean.d.ts.map +1 -0
  41. package/lib/core/secs2item/Secs2ItemBoolean.js +27 -0
  42. package/lib/core/secs2item/Secs2ItemBoolean.js.map +1 -0
  43. package/lib/core/secs2item/Secs2ItemFactory.d.ts +27 -0
  44. package/lib/core/secs2item/Secs2ItemFactory.d.ts.map +1 -0
  45. package/lib/core/secs2item/Secs2ItemFactory.js +56 -0
  46. package/lib/core/secs2item/Secs2ItemFactory.js.map +1 -0
  47. package/lib/core/secs2item/Secs2ItemList.d.ts +11 -0
  48. package/lib/core/secs2item/Secs2ItemList.d.ts.map +1 -0
  49. package/lib/core/secs2item/Secs2ItemList.js +26 -0
  50. package/lib/core/secs2item/Secs2ItemList.js.map +1 -0
  51. package/lib/core/secs2item/Secs2ItemNumeric.d.ts +14 -0
  52. package/lib/core/secs2item/Secs2ItemNumeric.d.ts.map +1 -0
  53. package/lib/core/secs2item/Secs2ItemNumeric.js +128 -0
  54. package/lib/core/secs2item/Secs2ItemNumeric.js.map +1 -0
  55. package/lib/core/secs2item/Secs2ItemParser.d.ts +12 -0
  56. package/lib/core/secs2item/Secs2ItemParser.d.ts.map +1 -0
  57. package/lib/core/secs2item/Secs2ItemParser.js +74 -0
  58. package/lib/core/secs2item/Secs2ItemParser.js.map +1 -0
  59. package/lib/gem/Clock.d.ts +21 -0
  60. package/lib/gem/Clock.d.ts.map +1 -0
  61. package/lib/gem/Clock.js +65 -0
  62. package/lib/gem/Clock.js.map +1 -0
  63. package/lib/gem/Gem.d.ts +55 -0
  64. package/lib/gem/Gem.d.ts.map +1 -0
  65. package/lib/gem/Gem.js +137 -0
  66. package/lib/gem/Gem.js.map +1 -0
  67. package/lib/helper/Secs2ItemHelper.d.ts +96 -0
  68. package/lib/helper/Secs2ItemHelper.d.ts.map +1 -0
  69. package/lib/helper/Secs2ItemHelper.js +135 -0
  70. package/lib/helper/Secs2ItemHelper.js.map +1 -0
  71. package/lib/hsms/HsmsActiveCommunicator.d.ts +29 -0
  72. package/lib/hsms/HsmsActiveCommunicator.d.ts.map +1 -0
  73. package/lib/hsms/HsmsActiveCommunicator.js +123 -0
  74. package/lib/hsms/HsmsActiveCommunicator.js.map +1 -0
  75. package/lib/hsms/HsmsCommunicator.d.ts +70 -0
  76. package/lib/hsms/HsmsCommunicator.d.ts.map +1 -0
  77. package/lib/hsms/HsmsCommunicator.js +322 -0
  78. package/lib/hsms/HsmsCommunicator.js.map +1 -0
  79. package/lib/hsms/HsmsMessage.d.ts +92 -0
  80. package/lib/hsms/HsmsMessage.d.ts.map +1 -0
  81. package/lib/hsms/HsmsMessage.js +163 -0
  82. package/lib/hsms/HsmsMessage.js.map +1 -0
  83. package/lib/hsms/HsmsPassiveCommunicator.d.ts +48 -0
  84. package/lib/hsms/HsmsPassiveCommunicator.d.ts.map +1 -0
  85. package/lib/hsms/HsmsPassiveCommunicator.js +304 -0
  86. package/lib/hsms/HsmsPassiveCommunicator.js.map +1 -0
  87. package/lib/hsms/enums/HsmsControlType.d.ts +15 -0
  88. package/lib/hsms/enums/HsmsControlType.d.ts.map +1 -0
  89. package/lib/hsms/enums/HsmsControlType.js +17 -0
  90. package/lib/hsms/enums/HsmsControlType.js.map +1 -0
  91. package/lib/hsms/enums/RejectReason.d.ts +11 -0
  92. package/lib/hsms/enums/RejectReason.d.ts.map +1 -0
  93. package/lib/hsms/enums/RejectReason.js +13 -0
  94. package/lib/hsms/enums/RejectReason.js.map +1 -0
  95. package/lib/hsms/enums/SelectStatus.d.ts +11 -0
  96. package/lib/hsms/enums/SelectStatus.d.ts.map +1 -0
  97. package/lib/hsms/enums/SelectStatus.js +13 -0
  98. package/lib/hsms/enums/SelectStatus.js.map +1 -0
  99. package/lib/index.d.ts +28 -0
  100. package/lib/index.js +29 -0
  101. package/lib/secs1/Secs1Communicator.d.ts +51 -0
  102. package/lib/secs1/Secs1Communicator.d.ts.map +1 -0
  103. package/lib/secs1/Secs1Communicator.js +342 -0
  104. package/lib/secs1/Secs1Communicator.js.map +1 -0
  105. package/lib/secs1/Secs1Message.d.ts +21 -0
  106. package/lib/secs1/Secs1Message.d.ts.map +1 -0
  107. package/lib/secs1/Secs1Message.js +77 -0
  108. package/lib/secs1/Secs1Message.js.map +1 -0
  109. package/lib/secs1/Secs1MessageBlock.d.ts +23 -0
  110. package/lib/secs1/Secs1MessageBlock.d.ts.map +1 -0
  111. package/lib/secs1/Secs1MessageBlock.js +86 -0
  112. package/lib/secs1/Secs1MessageBlock.js.map +1 -0
  113. package/lib/secs1/Secs1OnTcpIpActiveCommunicator.d.ts +23 -0
  114. package/lib/secs1/Secs1OnTcpIpActiveCommunicator.d.ts.map +1 -0
  115. package/lib/secs1/Secs1OnTcpIpActiveCommunicator.js +82 -0
  116. package/lib/secs1/Secs1OnTcpIpActiveCommunicator.js.map +1 -0
  117. package/lib/secs1/Secs1OnTcpIpPassiveCommunicator.d.ts +19 -0
  118. package/lib/secs1/Secs1OnTcpIpPassiveCommunicator.d.ts.map +1 -0
  119. package/lib/secs1/Secs1OnTcpIpPassiveCommunicator.js +49 -0
  120. package/lib/secs1/Secs1OnTcpIpPassiveCommunicator.js.map +1 -0
  121. package/lib/secs1/Secs1SerialCommunicator.d.ts +18 -0
  122. package/lib/secs1/Secs1SerialCommunicator.d.ts.map +1 -0
  123. package/lib/secs1/Secs1SerialCommunicator.js +59 -0
  124. package/lib/secs1/Secs1SerialCommunicator.js.map +1 -0
  125. package/lib/sml/SmlParser.d.ts +27 -0
  126. package/lib/sml/SmlParser.d.ts.map +1 -0
  127. package/lib/sml/SmlParser.js +184 -0
  128. package/lib/sml/SmlParser.js.map +1 -0
  129. package/package.json +53 -0
@@ -0,0 +1,342 @@
1
+ import { AbstractSecsCommunicator } from "../core/AbstractSecsCommunicator.js";
2
+ import { Secs1MessageBlock } from "./Secs1MessageBlock.js";
3
+ import { Secs1Message } from "./Secs1Message.js";
4
+
5
+ //#region src/secs1/Secs1Communicator.ts
6
+ const ENQ = 5;
7
+ const EOT = 4;
8
+ const ACK = 6;
9
+ const NAK = 21;
10
+ var CommState = /* @__PURE__ */ function(CommState$1) {
11
+ CommState$1[CommState$1["IDLE"] = 0] = "IDLE";
12
+ CommState$1[CommState$1["WAIT_EOT"] = 1] = "WAIT_EOT";
13
+ CommState$1[CommState$1["WAIT_ACK"] = 2] = "WAIT_ACK";
14
+ CommState$1[CommState$1["WAIT_BLOCK_LENGTH"] = 3] = "WAIT_BLOCK_LENGTH";
15
+ CommState$1[CommState$1["WAIT_BLOCK_DATA"] = 4] = "WAIT_BLOCK_DATA";
16
+ return CommState$1;
17
+ }(CommState || {});
18
+ var Secs1Communicator = class extends AbstractSecsCommunicator {
19
+ retry;
20
+ isMaster;
21
+ stream = null;
22
+ state = CommState.IDLE;
23
+ buffer = Buffer.alloc(0);
24
+ sendQueue = [];
25
+ currentBlocks = [];
26
+ currentBlockIndex = 0;
27
+ retryCount = 0;
28
+ receivedBlocks = [];
29
+ expectedBlockNum = 1;
30
+ currentBlockLength = 0;
31
+ t1Timer = null;
32
+ t2Timer = null;
33
+ t4Timer = null;
34
+ constructor(config) {
35
+ super(config);
36
+ this.retry = config.retry ?? 3;
37
+ this.isMaster = config.isMaster ?? false;
38
+ }
39
+ attachStream(stream) {
40
+ this.stream = stream;
41
+ this.resetState();
42
+ this.buffer = Buffer.alloc(0);
43
+ stream.on("data", (data) => {
44
+ this.buffer = Buffer.concat([this.buffer, data]);
45
+ if (this.state === CommState.WAIT_BLOCK_LENGTH || this.state === CommState.WAIT_BLOCK_DATA) this.startT1();
46
+ this.processBuffer();
47
+ });
48
+ stream.on("close", () => {
49
+ this.rejectAllTransactions(/* @__PURE__ */ new Error("Stream closed"));
50
+ this.stream = null;
51
+ this.emit("disconnected");
52
+ this.stopAllTimers();
53
+ this.resetState();
54
+ });
55
+ stream.on("error", (err) => {
56
+ this.emit("error", err);
57
+ });
58
+ this.emit("connected");
59
+ this.processSendQueue();
60
+ }
61
+ stop() {
62
+ const stream = this.stream;
63
+ if (stream && !stream.destroyed) stream.destroy();
64
+ this.stream = null;
65
+ this.stopAllTimers();
66
+ this.resetState();
67
+ }
68
+ sendBuffer(buffer) {
69
+ this.sendQueue.push(buffer);
70
+ process.nextTick(() => this.processSendQueue());
71
+ return Promise.resolve();
72
+ }
73
+ createMessage(stream, func, wBit, body, systemBytes) {
74
+ return new Secs1Message(stream, func, wBit, body, systemBytes, this.deviceId);
75
+ }
76
+ clearT1() {
77
+ if (this.t1Timer) {
78
+ clearTimeout(this.t1Timer);
79
+ this.t1Timer = null;
80
+ }
81
+ }
82
+ clearT2() {
83
+ if (this.t2Timer) {
84
+ clearTimeout(this.t2Timer);
85
+ this.t2Timer = null;
86
+ }
87
+ }
88
+ clearT4() {
89
+ if (this.t4Timer) {
90
+ clearTimeout(this.t4Timer);
91
+ this.t4Timer = null;
92
+ }
93
+ }
94
+ stopAllTimers() {
95
+ this.clearT1();
96
+ this.clearT2();
97
+ this.clearT4();
98
+ }
99
+ startT1() {
100
+ this.clearT1();
101
+ if (this.timeoutT1 <= 0) return;
102
+ this.t1Timer = setTimeout(() => {
103
+ this.handleT1Timeout();
104
+ }, this.timeoutT1 * 1e3);
105
+ }
106
+ startT2() {
107
+ this.clearT2();
108
+ if (this.timeoutT2 <= 0) return;
109
+ const timeout = this.timeoutT2 * 1e3;
110
+ this.t2Timer = setTimeout(() => {
111
+ this.handleT2Timeout();
112
+ }, timeout);
113
+ }
114
+ startT4() {
115
+ this.clearT4();
116
+ if (this.timeoutT4 <= 0) return;
117
+ const timeout = this.timeoutT4 * 1e3;
118
+ this.t4Timer = setTimeout(() => {
119
+ this.handleT4Timeout();
120
+ }, timeout);
121
+ }
122
+ handleT1Timeout() {
123
+ console.warn("T1 Timeout");
124
+ this.t1Timer = null;
125
+ this.emit("error", /* @__PURE__ */ new Error("T1 Timeout"));
126
+ this.resetState();
127
+ }
128
+ handleT2Timeout() {
129
+ console.warn("T2 Timeout");
130
+ this.t2Timer = null;
131
+ if (this.state === CommState.WAIT_EOT) {
132
+ this.retryCount++;
133
+ if (this.retryCount > this.retry) {
134
+ this.emit("error", /* @__PURE__ */ new Error("Retry limit exceeded waiting for EOT"));
135
+ this.resetState();
136
+ } else {
137
+ console.log(`Retrying ENQ (${this.retryCount}/${this.retry})`);
138
+ this.sendByte(ENQ);
139
+ this.startT2();
140
+ }
141
+ return;
142
+ }
143
+ if (this.state === CommState.WAIT_ACK) {
144
+ this.retryCount++;
145
+ if (this.retryCount > this.retry) {
146
+ this.emit("error", /* @__PURE__ */ new Error("Retry limit exceeded waiting for ACK"));
147
+ this.resetState();
148
+ } else {
149
+ console.log(`Retrying Block (${this.retryCount}/${this.retry})`);
150
+ this.sendCurrentBlock();
151
+ }
152
+ return;
153
+ }
154
+ this.resetState();
155
+ }
156
+ handleT4Timeout() {
157
+ console.warn("T4 Timeout (Inter-block)");
158
+ this.t4Timer = null;
159
+ this.resetState();
160
+ }
161
+ resetState() {
162
+ this.state = CommState.IDLE;
163
+ this.receivedBlocks = [];
164
+ this.expectedBlockNum = 1;
165
+ this.currentBlockLength = 0;
166
+ this.stopAllTimers();
167
+ }
168
+ sendByte(byte) {
169
+ const stream = this.stream;
170
+ if (stream && !stream.destroyed) stream.write(Buffer.from([byte]));
171
+ }
172
+ processBuffer() {
173
+ while (this.buffer.length > 0) switch (this.state) {
174
+ case CommState.IDLE: {
175
+ const byte = this.buffer[0];
176
+ this.buffer = this.buffer.subarray(1);
177
+ if (byte === ENQ) {
178
+ this.sendByte(EOT);
179
+ this.state = CommState.WAIT_BLOCK_LENGTH;
180
+ this.receivedBlocks = [];
181
+ this.expectedBlockNum = 1;
182
+ this.startT1();
183
+ }
184
+ break;
185
+ }
186
+ case CommState.WAIT_EOT: {
187
+ const byte = this.buffer[0];
188
+ this.buffer = this.buffer.subarray(1);
189
+ if (byte === EOT) {
190
+ this.clearT2();
191
+ this.currentBlockIndex = 0;
192
+ this.sendCurrentBlock();
193
+ } else if (byte === ENQ) {
194
+ if (!this.isMaster) {
195
+ this.clearT2();
196
+ this.sendByte(EOT);
197
+ this.state = CommState.WAIT_BLOCK_LENGTH;
198
+ this.receivedBlocks = [];
199
+ this.expectedBlockNum = 1;
200
+ this.startT1();
201
+ }
202
+ }
203
+ break;
204
+ }
205
+ case CommState.WAIT_ACK: {
206
+ const byte = this.buffer[0];
207
+ this.buffer = this.buffer.subarray(1);
208
+ if (byte === ACK) {
209
+ this.clearT2();
210
+ if (this.currentBlocks[this.currentBlockIndex].eBit) {
211
+ this.currentBlocks = [];
212
+ this.retryCount = 0;
213
+ this.state = CommState.IDLE;
214
+ this.processSendQueue();
215
+ } else {
216
+ this.currentBlockIndex++;
217
+ this.sendCurrentBlock();
218
+ }
219
+ } else if (byte === NAK) {
220
+ this.clearT2();
221
+ this.handleT2Timeout();
222
+ }
223
+ break;
224
+ }
225
+ case CommState.WAIT_BLOCK_LENGTH: {
226
+ if (this.t4Timer) {
227
+ this.clearT4();
228
+ this.startT1();
229
+ }
230
+ const len = this.buffer[0];
231
+ if (len < 10) this.buffer = this.buffer.subarray(1);
232
+ else {
233
+ this.currentBlockLength = len;
234
+ this.buffer = this.buffer.subarray(1);
235
+ this.state = CommState.WAIT_BLOCK_DATA;
236
+ this.startT1();
237
+ }
238
+ break;
239
+ }
240
+ case CommState.WAIT_BLOCK_DATA:
241
+ if (this.buffer.length >= this.currentBlockLength + 2) {
242
+ const blockData = this.buffer.subarray(0, this.currentBlockLength + 2);
243
+ this.buffer = this.buffer.subarray(this.currentBlockLength + 2);
244
+ this.stopAllTimers();
245
+ const fullBlockBuffer = Buffer.alloc(1 + blockData.length);
246
+ fullBlockBuffer[0] = this.currentBlockLength;
247
+ blockData.copy(fullBlockBuffer, 1);
248
+ const block = new Secs1MessageBlock(fullBlockBuffer);
249
+ if (block.isValid()) if (block.blockNumber !== this.expectedBlockNum) {
250
+ console.warn(`Wrong Block Number. Expected ${this.expectedBlockNum}, got ${block.blockNumber}`);
251
+ this.sendByte(NAK);
252
+ this.state = CommState.IDLE;
253
+ this.resetState();
254
+ } else {
255
+ this.sendByte(ACK);
256
+ this.receivedBlocks.push(block);
257
+ if (block.eBit) {
258
+ try {
259
+ const msg = Secs1Message.fromBlocks(this.receivedBlocks);
260
+ this.handleMessage(msg);
261
+ } catch (e) {
262
+ this.emit("error", e instanceof Error ? e : new Error(String(e)));
263
+ }
264
+ this.resetState();
265
+ this.processSendQueue();
266
+ } else {
267
+ this.expectedBlockNum++;
268
+ this.state = CommState.WAIT_BLOCK_LENGTH;
269
+ this.startT4();
270
+ }
271
+ }
272
+ else {
273
+ console.warn("Invalid Checksum");
274
+ this.sendByte(NAK);
275
+ this.state = CommState.IDLE;
276
+ this.resetState();
277
+ }
278
+ } else return;
279
+ break;
280
+ default: return;
281
+ }
282
+ }
283
+ sendCurrentBlock() {
284
+ if (this.currentBlockIndex >= this.currentBlocks.length) return;
285
+ const stream = this.stream;
286
+ const block = this.currentBlocks[this.currentBlockIndex];
287
+ if (stream && !stream.destroyed) {
288
+ stream.write(block.buffer);
289
+ this.state = CommState.WAIT_ACK;
290
+ this.startT2();
291
+ }
292
+ }
293
+ processSendQueue() {
294
+ if (this.state !== CommState.IDLE) return;
295
+ const stream = this.stream;
296
+ if (!stream || stream.destroyed) return;
297
+ if (this.sendQueue.length === 0) return;
298
+ const buffer = this.sendQueue.shift();
299
+ if (!buffer) return;
300
+ try {
301
+ const rBit = (buffer[0] & 128) === 128;
302
+ const deviceId = (buffer[0] & 127) << 8 | buffer[1];
303
+ const streamId = buffer[2] & 127;
304
+ const wBit = (buffer[2] & 128) === 128;
305
+ const func = buffer[3];
306
+ const systemBytes = buffer.readUInt32BE(6);
307
+ const bodyBuffer = buffer.subarray(10);
308
+ this.currentBlocks = [];
309
+ let pos = 0;
310
+ let blockNum = 1;
311
+ if (bodyBuffer.length === 0) this.currentBlocks.push(Secs1MessageBlock.fromParts(deviceId, streamId, func, wBit, true, blockNum, systemBytes, Buffer.alloc(0), rBit));
312
+ else while (pos < bodyBuffer.length) {
313
+ const remaining = bodyBuffer.length - pos;
314
+ const chunkSize = remaining > 244 ? 244 : remaining;
315
+ const chunk = bodyBuffer.subarray(pos, pos + chunkSize);
316
+ const isLast = pos + chunkSize >= bodyBuffer.length;
317
+ this.currentBlocks.push(Secs1MessageBlock.fromParts(deviceId, streamId, func, wBit, isLast, blockNum, systemBytes, chunk, rBit));
318
+ pos += chunkSize;
319
+ blockNum++;
320
+ }
321
+ this.currentBlockIndex = 0;
322
+ this.retryCount = 0;
323
+ this.sendByte(ENQ);
324
+ this.state = CommState.WAIT_EOT;
325
+ this.startT2();
326
+ } catch (e) {
327
+ this.emit("error", e instanceof Error ? e : new Error(String(e)));
328
+ this.processSendQueue();
329
+ }
330
+ }
331
+ rejectAllTransactions(err) {
332
+ for (const [systemBytes, tx] of this._transactions) {
333
+ clearTimeout(tx.timer);
334
+ tx.reject(err);
335
+ this._transactions.delete(systemBytes);
336
+ }
337
+ }
338
+ };
339
+
340
+ //#endregion
341
+ export { Secs1Communicator };
342
+ //# sourceMappingURL=Secs1Communicator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Secs1Communicator.js","names":[],"sources":["../../src/secs1/Secs1Communicator.ts"],"sourcesContent":["import { Duplex } from \"stream\";\nimport {\n\tAbstractSecsCommunicator,\n\tSecsCommunicatorConfig,\n} from \"../core/AbstractSecsCommunicator.js\";\nimport { SecsMessage } from \"../core/AbstractSecsMessage.js\";\nimport { AbstractSecs2Item } from \"../core/secs2item/AbstractSecs2Item.js\";\nimport { Secs1Message } from \"./Secs1Message.js\";\nimport { Secs1MessageBlock } from \"./Secs1MessageBlock.js\";\n\nexport interface Secs1CommunicatorConfig extends SecsCommunicatorConfig {\n\tretry?: number;\n\tisMaster?: boolean;\n}\n\nconst ENQ = 0x05;\nconst EOT = 0x04;\nconst ACK = 0x06;\nconst NAK = 0x15;\n\nenum CommState {\n\tIDLE,\n\tWAIT_EOT,\n\tWAIT_ACK,\n\tWAIT_BLOCK_LENGTH,\n\tWAIT_BLOCK_DATA,\n}\n\nexport abstract class Secs1Communicator extends AbstractSecsCommunicator {\n\tpublic retry: number;\n\tpublic isMaster: boolean;\n\n\tprotected stream: Duplex | null = null;\n\n\tprivate state: CommState = CommState.IDLE;\n\tprivate buffer: Buffer = Buffer.alloc(0);\n\n\tprivate sendQueue: Buffer[] = [];\n\tprivate currentBlocks: Secs1MessageBlock[] = [];\n\tprivate currentBlockIndex = 0;\n\tprivate retryCount = 0;\n\n\tprivate receivedBlocks: Secs1MessageBlock[] = [];\n\tprivate expectedBlockNum = 1;\n\tprivate currentBlockLength = 0;\n\n\tprivate t1Timer: NodeJS.Timeout | null = null;\n\tprivate t2Timer: NodeJS.Timeout | null = null;\n\tprivate t4Timer: NodeJS.Timeout | null = null;\n\n\tconstructor(config: Secs1CommunicatorConfig) {\n\t\tsuper(config);\n\t\tthis.retry = config.retry ?? 3;\n\t\tthis.isMaster = config.isMaster ?? false;\n\t}\n\n\tprotected attachStream(stream: Duplex) {\n\t\tthis.stream = stream;\n\t\tthis.resetState();\n\t\tthis.buffer = Buffer.alloc(0);\n\n\t\tstream.on(\"data\", (data: Buffer) => {\n\t\t\tthis.buffer = Buffer.concat([this.buffer, data]);\n\t\t\tif (\n\t\t\t\tthis.state === CommState.WAIT_BLOCK_LENGTH ||\n\t\t\t\tthis.state === CommState.WAIT_BLOCK_DATA\n\t\t\t) {\n\t\t\t\tthis.startT1();\n\t\t\t}\n\t\t\tthis.processBuffer();\n\t\t});\n\n\t\tstream.on(\"close\", () => {\n\t\t\tthis.rejectAllTransactions(new Error(\"Stream closed\"));\n\t\t\tthis.stream = null;\n\t\t\tthis.emit(\"disconnected\");\n\t\t\tthis.stopAllTimers();\n\t\t\tthis.resetState();\n\t\t});\n\n\t\tstream.on(\"error\", (err: Error) => {\n\t\t\tthis.emit(\"error\", err);\n\t\t});\n\n\t\tthis.emit(\"connected\");\n\t\tthis.processSendQueue();\n\t}\n\n\tprotected stop() {\n\t\tconst stream = this.stream;\n\t\tif (stream && !stream.destroyed) {\n\t\t\tstream.destroy();\n\t\t}\n\t\tthis.stream = null;\n\t\tthis.stopAllTimers();\n\t\tthis.resetState();\n\t}\n\n\tprotected override sendBuffer(buffer: Buffer): Promise<void> {\n\t\tthis.sendQueue.push(buffer);\n\t\tprocess.nextTick(() => this.processSendQueue());\n\t\treturn Promise.resolve();\n\t}\n\n\tprotected override createMessage(\n\t\tstream: number,\n\t\tfunc: number,\n\t\twBit: boolean,\n\t\tbody: AbstractSecs2Item | null,\n\t\tsystemBytes: number,\n\t): SecsMessage {\n\t\treturn new Secs1Message(\n\t\t\tstream,\n\t\t\tfunc,\n\t\t\twBit,\n\t\t\tbody,\n\t\t\tsystemBytes,\n\t\t\tthis.deviceId,\n\t\t);\n\t}\n\n\tprivate clearT1() {\n\t\tif (this.t1Timer) {\n\t\t\tclearTimeout(this.t1Timer);\n\t\t\tthis.t1Timer = null;\n\t\t}\n\t}\n\n\tprivate clearT2() {\n\t\tif (this.t2Timer) {\n\t\t\tclearTimeout(this.t2Timer);\n\t\t\tthis.t2Timer = null;\n\t\t}\n\t}\n\n\tprivate clearT4() {\n\t\tif (this.t4Timer) {\n\t\t\tclearTimeout(this.t4Timer);\n\t\t\tthis.t4Timer = null;\n\t\t}\n\t}\n\n\tprivate stopAllTimers() {\n\t\tthis.clearT1();\n\t\tthis.clearT2();\n\t\tthis.clearT4();\n\t}\n\n\tprivate startT1() {\n\t\tthis.clearT1();\n\t\tif (this.timeoutT1 <= 0) return;\n\t\tthis.t1Timer = setTimeout(() => {\n\t\t\tthis.handleT1Timeout();\n\t\t}, this.timeoutT1 * 1000);\n\t}\n\n\tprivate startT2() {\n\t\tthis.clearT2();\n\t\tif (this.timeoutT2 <= 0) return;\n\t\tconst timeout = this.timeoutT2 * 1000;\n\t\tthis.t2Timer = setTimeout(() => {\n\t\t\tthis.handleT2Timeout();\n\t\t}, timeout);\n\t}\n\n\tprivate startT4() {\n\t\tthis.clearT4();\n\t\tif (this.timeoutT4 <= 0) return;\n\t\tconst timeout = this.timeoutT4 * 1000;\n\t\tthis.t4Timer = setTimeout(() => {\n\t\t\tthis.handleT4Timeout();\n\t\t}, timeout);\n\t}\n\n\tprivate handleT1Timeout() {\n\t\tconsole.warn(\"T1 Timeout\");\n\t\tthis.t1Timer = null;\n\t\tthis.emit(\"error\", new Error(\"T1 Timeout\"));\n\t\tthis.resetState();\n\t}\n\n\tprivate handleT2Timeout() {\n\t\tconsole.warn(\"T2 Timeout\");\n\t\tthis.t2Timer = null;\n\t\tif (this.state === CommState.WAIT_EOT) {\n\t\t\tthis.retryCount++;\n\t\t\tif (this.retryCount > this.retry) {\n\t\t\t\tthis.emit(\"error\", new Error(\"Retry limit exceeded waiting for EOT\"));\n\t\t\t\tthis.resetState();\n\t\t\t} else {\n\t\t\t\tconsole.log(`Retrying ENQ (${this.retryCount}/${this.retry})`);\n\t\t\t\tthis.sendByte(ENQ);\n\t\t\t\tthis.startT2();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.state === CommState.WAIT_ACK) {\n\t\t\tthis.retryCount++;\n\t\t\tif (this.retryCount > this.retry) {\n\t\t\t\tthis.emit(\"error\", new Error(\"Retry limit exceeded waiting for ACK\"));\n\t\t\t\tthis.resetState();\n\t\t\t} else {\n\t\t\t\tconsole.log(`Retrying Block (${this.retryCount}/${this.retry})`);\n\t\t\t\tthis.sendCurrentBlock();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tthis.resetState();\n\t}\n\n\tprivate handleT4Timeout() {\n\t\tconsole.warn(\"T4 Timeout (Inter-block)\");\n\t\tthis.t4Timer = null;\n\t\tthis.resetState();\n\t}\n\n\tprivate resetState() {\n\t\tthis.state = CommState.IDLE;\n\t\tthis.receivedBlocks = [];\n\t\tthis.expectedBlockNum = 1;\n\t\tthis.currentBlockLength = 0;\n\t\tthis.stopAllTimers();\n\t}\n\n\tprivate sendByte(byte: number) {\n\t\tconst stream = this.stream;\n\t\tif (stream && !stream.destroyed) {\n\t\t\tstream.write(Buffer.from([byte]));\n\t\t}\n\t}\n\n\tprivate processBuffer() {\n\t\twhile (this.buffer.length > 0) {\n\t\t\tswitch (this.state) {\n\t\t\t\tcase CommState.IDLE: {\n\t\t\t\t\tconst byte = this.buffer[0];\n\t\t\t\t\tthis.buffer = this.buffer.subarray(1);\n\t\t\t\t\tif (byte === ENQ) {\n\t\t\t\t\t\tthis.sendByte(EOT);\n\t\t\t\t\t\tthis.state = CommState.WAIT_BLOCK_LENGTH;\n\t\t\t\t\t\tthis.receivedBlocks = [];\n\t\t\t\t\t\tthis.expectedBlockNum = 1;\n\t\t\t\t\t\tthis.startT1();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase CommState.WAIT_EOT: {\n\t\t\t\t\tconst byte = this.buffer[0];\n\t\t\t\t\tthis.buffer = this.buffer.subarray(1);\n\t\t\t\t\tif (byte === EOT) {\n\t\t\t\t\t\tthis.clearT2();\n\t\t\t\t\t\tthis.currentBlockIndex = 0;\n\t\t\t\t\t\tthis.sendCurrentBlock();\n\t\t\t\t\t} else if (byte === ENQ) {\n\t\t\t\t\t\tif (!this.isMaster) {\n\t\t\t\t\t\t\tthis.clearT2();\n\t\t\t\t\t\t\tthis.sendByte(EOT);\n\t\t\t\t\t\t\tthis.state = CommState.WAIT_BLOCK_LENGTH;\n\t\t\t\t\t\t\tthis.receivedBlocks = [];\n\t\t\t\t\t\t\tthis.expectedBlockNum = 1;\n\t\t\t\t\t\t\tthis.startT1();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase CommState.WAIT_ACK: {\n\t\t\t\t\tconst byte = this.buffer[0];\n\t\t\t\t\tthis.buffer = this.buffer.subarray(1);\n\t\t\t\t\tif (byte === ACK) {\n\t\t\t\t\t\tthis.clearT2();\n\t\t\t\t\t\tconst currentBlock = this.currentBlocks[this.currentBlockIndex];\n\t\t\t\t\t\tif (currentBlock.eBit) {\n\t\t\t\t\t\t\tthis.currentBlocks = [];\n\t\t\t\t\t\t\tthis.retryCount = 0;\n\t\t\t\t\t\t\tthis.state = CommState.IDLE;\n\t\t\t\t\t\t\tthis.processSendQueue();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.currentBlockIndex++;\n\t\t\t\t\t\t\tthis.sendCurrentBlock();\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (byte === NAK) {\n\t\t\t\t\t\tthis.clearT2();\n\t\t\t\t\t\tthis.handleT2Timeout();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase CommState.WAIT_BLOCK_LENGTH: {\n\t\t\t\t\tif (this.t4Timer) {\n\t\t\t\t\t\tthis.clearT4();\n\t\t\t\t\t\tthis.startT1();\n\t\t\t\t\t}\n\t\t\t\t\tconst len = this.buffer[0];\n\t\t\t\t\tif (len < 10) {\n\t\t\t\t\t\tthis.buffer = this.buffer.subarray(1);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.currentBlockLength = len;\n\t\t\t\t\t\tthis.buffer = this.buffer.subarray(1);\n\t\t\t\t\t\tthis.state = CommState.WAIT_BLOCK_DATA;\n\t\t\t\t\t\tthis.startT1();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase CommState.WAIT_BLOCK_DATA: {\n\t\t\t\t\tif (this.buffer.length >= this.currentBlockLength + 2) {\n\t\t\t\t\t\tconst blockData = this.buffer.subarray(\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\tthis.currentBlockLength + 2,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthis.buffer = this.buffer.subarray(this.currentBlockLength + 2);\n\t\t\t\t\t\tthis.stopAllTimers();\n\n\t\t\t\t\t\tconst fullBlockBuffer = Buffer.alloc(1 + blockData.length);\n\t\t\t\t\t\tfullBlockBuffer[0] = this.currentBlockLength;\n\t\t\t\t\t\tblockData.copy(fullBlockBuffer, 1);\n\n\t\t\t\t\t\tconst block = new Secs1MessageBlock(fullBlockBuffer);\n\t\t\t\t\t\tif (block.isValid()) {\n\t\t\t\t\t\t\tif (block.blockNumber !== this.expectedBlockNum) {\n\t\t\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t\t\t`Wrong Block Number. Expected ${this.expectedBlockNum}, got ${block.blockNumber}`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tthis.sendByte(NAK);\n\t\t\t\t\t\t\t\tthis.state = CommState.IDLE;\n\t\t\t\t\t\t\t\tthis.resetState();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.sendByte(ACK);\n\t\t\t\t\t\t\t\tthis.receivedBlocks.push(block);\n\t\t\t\t\t\t\t\tif (block.eBit) {\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tconst msg = Secs1Message.fromBlocks(this.receivedBlocks);\n\t\t\t\t\t\t\t\t\t\tthis.handleMessage(msg);\n\t\t\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\t\t\tthis.emit(\n\t\t\t\t\t\t\t\t\t\t\t\"error\",\n\t\t\t\t\t\t\t\t\t\t\te instanceof Error ? e : new Error(String(e)),\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tthis.resetState();\n\t\t\t\t\t\t\t\t\tthis.processSendQueue();\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tthis.expectedBlockNum++;\n\t\t\t\t\t\t\t\t\tthis.state = CommState.WAIT_BLOCK_LENGTH;\n\t\t\t\t\t\t\t\t\tthis.startT4();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconsole.warn(\"Invalid Checksum\");\n\t\t\t\t\t\t\tthis.sendByte(NAK);\n\t\t\t\t\t\t\tthis.state = CommState.IDLE;\n\t\t\t\t\t\t\tthis.resetState();\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate sendCurrentBlock() {\n\t\tif (this.currentBlockIndex >= this.currentBlocks.length) return;\n\t\tconst stream = this.stream;\n\t\tconst block = this.currentBlocks[this.currentBlockIndex];\n\t\tif (stream && !stream.destroyed) {\n\t\t\tstream.write(block.buffer);\n\t\t\tthis.state = CommState.WAIT_ACK;\n\t\t\tthis.startT2();\n\t\t}\n\t}\n\n\tprivate processSendQueue() {\n\t\tif (this.state !== CommState.IDLE) return;\n\t\tconst stream = this.stream;\n\t\tif (!stream || stream.destroyed) return;\n\t\tif (this.sendQueue.length === 0) return;\n\n\t\tconst buffer = this.sendQueue.shift();\n\t\tif (!buffer) return;\n\n\t\ttry {\n\t\t\tconst rBit = (buffer[0] & 0x80) === 0x80;\n\t\t\tconst deviceId = ((buffer[0] & 0x7f) << 8) | buffer[1];\n\t\t\tconst streamId = buffer[2] & 0x7f;\n\t\t\tconst wBit = (buffer[2] & 0x80) === 0x80;\n\t\t\tconst func = buffer[3];\n\t\t\tconst systemBytes = buffer.readUInt32BE(6);\n\t\t\tconst bodyBuffer = buffer.subarray(10);\n\n\t\t\tthis.currentBlocks = [];\n\t\t\tlet pos = 0;\n\t\t\tlet blockNum = 1;\n\n\t\t\tif (bodyBuffer.length === 0) {\n\t\t\t\tthis.currentBlocks.push(\n\t\t\t\t\tSecs1MessageBlock.fromParts(\n\t\t\t\t\t\tdeviceId,\n\t\t\t\t\t\tstreamId,\n\t\t\t\t\t\tfunc,\n\t\t\t\t\t\twBit,\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t\tblockNum,\n\t\t\t\t\t\tsystemBytes,\n\t\t\t\t\t\tBuffer.alloc(0),\n\t\t\t\t\t\trBit,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\twhile (pos < bodyBuffer.length) {\n\t\t\t\t\tconst remaining = bodyBuffer.length - pos;\n\t\t\t\t\tconst chunkSize = remaining > 244 ? 244 : remaining;\n\t\t\t\t\tconst chunk = bodyBuffer.subarray(pos, pos + chunkSize);\n\t\t\t\t\tconst isLast = pos + chunkSize >= bodyBuffer.length;\n\n\t\t\t\t\tthis.currentBlocks.push(\n\t\t\t\t\t\tSecs1MessageBlock.fromParts(\n\t\t\t\t\t\t\tdeviceId,\n\t\t\t\t\t\t\tstreamId,\n\t\t\t\t\t\t\tfunc,\n\t\t\t\t\t\t\twBit,\n\t\t\t\t\t\t\tisLast,\n\t\t\t\t\t\t\tblockNum,\n\t\t\t\t\t\t\tsystemBytes,\n\t\t\t\t\t\t\tchunk,\n\t\t\t\t\t\t\trBit,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tpos += chunkSize;\n\t\t\t\t\tblockNum++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.currentBlockIndex = 0;\n\t\t\tthis.retryCount = 0;\n\n\t\t\tthis.sendByte(ENQ);\n\t\t\tthis.state = CommState.WAIT_EOT;\n\t\t\tthis.startT2();\n\t\t} catch (e) {\n\t\t\tthis.emit(\"error\", e instanceof Error ? e : new Error(String(e)));\n\t\t\tthis.processSendQueue();\n\t\t}\n\t}\n\n\tprivate rejectAllTransactions(err: Error) {\n\t\tfor (const [systemBytes, tx] of this._transactions) {\n\t\t\tclearTimeout(tx.timer);\n\t\t\ttx.reject(err);\n\t\t\tthis._transactions.delete(systemBytes);\n\t\t}\n\t}\n}\n"],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { AbstractSecs2Item } from "../core/secs2item/AbstractSecs2Item.js";
2
+ import { SecsMessage } from "../core/AbstractSecsMessage.js";
3
+ import { Secs1MessageBlock } from "./Secs1MessageBlock.js";
4
+
5
+ //#region src/secs1/Secs1Message.d.ts
6
+ declare class Secs1Message extends SecsMessage {
7
+ readonly rBit: boolean;
8
+ constructor(stream: number, func: number, wBit: boolean, body: AbstractSecs2Item | null, systemBytes: number, deviceId: number, rBit?: boolean);
9
+ /**
10
+ * @description Splits the message into SECS-I blocks.
11
+ */
12
+ toBlocks(): Secs1MessageBlock[];
13
+ /**
14
+ * Reassembles a SECS-I message from blocks.
15
+ */
16
+ static fromBlocks(blocks: Secs1MessageBlock[]): Secs1Message;
17
+ toBuffer(): Buffer;
18
+ }
19
+ //#endregion
20
+ export { Secs1Message };
21
+ //# sourceMappingURL=Secs1Message.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Secs1Message.d.ts","names":[],"sources":["../../src/secs1/Secs1Message.ts"],"sourcesContent":[],"mappings":";;;;;cAKa,YAAA,SAAqB,WAAA;;EAArB,WAAA,CAAA,MAAa,EAAA,MAAA,EAAA,IAAA,EAAA,MAAA,EAAA,IAAA,EAAA,OAAA,EAAA,IAAA,EAKlB,iBALkB,GAAA,IAAA,EAAA,WAAA,EAAA,MAAA,EAAA,QAAA,EAAA,MAAA,EAAA,IAAA,CAAA,EAAA,OAAA;EAKlB;;;EAsEyC,QAAA,CAAA,CAAA,EA3DpC,iBA2DoC,EAAA;EAsDpC;;;4BAtDc,sBAAsB;cAsDpC"}
@@ -0,0 +1,77 @@
1
+ import { SecsMessage } from "../core/AbstractSecsMessage.js";
2
+ import { Secs2ItemParser } from "../core/secs2item/Secs2ItemParser.js";
3
+ import { Secs1MessageBlock } from "./Secs1MessageBlock.js";
4
+
5
+ //#region src/secs1/Secs1Message.ts
6
+ var Secs1Message = class Secs1Message extends SecsMessage {
7
+ constructor(stream, func, wBit, body, systemBytes, deviceId, rBit = false) {
8
+ super(stream, func, wBit, body, systemBytes, deviceId);
9
+ this.rBit = rBit;
10
+ }
11
+ /**
12
+ * @description Splits the message into SECS-I blocks.
13
+ */
14
+ toBlocks() {
15
+ const bodyBuffer = this.body ? this.body.toBuffer() : Buffer.alloc(0);
16
+ const blocks = [];
17
+ let pos = 0;
18
+ let blockNum = 1;
19
+ if (bodyBuffer.length === 0) {
20
+ blocks.push(Secs1MessageBlock.fromParts(this.deviceId, this.stream, this.func, this.wBit, true, blockNum, this.systemBytes, Buffer.alloc(0), this.rBit));
21
+ return blocks;
22
+ }
23
+ while (pos < bodyBuffer.length) {
24
+ const remaining = bodyBuffer.length - pos;
25
+ const chunkSize = remaining > 244 ? 244 : remaining;
26
+ const chunk = bodyBuffer.subarray(pos, pos + chunkSize);
27
+ const isLast = pos + chunkSize >= bodyBuffer.length;
28
+ blocks.push(Secs1MessageBlock.fromParts(this.deviceId, this.stream, this.func, this.wBit, isLast, blockNum, this.systemBytes, chunk, this.rBit));
29
+ pos += chunkSize;
30
+ blockNum++;
31
+ if (blockNum > 32767) throw new Error("Block number overflow");
32
+ }
33
+ return blocks;
34
+ }
35
+ /**
36
+ * Reassembles a SECS-I message from blocks.
37
+ */
38
+ static fromBlocks(blocks) {
39
+ if (blocks.length === 0) throw new Error("No blocks to reassemble");
40
+ blocks.sort((a, b) => a.blockNumber - b.blockNumber);
41
+ for (let i = 0; i < blocks.length; i++) {
42
+ if (blocks[i].blockNumber !== i + 1) throw new Error(`Missing block ${i + 1}`);
43
+ if (i > 0) {
44
+ const prev = blocks[i - 1];
45
+ const curr = blocks[i];
46
+ if (prev.systemBytes !== curr.systemBytes || prev.stream !== curr.stream || prev.func !== curr.func || prev.deviceId !== curr.deviceId) throw new Error("Blocks do not belong to the same message");
47
+ }
48
+ }
49
+ if (!blocks[blocks.length - 1].eBit) throw new Error("Last block missing E-Bit");
50
+ const first = blocks[0];
51
+ const bodyBuffers = blocks.map((b) => b.body);
52
+ const fullBodyBuffer = Buffer.concat(bodyBuffers);
53
+ let body = null;
54
+ if (fullBodyBuffer.length > 0) body = Secs2ItemParser.fromBuffer(fullBodyBuffer).item;
55
+ return new Secs1Message(first.stream, first.func, first.wBit, body, first.systemBytes, first.deviceId, first.rBit);
56
+ }
57
+ toBuffer() {
58
+ const bodyBuffer = this.body ? this.body.toBuffer() : Buffer.alloc(0);
59
+ const header = Buffer.alloc(10);
60
+ let b0 = this.deviceId >> 8 & 127;
61
+ if (this.rBit) b0 |= 128;
62
+ header[0] = b0;
63
+ header[1] = this.deviceId & 255;
64
+ let b2 = this.stream & 127;
65
+ if (this.wBit) b2 |= 128;
66
+ header[2] = b2;
67
+ header[3] = this.func & 255;
68
+ header[4] = 0;
69
+ header[5] = 0;
70
+ header.writeUInt32BE(this.systemBytes, 6);
71
+ return Buffer.concat([header, bodyBuffer]);
72
+ }
73
+ };
74
+
75
+ //#endregion
76
+ export { Secs1Message };
77
+ //# sourceMappingURL=Secs1Message.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Secs1Message.js","names":["blocks: Secs1MessageBlock[]","body: AbstractSecs2Item | null"],"sources":["../../src/secs1/Secs1Message.ts"],"sourcesContent":["import { SecsMessage } from \"../core/AbstractSecsMessage.js\";\nimport { AbstractSecs2Item } from \"../core/secs2item/AbstractSecs2Item.js\";\nimport { Secs2ItemParser } from \"../core/secs2item/Secs2ItemParser.js\";\nimport { Secs1MessageBlock } from \"./Secs1MessageBlock.js\";\n\nexport class Secs1Message extends SecsMessage {\n\tconstructor(\n\t\tstream: number,\n\t\tfunc: number,\n\t\twBit: boolean,\n\t\tbody: AbstractSecs2Item | null,\n\t\tsystemBytes: number,\n\t\tdeviceId: number,\n\t\tpublic readonly rBit = false,\n\t) {\n\t\tsuper(stream, func, wBit, body, systemBytes, deviceId);\n\t}\n\n\t/**\n\t * @description Splits the message into SECS-I blocks.\n\t */\n\ttoBlocks(): Secs1MessageBlock[] {\n\t\tconst bodyBuffer = this.body ? this.body.toBuffer() : Buffer.alloc(0);\n\t\tconst blocks: Secs1MessageBlock[] = [];\n\n\t\tlet pos = 0;\n\t\tlet blockNum = 1;\n\n\t\tif (bodyBuffer.length === 0) {\n\t\t\t// Header only block? Or empty body block?\n\t\t\t// SECS-I allows empty body.\n\t\t\tblocks.push(\n\t\t\t\tSecs1MessageBlock.fromParts(\n\t\t\t\t\tthis.deviceId,\n\t\t\t\t\tthis.stream,\n\t\t\t\t\tthis.func,\n\t\t\t\t\tthis.wBit,\n\t\t\t\t\ttrue, // E-Bit\n\t\t\t\t\tblockNum,\n\t\t\t\t\tthis.systemBytes,\n\t\t\t\t\tBuffer.alloc(0),\n\t\t\t\t\tthis.rBit,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn blocks;\n\t\t}\n\n\t\twhile (pos < bodyBuffer.length) {\n\t\t\tconst remaining = bodyBuffer.length - pos;\n\t\t\tconst chunkSize = remaining > 244 ? 244 : remaining;\n\t\t\tconst chunk = bodyBuffer.subarray(pos, pos + chunkSize);\n\t\t\tconst isLast = pos + chunkSize >= bodyBuffer.length;\n\n\t\t\tblocks.push(\n\t\t\t\tSecs1MessageBlock.fromParts(\n\t\t\t\t\tthis.deviceId,\n\t\t\t\t\tthis.stream,\n\t\t\t\t\tthis.func,\n\t\t\t\t\tthis.wBit,\n\t\t\t\t\tisLast, // E-Bit\n\t\t\t\t\tblockNum,\n\t\t\t\t\tthis.systemBytes,\n\t\t\t\t\tchunk,\n\t\t\t\t\tthis.rBit,\n\t\t\t\t),\n\t\t\t);\n\n\t\t\tpos += chunkSize;\n\t\t\tblockNum++;\n\t\t\tif (blockNum > 0x7fff) {\n\t\t\t\tthrow new Error(\"Block number overflow\");\n\t\t\t}\n\t\t}\n\n\t\treturn blocks;\n\t}\n\n\t/**\n\t * Reassembles a SECS-I message from blocks.\n\t */\n\tstatic fromBlocks(blocks: Secs1MessageBlock[]): Secs1Message {\n\t\tif (blocks.length === 0) {\n\t\t\tthrow new Error(\"No blocks to reassemble\");\n\t\t}\n\n\t\t// Sort by block number just in case (though usually they come in order)\n\t\tblocks.sort((a, b) => a.blockNumber - b.blockNumber);\n\n\t\t// Validate sequence\n\t\tfor (let i = 0; i < blocks.length; i++) {\n\t\t\tif (blocks[i].blockNumber !== i + 1) {\n\t\t\t\tthrow new Error(`Missing block ${i + 1}`);\n\t\t\t}\n\t\t\t// Check if all blocks belong to the same message (SystemBytes, Stream, Func, DeviceID)\n\t\t\tif (i > 0) {\n\t\t\t\tconst prev = blocks[i - 1];\n\t\t\t\tconst curr = blocks[i];\n\t\t\t\tif (\n\t\t\t\t\tprev.systemBytes !== curr.systemBytes ||\n\t\t\t\t\tprev.stream !== curr.stream ||\n\t\t\t\t\tprev.func !== curr.func ||\n\t\t\t\t\tprev.deviceId !== curr.deviceId\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(\"Blocks do not belong to the same message\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!blocks[blocks.length - 1].eBit) {\n\t\t\tthrow new Error(\"Last block missing E-Bit\");\n\t\t}\n\n\t\tconst first = blocks[0];\n\t\tconst bodyBuffers = blocks.map((b) => b.body);\n\t\tconst fullBodyBuffer = Buffer.concat(bodyBuffers);\n\n\t\tlet body: AbstractSecs2Item | null = null;\n\t\tif (fullBodyBuffer.length > 0) {\n\t\t\tconst result = Secs2ItemParser.fromBuffer(fullBodyBuffer);\n\t\t\tbody = result.item;\n\t\t}\n\n\t\treturn new Secs1Message(\n\t\t\tfirst.stream,\n\t\t\tfirst.func,\n\t\t\tfirst.wBit,\n\t\t\tbody,\n\t\t\tfirst.systemBytes,\n\t\t\tfirst.deviceId,\n\t\t\tfirst.rBit,\n\t\t);\n\t}\n\n\t// Override toBuffer to return logical buffer (10-byte header + body)\n\ttoBuffer(): Buffer {\n\t\tconst bodyBuffer = this.body ? this.body.toBuffer() : Buffer.alloc(0);\n\t\tconst header = Buffer.alloc(10);\n\n\t\t// Byte 0: R-Bit + DeviceID MSB\n\t\tlet b0 = (this.deviceId >> 8) & 0x7f;\n\t\tif (this.rBit) b0 |= 0x80;\n\t\theader[0] = b0;\n\n\t\t// Byte 1: DeviceID LSB\n\t\theader[1] = this.deviceId & 0xff;\n\n\t\t// Byte 2: W-Bit + Stream\n\t\tlet b2 = this.stream & 0x7f;\n\t\tif (this.wBit) b2 |= 0x80;\n\t\theader[2] = b2;\n\n\t\t// Byte 3: Function\n\t\theader[3] = this.func & 0xff;\n\n\t\t// Byte 4: E-Bit + BlockNum (Logical 0 or 1? For logical message, maybe 0)\n\t\t// Usually block number is per block. For a \"Message Buffer\", we don't have block number.\n\t\t// We'll leave it 0 or standard.\n\t\theader[4] = 0;\n\t\theader[5] = 0;\n\n\t\t// Byte 6-9: System Bytes\n\t\theader.writeUInt32BE(this.systemBytes, 6);\n\n\t\treturn Buffer.concat([header, bodyBuffer]);\n\t}\n}\n"],"mappings":";;;;;AAKA,IAAa,eAAb,MAAa,qBAAqB,YAAY;CAC7C,YACC,QACA,MACA,MACA,MACA,aACA,UACA,AAAgB,OAAO,OACtB;AACD,QAAM,QAAQ,MAAM,MAAM,MAAM,aAAa,SAAS;EAFtC;;;;;CAQjB,WAAgC;EAC/B,MAAM,aAAa,KAAK,OAAO,KAAK,KAAK,UAAU,GAAG,OAAO,MAAM,EAAE;EACrE,MAAMA,SAA8B,EAAE;EAEtC,IAAI,MAAM;EACV,IAAI,WAAW;AAEf,MAAI,WAAW,WAAW,GAAG;AAG5B,UAAO,KACN,kBAAkB,UACjB,KAAK,UACL,KAAK,QACL,KAAK,MACL,KAAK,MACL,MACA,UACA,KAAK,aACL,OAAO,MAAM,EAAE,EACf,KAAK,KACL,CACD;AACD,UAAO;;AAGR,SAAO,MAAM,WAAW,QAAQ;GAC/B,MAAM,YAAY,WAAW,SAAS;GACtC,MAAM,YAAY,YAAY,MAAM,MAAM;GAC1C,MAAM,QAAQ,WAAW,SAAS,KAAK,MAAM,UAAU;GACvD,MAAM,SAAS,MAAM,aAAa,WAAW;AAE7C,UAAO,KACN,kBAAkB,UACjB,KAAK,UACL,KAAK,QACL,KAAK,MACL,KAAK,MACL,QACA,UACA,KAAK,aACL,OACA,KAAK,KACL,CACD;AAED,UAAO;AACP;AACA,OAAI,WAAW,MACd,OAAM,IAAI,MAAM,wBAAwB;;AAI1C,SAAO;;;;;CAMR,OAAO,WAAW,QAA2C;AAC5D,MAAI,OAAO,WAAW,EACrB,OAAM,IAAI,MAAM,0BAA0B;AAI3C,SAAO,MAAM,GAAG,MAAM,EAAE,cAAc,EAAE,YAAY;AAGpD,OAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACvC,OAAI,OAAO,GAAG,gBAAgB,IAAI,EACjC,OAAM,IAAI,MAAM,iBAAiB,IAAI,IAAI;AAG1C,OAAI,IAAI,GAAG;IACV,MAAM,OAAO,OAAO,IAAI;IACxB,MAAM,OAAO,OAAO;AACpB,QACC,KAAK,gBAAgB,KAAK,eAC1B,KAAK,WAAW,KAAK,UACrB,KAAK,SAAS,KAAK,QACnB,KAAK,aAAa,KAAK,SAEvB,OAAM,IAAI,MAAM,2CAA2C;;;AAK9D,MAAI,CAAC,OAAO,OAAO,SAAS,GAAG,KAC9B,OAAM,IAAI,MAAM,2BAA2B;EAG5C,MAAM,QAAQ,OAAO;EACrB,MAAM,cAAc,OAAO,KAAK,MAAM,EAAE,KAAK;EAC7C,MAAM,iBAAiB,OAAO,OAAO,YAAY;EAEjD,IAAIC,OAAiC;AACrC,MAAI,eAAe,SAAS,EAE3B,QADe,gBAAgB,WAAW,eAAe,CAC3C;AAGf,SAAO,IAAI,aACV,MAAM,QACN,MAAM,MACN,MAAM,MACN,MACA,MAAM,aACN,MAAM,UACN,MAAM,KACN;;CAIF,WAAmB;EAClB,MAAM,aAAa,KAAK,OAAO,KAAK,KAAK,UAAU,GAAG,OAAO,MAAM,EAAE;EACrE,MAAM,SAAS,OAAO,MAAM,GAAG;EAG/B,IAAI,KAAM,KAAK,YAAY,IAAK;AAChC,MAAI,KAAK,KAAM,OAAM;AACrB,SAAO,KAAK;AAGZ,SAAO,KAAK,KAAK,WAAW;EAG5B,IAAI,KAAK,KAAK,SAAS;AACvB,MAAI,KAAK,KAAM,OAAM;AACrB,SAAO,KAAK;AAGZ,SAAO,KAAK,KAAK,OAAO;AAKxB,SAAO,KAAK;AACZ,SAAO,KAAK;AAGZ,SAAO,cAAc,KAAK,aAAa,EAAE;AAEzC,SAAO,OAAO,OAAO,CAAC,QAAQ,WAAW,CAAC"}
@@ -0,0 +1,23 @@
1
+ //#region src/secs1/Secs1MessageBlock.d.ts
2
+ declare class Secs1MessageBlock {
3
+ readonly buffer: Buffer;
4
+ constructor(buffer: Buffer);
5
+ get length(): number;
6
+ get header(): Buffer;
7
+ get body(): Buffer;
8
+ get checksum(): number;
9
+ get deviceId(): number;
10
+ get rBit(): boolean;
11
+ get stream(): number;
12
+ get wBit(): boolean;
13
+ get func(): number;
14
+ get blockNumber(): number;
15
+ get eBit(): boolean;
16
+ get systemBytes(): number;
17
+ isValid(): boolean;
18
+ private calculateChecksum;
19
+ static fromParts(deviceId: number, stream: number, func: number, wBit: boolean, eBit: boolean, blockNum: number, systemBytes: number, body: Buffer, rBit?: boolean): Secs1MessageBlock;
20
+ }
21
+ //#endregion
22
+ export { Secs1MessageBlock };
23
+ //# sourceMappingURL=Secs1MessageBlock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Secs1MessageBlock.d.ts","names":[],"sources":["../../src/secs1/Secs1MessageBlock.ts"],"sourcesContent":[],"mappings":";cAAa,iBAAA;EAAA,SAAA,MAAA,EAEwB,MAFP;EAEO,WAAA,CAAA,MAAA,EAAA,MAAA;EAAA,IAAA,MAAA,CAAA,CAAA,EAAA,MAAA;EAMtB,IAAA,MAAA,CAAA,CAAA,EAAA,MAAA;EAIF,IAAA,IAAA,CAAA,CAAA,EAAA,MAAA;EA2EL,IAAA,QAAA,CAAA,CAAA,EAAA,MAAA;EAEJ,IAAA,QAAA,CAAA,CAAA,EAAA,MAAA;EAAiB,IAAA,IAAA,CAAA,CAAA,EAAA,OAAA;;;;;;;;;8IAFb,yBAEJ"}
@@ -0,0 +1,86 @@
1
+ //#region src/secs1/Secs1MessageBlock.ts
2
+ var Secs1MessageBlock = class Secs1MessageBlock {
3
+ constructor(buffer) {
4
+ this.buffer = buffer;
5
+ }
6
+ get length() {
7
+ return this.buffer[0];
8
+ }
9
+ get header() {
10
+ return this.buffer.subarray(1, 11);
11
+ }
12
+ get body() {
13
+ return this.buffer.subarray(11, this.buffer.length - 2);
14
+ }
15
+ get checksum() {
16
+ return this.buffer.readUInt16BE(this.buffer.length - 2);
17
+ }
18
+ get deviceId() {
19
+ const bs = this.buffer.subarray(1, 3);
20
+ return bs[0] << 8 & 32512 | bs[1];
21
+ }
22
+ get rBit() {
23
+ return (this.buffer[1] & 128) === 128;
24
+ }
25
+ get stream() {
26
+ return this.buffer[3] & 127;
27
+ }
28
+ get wBit() {
29
+ return (this.buffer[3] & 128) === 128;
30
+ }
31
+ get func() {
32
+ return this.buffer[4];
33
+ }
34
+ get blockNumber() {
35
+ const bs = this.buffer.subarray(5, 7);
36
+ return bs[0] << 8 & 32512 | bs[1];
37
+ }
38
+ get eBit() {
39
+ return (this.buffer[5] & 128) === 128;
40
+ }
41
+ get systemBytes() {
42
+ return this.buffer.readUInt32BE(7);
43
+ }
44
+ isValid() {
45
+ if (this.buffer.length < 13) return false;
46
+ if (this.buffer[0] !== this.buffer.length - 3) return false;
47
+ return this.calculateChecksum() === this.checksum;
48
+ }
49
+ calculateChecksum() {
50
+ let sum = 0;
51
+ for (let i = 1; i < this.buffer.length - 2; i++) sum += this.buffer[i];
52
+ return sum & 65535;
53
+ }
54
+ static fromParts(deviceId, stream, func, wBit, eBit, blockNum, systemBytes, body, rBit = false) {
55
+ const header = Buffer.alloc(10);
56
+ let b0 = deviceId >> 8 & 127;
57
+ if (rBit) b0 |= 128;
58
+ header[0] = b0;
59
+ header[1] = deviceId & 255;
60
+ let b2 = stream & 127;
61
+ if (wBit) b2 |= 128;
62
+ header[2] = b2;
63
+ header[3] = func & 255;
64
+ let b4 = blockNum >> 8 & 127;
65
+ if (eBit) b4 |= 128;
66
+ header[4] = b4;
67
+ header[5] = blockNum & 255;
68
+ header.writeUInt32BE(systemBytes, 6);
69
+ const length = 10 + body.length;
70
+ if (length > 254) throw new Error("Block too large");
71
+ let sum = 0;
72
+ for (const b of header) sum += b;
73
+ for (const b of body) sum += b;
74
+ const checksum = sum & 65535;
75
+ const block = Buffer.alloc(11 + body.length + 2);
76
+ block[0] = length;
77
+ header.copy(block, 1);
78
+ body.copy(block, 11);
79
+ block.writeUInt16BE(checksum, block.length - 2);
80
+ return new Secs1MessageBlock(block);
81
+ }
82
+ };
83
+
84
+ //#endregion
85
+ export { Secs1MessageBlock };
86
+ //# sourceMappingURL=Secs1MessageBlock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Secs1MessageBlock.js","names":["buffer: Buffer"],"sources":["../../src/secs1/Secs1MessageBlock.ts"],"sourcesContent":["export class Secs1MessageBlock {\n\t// The full block bytes: [Length(1)] + [Header(10)] + [Body(0-244)] + [Checksum(2)]\n\tconstructor(public readonly buffer: Buffer) {}\n\n\tget length(): number {\n\t\treturn this.buffer[0];\n\t}\n\n\tget header(): Buffer {\n\t\treturn this.buffer.subarray(1, 11);\n\t}\n\n\tget body(): Buffer {\n\t\treturn this.buffer.subarray(11, this.buffer.length - 2);\n\t}\n\n\tget checksum(): number {\n\t\treturn this.buffer.readUInt16BE(this.buffer.length - 2);\n\t}\n\n\t// Parsed fields\n\tget deviceId(): number {\n\t\tconst bs = this.buffer.subarray(1, 3);\n\t\treturn ((bs[0] << 8) & 0x7f00) | bs[1];\n\t}\n\n\tget rBit(): boolean {\n\t\treturn (this.buffer[1] & 0x80) === 0x80;\n\t}\n\n\tget stream(): number {\n\t\treturn this.buffer[3] & 0x7f;\n\t}\n\n\tget wBit(): boolean {\n\t\treturn (this.buffer[3] & 0x80) === 0x80;\n\t}\n\n\tget func(): number {\n\t\treturn this.buffer[4];\n\t}\n\n\tget blockNumber(): number {\n\t\tconst bs = this.buffer.subarray(5, 7);\n\t\treturn ((bs[0] << 8) & 0x7f00) | bs[1];\n\t}\n\n\tget eBit(): boolean {\n\t\treturn (this.buffer[5] & 0x80) === 0x80;\n\t}\n\n\tget systemBytes(): number {\n\t\treturn this.buffer.readUInt32BE(7);\n\t}\n\n\tisValid(): boolean {\n\t\tif (this.buffer.length < 13) return false; // Len(1) + Head(10) + Sum(2)\n\t\tif (this.buffer[0] !== this.buffer.length - 3) return false; // Length byte excludes itself and checksum?\n\t\t// Wait, SECS-I Length Byte is the number of bytes in the block EXCLUSIVE of the length byte itself and the checksum?\n\t\t// No, standard says: \"Length byte is the number of bytes in the block header plus the text.\" (Header + Body).\n\t\t// So Length = 10 + BodyLength.\n\t\t// Total buffer size = 1 (LenByte) + Length + 2 (Checksum).\n\t\t// So Buffer Length = 1 + Length + 2 = Length + 3.\n\t\t// So Length Byte value should be BufferLength - 3.\n\n\t\tconst calculatedSum = this.calculateChecksum();\n\t\treturn calculatedSum === this.checksum;\n\t}\n\n\tprivate calculateChecksum(): number {\n\t\t// Sum of bytes from Header to end of Body (excluding Length byte and Checksum bytes)\n\t\t// i.e., indices 1 to length-3\n\t\tlet sum = 0;\n\t\tfor (let i = 1; i < this.buffer.length - 2; i++) {\n\t\t\tsum += this.buffer[i];\n\t\t}\n\t\treturn sum & 0xffff;\n\t}\n\n\tstatic fromParts(\n\t\tdeviceId: number,\n\t\tstream: number,\n\t\tfunc: number,\n\t\twBit: boolean,\n\t\teBit: boolean,\n\t\tblockNum: number,\n\t\tsystemBytes: number,\n\t\tbody: Buffer,\n\t\trBit = false,\n\t): Secs1MessageBlock {\n\t\tconst header = Buffer.alloc(10);\n\t\t// Byte 0: R-Bit + DeviceID MSB\n\t\tlet b0 = (deviceId >> 8) & 0x7f;\n\t\tif (rBit) b0 |= 0x80;\n\t\theader[0] = b0;\n\t\t// Byte 1: DeviceID LSB\n\t\theader[1] = deviceId & 0xff;\n\n\t\t// Byte 2: W-Bit + Stream\n\t\tlet b2 = stream & 0x7f;\n\t\tif (wBit) b2 |= 0x80;\n\t\theader[2] = b2;\n\n\t\t// Byte 3: Function\n\t\theader[3] = func & 0xff;\n\n\t\t// Byte 4: E-Bit + BlockNum MSB\n\t\tlet b4 = (blockNum >> 8) & 0x7f;\n\t\tif (eBit) b4 |= 0x80;\n\t\theader[4] = b4;\n\n\t\t// Byte 5: BlockNum LSB\n\t\theader[5] = blockNum & 0xff;\n\n\t\t// Byte 6-9: System Bytes\n\t\theader.writeUInt32BE(systemBytes, 6);\n\n\t\t// Calculate Length\n\t\tconst length = 10 + body.length;\n\t\tif (length > 254) throw new Error(\"Block too large\");\n\n\t\t// Calculate Checksum\n\t\tlet sum = 0;\n\t\tfor (const b of header) sum += b;\n\t\tfor (const b of body) sum += b;\n\t\tconst checksum = sum & 0xffff;\n\n\t\tconst block = Buffer.alloc(1 + 10 + body.length + 2);\n\t\tblock[0] = length;\n\t\theader.copy(block, 1);\n\t\tbody.copy(block, 11);\n\t\tblock.writeUInt16BE(checksum, block.length - 2);\n\n\t\treturn new Secs1MessageBlock(block);\n\t}\n}\n"],"mappings":";AAAA,IAAa,oBAAb,MAAa,kBAAkB;CAE9B,YAAY,AAAgBA,QAAgB;EAAhB;;CAE5B,IAAI,SAAiB;AACpB,SAAO,KAAK,OAAO;;CAGpB,IAAI,SAAiB;AACpB,SAAO,KAAK,OAAO,SAAS,GAAG,GAAG;;CAGnC,IAAI,OAAe;AAClB,SAAO,KAAK,OAAO,SAAS,IAAI,KAAK,OAAO,SAAS,EAAE;;CAGxD,IAAI,WAAmB;AACtB,SAAO,KAAK,OAAO,aAAa,KAAK,OAAO,SAAS,EAAE;;CAIxD,IAAI,WAAmB;EACtB,MAAM,KAAK,KAAK,OAAO,SAAS,GAAG,EAAE;AACrC,SAAS,GAAG,MAAM,IAAK,QAAU,GAAG;;CAGrC,IAAI,OAAgB;AACnB,UAAQ,KAAK,OAAO,KAAK,SAAU;;CAGpC,IAAI,SAAiB;AACpB,SAAO,KAAK,OAAO,KAAK;;CAGzB,IAAI,OAAgB;AACnB,UAAQ,KAAK,OAAO,KAAK,SAAU;;CAGpC,IAAI,OAAe;AAClB,SAAO,KAAK,OAAO;;CAGpB,IAAI,cAAsB;EACzB,MAAM,KAAK,KAAK,OAAO,SAAS,GAAG,EAAE;AACrC,SAAS,GAAG,MAAM,IAAK,QAAU,GAAG;;CAGrC,IAAI,OAAgB;AACnB,UAAQ,KAAK,OAAO,KAAK,SAAU;;CAGpC,IAAI,cAAsB;AACzB,SAAO,KAAK,OAAO,aAAa,EAAE;;CAGnC,UAAmB;AAClB,MAAI,KAAK,OAAO,SAAS,GAAI,QAAO;AACpC,MAAI,KAAK,OAAO,OAAO,KAAK,OAAO,SAAS,EAAG,QAAO;AAStD,SADsB,KAAK,mBAAmB,KACrB,KAAK;;CAG/B,AAAQ,oBAA4B;EAGnC,IAAI,MAAM;AACV,OAAK,IAAI,IAAI,GAAG,IAAI,KAAK,OAAO,SAAS,GAAG,IAC3C,QAAO,KAAK,OAAO;AAEpB,SAAO,MAAM;;CAGd,OAAO,UACN,UACA,QACA,MACA,MACA,MACA,UACA,aACA,MACA,OAAO,OACa;EACpB,MAAM,SAAS,OAAO,MAAM,GAAG;EAE/B,IAAI,KAAM,YAAY,IAAK;AAC3B,MAAI,KAAM,OAAM;AAChB,SAAO,KAAK;AAEZ,SAAO,KAAK,WAAW;EAGvB,IAAI,KAAK,SAAS;AAClB,MAAI,KAAM,OAAM;AAChB,SAAO,KAAK;AAGZ,SAAO,KAAK,OAAO;EAGnB,IAAI,KAAM,YAAY,IAAK;AAC3B,MAAI,KAAM,OAAM;AAChB,SAAO,KAAK;AAGZ,SAAO,KAAK,WAAW;AAGvB,SAAO,cAAc,aAAa,EAAE;EAGpC,MAAM,SAAS,KAAK,KAAK;AACzB,MAAI,SAAS,IAAK,OAAM,IAAI,MAAM,kBAAkB;EAGpD,IAAI,MAAM;AACV,OAAK,MAAM,KAAK,OAAQ,QAAO;AAC/B,OAAK,MAAM,KAAK,KAAM,QAAO;EAC7B,MAAM,WAAW,MAAM;EAEvB,MAAM,QAAQ,OAAO,MAAM,KAAS,KAAK,SAAS,EAAE;AACpD,QAAM,KAAK;AACX,SAAO,KAAK,OAAO,EAAE;AACrB,OAAK,KAAK,OAAO,GAAG;AACpB,QAAM,cAAc,UAAU,MAAM,SAAS,EAAE;AAE/C,SAAO,IAAI,kBAAkB,MAAM"}
@@ -0,0 +1,23 @@
1
+ import { Secs1Communicator, Secs1CommunicatorConfig } from "./Secs1Communicator.js";
2
+
3
+ //#region src/secs1/Secs1OnTcpIpActiveCommunicator.d.ts
4
+ interface Secs1OnTcpIpActiveCommunicatorConfig extends Secs1CommunicatorConfig {
5
+ ip: string;
6
+ port: number;
7
+ }
8
+ declare class Secs1OnTcpIpActiveCommunicator extends Secs1Communicator {
9
+ ip: string;
10
+ port: number;
11
+ private shouldStop;
12
+ private reconnectTimer;
13
+ private connectionPromiseResolver;
14
+ private pendingSocket;
15
+ constructor(config: Secs1OnTcpIpActiveCommunicatorConfig);
16
+ open(): Promise<void>;
17
+ private connect;
18
+ private scheduleReconnect;
19
+ close(): Promise<void>;
20
+ }
21
+ //#endregion
22
+ export { Secs1OnTcpIpActiveCommunicator, Secs1OnTcpIpActiveCommunicatorConfig };
23
+ //# sourceMappingURL=Secs1OnTcpIpActiveCommunicator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Secs1OnTcpIpActiveCommunicator.d.ts","names":[],"sources":["../../src/secs1/Secs1OnTcpIpActiveCommunicator.ts"],"sourcesContent":[],"mappings":";;;UAMiB,oCAAA,SAA6C;;EAA7C,IAAA,EAAA,MAAA;AAKjB;AASqB,cATR,8BAAA,SAAuC,iBAAA,CAS/B;EAcN,EAAA,EAAA,MAAA;EA+DC,IAAA,EAAA,MAAA;EAtFoC,QAAA,UAAA;EAAiB,QAAA,cAAA;;;sBAShD;UAcN;;;WA+DC"}