secs4js 0.2.0 → 0.4.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 (55) hide show
  1. package/LICENSE.md +20 -20
  2. package/README.md +442 -442
  3. package/lib/core/AbstractSecsCommunicator.d.ts +4 -0
  4. package/lib/core/AbstractSecsCommunicator.d.ts.map +1 -1
  5. package/lib/core/AbstractSecsCommunicator.js +70 -5
  6. package/lib/core/AbstractSecsCommunicator.js.map +1 -1
  7. package/lib/core/AbstractSecsMessage.js.map +1 -1
  8. package/lib/core/enums/HsmsSsControlType.js.map +1 -1
  9. package/lib/core/enums/RejectReason.js.map +1 -1
  10. package/lib/core/enums/SecsItemType.js.map +1 -1
  11. package/lib/core/enums/SelectStatus.js.map +1 -1
  12. package/lib/core/secs2item/AbstractSecs2Item.js.map +1 -1
  13. package/lib/core/secs2item/Secs2ItemAscii.js.map +1 -1
  14. package/lib/core/secs2item/Secs2ItemBinary.js.map +1 -1
  15. package/lib/core/secs2item/Secs2ItemBoolean.js.map +1 -1
  16. package/lib/core/secs2item/Secs2ItemFactory.js.map +1 -1
  17. package/lib/core/secs2item/Secs2ItemList.js.map +1 -1
  18. package/lib/core/secs2item/Secs2ItemNumeric.js.map +1 -1
  19. package/lib/core/secs2item/Secs2ItemParser.js.map +1 -1
  20. package/lib/gem/Clock.js.map +1 -1
  21. package/lib/gem/Gem.js.map +1 -1
  22. package/lib/helper/Secs2ItemHelper.js.map +1 -1
  23. package/lib/hsms/HsmsActiveCommunicator.d.ts.map +1 -1
  24. package/lib/hsms/HsmsActiveCommunicator.js +21 -5
  25. package/lib/hsms/HsmsActiveCommunicator.js.map +1 -1
  26. package/lib/hsms/HsmsCommunicator.d.ts +1 -0
  27. package/lib/hsms/HsmsCommunicator.d.ts.map +1 -1
  28. package/lib/hsms/HsmsCommunicator.js +72 -7
  29. package/lib/hsms/HsmsCommunicator.js.map +1 -1
  30. package/lib/hsms/HsmsMessage.js.map +1 -1
  31. package/lib/hsms/HsmsPassiveCommunicator.js.map +1 -1
  32. package/lib/hsms/enums/HsmsControlType.js.map +1 -1
  33. package/lib/hsms/enums/RejectReason.js.map +1 -1
  34. package/lib/hsms/enums/SelectStatus.js.map +1 -1
  35. package/lib/index.d.ts +2 -1
  36. package/lib/index.js +2 -1
  37. package/lib/logging/SecsLogger.d.ts +36 -0
  38. package/lib/logging/SecsLogger.d.ts.map +1 -0
  39. package/lib/logging/SecsLogger.js +415 -0
  40. package/lib/logging/SecsLogger.js.map +1 -0
  41. package/lib/secs1/Secs1Communicator.d.ts +1 -0
  42. package/lib/secs1/Secs1Communicator.d.ts.map +1 -1
  43. package/lib/secs1/Secs1Communicator.js +45 -8
  44. package/lib/secs1/Secs1Communicator.js.map +1 -1
  45. package/lib/secs1/Secs1Message.js.map +1 -1
  46. package/lib/secs1/Secs1MessageBlock.js.map +1 -1
  47. package/lib/secs1/Secs1OnTcpIpActiveCommunicator.d.ts.map +1 -1
  48. package/lib/secs1/Secs1OnTcpIpActiveCommunicator.js +13 -2
  49. package/lib/secs1/Secs1OnTcpIpActiveCommunicator.js.map +1 -1
  50. package/lib/secs1/Secs1OnTcpIpPassiveCommunicator.d.ts.map +1 -1
  51. package/lib/secs1/Secs1OnTcpIpPassiveCommunicator.js +10 -2
  52. package/lib/secs1/Secs1OnTcpIpPassiveCommunicator.js.map +1 -1
  53. package/lib/secs1/Secs1SerialCommunicator.js.map +1 -1
  54. package/lib/sml/SmlParser.js.map +1 -1
  55. package/package.json +16 -2
