secs4js 0.4.1 → 0.4.2
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/LICENSE.md +20 -20
- package/lib/core/AbstractSecsMessage.js.map +1 -1
- package/lib/core/enums/HsmsSsControlType.js.map +1 -1
- package/lib/core/enums/RejectReason.js.map +1 -1
- package/lib/core/enums/SecsItemType.js.map +1 -1
- package/lib/core/enums/SelectStatus.js.map +1 -1
- package/lib/core/secs2item/AbstractSecs2Item.js.map +1 -1
- package/lib/core/secs2item/Secs2ItemAscii.js.map +1 -1
- package/lib/core/secs2item/Secs2ItemBinary.js.map +1 -1
- package/lib/core/secs2item/Secs2ItemBoolean.js.map +1 -1
- package/lib/core/secs2item/Secs2ItemFactory.js.map +1 -1
- package/lib/core/secs2item/Secs2ItemList.js.map +1 -1
- package/lib/core/secs2item/Secs2ItemNumeric.js.map +1 -1
- package/lib/core/secs2item/Secs2ItemParser.js.map +1 -1
- package/lib/gem/Clock.js.map +1 -1
- package/lib/gem/Gem.js.map +1 -1
- package/lib/helper/Secs2ItemHelper.js.map +1 -1
- package/lib/hsms/HsmsMessage.js.map +1 -1
- package/lib/hsms/HsmsPassiveCommunicator.js.map +1 -1
- package/lib/hsms/enums/HsmsControlType.js.map +1 -1
- package/lib/hsms/enums/RejectReason.js.map +1 -1
- package/lib/hsms/enums/SelectStatus.js.map +1 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.js +2 -1
- package/lib/secs1/Secs1Message.js.map +1 -1
- package/lib/secs1/Secs1MessageBlock.js.map +1 -1
- package/lib/secs1/Secs1SerialCommunicator.js.map +1 -1
- package/lib/sml/SmlParser.js.map +1 -1
- package/package.json +1 -1
package/LICENSE.md
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
# MIT License
|
|
2
|
-
|
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
-
a copy of this software and associated documentation files (the
|
|
5
|
-
'Software'), to deal in the Software without restriction, including
|
|
6
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
-
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
-
the following conditions:
|
|
10
|
-
|
|
11
|
-
The above copyright notice and this permission notice shall be
|
|
12
|
-
included in all copies or substantial portions of the Software.
|
|
13
|
-
|
|
14
|
-
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
17
|
-
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
18
|
-
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
19
|
-
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
20
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
'Software'), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
17
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
18
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
19
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
20
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AbstractSecsMessage.js","names":["stream: number","func: number","wBit: boolean","body: AbstractSecs2Item | null"],"sources":["../../src/core/AbstractSecsMessage.ts"],"sourcesContent":["import { AbstractSecs2Item } from \"./secs2item/AbstractSecs2Item.js\";\
|
|
1
|
+
{"version":3,"file":"AbstractSecsMessage.js","names":["stream: number","func: number","wBit: boolean","body: AbstractSecs2Item | null"],"sources":["../../src/core/AbstractSecsMessage.ts"],"sourcesContent":["import { AbstractSecs2Item } from \"./secs2item/AbstractSecs2Item.js\";\n\n/**\n * @param stream The stream number.\n * @param func The function number.\n * @param wBit Whether the message is a request.\n * @param body The body of the message.\n * @param systemBytes The system bytes.\n * @param deviceId The device ID.\n */\nexport class SecsMessage {\n\tconstructor(\n\t\tpublic readonly stream: number,\n\t\tpublic readonly func: number,\n\t\tpublic readonly wBit: boolean,\n\t\tpublic readonly body: AbstractSecs2Item | null = null,\n\t\tpublic readonly systemBytes = 0, // Typically 4 bytes, treated as integer for convenience if it fits, or Buffer\n\t\tpublic readonly deviceId = 0,\n\t) {\n\t\tif (stream < 0 || stream > 127) throw new Error(\"Stream must be 0-127\");\n\t\tif (func < 0 || func > 255) throw new Error(\"Function must be 0-255\");\n\t}\n\n\t/**\n\t * @description Returns the SML representation of the message.\n\t * @returns The SML representation.\n\t */\n\ttoSml(): string {\n\t\tconst wBitStr = this.wBit ? \"W\" : \"\";\n\t\tconst header = `S${this.stream.toString()}F${this.func.toString()} ${wBitStr}`;\n\t\tif (this.body) {\n\t\t\treturn `${header}\\n${this.body.toSml()}.`;\n\t\t}\n\t\treturn `${header}.`;\n\t}\n\n\t/**\n\t * @description Returns the binary representation of the message.\n\t * @returns The binary representation.\n\t */\n\ttoBuffer(): Buffer {\n\t\tconst header = Buffer.from([\n\t\t\t0x02, // SML header\n\t\t\tthis.stream,\n\t\t\tthis.func,\n\t\t\tthis.wBit ? 0x80 : 0x00,\n\t\t]);\n\t\tconst body = this.body?.toBuffer() ?? Buffer.alloc(0);\n\t\tconst systemBytes =\n\t\t\ttypeof this.systemBytes === \"number\"\n\t\t\t\t? Buffer.from([\n\t\t\t\t\t\tthis.systemBytes >>> 24,\n\t\t\t\t\t\t(this.systemBytes >>> 16) & 0xff,\n\t\t\t\t\t\t(this.systemBytes >>> 8) & 0xff,\n\t\t\t\t\t\tthis.systemBytes & 0xff,\n\t\t\t\t\t])\n\t\t\t\t: this.systemBytes;\n\t\tconst deviceId = Buffer.from([\n\t\t\tthis.deviceId >>> 24,\n\t\t\t(this.deviceId >>> 16) & 0xff,\n\t\t\t(this.deviceId >>> 8) & 0xff,\n\t\t\tthis.deviceId & 0xff,\n\t\t]);\n\t\treturn Buffer.concat([header, systemBytes, deviceId, body]);\n\t}\n}\n"],"mappings":";;;;;;;;;AAUA,IAAa,cAAb,MAAyB;CACxB,YACC,AAAgBA,QAChB,AAAgBC,MAChB,AAAgBC,MAChB,AAAgBC,OAAiC,MACjD,AAAgB,cAAc,GAC9B,AAAgB,WAAW,GAC1B;EANe;EACA;EACA;EACA;EACA;EACA;AAEhB,MAAI,SAAS,KAAK,SAAS,IAAK,OAAM,IAAI,MAAM,uBAAuB;AACvE,MAAI,OAAO,KAAK,OAAO,IAAK,OAAM,IAAI,MAAM,yBAAyB;;;;;;CAOtE,QAAgB;EACf,MAAM,UAAU,KAAK,OAAO,MAAM;EAClC,MAAM,SAAS,IAAI,KAAK,OAAO,UAAU,CAAC,GAAG,KAAK,KAAK,UAAU,CAAC,GAAG;AACrE,MAAI,KAAK,KACR,QAAO,GAAG,OAAO,IAAI,KAAK,KAAK,OAAO,CAAC;AAExC,SAAO,GAAG,OAAO;;;;;;CAOlB,WAAmB;EAClB,MAAM,SAAS,OAAO,KAAK;GAC1B;GACA,KAAK;GACL,KAAK;GACL,KAAK,OAAO,MAAO;GACnB,CAAC;EACF,MAAM,OAAO,KAAK,MAAM,UAAU,IAAI,OAAO,MAAM,EAAE;EACrD,MAAM,cACL,OAAO,KAAK,gBAAgB,WACzB,OAAO,KAAK;GACZ,KAAK,gBAAgB;GACpB,KAAK,gBAAgB,KAAM;GAC3B,KAAK,gBAAgB,IAAK;GAC3B,KAAK,cAAc;GACnB,CAAC,GACD,KAAK;EACT,MAAM,WAAW,OAAO,KAAK;GAC5B,KAAK,aAAa;GACjB,KAAK,aAAa,KAAM;GACxB,KAAK,aAAa,IAAK;GACxB,KAAK,WAAW;GAChB,CAAC;AACF,SAAO,OAAO,OAAO;GAAC;GAAQ;GAAa;GAAU;GAAK,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HsmsSsControlType.js","names":[],"sources":["../../../src/core/enums/HsmsSsControlType.ts"],"sourcesContent":["/**\
|
|
1
|
+
{"version":3,"file":"HsmsSsControlType.js","names":[],"sources":["../../../src/core/enums/HsmsSsControlType.ts"],"sourcesContent":["/**\n * HSMS-SS 控制类型(PType + SType 组合)\n * 存储在 Header 的 Byte 4-5\n */\nexport class HsmsSsControlType {\n\t// 只读实例属性\n\treadonly PType: number;\n\treadonly SType: number;\n\n\t// 私有构造函数,防止外部直接实例化\n\tprivate constructor(pType: number, sType: number) {\n\t\tthis.PType = pType;\n\t\tthis.SType = sType;\n\t}\n\n\t// ========== 静态只读实例 ==========\n\n\t// 未定义类型\n\tstatic readonly Undefined = new HsmsSsControlType(0xff, 0xff);\n\n\t// 数据消息(携带 SECS-II 数据)\n\tstatic readonly Data = new HsmsSsControlType(0x00, 0x00);\n\n\t// 连接控制消息\n\tstatic readonly SelectReq = new HsmsSsControlType(0x00, 0x01);\n\tstatic readonly SelectRsp = new HsmsSsControlType(0x00, 0x02);\n\tstatic readonly DeselectReq = new HsmsSsControlType(0x00, 0x03);\n\tstatic readonly DeselectRsp = new HsmsSsControlType(0x00, 0x04);\n\n\t// 链路测试消息\n\tstatic readonly LinktestReq = new HsmsSsControlType(0x00, 0x05);\n\tstatic readonly LinktestRsp = new HsmsSsControlType(0x00, 0x06);\n\n\t// 拒绝消息\n\tstatic readonly RejectReq = new HsmsSsControlType(0x00, 0x07);\n\n\t// 分离请求\n\tstatic readonly SeparateReq = new HsmsSsControlType(0x00, 0x09);\n\n\t// 私有已知类型数组\n\tprivate static readonly KnownTypes: HsmsSsControlType[] = [\n\t\tHsmsSsControlType.Data,\n\t\tHsmsSsControlType.SelectReq,\n\t\tHsmsSsControlType.SelectRsp,\n\t\tHsmsSsControlType.DeselectReq,\n\t\tHsmsSsControlType.DeselectRsp,\n\t\tHsmsSsControlType.LinktestReq,\n\t\tHsmsSsControlType.LinktestRsp,\n\t\tHsmsSsControlType.RejectReq,\n\t\tHsmsSsControlType.SeparateReq,\n\t];\n\n\t// ========== 静态工厂方法 ==========\n\n\t/**\n\t * 从字节解析控制类型\n\t */\n\tstatic fromBytes(pType: number, sType: number): HsmsSsControlType {\n\t\tfor (const known of HsmsSsControlType.KnownTypes) {\n\t\t\tif (known.PType === pType && known.SType === sType) {\n\t\t\t\treturn known;\n\t\t\t}\n\t\t}\n\t\treturn HsmsSsControlType.Undefined;\n\t}\n\n\t/**\n\t * 从 Header Bytes 4-5 解析\n\t */\n\tstatic fromHeaderBytes(\n\t\theaderBytes: Uint8Array | number[],\n\t): HsmsSsControlType {\n\t\treturn HsmsSsControlType.fromBytes(headerBytes[4], headerBytes[5]);\n\t}\n\n\t// ========== 实例方法 ==========\n\n\t/**\n\t * 判断是否为数据消息\n\t */\n\tget isDataMessage(): boolean {\n\t\treturn this === HsmsSsControlType.Data;\n\t}\n\n\t/**\n\t * 判断是否为控制消息\n\t */\n\tget isControlMessage(): boolean {\n\t\treturn !this.isDataMessage && this !== HsmsSsControlType.Undefined;\n\t}\n\n\tget isSelectRequest(): boolean {\n\t\treturn this === HsmsSsControlType.SelectReq;\n\t}\n\n\tget isSelectResponse(): boolean {\n\t\treturn this === HsmsSsControlType.SelectRsp;\n\t}\n\n\tget isLinktestRequest(): boolean {\n\t\treturn this === HsmsSsControlType.LinktestReq;\n\t}\n\n\tget isRejectRequest(): boolean {\n\t\treturn this === HsmsSsControlType.RejectReq;\n\t}\n\n\t/**\n\t * 字符串表示\n\t */\n\ttoString(): string {\n\t\tif (this === HsmsSsControlType.Data) return \"DATA\";\n\t\tif (this === HsmsSsControlType.SelectReq) return \"SELECT.req\";\n\t\tif (this === HsmsSsControlType.SelectRsp) return \"SELECT.rsp\";\n\t\tif (this === HsmsSsControlType.DeselectReq) return \"DESELECT.req\";\n\t\tif (this === HsmsSsControlType.DeselectRsp) return \"DESELECT.rsp\";\n\t\tif (this === HsmsSsControlType.LinktestReq) return \"LINKTEST.req\";\n\t\tif (this === HsmsSsControlType.LinktestRsp) return \"LINKTEST.rsp\";\n\t\tif (this === HsmsSsControlType.RejectReq) return \"REJECT.req\";\n\t\tif (this === HsmsSsControlType.SeparateReq) return \"SEPARATE.req\";\n\t\treturn `Unknown(${this.PType.toString(16).toUpperCase()},${this.SType.toString(16).toUpperCase()})`;\n\t}\n\n\t// ========== 值相等性比较 ==========\n\n\t/**\n\t * 比较两个控制类型是否相等(C# record struct 的值比较语义)\n\t */\n\tequals(other: HsmsSsControlType): boolean {\n\t\treturn this.PType === other.PType && this.SType === other.SType;\n\t}\n\n\t/**\n\t * 支持 === 运算符的比较\n\t */\n\tvalueOf(): { PType: number; SType: number } {\n\t\treturn { PType: this.PType, SType: this.SType };\n\t}\n}\n"],"mappings":";;;;;AAIA,IAAa,oBAAb,MAAa,kBAAkB;CAE9B,AAAS;CACT,AAAS;CAGT,AAAQ,YAAY,OAAe,OAAe;AACjD,OAAK,QAAQ;AACb,OAAK,QAAQ;;CAMd,OAAgB,YAAY,IAAI,kBAAkB,KAAM,IAAK;CAG7D,OAAgB,OAAO,IAAI,kBAAkB,GAAM,EAAK;CAGxD,OAAgB,YAAY,IAAI,kBAAkB,GAAM,EAAK;CAC7D,OAAgB,YAAY,IAAI,kBAAkB,GAAM,EAAK;CAC7D,OAAgB,cAAc,IAAI,kBAAkB,GAAM,EAAK;CAC/D,OAAgB,cAAc,IAAI,kBAAkB,GAAM,EAAK;CAG/D,OAAgB,cAAc,IAAI,kBAAkB,GAAM,EAAK;CAC/D,OAAgB,cAAc,IAAI,kBAAkB,GAAM,EAAK;CAG/D,OAAgB,YAAY,IAAI,kBAAkB,GAAM,EAAK;CAG7D,OAAgB,cAAc,IAAI,kBAAkB,GAAM,EAAK;CAG/D,OAAwB,aAAkC;EACzD,kBAAkB;EAClB,kBAAkB;EAClB,kBAAkB;EAClB,kBAAkB;EAClB,kBAAkB;EAClB,kBAAkB;EAClB,kBAAkB;EAClB,kBAAkB;EAClB,kBAAkB;EAClB;;;;CAOD,OAAO,UAAU,OAAe,OAAkC;AACjE,OAAK,MAAM,SAAS,kBAAkB,WACrC,KAAI,MAAM,UAAU,SAAS,MAAM,UAAU,MAC5C,QAAO;AAGT,SAAO,kBAAkB;;;;;CAM1B,OAAO,gBACN,aACoB;AACpB,SAAO,kBAAkB,UAAU,YAAY,IAAI,YAAY,GAAG;;;;;CAQnE,IAAI,gBAAyB;AAC5B,SAAO,SAAS,kBAAkB;;;;;CAMnC,IAAI,mBAA4B;AAC/B,SAAO,CAAC,KAAK,iBAAiB,SAAS,kBAAkB;;CAG1D,IAAI,kBAA2B;AAC9B,SAAO,SAAS,kBAAkB;;CAGnC,IAAI,mBAA4B;AAC/B,SAAO,SAAS,kBAAkB;;CAGnC,IAAI,oBAA6B;AAChC,SAAO,SAAS,kBAAkB;;CAGnC,IAAI,kBAA2B;AAC9B,SAAO,SAAS,kBAAkB;;;;;CAMnC,WAAmB;AAClB,MAAI,SAAS,kBAAkB,KAAM,QAAO;AAC5C,MAAI,SAAS,kBAAkB,UAAW,QAAO;AACjD,MAAI,SAAS,kBAAkB,UAAW,QAAO;AACjD,MAAI,SAAS,kBAAkB,YAAa,QAAO;AACnD,MAAI,SAAS,kBAAkB,YAAa,QAAO;AACnD,MAAI,SAAS,kBAAkB,YAAa,QAAO;AACnD,MAAI,SAAS,kBAAkB,YAAa,QAAO;AACnD,MAAI,SAAS,kBAAkB,UAAW,QAAO;AACjD,MAAI,SAAS,kBAAkB,YAAa,QAAO;AACnD,SAAO,WAAW,KAAK,MAAM,SAAS,GAAG,CAAC,aAAa,CAAC,GAAG,KAAK,MAAM,SAAS,GAAG,CAAC,aAAa,CAAC;;;;;CAQlG,OAAO,OAAmC;AACzC,SAAO,KAAK,UAAU,MAAM,SAAS,KAAK,UAAU,MAAM;;;;;CAM3D,UAA4C;AAC3C,SAAO;GAAE,OAAO,KAAK;GAAO,OAAO,KAAK;GAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RejectReason.js","names":[],"sources":["../../../src/core/enums/RejectReason.ts"],"sourcesContent":["export enum RejectReason {\
|
|
1
|
+
{"version":3,"file":"RejectReason.js","names":[],"sources":["../../../src/core/enums/RejectReason.ts"],"sourcesContent":["export enum RejectReason {\n\tUnknown = 0xff,\n\tNotSupportTypeS = 0x01,\n\tNotSupportTypeP = 0x02,\n\tTransactionNotOpen = 0x03,\n\tNotSelected = 0x04,\n}\n"],"mappings":";AAAA,IAAY,wDAAL;AACN;AACA;AACA;AACA;AACA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SecsItemType.js","names":[],"sources":["../../../src/core/enums/SecsItemType.ts"],"sourcesContent":["export enum SecsItemType {\
|
|
1
|
+
{"version":3,"file":"SecsItemType.js","names":[],"sources":["../../../src/core/enums/SecsItemType.ts"],"sourcesContent":["export enum SecsItemType {\n L = 0x00, // List\n B = 0x20, // Binary\n BOOLEAN = 0x24, // Boolean\n A = 0x40, // ASCII\n I8 = 0x60, // Integer 8\n I1 = 0x64, // Integer 1\n I2 = 0x68, // Integer 2\n I4 = 0x70, // Integer 4\n F8 = 0x80, // Floating Point 8\n F4 = 0x90, // Floating Point 4\n U8 = 0xa0, // Unsigned Integer 8\n U1 = 0xa4, // Unsigned Integer 1\n U2 = 0xa8, // Unsigned Integer 2\n U4 = 0xb0, // Unsigned Integer 4\n}\n"],"mappings":";AAAA,IAAY,wDAAL;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectStatus.js","names":[],"sources":["../../../src/core/enums/SelectStatus.ts"],"sourcesContent":["export enum SelectStatus {\
|
|
1
|
+
{"version":3,"file":"SelectStatus.js","names":[],"sources":["../../../src/core/enums/SelectStatus.ts"],"sourcesContent":["export enum SelectStatus {\n\tUnknown = 0xff,\n\tSuccess = 0x00,\n\tActivated = 0x01,\n\tNotReady = 0x02,\n\tAlreadyUsed = 0x03,\n}\n"],"mappings":";AAAA,IAAY,wDAAL;AACN;AACA;AACA;AACA;AACA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AbstractSecs2Item.js","names":["type: SecsItemType","_value: T","lengthBytes: Buffer"],"sources":["../../../src/core/secs2item/AbstractSecs2Item.ts"],"sourcesContent":["import { SecsItemType } from \"../enums/SecsItemType.js\";\
|
|
1
|
+
{"version":3,"file":"AbstractSecs2Item.js","names":["type: SecsItemType","_value: T","lengthBytes: Buffer"],"sources":["../../../src/core/secs2item/AbstractSecs2Item.ts"],"sourcesContent":["import { SecsItemType } from \"../enums/SecsItemType.js\";\n\nexport abstract class AbstractSecs2Item<T = unknown> {\n\t[index: number]: unknown;\n\n\tconstructor(\n\t\tpublic readonly type: SecsItemType,\n\t\tprotected readonly _value: T,\n\t) {\n\t\treturn new Proxy(this, {\n\t\t\tget: (target, prop, receiver) => {\n\t\t\t\tif (typeof prop === \"string\") {\n\t\t\t\t\tconst index = Number(prop);\n\t\t\t\t\tif (Number.isInteger(index) && index >= 0) {\n\t\t\t\t\t\treturn target.getByIndex(index);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn Reflect.get(target, prop, receiver);\n\t\t\t},\n\t\t});\n\t}\n\n\t/**\n\t * @description Returns the value of the item.\n\t */\n\tget value(): T {\n\t\treturn this._value;\n\t}\n\n\t/**\n\t * @description Returns the value of the item at the given index.\n\t * @param index The index of the value to return.\n\t * @returns The value of the item at the given index.\n\t */\n\tprotected getByIndex(index: number): unknown {\n\t\tconst v = this._value;\n\t\tif (Array.isArray(v) || Buffer.isBuffer(v) || typeof v === \"string\") {\n\t\t\treturn v[index];\n\t\t}\n\t\t// Scalar value\n\t\tif (index === 0) {\n\t\t\treturn v;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * @description Returns the SML representation of the item.\n\t */\n\tabstract toSml(): string;\n\n\t/**\n\t * @description Returns the SECS-II encoded buffer of the item.\n\t */\n\tabstract toBuffer(): Buffer;\n\n\t/**\n\t * @description Helper to create the header (Type + LengthBytes)\n\t */\n\tprotected createHeader(length: number): Buffer {\n\t\tlet headerByte = this.type;\n\t\tlet lengthBytes: Buffer;\n\n\t\tif (length > 0xffffff) {\n\t\t\tthrow new Error(`Length ${length.toString()} is too large for SECS item`);\n\t\t}\n\n\t\tif (length > 0xffff) {\n\t\t\t// 3 bytes length\n\t\t\theaderByte |= 0x03;\n\t\t\tlengthBytes = Buffer.alloc(4);\n\t\t\tlengthBytes.writeUInt8(headerByte, 0);\n\t\t\tlengthBytes.writeUIntBE(length, 1, 3);\n\t\t} else if (length > 0xff) {\n\t\t\t// 2 bytes length\n\t\t\theaderByte |= 0x02;\n\t\t\tlengthBytes = Buffer.alloc(3);\n\t\t\tlengthBytes.writeUInt8(headerByte, 0);\n\t\t\tlengthBytes.writeUInt16BE(length, 1);\n\t\t} else {\n\t\t\t// 1 byte length\n\t\t\theaderByte |= 0x01;\n\t\t\tlengthBytes = Buffer.alloc(2);\n\t\t\tlengthBytes.writeUInt8(headerByte, 0);\n\t\t\tlengthBytes.writeUInt8(length, 1);\n\t\t}\n\t\treturn lengthBytes;\n\t}\n}\n"],"mappings":";AAEA,IAAsB,oBAAtB,MAAqD;CAGpD,YACC,AAAgBA,MAChB,AAAmBC,QAClB;EAFe;EACG;AAEnB,SAAO,IAAI,MAAM,MAAM,EACtB,MAAM,QAAQ,MAAM,aAAa;AAChC,OAAI,OAAO,SAAS,UAAU;IAC7B,MAAM,QAAQ,OAAO,KAAK;AAC1B,QAAI,OAAO,UAAU,MAAM,IAAI,SAAS,EACvC,QAAO,OAAO,WAAW,MAAM;;AAGjC,UAAO,QAAQ,IAAI,QAAQ,MAAM,SAAS;KAE3C,CAAC;;;;;CAMH,IAAI,QAAW;AACd,SAAO,KAAK;;;;;;;CAQb,AAAU,WAAW,OAAwB;EAC5C,MAAM,IAAI,KAAK;AACf,MAAI,MAAM,QAAQ,EAAE,IAAI,OAAO,SAAS,EAAE,IAAI,OAAO,MAAM,SAC1D,QAAO,EAAE;AAGV,MAAI,UAAU,EACb,QAAO;;;;;CAkBT,AAAU,aAAa,QAAwB;EAC9C,IAAI,aAAa,KAAK;EACtB,IAAIC;AAEJ,MAAI,SAAS,SACZ,OAAM,IAAI,MAAM,UAAU,OAAO,UAAU,CAAC,6BAA6B;AAG1E,MAAI,SAAS,OAAQ;AAEpB,iBAAc;AACd,iBAAc,OAAO,MAAM,EAAE;AAC7B,eAAY,WAAW,YAAY,EAAE;AACrC,eAAY,YAAY,QAAQ,GAAG,EAAE;aAC3B,SAAS,KAAM;AAEzB,iBAAc;AACd,iBAAc,OAAO,MAAM,EAAE;AAC7B,eAAY,WAAW,YAAY,EAAE;AACrC,eAAY,cAAc,QAAQ,EAAE;SAC9B;AAEN,iBAAc;AACd,iBAAc,OAAO,MAAM,EAAE;AAC7B,eAAY,WAAW,YAAY,EAAE;AACrC,eAAY,WAAW,QAAQ,EAAE;;AAElC,SAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Secs2ItemAscii.js","names":[],"sources":["../../../src/core/secs2item/Secs2ItemAscii.ts"],"sourcesContent":["import { SecsItemType } from \"../enums/SecsItemType.js\";\
|
|
1
|
+
{"version":3,"file":"Secs2ItemAscii.js","names":[],"sources":["../../../src/core/secs2item/Secs2ItemAscii.ts"],"sourcesContent":["import { SecsItemType } from \"../enums/SecsItemType.js\";\nimport { AbstractSecs2Item } from \"./AbstractSecs2Item.js\";\n\n/**\n * @description\n * ASCII string item is a string item that contains only ASCII characters.\n * @example\n * new Secs2ItemAscii(\"Hello World\");\n */\nexport class Secs2ItemAscii extends AbstractSecs2Item<string> {\n\tconstructor(value: string) {\n\t\tsuper(SecsItemType.A, value);\n\t}\n\n\toverride toSml(): string {\n\t\treturn `<A [${this._value.length}] \"${this._value}\">`;\n\t}\n\n\toverride toBuffer(): Buffer {\n\t\tconst valueBuffer = Buffer.from(this._value, \"ascii\");\n\t\tconst header = this.createHeader(valueBuffer.length);\n\t\treturn Buffer.concat([header, valueBuffer]);\n\t}\n}\n"],"mappings":";;;;;;;;;;AASA,IAAa,iBAAb,cAAoC,kBAA0B;CAC7D,YAAY,OAAe;AAC1B,QAAM,aAAa,GAAG,MAAM;;CAG7B,AAAS,QAAgB;AACxB,SAAO,OAAO,KAAK,OAAO,OAAO,KAAK,KAAK,OAAO;;CAGnD,AAAS,WAAmB;EAC3B,MAAM,cAAc,OAAO,KAAK,KAAK,QAAQ,QAAQ;EACrD,MAAM,SAAS,KAAK,aAAa,YAAY,OAAO;AACpD,SAAO,OAAO,OAAO,CAAC,QAAQ,YAAY,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Secs2ItemBinary.js","names":[],"sources":["../../../src/core/secs2item/Secs2ItemBinary.ts"],"sourcesContent":["import { SecsItemType } from \"../enums/SecsItemType.js\";\
|
|
1
|
+
{"version":3,"file":"Secs2ItemBinary.js","names":[],"sources":["../../../src/core/secs2item/Secs2ItemBinary.ts"],"sourcesContent":["import { SecsItemType } from \"../enums/SecsItemType.js\";\nimport { AbstractSecs2Item } from \"./AbstractSecs2Item.js\";\n\nexport class Secs2ItemBinary extends AbstractSecs2Item<Buffer> {\n\tconstructor(value: Buffer | number[]) {\n\t\tsuper(SecsItemType.B, Buffer.isBuffer(value) ? value : Buffer.from(value));\n\t}\n\n\toverride toSml(): string {\n\t\tconst hex = [];\n\t\tfor (const byte of this._value) {\n\t\t\thex.push(\"0x\" + byte.toString(16).toUpperCase().padStart(2, \"0\"));\n\t\t}\n\t\treturn `<B [${this._value.length}] ${hex.join(\" \")}>`;\n\t}\n\n\toverride toBuffer(): Buffer {\n\t\tconst header = this.createHeader(this._value.length);\n\t\treturn Buffer.concat([header, this._value]);\n\t}\n}\n"],"mappings":";;;;AAGA,IAAa,kBAAb,cAAqC,kBAA0B;CAC9D,YAAY,OAA0B;AACrC,QAAM,aAAa,GAAG,OAAO,SAAS,MAAM,GAAG,QAAQ,OAAO,KAAK,MAAM,CAAC;;CAG3E,AAAS,QAAgB;EACxB,MAAM,MAAM,EAAE;AACd,OAAK,MAAM,QAAQ,KAAK,OACvB,KAAI,KAAK,OAAO,KAAK,SAAS,GAAG,CAAC,aAAa,CAAC,SAAS,GAAG,IAAI,CAAC;AAElE,SAAO,OAAO,KAAK,OAAO,OAAO,IAAI,IAAI,KAAK,IAAI,CAAC;;CAGpD,AAAS,WAAmB;EAC3B,MAAM,SAAS,KAAK,aAAa,KAAK,OAAO,OAAO;AACpD,SAAO,OAAO,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Secs2ItemBoolean.js","names":[],"sources":["../../../src/core/secs2item/Secs2ItemBoolean.ts"],"sourcesContent":["import { SecsItemType } from \"../enums/SecsItemType.js\";\
|
|
1
|
+
{"version":3,"file":"Secs2ItemBoolean.js","names":[],"sources":["../../../src/core/secs2item/Secs2ItemBoolean.ts"],"sourcesContent":["import { SecsItemType } from \"../enums/SecsItemType.js\";\nimport { AbstractSecs2Item } from \"./AbstractSecs2Item.js\";\n\nexport class Secs2ItemBoolean extends AbstractSecs2Item<boolean | boolean[]> {\n\tconstructor(value: boolean | boolean[]) {\n\t\tsuper(SecsItemType.BOOLEAN, value);\n\t}\n\n\tget valueAsArray(): boolean[] {\n\t\treturn Array.isArray(this._value) ? this._value : [this._value];\n\t}\n\n\toverride toSml(): string {\n\t\tconst values = this.valueAsArray.map((v) => (v ? \"T\" : \"F\")); // Using T/F for brevity, standard might be TRUE/FALSE\n\t\treturn `<BOOLEAN ${values.join(\" \")}>`;\n\t}\n\n\toverride toBuffer(): Buffer {\n\t\tconst values = this.valueAsArray;\n\t\tconst buffer = Buffer.alloc(values.length);\n\t\tvalues.forEach((v, i) => buffer.writeUInt8(v ? 1 : 0, i)); // Or 0xFF? Python says 0xFF if v else 0x00?\n\t\t// Python code: 0xFF if v else 0x00.\n\t\t// Let's check pysemisecs again.\n\t\t// return bytes([(0xFF if v else 0x00) for v in self._value])\n\t\t// So 0xFF.\n\t\tvalues.forEach((v, i) => buffer.writeUInt8(v ? 0xff : 0x00, i));\n\t\tconst header = this.createHeader(buffer.length);\n\t\treturn Buffer.concat([header, buffer]);\n\t}\n}\n"],"mappings":";;;;AAGA,IAAa,mBAAb,cAAsC,kBAAuC;CAC5E,YAAY,OAA4B;AACvC,QAAM,aAAa,SAAS,MAAM;;CAGnC,IAAI,eAA0B;AAC7B,SAAO,MAAM,QAAQ,KAAK,OAAO,GAAG,KAAK,SAAS,CAAC,KAAK,OAAO;;CAGhE,AAAS,QAAgB;AAExB,SAAO,YADQ,KAAK,aAAa,KAAK,MAAO,IAAI,MAAM,IAAK,CAClC,KAAK,IAAI,CAAC;;CAGrC,AAAS,WAAmB;EAC3B,MAAM,SAAS,KAAK;EACpB,MAAM,SAAS,OAAO,MAAM,OAAO,OAAO;AAC1C,SAAO,SAAS,GAAG,MAAM,OAAO,WAAW,IAAI,IAAI,GAAG,EAAE,CAAC;AAKzD,SAAO,SAAS,GAAG,MAAM,OAAO,WAAW,IAAI,MAAO,GAAM,EAAE,CAAC;EAC/D,MAAM,SAAS,KAAK,aAAa,OAAO,OAAO;AAC/C,SAAO,OAAO,OAAO,CAAC,QAAQ,OAAO,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Secs2ItemFactory.js","names":[],"sources":["../../../src/core/secs2item/Secs2ItemFactory.ts"],"sourcesContent":["import { SecsItemType } from \"../enums/SecsItemType.js\";\
|
|
1
|
+
{"version":3,"file":"Secs2ItemFactory.js","names":[],"sources":["../../../src/core/secs2item/Secs2ItemFactory.ts"],"sourcesContent":["import { SecsItemType } from \"../enums/SecsItemType.js\";\nimport { AbstractSecs2Item } from \"./AbstractSecs2Item.js\";\nimport { Secs2ItemNumeric } from \"./Secs2ItemNumeric.js\";\nimport { Secs2ItemAscii } from \"./Secs2ItemAscii.js\";\nimport { Secs2ItemBinary } from \"./Secs2ItemBinary.js\";\nimport { Secs2ItemBoolean } from \"./Secs2ItemBoolean.js\";\nimport { Secs2ItemList } from \"./Secs2ItemList.js\";\n\nexport class Secs2ItemFactory {\n\tstatic createAsciiItem(value: string): Secs2ItemAscii {\n\t\treturn new Secs2ItemAscii(value);\n\t}\n\n\tstatic createBooleanItem(...value: boolean[]): Secs2ItemBoolean {\n\t\treturn new Secs2ItemBoolean(value);\n\t}\n\n\tstatic createBinaryItem(...value: Buffer[]): Secs2ItemBinary {\n\t\treturn new Secs2ItemBinary(Buffer.concat(value));\n\t}\n\n\tstatic createListItem(...items: AbstractSecs2Item[]): Secs2ItemList {\n\t\treturn new Secs2ItemList(items);\n\t}\n\n\tstatic createU1Item(...value: number[]): Secs2ItemNumeric {\n\t\treturn new Secs2ItemNumeric(SecsItemType.U1, value);\n\t}\n\n\tstatic createU2Item(...value: number[]): Secs2ItemNumeric {\n\t\treturn new Secs2ItemNumeric(SecsItemType.U2, value);\n\t}\n\n\tstatic createU4Item(...value: number[]): Secs2ItemNumeric {\n\t\treturn new Secs2ItemNumeric(SecsItemType.U4, value);\n\t}\n\n\tstatic createU8Item(...value: number[] | bigint[]): Secs2ItemNumeric {\n\t\treturn new Secs2ItemNumeric(SecsItemType.U8, value);\n\t}\n\n\tstatic createI1Item(...value: number[]): Secs2ItemNumeric {\n\t\treturn new Secs2ItemNumeric(SecsItemType.I1, value);\n\t}\n\n\tstatic createI2Item(...value: number[]): Secs2ItemNumeric {\n\t\treturn new Secs2ItemNumeric(SecsItemType.I2, value);\n\t}\n\n\tstatic createI4Item(...value: number[]): Secs2ItemNumeric {\n\t\treturn new Secs2ItemNumeric(SecsItemType.I4, value);\n\t}\n\n\tstatic createI8Item(...value: number[] | bigint[]): Secs2ItemNumeric {\n\t\treturn new Secs2ItemNumeric(SecsItemType.I8, value);\n\t}\n\n\tstatic createF4Item(...value: number[]): Secs2ItemNumeric {\n\t\treturn new Secs2ItemNumeric(SecsItemType.F4, value);\n\t}\n\n\tstatic createF8Item(...value: number[] | bigint[]): Secs2ItemNumeric {\n\t\treturn new Secs2ItemNumeric(SecsItemType.F8, value);\n\t}\n}\n"],"mappings":";;;;;;;;AAQA,IAAa,mBAAb,MAA8B;CAC7B,OAAO,gBAAgB,OAA+B;AACrD,SAAO,IAAI,eAAe,MAAM;;CAGjC,OAAO,kBAAkB,GAAG,OAAoC;AAC/D,SAAO,IAAI,iBAAiB,MAAM;;CAGnC,OAAO,iBAAiB,GAAG,OAAkC;AAC5D,SAAO,IAAI,gBAAgB,OAAO,OAAO,MAAM,CAAC;;CAGjD,OAAO,eAAe,GAAG,OAA2C;AACnE,SAAO,IAAI,cAAc,MAAM;;CAGhC,OAAO,aAAa,GAAG,OAAmC;AACzD,SAAO,IAAI,iBAAiB,aAAa,IAAI,MAAM;;CAGpD,OAAO,aAAa,GAAG,OAAmC;AACzD,SAAO,IAAI,iBAAiB,aAAa,IAAI,MAAM;;CAGpD,OAAO,aAAa,GAAG,OAAmC;AACzD,SAAO,IAAI,iBAAiB,aAAa,IAAI,MAAM;;CAGpD,OAAO,aAAa,GAAG,OAA8C;AACpE,SAAO,IAAI,iBAAiB,aAAa,IAAI,MAAM;;CAGpD,OAAO,aAAa,GAAG,OAAmC;AACzD,SAAO,IAAI,iBAAiB,aAAa,IAAI,MAAM;;CAGpD,OAAO,aAAa,GAAG,OAAmC;AACzD,SAAO,IAAI,iBAAiB,aAAa,IAAI,MAAM;;CAGpD,OAAO,aAAa,GAAG,OAAmC;AACzD,SAAO,IAAI,iBAAiB,aAAa,IAAI,MAAM;;CAGpD,OAAO,aAAa,GAAG,OAA8C;AACpE,SAAO,IAAI,iBAAiB,aAAa,IAAI,MAAM;;CAGpD,OAAO,aAAa,GAAG,OAAmC;AACzD,SAAO,IAAI,iBAAiB,aAAa,IAAI,MAAM;;CAGpD,OAAO,aAAa,GAAG,OAA8C;AACpE,SAAO,IAAI,iBAAiB,aAAa,IAAI,MAAM"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Secs2ItemList.js","names":[],"sources":["../../../src/core/secs2item/Secs2ItemList.ts"],"sourcesContent":["import { SecsItemType } from \"../enums/SecsItemType.js\";\
|
|
1
|
+
{"version":3,"file":"Secs2ItemList.js","names":[],"sources":["../../../src/core/secs2item/Secs2ItemList.ts"],"sourcesContent":["import { SecsItemType } from \"../enums/SecsItemType.js\";\nimport { AbstractSecs2Item } from \"./AbstractSecs2Item.js\";\n\nexport class Secs2ItemList extends AbstractSecs2Item<AbstractSecs2Item[]> {\n\tconstructor(value: AbstractSecs2Item[]) {\n\t\tsuper(SecsItemType.L, value);\n\t}\n\n\toverride toSml(): string {\n\t\tif (this._value.length === 0) {\n\t\t\treturn \"<L [0] >\";\n\t\t}\n\t\tconst lines = [`<L [${this._value.length.toString()}] `];\n\t\tfor (const item of this._value) {\n\t\t\tlines.push(\" \" + item.toSml().replace(/\\n/g, \"\\n \"));\n\t\t}\n\t\tlines.push(\">\");\n\t\treturn lines.join(\"\\n\");\n\t}\n\n\toverride toBuffer(): Buffer {\n\t\tconst buffers = this._value.map((item) => item.toBuffer());\n\t\tconst valueBuffer = Buffer.concat(buffers);\n\t\t// For List, length is number of items, not byte length\n\t\tconst header = this.createHeader(this._value.length);\n\t\treturn Buffer.concat([header, valueBuffer]);\n\t}\n}\n"],"mappings":";;;;AAGA,IAAa,gBAAb,cAAmC,kBAAuC;CACzE,YAAY,OAA4B;AACvC,QAAM,aAAa,GAAG,MAAM;;CAG7B,AAAS,QAAgB;AACxB,MAAI,KAAK,OAAO,WAAW,EAC1B,QAAO;EAER,MAAM,QAAQ,CAAC,OAAO,KAAK,OAAO,OAAO,UAAU,CAAC,IAAI;AACxD,OAAK,MAAM,QAAQ,KAAK,OACvB,OAAM,KAAK,OAAO,KAAK,OAAO,CAAC,QAAQ,OAAO,OAAO,CAAC;AAEvD,QAAM,KAAK,IAAI;AACf,SAAO,MAAM,KAAK,KAAK;;CAGxB,AAAS,WAAmB;EAC3B,MAAM,UAAU,KAAK,OAAO,KAAK,SAAS,KAAK,UAAU,CAAC;EAC1D,MAAM,cAAc,OAAO,OAAO,QAAQ;EAE1C,MAAM,SAAS,KAAK,aAAa,KAAK,OAAO,OAAO;AACpD,SAAO,OAAO,OAAO,CAAC,QAAQ,YAAY,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Secs2ItemNumeric.js","names":["writeFunc: (val: number | bigint, buf: Buffer, offset: number) => void","readFunc: (buf: Buffer, offset: number) => number | bigint","values: (number | bigint)[]"],"sources":["../../../src/core/secs2item/Secs2ItemNumeric.ts"],"sourcesContent":["import { SecsItemType } from \"../enums/SecsItemType.js\";\
|
|
1
|
+
{"version":3,"file":"Secs2ItemNumeric.js","names":["writeFunc: (val: number | bigint, buf: Buffer, offset: number) => void","readFunc: (buf: Buffer, offset: number) => number | bigint","values: (number | bigint)[]"],"sources":["../../../src/core/secs2item/Secs2ItemNumeric.ts"],"sourcesContent":["import { SecsItemType } from \"../enums/SecsItemType.js\";\nimport { AbstractSecs2Item } from \"./AbstractSecs2Item.js\";\n\nexport class Secs2ItemNumeric extends AbstractSecs2Item<\n\tnumber | number[] | bigint | bigint[]\n> {\n\tconstructor(\n\t\ttype: SecsItemType,\n\t\tvalue: number | number[] | bigint | bigint[],\n\t) {\n\t\tsuper(type, value);\n\t}\n\n\tget valueAsArray(): (number | bigint)[] {\n\t\treturn Array.isArray(this._value) ? this._value : [this._value];\n\t}\n\n\toverride toSml(): string {\n\t\tconst typeName = SecsItemType[this.type];\n\t\tconst values = this.valueAsArray.map((v) => v.toString());\n\t\treturn `<${typeName} [${values.length}] ${values.join(\" \")}>`;\n\t}\n\n\toverride toBuffer(): Buffer {\n\t\tconst values = this.valueAsArray;\n\t\tlet elementSize = 0;\n\t\tlet writeFunc: (val: number | bigint, buf: Buffer, offset: number) => void;\n\n\t\tswitch (this.type) {\n\t\t\tcase SecsItemType.I1:\n\t\t\t\telementSize = 1;\n\t\t\t\twriteFunc = (v, b, o) => b.writeInt8(Number(v), o);\n\t\t\t\tbreak;\n\t\t\tcase SecsItemType.I2:\n\t\t\t\telementSize = 2;\n\t\t\t\twriteFunc = (v, b, o) => b.writeInt16BE(Number(v), o);\n\t\t\t\tbreak;\n\t\t\tcase SecsItemType.I4:\n\t\t\t\telementSize = 4;\n\t\t\t\twriteFunc = (v, b, o) => b.writeInt32BE(Number(v), o);\n\t\t\t\tbreak;\n\t\t\tcase SecsItemType.I8:\n\t\t\t\telementSize = 8;\n\t\t\t\twriteFunc = (v, b, o) => b.writeBigInt64BE(BigInt(v), o);\n\t\t\t\tbreak;\n\t\t\tcase SecsItemType.U1:\n\t\t\t\telementSize = 1;\n\t\t\t\twriteFunc = (v, b, o) => b.writeUInt8(Number(v), o);\n\t\t\t\tbreak;\n\t\t\tcase SecsItemType.U2:\n\t\t\t\telementSize = 2;\n\t\t\t\twriteFunc = (v, b, o) => b.writeUInt16BE(Number(v), o);\n\t\t\t\tbreak;\n\t\t\tcase SecsItemType.U4:\n\t\t\t\telementSize = 4;\n\t\t\t\twriteFunc = (v, b, o) => b.writeUInt32BE(Number(v), o);\n\t\t\t\tbreak;\n\t\t\tcase SecsItemType.U8:\n\t\t\t\telementSize = 8;\n\t\t\t\twriteFunc = (v, b, o) => b.writeBigUInt64BE(BigInt(v), o);\n\t\t\t\tbreak;\n\t\t\tcase SecsItemType.F4:\n\t\t\t\telementSize = 4;\n\t\t\t\twriteFunc = (v, b, o) => b.writeFloatBE(Number(v), o);\n\t\t\t\tbreak;\n\t\t\tcase SecsItemType.F8:\n\t\t\t\telementSize = 8;\n\t\t\t\twriteFunc = (v, b, o) => b.writeDoubleBE(Number(v), o);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unsupported numeric type: ${this.type.toString()}`);\n\t\t}\n\n\t\tconst buffer = Buffer.alloc(values.length * elementSize);\n\t\tvalues.forEach((v, i) => {\n\t\t\twriteFunc(v, buffer, i * elementSize);\n\t\t});\n\t\tconst header = this.createHeader(buffer.length);\n\t\treturn Buffer.concat([header, buffer]);\n\t}\n\n\tstatic fromTypeBuffer(type: SecsItemType, buffer: Buffer): Secs2ItemNumeric {\n\t\tlet elementSize = 0;\n\t\tlet readFunc: (buf: Buffer, offset: number) => number | bigint;\n\n\t\tswitch (type) {\n\t\t\tcase SecsItemType.I1:\n\t\t\t\telementSize = 1;\n\t\t\t\treadFunc = (b, o) => b.readInt8(o);\n\t\t\t\tbreak;\n\t\t\tcase SecsItemType.I2:\n\t\t\t\telementSize = 2;\n\t\t\t\treadFunc = (b, o) => b.readInt16BE(o);\n\t\t\t\tbreak;\n\t\t\tcase SecsItemType.I4:\n\t\t\t\telementSize = 4;\n\t\t\t\treadFunc = (b, o) => b.readInt32BE(o);\n\t\t\t\tbreak;\n\t\t\tcase SecsItemType.I8:\n\t\t\t\telementSize = 8;\n\t\t\t\treadFunc = (b, o) => b.readBigInt64BE(o);\n\t\t\t\tbreak;\n\t\t\tcase SecsItemType.U1:\n\t\t\t\telementSize = 1;\n\t\t\t\treadFunc = (b, o) => b.readUInt8(o);\n\t\t\t\tbreak;\n\t\t\tcase SecsItemType.U2:\n\t\t\t\telementSize = 2;\n\t\t\t\treadFunc = (b, o) => b.readUInt16BE(o);\n\t\t\t\tbreak;\n\t\t\tcase SecsItemType.U4:\n\t\t\t\telementSize = 4;\n\t\t\t\treadFunc = (b, o) => b.readUInt32BE(o);\n\t\t\t\tbreak;\n\t\t\tcase SecsItemType.U8:\n\t\t\t\telementSize = 8;\n\t\t\t\treadFunc = (b, o) => b.readBigUInt64BE(o);\n\t\t\t\tbreak;\n\t\t\tcase SecsItemType.F4:\n\t\t\t\telementSize = 4;\n\t\t\t\treadFunc = (b, o) => b.readFloatBE(o);\n\t\t\t\tbreak;\n\t\t\tcase SecsItemType.F8:\n\t\t\t\telementSize = 8;\n\t\t\t\treadFunc = (b, o) => b.readDoubleBE(o);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unsupported numeric type: ${type.toString()}`);\n\t\t}\n\n\t\tconst count = buffer.length / elementSize;\n\t\tif (!Number.isInteger(count)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Buffer length ${buffer.length.toString()} is not multiple of element size ${elementSize.toString()}`,\n\t\t\t);\n\t\t}\n\n\t\tconst values: (number | bigint)[] = [];\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tvalues.push(readFunc(buffer, i * elementSize));\n\t\t}\n\n\t\tif (type === SecsItemType.I8 || type === SecsItemType.U8) {\n\t\t\treturn new Secs2ItemNumeric(\n\t\t\t\ttype,\n\t\t\t\tvalues.length === 1\n\t\t\t\t\t? (values[0] as bigint)\n\t\t\t\t\t: (values as unknown as bigint[]),\n\t\t\t);\n\t\t}\n\n\t\treturn new Secs2ItemNumeric(\n\t\t\ttype,\n\t\t\tvalues.length === 1 ? (values[0] as number) : (values as number[]),\n\t\t);\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Secs2ItemParser.js","names":["items: AbstractSecs2Item[]","item: AbstractSecs2Item"],"sources":["../../../src/core/secs2item/Secs2ItemParser.ts"],"sourcesContent":["import { SecsItemType } from \"../enums/SecsItemType.js\";\
|
|
1
|
+
{"version":3,"file":"Secs2ItemParser.js","names":["items: AbstractSecs2Item[]","item: AbstractSecs2Item"],"sources":["../../../src/core/secs2item/Secs2ItemParser.ts"],"sourcesContent":["import { SecsItemType } from \"../enums/SecsItemType.js\";\nimport { AbstractSecs2Item } from \"./AbstractSecs2Item.js\";\nimport { Secs2ItemFactory } from \"./Secs2ItemFactory.js\";\nimport { Secs2ItemNumeric } from \"./Secs2ItemNumeric.js\";\n\nexport class Secs2ItemParser {\n\tstatic fromBuffer(buffer: Buffer): {\n\t\titem: AbstractSecs2Item;\n\t\tconsumed: number;\n\t} {\n\t\tif (buffer.length === 0) {\n\t\t\tthrow new Error(\"Empty buffer\");\n\t\t}\n\n\t\tconst headerByte = buffer.readUInt8(0);\n\t\tconst itemType = (headerByte & 0xfc) as SecsItemType; // Clear last 2 bits\n\t\tconst lengthBytes = headerByte & 0x03;\n\n\t\tlet length = 0;\n\t\tif (lengthBytes === 1) {\n\t\t\tlength = buffer.readUInt8(1);\n\t\t} else if (lengthBytes === 2) {\n\t\t\tlength = buffer.readUInt16BE(1);\n\t\t} else if (lengthBytes === 3) {\n\t\t\tlength = buffer.readUIntBE(1, 3);\n\t\t} else {\n\t\t\tthrow new Error(`Invalid length bytes count: ${lengthBytes.toString()}`);\n\t\t}\n\n\t\tconst valueStart = 1 + lengthBytes;\n\n\t\t// Handle List items differently: length is number of items, not byte length\n\t\tif (itemType === SecsItemType.L) {\n\t\t\tconst items: AbstractSecs2Item[] = [];\n\t\t\tlet offset = valueStart;\n\t\t\tconst numItems = length;\n\n\t\t\tfor (let i = 0; i < numItems; i++) {\n\t\t\t\tif (offset >= buffer.length) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Insufficient buffer for List items. Expected ${numItems} items, got incomplete data.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst result = Secs2ItemParser.fromBuffer(buffer.subarray(offset));\n\t\t\t\titems.push(result.item);\n\t\t\t\toffset += result.consumed;\n\t\t\t}\n\n\t\t\tconst item = Secs2ItemFactory.createListItem(...items);\n\t\t\treturn { item, consumed: offset };\n\t\t}\n\n\t\t// For other types, length is byte length\n\t\tconst valueEnd = valueStart + length;\n\n\t\tif (buffer.length < valueEnd) {\n\t\t\tthrow new Error(\n\t\t\t\t`Insufficient buffer length. Expected ${valueEnd.toString()}, got ${buffer.length.toString()}`,\n\t\t\t);\n\t\t}\n\n\t\tconst valueBuffer = buffer.subarray(valueStart, valueEnd);\n\t\tconst consumed = valueEnd;\n\n\t\tlet item: AbstractSecs2Item;\n\n\t\tswitch (itemType) {\n\t\t\tcase SecsItemType.A:\n\t\t\t\titem = Secs2ItemFactory.createAsciiItem(valueBuffer.toString(\"ascii\"));\n\t\t\t\tbreak;\n\t\t\tcase SecsItemType.B:\n\t\t\t\titem = Secs2ItemFactory.createBinaryItem(valueBuffer);\n\t\t\t\tbreak;\n\t\t\tcase SecsItemType.BOOLEAN: {\n\t\t\t\t// Parse boolean array\n\t\t\t\tconst bools = [];\n\t\t\t\tfor (const byte of valueBuffer) {\n\t\t\t\t\tbools.push(byte !== 0);\n\t\t\t\t}\n\t\t\t\titem = Secs2ItemFactory.createBooleanItem(...bools);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase SecsItemType.I1:\n\t\t\tcase SecsItemType.I2:\n\t\t\tcase SecsItemType.I4:\n\t\t\tcase SecsItemType.I8:\n\t\t\tcase SecsItemType.U1:\n\t\t\tcase SecsItemType.U2:\n\t\t\tcase SecsItemType.U4:\n\t\t\tcase SecsItemType.U8:\n\t\t\tcase SecsItemType.F4:\n\t\t\tcase SecsItemType.F8:\n\t\t\t\titem = Secs2ItemNumeric.fromTypeBuffer(itemType, valueBuffer);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Unknown item type: 0x${(itemType as number).toString(16)}`,\n\t\t\t\t);\n\t\t}\n\n\t\treturn { item, consumed };\n\t}\n}\n"],"mappings":";;;;;AAKA,IAAa,kBAAb,MAAa,gBAAgB;CAC5B,OAAO,WAAW,QAGhB;AACD,MAAI,OAAO,WAAW,EACrB,OAAM,IAAI,MAAM,eAAe;EAGhC,MAAM,aAAa,OAAO,UAAU,EAAE;EACtC,MAAM,WAAY,aAAa;EAC/B,MAAM,cAAc,aAAa;EAEjC,IAAI,SAAS;AACb,MAAI,gBAAgB,EACnB,UAAS,OAAO,UAAU,EAAE;WAClB,gBAAgB,EAC1B,UAAS,OAAO,aAAa,EAAE;WACrB,gBAAgB,EAC1B,UAAS,OAAO,WAAW,GAAG,EAAE;MAEhC,OAAM,IAAI,MAAM,+BAA+B,YAAY,UAAU,GAAG;EAGzE,MAAM,aAAa,IAAI;AAGvB,MAAI,aAAa,aAAa,GAAG;GAChC,MAAMA,QAA6B,EAAE;GACrC,IAAI,SAAS;GACb,MAAM,WAAW;AAEjB,QAAK,IAAI,IAAI,GAAG,IAAI,UAAU,KAAK;AAClC,QAAI,UAAU,OAAO,OACpB,OAAM,IAAI,MACT,gDAAgD,SAAS,8BACzD;IAEF,MAAM,SAAS,gBAAgB,WAAW,OAAO,SAAS,OAAO,CAAC;AAClE,UAAM,KAAK,OAAO,KAAK;AACvB,cAAU,OAAO;;AAIlB,UAAO;IAAE,MADI,iBAAiB,eAAe,GAAG,MAAM;IACvC,UAAU;IAAQ;;EAIlC,MAAM,WAAW,aAAa;AAE9B,MAAI,OAAO,SAAS,SACnB,OAAM,IAAI,MACT,wCAAwC,SAAS,UAAU,CAAC,QAAQ,OAAO,OAAO,UAAU,GAC5F;EAGF,MAAM,cAAc,OAAO,SAAS,YAAY,SAAS;EACzD,MAAM,WAAW;EAEjB,IAAIC;AAEJ,UAAQ,UAAR;GACC,KAAK,aAAa;AACjB,WAAO,iBAAiB,gBAAgB,YAAY,SAAS,QAAQ,CAAC;AACtE;GACD,KAAK,aAAa;AACjB,WAAO,iBAAiB,iBAAiB,YAAY;AACrD;GACD,KAAK,aAAa,SAAS;IAE1B,MAAM,QAAQ,EAAE;AAChB,SAAK,MAAM,QAAQ,YAClB,OAAM,KAAK,SAAS,EAAE;AAEvB,WAAO,iBAAiB,kBAAkB,GAAG,MAAM;AACnD;;GAED,KAAK,aAAa;GAClB,KAAK,aAAa;GAClB,KAAK,aAAa;GAClB,KAAK,aAAa;GAClB,KAAK,aAAa;GAClB,KAAK,aAAa;GAClB,KAAK,aAAa;GAClB,KAAK,aAAa;GAClB,KAAK,aAAa;GAClB,KAAK,aAAa;AACjB,WAAO,iBAAiB,eAAe,UAAU,YAAY;AAC7D;GACD,QACC,OAAM,IAAI,MACT,wBAAyB,SAAoB,SAAS,GAAG,GACzD;;AAGH,SAAO;GAAE;GAAM;GAAU"}
|
package/lib/gem/Clock.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Clock.js","names":["datetime: Date"],"sources":["../../src/gem/Clock.ts"],"sourcesContent":["import { AbstractSecs2Item } from \"../core/secs2item/AbstractSecs2Item.js\";\
|
|
1
|
+
{"version":3,"file":"Clock.js","names":["datetime: Date"],"sources":["../../src/gem/Clock.ts"],"sourcesContent":["import { AbstractSecs2Item } from \"../core/secs2item/AbstractSecs2Item.js\";\nimport { Secs2ItemAscii } from \"../core/secs2item/Secs2ItemAscii.js\";\n\nexport enum ClockType {\n\tA12 = \"A12\",\n\tA16 = \"A16\",\n}\n\nexport class Clock {\n\tconstructor(private datetime: Date) {}\n\n\ttoA16(): Secs2ItemAscii {\n\t\tconst year = this.datetime.getFullYear();\n\t\tconst month = (this.datetime.getMonth() + 1).toString().padStart(2, \"0\");\n\t\tconst day = this.datetime.getDate().toString().padStart(2, \"0\");\n\t\tconst hour = this.datetime.getHours().toString().padStart(2, \"0\");\n\t\tconst minute = this.datetime.getMinutes().toString().padStart(2, \"0\");\n\t\tconst second = this.datetime.getSeconds().toString().padStart(2, \"0\");\n\t\tconst cc = Math.floor(this.datetime.getMilliseconds() / 10)\n\t\t\t.toString()\n\t\t\t.padStart(2, \"0\");\n\n\t\treturn new Secs2ItemAscii(\n\t\t\t`${year}${month}${day}${hour}${minute}${second}${cc}`,\n\t\t);\n\t}\n\n\ttoA12(): Secs2ItemAscii {\n\t\tconst year = this.datetime.getFullYear().toString().slice(-2);\n\t\tconst month = (this.datetime.getMonth() + 1).toString().padStart(2, \"0\");\n\t\tconst day = this.datetime.getDate().toString().padStart(2, \"0\");\n\t\tconst hour = this.datetime.getHours().toString().padStart(2, \"0\");\n\t\tconst minute = this.datetime.getMinutes().toString().padStart(2, \"0\");\n\t\tconst second = this.datetime.getSeconds().toString().padStart(2, \"0\");\n\n\t\treturn new Secs2ItemAscii(`${year}${month}${day}${hour}${minute}${second}`);\n\t}\n\n\ttoDatetime(): Date {\n\t\treturn this.datetime;\n\t}\n\n\tstatic now(): Clock {\n\t\treturn new Clock(new Date());\n\t}\n\n\tstatic fromAscii(item: AbstractSecs2Item): Clock {\n\t\tif (!(item instanceof Secs2ItemAscii)) {\n\t\t\tthrow new Error(\"Clock can only be parsed from ASCII item\");\n\t\t}\n\t\tconst val = item.value;\n\t\tconst len = val.length;\n\n\t\tif (len === 12) {\n\t\t\t// YYMMDDHHMMSS\n\t\t\tconst yy = parseInt(val.substring(0, 2), 10);\n\t\t\tconst mm = parseInt(val.substring(2, 4), 10);\n\t\t\tconst dd = parseInt(val.substring(4, 6), 10);\n\t\t\tconst hh = parseInt(val.substring(6, 8), 10);\n\t\t\tconst min = parseInt(val.substring(8, 10), 10);\n\t\t\tconst ss = parseInt(val.substring(10, 12), 10);\n\n\t\t\tconst year = Clock.getYear(yy);\n\t\t\treturn new Clock(new Date(year, mm - 1, dd, hh, min, ss));\n\t\t} else if (len === 16) {\n\t\t\t// YYYYMMDDHHMMSSCC\n\t\t\tconst year = parseInt(val.substring(0, 4), 10);\n\t\t\tconst mm = parseInt(val.substring(4, 6), 10);\n\t\t\tconst dd = parseInt(val.substring(6, 8), 10);\n\t\t\tconst hh = parseInt(val.substring(8, 10), 10);\n\t\t\tconst min = parseInt(val.substring(10, 12), 10);\n\t\t\tconst ss = parseInt(val.substring(12, 14), 10);\n\t\t\tconst cc = parseInt(val.substring(14, 16), 10);\n\n\t\t\treturn new Clock(new Date(year, mm - 1, dd, hh, min, ss, cc * 10));\n\t\t}\n\n\t\tthrow new Error(\"Unknown ClockType format\");\n\t}\n\n\tprivate static getYear(yy: number): number {\n\t\tconst nowYear = new Date().getFullYear();\n\t\tconst century = Math.floor(nowYear / 100) * 100;\n\t\tconst flacYear = nowYear % 100;\n\n\t\tif (flacYear < 25) {\n\t\t\tif (yy >= 75) return century - 100 + yy;\n\t\t} else if (flacYear >= 75) {\n\t\t\tif (yy < 25) return century + 100 + yy;\n\t\t}\n\t\treturn century + yy;\n\t}\n}\n"],"mappings":"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"}
|
package/lib/gem/Gem.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Gem.js","names":["comm: AbstractSecsCommunicator","body: Secs2ItemList"],"sources":["../../src/gem/Gem.ts"],"sourcesContent":["import { AbstractSecsCommunicator } from \"../core/AbstractSecsCommunicator.js\";\
|
|
1
|
+
{"version":3,"file":"Gem.js","names":["comm: AbstractSecsCommunicator","body: Secs2ItemList"],"sources":["../../src/gem/Gem.ts"],"sourcesContent":["import { AbstractSecsCommunicator } from \"../core/AbstractSecsCommunicator.js\";\nimport { SecsMessage } from \"../core/AbstractSecsMessage.js\";\nimport { Secs2ItemAscii } from \"../core/secs2item/Secs2ItemAscii.js\";\nimport { Secs2ItemBinary } from \"../core/secs2item/Secs2ItemBinary.js\";\nimport { Secs2ItemList } from \"../core/secs2item/Secs2ItemList.js\";\nimport { A, B, L } from \"../helper/Secs2ItemHelper.js\";\nimport { Clock, ClockType } from \"./Clock.js\";\n\nexport enum CommAck {\n\tOK = 0x0,\n\tDENIED = 0x1,\n}\n\nexport enum OflAck {\n\tOK = 0x0,\n}\n\nexport enum OnlAck {\n\tOK = 0x0,\n\tREFUSE = 0x1,\n\tALREADY_ONLINE = 0x2,\n}\n\nexport enum TiAck {\n\tOK = 0x0,\n\tNOT_DONE = 0x1,\n}\n\nexport class Gem {\n\tprivate static readonly DEFAULT_MDLN = \" \";\n\tprivate static readonly DEFAULT_SOFTREV = \" \";\n\tprivate static readonly DEFAULT_CLOCK_TYPE = ClockType.A16;\n\n\tpublic mdln: string = Gem.DEFAULT_MDLN;\n\tpublic softrev: string = Gem.DEFAULT_SOFTREV;\n\tpublic clockType: ClockType = Gem.DEFAULT_CLOCK_TYPE;\n\n\tconstructor(public comm: AbstractSecsCommunicator) {}\n\n\t// S1F2 - Are You There?\n\tasync s1f2(primaryMsg: SecsMessage): Promise<void> {\n\t\tawait this.comm.reply(primaryMsg, 1, 2, L());\n\t}\n\n\t// S1F13 - Establish Communications Request\n\tasync s1f13(): Promise<number> {\n\t\tlet body: Secs2ItemList;\n\t\tif (this.comm.isEquip) {\n\t\t\tbody = L(A(this.mdln), A(this.softrev));\n\t\t} else {\n\t\t\tbody = L();\n\t\t}\n\n\t\tconst reply = await this.comm.send(1, 13, true, body);\n\t\tif (reply && reply.body instanceof Secs2ItemList) {\n\t\t\tconst list = reply.body;\n\t\t\tif (list.value.length > 0 && list.value[0] instanceof Secs2ItemBinary) {\n\t\t\t\tconst bin = list.value[0];\n\t\t\t\treturn bin.value[0];\n\t\t\t}\n\t\t}\n\t\tthrow new Error(\"S1F14 invalid response or not COMMACK\");\n\t}\n\n\t// S1F14 - Establish Communications Acknowledge\n\tasync s1f14(primaryMsg: SecsMessage, commAck: CommAck): Promise<void> {\n\t\tlet body: Secs2ItemList;\n\t\tif (this.comm.isEquip) {\n\t\t\tbody = L(B(Buffer.from([commAck])), L(A(this.mdln), A(this.softrev)));\n\t\t} else {\n\t\t\tbody = L(B(Buffer.from([commAck])), L());\n\t\t}\n\t\tawait this.comm.reply(primaryMsg, 1, 14, body);\n\t}\n\n\t// S1F15 - Request OFF-LINE\n\tasync s1f15(): Promise<number> {\n\t\tconst reply = await this.comm.send(1, 15, true);\n\t\tif (reply && reply.body instanceof Secs2ItemBinary) {\n\t\t\treturn reply.body.value[0];\n\t\t}\n\t\tthrow new Error(\"S1F16 invalid response or not OFLACK\");\n\t}\n\n\t// S1F16 - OFF-LINE Acknowledge\n\tasync s1f16(primaryMsg: SecsMessage): Promise<void> {\n\t\tawait this.comm.reply(primaryMsg, 1, 16, B(Buffer.from([OflAck.OK])));\n\t}\n\n\t// S1F17 - Request ON-LINE\n\tasync s1f17(): Promise<number> {\n\t\tconst reply = await this.comm.send(1, 17, true);\n\t\tif (reply && reply.body instanceof Secs2ItemBinary) {\n\t\t\treturn reply.body.value[0];\n\t\t}\n\t\tthrow new Error(\"S1F18 invalid response or not ONLACK\");\n\t}\n\n\t// S1F18 - ON-LINE Acknowledge\n\tasync s1f18(primaryMsg: SecsMessage, onlAck: OnlAck): Promise<void> {\n\t\tawait this.comm.reply(primaryMsg, 1, 18, B(Buffer.from([onlAck])));\n\t}\n\n\t// S2F17 - Date and Time Request\n\tasync s2f17(): Promise<Clock> {\n\t\tconst reply = await this.comm.send(2, 17, true);\n\t\tif (reply?.body instanceof Secs2ItemAscii) {\n\t\t\treturn Clock.fromAscii(reply.body);\n\t\t}\n\t\tthrow new Error(\"S2F18 invalid response or not time\");\n\t}\n\n\t// S2F18 - Date and Time Data\n\tasync s2f18(\n\t\tprimaryMsg: SecsMessage,\n\t\tclock: Clock = Clock.now(),\n\t): Promise<void> {\n\t\tconst body =\n\t\t\tthis.clockType === ClockType.A12 ? clock.toA12() : clock.toA16();\n\t\tawait this.comm.reply(primaryMsg, 2, 18, body);\n\t}\n\n\tasync s2f18Now(primaryMsg: SecsMessage): Promise<void> {\n\t\treturn this.s2f18(primaryMsg, Clock.now());\n\t}\n\n\t// S2F31 - Date and Time Set Request\n\tasync s2f31(clock: Clock): Promise<number> {\n\t\tconst body =\n\t\t\tthis.clockType === ClockType.A12 ? clock.toA12() : clock.toA16();\n\t\tconst reply = await this.comm.send(2, 31, true, body);\n\t\tif (reply && reply.body instanceof Secs2ItemBinary) {\n\t\t\treturn reply.body.value[0];\n\t\t}\n\t\tthrow new Error(\"S2F32 invalid response or not TIACK\");\n\t}\n\n\tasync s2f31Now(): Promise<number> {\n\t\treturn this.s2f31(Clock.now());\n\t}\n\n\t// S2F32 - Date and Time Set Acknowledge\n\tasync s2f32(primaryMsg: SecsMessage, tiAck: TiAck): Promise<void> {\n\t\tawait this.comm.reply(primaryMsg, 2, 32, B(Buffer.from([tiAck])));\n\t}\n\n\t// S9Fx Helpers\n\tasync s9f1(refMsg: SecsMessage): Promise<void> {\n\t\tawait this.s9fy(refMsg, 1);\n\t}\n\tasync s9f3(refMsg: SecsMessage): Promise<void> {\n\t\tawait this.s9fy(refMsg, 3);\n\t}\n\tasync s9f5(refMsg: SecsMessage): Promise<void> {\n\t\tawait this.s9fy(refMsg, 5);\n\t}\n\tasync s9f7(refMsg: SecsMessage): Promise<void> {\n\t\tawait this.s9fy(refMsg, 7);\n\t}\n\tasync s9f9(refMsg: SecsMessage): Promise<void> {\n\t\tawait this.s9fy(refMsg, 9);\n\t}\n\tasync s9f11(refMsg: SecsMessage): Promise<void> {\n\t\tawait this.s9fy(refMsg, 11);\n\t}\n\n\tprivate async s9fy(refMsg: SecsMessage, func: number): Promise<void> {\n\t\tconst header = this.getHeader10Bytes(refMsg);\n\t\tawait this.comm.send(9, func, false, B(header));\n\t}\n\n\tprivate getHeader10Bytes(msg: SecsMessage): Buffer {\n\t\tconst buffer = Buffer.alloc(10);\n\t\t// Session ID (Device ID)\n\t\tbuffer.writeUInt16BE(msg.deviceId & 0x7fff, 0);\n\n\t\t// Stream + W-bit\n\t\tlet streamByte = msg.stream & 0x7f;\n\t\tif (msg.wBit) {\n\t\t\tstreamByte |= 0x80;\n\t\t}\n\t\tbuffer.writeUInt8(streamByte, 2);\n\n\t\t// Function\n\t\tbuffer.writeUInt8(msg.func, 3);\n\n\t\t// P-Type, S-Type (Assuming 0 for now)\n\t\tbuffer.writeUInt8(0, 4);\n\t\tbuffer.writeUInt8(0, 5);\n\n\t\t// System Bytes\n\t\tif (typeof msg.systemBytes === \"number\") {\n\t\t\tbuffer.writeUInt32BE(msg.systemBytes, 6);\n\t\t} else {\n\t\t\t// Assuming Buffer\n\t\t\tconst sysBuf = msg.systemBytes as Buffer;\n\t\t\tsysBuf.copy(buffer, 6, 0, 4);\n\t\t}\n\n\t\treturn buffer;\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Secs2ItemHelper.js","names":["booleanValues: boolean[]","binaryValues: number[]"],"sources":["../../src/helper/Secs2ItemHelper.ts"],"sourcesContent":["import { AbstractSecs2Item } from \"../core/secs2item/AbstractSecs2Item.js\";\
|
|
1
|
+
{"version":3,"file":"Secs2ItemHelper.js","names":["booleanValues: boolean[]","binaryValues: number[]"],"sources":["../../src/helper/Secs2ItemHelper.ts"],"sourcesContent":["import { AbstractSecs2Item } from \"../core/secs2item/AbstractSecs2Item.js\";\nimport { Secs2ItemAscii } from \"../core/secs2item/Secs2ItemAscii.js\";\nimport { Secs2ItemBinary } from \"../core/secs2item/Secs2ItemBinary.js\";\nimport { Secs2ItemBoolean } from \"../core/secs2item/Secs2ItemBoolean.js\";\nimport { Secs2ItemFactory } from \"../core/secs2item/Secs2ItemFactory.js\";\nimport { Secs2ItemList } from \"../core/secs2item/Secs2ItemList.js\";\nimport { Secs2ItemNumeric } from \"../core/secs2item/Secs2ItemNumeric.js\";\n\n/**\n * @description Creates a SECS-II list item.\n * @param items The items in the list.\n * @returns The SECS-II list item.\n */\nexport function L(...items: AbstractSecs2Item[]): Secs2ItemList {\n\treturn Secs2ItemFactory.createListItem(...items);\n}\n\n/**\n * @description Creates a SECS-II ASCII item.\n * @param value The value of the item.\n * @returns The SECS-II ASCII item.\n */\nexport function A(value: string): Secs2ItemAscii {\n\treturn Secs2ItemFactory.createAsciiItem(value);\n}\n\n/**\n * @description Creates a SECS-II boolean item.\n * @param value The value of the item.\n * @returns The SECS-II boolean item.\n */\nexport function BOOLEAN(value: string): Secs2ItemBoolean {\n\tconst booleanValues: boolean[] = [];\n\tconst values = value.split(\"\");\n\tvalues.map((v) => {\n\t\tif (v !== \"TRUE\" && v !== \"FALSE\") {\n\t\t\tthrow new Error(\"BOOLEAN value must be TRUE or FALSE\");\n\t\t}\n\t\tif (v === \"TRUE\") {\n\t\t\tbooleanValues.push(true);\n\t\t} else {\n\t\t\tbooleanValues.push(false);\n\t\t}\n\t});\n\treturn Secs2ItemFactory.createBooleanItem(...booleanValues);\n}\n\n/**\n * @description Creates a SECS-II binary item.\n * @param value The value of the item.\n * @returns The SECS-II binary item.\n */\nexport function B(value: string | Buffer): Secs2ItemBinary {\n\tconst valueType = typeof value;\n\tif (valueType === \"string\") {\n\t\tconst stringToBytes = (s: string) =>\n\t\t\ts\n\t\t\t\t.split(/\\s+/)\n\t\t\t\t.map((v) =>\n\t\t\t\t\tv.trim().startsWith(\"0x\") ? parseInt(v, 16) : parseInt(v, 10),\n\t\t\t\t);\n\n\t\tconst binaryValues: number[] = stringToBytes(value as string);\n\t\treturn Secs2ItemFactory.createBinaryItem(Buffer.from(binaryValues));\n\t}\n\n\treturn Secs2ItemFactory.createBinaryItem(value as Buffer);\n}\n\n/**\n * @description Creates a SECS-II unsigned 8-bit integer item.\n * @param value The value of the item.\n * @returns The SECS-II unsigned 8-bit integer item.\n */\nexport function U1(...value: number[]): Secs2ItemNumeric {\n\tif (value.some((v) => v < 0)) {\n\t\tthrow new Error(\"U1 value must be unsigned 8-bit integer\");\n\t}\n\treturn Secs2ItemFactory.createU1Item(...value);\n}\n\n/**\n * @description Creates a SECS-II unsigned 16-bit integer item.\n * @param value The value of the item.\n * @returns The SECS-II unsigned 16-bit integer item.\n */\nexport function U2(...value: number[]): Secs2ItemNumeric {\n\tif (value.some((v) => v < 0)) {\n\t\tthrow new Error(\"U2 value must be unsigned 16-bit integer\");\n\t}\n\treturn Secs2ItemFactory.createU2Item(...value);\n}\n\n/**\n * @description Creates a SECS-II unsigned 32-bit integer item.\n * @param value The value of the item.\n * @returns The SECS-II unsigned 32-bit integer item.\n */\nexport function U4(...value: number[]): Secs2ItemNumeric {\n\tif (value.some((v) => v < 0)) {\n\t\tthrow new Error(\"U4 value must be unsigned 32-bit integer\");\n\t}\n\treturn Secs2ItemFactory.createU4Item(...value);\n}\n\n/**\n * @description Creates a SECS-II unsigned 64-bit integer item.\n * @param value The value of the item.\n * @returns The SECS-II unsigned 64-bit integer item.\n */\nexport function U8(...value: number[] | bigint[]): Secs2ItemNumeric {\n\tif (value.some((v) => v < 0)) {\n\t\tthrow new Error(\"U8 value must be unsigned 64-bit integer\");\n\t}\n\treturn Secs2ItemFactory.createU8Item(...value);\n}\n\n/**\n * @description Creates a SECS-II signed 8-bit integer item.\n * @param value The value of the item.\n * @returns The SECS-II signed 8-bit integer item.\n */\nexport function I1(...value: number[]): Secs2ItemNumeric {\n\treturn Secs2ItemFactory.createI1Item(...value);\n}\n\n/**\n * @description Creates a SECS-II signed 16-bit integer item.\n * @param value The value of the item.\n * @returns The SECS-II signed 16-bit integer item.\n */\nexport function I2(...value: number[]): Secs2ItemNumeric {\n\treturn Secs2ItemFactory.createI2Item(...value);\n}\n\n/**\n * @description Creates a SECS-II signed 32-bit integer item.\n * @param value The value of the item.\n * @returns The SECS-II signed 32-bit integer item.\n */\nexport function I4(...value: number[]): Secs2ItemNumeric {\n\treturn Secs2ItemFactory.createI4Item(...value);\n}\n\n/**\n * @description Creates a SECS-II signed 64-bit integer item.\n * @param value The value of the item.\n * @returns The SECS-II signed 64-bit integer item.\n */\nexport function I8(...value: number[] | bigint[]): Secs2ItemNumeric {\n\treturn Secs2ItemFactory.createI8Item(...value);\n}\n\n/**\n * @description Creates a SECS-II float 32-bit number item.\n * @param value The value of the item.\n * @returns The SECS-II float 32-bit number item.\n */\nexport function F4(...value: number[]): Secs2ItemNumeric {\n\tif (value.some((v) => v % 1 !== 0)) {\n\t\tthrow new Error(\"F4 value must be float 32-bit number\");\n\t}\n\treturn Secs2ItemFactory.createF4Item(...value);\n}\n\n/**\n * @description Creates a SECS-II float 64-bit number item.\n * @param value The value of the item.\n * @returns The SECS-II float 64-bit number item.\n */\nexport function F8(...value: number[]): Secs2ItemNumeric {\n\treturn Secs2ItemFactory.createF8Item(...value);\n}\n"],"mappings":";;;;;;;;AAaA,SAAgB,EAAE,GAAG,OAA2C;AAC/D,QAAO,iBAAiB,eAAe,GAAG,MAAM;;;;;;;AAQjD,SAAgB,EAAE,OAA+B;AAChD,QAAO,iBAAiB,gBAAgB,MAAM;;;;;;;AAQ/C,SAAgB,QAAQ,OAAiC;CACxD,MAAMA,gBAA2B,EAAE;AAEnC,CADe,MAAM,MAAM,GAAG,CACvB,KAAK,MAAM;AACjB,MAAI,MAAM,UAAU,MAAM,QACzB,OAAM,IAAI,MAAM,sCAAsC;AAEvD,MAAI,MAAM,OACT,eAAc,KAAK,KAAK;MAExB,eAAc,KAAK,MAAM;GAEzB;AACF,QAAO,iBAAiB,kBAAkB,GAAG,cAAc;;;;;;;AAQ5D,SAAgB,EAAE,OAAyC;AAE1D,KADkB,OAAO,UACP,UAAU;EAC3B,MAAM,iBAAiB,MACtB,EACE,MAAM,MAAM,CACZ,KAAK,MACL,EAAE,MAAM,CAAC,WAAW,KAAK,GAAG,SAAS,GAAG,GAAG,GAAG,SAAS,GAAG,GAAG,CAC7D;EAEH,MAAMC,eAAyB,cAAc,MAAgB;AAC7D,SAAO,iBAAiB,iBAAiB,OAAO,KAAK,aAAa,CAAC;;AAGpE,QAAO,iBAAiB,iBAAiB,MAAgB;;;;;;;AAQ1D,SAAgB,GAAG,GAAG,OAAmC;AACxD,KAAI,MAAM,MAAM,MAAM,IAAI,EAAE,CAC3B,OAAM,IAAI,MAAM,0CAA0C;AAE3D,QAAO,iBAAiB,aAAa,GAAG,MAAM;;;;;;;AAQ/C,SAAgB,GAAG,GAAG,OAAmC;AACxD,KAAI,MAAM,MAAM,MAAM,IAAI,EAAE,CAC3B,OAAM,IAAI,MAAM,2CAA2C;AAE5D,QAAO,iBAAiB,aAAa,GAAG,MAAM;;;;;;;AAQ/C,SAAgB,GAAG,GAAG,OAAmC;AACxD,KAAI,MAAM,MAAM,MAAM,IAAI,EAAE,CAC3B,OAAM,IAAI,MAAM,2CAA2C;AAE5D,QAAO,iBAAiB,aAAa,GAAG,MAAM;;;;;;;AAQ/C,SAAgB,GAAG,GAAG,OAA8C;AACnE,KAAI,MAAM,MAAM,MAAM,IAAI,EAAE,CAC3B,OAAM,IAAI,MAAM,2CAA2C;AAE5D,QAAO,iBAAiB,aAAa,GAAG,MAAM;;;;;;;AAQ/C,SAAgB,GAAG,GAAG,OAAmC;AACxD,QAAO,iBAAiB,aAAa,GAAG,MAAM;;;;;;;AAQ/C,SAAgB,GAAG,GAAG,OAAmC;AACxD,QAAO,iBAAiB,aAAa,GAAG,MAAM;;;;;;;AAQ/C,SAAgB,GAAG,GAAG,OAAmC;AACxD,QAAO,iBAAiB,aAAa,GAAG,MAAM;;;;;;;AAQ/C,SAAgB,GAAG,GAAG,OAA8C;AACnE,QAAO,iBAAiB,aAAa,GAAG,MAAM;;;;;;;AAQ/C,SAAgB,GAAG,GAAG,OAAmC;AACxD,KAAI,MAAM,MAAM,MAAM,IAAI,MAAM,EAAE,CACjC,OAAM,IAAI,MAAM,uCAAuC;AAExD,QAAO,iBAAiB,aAAa,GAAG,MAAM;;;;;;;AAQ/C,SAAgB,GAAG,GAAG,OAAmC;AACxD,QAAO,iBAAiB,aAAa,GAAG,MAAM"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HsmsMessage.js","names":["body: AbstractSecs2Item | null"],"sources":["../../src/hsms/HsmsMessage.ts"],"sourcesContent":["import { SecsMessage } from \"../core/AbstractSecsMessage.js\";\r\nimport { AbstractSecs2Item } from \"../core/secs2item/AbstractSecs2Item.js\";\r\nimport { HsmsControlType } from \"./enums/HsmsControlType.js\";\r\nimport { RejectReason } from \"./enums/RejectReason.js\";\r\nimport { Secs2ItemParser } from \"../core/secs2item/Secs2ItemParser.js\";\r\n\r\n/**\r\n * @description HsmsMessage is the class that represents an HSMS message.\r\n * @param stream The stream number of the message.\r\n * @param func The function number of the message.\r\n * @param wBit The W-Bit of the message.\r\n * @param body The body of the message.\r\n * @param systemBytes The system bytes of the message.\r\n * @param deviceId The device ID of the message.\r\n * @param pType The P-Type of the message.\r\n * @param sType The S-Type of the message.\r\n */\r\nexport class HsmsMessage extends SecsMessage {\r\n\tconstructor(\r\n\t\tstream: number,\r\n\t\tfunc: number,\r\n\t\twBit: boolean,\r\n\t\tbody: AbstractSecs2Item | null,\r\n\t\tsystemBytes: number,\r\n\t\tdeviceId: number,\r\n\t\tpublic readonly pType = 0,\r\n\t\tpublic readonly sType = 0,\r\n\t) {\r\n\t\tsuper(stream, func, wBit, body, systemBytes, deviceId);\r\n\t}\r\n\r\n\t/**\r\n\t * @description Encodes the message to a buffer (Length + Header + Body).\r\n\t */\r\n\ttoBuffer(): Buffer {\r\n\t\tconst bodyBuffer = this.body ? this.body.toBuffer() : Buffer.alloc(0);\r\n\t\tconst header = Buffer.alloc(10);\r\n\r\n\t\t// Byte 0-1: Session ID (Device ID) or 0xFFFF\r\n\t\tif (this.isDataMessage()) {\r\n\t\t\theader.writeUInt16BE(this.deviceId, 0);\r\n\t\t} else {\r\n\t\t\theader.writeUInt16BE(0xffff, 0);\r\n\t\t}\r\n\r\n\t\t// Byte 2: Stream / WBit (only for Data)\r\n\t\t// Byte 3: Function (only for Data)\r\n\t\tif (this.isDataMessage()) {\r\n\t\t\tlet b2 = this.stream;\r\n\t\t\tif (this.wBit) {\r\n\t\t\t\tb2 |= 0x80;\r\n\t\t\t}\r\n\t\t\theader.writeUInt8(b2, 2);\r\n\t\t\theader.writeUInt8(this.func, 3);\r\n\t\t} else {\r\n\t\t\t// For control messages, byte 2 and 3 depend on type\r\n\t\t\t// But typically 0 unless SelectStatus/RejectReason\r\n\t\t\t// We will handle specific construction in static methods\r\n\t\t\t// Here we assume pType and sType are set correctly for Control Messages\r\n\t\t\t// Wait, P-Type is Byte 4, S-Type is Byte 5.\r\n\t\t\t// Byte 2 and 3 are 0 for most control messages.\r\n\t\t\t// EXCEPT Select Response (Byte 3 = Status) and Reject (Byte 3 = Reason).\r\n\t\t\t// But those are stored in 'sType' or 'func' or similar?\r\n\t\t\t// In this class, I store pType and sType (Byte 4, 5).\r\n\t\t\t// Where do I store Byte 2 and 3 for Control Messages?\r\n\t\t\t// The Python code:\r\n\t\t\t// Select Response: h10bytes = ... 0x00, select_status ...\r\n\t\t\t// Reject: ... b2, reject_reason ...\r\n\r\n\t\t\t// I should allow passing byte 2 and 3 specifically or handle it via polymorphism.\r\n\t\t\t// To keep it simple, I will use 'stream' and 'func' to hold Byte 2 and 3 for Control Messages too,\r\n\t\t\t// even if they don't mean Stream/Function.\r\n\r\n\t\t\theader.writeUInt8(this.stream, 2);\r\n\t\t\theader.writeUInt8(this.func, 3);\r\n\t\t}\r\n\r\n\t\t// Byte 4: P-Type\r\n\t\theader.writeUInt8(this.pType, 4);\r\n\r\n\t\t// Byte 5: S-Type\r\n\t\theader.writeUInt8(this.sType, 5);\r\n\r\n\t\t// Byte 6-9: System Bytes\r\n\t\theader.writeUInt32BE(this.systemBytes, 6);\r\n\r\n\t\tconst length = header.length + bodyBuffer.length;\r\n\t\tconst lengthBuffer = Buffer.alloc(4);\r\n\t\tlengthBuffer.writeUInt32BE(length, 0);\r\n\r\n\t\treturn Buffer.concat([lengthBuffer, header, bodyBuffer]);\r\n\t}\r\n\r\n\t/**\r\n\t * @description Checks if the message is a data message.\r\n\t * @description data message: deviceId not 0xFF 0xFF and header[4] and header[5] are 0.\r\n\t * @returns True if the message is a data message, false otherwise.\r\n\t */\r\n\tisDataMessage(): boolean {\r\n\t\treturn (this.sType as HsmsControlType) === HsmsControlType.Data;\r\n\t}\r\n\r\n\t/**\r\n\t * @description Creates an HsmsMessage from a buffer.\r\n\t * @param buffer The buffer containing the message data.\r\n\t * @returns The HsmsMessage object.\r\n\t */\r\n\tstatic fromBuffer(buffer: Buffer): HsmsMessage {\r\n\t\tif (buffer.length < 14) {\r\n\t\t\tthrow new Error(\"Buffer too short for HSMS message\");\r\n\t\t}\r\n\r\n\t\t// Bytes 0-3: Length (ignored here, assumed to be correct or handled by framer)\r\n\t\tconst header = buffer.subarray(4, 14);\r\n\t\tconst bodyBuffer = buffer.subarray(14);\r\n\r\n\t\tconst sessionId = header.readUInt16BE(0);\r\n\t\tconst byte2 = header.readUInt8(2);\r\n\t\tconst byte3 = header.readUInt8(3);\r\n\t\tconst pType = header.readUInt8(4);\r\n\t\tconst sType = header.readUInt8(5);\r\n\t\tconst systemBytes = header.readUInt32BE(6);\r\n\r\n\t\tlet stream = 0;\r\n\t\tlet func = 0;\r\n\t\tlet wBit = false;\r\n\t\tconst deviceId = sessionId;\r\n\t\tlet body: AbstractSecs2Item | null = null;\r\n\r\n\t\tif ((sType as HsmsControlType) === HsmsControlType.Data) {\r\n\t\t\tstream = byte2 & 0x7f;\r\n\t\t\twBit = (byte2 & 0x80) !== 0;\r\n\t\t\tfunc = byte3;\r\n\r\n\t\t\tif (bodyBuffer.length > 0) {\r\n\t\t\t\tconst result = Secs2ItemParser.fromBuffer(bodyBuffer);\r\n\t\t\t\tbody = result.item;\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\t// Control Message\r\n\t\t\t// Mapping Byte 2/3 to stream/func to preserve data (e.g. Select Status)\r\n\t\t\tstream = byte2;\r\n\t\t\tfunc = byte3;\r\n\t\t\t// deviceId is usually ignored or 0xFFFF, but we keep what we read\r\n\t\t}\r\n\r\n\t\treturn new HsmsMessage(\r\n\t\t\tstream,\r\n\t\t\tfunc,\r\n\t\t\twBit,\r\n\t\t\tbody,\r\n\t\t\tsystemBytes,\r\n\t\t\tdeviceId,\r\n\t\t\tpType,\r\n\t\t\tsType,\r\n\t\t);\r\n\t}\r\n\r\n\t// Factory methods for Control Messages\r\n\t/**\r\n\t * @description Creates a Select Request message.\r\n\t * @param systemBytes The system bytes of the message.\r\n\t * @returns The HsmsMessage object.\r\n\t */\r\n\tstatic selectReq(systemBytes: number): HsmsMessage {\r\n\t\treturn new HsmsMessage(\r\n\t\t\t0,\r\n\t\t\t0,\r\n\t\t\tfalse,\r\n\t\t\tnull,\r\n\t\t\tsystemBytes,\r\n\t\t\t0xffff,\r\n\t\t\t0,\r\n\t\t\tHsmsControlType.SelectReq,\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * @description Creates a Select Response message.\r\n\t * @param req The Select Request message.\r\n\t * @param status The status of the response.\r\n\t * @returns The HsmsMessage object.\r\n\t */\r\n\tstatic selectRsp(req: HsmsMessage, status: number): HsmsMessage {\r\n\t\treturn new HsmsMessage(\r\n\t\t\t0,\r\n\t\t\tstatus,\r\n\t\t\tfalse,\r\n\t\t\tnull,\r\n\t\t\treq.systemBytes,\r\n\t\t\t0xffff,\r\n\t\t\t0,\r\n\t\t\tHsmsControlType.SelectRsp,\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * @description Creates a Deselect Request message.\r\n\t * @param systemBytes The system bytes of the message.\r\n\t * @returns The HsmsMessage object.\r\n\t */\r\n\tstatic deselectReq(systemBytes: number): HsmsMessage {\r\n\t\treturn new HsmsMessage(\r\n\t\t\t0,\r\n\t\t\t0,\r\n\t\t\tfalse,\r\n\t\t\tnull,\r\n\t\t\tsystemBytes,\r\n\t\t\t0xffff,\r\n\t\t\t0,\r\n\t\t\tHsmsControlType.DeselectReq,\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * @description Creates a Deselect Response message.\r\n\t * @param req The Deselect Request message.\r\n\t * @param status The status of the response.\r\n\t * @returns The HsmsMessage object.\r\n\t */\r\n\tstatic deselectRsp(req: HsmsMessage, status: number): HsmsMessage {\r\n\t\treturn new HsmsMessage(\r\n\t\t\t0,\r\n\t\t\tstatus,\r\n\t\t\tfalse,\r\n\t\t\tnull,\r\n\t\t\treq.systemBytes,\r\n\t\t\t0xffff,\r\n\t\t\t0,\r\n\t\t\tHsmsControlType.DeselectRsp,\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * @description Creates a Link Test Request message.\r\n\t * @param systemBytes The system bytes of the message.\r\n\t * @returns The HsmsMessage object.\r\n\t */\r\n\tstatic linkTestReq(systemBytes: number): HsmsMessage {\r\n\t\treturn new HsmsMessage(\r\n\t\t\t0,\r\n\t\t\t0,\r\n\t\t\tfalse,\r\n\t\t\tnull,\r\n\t\t\tsystemBytes,\r\n\t\t\t0xffff,\r\n\t\t\t0,\r\n\t\t\tHsmsControlType.LinkTestReq,\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * @description Creates a Link Test Response message.\r\n\t * @param req The Link Test Request message.\r\n\t * @returns The HsmsMessage object.\r\n\t */\r\n\tstatic linkTestRsp(req: HsmsMessage): HsmsMessage {\r\n\t\treturn new HsmsMessage(\r\n\t\t\t0,\r\n\t\t\t0,\r\n\t\t\tfalse,\r\n\t\t\tnull,\r\n\t\t\treq.systemBytes,\r\n\t\t\t0xffff,\r\n\t\t\t0,\r\n\t\t\tHsmsControlType.LinkTestRsp,\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * @description Creates a Reject Request message.\r\n\t * @param req The message that triggered the reject.\r\n\t * @param reason The reason for the reject.\r\n\t * @returns The HsmsMessage object.\r\n\t */\r\n\tstatic rejectReq(req: HsmsMessage, reason: RejectReason): HsmsMessage {\r\n\t\t// Byte 2 (Stream) should be the sType of the rejected message if PType is not supported\r\n\t\t// But typically it's just mirroring or specific logic.\r\n\t\t// Python: b2 = h10bytes[4] (PType) if reason == NOT_SUPPORT_TYPE_P else h10bytes[5] (SType)\r\n\t\tconst b2 = reason === RejectReason.NotSupportTypeP ? req.pType : req.sType;\r\n\t\treturn new HsmsMessage(\r\n\t\t\tb2,\r\n\t\t\treason,\r\n\t\t\tfalse,\r\n\t\t\tnull,\r\n\t\t\treq.systemBytes,\r\n\t\t\t0xffff,\r\n\t\t\t0,\r\n\t\t\tHsmsControlType.RejectReq,\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * @description Creates a Separate Request message.\r\n\t * @param systemBytes The system bytes of the message.\r\n\t * @returns The HsmsMessage object.\r\n\t */\r\n\tstatic separateReq(systemBytes: number): HsmsMessage {\r\n\t\treturn new HsmsMessage(\r\n\t\t\t0,\r\n\t\t\t0,\r\n\t\t\tfalse,\r\n\t\t\tnull,\r\n\t\t\tsystemBytes,\r\n\t\t\t0xffff,\r\n\t\t\t0,\r\n\t\t\tHsmsControlType.SeparateReq,\r\n\t\t);\r\n\t}\r\n}\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"HsmsMessage.js","names":["body: AbstractSecs2Item | null"],"sources":["../../src/hsms/HsmsMessage.ts"],"sourcesContent":["import { SecsMessage } from \"../core/AbstractSecsMessage.js\";\nimport { AbstractSecs2Item } from \"../core/secs2item/AbstractSecs2Item.js\";\nimport { HsmsControlType } from \"./enums/HsmsControlType.js\";\nimport { RejectReason } from \"./enums/RejectReason.js\";\nimport { Secs2ItemParser } from \"../core/secs2item/Secs2ItemParser.js\";\n\n/**\n * @description HsmsMessage is the class that represents an HSMS message.\n * @param stream The stream number of the message.\n * @param func The function number of the message.\n * @param wBit The W-Bit of the message.\n * @param body The body of the message.\n * @param systemBytes The system bytes of the message.\n * @param deviceId The device ID of the message.\n * @param pType The P-Type of the message.\n * @param sType The S-Type of the message.\n */\nexport class HsmsMessage extends SecsMessage {\n\tconstructor(\n\t\tstream: number,\n\t\tfunc: number,\n\t\twBit: boolean,\n\t\tbody: AbstractSecs2Item | null,\n\t\tsystemBytes: number,\n\t\tdeviceId: number,\n\t\tpublic readonly pType = 0,\n\t\tpublic readonly sType = 0,\n\t) {\n\t\tsuper(stream, func, wBit, body, systemBytes, deviceId);\n\t}\n\n\t/**\n\t * @description Encodes the message to a buffer (Length + Header + Body).\n\t */\n\ttoBuffer(): Buffer {\n\t\tconst bodyBuffer = this.body ? this.body.toBuffer() : Buffer.alloc(0);\n\t\tconst header = Buffer.alloc(10);\n\n\t\t// Byte 0-1: Session ID (Device ID) or 0xFFFF\n\t\tif (this.isDataMessage()) {\n\t\t\theader.writeUInt16BE(this.deviceId, 0);\n\t\t} else {\n\t\t\theader.writeUInt16BE(0xffff, 0);\n\t\t}\n\n\t\t// Byte 2: Stream / WBit (only for Data)\n\t\t// Byte 3: Function (only for Data)\n\t\tif (this.isDataMessage()) {\n\t\t\tlet b2 = this.stream;\n\t\t\tif (this.wBit) {\n\t\t\t\tb2 |= 0x80;\n\t\t\t}\n\t\t\theader.writeUInt8(b2, 2);\n\t\t\theader.writeUInt8(this.func, 3);\n\t\t} else {\n\t\t\t// For control messages, byte 2 and 3 depend on type\n\t\t\t// But typically 0 unless SelectStatus/RejectReason\n\t\t\t// We will handle specific construction in static methods\n\t\t\t// Here we assume pType and sType are set correctly for Control Messages\n\t\t\t// Wait, P-Type is Byte 4, S-Type is Byte 5.\n\t\t\t// Byte 2 and 3 are 0 for most control messages.\n\t\t\t// EXCEPT Select Response (Byte 3 = Status) and Reject (Byte 3 = Reason).\n\t\t\t// But those are stored in 'sType' or 'func' or similar?\n\t\t\t// In this class, I store pType and sType (Byte 4, 5).\n\t\t\t// Where do I store Byte 2 and 3 for Control Messages?\n\t\t\t// The Python code:\n\t\t\t// Select Response: h10bytes = ... 0x00, select_status ...\n\t\t\t// Reject: ... b2, reject_reason ...\n\n\t\t\t// I should allow passing byte 2 and 3 specifically or handle it via polymorphism.\n\t\t\t// To keep it simple, I will use 'stream' and 'func' to hold Byte 2 and 3 for Control Messages too,\n\t\t\t// even if they don't mean Stream/Function.\n\n\t\t\theader.writeUInt8(this.stream, 2);\n\t\t\theader.writeUInt8(this.func, 3);\n\t\t}\n\n\t\t// Byte 4: P-Type\n\t\theader.writeUInt8(this.pType, 4);\n\n\t\t// Byte 5: S-Type\n\t\theader.writeUInt8(this.sType, 5);\n\n\t\t// Byte 6-9: System Bytes\n\t\theader.writeUInt32BE(this.systemBytes, 6);\n\n\t\tconst length = header.length + bodyBuffer.length;\n\t\tconst lengthBuffer = Buffer.alloc(4);\n\t\tlengthBuffer.writeUInt32BE(length, 0);\n\n\t\treturn Buffer.concat([lengthBuffer, header, bodyBuffer]);\n\t}\n\n\t/**\n\t * @description Checks if the message is a data message.\n\t * @description data message: deviceId not 0xFF 0xFF and header[4] and header[5] are 0.\n\t * @returns True if the message is a data message, false otherwise.\n\t */\n\tisDataMessage(): boolean {\n\t\treturn (this.sType as HsmsControlType) === HsmsControlType.Data;\n\t}\n\n\t/**\n\t * @description Creates an HsmsMessage from a buffer.\n\t * @param buffer The buffer containing the message data.\n\t * @returns The HsmsMessage object.\n\t */\n\tstatic fromBuffer(buffer: Buffer): HsmsMessage {\n\t\tif (buffer.length < 14) {\n\t\t\tthrow new Error(\"Buffer too short for HSMS message\");\n\t\t}\n\n\t\t// Bytes 0-3: Length (ignored here, assumed to be correct or handled by framer)\n\t\tconst header = buffer.subarray(4, 14);\n\t\tconst bodyBuffer = buffer.subarray(14);\n\n\t\tconst sessionId = header.readUInt16BE(0);\n\t\tconst byte2 = header.readUInt8(2);\n\t\tconst byte3 = header.readUInt8(3);\n\t\tconst pType = header.readUInt8(4);\n\t\tconst sType = header.readUInt8(5);\n\t\tconst systemBytes = header.readUInt32BE(6);\n\n\t\tlet stream = 0;\n\t\tlet func = 0;\n\t\tlet wBit = false;\n\t\tconst deviceId = sessionId;\n\t\tlet body: AbstractSecs2Item | null = null;\n\n\t\tif ((sType as HsmsControlType) === HsmsControlType.Data) {\n\t\t\tstream = byte2 & 0x7f;\n\t\t\twBit = (byte2 & 0x80) !== 0;\n\t\t\tfunc = byte3;\n\n\t\t\tif (bodyBuffer.length > 0) {\n\t\t\t\tconst result = Secs2ItemParser.fromBuffer(bodyBuffer);\n\t\t\t\tbody = result.item;\n\t\t\t}\n\t\t} else {\n\t\t\t// Control Message\n\t\t\t// Mapping Byte 2/3 to stream/func to preserve data (e.g. Select Status)\n\t\t\tstream = byte2;\n\t\t\tfunc = byte3;\n\t\t\t// deviceId is usually ignored or 0xFFFF, but we keep what we read\n\t\t}\n\n\t\treturn new HsmsMessage(\n\t\t\tstream,\n\t\t\tfunc,\n\t\t\twBit,\n\t\t\tbody,\n\t\t\tsystemBytes,\n\t\t\tdeviceId,\n\t\t\tpType,\n\t\t\tsType,\n\t\t);\n\t}\n\n\t// Factory methods for Control Messages\n\t/**\n\t * @description Creates a Select Request message.\n\t * @param systemBytes The system bytes of the message.\n\t * @returns The HsmsMessage object.\n\t */\n\tstatic selectReq(systemBytes: number): HsmsMessage {\n\t\treturn new HsmsMessage(\n\t\t\t0,\n\t\t\t0,\n\t\t\tfalse,\n\t\t\tnull,\n\t\t\tsystemBytes,\n\t\t\t0xffff,\n\t\t\t0,\n\t\t\tHsmsControlType.SelectReq,\n\t\t);\n\t}\n\n\t/**\n\t * @description Creates a Select Response message.\n\t * @param req The Select Request message.\n\t * @param status The status of the response.\n\t * @returns The HsmsMessage object.\n\t */\n\tstatic selectRsp(req: HsmsMessage, status: number): HsmsMessage {\n\t\treturn new HsmsMessage(\n\t\t\t0,\n\t\t\tstatus,\n\t\t\tfalse,\n\t\t\tnull,\n\t\t\treq.systemBytes,\n\t\t\t0xffff,\n\t\t\t0,\n\t\t\tHsmsControlType.SelectRsp,\n\t\t);\n\t}\n\n\t/**\n\t * @description Creates a Deselect Request message.\n\t * @param systemBytes The system bytes of the message.\n\t * @returns The HsmsMessage object.\n\t */\n\tstatic deselectReq(systemBytes: number): HsmsMessage {\n\t\treturn new HsmsMessage(\n\t\t\t0,\n\t\t\t0,\n\t\t\tfalse,\n\t\t\tnull,\n\t\t\tsystemBytes,\n\t\t\t0xffff,\n\t\t\t0,\n\t\t\tHsmsControlType.DeselectReq,\n\t\t);\n\t}\n\n\t/**\n\t * @description Creates a Deselect Response message.\n\t * @param req The Deselect Request message.\n\t * @param status The status of the response.\n\t * @returns The HsmsMessage object.\n\t */\n\tstatic deselectRsp(req: HsmsMessage, status: number): HsmsMessage {\n\t\treturn new HsmsMessage(\n\t\t\t0,\n\t\t\tstatus,\n\t\t\tfalse,\n\t\t\tnull,\n\t\t\treq.systemBytes,\n\t\t\t0xffff,\n\t\t\t0,\n\t\t\tHsmsControlType.DeselectRsp,\n\t\t);\n\t}\n\n\t/**\n\t * @description Creates a Link Test Request message.\n\t * @param systemBytes The system bytes of the message.\n\t * @returns The HsmsMessage object.\n\t */\n\tstatic linkTestReq(systemBytes: number): HsmsMessage {\n\t\treturn new HsmsMessage(\n\t\t\t0,\n\t\t\t0,\n\t\t\tfalse,\n\t\t\tnull,\n\t\t\tsystemBytes,\n\t\t\t0xffff,\n\t\t\t0,\n\t\t\tHsmsControlType.LinkTestReq,\n\t\t);\n\t}\n\n\t/**\n\t * @description Creates a Link Test Response message.\n\t * @param req The Link Test Request message.\n\t * @returns The HsmsMessage object.\n\t */\n\tstatic linkTestRsp(req: HsmsMessage): HsmsMessage {\n\t\treturn new HsmsMessage(\n\t\t\t0,\n\t\t\t0,\n\t\t\tfalse,\n\t\t\tnull,\n\t\t\treq.systemBytes,\n\t\t\t0xffff,\n\t\t\t0,\n\t\t\tHsmsControlType.LinkTestRsp,\n\t\t);\n\t}\n\n\t/**\n\t * @description Creates a Reject Request message.\n\t * @param req The message that triggered the reject.\n\t * @param reason The reason for the reject.\n\t * @returns The HsmsMessage object.\n\t */\n\tstatic rejectReq(req: HsmsMessage, reason: RejectReason): HsmsMessage {\n\t\t// Byte 2 (Stream) should be the sType of the rejected message if PType is not supported\n\t\t// But typically it's just mirroring or specific logic.\n\t\t// Python: b2 = h10bytes[4] (PType) if reason == NOT_SUPPORT_TYPE_P else h10bytes[5] (SType)\n\t\tconst b2 = reason === RejectReason.NotSupportTypeP ? req.pType : req.sType;\n\t\treturn new HsmsMessage(\n\t\t\tb2,\n\t\t\treason,\n\t\t\tfalse,\n\t\t\tnull,\n\t\t\treq.systemBytes,\n\t\t\t0xffff,\n\t\t\t0,\n\t\t\tHsmsControlType.RejectReq,\n\t\t);\n\t}\n\n\t/**\n\t * @description Creates a Separate Request message.\n\t * @param systemBytes The system bytes of the message.\n\t * @returns The HsmsMessage object.\n\t */\n\tstatic separateReq(systemBytes: number): HsmsMessage {\n\t\treturn new HsmsMessage(\n\t\t\t0,\n\t\t\t0,\n\t\t\tfalse,\n\t\t\tnull,\n\t\t\tsystemBytes,\n\t\t\t0xffff,\n\t\t\t0,\n\t\t\tHsmsControlType.SeparateReq,\n\t\t);\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAiBA,IAAa,cAAb,MAAa,oBAAoB,YAAY;CAC5C,YACC,QACA,MACA,MACA,MACA,aACA,UACA,AAAgB,QAAQ,GACxB,AAAgB,QAAQ,GACvB;AACD,QAAM,QAAQ,MAAM,MAAM,MAAM,aAAa,SAAS;EAHtC;EACA;;;;;CAQjB,WAAmB;EAClB,MAAM,aAAa,KAAK,OAAO,KAAK,KAAK,UAAU,GAAG,OAAO,MAAM,EAAE;EACrE,MAAM,SAAS,OAAO,MAAM,GAAG;AAG/B,MAAI,KAAK,eAAe,CACvB,QAAO,cAAc,KAAK,UAAU,EAAE;MAEtC,QAAO,cAAc,OAAQ,EAAE;AAKhC,MAAI,KAAK,eAAe,EAAE;GACzB,IAAI,KAAK,KAAK;AACd,OAAI,KAAK,KACR,OAAM;AAEP,UAAO,WAAW,IAAI,EAAE;AACxB,UAAO,WAAW,KAAK,MAAM,EAAE;SACzB;AAmBN,UAAO,WAAW,KAAK,QAAQ,EAAE;AACjC,UAAO,WAAW,KAAK,MAAM,EAAE;;AAIhC,SAAO,WAAW,KAAK,OAAO,EAAE;AAGhC,SAAO,WAAW,KAAK,OAAO,EAAE;AAGhC,SAAO,cAAc,KAAK,aAAa,EAAE;EAEzC,MAAM,SAAS,OAAO,SAAS,WAAW;EAC1C,MAAM,eAAe,OAAO,MAAM,EAAE;AACpC,eAAa,cAAc,QAAQ,EAAE;AAErC,SAAO,OAAO,OAAO;GAAC;GAAc;GAAQ;GAAW,CAAC;;;;;;;CAQzD,gBAAyB;AACxB,SAAQ,KAAK,UAA8B,gBAAgB;;;;;;;CAQ5D,OAAO,WAAW,QAA6B;AAC9C,MAAI,OAAO,SAAS,GACnB,OAAM,IAAI,MAAM,oCAAoC;EAIrD,MAAM,SAAS,OAAO,SAAS,GAAG,GAAG;EACrC,MAAM,aAAa,OAAO,SAAS,GAAG;EAEtC,MAAM,YAAY,OAAO,aAAa,EAAE;EACxC,MAAM,QAAQ,OAAO,UAAU,EAAE;EACjC,MAAM,QAAQ,OAAO,UAAU,EAAE;EACjC,MAAM,QAAQ,OAAO,UAAU,EAAE;EACjC,MAAM,QAAQ,OAAO,UAAU,EAAE;EACjC,MAAM,cAAc,OAAO,aAAa,EAAE;EAE1C,IAAI,SAAS;EACb,IAAI,OAAO;EACX,IAAI,OAAO;EACX,MAAM,WAAW;EACjB,IAAIA,OAAiC;AAErC,MAAK,UAA8B,gBAAgB,MAAM;AACxD,YAAS,QAAQ;AACjB,WAAQ,QAAQ,SAAU;AAC1B,UAAO;AAEP,OAAI,WAAW,SAAS,EAEvB,QADe,gBAAgB,WAAW,WAAW,CACvC;SAET;AAGN,YAAS;AACT,UAAO;;AAIR,SAAO,IAAI,YACV,QACA,MACA,MACA,MACA,aACA,UACA,OACA,MACA;;;;;;;CASF,OAAO,UAAU,aAAkC;AAClD,SAAO,IAAI,YACV,GACA,GACA,OACA,MACA,aACA,OACA,GACA,gBAAgB,UAChB;;;;;;;;CASF,OAAO,UAAU,KAAkB,QAA6B;AAC/D,SAAO,IAAI,YACV,GACA,QACA,OACA,MACA,IAAI,aACJ,OACA,GACA,gBAAgB,UAChB;;;;;;;CAQF,OAAO,YAAY,aAAkC;AACpD,SAAO,IAAI,YACV,GACA,GACA,OACA,MACA,aACA,OACA,GACA,gBAAgB,YAChB;;;;;;;;CASF,OAAO,YAAY,KAAkB,QAA6B;AACjE,SAAO,IAAI,YACV,GACA,QACA,OACA,MACA,IAAI,aACJ,OACA,GACA,gBAAgB,YAChB;;;;;;;CAQF,OAAO,YAAY,aAAkC;AACpD,SAAO,IAAI,YACV,GACA,GACA,OACA,MACA,aACA,OACA,GACA,gBAAgB,YAChB;;;;;;;CAQF,OAAO,YAAY,KAA+B;AACjD,SAAO,IAAI,YACV,GACA,GACA,OACA,MACA,IAAI,aACJ,OACA,GACA,gBAAgB,YAChB;;;;;;;;CASF,OAAO,UAAU,KAAkB,QAAmC;AAKrE,SAAO,IAAI,YADA,WAAW,aAAa,kBAAkB,IAAI,QAAQ,IAAI,OAGpE,QACA,OACA,MACA,IAAI,aACJ,OACA,GACA,gBAAgB,UAChB;;;;;;;CAQF,OAAO,YAAY,aAAkC;AACpD,SAAO,IAAI,YACV,GACA,GACA,OACA,MACA,aACA,OACA,GACA,gBAAgB,YAChB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HsmsPassiveCommunicator.js","names":["resolveFirstListen: (() => void) | null","t8Timer: NodeJS.Timeout | null","t7Timer: NodeJS.Timeout | null","msg: HsmsMessage"],"sources":["../../src/hsms/HsmsPassiveCommunicator.ts"],"sourcesContent":["import { Server, Socket, createServer } from \"net\";\r\nimport {\r\n\tHsmsCommunicator,\r\n\tHsmsCommunicatorConfig,\r\n\tHsmsState,\r\n} from \"./HsmsCommunicator.js\";\r\nimport { HsmsMessage } from \"./HsmsMessage.js\";\r\nimport { HsmsControlType } from \"./enums/HsmsControlType.js\";\r\nimport { SelectStatus } from \"./enums/SelectStatus.js\";\r\nimport { RejectReason } from \"./enums/RejectReason.js\";\r\n\r\nexport interface HsmsPassiveCommunicatorConfig extends HsmsCommunicatorConfig {\r\n\ttimeoutRebind?: number;\r\n}\r\n\r\n/**\r\n * @description HsmsPassiveCommunicator is the class that represents an HSMS passive communicator.\r\n */\r\nexport class HsmsPassiveCommunicator extends HsmsCommunicator {\r\n\tprivate server: Server | null = null;\r\n\tprivate shouldStop = false;\r\n\tprivate serverLoopPromise: Promise<void> | null = null;\r\n\tprivate timeoutRebind = 5;\r\n\r\n\tconstructor(config: HsmsPassiveCommunicatorConfig) {\r\n\t\tsuper(config);\r\n\t\tif (config.timeoutRebind !== undefined) {\r\n\t\t\tthis.timeoutRebind = config.timeoutRebind;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * @description Opens the passive communicator.\r\n\t */\r\n\tasync open(): Promise<void> {\r\n\t\tif (this.serverLoopPromise) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tthis.shouldStop = false;\r\n\r\n\t\tlet resolveFirstListen: (() => void) | null = null;\r\n\t\tconst firstListen = new Promise<void>((resolve) => {\r\n\t\t\tresolveFirstListen = resolve;\r\n\t\t});\r\n\r\n\t\tthis.serverLoopPromise = this.runServerLoop(() => {\r\n\t\t\tresolveFirstListen?.();\r\n\t\t\tresolveFirstListen = null;\r\n\t\t}).catch((err: unknown) => {\r\n\t\t\tthis.emit(\"error\", err instanceof Error ? err : new Error(String(err)));\r\n\t\t});\r\n\r\n\t\tawait firstListen;\r\n\t}\r\n\r\n\t/**\r\n\t * @description Runs the server loop.\r\n\t * @param onFirstListening The callback function to be called when the first listening is completed.\r\n\t * @returns A Promise that resolves when the server loop is stopped.\r\n\t */\r\n\tprivate async runServerLoop(onFirstListening: () => void): Promise<void> {\r\n\t\tlet first = true;\r\n\t\twhile (!this.shouldStop) {\r\n\t\t\ttry {\r\n\t\t\t\tawait this.listenOnce(first ? onFirstListening : null);\r\n\t\t\t} catch (err) {\r\n\t\t\t\tif (!this.shouldStop) {\r\n\t\t\t\t\tthis.emit(\r\n\t\t\t\t\t\t\"error\",\r\n\t\t\t\t\t\terr instanceof Error ? err : new Error(String(err)),\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t\tif (!this.shouldStop) {\r\n\t\t\t\t\tawait new Promise((resolve) =>\r\n\t\t\t\t\t\tsetTimeout(resolve, this.timeoutRebind * 1000),\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tfirst = false;\r\n\t\t\tif (this.shouldStop) return;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * @description Listens for a single connection.\r\n\t * @param onListening The callback function to be called when the connection is established.\r\n\t * @returns A Promise that resolves when the connection is closed.\r\n\t */\r\n\tprivate async listenOnce(onListening: (() => void) | null): Promise<void> {\r\n\t\treturn new Promise((resolve, reject) => {\r\n\t\t\tconst server = createServer((socket) => {\r\n\t\t\t\tvoid this.handleIncomingSocket(socket);\r\n\t\t\t});\r\n\t\t\tthis.server = server;\r\n\r\n\t\t\tlet hasConnected = false;\r\n\t\t\tlet settled = false;\r\n\r\n\t\t\tconst cleanup = () => {\r\n\t\t\t\tserver.removeListener(\"error\", onServerError);\r\n\t\t\t\tserver.removeListener(\"close\", onServerClose);\r\n\t\t\t\tthis.removeListener(\"connected\", onConnected);\r\n\t\t\t\tthis.removeListener(\"disconnected\", onDisconnected);\r\n\t\t\t};\r\n\r\n\t\t\tconst finish = (err?: Error) => {\r\n\t\t\t\tif (settled) return;\r\n\t\t\t\tsettled = true;\r\n\t\t\t\tif (this.server === server) {\r\n\t\t\t\t\tthis.server = null;\r\n\t\t\t\t}\r\n\t\t\t\tcleanup();\r\n\t\t\t\tif (err) reject(err);\r\n\t\t\t\telse resolve();\r\n\t\t\t};\r\n\r\n\t\t\tconst closeServer = () => {\r\n\t\t\t\tif (settled) return;\r\n\t\t\t\tif (!server.listening) {\r\n\t\t\t\t\tfinish();\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tserver.close((err) => {\r\n\t\t\t\t\tif (err) finish(err);\r\n\t\t\t\t\telse finish();\r\n\t\t\t\t});\r\n\t\t\t};\r\n\r\n\t\t\tconst onServerError = (err: Error) => {\r\n\t\t\t\tfinish(err);\r\n\t\t\t};\r\n\r\n\t\t\tconst onServerClose = () => {\r\n\t\t\t\tfinish();\r\n\t\t\t};\r\n\r\n\t\t\tconst onConnected = () => {\r\n\t\t\t\thasConnected = true;\r\n\t\t\t};\r\n\r\n\t\t\tconst onDisconnected = () => {\r\n\t\t\t\tif (!hasConnected) return;\r\n\t\t\t\tcloseServer();\r\n\t\t\t};\r\n\r\n\t\t\tserver.on(\"error\", onServerError);\r\n\t\t\tserver.on(\"close\", onServerClose);\r\n\t\t\tthis.on(\"connected\", onConnected);\r\n\t\t\tthis.on(\"disconnected\", onDisconnected);\r\n\r\n\t\t\tserver.listen(this.port, this.ip, () => {\r\n\t\t\t\tonListening?.();\r\n\t\t\t});\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * @description Handles an incoming socket connection.\r\n\t * @param socket The socket object representing the incoming connection.\r\n\t * @returns A Promise that resolves when the socket connection is handled.\r\n\t */\r\n\tprivate async handleIncomingSocket(socket: Socket): Promise<void> {\r\n\t\tsocket.setNoDelay(true);\r\n\r\n\t\tif (!this.socket || this.socket.destroyed) {\r\n\t\t\tconst promoted = await this.handleSocketUntilSelected(socket);\r\n\t\t\tif (promoted) return;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tawait this.handleSocketUntilSelected(socket);\r\n\t}\r\n\r\n\t/**\r\n\t * @description Handles a socket connection until it is selected.\r\n\t * @param socket The socket object representing the connection.\r\n\t * @returns A Promise that resolves with a boolean indicating whether the socket was promoted to selected.\r\n\t */\r\n\tprivate async handleSocketUntilSelected(socket: Socket): Promise<boolean> {\r\n\t\tlet buffer = Buffer.alloc(0);\r\n\t\tlet t8Timer: NodeJS.Timeout | null = null;\r\n\t\tlet t7Timer: NodeJS.Timeout | null = null;\r\n\r\n\t\tconst clearT8 = () => {\r\n\t\t\tif (t8Timer) {\r\n\t\t\t\tclearTimeout(t8Timer);\r\n\t\t\t\tt8Timer = null;\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tconst resetT8 = () => {\r\n\t\t\tclearT8();\r\n\t\t\tif (this.timeoutT8 <= 0) return;\r\n\t\t\tt8Timer = setTimeout(() => {\r\n\t\t\t\tt8Timer = null;\r\n\t\t\t\tif (buffer.length > 0 && !socket.destroyed) {\r\n\t\t\t\t\tthis.emit(\"error\", new Error(\"T8 Timeout\"));\r\n\t\t\t\t\tsocket.destroy();\r\n\t\t\t\t}\r\n\t\t\t}, this.timeoutT8 * 1000);\r\n\t\t};\r\n\r\n\t\tconst clearT7 = () => {\r\n\t\t\tif (t7Timer) {\r\n\t\t\t\tclearTimeout(t7Timer);\r\n\t\t\t\tt7Timer = null;\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tconst resetT7 = () => {\r\n\t\t\tclearT7();\r\n\t\t\tif (this.timeoutT7 <= 0) return;\r\n\t\t\tt7Timer = setTimeout(() => {\r\n\t\t\t\tt7Timer = null;\r\n\t\t\t\tif (!socket.destroyed) {\r\n\t\t\t\t\tsocket.destroy();\r\n\t\t\t\t}\r\n\t\t\t}, this.timeoutT7 * 1000);\r\n\t\t};\r\n\r\n\t\tconst sendSocketBuffer = async (buf: Buffer): Promise<void> => {\r\n\t\t\tawait new Promise<void>((resolve, reject) => {\r\n\t\t\t\tsocket.write(buf, (err) => {\r\n\t\t\t\t\tif (err) reject(err);\r\n\t\t\t\t\telse resolve();\r\n\t\t\t\t});\r\n\t\t\t});\r\n\t\t};\r\n\r\n\t\tconst cleanup = () => {\r\n\t\t\tclearT8();\r\n\t\t\tclearT7();\r\n\t\t};\r\n\r\n\t\tconst promoteToSelected = (selectReq: HsmsMessage) => {\r\n\t\t\tsocket.removeListener(\"data\", onData);\r\n\t\t\tsocket.removeListener(\"close\", onClose);\r\n\t\t\tsocket.removeListener(\"end\", onEnd);\r\n\t\t\tsocket.removeListener(\"error\", onError);\r\n\t\t\tcleanup();\r\n\t\t\tthis.handleSocketEvents(socket);\r\n\t\t\tthis.handleSelectReq(selectReq);\r\n\t\t};\r\n\r\n\t\tconst handlePreSelectedMessage = async (msg: HsmsMessage) => {\r\n\t\t\tswitch (msg.sType as HsmsControlType) {\r\n\t\t\t\tcase HsmsControlType.Data: {\r\n\t\t\t\t\tconst rsp = HsmsMessage.rejectReq(msg, RejectReason.NotSelected);\r\n\t\t\t\t\tawait sendSocketBuffer(rsp.toBuffer());\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase HsmsControlType.LinkTestReq: {\r\n\t\t\t\t\tconst rsp = HsmsMessage.linkTestRsp(msg);\r\n\t\t\t\t\tawait sendSocketBuffer(rsp.toBuffer());\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase HsmsControlType.SeparateReq: {\r\n\t\t\t\t\tsocket.destroy();\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase HsmsControlType.SelectReq: {\r\n\t\t\t\t\tif (\r\n\t\t\t\t\t\tthis.socket &&\r\n\t\t\t\t\t\t!this.socket.destroyed &&\r\n\t\t\t\t\t\tthis.state === HsmsState.Selected\r\n\t\t\t\t\t) {\r\n\t\t\t\t\t\tconst rsp = HsmsMessage.selectRsp(msg, SelectStatus.AlreadyUsed);\r\n\t\t\t\t\t\tawait sendSocketBuffer(rsp.toBuffer());\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tpromoteToSelected(msg);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase HsmsControlType.SelectRsp:\r\n\t\t\t\tcase HsmsControlType.LinkTestRsp: {\r\n\t\t\t\t\tconst rsp = HsmsMessage.rejectReq(\r\n\t\t\t\t\t\tmsg,\r\n\t\t\t\t\t\tRejectReason.TransactionNotOpen,\r\n\t\t\t\t\t);\r\n\t\t\t\t\tawait sendSocketBuffer(rsp.toBuffer());\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tcase HsmsControlType.RejectReq: {\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tdefault: {\r\n\t\t\t\t\tconst reason =\r\n\t\t\t\t\t\tmsg.pType !== 0\r\n\t\t\t\t\t\t\t? RejectReason.NotSupportTypeP\r\n\t\t\t\t\t\t\t: RejectReason.NotSupportTypeS;\r\n\t\t\t\t\tconst rsp = HsmsMessage.rejectReq(msg, reason);\r\n\t\t\t\t\tawait sendSocketBuffer(rsp.toBuffer());\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tlet processing = false;\r\n\t\tconst processIncoming = async () => {\r\n\t\t\tif (processing) return;\r\n\t\t\tprocessing = true;\r\n\t\t\ttry {\r\n\t\t\t\twhile (true) {\r\n\t\t\t\t\tif (buffer.length < 4) return;\r\n\t\t\t\t\tconst length = buffer.readUInt32BE(0);\r\n\t\t\t\t\tif (length < 10) {\r\n\t\t\t\t\t\tthis.emit(\"error\", new Error(\"Receive message size < 10\"));\r\n\t\t\t\t\t\tbuffer = Buffer.alloc(0);\r\n\t\t\t\t\t\tsocket.destroy();\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (buffer.length < 4 + length) return;\r\n\r\n\t\t\t\t\tconst msgBuffer = buffer.subarray(0, 4 + length);\r\n\t\t\t\t\tbuffer = buffer.subarray(4 + length);\r\n\t\t\t\t\tif (buffer.length === 0) clearT8();\r\n\r\n\t\t\t\t\tlet msg: HsmsMessage;\r\n\t\t\t\t\ttry {\r\n\t\t\t\t\t\tmsg = HsmsMessage.fromBuffer(msgBuffer);\r\n\t\t\t\t\t} catch (err) {\r\n\t\t\t\t\t\tthis.emit(\r\n\t\t\t\t\t\t\t\"error\",\r\n\t\t\t\t\t\t\terr instanceof Error ? err : new Error(String(err)),\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t\tsocket.destroy();\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tresetT7();\r\n\t\t\t\t\tawait handlePreSelectedMessage(msg);\r\n\r\n\t\t\t\t\tif (this.socket === socket && this.state === HsmsState.Selected) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t} catch (err) {\r\n\t\t\t\tthis.emit(\"error\", err instanceof Error ? err : new Error(String(err)));\r\n\t\t\t\tsocket.destroy();\r\n\t\t\t} finally {\r\n\t\t\t\tprocessing = false;\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tconst onData = (data: Buffer) => {\r\n\t\t\tbuffer = Buffer.concat([buffer, data]);\r\n\t\t\tresetT8();\r\n\t\t\tvoid processIncoming();\r\n\t\t};\r\n\r\n\t\tconst onClose = () => {\r\n\t\t\tcleanup();\r\n\t\t};\r\n\r\n\t\tconst onEnd = () => {\r\n\t\t\tif (!socket.destroyed) {\r\n\t\t\t\tsocket.destroy();\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tconst onError = (err: Error) => {\r\n\t\t\tthis.emit(\"error\", err);\r\n\t\t};\r\n\r\n\t\tsocket.on(\"data\", onData);\r\n\t\tsocket.on(\"close\", onClose);\r\n\t\tsocket.on(\"end\", onEnd);\r\n\t\tsocket.on(\"error\", onError);\r\n\t\tresetT7();\r\n\r\n\t\tawait new Promise<void>((resolve) => {\r\n\t\t\tsocket.once(\"close\", () => resolve());\r\n\t\t});\r\n\r\n\t\treturn this.socket === socket && this.state === HsmsState.Selected;\r\n\t}\r\n\r\n\tasync close(): Promise<void> {\r\n\t\tthis.shouldStop = true;\r\n\t\t// Close client connection first\r\n\t\tif (this.socket) {\r\n\t\t\tthis.socket.end();\r\n\t\t\tthis.socket.destroy();\r\n\t\t\tthis.socket = null;\r\n\t\t}\r\n\r\n\t\t// Stop listening\r\n\t\tconst server = this.server;\r\n\t\tif (server) {\r\n\t\t\tawait new Promise<void>((resolve, reject) => {\r\n\t\t\t\tserver.close((err) => {\r\n\t\t\t\t\tthis.server = null;\r\n\t\t\t\t\tif (err) reject(err);\r\n\t\t\t\t\telse resolve();\r\n\t\t\t\t});\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tif (this.serverLoopPromise) {\r\n\t\t\tconst loop = this.serverLoopPromise;\r\n\t\t\tthis.serverLoopPromise = null;\r\n\t\t\tawait loop;\r\n\t\t}\r\n\t}\r\n}\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"HsmsPassiveCommunicator.js","names":["resolveFirstListen: (() => void) | null","t8Timer: NodeJS.Timeout | null","t7Timer: NodeJS.Timeout | null","msg: HsmsMessage"],"sources":["../../src/hsms/HsmsPassiveCommunicator.ts"],"sourcesContent":["import { Server, Socket, createServer } from \"net\";\nimport {\n\tHsmsCommunicator,\n\tHsmsCommunicatorConfig,\n\tHsmsState,\n} from \"./HsmsCommunicator.js\";\nimport { HsmsMessage } from \"./HsmsMessage.js\";\nimport { HsmsControlType } from \"./enums/HsmsControlType.js\";\nimport { SelectStatus } from \"./enums/SelectStatus.js\";\nimport { RejectReason } from \"./enums/RejectReason.js\";\n\nexport interface HsmsPassiveCommunicatorConfig extends HsmsCommunicatorConfig {\n\ttimeoutRebind?: number;\n}\n\n/**\n * @description HsmsPassiveCommunicator is the class that represents an HSMS passive communicator.\n */\nexport class HsmsPassiveCommunicator extends HsmsCommunicator {\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: HsmsPassiveCommunicatorConfig) {\n\t\tsuper(config);\n\t\tif (config.timeoutRebind !== undefined) {\n\t\t\tthis.timeoutRebind = config.timeoutRebind;\n\t\t}\n\t}\n\n\t/**\n\t * @description Opens the passive communicator.\n\t */\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\t/**\n\t * @description Runs the server loop.\n\t * @param onFirstListening The callback function to be called when the first listening is completed.\n\t * @returns A Promise that resolves when the server loop is stopped.\n\t */\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\t/**\n\t * @description Listens for a single connection.\n\t * @param onListening The callback function to be called when the connection is established.\n\t * @returns A Promise that resolves when the connection is closed.\n\t */\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((err) => {\n\t\t\t\t\tif (err) finish(err);\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\tfinish(err);\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\t/**\n\t * @description Handles an incoming socket connection.\n\t * @param socket The socket object representing the incoming connection.\n\t * @returns A Promise that resolves when the socket connection is handled.\n\t */\n\tprivate async handleIncomingSocket(socket: Socket): Promise<void> {\n\t\tsocket.setNoDelay(true);\n\n\t\tif (!this.socket || this.socket.destroyed) {\n\t\t\tconst promoted = await this.handleSocketUntilSelected(socket);\n\t\t\tif (promoted) return;\n\t\t\treturn;\n\t\t}\n\n\t\tawait this.handleSocketUntilSelected(socket);\n\t}\n\n\t/**\n\t * @description Handles a socket connection until it is selected.\n\t * @param socket The socket object representing the connection.\n\t * @returns A Promise that resolves with a boolean indicating whether the socket was promoted to selected.\n\t */\n\tprivate async handleSocketUntilSelected(socket: Socket): Promise<boolean> {\n\t\tlet buffer = Buffer.alloc(0);\n\t\tlet t8Timer: NodeJS.Timeout | null = null;\n\t\tlet t7Timer: NodeJS.Timeout | null = null;\n\n\t\tconst clearT8 = () => {\n\t\t\tif (t8Timer) {\n\t\t\t\tclearTimeout(t8Timer);\n\t\t\t\tt8Timer = null;\n\t\t\t}\n\t\t};\n\n\t\tconst resetT8 = () => {\n\t\t\tclearT8();\n\t\t\tif (this.timeoutT8 <= 0) return;\n\t\t\tt8Timer = setTimeout(() => {\n\t\t\t\tt8Timer = null;\n\t\t\t\tif (buffer.length > 0 && !socket.destroyed) {\n\t\t\t\t\tthis.emit(\"error\", new Error(\"T8 Timeout\"));\n\t\t\t\t\tsocket.destroy();\n\t\t\t\t}\n\t\t\t}, this.timeoutT8 * 1000);\n\t\t};\n\n\t\tconst clearT7 = () => {\n\t\t\tif (t7Timer) {\n\t\t\t\tclearTimeout(t7Timer);\n\t\t\t\tt7Timer = null;\n\t\t\t}\n\t\t};\n\n\t\tconst resetT7 = () => {\n\t\t\tclearT7();\n\t\t\tif (this.timeoutT7 <= 0) return;\n\t\t\tt7Timer = setTimeout(() => {\n\t\t\t\tt7Timer = null;\n\t\t\t\tif (!socket.destroyed) {\n\t\t\t\t\tsocket.destroy();\n\t\t\t\t}\n\t\t\t}, this.timeoutT7 * 1000);\n\t\t};\n\n\t\tconst sendSocketBuffer = async (buf: Buffer): Promise<void> => {\n\t\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\t\tsocket.write(buf, (err) => {\n\t\t\t\t\tif (err) reject(err);\n\t\t\t\t\telse resolve();\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\n\t\tconst cleanup = () => {\n\t\t\tclearT8();\n\t\t\tclearT7();\n\t\t};\n\n\t\tconst promoteToSelected = (selectReq: HsmsMessage) => {\n\t\t\tsocket.removeListener(\"data\", onData);\n\t\t\tsocket.removeListener(\"close\", onClose);\n\t\t\tsocket.removeListener(\"end\", onEnd);\n\t\t\tsocket.removeListener(\"error\", onError);\n\t\t\tcleanup();\n\t\t\tthis.handleSocketEvents(socket);\n\t\t\tthis.handleSelectReq(selectReq);\n\t\t};\n\n\t\tconst handlePreSelectedMessage = async (msg: HsmsMessage) => {\n\t\t\tswitch (msg.sType as HsmsControlType) {\n\t\t\t\tcase HsmsControlType.Data: {\n\t\t\t\t\tconst rsp = HsmsMessage.rejectReq(msg, RejectReason.NotSelected);\n\t\t\t\t\tawait sendSocketBuffer(rsp.toBuffer());\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase HsmsControlType.LinkTestReq: {\n\t\t\t\t\tconst rsp = HsmsMessage.linkTestRsp(msg);\n\t\t\t\t\tawait sendSocketBuffer(rsp.toBuffer());\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase HsmsControlType.SeparateReq: {\n\t\t\t\t\tsocket.destroy();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase HsmsControlType.SelectReq: {\n\t\t\t\t\tif (\n\t\t\t\t\t\tthis.socket &&\n\t\t\t\t\t\t!this.socket.destroyed &&\n\t\t\t\t\t\tthis.state === HsmsState.Selected\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst rsp = HsmsMessage.selectRsp(msg, SelectStatus.AlreadyUsed);\n\t\t\t\t\t\tawait sendSocketBuffer(rsp.toBuffer());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpromoteToSelected(msg);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase HsmsControlType.SelectRsp:\n\t\t\t\tcase HsmsControlType.LinkTestRsp: {\n\t\t\t\t\tconst rsp = HsmsMessage.rejectReq(\n\t\t\t\t\t\tmsg,\n\t\t\t\t\t\tRejectReason.TransactionNotOpen,\n\t\t\t\t\t);\n\t\t\t\t\tawait sendSocketBuffer(rsp.toBuffer());\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase HsmsControlType.RejectReq: {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault: {\n\t\t\t\t\tconst reason =\n\t\t\t\t\t\tmsg.pType !== 0\n\t\t\t\t\t\t\t? RejectReason.NotSupportTypeP\n\t\t\t\t\t\t\t: RejectReason.NotSupportTypeS;\n\t\t\t\t\tconst rsp = HsmsMessage.rejectReq(msg, reason);\n\t\t\t\t\tawait sendSocketBuffer(rsp.toBuffer());\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tlet processing = false;\n\t\tconst processIncoming = async () => {\n\t\t\tif (processing) return;\n\t\t\tprocessing = true;\n\t\t\ttry {\n\t\t\t\twhile (true) {\n\t\t\t\t\tif (buffer.length < 4) return;\n\t\t\t\t\tconst length = buffer.readUInt32BE(0);\n\t\t\t\t\tif (length < 10) {\n\t\t\t\t\t\tthis.emit(\"error\", new Error(\"Receive message size < 10\"));\n\t\t\t\t\t\tbuffer = Buffer.alloc(0);\n\t\t\t\t\t\tsocket.destroy();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (buffer.length < 4 + length) return;\n\n\t\t\t\t\tconst msgBuffer = buffer.subarray(0, 4 + length);\n\t\t\t\t\tbuffer = buffer.subarray(4 + length);\n\t\t\t\t\tif (buffer.length === 0) clearT8();\n\n\t\t\t\t\tlet msg: HsmsMessage;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tmsg = HsmsMessage.fromBuffer(msgBuffer);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tthis.emit(\n\t\t\t\t\t\t\t\"error\",\n\t\t\t\t\t\t\terr instanceof Error ? err : new Error(String(err)),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tsocket.destroy();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tresetT7();\n\t\t\t\t\tawait handlePreSelectedMessage(msg);\n\n\t\t\t\t\tif (this.socket === socket && this.state === HsmsState.Selected) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tthis.emit(\"error\", err instanceof Error ? err : new Error(String(err)));\n\t\t\t\tsocket.destroy();\n\t\t\t} finally {\n\t\t\t\tprocessing = false;\n\t\t\t}\n\t\t};\n\n\t\tconst onData = (data: Buffer) => {\n\t\t\tbuffer = Buffer.concat([buffer, data]);\n\t\t\tresetT8();\n\t\t\tvoid processIncoming();\n\t\t};\n\n\t\tconst onClose = () => {\n\t\t\tcleanup();\n\t\t};\n\n\t\tconst onEnd = () => {\n\t\t\tif (!socket.destroyed) {\n\t\t\t\tsocket.destroy();\n\t\t\t}\n\t\t};\n\n\t\tconst onError = (err: Error) => {\n\t\t\tthis.emit(\"error\", err);\n\t\t};\n\n\t\tsocket.on(\"data\", onData);\n\t\tsocket.on(\"close\", onClose);\n\t\tsocket.on(\"end\", onEnd);\n\t\tsocket.on(\"error\", onError);\n\t\tresetT7();\n\n\t\tawait new Promise<void>((resolve) => {\n\t\t\tsocket.once(\"close\", () => resolve());\n\t\t});\n\n\t\treturn this.socket === socket && this.state === HsmsState.Selected;\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.shouldStop = true;\n\t\t// Close client connection first\n\t\tif (this.socket) {\n\t\t\tthis.socket.end();\n\t\t\tthis.socket.destroy();\n\t\t\tthis.socket = null;\n\t\t}\n\n\t\t// Stop listening\n\t\tconst server = this.server;\n\t\tif (server) {\n\t\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\t\tserver.close((err) => {\n\t\t\t\t\tthis.server = null;\n\t\t\t\t\tif (err) reject(err);\n\t\t\t\t\telse resolve();\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\n\t\tif (this.serverLoopPromise) {\n\t\t\tconst loop = this.serverLoopPromise;\n\t\t\tthis.serverLoopPromise = null;\n\t\t\tawait loop;\n\t\t}\n\t}\n}\n"],"mappings":";;;;;;;;;;;AAkBA,IAAa,0BAAb,cAA6C,iBAAiB;CAC7D,AAAQ,SAAwB;CAChC,AAAQ,aAAa;CACrB,AAAQ,oBAA0C;CAClD,AAAQ,gBAAgB;CAExB,YAAY,QAAuC;AAClD,QAAM,OAAO;AACb,MAAI,OAAO,kBAAkB,OAC5B,MAAK,gBAAgB,OAAO;;;;;CAO9B,MAAM,OAAsB;AAC3B,MAAI,KAAK,kBACR;AAGD,OAAK,aAAa;EAElB,IAAIA,qBAA0C;EAC9C,MAAM,cAAc,IAAI,SAAe,YAAY;AAClD,wBAAqB;IACpB;AAEF,OAAK,oBAAoB,KAAK,oBAAoB;AACjD,yBAAsB;AACtB,wBAAqB;IACpB,CAAC,OAAO,QAAiB;AAC1B,QAAK,KAAK,SAAS,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC,CAAC;IACtE;AAEF,QAAM;;;;;;;CAQP,MAAc,cAAc,kBAA6C;EACxE,IAAI,QAAQ;AACZ,SAAO,CAAC,KAAK,YAAY;AACxB,OAAI;AACH,UAAM,KAAK,WAAW,QAAQ,mBAAmB,KAAK;YAC9C,KAAK;AACb,QAAI,CAAC,KAAK,WACT,MAAK,KACJ,SACA,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC,CACnD;AAEF,QAAI,CAAC,KAAK,WACT,OAAM,IAAI,SAAS,YAClB,WAAW,SAAS,KAAK,gBAAgB,IAAK,CAC9C;;AAGH,WAAQ;AACR,OAAI,KAAK,WAAY;;;;;;;;CASvB,MAAc,WAAW,aAAiD;AACzE,SAAO,IAAI,SAAS,SAAS,WAAW;GACvC,MAAM,SAAS,cAAc,WAAW;AACvC,IAAK,KAAK,qBAAqB,OAAO;KACrC;AACF,QAAK,SAAS;GAEd,IAAI,eAAe;GACnB,IAAI,UAAU;GAEd,MAAM,gBAAgB;AACrB,WAAO,eAAe,SAAS,cAAc;AAC7C,WAAO,eAAe,SAAS,cAAc;AAC7C,SAAK,eAAe,aAAa,YAAY;AAC7C,SAAK,eAAe,gBAAgB,eAAe;;GAGpD,MAAM,UAAU,QAAgB;AAC/B,QAAI,QAAS;AACb,cAAU;AACV,QAAI,KAAK,WAAW,OACnB,MAAK,SAAS;AAEf,aAAS;AACT,QAAI,IAAK,QAAO,IAAI;QACf,UAAS;;GAGf,MAAM,oBAAoB;AACzB,QAAI,QAAS;AACb,QAAI,CAAC,OAAO,WAAW;AACtB,aAAQ;AACR;;AAED,WAAO,OAAO,QAAQ;AACrB,SAAI,IAAK,QAAO,IAAI;SACf,SAAQ;MACZ;;GAGH,MAAM,iBAAiB,QAAe;AACrC,WAAO,IAAI;;GAGZ,MAAM,sBAAsB;AAC3B,YAAQ;;GAGT,MAAM,oBAAoB;AACzB,mBAAe;;GAGhB,MAAM,uBAAuB;AAC5B,QAAI,CAAC,aAAc;AACnB,iBAAa;;AAGd,UAAO,GAAG,SAAS,cAAc;AACjC,UAAO,GAAG,SAAS,cAAc;AACjC,QAAK,GAAG,aAAa,YAAY;AACjC,QAAK,GAAG,gBAAgB,eAAe;AAEvC,UAAO,OAAO,KAAK,MAAM,KAAK,UAAU;AACvC,mBAAe;KACd;IACD;;;;;;;CAQH,MAAc,qBAAqB,QAA+B;AACjE,SAAO,WAAW,KAAK;AAEvB,MAAI,CAAC,KAAK,UAAU,KAAK,OAAO,WAAW;AAE1C,OADiB,MAAM,KAAK,0BAA0B,OAAO,CAC/C;AACd;;AAGD,QAAM,KAAK,0BAA0B,OAAO;;;;;;;CAQ7C,MAAc,0BAA0B,QAAkC;EACzE,IAAI,SAAS,OAAO,MAAM,EAAE;EAC5B,IAAIC,UAAiC;EACrC,IAAIC,UAAiC;EAErC,MAAM,gBAAgB;AACrB,OAAI,SAAS;AACZ,iBAAa,QAAQ;AACrB,cAAU;;;EAIZ,MAAM,gBAAgB;AACrB,YAAS;AACT,OAAI,KAAK,aAAa,EAAG;AACzB,aAAU,iBAAiB;AAC1B,cAAU;AACV,QAAI,OAAO,SAAS,KAAK,CAAC,OAAO,WAAW;AAC3C,UAAK,KAAK,yBAAS,IAAI,MAAM,aAAa,CAAC;AAC3C,YAAO,SAAS;;MAEf,KAAK,YAAY,IAAK;;EAG1B,MAAM,gBAAgB;AACrB,OAAI,SAAS;AACZ,iBAAa,QAAQ;AACrB,cAAU;;;EAIZ,MAAM,gBAAgB;AACrB,YAAS;AACT,OAAI,KAAK,aAAa,EAAG;AACzB,aAAU,iBAAiB;AAC1B,cAAU;AACV,QAAI,CAAC,OAAO,UACX,QAAO,SAAS;MAEf,KAAK,YAAY,IAAK;;EAG1B,MAAM,mBAAmB,OAAO,QAA+B;AAC9D,SAAM,IAAI,SAAe,SAAS,WAAW;AAC5C,WAAO,MAAM,MAAM,QAAQ;AAC1B,SAAI,IAAK,QAAO,IAAI;SACf,UAAS;MACb;KACD;;EAGH,MAAM,gBAAgB;AACrB,YAAS;AACT,YAAS;;EAGV,MAAM,qBAAqB,cAA2B;AACrD,UAAO,eAAe,QAAQ,OAAO;AACrC,UAAO,eAAe,SAAS,QAAQ;AACvC,UAAO,eAAe,OAAO,MAAM;AACnC,UAAO,eAAe,SAAS,QAAQ;AACvC,YAAS;AACT,QAAK,mBAAmB,OAAO;AAC/B,QAAK,gBAAgB,UAAU;;EAGhC,MAAM,2BAA2B,OAAO,QAAqB;AAC5D,WAAQ,IAAI,OAAZ;IACC,KAAK,gBAAgB;AAEpB,WAAM,iBADM,YAAY,UAAU,KAAK,aAAa,YAAY,CACrC,UAAU,CAAC;AACtC;IAED,KAAK,gBAAgB;AAEpB,WAAM,iBADM,YAAY,YAAY,IAAI,CACb,UAAU,CAAC;AACtC;IAED,KAAK,gBAAgB;AACpB,YAAO,SAAS;AAChB;IAED,KAAK,gBAAgB;AACpB,SACC,KAAK,UACL,CAAC,KAAK,OAAO,aACb,KAAK,UAAU,UAAU,SAGzB,OAAM,iBADM,YAAY,UAAU,KAAK,aAAa,YAAY,CACrC,UAAU,CAAC;SAEtC,mBAAkB,IAAI;AAEvB;IAED,KAAK,gBAAgB;IACrB,KAAK,gBAAgB;AAKpB,WAAM,iBAJM,YAAY,UACvB,KACA,aAAa,mBACb,CAC0B,UAAU,CAAC;AACtC;IAED,KAAK,gBAAgB,UACpB;IAED,SAAS;KACR,MAAM,SACL,IAAI,UAAU,IACX,aAAa,kBACb,aAAa;AAEjB,WAAM,iBADM,YAAY,UAAU,KAAK,OAAO,CACnB,UAAU,CAAC;AACtC;;;;EAKH,IAAI,aAAa;EACjB,MAAM,kBAAkB,YAAY;AACnC,OAAI,WAAY;AAChB,gBAAa;AACb,OAAI;AACH,WAAO,MAAM;AACZ,SAAI,OAAO,SAAS,EAAG;KACvB,MAAM,SAAS,OAAO,aAAa,EAAE;AACrC,SAAI,SAAS,IAAI;AAChB,WAAK,KAAK,yBAAS,IAAI,MAAM,4BAA4B,CAAC;AAC1D,eAAS,OAAO,MAAM,EAAE;AACxB,aAAO,SAAS;AAChB;;AAED,SAAI,OAAO,SAAS,IAAI,OAAQ;KAEhC,MAAM,YAAY,OAAO,SAAS,GAAG,IAAI,OAAO;AAChD,cAAS,OAAO,SAAS,IAAI,OAAO;AACpC,SAAI,OAAO,WAAW,EAAG,UAAS;KAElC,IAAIC;AACJ,SAAI;AACH,YAAM,YAAY,WAAW,UAAU;cAC/B,KAAK;AACb,WAAK,KACJ,SACA,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC,CACnD;AACD,aAAO,SAAS;AAChB;;AAGD,cAAS;AACT,WAAM,yBAAyB,IAAI;AAEnC,SAAI,KAAK,WAAW,UAAU,KAAK,UAAU,UAAU,SACtD;;YAGM,KAAK;AACb,SAAK,KAAK,SAAS,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC,CAAC;AACvE,WAAO,SAAS;aACP;AACT,iBAAa;;;EAIf,MAAM,UAAU,SAAiB;AAChC,YAAS,OAAO,OAAO,CAAC,QAAQ,KAAK,CAAC;AACtC,YAAS;AACT,GAAK,iBAAiB;;EAGvB,MAAM,gBAAgB;AACrB,YAAS;;EAGV,MAAM,cAAc;AACnB,OAAI,CAAC,OAAO,UACX,QAAO,SAAS;;EAIlB,MAAM,WAAW,QAAe;AAC/B,QAAK,KAAK,SAAS,IAAI;;AAGxB,SAAO,GAAG,QAAQ,OAAO;AACzB,SAAO,GAAG,SAAS,QAAQ;AAC3B,SAAO,GAAG,OAAO,MAAM;AACvB,SAAO,GAAG,SAAS,QAAQ;AAC3B,WAAS;AAET,QAAM,IAAI,SAAe,YAAY;AACpC,UAAO,KAAK,eAAe,SAAS,CAAC;IACpC;AAEF,SAAO,KAAK,WAAW,UAAU,KAAK,UAAU,UAAU;;CAG3D,MAAM,QAAuB;AAC5B,OAAK,aAAa;AAElB,MAAI,KAAK,QAAQ;AAChB,QAAK,OAAO,KAAK;AACjB,QAAK,OAAO,SAAS;AACrB,QAAK,SAAS;;EAIf,MAAM,SAAS,KAAK;AACpB,MAAI,OACH,OAAM,IAAI,SAAe,SAAS,WAAW;AAC5C,UAAO,OAAO,QAAQ;AACrB,SAAK,SAAS;AACd,QAAI,IAAK,QAAO,IAAI;QACf,UAAS;KACb;IACD;AAGH,MAAI,KAAK,mBAAmB;GAC3B,MAAM,OAAO,KAAK;AAClB,QAAK,oBAAoB;AACzB,SAAM"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HsmsControlType.js","names":[],"sources":["../../../src/hsms/enums/HsmsControlType.ts"],"sourcesContent":["export enum HsmsControlType {\
|
|
1
|
+
{"version":3,"file":"HsmsControlType.js","names":[],"sources":["../../../src/hsms/enums/HsmsControlType.ts"],"sourcesContent":["export enum HsmsControlType {\n Data = 0,\n SelectReq = 1,\n SelectRsp = 2,\n DeselectReq = 3,\n DeselectRsp = 4,\n LinkTestReq = 5,\n LinkTestRsp = 6,\n RejectReq = 7,\n SeparateReq = 9,\n}\n"],"mappings":";AAAA,IAAY,8DAAL;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RejectReason.js","names":[],"sources":["../../../src/hsms/enums/RejectReason.ts"],"sourcesContent":["export enum RejectReason {\
|
|
1
|
+
{"version":3,"file":"RejectReason.js","names":[],"sources":["../../../src/hsms/enums/RejectReason.ts"],"sourcesContent":["export enum RejectReason {\n NotSupportTypeS = 1,\n NotSupportTypeP = 2,\n TransactionNotOpen = 3,\n NotSelected = 4,\n Unknown = 0xff,\n}\n"],"mappings":";AAAA,IAAY,wDAAL;AACL;AACA;AACA;AACA;AACA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectStatus.js","names":[],"sources":["../../../src/hsms/enums/SelectStatus.ts"],"sourcesContent":["export enum SelectStatus {\
|
|
1
|
+
{"version":3,"file":"SelectStatus.js","names":[],"sources":["../../../src/hsms/enums/SelectStatus.ts"],"sourcesContent":["export enum SelectStatus {\n Success = 0,\n Actived = 1,\n NotReady = 2,\n AlreadyUsed = 3,\n Unknown = 0xff,\n}\n"],"mappings":";AAAA,IAAY,wDAAL;AACL;AACA;AACA;AACA;AACA"}
|
package/lib/index.d.ts
CHANGED
|
@@ -26,4 +26,5 @@ import { Secs1Communicator, Secs1CommunicatorConfig } from "./secs1/Secs1Communi
|
|
|
26
26
|
import { Secs1OnTcpIpActiveCommunicator, Secs1OnTcpIpActiveCommunicatorConfig } from "./secs1/Secs1OnTcpIpActiveCommunicator.js";
|
|
27
27
|
import { Secs1OnTcpIpPassiveCommunicator, Secs1OnTcpIpPassiveCommunicatorConfig } from "./secs1/Secs1OnTcpIpPassiveCommunicator.js";
|
|
28
28
|
import { Secs1SerialCommunicator, Secs1SerialCommunicatorConfig } from "./secs1/Secs1SerialCommunicator.js";
|
|
29
|
-
|
|
29
|
+
import { SmlParser } from "./sml/SmlParser.js";
|
|
30
|
+
export { A, AbstractSecs2Item, AbstractSecsCommunicator, B, BOOLEAN, Clock, ClockType, CommAck, F4, F8, Gem, HsmsActiveCommunicator, HsmsCommunicator, HsmsCommunicatorConfig, HsmsCommunicatorEvents, HsmsControlType, HsmsMessage, HsmsPassiveCommunicator, HsmsPassiveCommunicatorConfig, HsmsState, I1, I2, I4, I8, L, OflAck, OnlAck, RejectReason, Secs1Communicator, Secs1CommunicatorConfig, Secs1Message, Secs1MessageBlock, Secs1OnTcpIpActiveCommunicator, Secs1OnTcpIpActiveCommunicatorConfig, Secs1OnTcpIpPassiveCommunicator, Secs1OnTcpIpPassiveCommunicatorConfig, Secs1SerialCommunicator, Secs1SerialCommunicatorConfig, Secs2ItemAscii, Secs2ItemBinary, Secs2ItemBoolean, Secs2ItemFactory, Secs2ItemList, Secs2ItemNumeric, Secs2ItemParser, SecsCommunicatorConfig, SecsCommunicatorEvents, SecsItemType, SecsLogDirection, SecsLogger, SecsLoggerConfig, SecsLoggerContext, SecsMessage, SelectStatus, SmlParser, TiAck, U1, U2, U4, U8 };
|
package/lib/index.js
CHANGED
|
@@ -26,5 +26,6 @@ import { Secs1OnTcpIpPassiveCommunicator } from "./secs1/Secs1OnTcpIpPassiveComm
|
|
|
26
26
|
import { Secs1SerialCommunicator } from "./secs1/Secs1SerialCommunicator.js";
|
|
27
27
|
import { Clock, ClockType } from "./gem/Clock.js";
|
|
28
28
|
import { CommAck, Gem, OflAck, OnlAck, TiAck } from "./gem/Gem.js";
|
|
29
|
+
import { SmlParser } from "./sml/SmlParser.js";
|
|
29
30
|
|
|
30
|
-
export { A, AbstractSecs2Item, AbstractSecsCommunicator, B, BOOLEAN, Clock, ClockType, CommAck, F4, F8, Gem, HsmsActiveCommunicator, HsmsCommunicator, HsmsControlType, HsmsMessage, HsmsPassiveCommunicator, HsmsState, I1, I2, I4, I8, L, OflAck, OnlAck, RejectReason, Secs1Communicator, Secs1Message, Secs1MessageBlock, Secs1OnTcpIpActiveCommunicator, Secs1OnTcpIpPassiveCommunicator, Secs1SerialCommunicator, Secs2ItemAscii, Secs2ItemBinary, Secs2ItemBoolean, Secs2ItemFactory, Secs2ItemList, Secs2ItemNumeric, Secs2ItemParser, SecsItemType, SecsLogger, SecsMessage, SelectStatus, TiAck, U1, U2, U4, U8 };
|
|
31
|
+
export { A, AbstractSecs2Item, AbstractSecsCommunicator, B, BOOLEAN, Clock, ClockType, CommAck, F4, F8, Gem, HsmsActiveCommunicator, HsmsCommunicator, HsmsControlType, HsmsMessage, HsmsPassiveCommunicator, HsmsState, I1, I2, I4, I8, L, OflAck, OnlAck, RejectReason, Secs1Communicator, Secs1Message, Secs1MessageBlock, Secs1OnTcpIpActiveCommunicator, Secs1OnTcpIpPassiveCommunicator, Secs1SerialCommunicator, Secs2ItemAscii, Secs2ItemBinary, Secs2ItemBoolean, Secs2ItemFactory, Secs2ItemList, Secs2ItemNumeric, Secs2ItemParser, SecsItemType, SecsLogger, SecsMessage, SelectStatus, SmlParser, TiAck, U1, U2, U4, U8 };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Secs1Message.js","names":["blocks: Secs1MessageBlock[]","body: AbstractSecs2Item | null"],"sources":["../../src/secs1/Secs1Message.ts"],"sourcesContent":["import { SecsMessage } from \"../core/AbstractSecsMessage.js\";\
|
|
1
|
+
{"version":3,"file":"Secs1Message.js","names":["blocks: Secs1MessageBlock[]","body: AbstractSecs2Item | null"],"sources":["../../src/secs1/Secs1Message.ts"],"sourcesContent":["import { SecsMessage } from \"../core/AbstractSecsMessage.js\";\nimport { AbstractSecs2Item } from \"../core/secs2item/AbstractSecs2Item.js\";\nimport { Secs2ItemParser } from \"../core/secs2item/Secs2ItemParser.js\";\nimport { Secs1MessageBlock } from \"./Secs1MessageBlock.js\";\n\nexport class Secs1Message extends SecsMessage {\n\tconstructor(\n\t\tstream: number,\n\t\tfunc: number,\n\t\twBit: boolean,\n\t\tbody: AbstractSecs2Item | null,\n\t\tsystemBytes: number,\n\t\tdeviceId: number,\n\t\tpublic readonly rBit = false,\n\t) {\n\t\tsuper(stream, func, wBit, body, systemBytes, deviceId);\n\t}\n\n\t/**\n\t * @description Splits the message into SECS-I blocks.\n\t */\n\ttoBlocks(): Secs1MessageBlock[] {\n\t\tconst bodyBuffer = this.body ? this.body.toBuffer() : Buffer.alloc(0);\n\t\tconst blocks: Secs1MessageBlock[] = [];\n\n\t\tlet pos = 0;\n\t\tlet blockNum = 1;\n\n\t\tif (bodyBuffer.length === 0) {\n\t\t\t// Header only block? Or empty body block?\n\t\t\t// SECS-I allows empty body.\n\t\t\tblocks.push(\n\t\t\t\tSecs1MessageBlock.fromParts(\n\t\t\t\t\tthis.deviceId,\n\t\t\t\t\tthis.stream,\n\t\t\t\t\tthis.func,\n\t\t\t\t\tthis.wBit,\n\t\t\t\t\ttrue, // E-Bit\n\t\t\t\t\tblockNum,\n\t\t\t\t\tthis.systemBytes,\n\t\t\t\t\tBuffer.alloc(0),\n\t\t\t\t\tthis.rBit,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn blocks;\n\t\t}\n\n\t\twhile (pos < bodyBuffer.length) {\n\t\t\tconst remaining = bodyBuffer.length - pos;\n\t\t\tconst chunkSize = remaining > 244 ? 244 : remaining;\n\t\t\tconst chunk = bodyBuffer.subarray(pos, pos + chunkSize);\n\t\t\tconst isLast = pos + chunkSize >= bodyBuffer.length;\n\n\t\t\tblocks.push(\n\t\t\t\tSecs1MessageBlock.fromParts(\n\t\t\t\t\tthis.deviceId,\n\t\t\t\t\tthis.stream,\n\t\t\t\t\tthis.func,\n\t\t\t\t\tthis.wBit,\n\t\t\t\t\tisLast, // E-Bit\n\t\t\t\t\tblockNum,\n\t\t\t\t\tthis.systemBytes,\n\t\t\t\t\tchunk,\n\t\t\t\t\tthis.rBit,\n\t\t\t\t),\n\t\t\t);\n\n\t\t\tpos += chunkSize;\n\t\t\tblockNum++;\n\t\t\tif (blockNum > 0x7fff) {\n\t\t\t\tthrow new Error(\"Block number overflow\");\n\t\t\t}\n\t\t}\n\n\t\treturn blocks;\n\t}\n\n\t/**\n\t * Reassembles a SECS-I message from blocks.\n\t */\n\tstatic fromBlocks(blocks: Secs1MessageBlock[]): Secs1Message {\n\t\tif (blocks.length === 0) {\n\t\t\tthrow new Error(\"No blocks to reassemble\");\n\t\t}\n\n\t\t// Sort by block number just in case (though usually they come in order)\n\t\tblocks.sort((a, b) => a.blockNumber - b.blockNumber);\n\n\t\t// Validate sequence\n\t\tfor (let i = 0; i < blocks.length; i++) {\n\t\t\tif (blocks[i].blockNumber !== i + 1) {\n\t\t\t\tthrow new Error(`Missing block ${i + 1}`);\n\t\t\t}\n\t\t\t// Check if all blocks belong to the same message (SystemBytes, Stream, Func, DeviceID)\n\t\t\tif (i > 0) {\n\t\t\t\tconst prev = blocks[i - 1];\n\t\t\t\tconst curr = blocks[i];\n\t\t\t\tif (\n\t\t\t\t\tprev.systemBytes !== curr.systemBytes ||\n\t\t\t\t\tprev.stream !== curr.stream ||\n\t\t\t\t\tprev.func !== curr.func ||\n\t\t\t\t\tprev.deviceId !== curr.deviceId\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(\"Blocks do not belong to the same message\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!blocks[blocks.length - 1].eBit) {\n\t\t\tthrow new Error(\"Last block missing E-Bit\");\n\t\t}\n\n\t\tconst first = blocks[0];\n\t\tconst bodyBuffers = blocks.map((b) => b.body);\n\t\tconst fullBodyBuffer = Buffer.concat(bodyBuffers);\n\n\t\tlet body: AbstractSecs2Item | null = null;\n\t\tif (fullBodyBuffer.length > 0) {\n\t\t\tconst result = Secs2ItemParser.fromBuffer(fullBodyBuffer);\n\t\t\tbody = result.item;\n\t\t}\n\n\t\treturn new Secs1Message(\n\t\t\tfirst.stream,\n\t\t\tfirst.func,\n\t\t\tfirst.wBit,\n\t\t\tbody,\n\t\t\tfirst.systemBytes,\n\t\t\tfirst.deviceId,\n\t\t\tfirst.rBit,\n\t\t);\n\t}\n\n\t// Override toBuffer to return logical buffer (10-byte header + body)\n\ttoBuffer(): Buffer {\n\t\tconst bodyBuffer = this.body ? this.body.toBuffer() : Buffer.alloc(0);\n\t\tconst header = Buffer.alloc(10);\n\n\t\t// Byte 0: R-Bit + DeviceID MSB\n\t\tlet b0 = (this.deviceId >> 8) & 0x7f;\n\t\tif (this.rBit) b0 |= 0x80;\n\t\theader[0] = b0;\n\n\t\t// Byte 1: DeviceID LSB\n\t\theader[1] = this.deviceId & 0xff;\n\n\t\t// Byte 2: W-Bit + Stream\n\t\tlet b2 = this.stream & 0x7f;\n\t\tif (this.wBit) b2 |= 0x80;\n\t\theader[2] = b2;\n\n\t\t// Byte 3: Function\n\t\theader[3] = this.func & 0xff;\n\n\t\t// Byte 4: E-Bit + BlockNum (Logical 0 or 1? For logical message, maybe 0)\n\t\t// Usually block number is per block. For a \"Message Buffer\", we don't have block number.\n\t\t// We'll leave it 0 or standard.\n\t\theader[4] = 0;\n\t\theader[5] = 0;\n\n\t\t// Byte 6-9: System Bytes\n\t\theader.writeUInt32BE(this.systemBytes, 6);\n\n\t\treturn Buffer.concat([header, bodyBuffer]);\n\t}\n}\n"],"mappings":";;;;;AAKA,IAAa,eAAb,MAAa,qBAAqB,YAAY;CAC7C,YACC,QACA,MACA,MACA,MACA,aACA,UACA,AAAgB,OAAO,OACtB;AACD,QAAM,QAAQ,MAAM,MAAM,MAAM,aAAa,SAAS;EAFtC;;;;;CAQjB,WAAgC;EAC/B,MAAM,aAAa,KAAK,OAAO,KAAK,KAAK,UAAU,GAAG,OAAO,MAAM,EAAE;EACrE,MAAMA,SAA8B,EAAE;EAEtC,IAAI,MAAM;EACV,IAAI,WAAW;AAEf,MAAI,WAAW,WAAW,GAAG;AAG5B,UAAO,KACN,kBAAkB,UACjB,KAAK,UACL,KAAK,QACL,KAAK,MACL,KAAK,MACL,MACA,UACA,KAAK,aACL,OAAO,MAAM,EAAE,EACf,KAAK,KACL,CACD;AACD,UAAO;;AAGR,SAAO,MAAM,WAAW,QAAQ;GAC/B,MAAM,YAAY,WAAW,SAAS;GACtC,MAAM,YAAY,YAAY,MAAM,MAAM;GAC1C,MAAM,QAAQ,WAAW,SAAS,KAAK,MAAM,UAAU;GACvD,MAAM,SAAS,MAAM,aAAa,WAAW;AAE7C,UAAO,KACN,kBAAkB,UACjB,KAAK,UACL,KAAK,QACL,KAAK,MACL,KAAK,MACL,QACA,UACA,KAAK,aACL,OACA,KAAK,KACL,CACD;AAED,UAAO;AACP;AACA,OAAI,WAAW,MACd,OAAM,IAAI,MAAM,wBAAwB;;AAI1C,SAAO;;;;;CAMR,OAAO,WAAW,QAA2C;AAC5D,MAAI,OAAO,WAAW,EACrB,OAAM,IAAI,MAAM,0BAA0B;AAI3C,SAAO,MAAM,GAAG,MAAM,EAAE,cAAc,EAAE,YAAY;AAGpD,OAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACvC,OAAI,OAAO,GAAG,gBAAgB,IAAI,EACjC,OAAM,IAAI,MAAM,iBAAiB,IAAI,IAAI;AAG1C,OAAI,IAAI,GAAG;IACV,MAAM,OAAO,OAAO,IAAI;IACxB,MAAM,OAAO,OAAO;AACpB,QACC,KAAK,gBAAgB,KAAK,eAC1B,KAAK,WAAW,KAAK,UACrB,KAAK,SAAS,KAAK,QACnB,KAAK,aAAa,KAAK,SAEvB,OAAM,IAAI,MAAM,2CAA2C;;;AAK9D,MAAI,CAAC,OAAO,OAAO,SAAS,GAAG,KAC9B,OAAM,IAAI,MAAM,2BAA2B;EAG5C,MAAM,QAAQ,OAAO;EACrB,MAAM,cAAc,OAAO,KAAK,MAAM,EAAE,KAAK;EAC7C,MAAM,iBAAiB,OAAO,OAAO,YAAY;EAEjD,IAAIC,OAAiC;AACrC,MAAI,eAAe,SAAS,EAE3B,QADe,gBAAgB,WAAW,eAAe,CAC3C;AAGf,SAAO,IAAI,aACV,MAAM,QACN,MAAM,MACN,MAAM,MACN,MACA,MAAM,aACN,MAAM,UACN,MAAM,KACN;;CAIF,WAAmB;EAClB,MAAM,aAAa,KAAK,OAAO,KAAK,KAAK,UAAU,GAAG,OAAO,MAAM,EAAE;EACrE,MAAM,SAAS,OAAO,MAAM,GAAG;EAG/B,IAAI,KAAM,KAAK,YAAY,IAAK;AAChC,MAAI,KAAK,KAAM,OAAM;AACrB,SAAO,KAAK;AAGZ,SAAO,KAAK,KAAK,WAAW;EAG5B,IAAI,KAAK,KAAK,SAAS;AACvB,MAAI,KAAK,KAAM,OAAM;AACrB,SAAO,KAAK;AAGZ,SAAO,KAAK,KAAK,OAAO;AAKxB,SAAO,KAAK;AACZ,SAAO,KAAK;AAGZ,SAAO,cAAc,KAAK,aAAa,EAAE;AAEzC,SAAO,OAAO,OAAO,CAAC,QAAQ,WAAW,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Secs1MessageBlock.js","names":["buffer: Buffer"],"sources":["../../src/secs1/Secs1MessageBlock.ts"],"sourcesContent":["export class Secs1MessageBlock {\
|
|
1
|
+
{"version":3,"file":"Secs1MessageBlock.js","names":["buffer: Buffer"],"sources":["../../src/secs1/Secs1MessageBlock.ts"],"sourcesContent":["export class Secs1MessageBlock {\n\t// The full block bytes: [Length(1)] + [Header(10)] + [Body(0-244)] + [Checksum(2)]\n\tconstructor(public readonly buffer: Buffer) {}\n\n\tget length(): number {\n\t\treturn this.buffer[0];\n\t}\n\n\tget header(): Buffer {\n\t\treturn this.buffer.subarray(1, 11);\n\t}\n\n\tget body(): Buffer {\n\t\treturn this.buffer.subarray(11, this.buffer.length - 2);\n\t}\n\n\tget checksum(): number {\n\t\treturn this.buffer.readUInt16BE(this.buffer.length - 2);\n\t}\n\n\t// Parsed fields\n\tget deviceId(): number {\n\t\tconst bs = this.buffer.subarray(1, 3);\n\t\treturn ((bs[0] << 8) & 0x7f00) | bs[1];\n\t}\n\n\tget rBit(): boolean {\n\t\treturn (this.buffer[1] & 0x80) === 0x80;\n\t}\n\n\tget stream(): number {\n\t\treturn this.buffer[3] & 0x7f;\n\t}\n\n\tget wBit(): boolean {\n\t\treturn (this.buffer[3] & 0x80) === 0x80;\n\t}\n\n\tget func(): number {\n\t\treturn this.buffer[4];\n\t}\n\n\tget blockNumber(): number {\n\t\tconst bs = this.buffer.subarray(5, 7);\n\t\treturn ((bs[0] << 8) & 0x7f00) | bs[1];\n\t}\n\n\tget eBit(): boolean {\n\t\treturn (this.buffer[5] & 0x80) === 0x80;\n\t}\n\n\tget systemBytes(): number {\n\t\treturn this.buffer.readUInt32BE(7);\n\t}\n\n\tisValid(): boolean {\n\t\tif (this.buffer.length < 13) return false; // Len(1) + Head(10) + Sum(2)\n\t\tif (this.buffer[0] !== this.buffer.length - 3) return false; // Length byte excludes itself and checksum?\n\t\t// Wait, SECS-I Length Byte is the number of bytes in the block EXCLUSIVE of the length byte itself and the checksum?\n\t\t// No, standard says: \"Length byte is the number of bytes in the block header plus the text.\" (Header + Body).\n\t\t// So Length = 10 + BodyLength.\n\t\t// Total buffer size = 1 (LenByte) + Length + 2 (Checksum).\n\t\t// So Buffer Length = 1 + Length + 2 = Length + 3.\n\t\t// So Length Byte value should be BufferLength - 3.\n\n\t\tconst calculatedSum = this.calculateChecksum();\n\t\treturn calculatedSum === this.checksum;\n\t}\n\n\tprivate calculateChecksum(): number {\n\t\t// Sum of bytes from Header to end of Body (excluding Length byte and Checksum bytes)\n\t\t// i.e., indices 1 to length-3\n\t\tlet sum = 0;\n\t\tfor (let i = 1; i < this.buffer.length - 2; i++) {\n\t\t\tsum += this.buffer[i];\n\t\t}\n\t\treturn sum & 0xffff;\n\t}\n\n\tstatic fromParts(\n\t\tdeviceId: number,\n\t\tstream: number,\n\t\tfunc: number,\n\t\twBit: boolean,\n\t\teBit: boolean,\n\t\tblockNum: number,\n\t\tsystemBytes: number,\n\t\tbody: Buffer,\n\t\trBit = false,\n\t): Secs1MessageBlock {\n\t\tconst header = Buffer.alloc(10);\n\t\t// Byte 0: R-Bit + DeviceID MSB\n\t\tlet b0 = (deviceId >> 8) & 0x7f;\n\t\tif (rBit) b0 |= 0x80;\n\t\theader[0] = b0;\n\t\t// Byte 1: DeviceID LSB\n\t\theader[1] = deviceId & 0xff;\n\n\t\t// Byte 2: W-Bit + Stream\n\t\tlet b2 = stream & 0x7f;\n\t\tif (wBit) b2 |= 0x80;\n\t\theader[2] = b2;\n\n\t\t// Byte 3: Function\n\t\theader[3] = func & 0xff;\n\n\t\t// Byte 4: E-Bit + BlockNum MSB\n\t\tlet b4 = (blockNum >> 8) & 0x7f;\n\t\tif (eBit) b4 |= 0x80;\n\t\theader[4] = b4;\n\n\t\t// Byte 5: BlockNum LSB\n\t\theader[5] = blockNum & 0xff;\n\n\t\t// Byte 6-9: System Bytes\n\t\theader.writeUInt32BE(systemBytes, 6);\n\n\t\t// Calculate Length\n\t\tconst length = 10 + body.length;\n\t\tif (length > 254) throw new Error(\"Block too large\");\n\n\t\t// Calculate Checksum\n\t\tlet sum = 0;\n\t\tfor (const b of header) sum += b;\n\t\tfor (const b of body) sum += b;\n\t\tconst checksum = sum & 0xffff;\n\n\t\tconst block = Buffer.alloc(1 + 10 + body.length + 2);\n\t\tblock[0] = length;\n\t\theader.copy(block, 1);\n\t\tbody.copy(block, 11);\n\t\tblock.writeUInt16BE(checksum, block.length - 2);\n\n\t\treturn new Secs1MessageBlock(block);\n\t}\n}\n"],"mappings":";AAAA,IAAa,oBAAb,MAAa,kBAAkB;CAE9B,YAAY,AAAgBA,QAAgB;EAAhB;;CAE5B,IAAI,SAAiB;AACpB,SAAO,KAAK,OAAO;;CAGpB,IAAI,SAAiB;AACpB,SAAO,KAAK,OAAO,SAAS,GAAG,GAAG;;CAGnC,IAAI,OAAe;AAClB,SAAO,KAAK,OAAO,SAAS,IAAI,KAAK,OAAO,SAAS,EAAE;;CAGxD,IAAI,WAAmB;AACtB,SAAO,KAAK,OAAO,aAAa,KAAK,OAAO,SAAS,EAAE;;CAIxD,IAAI,WAAmB;EACtB,MAAM,KAAK,KAAK,OAAO,SAAS,GAAG,EAAE;AACrC,SAAS,GAAG,MAAM,IAAK,QAAU,GAAG;;CAGrC,IAAI,OAAgB;AACnB,UAAQ,KAAK,OAAO,KAAK,SAAU;;CAGpC,IAAI,SAAiB;AACpB,SAAO,KAAK,OAAO,KAAK;;CAGzB,IAAI,OAAgB;AACnB,UAAQ,KAAK,OAAO,KAAK,SAAU;;CAGpC,IAAI,OAAe;AAClB,SAAO,KAAK,OAAO;;CAGpB,IAAI,cAAsB;EACzB,MAAM,KAAK,KAAK,OAAO,SAAS,GAAG,EAAE;AACrC,SAAS,GAAG,MAAM,IAAK,QAAU,GAAG;;CAGrC,IAAI,OAAgB;AACnB,UAAQ,KAAK,OAAO,KAAK,SAAU;;CAGpC,IAAI,cAAsB;AACzB,SAAO,KAAK,OAAO,aAAa,EAAE;;CAGnC,UAAmB;AAClB,MAAI,KAAK,OAAO,SAAS,GAAI,QAAO;AACpC,MAAI,KAAK,OAAO,OAAO,KAAK,OAAO,SAAS,EAAG,QAAO;AAStD,SADsB,KAAK,mBAAmB,KACrB,KAAK;;CAG/B,AAAQ,oBAA4B;EAGnC,IAAI,MAAM;AACV,OAAK,IAAI,IAAI,GAAG,IAAI,KAAK,OAAO,SAAS,GAAG,IAC3C,QAAO,KAAK,OAAO;AAEpB,SAAO,MAAM;;CAGd,OAAO,UACN,UACA,QACA,MACA,MACA,MACA,UACA,aACA,MACA,OAAO,OACa;EACpB,MAAM,SAAS,OAAO,MAAM,GAAG;EAE/B,IAAI,KAAM,YAAY,IAAK;AAC3B,MAAI,KAAM,OAAM;AAChB,SAAO,KAAK;AAEZ,SAAO,KAAK,WAAW;EAGvB,IAAI,KAAK,SAAS;AAClB,MAAI,KAAM,OAAM;AAChB,SAAO,KAAK;AAGZ,SAAO,KAAK,OAAO;EAGnB,IAAI,KAAM,YAAY,IAAK;AAC3B,MAAI,KAAM,OAAM;AAChB,SAAO,KAAK;AAGZ,SAAO,KAAK,WAAW;AAGvB,SAAO,cAAc,aAAa,EAAE;EAGpC,MAAM,SAAS,KAAK,KAAK;AACzB,MAAI,SAAS,IAAK,OAAM,IAAI,MAAM,kBAAkB;EAGpD,IAAI,MAAM;AACV,OAAK,MAAM,KAAK,OAAQ,QAAO;AAC/B,OAAK,MAAM,KAAK,KAAM,QAAO;EAC7B,MAAM,WAAW,MAAM;EAEvB,MAAM,QAAQ,OAAO,MAAM,KAAS,KAAK,SAAS,EAAE;AACpD,QAAM,KAAK;AACX,SAAO,KAAK,OAAO,EAAE;AACrB,OAAK,KAAK,OAAO,GAAG;AACpB,QAAM,cAAc,UAAU,MAAM,SAAS,EAAE;AAE/C,SAAO,IAAI,kBAAkB,MAAM"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Secs1SerialCommunicator.js","names":[],"sources":["../../src/secs1/Secs1SerialCommunicator.ts"],"sourcesContent":["import { SerialPort } from \"serialport\";\
|
|
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"}
|
package/lib/sml/SmlParser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SmlParser.js","names":["str: string","item: AbstractSecs2Item","items: AbstractSecs2Item[]","buffer: number[]","bools: boolean[]","nums: number[]"],"sources":["../../src/sml/SmlParser.ts"],"sourcesContent":["import { SecsMessage } from \"../core/AbstractSecsMessage.js\";\r\nimport { AbstractSecs2Item } from \"../core/secs2item/AbstractSecs2Item.js\";\r\nimport { SecsItemType } from \"../core/enums/SecsItemType.js\";\r\nimport { Secs2ItemAscii } from \"../core/secs2item/Secs2ItemAscii.js\";\r\nimport { Secs2ItemList } from \"../core/secs2item/Secs2ItemList.js\";\r\nimport { Secs2ItemBinary } from \"../core/secs2item/Secs2ItemBinary.js\";\r\nimport { Secs2ItemBoolean } from \"../core/secs2item/Secs2ItemBoolean.js\";\r\nimport { Secs2ItemNumeric } from \"../core/secs2item/Secs2ItemNumeric.js\";\r\n\r\n/**\r\n * @description A cursor for SML parsing.\r\n */\r\nclass SmlCursor {\r\n\tconstructor(\r\n\t\tpublic str: string,\r\n\t\tpublic pos = 0,\r\n\t) {}\r\n\r\n\t/**\r\n\t * @description Returns the next character in the string without consuming it.\r\n\t * @returns The next character in the string.\r\n\t */\r\n\tpeek(): string {\r\n\t\treturn this.str[this.pos];\r\n\t}\r\n\r\n\t/**\r\n\t * @description Consumes the next character in the string and returns it.\r\n\t * @returns The consumed character.\r\n\t */\r\n\tconsume(): string {\r\n\t\treturn this.str[this.pos++];\r\n\t}\r\n\r\n\t/**\r\n\t * @description Returns true if the cursor is at the end of the string.\r\n\t * @returns True if the cursor is at the end of the string.\r\n\t */\r\n\teof(): boolean {\r\n\t\treturn this.pos >= this.str.length;\r\n\t}\r\n\r\n\t/**\r\n\t * @description Skips whitespace characters in the string.\r\n\t */\r\n\tskipWs() {\r\n\t\twhile (!this.eof() && /\\s/.test(this.peek())) this.pos++;\r\n\t}\r\n\r\n\t/**\r\n\t * @description Matches the next character in the string with the given character.\r\n\t * @param char The character to match.\r\n\t * @returns True if the next character in the string is the given character.\r\n\t */\r\n\tmatch(char: string): boolean {\r\n\t\tif (this.peek() === char) {\r\n\t\t\tthis.consume();\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\n/**\r\n * @description A parser for SECS-II SML strings.\r\n */\r\nexport class SmlParser {\r\n\tprivate static readonly SML_REGEX = /^[Ss](\\d+)[Ff](\\d+)\\s*(W?)\\s*(.*)\\.$/s;\r\n\r\n\t/**\r\n\t * @description Parses an SML string into a SecsMessage.\r\n\t * @param sml The SML string to parse.\r\n\t * @returns The parsed SecsMessage.\r\n\t */\r\n\tstatic parse(sml: string): SecsMessage {\r\n\t\tconst trimmed = sml.trim();\r\n\t\tconst match = this.SML_REGEX.exec(trimmed);\r\n\r\n\t\tif (!match) {\r\n\t\t\tthrow new Error(\"Invalid SML format. Must match 'SxFy [W] <Body>.'\");\r\n\t\t}\r\n\r\n\t\tconst stream = parseInt(match[1], 10);\r\n\t\tconst func = parseInt(match[2], 10);\r\n\t\tconst wBit = match[3].toUpperCase() === \"W\";\r\n\t\tconst bodyStr = match[4].trim();\r\n\r\n\t\tconst body = this.parseBody(bodyStr);\r\n\r\n\t\treturn new SecsMessage(stream, func, wBit, body);\r\n\t}\r\n\r\n\t/**\r\n\t * @description Parses an SML body string into a Secs2Item.\r\n\t * @param smlBody The SML body string to parse.\r\n\t * @returns The parsed Secs2Item.\r\n\t */\r\n\tstatic parseBody(smlBody: string): AbstractSecs2Item | null {\r\n\t\tconst trimmed = smlBody.trim();\r\n\t\tif (trimmed.length === 0) {\r\n\t\t\treturn null;\r\n\t\t}\r\n\t\tconst cursor = new SmlCursor(trimmed);\r\n\t\treturn this.parseItem(cursor);\r\n\t}\r\n\r\n\tprivate static parseItem(cursor: SmlCursor): AbstractSecs2Item {\r\n\t\tcursor.skipWs();\r\n\t\tif (cursor.consume() !== \"<\") {\r\n\t\t\tthrow new Error(`Expected '<' at pos ${(cursor.pos - 1).toString()}`);\r\n\t\t}\r\n\r\n\t\tcursor.skipWs();\r\n\t\tconst typeStart = cursor.pos;\r\n\t\twhile (!cursor.eof() && /[A-Z0-9]/.test(cursor.peek().toUpperCase())) {\r\n\t\t\tcursor.consume();\r\n\t\t}\r\n\t\tconst typeStr = cursor.str.substring(typeStart, cursor.pos).toUpperCase();\r\n\r\n\t\t// Skip length [size]\r\n\t\tcursor.skipWs();\r\n\t\tif (cursor.peek() === \"[\") {\r\n\t\t\twhile (!cursor.eof() && cursor.peek() !== \"]\") cursor.consume();\r\n\t\t\tif (cursor.peek() === \"]\") cursor.consume();\r\n\t\t}\r\n\r\n\t\tlet item: AbstractSecs2Item;\r\n\r\n\t\tif (typeStr === \"L\") {\r\n\t\t\tconst items: AbstractSecs2Item[] = [];\r\n\r\n\t\t\twhile (true) {\r\n\t\t\t\tcursor.skipWs();\r\n\t\t\t\tif (cursor.peek() === \">\") {\r\n\t\t\t\t\tcursor.consume();\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t} else if (cursor.peek() === \"<\") {\r\n\t\t\t\t\titems.push(this.parseItem(cursor));\r\n\t\t\t\t} else {\r\n\t\t\t\t\tthrow new Error(\r\n\t\t\t\t\t\t`Unexpected char in List: '${cursor.peek()}' at ${cursor.pos.toString()}`,\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\titem = new Secs2ItemList(items);\r\n\t\t} else if (typeStr === \"A\") {\r\n\t\t\tcursor.skipWs();\r\n\t\t\t// Expect quoted string\r\n\t\t\tif (cursor.peek() === '\"') {\r\n\t\t\t\tcursor.consume();\r\n\t\t\t\tconst start = cursor.pos;\r\n\t\t\t\twhile (!cursor.eof() && cursor.peek() !== '\"') cursor.consume(); // Handle escaping? SML usually simple.\r\n\t\t\t\tconst val = cursor.str.substring(start, cursor.pos);\r\n\t\t\t\tcursor.consume(); // quote\r\n\t\t\t\titem = new Secs2ItemAscii(val);\r\n\t\t\t} else {\r\n\t\t\t\t// Empty string or unquoted? Standard says quoted.\r\n\t\t\t\t// Assuming empty if > follows immediately\r\n\t\t\t\tif (cursor.peek() === \">\") {\r\n\t\t\t\t\titem = new Secs2ItemAscii(\"\");\r\n\t\t\t\t} else {\r\n\t\t\t\t\tthrow new Error(\r\n\t\t\t\t\t\t`Expected string value for type A at ${cursor.pos.toString()}`,\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tcursor.skipWs();\r\n\t\t\tif (cursor.consume() !== \">\") throw new Error(\"Expected '>' ending A\");\r\n\t\t} else if (typeStr === \"B\") {\r\n\t\t\t// Binary: 0xXX or XX\r\n\t\t\tconst buffer: number[] = [];\r\n\r\n\t\t\twhile (true) {\r\n\t\t\t\tcursor.skipWs();\r\n\t\t\t\tif (cursor.peek() === \">\") {\r\n\t\t\t\t\tcursor.consume();\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t// Read byte\r\n\t\t\t\t// Handle 0x prefix\r\n\t\t\t\tif (\r\n\t\t\t\t\tcursor.str.startsWith(\"0x\", cursor.pos) ||\r\n\t\t\t\t\tcursor.str.startsWith(\"0X\", cursor.pos)\r\n\t\t\t\t) {\r\n\t\t\t\t\tcursor.pos += 2;\r\n\t\t\t\t}\r\n\t\t\t\tconst byteStr = cursor.str.substring(cursor.pos, cursor.pos + 2);\r\n\t\t\t\tconst byteVal = parseInt(byteStr, 16);\r\n\t\t\t\tif (isNaN(byteVal))\r\n\t\t\t\t\tthrow new Error(`Invalid binary byte at ${cursor.pos.toString()}`);\r\n\t\t\t\tbuffer.push(byteVal);\r\n\t\t\t\tcursor.pos += 2;\r\n\t\t\t}\r\n\t\t\titem = new Secs2ItemBinary(Buffer.from(buffer));\r\n\t\t} else if (typeStr === \"BOOLEAN\") {\r\n\t\t\tconst bools: boolean[] = [];\r\n\r\n\t\t\twhile (true) {\r\n\t\t\t\tcursor.skipWs();\r\n\t\t\t\tif (cursor.peek() === \">\") {\r\n\t\t\t\t\tcursor.consume();\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t// Read T/True/F/False\r\n\t\t\t\tconst start = cursor.pos;\r\n\t\t\t\twhile (!cursor.eof() && /[A-Z]/.test(cursor.peek().toUpperCase()))\r\n\t\t\t\t\tcursor.consume();\r\n\t\t\t\tconst val = cursor.str.substring(start, cursor.pos).toUpperCase();\r\n\t\t\t\tif ([\"T\", \"TRUE\"].includes(val)) bools.push(true);\r\n\t\t\t\telse if ([\"F\", \"FALSE\"].includes(val)) bools.push(false);\r\n\t\t\t\telse throw new Error(`Invalid Boolean value ${val}`);\r\n\t\t\t}\r\n\t\t\titem = new Secs2ItemBoolean(bools.length === 1 ? bools[0] : bools);\r\n\t\t} else {\r\n\t\t\t// Numbers\r\n\t\t\tconst nums: number[] = []; // or bigint\r\n\t\t\t// Simplified number parsing\r\n\t\t\tconst isFloat = [\"F4\", \"F8\"].includes(typeStr);\r\n\r\n\t\t\twhile (true) {\r\n\t\t\t\tcursor.skipWs();\r\n\t\t\t\tif (cursor.peek() === \">\") {\r\n\t\t\t\t\tcursor.consume();\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tconst start = cursor.pos;\r\n\t\t\t\twhile (!cursor.eof() && /[0-9.\\-+]/.test(cursor.peek()))\r\n\t\t\t\t\tcursor.consume();\r\n\t\t\t\tconst valStr = cursor.str.substring(start, cursor.pos);\r\n\t\t\t\tconst val = isFloat ? parseFloat(valStr) : Number(valStr); // Use BigInt if needed for U8/I8\r\n\t\t\t\tif (isNaN(val))\r\n\t\t\t\t\tthrow new Error(`Invalid number ${valStr} at ${start.toString()}`);\r\n\t\t\t\tnums.push(val);\r\n\t\t\t}\r\n\r\n\t\t\t// Determine SecsItemType\r\n\t\t\tconst type = SecsItemType[typeStr as keyof typeof SecsItemType];\r\n\r\n\t\t\tif (type === undefined) throw new Error(`Unknown type ${typeStr}`);\r\n\r\n\t\t\titem = new Secs2ItemNumeric(type, nums.length === 1 ? nums[0] : nums);\r\n\t\t}\r\n\r\n\t\treturn item;\r\n\t}\r\n}\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SmlParser.js","names":["str: string","item: AbstractSecs2Item","items: AbstractSecs2Item[]","buffer: number[]","bools: boolean[]","nums: number[]"],"sources":["../../src/sml/SmlParser.ts"],"sourcesContent":["import { SecsMessage } from \"../core/AbstractSecsMessage.js\";\nimport { AbstractSecs2Item } from \"../core/secs2item/AbstractSecs2Item.js\";\nimport { SecsItemType } from \"../core/enums/SecsItemType.js\";\nimport { Secs2ItemAscii } from \"../core/secs2item/Secs2ItemAscii.js\";\nimport { Secs2ItemList } from \"../core/secs2item/Secs2ItemList.js\";\nimport { Secs2ItemBinary } from \"../core/secs2item/Secs2ItemBinary.js\";\nimport { Secs2ItemBoolean } from \"../core/secs2item/Secs2ItemBoolean.js\";\nimport { Secs2ItemNumeric } from \"../core/secs2item/Secs2ItemNumeric.js\";\n\n/**\n * @description A cursor for SML parsing.\n */\nclass SmlCursor {\n\tconstructor(\n\t\tpublic str: string,\n\t\tpublic pos = 0,\n\t) {}\n\n\t/**\n\t * @description Returns the next character in the string without consuming it.\n\t * @returns The next character in the string.\n\t */\n\tpeek(): string {\n\t\treturn this.str[this.pos];\n\t}\n\n\t/**\n\t * @description Consumes the next character in the string and returns it.\n\t * @returns The consumed character.\n\t */\n\tconsume(): string {\n\t\treturn this.str[this.pos++];\n\t}\n\n\t/**\n\t * @description Returns true if the cursor is at the end of the string.\n\t * @returns True if the cursor is at the end of the string.\n\t */\n\teof(): boolean {\n\t\treturn this.pos >= this.str.length;\n\t}\n\n\t/**\n\t * @description Skips whitespace characters in the string.\n\t */\n\tskipWs() {\n\t\twhile (!this.eof() && /\\s/.test(this.peek())) this.pos++;\n\t}\n\n\t/**\n\t * @description Matches the next character in the string with the given character.\n\t * @param char The character to match.\n\t * @returns True if the next character in the string is the given character.\n\t */\n\tmatch(char: string): boolean {\n\t\tif (this.peek() === char) {\n\t\t\tthis.consume();\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n}\n\n/**\n * @description A parser for SECS-II SML strings.\n */\nexport class SmlParser {\n\tprivate static readonly SML_REGEX = /^[Ss](\\d+)[Ff](\\d+)\\s*(W?)\\s*(.*)\\.$/s;\n\n\t/**\n\t * @description Parses an SML string into a SecsMessage.\n\t * @param sml The SML string to parse.\n\t * @returns The parsed SecsMessage.\n\t */\n\tstatic parse(sml: string): SecsMessage {\n\t\tconst trimmed = sml.trim();\n\t\tconst match = this.SML_REGEX.exec(trimmed);\n\n\t\tif (!match) {\n\t\t\tthrow new Error(\"Invalid SML format. Must match 'SxFy [W] <Body>.'\");\n\t\t}\n\n\t\tconst stream = parseInt(match[1], 10);\n\t\tconst func = parseInt(match[2], 10);\n\t\tconst wBit = match[3].toUpperCase() === \"W\";\n\t\tconst bodyStr = match[4].trim();\n\n\t\tconst body = this.parseBody(bodyStr);\n\n\t\treturn new SecsMessage(stream, func, wBit, body);\n\t}\n\n\t/**\n\t * @description Parses an SML body string into a Secs2Item.\n\t * @param smlBody The SML body string to parse.\n\t * @returns The parsed Secs2Item.\n\t */\n\tstatic parseBody(smlBody: string): AbstractSecs2Item | null {\n\t\tconst trimmed = smlBody.trim();\n\t\tif (trimmed.length === 0) {\n\t\t\treturn null;\n\t\t}\n\t\tconst cursor = new SmlCursor(trimmed);\n\t\treturn this.parseItem(cursor);\n\t}\n\n\tprivate static parseItem(cursor: SmlCursor): AbstractSecs2Item {\n\t\tcursor.skipWs();\n\t\tif (cursor.consume() !== \"<\") {\n\t\t\tthrow new Error(`Expected '<' at pos ${(cursor.pos - 1).toString()}`);\n\t\t}\n\n\t\tcursor.skipWs();\n\t\tconst typeStart = cursor.pos;\n\t\twhile (!cursor.eof() && /[A-Z0-9]/.test(cursor.peek().toUpperCase())) {\n\t\t\tcursor.consume();\n\t\t}\n\t\tconst typeStr = cursor.str.substring(typeStart, cursor.pos).toUpperCase();\n\n\t\t// Skip length [size]\n\t\tcursor.skipWs();\n\t\tif (cursor.peek() === \"[\") {\n\t\t\twhile (!cursor.eof() && cursor.peek() !== \"]\") cursor.consume();\n\t\t\tif (cursor.peek() === \"]\") cursor.consume();\n\t\t}\n\n\t\tlet item: AbstractSecs2Item;\n\n\t\tif (typeStr === \"L\") {\n\t\t\tconst items: AbstractSecs2Item[] = [];\n\n\t\t\twhile (true) {\n\t\t\t\tcursor.skipWs();\n\t\t\t\tif (cursor.peek() === \">\") {\n\t\t\t\t\tcursor.consume();\n\t\t\t\t\tbreak;\n\t\t\t\t} else if (cursor.peek() === \"<\") {\n\t\t\t\t\titems.push(this.parseItem(cursor));\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Unexpected char in List: '${cursor.peek()}' at ${cursor.pos.toString()}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\titem = new Secs2ItemList(items);\n\t\t} else if (typeStr === \"A\") {\n\t\t\tcursor.skipWs();\n\t\t\t// Expect quoted string\n\t\t\tif (cursor.peek() === '\"') {\n\t\t\t\tcursor.consume();\n\t\t\t\tconst start = cursor.pos;\n\t\t\t\twhile (!cursor.eof() && cursor.peek() !== '\"') cursor.consume(); // Handle escaping? SML usually simple.\n\t\t\t\tconst val = cursor.str.substring(start, cursor.pos);\n\t\t\t\tcursor.consume(); // quote\n\t\t\t\titem = new Secs2ItemAscii(val);\n\t\t\t} else {\n\t\t\t\t// Empty string or unquoted? Standard says quoted.\n\t\t\t\t// Assuming empty if > follows immediately\n\t\t\t\tif (cursor.peek() === \">\") {\n\t\t\t\t\titem = new Secs2ItemAscii(\"\");\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Expected string value for type A at ${cursor.pos.toString()}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tcursor.skipWs();\n\t\t\tif (cursor.consume() !== \">\") throw new Error(\"Expected '>' ending A\");\n\t\t} else if (typeStr === \"B\") {\n\t\t\t// Binary: 0xXX or XX\n\t\t\tconst buffer: number[] = [];\n\n\t\t\twhile (true) {\n\t\t\t\tcursor.skipWs();\n\t\t\t\tif (cursor.peek() === \">\") {\n\t\t\t\t\tcursor.consume();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t// Read byte\n\t\t\t\t// Handle 0x prefix\n\t\t\t\tif (\n\t\t\t\t\tcursor.str.startsWith(\"0x\", cursor.pos) ||\n\t\t\t\t\tcursor.str.startsWith(\"0X\", cursor.pos)\n\t\t\t\t) {\n\t\t\t\t\tcursor.pos += 2;\n\t\t\t\t}\n\t\t\t\tconst byteStr = cursor.str.substring(cursor.pos, cursor.pos + 2);\n\t\t\t\tconst byteVal = parseInt(byteStr, 16);\n\t\t\t\tif (isNaN(byteVal))\n\t\t\t\t\tthrow new Error(`Invalid binary byte at ${cursor.pos.toString()}`);\n\t\t\t\tbuffer.push(byteVal);\n\t\t\t\tcursor.pos += 2;\n\t\t\t}\n\t\t\titem = new Secs2ItemBinary(Buffer.from(buffer));\n\t\t} else if (typeStr === \"BOOLEAN\") {\n\t\t\tconst bools: boolean[] = [];\n\n\t\t\twhile (true) {\n\t\t\t\tcursor.skipWs();\n\t\t\t\tif (cursor.peek() === \">\") {\n\t\t\t\t\tcursor.consume();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t// Read T/True/F/False\n\t\t\t\tconst start = cursor.pos;\n\t\t\t\twhile (!cursor.eof() && /[A-Z]/.test(cursor.peek().toUpperCase()))\n\t\t\t\t\tcursor.consume();\n\t\t\t\tconst val = cursor.str.substring(start, cursor.pos).toUpperCase();\n\t\t\t\tif ([\"T\", \"TRUE\"].includes(val)) bools.push(true);\n\t\t\t\telse if ([\"F\", \"FALSE\"].includes(val)) bools.push(false);\n\t\t\t\telse throw new Error(`Invalid Boolean value ${val}`);\n\t\t\t}\n\t\t\titem = new Secs2ItemBoolean(bools.length === 1 ? bools[0] : bools);\n\t\t} else {\n\t\t\t// Numbers\n\t\t\tconst nums: number[] = []; // or bigint\n\t\t\t// Simplified number parsing\n\t\t\tconst isFloat = [\"F4\", \"F8\"].includes(typeStr);\n\n\t\t\twhile (true) {\n\t\t\t\tcursor.skipWs();\n\t\t\t\tif (cursor.peek() === \">\") {\n\t\t\t\t\tcursor.consume();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tconst start = cursor.pos;\n\t\t\t\twhile (!cursor.eof() && /[0-9.\\-+]/.test(cursor.peek()))\n\t\t\t\t\tcursor.consume();\n\t\t\t\tconst valStr = cursor.str.substring(start, cursor.pos);\n\t\t\t\tconst val = isFloat ? parseFloat(valStr) : Number(valStr); // Use BigInt if needed for U8/I8\n\t\t\t\tif (isNaN(val))\n\t\t\t\t\tthrow new Error(`Invalid number ${valStr} at ${start.toString()}`);\n\t\t\t\tnums.push(val);\n\t\t\t}\n\n\t\t\t// Determine SecsItemType\n\t\t\tconst type = SecsItemType[typeStr as keyof typeof SecsItemType];\n\n\t\t\tif (type === undefined) throw new Error(`Unknown type ${typeStr}`);\n\n\t\t\titem = new Secs2ItemNumeric(type, nums.length === 1 ? nums[0] : nums);\n\t\t}\n\n\t\treturn item;\n\t}\n}\n"],"mappings":";;;;;;;;;;;;AAYA,IAAM,YAAN,MAAgB;CACf,YACC,AAAOA,KACP,AAAO,MAAM,GACZ;EAFM;EACA;;;;;;CAOR,OAAe;AACd,SAAO,KAAK,IAAI,KAAK;;;;;;CAOtB,UAAkB;AACjB,SAAO,KAAK,IAAI,KAAK;;;;;;CAOtB,MAAe;AACd,SAAO,KAAK,OAAO,KAAK,IAAI;;;;;CAM7B,SAAS;AACR,SAAO,CAAC,KAAK,KAAK,IAAI,KAAK,KAAK,KAAK,MAAM,CAAC,CAAE,MAAK;;;;;;;CAQpD,MAAM,MAAuB;AAC5B,MAAI,KAAK,MAAM,KAAK,MAAM;AACzB,QAAK,SAAS;AACd,UAAO;;AAER,SAAO;;;;;;AAOT,IAAa,YAAb,MAAuB;CACtB,OAAwB,YAAY;;;;;;CAOpC,OAAO,MAAM,KAA0B;EACtC,MAAM,UAAU,IAAI,MAAM;EAC1B,MAAM,QAAQ,KAAK,UAAU,KAAK,QAAQ;AAE1C,MAAI,CAAC,MACJ,OAAM,IAAI,MAAM,oDAAoD;EAGrE,MAAM,SAAS,SAAS,MAAM,IAAI,GAAG;EACrC,MAAM,OAAO,SAAS,MAAM,IAAI,GAAG;EACnC,MAAM,OAAO,MAAM,GAAG,aAAa,KAAK;EACxC,MAAM,UAAU,MAAM,GAAG,MAAM;AAI/B,SAAO,IAAI,YAAY,QAAQ,MAAM,MAFxB,KAAK,UAAU,QAAQ,CAEY;;;;;;;CAQjD,OAAO,UAAU,SAA2C;EAC3D,MAAM,UAAU,QAAQ,MAAM;AAC9B,MAAI,QAAQ,WAAW,EACtB,QAAO;EAER,MAAM,SAAS,IAAI,UAAU,QAAQ;AACrC,SAAO,KAAK,UAAU,OAAO;;CAG9B,OAAe,UAAU,QAAsC;AAC9D,SAAO,QAAQ;AACf,MAAI,OAAO,SAAS,KAAK,IACxB,OAAM,IAAI,MAAM,wBAAwB,OAAO,MAAM,GAAG,UAAU,GAAG;AAGtE,SAAO,QAAQ;EACf,MAAM,YAAY,OAAO;AACzB,SAAO,CAAC,OAAO,KAAK,IAAI,WAAW,KAAK,OAAO,MAAM,CAAC,aAAa,CAAC,CACnE,QAAO,SAAS;EAEjB,MAAM,UAAU,OAAO,IAAI,UAAU,WAAW,OAAO,IAAI,CAAC,aAAa;AAGzE,SAAO,QAAQ;AACf,MAAI,OAAO,MAAM,KAAK,KAAK;AAC1B,UAAO,CAAC,OAAO,KAAK,IAAI,OAAO,MAAM,KAAK,IAAK,QAAO,SAAS;AAC/D,OAAI,OAAO,MAAM,KAAK,IAAK,QAAO,SAAS;;EAG5C,IAAIC;AAEJ,MAAI,YAAY,KAAK;GACpB,MAAMC,QAA6B,EAAE;AAErC,UAAO,MAAM;AACZ,WAAO,QAAQ;AACf,QAAI,OAAO,MAAM,KAAK,KAAK;AAC1B,YAAO,SAAS;AAChB;eACU,OAAO,MAAM,KAAK,IAC5B,OAAM,KAAK,KAAK,UAAU,OAAO,CAAC;QAElC,OAAM,IAAI,MACT,6BAA6B,OAAO,MAAM,CAAC,OAAO,OAAO,IAAI,UAAU,GACvE;;AAGH,UAAO,IAAI,cAAc,MAAM;aACrB,YAAY,KAAK;AAC3B,UAAO,QAAQ;AAEf,OAAI,OAAO,MAAM,KAAK,MAAK;AAC1B,WAAO,SAAS;IAChB,MAAM,QAAQ,OAAO;AACrB,WAAO,CAAC,OAAO,KAAK,IAAI,OAAO,MAAM,KAAK,KAAK,QAAO,SAAS;IAC/D,MAAM,MAAM,OAAO,IAAI,UAAU,OAAO,OAAO,IAAI;AACnD,WAAO,SAAS;AAChB,WAAO,IAAI,eAAe,IAAI;cAI1B,OAAO,MAAM,KAAK,IACrB,QAAO,IAAI,eAAe,GAAG;OAE7B,OAAM,IAAI,MACT,uCAAuC,OAAO,IAAI,UAAU,GAC5D;AAGH,UAAO,QAAQ;AACf,OAAI,OAAO,SAAS,KAAK,IAAK,OAAM,IAAI,MAAM,wBAAwB;aAC5D,YAAY,KAAK;GAE3B,MAAMC,SAAmB,EAAE;AAE3B,UAAO,MAAM;AACZ,WAAO,QAAQ;AACf,QAAI,OAAO,MAAM,KAAK,KAAK;AAC1B,YAAO,SAAS;AAChB;;AAID,QACC,OAAO,IAAI,WAAW,MAAM,OAAO,IAAI,IACvC,OAAO,IAAI,WAAW,MAAM,OAAO,IAAI,CAEvC,QAAO,OAAO;IAEf,MAAM,UAAU,OAAO,IAAI,UAAU,OAAO,KAAK,OAAO,MAAM,EAAE;IAChE,MAAM,UAAU,SAAS,SAAS,GAAG;AACrC,QAAI,MAAM,QAAQ,CACjB,OAAM,IAAI,MAAM,0BAA0B,OAAO,IAAI,UAAU,GAAG;AACnE,WAAO,KAAK,QAAQ;AACpB,WAAO,OAAO;;AAEf,UAAO,IAAI,gBAAgB,OAAO,KAAK,OAAO,CAAC;aACrC,YAAY,WAAW;GACjC,MAAMC,QAAmB,EAAE;AAE3B,UAAO,MAAM;AACZ,WAAO,QAAQ;AACf,QAAI,OAAO,MAAM,KAAK,KAAK;AAC1B,YAAO,SAAS;AAChB;;IAGD,MAAM,QAAQ,OAAO;AACrB,WAAO,CAAC,OAAO,KAAK,IAAI,QAAQ,KAAK,OAAO,MAAM,CAAC,aAAa,CAAC,CAChE,QAAO,SAAS;IACjB,MAAM,MAAM,OAAO,IAAI,UAAU,OAAO,OAAO,IAAI,CAAC,aAAa;AACjE,QAAI,CAAC,KAAK,OAAO,CAAC,SAAS,IAAI,CAAE,OAAM,KAAK,KAAK;aACxC,CAAC,KAAK,QAAQ,CAAC,SAAS,IAAI,CAAE,OAAM,KAAK,MAAM;QACnD,OAAM,IAAI,MAAM,yBAAyB,MAAM;;AAErD,UAAO,IAAI,iBAAiB,MAAM,WAAW,IAAI,MAAM,KAAK,MAAM;SAC5D;GAEN,MAAMC,OAAiB,EAAE;GAEzB,MAAM,UAAU,CAAC,MAAM,KAAK,CAAC,SAAS,QAAQ;AAE9C,UAAO,MAAM;AACZ,WAAO,QAAQ;AACf,QAAI,OAAO,MAAM,KAAK,KAAK;AAC1B,YAAO,SAAS;AAChB;;IAED,MAAM,QAAQ,OAAO;AACrB,WAAO,CAAC,OAAO,KAAK,IAAI,YAAY,KAAK,OAAO,MAAM,CAAC,CACtD,QAAO,SAAS;IACjB,MAAM,SAAS,OAAO,IAAI,UAAU,OAAO,OAAO,IAAI;IACtD,MAAM,MAAM,UAAU,WAAW,OAAO,GAAG,OAAO,OAAO;AACzD,QAAI,MAAM,IAAI,CACb,OAAM,IAAI,MAAM,kBAAkB,OAAO,MAAM,MAAM,UAAU,GAAG;AACnE,SAAK,KAAK,IAAI;;GAIf,MAAM,OAAO,aAAa;AAE1B,OAAI,SAAS,OAAW,OAAM,IAAI,MAAM,gBAAgB,UAAU;AAElE,UAAO,IAAI,iBAAiB,MAAM,KAAK,WAAW,IAAI,KAAK,KAAK,KAAK;;AAGtE,SAAO"}
|