secs4js 0.4.3 → 0.4.4
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/README.md +87 -1
- package/lib/secs1/Secs1Communicator.js +17 -17
- package/lib/secs1/Secs1Communicator.js.map +1 -1
- package/lib/secs1/Secs1OnTcpIpActiveCommunicator.js +2 -2
- package/lib/secs1/Secs1OnTcpIpActiveCommunicator.js.map +1 -1
- package/lib/secs1/Secs1OnTcpIpPassiveCommunicator.d.ts +7 -1
- package/lib/secs1/Secs1OnTcpIpPassiveCommunicator.d.ts.map +1 -1
- package/lib/secs1/Secs1OnTcpIpPassiveCommunicator.js +111 -25
- package/lib/secs1/Secs1OnTcpIpPassiveCommunicator.js.map +1 -1
- package/lib/secs1/Secs1SerialCommunicator.d.ts.map +1 -1
- package/lib/secs1/Secs1SerialCommunicator.js +1 -0
- package/lib/secs1/Secs1SerialCommunicator.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -51,7 +51,22 @@ pnpm dlx tsx examples/<example_file_name>.ts
|
|
|
51
51
|
I provide a concise, clear, and efficient way to create SECS-II message types. You can use the following code to import the required items:
|
|
52
52
|
|
|
53
53
|
```ts
|
|
54
|
-
import {
|
|
54
|
+
import {
|
|
55
|
+
B,
|
|
56
|
+
BOOLEAN,
|
|
57
|
+
U1,
|
|
58
|
+
U2,
|
|
59
|
+
U4,
|
|
60
|
+
U8,
|
|
61
|
+
I1,
|
|
62
|
+
I2,
|
|
63
|
+
I4,
|
|
64
|
+
I8,
|
|
65
|
+
F4,
|
|
66
|
+
F8,
|
|
67
|
+
A,
|
|
68
|
+
L,
|
|
69
|
+
} from "secs4js";
|
|
55
70
|
```
|
|
56
71
|
|
|
57
72
|
Using these items, you can easily create SECS-II message types. For example, to create a message containing L, A, and U1 items, you can use the following code:
|
|
@@ -159,6 +174,77 @@ const parsedBody = SmlParser.parseBody(smlBody);
|
|
|
159
174
|
console.log(parsedBody?.toSml());
|
|
160
175
|
```
|
|
161
176
|
|
|
177
|
+
### 3. Extracting Data from SECS-II Messages
|
|
178
|
+
|
|
179
|
+
Data extraction is performed using array indexers, and specific values are retrieved through the `.value` property.
|
|
180
|
+
|
|
181
|
+
We implement parsing conventions that align better with user expectations. For instance, `<BOOLEAN TRUE FALSE>` is parsed into a Boolean array `[true, false]`.
|
|
182
|
+
|
|
183
|
+
For single values, we return the value directly rather than wrapping it in an array. For example, `<U1 123>` is parsed as `123`.
|
|
184
|
+
|
|
185
|
+
For detailed usage, please refer to the code example below. Note that type assertions are required for each retrieved node to ensure TypeScript type safety.
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
import {
|
|
189
|
+
A,
|
|
190
|
+
L,
|
|
191
|
+
Secs2ItemAscii,
|
|
192
|
+
Secs2ItemList,
|
|
193
|
+
Secs2ItemNumeric,
|
|
194
|
+
SmlParser,
|
|
195
|
+
} from "secs4js";
|
|
196
|
+
|
|
197
|
+
function getItemValue() {
|
|
198
|
+
const body = L(A("MDLN-A"), A("SOFTREV-1"));
|
|
199
|
+
const firstA = body?.[0] as Secs2ItemAscii;
|
|
200
|
+
console.log("MDLN: ", firstA.value);
|
|
201
|
+
|
|
202
|
+
const smlBody = `
|
|
203
|
+
<L
|
|
204
|
+
<A "OK" >
|
|
205
|
+
<U1 20 >
|
|
206
|
+
<U2 1000 2000 >
|
|
207
|
+
<U4 100000000 200000000 >
|
|
208
|
+
<U8 1000000000000000 2000000000000 >
|
|
209
|
+
<I1 10 20 >
|
|
210
|
+
<I2 1000 -2000 >
|
|
211
|
+
<I4 100 >
|
|
212
|
+
<I8 -1234567890123456 9973232131213124 >
|
|
213
|
+
<F4 3.14 -6.18 >
|
|
214
|
+
<F8 1.234567890123456 6.18 >
|
|
215
|
+
<B 0x10 0x20 >
|
|
216
|
+
<Boolean TRUE FALSE >
|
|
217
|
+
<L
|
|
218
|
+
<A "Nested" >
|
|
219
|
+
<F4 3.14 >
|
|
220
|
+
<L
|
|
221
|
+
<A "More Nested">
|
|
222
|
+
<Boolean F>
|
|
223
|
+
>
|
|
224
|
+
>
|
|
225
|
+
>
|
|
226
|
+
`;
|
|
227
|
+
const smlBodySecs2Items = SmlParser.parseBody(smlBody);
|
|
228
|
+
const zeroItem = smlBodySecs2Items?.[0] as Secs2ItemAscii;
|
|
229
|
+
const firstU1 = smlBodySecs2Items?.[1] as Secs2ItemNumeric;
|
|
230
|
+
const secondItem = smlBodySecs2Items?.[2] as Secs2ItemNumeric;
|
|
231
|
+
const eighthItem = smlBodySecs2Items?.[8] as Secs2ItemNumeric;
|
|
232
|
+
const tenthItem = smlBodySecs2Items?.[10] as Secs2ItemNumeric;
|
|
233
|
+
const twelfthItem = smlBodySecs2Items?.[12] as Secs2ItemNumeric;
|
|
234
|
+
const nestedList = smlBodySecs2Items?.[13] as Secs2ItemList;
|
|
235
|
+
const nestedListFirstItem = nestedList?.[0] as Secs2ItemAscii;
|
|
236
|
+
console.log("ASCII value: ", zeroItem.value);
|
|
237
|
+
console.log("U1 value: ", firstU1.value);
|
|
238
|
+
console.log("U2 value: ", secondItem.value);
|
|
239
|
+
console.log("I8 value: ", eighthItem.value);
|
|
240
|
+
console.log("F8 value: ", tenthItem.value);
|
|
241
|
+
console.log("BOOLEAN value: ", twelfthItem.value);
|
|
242
|
+
console.log("NESTED ASCII value: ", nestedListFirstItem.value);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
getItemValue();
|
|
246
|
+
```
|
|
247
|
+
|
|
162
248
|
## Sending and Replying to Messages
|
|
163
249
|
|
|
164
250
|
In this library, you can actively send messages and passively reply to messages.
|
|
@@ -40,9 +40,9 @@ var Secs1Communicator = class extends AbstractSecsCommunicator {
|
|
|
40
40
|
this.stream = stream;
|
|
41
41
|
this.resetState();
|
|
42
42
|
this.buffer = Buffer.alloc(0);
|
|
43
|
-
this.logger.logState("
|
|
43
|
+
this.logger.logState("SECS-I", "NotConnected", "Connected");
|
|
44
44
|
stream.on("data", (data) => {
|
|
45
|
-
this.logger.logBytes("Received", "
|
|
45
|
+
this.logger.logBytes("Received", "SECS-I", data, { chunkLength: data.length });
|
|
46
46
|
this.buffer = Buffer.concat([this.buffer, data]);
|
|
47
47
|
if (this.state === CommState.WAIT_BLOCK_LENGTH || this.state === CommState.WAIT_BLOCK_DATA) this.startT1();
|
|
48
48
|
this.processBuffer();
|
|
@@ -51,7 +51,7 @@ var Secs1Communicator = class extends AbstractSecsCommunicator {
|
|
|
51
51
|
this.rejectAllTransactions(/* @__PURE__ */ new Error("Stream closed"));
|
|
52
52
|
this.stream = null;
|
|
53
53
|
this.emit("disconnected");
|
|
54
|
-
this.logger.logState("
|
|
54
|
+
this.logger.logState("SECS-I", "Connected", "NotConnected");
|
|
55
55
|
this.stopAllTimers();
|
|
56
56
|
this.resetState();
|
|
57
57
|
});
|
|
@@ -129,13 +129,13 @@ var Secs1Communicator = class extends AbstractSecsCommunicator {
|
|
|
129
129
|
}, timeout);
|
|
130
130
|
}
|
|
131
131
|
handleT1Timeout() {
|
|
132
|
-
this.logger.detail.warn({ protocol: "
|
|
132
|
+
this.logger.detail.warn({ protocol: "SECS-I" }, "t1 timeout");
|
|
133
133
|
this.t1Timer = null;
|
|
134
134
|
this.emit("error", /* @__PURE__ */ new Error("T1 Timeout"));
|
|
135
135
|
this.resetState();
|
|
136
136
|
}
|
|
137
137
|
handleT2Timeout() {
|
|
138
|
-
this.logger.detail.warn({ protocol: "
|
|
138
|
+
this.logger.detail.warn({ protocol: "SECS-I" }, "t2 timeout");
|
|
139
139
|
this.t2Timer = null;
|
|
140
140
|
if (this.state === CommState.WAIT_EOT) {
|
|
141
141
|
this.retryCount++;
|
|
@@ -144,7 +144,7 @@ var Secs1Communicator = class extends AbstractSecsCommunicator {
|
|
|
144
144
|
this.resetState();
|
|
145
145
|
} else {
|
|
146
146
|
this.logger.detail.info({
|
|
147
|
-
protocol: "
|
|
147
|
+
protocol: "SECS-I",
|
|
148
148
|
retryCount: this.retryCount,
|
|
149
149
|
retry: this.retry
|
|
150
150
|
}, "retrying ENQ");
|
|
@@ -160,7 +160,7 @@ var Secs1Communicator = class extends AbstractSecsCommunicator {
|
|
|
160
160
|
this.resetState();
|
|
161
161
|
} else {
|
|
162
162
|
this.logger.detail.info({
|
|
163
|
-
protocol: "
|
|
163
|
+
protocol: "SECS-I",
|
|
164
164
|
retryCount: this.retryCount,
|
|
165
165
|
retry: this.retry
|
|
166
166
|
}, "retrying block");
|
|
@@ -171,7 +171,7 @@ var Secs1Communicator = class extends AbstractSecsCommunicator {
|
|
|
171
171
|
this.resetState();
|
|
172
172
|
}
|
|
173
173
|
handleT4Timeout() {
|
|
174
|
-
this.logger.detail.warn({ protocol: "
|
|
174
|
+
this.logger.detail.warn({ protocol: "SECS-I" }, "t4 timeout");
|
|
175
175
|
this.t4Timer = null;
|
|
176
176
|
this.resetState();
|
|
177
177
|
}
|
|
@@ -186,7 +186,7 @@ var Secs1Communicator = class extends AbstractSecsCommunicator {
|
|
|
186
186
|
const stream = this.stream;
|
|
187
187
|
if (stream && !stream.destroyed) {
|
|
188
188
|
const buf = Buffer.from([byte]);
|
|
189
|
-
this.logger.logBytes("Sent", "
|
|
189
|
+
this.logger.logBytes("Sent", "SECS-I", buf);
|
|
190
190
|
stream.write(buf);
|
|
191
191
|
}
|
|
192
192
|
}
|
|
@@ -196,7 +196,7 @@ var Secs1Communicator = class extends AbstractSecsCommunicator {
|
|
|
196
196
|
const byte = this.buffer[0];
|
|
197
197
|
this.buffer = this.buffer.subarray(1);
|
|
198
198
|
if (byte === ENQ) {
|
|
199
|
-
this.logger.detail.debug({ protocol: "
|
|
199
|
+
this.logger.detail.debug({ protocol: "SECS-I" }, "rx ENQ");
|
|
200
200
|
this.sendByte(EOT);
|
|
201
201
|
this.state = CommState.WAIT_BLOCK_LENGTH;
|
|
202
202
|
this.receivedBlocks = [];
|
|
@@ -209,13 +209,13 @@ var Secs1Communicator = class extends AbstractSecsCommunicator {
|
|
|
209
209
|
const byte = this.buffer[0];
|
|
210
210
|
this.buffer = this.buffer.subarray(1);
|
|
211
211
|
if (byte === EOT) {
|
|
212
|
-
this.logger.detail.debug({ protocol: "
|
|
212
|
+
this.logger.detail.debug({ protocol: "SECS-I" }, "rx EOT");
|
|
213
213
|
this.clearT2();
|
|
214
214
|
this.currentBlockIndex = 0;
|
|
215
215
|
this.sendCurrentBlock();
|
|
216
216
|
} else if (byte === ENQ) {
|
|
217
217
|
if (!this.isMaster) {
|
|
218
|
-
this.logger.detail.debug({ protocol: "
|
|
218
|
+
this.logger.detail.debug({ protocol: "SECS-I" }, "rx ENQ while waiting EOT");
|
|
219
219
|
this.clearT2();
|
|
220
220
|
this.sendByte(EOT);
|
|
221
221
|
this.state = CommState.WAIT_BLOCK_LENGTH;
|
|
@@ -230,7 +230,7 @@ var Secs1Communicator = class extends AbstractSecsCommunicator {
|
|
|
230
230
|
const byte = this.buffer[0];
|
|
231
231
|
this.buffer = this.buffer.subarray(1);
|
|
232
232
|
if (byte === ACK) {
|
|
233
|
-
this.logger.detail.debug({ protocol: "
|
|
233
|
+
this.logger.detail.debug({ protocol: "SECS-I" }, "rx ACK");
|
|
234
234
|
this.clearT2();
|
|
235
235
|
if (this.currentBlocks[this.currentBlockIndex].eBit) {
|
|
236
236
|
this.currentBlocks = [];
|
|
@@ -242,7 +242,7 @@ var Secs1Communicator = class extends AbstractSecsCommunicator {
|
|
|
242
242
|
this.sendCurrentBlock();
|
|
243
243
|
}
|
|
244
244
|
} else if (byte === NAK) {
|
|
245
|
-
this.logger.detail.warn({ protocol: "
|
|
245
|
+
this.logger.detail.warn({ protocol: "SECS-I" }, "rx NAK");
|
|
246
246
|
this.clearT2();
|
|
247
247
|
this.handleT2Timeout();
|
|
248
248
|
}
|
|
@@ -274,7 +274,7 @@ var Secs1Communicator = class extends AbstractSecsCommunicator {
|
|
|
274
274
|
const block = new Secs1MessageBlock(fullBlockBuffer);
|
|
275
275
|
if (block.isValid()) if (block.blockNumber !== this.expectedBlockNum) {
|
|
276
276
|
this.logger.detail.warn({
|
|
277
|
-
protocol: "
|
|
277
|
+
protocol: "SECS-I",
|
|
278
278
|
expected: this.expectedBlockNum,
|
|
279
279
|
got: block.blockNumber
|
|
280
280
|
}, "wrong block number");
|
|
@@ -300,7 +300,7 @@ var Secs1Communicator = class extends AbstractSecsCommunicator {
|
|
|
300
300
|
}
|
|
301
301
|
}
|
|
302
302
|
else {
|
|
303
|
-
this.logger.detail.warn({ protocol: "
|
|
303
|
+
this.logger.detail.warn({ protocol: "SECS-I" }, "invalid checksum");
|
|
304
304
|
this.sendByte(NAK);
|
|
305
305
|
this.state = CommState.IDLE;
|
|
306
306
|
this.resetState();
|
|
@@ -315,7 +315,7 @@ var Secs1Communicator = class extends AbstractSecsCommunicator {
|
|
|
315
315
|
const stream = this.stream;
|
|
316
316
|
const block = this.currentBlocks[this.currentBlockIndex];
|
|
317
317
|
if (stream && !stream.destroyed) {
|
|
318
|
-
this.logger.logBytes("Sent", "
|
|
318
|
+
this.logger.logBytes("Sent", "SECS-I", block.buffer, {
|
|
319
319
|
blockNumber: block.blockNumber,
|
|
320
320
|
eBit: block.eBit,
|
|
321
321
|
systemBytes: block.systemBytes,
|
|
@@ -1 +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\t\tthis.logger.logState(\"SECS1\", \"NotConnected\", \"Connected\");\n\n\t\tstream.on(\"data\", (data: Buffer) => {\n\t\t\tthis.logger.logBytes(\"Received\", \"SECS1\", data, {\n\t\t\t\tchunkLength: data.length,\n\t\t\t});\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.logger.logState(\"SECS1\", \"Connected\", \"NotConnected\");\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 async sendBufferWithLogs(\n\t\tdirection: \"Sent\" | \"Received\",\n\t\tprotocol: string,\n\t\tbuffer: Buffer,\n\t\tmeta?: Record<string, unknown>,\n\t): Promise<void> {\n\t\tawait super.sendBufferWithLogs(\n\t\t\tdirection,\n\t\t\tprotocol === \"SECS\" ? \"SECS1\" : protocol,\n\t\t\tbuffer,\n\t\t\t{\n\t\t\t\tcommState: CommState[this.state],\n\t\t\t\t...meta,\n\t\t\t},\n\t\t);\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\tthis.logger.detail.warn({ protocol: \"SECS1\" }, \"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\tthis.logger.detail.warn({ protocol: \"SECS1\" }, \"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\tthis.logger.detail.info(\n\t\t\t\t\t{\n\t\t\t\t\t\tprotocol: \"SECS1\",\n\t\t\t\t\t\tretryCount: this.retryCount,\n\t\t\t\t\t\tretry: this.retry,\n\t\t\t\t\t},\n\t\t\t\t\t\"retrying ENQ\",\n\t\t\t\t);\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\tthis.logger.detail.info(\n\t\t\t\t\t{\n\t\t\t\t\t\tprotocol: \"SECS1\",\n\t\t\t\t\t\tretryCount: this.retryCount,\n\t\t\t\t\t\tretry: this.retry,\n\t\t\t\t\t},\n\t\t\t\t\t\"retrying block\",\n\t\t\t\t);\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\tthis.logger.detail.warn({ protocol: \"SECS1\" }, \"t4 timeout\");\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\tconst buf = Buffer.from([byte]);\n\t\t\tthis.logger.logBytes(\"Sent\", \"SECS1\", buf);\n\t\t\tstream.write(buf);\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.logger.detail.debug({ protocol: \"SECS1\" }, \"rx 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.logger.detail.debug({ protocol: \"SECS1\" }, \"rx 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.logger.detail.debug(\n\t\t\t\t\t\t\t\t{ protocol: \"SECS1\" },\n\t\t\t\t\t\t\t\t\"rx ENQ while waiting EOT\",\n\t\t\t\t\t\t\t);\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.logger.detail.debug({ protocol: \"SECS1\" }, \"rx 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.logger.detail.warn({ protocol: \"SECS1\" }, \"rx 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\tthis.logger.detail.warn(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tprotocol: \"SECS1\",\n\t\t\t\t\t\t\t\t\t\texpected: this.expectedBlockNum,\n\t\t\t\t\t\t\t\t\t\tgot: block.blockNumber,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"wrong block number\",\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\tthis.logger.detail.warn(\n\t\t\t\t\t\t\t\t{ protocol: \"SECS1\" },\n\t\t\t\t\t\t\t\t\"invalid checksum\",\n\t\t\t\t\t\t\t);\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\tthis.logger.logBytes(\"Sent\", \"SECS1\", block.buffer, {\n\t\t\t\tblockNumber: block.blockNumber,\n\t\t\t\teBit: block.eBit,\n\t\t\t\tsystemBytes: block.systemBytes,\n\t\t\t\tstream: block.stream,\n\t\t\t\tfunc: block.func,\n\t\t\t});\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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"}
|
|
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\t\tthis.logger.logState(\"SECS-I\", \"NotConnected\", \"Connected\");\n\n\t\tstream.on(\"data\", (data: Buffer) => {\n\t\t\tthis.logger.logBytes(\"Received\", \"SECS-I\", data, {\n\t\t\t\tchunkLength: data.length,\n\t\t\t});\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.logger.logState(\"SECS-I\", \"Connected\", \"NotConnected\");\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 async sendBufferWithLogs(\n\t\tdirection: \"Sent\" | \"Received\",\n\t\tprotocol: string,\n\t\tbuffer: Buffer,\n\t\tmeta?: Record<string, unknown>,\n\t): Promise<void> {\n\t\tawait super.sendBufferWithLogs(\n\t\t\tdirection,\n\t\t\tprotocol === \"SECS\" ? \"SECS1\" : protocol,\n\t\t\tbuffer,\n\t\t\t{\n\t\t\t\tcommState: CommState[this.state],\n\t\t\t\t...meta,\n\t\t\t},\n\t\t);\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\tthis.logger.detail.warn({ protocol: \"SECS-I\" }, \"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\tthis.logger.detail.warn({ protocol: \"SECS-I\" }, \"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\tthis.logger.detail.info(\n\t\t\t\t\t{\n\t\t\t\t\t\tprotocol: \"SECS-I\",\n\t\t\t\t\t\tretryCount: this.retryCount,\n\t\t\t\t\t\tretry: this.retry,\n\t\t\t\t\t},\n\t\t\t\t\t\"retrying ENQ\",\n\t\t\t\t);\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\tthis.logger.detail.info(\n\t\t\t\t\t{\n\t\t\t\t\t\tprotocol: \"SECS-I\",\n\t\t\t\t\t\tretryCount: this.retryCount,\n\t\t\t\t\t\tretry: this.retry,\n\t\t\t\t\t},\n\t\t\t\t\t\"retrying block\",\n\t\t\t\t);\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\tthis.logger.detail.warn({ protocol: \"SECS-I\" }, \"t4 timeout\");\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\tconst buf = Buffer.from([byte]);\n\t\t\tthis.logger.logBytes(\"Sent\", \"SECS-I\", buf);\n\t\t\tstream.write(buf);\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.logger.detail.debug({ protocol: \"SECS-I\" }, \"rx 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.logger.detail.debug({ protocol: \"SECS-I\" }, \"rx 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.logger.detail.debug(\n\t\t\t\t\t\t\t\t{ protocol: \"SECS-I\" },\n\t\t\t\t\t\t\t\t\"rx ENQ while waiting EOT\",\n\t\t\t\t\t\t\t);\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.logger.detail.debug({ protocol: \"SECS-I\" }, \"rx 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.logger.detail.warn({ protocol: \"SECS-I\" }, \"rx 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\tthis.logger.detail.warn(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tprotocol: \"SECS-I\",\n\t\t\t\t\t\t\t\t\t\texpected: this.expectedBlockNum,\n\t\t\t\t\t\t\t\t\t\tgot: block.blockNumber,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"wrong block number\",\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\tthis.logger.detail.warn(\n\t\t\t\t\t\t\t\t{ protocol: \"SECS-I\" },\n\t\t\t\t\t\t\t\t\"invalid checksum\",\n\t\t\t\t\t\t\t);\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\tthis.logger.logBytes(\"Sent\", \"SECS-I\", block.buffer, {\n\t\t\t\tblockNumber: block.blockNumber,\n\t\t\t\teBit: block.eBit,\n\t\t\t\tsystemBytes: block.systemBytes,\n\t\t\t\tstream: block.stream,\n\t\t\t\tfunc: block.func,\n\t\t\t});\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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"}
|
|
@@ -16,7 +16,7 @@ var Secs1OnTcpIpActiveCommunicator = class extends Secs1Communicator {
|
|
|
16
16
|
this.on("disconnected", () => {
|
|
17
17
|
if (!this.shouldStop) {
|
|
18
18
|
this.logger.detail.warn({
|
|
19
|
-
protocol: "
|
|
19
|
+
protocol: "SECS-I-TCP/IP",
|
|
20
20
|
ip: this.ip,
|
|
21
21
|
port: this.port,
|
|
22
22
|
timeoutT5: this.timeoutT5
|
|
@@ -44,7 +44,7 @@ var Secs1OnTcpIpActiveCommunicator = class extends Secs1Communicator {
|
|
|
44
44
|
const onError = (err) => {
|
|
45
45
|
socket.destroy();
|
|
46
46
|
this.logger.detail.warn({
|
|
47
|
-
protocol: "
|
|
47
|
+
protocol: "SECS-I-TCP/IP",
|
|
48
48
|
ip: this.ip,
|
|
49
49
|
port: this.port,
|
|
50
50
|
timeoutT5: this.timeoutT5,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Secs1OnTcpIpActiveCommunicator.js","names":[],"sources":["../../src/secs1/Secs1OnTcpIpActiveCommunicator.ts"],"sourcesContent":["import { Socket } from \"net\";\nimport {\n\tSecs1Communicator,\n\tSecs1CommunicatorConfig,\n} from \"./Secs1Communicator.js\";\n\nexport interface Secs1OnTcpIpActiveCommunicatorConfig extends Secs1CommunicatorConfig {\n\tip: string;\n\tport: number;\n}\n\nexport class Secs1OnTcpIpActiveCommunicator extends Secs1Communicator {\n\tpublic ip: string;\n\tpublic port: number;\n\n\tprivate shouldStop = false;\n\tprivate reconnectTimer: NodeJS.Timeout | null = null;\n\tprivate connectionPromiseResolver: (() => void) | null = null;\n\tprivate pendingSocket: Socket | null = null;\n\n\tconstructor(config: Secs1OnTcpIpActiveCommunicatorConfig) {\n\t\tsuper(config);\n\t\tthis.ip = config.ip;\n\t\tthis.port = config.port;\n\t\tthis.on(\"disconnected\", () => {\n\t\t\tif (!this.shouldStop) {\n\t\t\t\tthis.logger.detail.warn(\n\t\t\t\t\t{\n\t\t\t\t\t\tprotocol: \"
|
|
1
|
+
{"version":3,"file":"Secs1OnTcpIpActiveCommunicator.js","names":[],"sources":["../../src/secs1/Secs1OnTcpIpActiveCommunicator.ts"],"sourcesContent":["import { Socket } from \"net\";\nimport {\n\tSecs1Communicator,\n\tSecs1CommunicatorConfig,\n} from \"./Secs1Communicator.js\";\n\nexport interface Secs1OnTcpIpActiveCommunicatorConfig extends Secs1CommunicatorConfig {\n\tip: string;\n\tport: number;\n}\n\nexport class Secs1OnTcpIpActiveCommunicator extends Secs1Communicator {\n\tpublic ip: string;\n\tpublic port: number;\n\n\tprivate shouldStop = false;\n\tprivate reconnectTimer: NodeJS.Timeout | null = null;\n\tprivate connectionPromiseResolver: (() => void) | null = null;\n\tprivate pendingSocket: Socket | null = null;\n\n\tconstructor(config: Secs1OnTcpIpActiveCommunicatorConfig) {\n\t\tsuper(config);\n\t\tthis.ip = config.ip;\n\t\tthis.port = config.port;\n\t\tthis.on(\"disconnected\", () => {\n\t\t\tif (!this.shouldStop) {\n\t\t\t\tthis.logger.detail.warn(\n\t\t\t\t\t{\n\t\t\t\t\t\tprotocol: \"SECS-I-TCP/IP\",\n\t\t\t\t\t\tip: this.ip,\n\t\t\t\t\t\tport: this.port,\n\t\t\t\t\t\ttimeoutT5: this.timeoutT5,\n\t\t\t\t\t},\n\t\t\t\t\t\"connection lost; scheduling reconnect\",\n\t\t\t\t);\n\t\t\t\tthis.scheduleReconnect();\n\t\t\t}\n\t\t});\n\t}\n\n\tasync open(): Promise<void> {\n\t\tif (this.stream && !this.stream.destroyed) return;\n\t\tif (this.pendingSocket && !this.pendingSocket.destroyed) return;\n\n\t\tthis.shouldStop = false;\n\n\t\treturn new Promise((resolve) => {\n\t\t\tthis.connectionPromiseResolver = resolve;\n\t\t\tthis.connect();\n\t\t});\n\t}\n\n\tprivate connect() {\n\t\tif (this.shouldStop) return;\n\t\tif (this.stream && !this.stream.destroyed) return;\n\t\tif (this.pendingSocket && !this.pendingSocket.destroyed) return;\n\n\t\tconst socket = new Socket();\n\t\tsocket.setNoDelay(true);\n\t\tthis.pendingSocket = socket;\n\n\t\tconst onError = (err: Error) => {\n\t\t\tsocket.destroy();\n\t\t\tthis.logger.detail.warn(\n\t\t\t\t{\n\t\t\t\t\tprotocol: \"SECS-I-TCP/IP\",\n\t\t\t\t\tip: this.ip,\n\t\t\t\t\tport: this.port,\n\t\t\t\t\ttimeoutT5: this.timeoutT5,\n\t\t\t\t\terr,\n\t\t\t\t},\n\t\t\t\t\"connection failed; scheduling reconnect\",\n\t\t\t);\n\t\t\tif (!this.shouldStop) {\n\t\t\t\tthis.scheduleReconnect();\n\t\t\t}\n\t\t};\n\n\t\tsocket.once(\"error\", onError);\n\n\t\tsocket.once(\"close\", () => {\n\t\t\tif (this.pendingSocket === socket) {\n\t\t\t\tthis.pendingSocket = null;\n\t\t\t}\n\t\t});\n\n\t\tsocket.connect(this.port, this.ip, () => {\n\t\t\tsocket.removeListener(\"error\", onError);\n\t\t\tif (this.pendingSocket === socket) {\n\t\t\t\tthis.pendingSocket = null;\n\t\t\t}\n\t\t\tthis.attachStream(socket);\n\n\t\t\tif (this.connectionPromiseResolver) {\n\t\t\t\tthis.connectionPromiseResolver();\n\t\t\t\tthis.connectionPromiseResolver = null;\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate scheduleReconnect() {\n\t\tif (this.reconnectTimer) {\n\t\t\tclearTimeout(this.reconnectTimer);\n\t\t}\n\t\tthis.reconnectTimer = setTimeout(() => {\n\t\t\tthis.reconnectTimer = null;\n\t\t\tthis.connect();\n\t\t}, this.timeoutT5 * 1000);\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.shouldStop = true;\n\t\tif (this.reconnectTimer) {\n\t\t\tclearTimeout(this.reconnectTimer);\n\t\t\tthis.reconnectTimer = null;\n\t\t}\n\t\tif (this.pendingSocket) {\n\t\t\tthis.pendingSocket.destroy();\n\t\t\tthis.pendingSocket = null;\n\t\t}\n\t\tthis.stop();\n\t\tawait Promise.resolve();\n\t}\n}\n"],"mappings":";;;;AAWA,IAAa,iCAAb,cAAoD,kBAAkB;CACrE,AAAO;CACP,AAAO;CAEP,AAAQ,aAAa;CACrB,AAAQ,iBAAwC;CAChD,AAAQ,4BAAiD;CACzD,AAAQ,gBAA+B;CAEvC,YAAY,QAA8C;AACzD,QAAM,OAAO;AACb,OAAK,KAAK,OAAO;AACjB,OAAK,OAAO,OAAO;AACnB,OAAK,GAAG,sBAAsB;AAC7B,OAAI,CAAC,KAAK,YAAY;AACrB,SAAK,OAAO,OAAO,KAClB;KACC,UAAU;KACV,IAAI,KAAK;KACT,MAAM,KAAK;KACX,WAAW,KAAK;KAChB,EACD,wCACA;AACD,SAAK,mBAAmB;;IAExB;;CAGH,MAAM,OAAsB;AAC3B,MAAI,KAAK,UAAU,CAAC,KAAK,OAAO,UAAW;AAC3C,MAAI,KAAK,iBAAiB,CAAC,KAAK,cAAc,UAAW;AAEzD,OAAK,aAAa;AAElB,SAAO,IAAI,SAAS,YAAY;AAC/B,QAAK,4BAA4B;AACjC,QAAK,SAAS;IACb;;CAGH,AAAQ,UAAU;AACjB,MAAI,KAAK,WAAY;AACrB,MAAI,KAAK,UAAU,CAAC,KAAK,OAAO,UAAW;AAC3C,MAAI,KAAK,iBAAiB,CAAC,KAAK,cAAc,UAAW;EAEzD,MAAM,SAAS,IAAI,QAAQ;AAC3B,SAAO,WAAW,KAAK;AACvB,OAAK,gBAAgB;EAErB,MAAM,WAAW,QAAe;AAC/B,UAAO,SAAS;AAChB,QAAK,OAAO,OAAO,KAClB;IACC,UAAU;IACV,IAAI,KAAK;IACT,MAAM,KAAK;IACX,WAAW,KAAK;IAChB;IACA,EACD,0CACA;AACD,OAAI,CAAC,KAAK,WACT,MAAK,mBAAmB;;AAI1B,SAAO,KAAK,SAAS,QAAQ;AAE7B,SAAO,KAAK,eAAe;AAC1B,OAAI,KAAK,kBAAkB,OAC1B,MAAK,gBAAgB;IAErB;AAEF,SAAO,QAAQ,KAAK,MAAM,KAAK,UAAU;AACxC,UAAO,eAAe,SAAS,QAAQ;AACvC,OAAI,KAAK,kBAAkB,OAC1B,MAAK,gBAAgB;AAEtB,QAAK,aAAa,OAAO;AAEzB,OAAI,KAAK,2BAA2B;AACnC,SAAK,2BAA2B;AAChC,SAAK,4BAA4B;;IAEjC;;CAGH,AAAQ,oBAAoB;AAC3B,MAAI,KAAK,eACR,cAAa,KAAK,eAAe;AAElC,OAAK,iBAAiB,iBAAiB;AACtC,QAAK,iBAAiB;AACtB,QAAK,SAAS;KACZ,KAAK,YAAY,IAAK;;CAG1B,MAAM,QAAuB;AAC5B,OAAK,aAAa;AAClB,MAAI,KAAK,gBAAgB;AACxB,gBAAa,KAAK,eAAe;AACjC,QAAK,iBAAiB;;AAEvB,MAAI,KAAK,eAAe;AACvB,QAAK,cAAc,SAAS;AAC5B,QAAK,gBAAgB;;AAEtB,OAAK,MAAM;AACX,QAAM,QAAQ,SAAS"}
|
|
@@ -4,15 +4,21 @@ import { Secs1Communicator, Secs1CommunicatorConfig } from "./Secs1Communicator.
|
|
|
4
4
|
interface Secs1OnTcpIpPassiveCommunicatorConfig extends Secs1CommunicatorConfig {
|
|
5
5
|
ip: string;
|
|
6
6
|
port: number;
|
|
7
|
+
timeoutRebind?: number;
|
|
7
8
|
}
|
|
8
9
|
declare class Secs1OnTcpIpPassiveCommunicator extends Secs1Communicator {
|
|
9
10
|
ip: string;
|
|
10
11
|
port: number;
|
|
11
12
|
private server;
|
|
13
|
+
private shouldStop;
|
|
14
|
+
private serverLoopPromise;
|
|
15
|
+
private timeoutRebind;
|
|
12
16
|
constructor(config: Secs1OnTcpIpPassiveCommunicatorConfig);
|
|
13
17
|
open(): Promise<void>;
|
|
14
|
-
|
|
18
|
+
private runServerLoop;
|
|
19
|
+
private listenOnce;
|
|
15
20
|
private handleIncomingSocket;
|
|
21
|
+
close(): Promise<void>;
|
|
16
22
|
}
|
|
17
23
|
//#endregion
|
|
18
24
|
export { Secs1OnTcpIpPassiveCommunicator, Secs1OnTcpIpPassiveCommunicatorConfig };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Secs1OnTcpIpPassiveCommunicator.d.ts","names":[],"sources":["../../src/secs1/Secs1OnTcpIpPassiveCommunicator.ts"],"sourcesContent":[],"mappings":";;;UAMiB,qCAAA,SAA8C;;EAA9C,IAAA,EAAA,MAAA;
|
|
1
|
+
{"version":3,"file":"Secs1OnTcpIpPassiveCommunicator.d.ts","names":[],"sources":["../../src/secs1/Secs1OnTcpIpPassiveCommunicator.ts"],"sourcesContent":[],"mappings":";;;UAMiB,qCAAA,SAA8C;;EAA9C,IAAA,EAAA,MAAA;EAMJ,aAAA,CAAA,EAAA,MAAA;;AAkBE,cAlBF,+BAAA,SAAwC,iBAAA,CAkBtC;EA6IL,EAAA,EAAA,MAAA;EA/J2C,IAAA,EAAA,MAAA;EAAiB,QAAA,MAAA;;;;sBASjD;UASN;;;;WA6IL"}
|
|
@@ -6,50 +6,136 @@ var Secs1OnTcpIpPassiveCommunicator = class extends Secs1Communicator {
|
|
|
6
6
|
ip;
|
|
7
7
|
port;
|
|
8
8
|
server = null;
|
|
9
|
+
shouldStop = false;
|
|
10
|
+
serverLoopPromise = null;
|
|
11
|
+
timeoutRebind = 5;
|
|
9
12
|
constructor(config) {
|
|
10
13
|
super(config);
|
|
11
14
|
this.ip = config.ip;
|
|
12
15
|
this.port = config.port;
|
|
16
|
+
if (config.timeoutRebind !== void 0) this.timeoutRebind = config.timeoutRebind;
|
|
13
17
|
}
|
|
14
18
|
async open() {
|
|
15
|
-
if (this.
|
|
19
|
+
if (this.serverLoopPromise) return;
|
|
20
|
+
this.shouldStop = false;
|
|
21
|
+
let resolveFirstListen = null;
|
|
22
|
+
const firstListen = new Promise((resolve) => {
|
|
23
|
+
resolveFirstListen = resolve;
|
|
24
|
+
});
|
|
25
|
+
this.serverLoopPromise = this.runServerLoop(() => {
|
|
26
|
+
resolveFirstListen?.();
|
|
27
|
+
resolveFirstListen = null;
|
|
28
|
+
}).catch((err) => {
|
|
29
|
+
this.emit("error", err instanceof Error ? err : new Error(String(err)));
|
|
30
|
+
});
|
|
31
|
+
await firstListen;
|
|
32
|
+
}
|
|
33
|
+
async runServerLoop(onFirstListening) {
|
|
34
|
+
let first = true;
|
|
35
|
+
while (!this.shouldStop) {
|
|
36
|
+
try {
|
|
37
|
+
await this.listenOnce(first ? onFirstListening : null);
|
|
38
|
+
} catch (err) {
|
|
39
|
+
if (!this.shouldStop) this.emit("error", err instanceof Error ? err : new Error(String(err)));
|
|
40
|
+
if (!this.shouldStop) await new Promise((resolve) => setTimeout(resolve, this.timeoutRebind * 1e3));
|
|
41
|
+
}
|
|
42
|
+
first = false;
|
|
43
|
+
if (this.shouldStop) return;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async listenOnce(onListening) {
|
|
16
47
|
return new Promise((resolve, reject) => {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
48
|
+
const server = createServer((socket) => {
|
|
49
|
+
this.handleIncomingSocket(socket);
|
|
50
|
+
});
|
|
51
|
+
this.server = server;
|
|
52
|
+
let hasConnected = false;
|
|
53
|
+
let settled = false;
|
|
54
|
+
const cleanup = () => {
|
|
55
|
+
server.removeListener("error", onServerError);
|
|
56
|
+
server.removeListener("close", onServerClose);
|
|
57
|
+
this.removeListener("connected", onConnected);
|
|
58
|
+
this.removeListener("disconnected", onDisconnected);
|
|
59
|
+
};
|
|
60
|
+
const finish = (err) => {
|
|
61
|
+
if (settled) return;
|
|
62
|
+
settled = true;
|
|
63
|
+
if (this.server === server) this.server = null;
|
|
64
|
+
cleanup();
|
|
65
|
+
if (err) reject(err);
|
|
66
|
+
else resolve();
|
|
67
|
+
};
|
|
68
|
+
const closeServer = () => {
|
|
69
|
+
if (settled) return;
|
|
70
|
+
if (!server.listening) {
|
|
71
|
+
finish();
|
|
25
72
|
return;
|
|
26
73
|
}
|
|
27
|
-
|
|
28
|
-
|
|
74
|
+
server.close((closeErr) => {
|
|
75
|
+
if (closeErr) finish(closeErr);
|
|
76
|
+
else finish();
|
|
77
|
+
});
|
|
78
|
+
};
|
|
79
|
+
const onServerError = (_err) => {
|
|
80
|
+
closeServer();
|
|
81
|
+
};
|
|
82
|
+
const onServerClose = () => {
|
|
83
|
+
finish();
|
|
84
|
+
};
|
|
85
|
+
const onConnected = () => {
|
|
86
|
+
hasConnected = true;
|
|
87
|
+
};
|
|
88
|
+
const onDisconnected = () => {
|
|
89
|
+
if (!hasConnected) return;
|
|
90
|
+
closeServer();
|
|
91
|
+
};
|
|
92
|
+
server.on("error", onServerError);
|
|
93
|
+
server.on("close", onServerClose);
|
|
94
|
+
this.on("connected", onConnected);
|
|
95
|
+
this.on("disconnected", onDisconnected);
|
|
96
|
+
server.listen(this.port, this.ip, () => {
|
|
97
|
+
onListening?.();
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
handleIncomingSocket(socket) {
|
|
102
|
+
return new Promise((resolve) => {
|
|
103
|
+
if (this.stream && !this.stream.destroyed) {
|
|
104
|
+
this.logger.detail.warn({
|
|
105
|
+
protocol: "SECS-I-TCP/IP",
|
|
29
106
|
remoteAddress: socket.remoteAddress,
|
|
30
107
|
remotePort: socket.remotePort
|
|
31
|
-
}, "
|
|
32
|
-
|
|
33
|
-
});
|
|
34
|
-
this.server.on("error", (err) => {
|
|
35
|
-
reject(err);
|
|
36
|
-
});
|
|
37
|
-
this.server.listen(this.port, this.ip, () => {
|
|
108
|
+
}, "rejecting new connection (single session)");
|
|
109
|
+
socket.destroy();
|
|
38
110
|
resolve();
|
|
39
|
-
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
this.logger.detail.info({
|
|
114
|
+
protocol: "SECS-I-TCP/IP",
|
|
115
|
+
remoteAddress: socket.remoteAddress,
|
|
116
|
+
remotePort: socket.remotePort
|
|
117
|
+
}, "accepted connection");
|
|
118
|
+
this.attachStream(socket);
|
|
119
|
+
resolve();
|
|
40
120
|
});
|
|
41
121
|
}
|
|
42
122
|
close() {
|
|
123
|
+
this.shouldStop = true;
|
|
43
124
|
this.stop();
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
125
|
+
const server = this.server;
|
|
126
|
+
if (server) return new Promise((resolve) => {
|
|
127
|
+
server.close(() => {
|
|
128
|
+
this.server = null;
|
|
129
|
+
resolve();
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
if (this.serverLoopPromise) {
|
|
133
|
+
const loop = this.serverLoopPromise;
|
|
134
|
+
this.serverLoopPromise = null;
|
|
135
|
+
return loop;
|
|
47
136
|
}
|
|
48
137
|
return Promise.resolve();
|
|
49
138
|
}
|
|
50
|
-
handleIncomingSocket(socket) {
|
|
51
|
-
this.attachStream(socket);
|
|
52
|
-
}
|
|
53
139
|
};
|
|
54
140
|
|
|
55
141
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Secs1OnTcpIpPassiveCommunicator.js","names":[],"sources":["../../src/secs1/Secs1OnTcpIpPassiveCommunicator.ts"],"sourcesContent":["import { Server, Socket, createServer } from \"net\";\nimport {\n\tSecs1Communicator,\n\tSecs1CommunicatorConfig,\n} from \"./Secs1Communicator.js\";\n\nexport interface Secs1OnTcpIpPassiveCommunicatorConfig extends Secs1CommunicatorConfig {\n\tip: string;\n\tport: number;\n}\n\nexport class Secs1OnTcpIpPassiveCommunicator extends Secs1Communicator {\n\tpublic ip: string;\n\tpublic port: number;\n\n\tprivate server: Server | null = null;\n\n\tconstructor(config: Secs1OnTcpIpPassiveCommunicatorConfig) {\n\t\tsuper(config);\n\t\tthis.ip = config.ip;\n\t\tthis.port = config.port;\n\t}\n\n\tasync open(): Promise<void> {\n\t\tif (this.
|
|
1
|
+
{"version":3,"file":"Secs1OnTcpIpPassiveCommunicator.js","names":["resolveFirstListen: (() => void) | null"],"sources":["../../src/secs1/Secs1OnTcpIpPassiveCommunicator.ts"],"sourcesContent":["import { Server, Socket, createServer } from \"net\";\nimport {\n\tSecs1Communicator,\n\tSecs1CommunicatorConfig,\n} from \"./Secs1Communicator.js\";\n\nexport interface Secs1OnTcpIpPassiveCommunicatorConfig extends Secs1CommunicatorConfig {\n\tip: string;\n\tport: number;\n\ttimeoutRebind?: number;\n}\n\nexport class Secs1OnTcpIpPassiveCommunicator extends Secs1Communicator {\n\tpublic ip: string;\n\tpublic port: number;\n\n\tprivate server: Server | null = null;\n\tprivate shouldStop = false;\n\tprivate serverLoopPromise: Promise<void> | null = null;\n\tprivate timeoutRebind = 5;\n\n\tconstructor(config: Secs1OnTcpIpPassiveCommunicatorConfig) {\n\t\tsuper(config);\n\t\tthis.ip = config.ip;\n\t\tthis.port = config.port;\n\t\tif (config.timeoutRebind !== undefined) {\n\t\t\tthis.timeoutRebind = config.timeoutRebind;\n\t\t}\n\t}\n\n\tasync open(): Promise<void> {\n\t\tif (this.serverLoopPromise) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.shouldStop = false;\n\n\t\tlet resolveFirstListen: (() => void) | null = null;\n\t\tconst firstListen = new Promise<void>((resolve) => {\n\t\t\tresolveFirstListen = resolve;\n\t\t});\n\n\t\tthis.serverLoopPromise = this.runServerLoop(() => {\n\t\t\tresolveFirstListen?.();\n\t\t\tresolveFirstListen = null;\n\t\t}).catch((err: unknown) => {\n\t\t\tthis.emit(\"error\", err instanceof Error ? err : new Error(String(err)));\n\t\t});\n\n\t\tawait firstListen;\n\t}\n\n\tprivate async runServerLoop(onFirstListening: () => void): Promise<void> {\n\t\tlet first = true;\n\t\twhile (!this.shouldStop) {\n\t\t\ttry {\n\t\t\t\tawait this.listenOnce(first ? onFirstListening : null);\n\t\t\t} catch (err) {\n\t\t\t\tif (!this.shouldStop) {\n\t\t\t\t\tthis.emit(\n\t\t\t\t\t\t\"error\",\n\t\t\t\t\t\terr instanceof Error ? err : new Error(String(err)),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (!this.shouldStop) {\n\t\t\t\t\tawait new Promise((resolve) =>\n\t\t\t\t\t\tsetTimeout(resolve, this.timeoutRebind * 1000),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfirst = false;\n\t\t\tif (this.shouldStop) return;\n\t\t}\n\t}\n\n\tprivate async listenOnce(onListening: (() => void) | null): Promise<void> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst server = createServer((socket) => {\n\t\t\t\tvoid this.handleIncomingSocket(socket);\n\t\t\t});\n\t\t\tthis.server = server;\n\n\t\t\tlet hasConnected = false;\n\t\t\tlet settled = false;\n\n\t\t\tconst cleanup = () => {\n\t\t\t\tserver.removeListener(\"error\", onServerError);\n\t\t\t\tserver.removeListener(\"close\", onServerClose);\n\t\t\t\tthis.removeListener(\"connected\", onConnected);\n\t\t\t\tthis.removeListener(\"disconnected\", onDisconnected);\n\t\t\t};\n\n\t\t\tconst finish = (err?: Error) => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tif (this.server === server) {\n\t\t\t\t\tthis.server = null;\n\t\t\t\t}\n\t\t\t\tcleanup();\n\t\t\t\tif (err) reject(err);\n\t\t\t\telse resolve();\n\t\t\t};\n\n\t\t\tconst closeServer = () => {\n\t\t\t\tif (settled) return;\n\t\t\t\tif (!server.listening) {\n\t\t\t\t\tfinish();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tserver.close((closeErr) => {\n\t\t\t\t\tif (closeErr) finish(closeErr);\n\t\t\t\t\telse finish();\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tconst onServerError = (_err: Error) => {\n\t\t\t\tcloseServer();\n\t\t\t};\n\n\t\t\tconst onServerClose = () => {\n\t\t\t\tfinish();\n\t\t\t};\n\n\t\t\tconst onConnected = () => {\n\t\t\t\thasConnected = true;\n\t\t\t};\n\n\t\t\tconst onDisconnected = () => {\n\t\t\t\tif (!hasConnected) return;\n\t\t\t\tcloseServer();\n\t\t\t};\n\n\t\t\tserver.on(\"error\", onServerError);\n\t\t\tserver.on(\"close\", onServerClose);\n\t\t\tthis.on(\"connected\", onConnected);\n\t\t\tthis.on(\"disconnected\", onDisconnected);\n\n\t\t\tserver.listen(this.port, this.ip, () => {\n\t\t\t\tonListening?.();\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate handleIncomingSocket(socket: Socket): Promise<void> {\n\t\treturn new Promise((resolve) => {\n\t\t\tif (this.stream && !this.stream.destroyed) {\n\t\t\t\tthis.logger.detail.warn(\n\t\t\t\t\t{\n\t\t\t\t\t\tprotocol: \"SECS-I-TCP/IP\",\n\t\t\t\t\t\tremoteAddress: socket.remoteAddress,\n\t\t\t\t\t\tremotePort: socket.remotePort,\n\t\t\t\t\t},\n\t\t\t\t\t\"rejecting new connection (single session)\",\n\t\t\t\t);\n\t\t\t\tsocket.destroy();\n\t\t\t\tresolve();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.logger.detail.info(\n\t\t\t\t{\n\t\t\t\t\tprotocol: \"SECS-I-TCP/IP\",\n\t\t\t\t\tremoteAddress: socket.remoteAddress,\n\t\t\t\t\tremotePort: socket.remotePort,\n\t\t\t\t},\n\t\t\t\t\"accepted connection\",\n\t\t\t);\n\t\t\tthis.attachStream(socket);\n\t\t\tresolve();\n\t\t});\n\t}\n\n\tclose(): Promise<void> {\n\t\tthis.shouldStop = true;\n\t\tthis.stop();\n\t\tconst server = this.server;\n\t\tif (server) {\n\t\t\treturn new Promise<void>((resolve) => {\n\t\t\t\tserver.close(() => {\n\t\t\t\t\tthis.server = null;\n\t\t\t\t\tresolve();\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t\tif (this.serverLoopPromise) {\n\t\t\tconst loop = this.serverLoopPromise;\n\t\t\tthis.serverLoopPromise = null;\n\t\t\treturn loop;\n\t\t}\n\t\treturn Promise.resolve();\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Secs1SerialCommunicator.d.ts","names":[],"sources":["../../src/secs1/Secs1SerialCommunicator.ts"],"sourcesContent":[],"mappings":";;;UAMiB,6BAAA,SAAsC;;EAAtC,QAAA,EAAA,MAAA;AAKjB;AAMqB,cANR,uBAAA,SAAgC,iBAAA,CAMxB;
|
|
1
|
+
{"version":3,"file":"Secs1SerialCommunicator.d.ts","names":[],"sources":["../../src/secs1/Secs1SerialCommunicator.ts"],"sourcesContent":[],"mappings":";;;UAMiB,6BAAA,SAAsC;;EAAtC,QAAA,EAAA,MAAA;AAKjB;AAMqB,cANR,uBAAA,SAAgC,iBAAA,CAMxB;EAON,QAAA,IAAA;EA4BC,IAAA,EAAA,MAAA;EAzC6B,QAAA,EAAA,MAAA;EAAiB,WAAA,CAAA,MAAA,EAMzC,6BANyC;UAa/C;WA4BC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Secs1SerialCommunicator.js","names":[],"sources":["../../src/secs1/Secs1SerialCommunicator.ts"],"sourcesContent":["import { SerialPort } from \"serialport\";\nimport {\n\tSecs1Communicator,\n\tSecs1CommunicatorConfig,\n} from \"./Secs1Communicator.js\";\n\nexport interface Secs1SerialCommunicatorConfig extends Secs1CommunicatorConfig {\n\tpath: string;\n\tbaudRate: number;\n}\n\nexport class Secs1SerialCommunicator extends Secs1Communicator {\n\tprivate port: SerialPort | null = null;\n\n\tpublic path: string;\n\tpublic baudRate: number;\n\n\tconstructor(config: Secs1SerialCommunicatorConfig) {\n\t\tsuper(config);\n\t\tthis.path = config.path;\n\t\tthis.baudRate = config.baudRate;\n\t}\n\n\tasync open(): Promise<void> {\n\t\tif (this.port?.isOpen) return;\n\n\t\tconst port = new SerialPort({\n\t\t\tpath: this.path,\n\t\t\tbaudRate: this.baudRate,\n\t\t\tautoOpen: false,\n\t\t});\n\t\tthis.port = port;\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst onError = (err: Error) => {\n\t\t\t\treject(err);\n\t\t\t};\n\n\t\t\tport.once(\"error\", onError);\n\t\t\tport.open((err) => {\n\t\t\t\tport.removeListener(\"error\", onError);\n\t\t\t\tif (err) {\n\t\t\t\t\treject(err);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.attachStream(port);\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.stop();\n\n\t\tconst port = this.port;\n\t\tthis.port = null;\n\t\tif (!port) return;\n\n\t\tif (!port.isOpen) {\n\t\t\tport.destroy();\n\t\t\treturn;\n\t\t}\n\n\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\tport.close((err) => {\n\t\t\t\tif (err) reject(err);\n\t\t\t\telse resolve();\n\t\t\t});\n\t\t});\n\n\t\tport.destroy();\n\t}\n}\n"],"mappings":";;;;AAWA,IAAa,0BAAb,cAA6C,kBAAkB;CAC9D,AAAQ,OAA0B;CAElC,AAAO;CACP,AAAO;CAEP,YAAY,QAAuC;AAClD,QAAM,OAAO;AACb,OAAK,OAAO,OAAO;AACnB,OAAK,WAAW,OAAO;;CAGxB,MAAM,OAAsB;AAC3B,MAAI,KAAK,MAAM,OAAQ;EAEvB,MAAM,OAAO,IAAI,WAAW;GAC3B,MAAM,KAAK;GACX,UAAU,KAAK;GACf,UAAU;GACV,CAAC;AACF,OAAK,OAAO;AAEZ,SAAO,IAAI,SAAS,SAAS,WAAW;GACvC,MAAM,WAAW,QAAe;AAC/B,WAAO,IAAI;;AAGZ,QAAK,KAAK,SAAS,QAAQ;AAC3B,QAAK,MAAM,QAAQ;AAClB,SAAK,eAAe,SAAS,QAAQ;AACrC,QAAI,KAAK;AACR,YAAO,IAAI;AACX;;AAED,SAAK,aAAa,KAAK;AACvB,aAAS;KACR;IACD;;CAGH,MAAM,QAAuB;AAC5B,OAAK,MAAM;EAEX,MAAM,OAAO,KAAK;AAClB,OAAK,OAAO;AACZ,MAAI,CAAC,KAAM;AAEX,MAAI,CAAC,KAAK,QAAQ;AACjB,QAAK,SAAS;AACd;;AAGD,QAAM,IAAI,SAAe,SAAS,WAAW;AAC5C,QAAK,OAAO,QAAQ;AACnB,QAAI,IAAK,QAAO,IAAI;QACf,UAAS;KACb;IACD;AAEF,OAAK,SAAS"}
|
|
1
|
+
{"version":3,"file":"Secs1SerialCommunicator.js","names":[],"sources":["../../src/secs1/Secs1SerialCommunicator.ts"],"sourcesContent":["import { SerialPort } from \"serialport\";\nimport {\n\tSecs1Communicator,\n\tSecs1CommunicatorConfig,\n} from \"./Secs1Communicator.js\";\n\nexport interface Secs1SerialCommunicatorConfig extends Secs1CommunicatorConfig {\n\tpath: string;\n\tbaudRate: number;\n}\n\nexport class Secs1SerialCommunicator extends Secs1Communicator {\n\tprivate port: SerialPort | null = null;\n\n\tpublic path: string;\n\tpublic baudRate: number;\n\n\tconstructor(config: Secs1SerialCommunicatorConfig) {\n\t\tsuper(config);\n\t\tthis.isMaster = config.isEquip;\n\t\tthis.path = config.path;\n\t\tthis.baudRate = config.baudRate;\n\t}\n\n\tasync open(): Promise<void> {\n\t\tif (this.port?.isOpen) return;\n\n\t\tconst port = new SerialPort({\n\t\t\tpath: this.path,\n\t\t\tbaudRate: this.baudRate,\n\t\t\tautoOpen: false,\n\t\t});\n\t\tthis.port = port;\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst onError = (err: Error) => {\n\t\t\t\treject(err);\n\t\t\t};\n\n\t\t\tport.once(\"error\", onError);\n\t\t\tport.open((err) => {\n\t\t\t\tport.removeListener(\"error\", onError);\n\t\t\t\tif (err) {\n\t\t\t\t\treject(err);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.attachStream(port);\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.stop();\n\n\t\tconst port = this.port;\n\t\tthis.port = null;\n\t\tif (!port) return;\n\n\t\tif (!port.isOpen) {\n\t\t\tport.destroy();\n\t\t\treturn;\n\t\t}\n\n\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\tport.close((err) => {\n\t\t\t\tif (err) reject(err);\n\t\t\t\telse resolve();\n\t\t\t});\n\t\t});\n\n\t\tport.destroy();\n\t}\n}\n"],"mappings":";;;;AAWA,IAAa,0BAAb,cAA6C,kBAAkB;CAC9D,AAAQ,OAA0B;CAElC,AAAO;CACP,AAAO;CAEP,YAAY,QAAuC;AAClD,QAAM,OAAO;AACb,OAAK,WAAW,OAAO;AACvB,OAAK,OAAO,OAAO;AACnB,OAAK,WAAW,OAAO;;CAGxB,MAAM,OAAsB;AAC3B,MAAI,KAAK,MAAM,OAAQ;EAEvB,MAAM,OAAO,IAAI,WAAW;GAC3B,MAAM,KAAK;GACX,UAAU,KAAK;GACf,UAAU;GACV,CAAC;AACF,OAAK,OAAO;AAEZ,SAAO,IAAI,SAAS,SAAS,WAAW;GACvC,MAAM,WAAW,QAAe;AAC/B,WAAO,IAAI;;AAGZ,QAAK,KAAK,SAAS,QAAQ;AAC3B,QAAK,MAAM,QAAQ;AAClB,SAAK,eAAe,SAAS,QAAQ;AACrC,QAAI,KAAK;AACR,YAAO,IAAI;AACX;;AAED,SAAK,aAAa,KAAK;AACvB,aAAS;KACR;IACD;;CAGH,MAAM,QAAuB;AAC5B,OAAK,MAAM;EAEX,MAAM,OAAO,KAAK;AAClB,OAAK,OAAO;AACZ,MAAI,CAAC,KAAM;AAEX,MAAI,CAAC,KAAK,QAAQ;AACjB,QAAK,SAAS;AACd;;AAGD,QAAM,IAAI,SAAe,SAAS,WAAW;AAC5C,QAAK,OAAO,QAAQ;AACnB,QAAI,IAAK,QAAO,IAAI;QACf,UAAS;KACb;IACD;AAEF,OAAK,SAAS"}
|