@@ -0,0 +1,36 @@
1
+ import { LevelWithSilent, Logger } from "pino";
2
+
3
+ //#region src/logging/SecsLogger.d.ts
4
+ type SecsLogDirection = "Received" | "Sent";
5
+ interface SecsLoggerConfig {
6
+ enabled?: boolean;
7
+ console?: boolean;
8
+ baseDir?: string;
9
+ retentionDays?: number;
10
+ detailLevel?: LevelWithSilent;
11
+ secs2Level?: LevelWithSilent;
12
+ maxHexBytes?: number;
13
+ }
14
+ interface SecsLoggerContext {
15
+ name: string;
16
+ deviceId: number;
17
+ isEquip: boolean;
18
+ }
19
+ declare class SecsLogger {
20
+ static disabled(): SecsLogger;
21
+ static create(config: SecsLoggerConfig | undefined, ctx: SecsLoggerContext): SecsLogger;
22
+ readonly detail: Logger;
23
+ private readonly secs2;
24
+ private readonly detailStream;
25
+ private readonly secs2Target;
26
+ private readonly secs2Stream;
27
+ private readonly maxHexBytes;
28
+ private constructor();
29
+ logSecs2(direction: SecsLogDirection, sml: string): void;
30
+ logBytes(direction: SecsLogDirection, protocol: string, buffer: Buffer, meta?: Record<string, unknown>): void;
31
+ logState(protocol: string, prev: string, next: string, meta?: Record<string, unknown>): void;
32
+ close(): void;
33
+ }
34
+ //#endregion
35
+ export { SecsLogDirection, SecsLogger, SecsLoggerConfig, SecsLoggerContext };
36
+ //# sourceMappingURL=SecsLogger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SecsLogger.d.ts","names":[],"sources":["../../src/logging/SecsLogger.ts"],"sourcesContent":[],"mappings":";;;KAKY,gBAAA;UAEK,gBAAA;EAFL,OAAA,CAAA,EAAA,OAAA;EAEK,OAAA,CAAA,EAAA,OAAA;EAUA,OAAA,CAAA,EAAA,MAAA;EAubJ,aAAU,CAAA,EAAA,MAAA;EACH,WAAA,CAAA,EA7bL,eA6bK;EAKV,UAAA,CAAA,EAjcI,eAicJ;EACH,WAAA,CAAA,EAAA,MAAA;;AA4EkB,UA1gBR,iBAAA,CA0gBQ;EAuBJ,IAAA,EAAA,MAAA;EAQR,QAAA,EAAA,MAAA;EAEH,OAAA,EAAA,OAAA;;AAmBD,cAvII,UAAA,CAuIJ;EAAM,OAAA,QAAA,CAAA,CAAA,EAtIK,UAsIL;wBAjIL,mCACH,oBACH;mBA2EqB;;;;;;;sBAuBJ;sBAQR,4CAEH,eACD;gEAkBA"}
@@ -0,0 +1,415 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { Transform, Writable } from "stream";
4
+ import pino from "pino";
5
+
6
+ //#region src/logging/SecsLogger.ts
7
+ function formatDate(date) {
8
+ const y = date.getFullYear();
9
+ const m = String(date.getMonth() + 1).padStart(2, "0");
10
+ const d = String(date.getDate()).padStart(2, "0");
11
+ return `${String(y)}-${m}-${d}`;
12
+ }
13
+ function formatDateTime(date) {
14
+ return `${formatDate(date)} ${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}:${String(date.getSeconds()).padStart(2, "0")}.${String(date.getMilliseconds()).padStart(3, "0")}`;
15
+ }
16
+ function tryParseYmdDirName(dirName) {
17
+ const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(dirName);
18
+ if (!m) return null;
19
+ const year = Number(m[1]);
20
+ const month = Number(m[2]);
21
+ const day = Number(m[3]);
22
+ if (!Number.isFinite(year) || !Number.isFinite(month) || !Number.isFinite(day)) return null;
23
+ const dt = new Date(year, month - 1, day);
24
+ if (dt.getFullYear() !== year) return null;
25
+ if (dt.getMonth() !== month - 1) return null;
26
+ if (dt.getDate() !== day) return null;
27
+ return dt;
28
+ }
29
+ function normalizeSmlForSingleLine(sml) {
30
+ return sml.trim();
31
+ }
32
+ function bufferToHex(buffer, maxHexBytes) {
33
+ const len = buffer.length;
34
+ const max = Math.max(0, maxHexBytes);
35
+ return `${(len <= max ? buffer : buffer.subarray(0, max)).toString("hex")}${len <= max ? "" : `…(+${String(len - max)} bytes)`}`;
36
+ }
37
+ var PrettyPrintTransformStream = class extends Transform {
38
+ pending = "";
39
+ constructor() {
40
+ super();
41
+ }
42
+ _transform(chunk, _encoding, callback) {
43
+ try {
44
+ const str = typeof chunk === "string" ? chunk : chunk.toString("utf8");
45
+ this.pending += str;
46
+ this.flush();
47
+ callback();
48
+ } catch (e) {
49
+ callback(e instanceof Error ? e : new Error(String(e)));
50
+ }
51
+ }
52
+ _flush(callback) {
53
+ callback();
54
+ }
55
+ flush() {
56
+ while (true) {
57
+ const idx = this.pending.indexOf("\n");
58
+ if (idx < 0) break;
59
+ const line = this.pending.slice(0, idx);
60
+ this.pending = this.pending.slice(idx + 1);
61
+ if (line.length === 0) continue;
62
+ const obj = JSON.parse(line);
63
+ const formatted = this.formatLine(obj);
64
+ this.push(formatted);
65
+ }
66
+ }
67
+ formatLine(obj) {
68
+ return `${this.formatTime(obj.time)} ${this.formatLevel(obj.level)} ${this.formatExtra(obj)} | ${this.formatMessage(obj)}\n`;
69
+ }
70
+ formatTime(timeValue) {
71
+ if (typeof timeValue === "number") return formatDateTime(new Date(timeValue));
72
+ if (typeof timeValue === "string") return formatDateTime(new Date(timeValue));
73
+ return formatDateTime(/* @__PURE__ */ new Date());
74
+ }
75
+ formatLevel(level) {
76
+ return {
77
+ 10: "TRACE",
78
+ 20: "DEBUG",
79
+ 30: "INFO ",
80
+ 40: "WARN ",
81
+ 50: "ERROR",
82
+ 60: "FATAL"
83
+ }[level] ?? "UNKNOWN";
84
+ }
85
+ formatExtra(obj) {
86
+ const parts = [];
87
+ if (typeof obj.protocol === "string") parts.push(obj.protocol);
88
+ if (typeof obj.dir === "string") parts.push(obj.dir);
89
+ if (typeof obj.prev === "string" && typeof obj.next === "string") parts.push(`${obj.prev} -> ${obj.next}`);
90
+ return parts.join(" ");
91
+ }
92
+ formatMessage(obj) {
93
+ const msgValue = obj.msg;
94
+ if (typeof msgValue === "string" && msgValue.trim().length > 0) return msgValue;
95
+ const excludeKeys = new Set([
96
+ "time",
97
+ "level",
98
+ "msg",
99
+ "name",
100
+ "deviceId",
101
+ "isEquip",
102
+ "protocol",
103
+ "dir",
104
+ "prev",
105
+ "next"
106
+ ]);
107
+ const pairs = [];
108
+ for (const [key, value] of Object.entries(obj)) {
109
+ if (excludeKeys.has(key)) continue;
110
+ if (Buffer.isBuffer(value)) pairs.push(`${key}=${value.toString("hex")}`);
111
+ else if (typeof value === "string") pairs.push(`${key}=${value}`);
112
+ else if (typeof value === "number" || typeof value === "boolean") pairs.push(`${key}=${String(value)}`);
113
+ else pairs.push(`${key}=${this.formatValue(value)}`);
114
+ }
115
+ return pairs.join(" ");
116
+ }
117
+ formatValue(value) {
118
+ if (value === null) return "null";
119
+ if (value === void 0) return "undefined";
120
+ if (typeof value === "string") return value;
121
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
122
+ if (Buffer.isBuffer(value)) return value.toString("hex");
123
+ if (typeof value === "object") try {
124
+ return JSON.stringify(value);
125
+ } catch {
126
+ return "[object]";
127
+ }
128
+ return String(value);
129
+ }
130
+ };
131
+ var DailyRotatingFileStream = class extends Writable {
132
+ baseDir;
133
+ fileNameForDate;
134
+ retentionDays;
135
+ currentYmd = null;
136
+ currentStream = null;
137
+ cleanupYmd = null;
138
+ pending = "";
139
+ constructor(params) {
140
+ super();
141
+ this.baseDir = params.baseDir;
142
+ this.fileNameForDate = params.fileNameForDate;
143
+ this.retentionDays = params.retentionDays;
144
+ }
145
+ _write(chunk, encoding, callback) {
146
+ try {
147
+ const str = typeof chunk === "string" ? chunk : chunk.toString("utf8");
148
+ this.pending += str;
149
+ this.flushCompleteLines();
150
+ callback();
151
+ } catch (e) {
152
+ callback(e instanceof Error ? e : new Error(String(e)));
153
+ }
154
+ }
155
+ _final(callback) {
156
+ try {
157
+ if (this.pending.length > 0) {
158
+ this.ensureStreamForNow();
159
+ this.currentStream?.write(this.pending);
160
+ this.pending = "";
161
+ }
162
+ this.currentStream?.end(() => callback());
163
+ this.currentStream = null;
164
+ } catch (e) {
165
+ callback(e instanceof Error ? e : new Error(String(e)));
166
+ }
167
+ }
168
+ flushCompleteLines() {
169
+ while (true) {
170
+ const idx = this.pending.indexOf("\n");
171
+ if (idx < 0) break;
172
+ const line = this.pending.slice(0, idx + 1);
173
+ this.pending = this.pending.slice(idx + 1);
174
+ this.ensureStreamForNow();
175
+ this.currentStream?.write(line);
176
+ }
177
+ }
178
+ ensureStreamForNow() {
179
+ const now = /* @__PURE__ */ new Date();
180
+ const ymd = formatDate(now);
181
+ if (this.currentYmd === ymd && this.currentStream) return;
182
+ if (this.currentStream) {
183
+ this.currentStream.end();
184
+ this.currentStream = null;
185
+ }
186
+ const dir = path.join(this.baseDir, ymd);
187
+ fs.mkdirSync(dir, { recursive: true });
188
+ const filePath = path.join(dir, this.fileNameForDate(ymd));
189
+ this.currentStream = fs.createWriteStream(filePath, { flags: "a" });
190
+ this.currentYmd = ymd;
191
+ if (this.retentionDays > 0 && this.cleanupYmd !== ymd) {
192
+ this.cleanupYmd = ymd;
193
+ queueMicrotask(() => {
194
+ this.cleanupOldDirs(now).catch(() => void 0);
195
+ });
196
+ }
197
+ }
198
+ async cleanupOldDirs(now) {
199
+ const retentionDays = this.retentionDays;
200
+ if (retentionDays <= 0) return;
201
+ let entries;
202
+ try {
203
+ entries = await fs.promises.readdir(this.baseDir, { withFileTypes: true });
204
+ } catch {
205
+ return;
206
+ }
207
+ const cutoff = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0);
208
+ cutoff.setDate(cutoff.getDate() - retentionDays);
209
+ for (const ent of entries) {
210
+ if (!ent.isDirectory()) continue;
211
+ const dirName = ent.name;
212
+ const dirDate = tryParseYmdDirName(dirName);
213
+ if (!dirDate) continue;
214
+ if (dirDate >= cutoff) continue;
215
+ const full = path.join(this.baseDir, dirName);
216
+ try {
217
+ await fs.promises.rm(full, {
218
+ recursive: true,
219
+ force: true
220
+ });
221
+ } catch {
222
+ continue;
223
+ }
224
+ }
225
+ }
226
+ };
227
+ var Secs2LineTransformStream = class extends Writable {
228
+ target;
229
+ pending = "";
230
+ constructor(target) {
231
+ super();
232
+ this.target = target;
233
+ }
234
+ _write(chunk, encoding, callback) {
235
+ try {
236
+ const str = typeof chunk === "string" ? chunk : chunk.toString("utf8");
237
+ this.pending += str;
238
+ this.flush();
239
+ callback();
240
+ } catch (e) {
241
+ callback(e instanceof Error ? e : new Error(String(e)));
242
+ }
243
+ }
244
+ _final(callback) {
245
+ try {
246
+ this.flush(true);
247
+ this.target.end(() => callback());
248
+ } catch (e) {
249
+ callback(e instanceof Error ? e : new Error(String(e)));
250
+ }
251
+ }
252
+ flush(flushAll = false) {
253
+ while (true) {
254
+ const idx = this.pending.indexOf("\n");
255
+ if (idx < 0) {
256
+ if (flushAll && this.pending.length > 0) {
257
+ this.handleLine(this.pending);
258
+ this.pending = "";
259
+ }
260
+ return;
261
+ }
262
+ const line = this.pending.slice(0, idx);
263
+ this.pending = this.pending.slice(idx + 1);
264
+ if (line.length === 0) continue;
265
+ this.handleLine(line);
266
+ }
267
+ }
268
+ handleLine(jsonLine) {
269
+ let obj;
270
+ try {
271
+ obj = JSON.parse(jsonLine);
272
+ } catch {
273
+ return;
274
+ }
275
+ if (!obj || typeof obj !== "object") return;
276
+ const rec = obj;
277
+ const timeValue = rec.time;
278
+ const dirValue = rec.dir;
279
+ const smlValue = rec.sml;
280
+ const dir = dirValue === "Sent" || dirValue === "Received" ? dirValue : null;
281
+ const sml = typeof smlValue === "string" ? smlValue : null;
282
+ if (!dir || !sml) return;
283
+ let date;
284
+ if (typeof timeValue === "number") date = new Date(timeValue);
285
+ else if (typeof timeValue === "string") date = new Date(timeValue);
286
+ else date = /* @__PURE__ */ new Date();
287
+ const out = `${formatDateTime(date)} ${dir} \n${normalizeSmlForSingleLine(sml)}\n`;
288
+ this.target.write(out);
289
+ }
290
+ };
291
+ var DisabledSecsLogger = class {
292
+ detail;
293
+ secs2;
294
+ constructor() {
295
+ this.detail = pino({ enabled: false });
296
+ this.secs2 = pino({ enabled: false });
297
+ }
298
+ logSecs2(_direction, _sml) {}
299
+ logBytes(_direction, _protocol, _buffer, _meta) {}
300
+ logState(_protocol, _prev, _next, _meta) {}
301
+ close() {}
302
+ };
303
+ var SecsLogger = class SecsLogger {
304
+ static disabled() {
305
+ return new DisabledSecsLogger();
306
+ }
307
+ static create(config, ctx) {
308
+ const enabled = config?.enabled ?? false;
309
+ const consoleEnabled = config?.console ?? false;
310
+ if (!enabled) return SecsLogger.disabled();
311
+ const baseDir = config?.baseDir ? path.resolve(config.baseDir) : path.resolve(process.cwd(), "logs");
312
+ const retentionDays = config?.retentionDays ?? 7;
313
+ const detailLevel = config?.detailLevel ?? "debug";
314
+ const secs2Level = config?.secs2Level ?? "info";
315
+ const detailStream = new DailyRotatingFileStream({
316
+ baseDir,
317
+ fileNameForDate: (ymd) => `${ymd}-DETAIL.log`,
318
+ retentionDays
319
+ });
320
+ const secs2Target = new DailyRotatingFileStream({
321
+ baseDir,
322
+ fileNameForDate: (ymd) => `${ymd}-SECS-II.log`,
323
+ retentionDays
324
+ });
325
+ const secs2Stream = new Secs2LineTransformStream(secs2Target);
326
+ const bindings = {
327
+ name: ctx.name,
328
+ deviceId: ctx.deviceId,
329
+ isEquip: ctx.isEquip
330
+ };
331
+ const detailStreams = [{ stream: detailStream }];
332
+ if (consoleEnabled) {
333
+ const prettyStream = new PrettyPrintTransformStream();
334
+ prettyStream.pipe(process.stdout);
335
+ detailStreams.push({
336
+ stream: prettyStream,
337
+ level: detailLevel
338
+ });
339
+ }
340
+ const detail = pino({
341
+ level: detailLevel,
342
+ base: bindings
343
+ }, pino.multistream(detailStreams));
344
+ const secs2Streams = [{ stream: secs2Stream }];
345
+ if (consoleEnabled) secs2Streams.push({
346
+ stream: process.stdout,
347
+ level: secs2Level
348
+ });
349
+ const secs2 = pino({
350
+ level: secs2Level,
351
+ base: null,
352
+ messageKey: "msg"
353
+ }, pino.multistream(secs2Streams));
354
+ return new SecsLogger({
355
+ config: {
356
+ ...config,
357
+ baseDir,
358
+ retentionDays
359
+ },
360
+ detail,
361
+ secs2,
362
+ detailStream,
363
+ secs2Target,
364
+ secs2Stream
365
+ });
366
+ }
367
+ detail;
368
+ secs2;
369
+ detailStream;
370
+ secs2Target;
371
+ secs2Stream;
372
+ maxHexBytes;
373
+ constructor(params) {
374
+ this.detail = params.detail;
375
+ this.secs2 = params.secs2;
376
+ this.detailStream = params.detailStream;
377
+ this.secs2Target = params.secs2Target;
378
+ this.secs2Stream = params.secs2Stream;
379
+ this.maxHexBytes = params.config.maxHexBytes ?? 64 * 1024;
380
+ }
381
+ logSecs2(direction, sml) {
382
+ this.secs2.info({
383
+ dir: direction,
384
+ sml: normalizeSmlForSingleLine(sml)
385
+ }, "");
386
+ }
387
+ logBytes(direction, protocol, buffer, meta) {
388
+ this.detail.trace({
389
+ protocol,
390
+ dir: direction,
391
+ byteLength: buffer.length,
392
+ hex: bufferToHex(buffer, this.maxHexBytes),
393
+ ...meta
394
+ }, "bytes");
395
+ }
396
+ logState(protocol, prev, next, meta) {
397
+ this.detail.info({
398
+ protocol,
399
+ prev,
400
+ next,
401
+ ...meta
402
+ }, "state");
403
+ }
404
+ close() {
405
+ this.secs2.flush();
406
+ this.detail.flush();
407
+ this.secs2Stream.end();
408
+ this.secs2Target.end();
409
+ this.detailStream.end();
410
+ }
411
+ };
412
+
413
+ //#endregion
414
+ export { SecsLogger };
415
+ //# sourceMappingURL=SecsLogger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SecsLogger.js","names":["parts: string[]","pairs: string[]","entries: fs.Dirent[]","obj: unknown","date: Date","detailStreams: pino.StreamEntry[]","secs2Streams: pino.StreamEntry[]"],"sources":["../../src/logging/SecsLogger.ts"],"sourcesContent":["import fs from \"fs\";\nimport path from \"path\";\nimport { Writable, Transform } from \"stream\";\nimport pino, { type LevelWithSilent, type Logger } from \"pino\";\n\nexport type SecsLogDirection = \"Received\" | \"Sent\";\n\nexport interface SecsLoggerConfig {\n\tenabled?: boolean;\n\tconsole?: boolean;\n\tbaseDir?: string;\n\tretentionDays?: number;\n\tdetailLevel?: LevelWithSilent;\n\tsecs2Level?: LevelWithSilent;\n\tmaxHexBytes?: number;\n}\n\nexport interface SecsLoggerContext {\n\tname: string;\n\tdeviceId: number;\n\tisEquip: boolean;\n}\n\nfunction formatDate(date: Date): string {\n\tconst y = date.getFullYear();\n\tconst m = String(date.getMonth() + 1).padStart(2, \"0\");\n\tconst d = String(date.getDate()).padStart(2, \"0\");\n\treturn `${String(y)}-${m}-${d}`;\n}\n\nfunction formatDateTime(date: Date): string {\n\tconst ymd = formatDate(date);\n\tconst hh = String(date.getHours()).padStart(2, \"0\");\n\tconst mm = String(date.getMinutes()).padStart(2, \"0\");\n\tconst ss = String(date.getSeconds()).padStart(2, \"0\");\n\tconst ms = String(date.getMilliseconds()).padStart(3, \"0\");\n\treturn `${ymd} ${hh}:${mm}:${ss}.${ms}`;\n}\n\nfunction tryParseYmdDirName(dirName: string): Date | null {\n\tconst m = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(dirName);\n\tif (!m) return null;\n\tconst year = Number(m[1]);\n\tconst month = Number(m[2]);\n\tconst day = Number(m[3]);\n\tif (\n\t\t!Number.isFinite(year) ||\n\t\t!Number.isFinite(month) ||\n\t\t!Number.isFinite(day)\n\t)\n\t\treturn null;\n\tconst dt = new Date(year, month - 1, day);\n\tif (dt.getFullYear() !== year) return null;\n\tif (dt.getMonth() !== month - 1) return null;\n\tif (dt.getDate() !== day) return null;\n\treturn dt;\n}\n\nfunction normalizeSmlForSingleLine(sml: string): string {\n\treturn sml.trim();\n}\n\nfunction bufferToHex(buffer: Buffer, maxHexBytes: number): string {\n\tconst len = buffer.length;\n\tconst max = Math.max(0, maxHexBytes);\n\tconst slice = len <= max ? buffer : buffer.subarray(0, max);\n\tconst hex = slice.toString(\"hex\");\n\tconst suffix = len <= max ? \"\" : `…(+${String(len - max)} bytes)`;\n\treturn `${hex}${suffix}`;\n}\n\nclass PrettyPrintTransformStream extends Transform {\n\tprivate pending = \"\";\n\n\tconstructor() {\n\t\tsuper();\n\t}\n\n\toverride _transform(\n\t\tchunk: Buffer | string,\n\t\t_encoding: BufferEncoding,\n\t\tcallback: (error?: Error | null) => void,\n\t): void {\n\t\ttry {\n\t\t\tconst str = typeof chunk === \"string\" ? chunk : chunk.toString(\"utf8\");\n\t\t\tthis.pending += str;\n\t\t\tthis.flush();\n\t\t\tcallback();\n\t\t} catch (e) {\n\t\t\tcallback(e instanceof Error ? e : new Error(String(e)));\n\t\t}\n\t}\n\n\toverride _flush(callback: (error?: Error | null) => void): void {\n\t\tcallback();\n\t}\n\n\tprivate flush(): void {\n\t\twhile (true) {\n\t\t\tconst idx = this.pending.indexOf(\"\\n\");\n\t\t\tif (idx < 0) break;\n\t\t\tconst line = this.pending.slice(0, idx);\n\t\t\tthis.pending = this.pending.slice(idx + 1);\n\t\t\tif (line.length === 0) continue;\n\t\t\tconst obj = JSON.parse(line) as Record<string, unknown>;\n\t\t\tconst formatted = this.formatLine(obj);\n\t\t\tthis.push(formatted);\n\t\t}\n\t}\n\n\tprivate formatLine(obj: Record<string, unknown>): string {\n\t\tconst time = this.formatTime(obj.time);\n\t\tconst level = this.formatLevel(obj.level as number);\n\t\tconst extra = this.formatExtra(obj);\n\t\tconst msg = this.formatMessage(obj);\n\n\t\treturn `${time} ${level} ${extra} | ${msg}\\n`;\n\t}\n\n\tprivate formatTime(timeValue: unknown): string {\n\t\tif (typeof timeValue === \"number\") {\n\t\t\treturn formatDateTime(new Date(timeValue));\n\t\t}\n\t\tif (typeof timeValue === \"string\") {\n\t\t\treturn formatDateTime(new Date(timeValue));\n\t\t}\n\t\treturn formatDateTime(new Date());\n\t}\n\n\tprivate formatLevel(level: number): string {\n\t\tconst levels: Record<number, string> = {\n\t\t\t10: \"TRACE\",\n\t\t\t20: \"DEBUG\",\n\t\t\t30: \"INFO \",\n\t\t\t40: \"WARN \",\n\t\t\t50: \"ERROR\",\n\t\t\t60: \"FATAL\",\n\t\t};\n\t\treturn levels[level] ?? \"UNKNOWN\";\n\t}\n\n\tprivate formatExtra(obj: Record<string, unknown>): string {\n\t\tconst parts: string[] = [];\n\n\t\tif (typeof obj.protocol === \"string\") {\n\t\t\tparts.push(obj.protocol);\n\t\t}\n\t\tif (typeof obj.dir === \"string\") {\n\t\t\tparts.push(obj.dir);\n\t\t}\n\t\tif (typeof obj.prev === \"string\" && typeof obj.next === \"string\") {\n\t\t\tparts.push(`${obj.prev} -> ${obj.next}`);\n\t\t}\n\n\t\treturn parts.join(\" \");\n\t}\n\n\tprivate formatMessage(obj: Record<string, unknown>): string {\n\t\tconst msgValue = obj.msg;\n\t\tif (typeof msgValue === \"string\" && msgValue.trim().length > 0) {\n\t\t\treturn msgValue;\n\t\t}\n\n\t\tconst excludeKeys = new Set([\n\t\t\t\"time\",\n\t\t\t\"level\",\n\t\t\t\"msg\",\n\t\t\t\"name\",\n\t\t\t\"deviceId\",\n\t\t\t\"isEquip\",\n\t\t\t\"protocol\",\n\t\t\t\"dir\",\n\t\t\t\"prev\",\n\t\t\t\"next\",\n\t\t]);\n\n\t\tconst pairs: string[] = [];\n\t\tfor (const [key, value] of Object.entries(obj)) {\n\t\t\tif (excludeKeys.has(key)) continue;\n\t\t\tif (Buffer.isBuffer(value)) {\n\t\t\t\tpairs.push(`${key}=${value.toString(\"hex\")}`);\n\t\t\t} else if (typeof value === \"string\") {\n\t\t\t\tpairs.push(`${key}=${value}`);\n\t\t\t} else if (typeof value === \"number\" || typeof value === \"boolean\") {\n\t\t\t\tpairs.push(`${key}=${String(value)}`);\n\t\t\t} else {\n\t\t\t\tpairs.push(`${key}=${this.formatValue(value)}`);\n\t\t\t}\n\t\t}\n\n\t\treturn pairs.join(\" \");\n\t}\n\n\tprivate formatValue(value: unknown): string {\n\t\tif (value === null) return \"null\";\n\t\tif (value === undefined) return \"undefined\";\n\t\tif (typeof value === \"string\") return value;\n\t\tif (typeof value === \"number\" || typeof value === \"boolean\") {\n\t\t\treturn String(value);\n\t\t}\n\t\tif (Buffer.isBuffer(value)) {\n\t\t\treturn value.toString(\"hex\");\n\t\t}\n\t\tif (typeof value === \"object\") {\n\t\t\ttry {\n\t\t\t\treturn JSON.stringify(value);\n\t\t\t} catch {\n\t\t\t\treturn \"[object]\";\n\t\t\t}\n\t\t}\n\t\treturn String(value as string | number | bigint | boolean);\n\t}\n}\n\nclass DailyRotatingFileStream extends Writable {\n\tprivate readonly baseDir: string;\n\tprivate readonly fileNameForDate: (ymd: string) => string;\n\tprivate readonly retentionDays: number;\n\tprivate currentYmd: string | null = null;\n\tprivate currentStream: fs.WriteStream | null = null;\n\tprivate cleanupYmd: string | null = null;\n\tprivate pending = \"\";\n\n\tconstructor(params: {\n\t\tbaseDir: string;\n\t\tfileNameForDate: (ymd: string) => string;\n\t\tretentionDays: number;\n\t}) {\n\t\tsuper();\n\t\tthis.baseDir = params.baseDir;\n\t\tthis.fileNameForDate = params.fileNameForDate;\n\t\tthis.retentionDays = params.retentionDays;\n\t}\n\n\toverride _write(\n\t\tchunk: Buffer | string,\n\t\tencoding: BufferEncoding,\n\t\tcallback: (error?: Error | null) => void,\n\t): void {\n\t\ttry {\n\t\t\tconst str = typeof chunk === \"string\" ? chunk : chunk.toString(\"utf8\");\n\t\t\tthis.pending += str;\n\t\t\tthis.flushCompleteLines();\n\t\t\tcallback();\n\t\t} catch (e) {\n\t\t\tcallback(e instanceof Error ? e : new Error(String(e)));\n\t\t}\n\t}\n\n\toverride _final(callback: (error?: Error | null) => void): void {\n\t\ttry {\n\t\t\tif (this.pending.length > 0) {\n\t\t\t\tthis.ensureStreamForNow();\n\t\t\t\tthis.currentStream?.write(this.pending);\n\t\t\t\tthis.pending = \"\";\n\t\t\t}\n\t\t\tthis.currentStream?.end(() => callback());\n\t\t\tthis.currentStream = null;\n\t\t} catch (e) {\n\t\t\tcallback(e instanceof Error ? e : new Error(String(e)));\n\t\t}\n\t}\n\n\tprivate flushCompleteLines() {\n\t\twhile (true) {\n\t\t\tconst idx = this.pending.indexOf(\"\\n\");\n\t\t\tif (idx < 0) break;\n\t\t\tconst line = this.pending.slice(0, idx + 1);\n\t\t\tthis.pending = this.pending.slice(idx + 1);\n\t\t\tthis.ensureStreamForNow();\n\t\t\tthis.currentStream?.write(line);\n\t\t}\n\t}\n\n\tprivate ensureStreamForNow() {\n\t\tconst now = new Date();\n\t\tconst ymd = formatDate(now);\n\t\tif (this.currentYmd === ymd && this.currentStream) return;\n\n\t\tif (this.currentStream) {\n\t\t\tthis.currentStream.end();\n\t\t\tthis.currentStream = null;\n\t\t}\n\n\t\tconst dir = path.join(this.baseDir, ymd);\n\t\tfs.mkdirSync(dir, { recursive: true });\n\t\tconst filePath = path.join(dir, this.fileNameForDate(ymd));\n\t\tthis.currentStream = fs.createWriteStream(filePath, { flags: \"a\" });\n\t\tthis.currentYmd = ymd;\n\n\t\tif (this.retentionDays > 0 && this.cleanupYmd !== ymd) {\n\t\t\tthis.cleanupYmd = ymd;\n\t\t\tqueueMicrotask(() => {\n\t\t\t\tthis.cleanupOldDirs(now).catch(() => undefined);\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async cleanupOldDirs(now: Date): Promise<void> {\n\t\tconst retentionDays = this.retentionDays;\n\t\tif (retentionDays <= 0) return;\n\n\t\tlet entries: fs.Dirent[];\n\t\ttry {\n\t\t\tentries = await fs.promises.readdir(this.baseDir, {\n\t\t\t\twithFileTypes: true,\n\t\t\t});\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\n\t\tconst cutoff = new Date(\n\t\t\tnow.getFullYear(),\n\t\t\tnow.getMonth(),\n\t\t\tnow.getDate(),\n\t\t\t0,\n\t\t\t0,\n\t\t\t0,\n\t\t\t0,\n\t\t);\n\t\tcutoff.setDate(cutoff.getDate() - retentionDays);\n\n\t\tfor (const ent of entries) {\n\t\t\tif (!ent.isDirectory()) continue;\n\t\t\tconst dirName = ent.name;\n\t\t\tconst dirDate = tryParseYmdDirName(dirName);\n\t\t\tif (!dirDate) continue;\n\t\t\tif (dirDate >= cutoff) continue;\n\t\t\tconst full = path.join(this.baseDir, dirName);\n\t\t\ttry {\n\t\t\t\tawait fs.promises.rm(full, { recursive: true, force: true });\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t}\n}\n\nclass Secs2LineTransformStream extends Writable {\n\tprivate readonly target: DailyRotatingFileStream;\n\tprivate pending = \"\";\n\n\tconstructor(target: DailyRotatingFileStream) {\n\t\tsuper();\n\t\tthis.target = target;\n\t}\n\n\toverride _write(\n\t\tchunk: Buffer | string,\n\t\tencoding: BufferEncoding,\n\t\tcallback: (error?: Error | null) => void,\n\t): void {\n\t\ttry {\n\t\t\tconst str = typeof chunk === \"string\" ? chunk : chunk.toString(\"utf8\");\n\t\t\tthis.pending += str;\n\t\t\tthis.flush();\n\t\t\tcallback();\n\t\t} catch (e) {\n\t\t\tcallback(e instanceof Error ? e : new Error(String(e)));\n\t\t}\n\t}\n\n\toverride _final(callback: (error?: Error | null) => void): void {\n\t\ttry {\n\t\t\tthis.flush(true);\n\t\t\tthis.target.end(() => callback());\n\t\t} catch (e) {\n\t\t\tcallback(e instanceof Error ? e : new Error(String(e)));\n\t\t}\n\t}\n\n\tprivate flush(flushAll = false) {\n\t\twhile (true) {\n\t\t\tconst idx = this.pending.indexOf(\"\\n\");\n\t\t\tif (idx < 0) {\n\t\t\t\tif (flushAll && this.pending.length > 0) {\n\t\t\t\t\tthis.handleLine(this.pending);\n\t\t\t\t\tthis.pending = \"\";\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst line = this.pending.slice(0, idx);\n\t\t\tthis.pending = this.pending.slice(idx + 1);\n\t\t\tif (line.length === 0) continue;\n\t\t\tthis.handleLine(line);\n\t\t}\n\t}\n\n\tprivate handleLine(jsonLine: string) {\n\t\tlet obj: unknown;\n\t\ttry {\n\t\t\tobj = JSON.parse(jsonLine);\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!obj || typeof obj !== \"object\") return;\n\t\tconst rec = obj as Record<string, unknown>;\n\t\tconst timeValue = rec.time;\n\t\tconst dirValue = rec.dir;\n\t\tconst smlValue = rec.sml;\n\n\t\tconst dir =\n\t\t\tdirValue === \"Sent\" || dirValue === \"Received\" ? dirValue : null;\n\t\tconst sml = typeof smlValue === \"string\" ? smlValue : null;\n\t\tif (!dir || !sml) return;\n\n\t\tlet date: Date;\n\t\tif (typeof timeValue === \"number\") {\n\t\t\tdate = new Date(timeValue);\n\t\t} else if (typeof timeValue === \"string\") {\n\t\t\tdate = new Date(timeValue);\n\t\t} else {\n\t\t\tdate = new Date();\n\t\t}\n\n\t\tconst out = `${formatDateTime(date)} ${dir} \\n${normalizeSmlForSingleLine(sml)}\\n`;\n\t\tthis.target.write(out);\n\t}\n}\n\nclass DisabledSecsLogger {\n\tdetail: Logger;\n\tsecs2: Logger;\n\tconstructor() {\n\t\tthis.detail = pino({ enabled: false });\n\t\tthis.secs2 = pino({ enabled: false });\n\t}\n\n\tlogSecs2(_direction: SecsLogDirection, _sml: string): void {\n\t\treturn;\n\t}\n\n\tlogBytes(\n\t\t_direction: SecsLogDirection,\n\t\t_protocol: string,\n\t\t_buffer: Buffer,\n\t\t_meta?: Record<string, unknown>,\n\t): void {\n\t\treturn;\n\t}\n\n\tlogState(\n\t\t_protocol: string,\n\t\t_prev: string,\n\t\t_next: string,\n\t\t_meta?: Record<string, unknown>,\n\t): void {\n\t\treturn;\n\t}\n\n\tclose(): void {\n\t\treturn;\n\t}\n}\n\nexport class SecsLogger {\n\tstatic disabled(): SecsLogger {\n\t\treturn new DisabledSecsLogger() as unknown as SecsLogger;\n\t}\n\n\tstatic create(\n\t\tconfig: SecsLoggerConfig | undefined,\n\t\tctx: SecsLoggerContext,\n\t): SecsLogger {\n\t\tconst enabled = config?.enabled ?? false;\n\t\tconst consoleEnabled = config?.console ?? false;\n\t\tif (!enabled) return SecsLogger.disabled();\n\n\t\tconst baseDir = config?.baseDir\n\t\t\t? path.resolve(config.baseDir)\n\t\t\t: path.resolve(process.cwd(), \"logs\");\n\t\tconst retentionDays = config?.retentionDays ?? 7;\n\t\tconst detailLevel = config?.detailLevel ?? \"debug\";\n\t\tconst secs2Level = config?.secs2Level ?? \"info\";\n\n\t\tconst detailStream = new DailyRotatingFileStream({\n\t\t\tbaseDir,\n\t\t\tfileNameForDate: (ymd) => `${ymd}-DETAIL.log`,\n\t\t\tretentionDays,\n\t\t});\n\n\t\tconst secs2Target = new DailyRotatingFileStream({\n\t\t\tbaseDir,\n\t\t\tfileNameForDate: (ymd) => `${ymd}-SECS-II.log`,\n\t\t\tretentionDays,\n\t\t});\n\t\tconst secs2Stream = new Secs2LineTransformStream(secs2Target);\n\n\t\tconst bindings = {\n\t\t\tname: ctx.name,\n\t\t\tdeviceId: ctx.deviceId,\n\t\t\tisEquip: ctx.isEquip,\n\t\t};\n\n\t\tconst detailStreams: pino.StreamEntry[] = [\n\t\t\t{ stream: detailStream as pino.DestinationStream },\n\t\t];\n\t\tif (consoleEnabled) {\n\t\t\tconst prettyStream = new PrettyPrintTransformStream();\n\t\t\tprettyStream.pipe(process.stdout);\n\t\t\tdetailStreams.push({\n\t\t\t\tstream: prettyStream,\n\t\t\t\tlevel: detailLevel as pino.Level,\n\t\t\t});\n\t\t}\n\t\tconst detail = pino(\n\t\t\t{ level: detailLevel, base: bindings },\n\t\t\tpino.multistream(detailStreams),\n\t\t);\n\n\t\tconst secs2Streams: pino.StreamEntry[] = [\n\t\t\t{ stream: secs2Stream as pino.DestinationStream },\n\t\t];\n\t\tif (consoleEnabled) {\n\t\t\tsecs2Streams.push({\n\t\t\t\tstream: process.stdout,\n\t\t\t\tlevel: secs2Level as pino.Level,\n\t\t\t});\n\t\t}\n\t\tconst secs2 = pino(\n\t\t\t{\n\t\t\t\tlevel: secs2Level,\n\t\t\t\tbase: null,\n\t\t\t\tmessageKey: \"msg\",\n\t\t\t},\n\t\t\tpino.multistream(secs2Streams),\n\t\t);\n\n\t\treturn new SecsLogger({\n\t\t\tconfig: { ...config, baseDir, retentionDays },\n\t\t\tdetail,\n\t\t\tsecs2,\n\t\t\tdetailStream,\n\t\t\tsecs2Target,\n\t\t\tsecs2Stream,\n\t\t});\n\t}\n\n\tpublic readonly detail: Logger;\n\tprivate readonly secs2: Logger;\n\tprivate readonly detailStream: DailyRotatingFileStream;\n\tprivate readonly secs2Target: DailyRotatingFileStream;\n\tprivate readonly secs2Stream: Secs2LineTransformStream;\n\tprivate readonly maxHexBytes: number;\n\n\tprivate constructor(params: {\n\t\tconfig: SecsLoggerConfig;\n\t\tdetail: Logger;\n\t\tsecs2: Logger;\n\t\tdetailStream: DailyRotatingFileStream;\n\t\tsecs2Target: DailyRotatingFileStream;\n\t\tsecs2Stream: Secs2LineTransformStream;\n\t}) {\n\t\tthis.detail = params.detail;\n\t\tthis.secs2 = params.secs2;\n\t\tthis.detailStream = params.detailStream;\n\t\tthis.secs2Target = params.secs2Target;\n\t\tthis.secs2Stream = params.secs2Stream;\n\t\tthis.maxHexBytes = params.config.maxHexBytes ?? 64 * 1024;\n\t}\n\n\tlogSecs2(direction: SecsLogDirection, sml: string): void {\n\t\tthis.secs2.info(\n\t\t\t{ dir: direction, sml: normalizeSmlForSingleLine(sml) },\n\t\t\t\"\",\n\t\t);\n\t}\n\n\tlogBytes(\n\t\tdirection: SecsLogDirection,\n\t\tprotocol: string,\n\t\tbuffer: Buffer,\n\t\tmeta?: Record<string, unknown>,\n\t): void {\n\t\tthis.detail.trace(\n\t\t\t{\n\t\t\t\tprotocol,\n\t\t\t\tdir: direction,\n\t\t\t\tbyteLength: buffer.length,\n\t\t\t\thex: bufferToHex(buffer, this.maxHexBytes),\n\t\t\t\t...meta,\n\t\t\t},\n\t\t\t\"bytes\",\n\t\t);\n\t}\n\n\tlogState(\n\t\tprotocol: string,\n\t\tprev: string,\n\t\tnext: string,\n\t\tmeta?: Record<string, unknown>,\n\t): void {\n\t\tthis.detail.info({ protocol, prev, next, ...meta }, \"state\");\n\t}\n\n\tclose(): void {\n\t\tthis.secs2.flush();\n\t\tthis.detail.flush();\n\t\tthis.secs2Stream.end();\n\t\tthis.secs2Target.end();\n\t\tthis.detailStream.end();\n\t}\n}\n"],"mappings":"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"}
@@ -27,6 +27,7 @@ declare abstract class Secs1Communicator extends AbstractSecsCommunicator {
27
27
  constructor(config: Secs1CommunicatorConfig);
28
28
  protected attachStream(stream: Duplex): void;
29
29
  protected stop(): void;
30
+ protected sendBufferWithLogs(direction: "Sent" | "Received", protocol: string, buffer: Buffer, meta?: Record<string, unknown>): Promise<void>;
30
31
  protected sendBuffer(buffer: Buffer): Promise<void>;
31
32
  protected createMessage(stream: number, func: number, wBit: boolean, body: AbstractSecs2Item | null, systemBytes: number): SecsMessage;
32
33
  private clearT1;
@@ -1 +1 @@
1
- {"version":3,"file":"Secs1Communicator.d.ts","names":[],"sources":["../../src/secs1/Secs1Communicator.ts"],"sourcesContent":[],"mappings":";;;;;;UAUiB,uBAAA,SAAgC;;EAAhC,QAAA,CAAA,EAAA,OAAA;AAkBjB;AAImB,uBAJG,iBAAA,SAA0B,wBAAA,CAI7B;EAkBE,KAAA,EAAA,MAAA;EAMW,QAAA,EAAA,OAAA;EA0CO,UAAA,MAAA,EAlEpB,MAkEoB,GAAA,IAAA;EAAS,QAAA,KAAA;EAUxC,QAAA,MAAA;EAEJ,QAAA,SAAA;EAlF4C,QAAA,aAAA;EAAwB,QAAA,iBAAA;;;;;;;;sBAsBnD;iCAMW;;+BA0CO,SAAS;6EAUxC,gDAEJ"}
1
+ {"version":3,"file":"Secs1Communicator.d.ts","names":[],"sources":["../../src/secs1/Secs1Communicator.ts"],"sourcesContent":[],"mappings":";;;;;;UAUiB,uBAAA,SAAgC;;EAAhC,QAAA,CAAA,EAAA,OAAA;AAkBjB;AAImB,uBAJG,iBAAA,SAA0B,wBAAA,CAI7B;EAkBE,KAAA,EAAA,MAAA;EAMW,QAAA,EAAA,OAAA;EAkDtB,UAAA,MAAA,EA1ES,MA0ET,GAAA,IAAA;EACD,QAAA,KAAA;EACL,QAAA,MAAA;EAYmC,QAAA,SAAA;EAAS,QAAA,aAAA;EAUxC,QAAA,iBAAA;EAEJ,QAAA,UAAA;EAxG4C,QAAA,cAAA;EAAwB,QAAA,gBAAA;;;;;sBAsBnD;iCAMW;;yFAkDtB,eACD,0BACL;+BAYmC,SAAS;6EAUxC,gDAEJ"}