UNPKG

netkitty

Version:
792 lines 54.1 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Goose = void 0; const BaseHeader_1 = require("../abstracts/BaseHeader"); const node_tlv_1 = __importDefault(require("node-tlv")); const HexToNumber_1 = require("../../helper/HexToNumber"); const NumberToBERHex_1 = require("../../helper/NumberToBERHex"); const NumberToHex_1 = require("../../helper/NumberToHex"); const StringContentEncodingEnum_1 = require("../lib/StringContentEncodingEnum"); const NumberToBERBuffer_1 = require("../../helper/NumberToBERBuffer"); const BufferToNumber_1 = require("../../helper/BufferToNumber"); const NumberToBuffer_1 = require("../../helper/NumberToBuffer"); const GetBERIntegerLengthFromBuffer_1 = require("../lib/GetBERIntegerLengthFromBuffer"); var ItemDataType; (function (ItemDataType) { ItemDataType["Boolean"] = "Boolean"; ItemDataType["INT8"] = "INT8"; ItemDataType["INT16"] = "INT16"; ItemDataType["INT32"] = "INT32"; ItemDataType["INT64"] = "INT64"; ItemDataType["INT8U"] = "INT8U"; ItemDataType["INT16U"] = "INT16U"; ItemDataType["INT32U"] = "INT32U"; ItemDataType["FLOAT32"] = "FLOAT32"; ItemDataType["CODEDENUM"] = "CODED-ENUM"; ItemDataType["OCTETSTRING"] = "OCTET-STRING"; ItemDataType["VISIBLESTRING"] = "VISIBLE-STRING"; ItemDataType["TimeStamp"] = "TimeStamp"; ItemDataType["Quality"] = "Quality"; ItemDataType["Structure"] = "Structure"; })(ItemDataType || (ItemDataType = {})); class Goose extends BaseHeader_1.BaseHeader { constructor() { super(...arguments); this.TLVChild = []; this.SCHEMA = { type: 'object', properties: { appid: { type: 'integer', minimum: 0, maximum: 65535, label: 'APPID', decode: () => { this.instance.appid.setValue((0, BufferToNumber_1.BufferToUInt16)(this.readBytes(0, 2))); }, encode: () => { const APPID = this.instance.appid.getValue(0, (nodePath) => this.recordError(nodePath, 'Not Found')); this.instance.appid.setValue(APPID); this.writeBytes(0, (0, NumberToBuffer_1.UInt16ToBuffer)(APPID)); } }, length: { type: 'integer', minimum: 0, maximum: 65535, label: 'Length', decode: () => { this.instance.length.setValue((0, BufferToNumber_1.BufferToUInt16)(this.readBytes(2, 2))); }, encode: () => { const length = this.instance.length.getValue(0, (nodePath) => this.recordError(nodePath, 'Not Found')); if (length > 0) { this.instance.length.setValue(length); this.writeBytes(2, (0, NumberToBuffer_1.UInt16ToBuffer)(length)); } else { this.addPostSelfEncodeHandler(() => { const finalLength = parseInt(this.instance.length.getValue().toString()); this.writeBytes(2, (0, NumberToBuffer_1.UInt16ToBuffer)(finalLength)); }); } } }, reserved1: { type: 'object', label: 'Reserved1', properties: { simulated: { type: 'boolean', label: 'Simulated', decode: () => { this.instance.reserved1.simulated.setValue(!!this.readBits(4, 2, 0, 1)); }, encode: () => { const simulated = this.instance.reserved1.simulated.getValue(false); this.writeBits(4, 2, 0, 1, simulated ? 1 : 0); } }, reserved: { type: 'number', minimum: 0, maximum: 32767, label: 'Reserved', decode: () => { this.instance.reserved1.reserved.setValue(this.readBits(4, 2, 1, 16)); }, encode: () => { const reserved = this.instance.reserved1.reserved.getValue(0); this.writeBits(4, 2, 1, 16, reserved); } } } }, reserved2: { type: 'object', label: 'Reserved2', properties: { reserved: { type: 'number', minimum: 0, maximum: 65535, label: 'Reserved', decode: () => { this.instance.reserved2.reserved.setValue(this.readBits(4, 2, 0, 16)); }, encode: () => { const reserved = this.instance.reserved2.reserved.getValue(0); this.writeBits(4, 2, 0, 16, reserved); } } } }, goosePdu: { type: 'object', label: 'GOOSE PDU', decode: () => { let readTLVBufferLength = this.packet.length - this.startPos - 8; while (!this.TLVInstance) { try { const buffer = this.readBytes(8, readTLVBufferLength, true); this.TLVInstance = node_tlv_1.default.parse(buffer); const tagWithLength = buffer.toString('hex').replace(this.TLVInstance.bValue.toString('hex'), '#').split('#'); const tagWithLengthBytes = Math.max(...tagWithLength.map((value) => Math.ceil(value.length / 2))); const TLVBufferLength = this.TLVInstance.bValue.length + tagWithLengthBytes; this.TLVInstance = node_tlv_1.default.parse(this.readBytes(8, TLVBufferLength, false)); } catch (e) { readTLVBufferLength -= 1; if (!readTLVBufferLength) break; } } this.TLVChild = this.TLVInstance ? this.TLVInstance.getChild() : []; }, encode: () => { let buffers = Buffer.from([]); this.TLVChild.forEach(item => buffers = Buffer.concat([buffers, item.bTag, item.bLength, item.bValue])); const goosePduTLV = new node_tlv_1.default(0x61, buffers); const goosePduBuffer = Buffer.concat([goosePduTLV.bTag, goosePduTLV.bLength, goosePduTLV.bValue]); this.writeBytes(8, goosePduBuffer); /** * Update the length only if it is not set * Update length(APPID's length + Length's length + Reserved1's length + Reserved2's length + goosePdu's length) */ if (this.instance.length.getValue() > 0) return; this.instance.length.setValue(2 + 2 + 2 + 2 + goosePduBuffer.length); }, properties: { gocbRef: { type: 'string', maxLength: 129, label: 'GoCBReference', contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.ASCII, decode: () => { const gocbRefTLV = this.TLVChild.find(tlv => tlv.getTag('number') === 0x80); if (!gocbRefTLV) return this.recordError(this.instance.goosePdu.gocbRef.getPath(), 'Not Found'); this.instance.goosePdu.gocbRef.setValue(gocbRefTLV.getValue('buffer').toString('ascii')); }, encode: () => { const gocbRefValue = this.instance.goosePdu.gocbRef.getValue('', (nodePath) => this.recordError(nodePath, 'Not Found')); if (!gocbRefValue) return; let gocbRefBuffer = Buffer.from(gocbRefValue, 'ascii'); if (gocbRefBuffer.length > 129) { this.recordError(this.instance.goosePdu.gocbRef.getPath(), 'This VisibleString shall have a maximum size of 129 octets'); gocbRefBuffer = gocbRefBuffer.subarray(0, 129); } this.TLVChild.push(new node_tlv_1.default(0x80, gocbRefBuffer)); } }, timeAllowedtoLive: { type: 'number', minimum: 0, maximum: 4294967295, label: 'TimeAllowedtoLive', decode: () => { const timeAllowedtoLiveString = this.TLVChild.find(tlv => tlv.getTag('number') === 0x81)?.getValue('hex'); if (!timeAllowedtoLiveString) return this.recordError(this.instance.goosePdu.timeAllowedtoLive.getPath(), 'Not Found'); this.instance.goosePdu.timeAllowedtoLive.setValue((0, HexToNumber_1.HexToUInt32)(timeAllowedtoLiveString)); }, encode: () => { let timeAllowedtoLiveValue = this.instance.goosePdu.timeAllowedtoLive.getValue(-1, (nodePath) => this.recordError(nodePath, 'Not Found')); if (timeAllowedtoLiveValue === -1) return; if (timeAllowedtoLiveValue < 1 || timeAllowedtoLiveValue > 4294967295) { this.recordError(this.instance.goosePdu.timeAllowedtoLive.getPath(), 'This INTEGER value shall have a range of 1 to 4294967295'); timeAllowedtoLiveValue = 4294967295; } const timeAllowedtoLiveTLV = new node_tlv_1.default(0x81, (0, NumberToBERBuffer_1.UInt32ToBERBuffer)(timeAllowedtoLiveValue)); this.TLVChild.push(timeAllowedtoLiveTLV); } }, datSet: { type: 'string', maxLength: 129, label: 'DatSet', contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.ASCII, decode: () => { const datSetTLV = this.TLVChild.find(tlv => tlv.getTag('number') === 0x82); if (!datSetTLV) return this.recordError(this.instance.goosePdu.datSet.getPath(), 'Not Found'); this.instance.goosePdu.datSet.setValue(datSetTLV.getValue('buffer').toString('ascii')); }, encode: () => { const datSetValue = this.instance.goosePdu.datSet.getValue('', (nodePath) => this.recordError(nodePath, 'Not Found')); if (!datSetValue) return; let datSetBuffer = Buffer.from(datSetValue, 'ascii'); if (datSetBuffer.length > 129) { this.recordError(this.instance.goosePdu.datSet.getPath(), 'This VisibleString shall have a maximum size of 129 octets'); datSetBuffer = datSetBuffer.subarray(0, 129); } this.TLVChild.push(new node_tlv_1.default(0x82, datSetBuffer)); } }, goID: { type: 'string', maxLength: 65, label: 'GoID', contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.ASCII, decode: () => { const goIDTLV = this.TLVChild.find(tlv => tlv.getTag('number') === 0x83); if (!goIDTLV) return this.recordError(this.instance.goosePdu.goID.getPath(), 'Not Found'); this.instance.goosePdu.goID.setValue(goIDTLV.getValue('buffer').toString('ascii')); }, encode: () => { const goIDValue = this.instance.goosePdu.goID.getValue('', (nodePath) => this.recordError(nodePath, 'Not Found')); if (!goIDValue) return; let goIDBuffer = Buffer.from(goIDValue, 'ascii'); if (goIDBuffer.length > 65) { this.recordError(this.instance.goosePdu.goID.getPath(), 'This VisibleString shall have a maximum size of 65 octets'); goIDBuffer = goIDBuffer.subarray(0, 65); } this.TLVChild.push(new node_tlv_1.default(0x83, goIDBuffer)); } }, t: { type: 'string', label: 'TimeStamp', contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.BIGINT, decode: () => { const tStr = this.TLVChild.find(tlv => tlv.getTag('number') === 0x84)?.getValue('hex'); if (!tStr) return this.recordError(this.instance.goosePdu.t.getPath(), 'Not Found'); this.instance.goosePdu.t.setValue(BigInt(`0x${tStr}`).toString()); }, encode: () => { const tStr = this.instance.goosePdu.t.getValue('', (nodePath) => this.recordError(nodePath, 'Not Found')); if (!tStr) return; const tBigIntValue = BigInt(tStr); const tTLV = new node_tlv_1.default(0x84, Buffer.from(tBigIntValue.toString(16).padStart(8 * 2, '0'), 'hex')); this.TLVChild.push(tTLV); } }, stNum: { type: 'integer', minimum: 0, maximum: 4294967295, label: 'StNum', decode: () => { const stNumStr = this.TLVChild.find(tlv => tlv.getTag('number') === 0x85)?.getValue('hex'); if (!stNumStr) return this.recordError(this.instance.goosePdu.stNum.getPath(), 'Not Found'); this.instance.goosePdu.stNum.setValue((0, HexToNumber_1.HexToUInt32)(stNumStr)); if (this.instance.goosePdu.stNum.getValue() < 1 || this.instance.goosePdu.stNum.getValue() > 4294967295) this.recordError(this.instance.goosePdu.stNum.getPath(), 'This INTEGER value shall have a range of 1 to 4294967295'); }, encode: () => { let stNumValue = this.instance.goosePdu.stNum.getValue(-1, (nodePath) => this.recordError(nodePath, 'Not Found')); if (stNumValue < 0) return; if (stNumValue > 4294967295) { stNumValue = 4294967295; this.recordError(this.instance.goosePdu.stNum.getPath(), 'This INTEGER value shall have a range of 1 to 4294967295'); } if (stNumValue === undefined) return this.recordError(this.instance.goosePdu.stNum.getPath(), 'Not Found'); const stNumTLV = new node_tlv_1.default(0x85, (0, NumberToBERBuffer_1.UInt32ToBERBuffer)(stNumValue)); this.TLVChild.push(stNumTLV); } }, sqNum: { type: 'integer', minimum: 0, maximum: 4294967295, label: 'SqNum', decode: () => { const sqNumStr = this.TLVChild.find(tlv => tlv.getTag('number') === 0x86)?.getValue('hex'); if (!sqNumStr) return this.recordError(this.instance.goosePdu.sqNum.getPath(), 'Not Found'); this.instance.goosePdu.sqNum.setValue((0, HexToNumber_1.HexToUInt32)(sqNumStr)); }, encode: () => { let sqNumValue = this.instance.goosePdu.sqNum.getValue(-1, (nodePath) => this.recordError(nodePath, 'Not Found')); if (sqNumValue < 0) return; if (sqNumValue > 4294967295) { sqNumValue = 4294967295; this.recordError(this.instance.goosePdu.sqNum.getPath(), 'This INTEGER value shall have a range of 1 to 4294967295'); } if (sqNumValue === undefined) return this.recordError(this.instance.goosePdu.sqNum.getPath(), 'Not Found'); const sqNumTLV = new node_tlv_1.default(0x86, (0, NumberToBERBuffer_1.UInt32ToBERBuffer)(sqNumValue)); this.TLVChild.push(sqNumTLV); } }, simulation: { type: 'boolean', label: 'Simulation', decode: () => { const simulationStr = this.TLVChild.find(tlv => tlv.getTag('number') === 0x87)?.getValue('hex'); if (!simulationStr) return this.recordError(this.instance.goosePdu.simulation.getPath(), 'Not Found'); const simulationNum = parseInt(simulationStr, 16); if (simulationNum > 1) this.recordError(this.instance.goosePdu.simulation.getPath(), 'This Boolean shall have a range of TRUE, FALSE'); this.instance.goosePdu.simulation.setValue(!!simulationNum); }, encode: () => { const simulationValue = this.instance.goosePdu.simulation.getValue(undefined, (nodePath) => this.recordError(nodePath, 'Not Found')); if (simulationValue === undefined) return; const simulationNum = simulationValue ? 1 : 0; const simulationTLV = new node_tlv_1.default(0x87, Buffer.from(simulationNum.toString(16).padStart(2, '0'), 'hex')); this.TLVChild.push(simulationTLV); } }, confRev: { type: 'integer', label: 'ConfRev', decode: () => { const confRevStr = this.TLVChild.find(tlv => tlv.getTag('number') === 0x88)?.getValue('hex'); if (!confRevStr) return this.recordError(this.instance.goosePdu.confRev.getPath(), 'Not Found'); this.instance.goosePdu.confRev.setValue((0, HexToNumber_1.HexToUInt32)(confRevStr)); }, encode: () => { let confRevValue = this.instance.goosePdu.confRev.getValue(-1, (nodePath) => this.recordError(nodePath, 'Not Found')); if (confRevValue > 4294967295) { confRevValue = 4294967295; this.recordError(this.instance.goosePdu.confRev.getPath(), 'This INTEGER value shall have a range of 0 to 4294967295'); } if (confRevValue === -1) return; const confRevTLV = new node_tlv_1.default(0x88, (0, NumberToBERBuffer_1.UInt32ToBERBuffer)(confRevValue)); this.TLVChild.push(confRevTLV); } }, ndsCom: { type: 'boolean', label: 'NdsCom', decode: () => { const ndsComStr = this.TLVChild.find(tlv => tlv.getTag('number') === 0x89)?.getValue('hex'); if (!ndsComStr) return this.recordError(this.instance.goosePdu.ndsCom.getPath(), 'Not Found'); const ndsComNum = parseInt(ndsComStr, 16); if (ndsComNum > 1) this.recordError(this.instance.goosePdu.ndsCom.getPath(), 'This Boolean shall have a range of TRUE, FALSE'); this.instance.goosePdu.ndsCom.setValue(!!ndsComNum); }, encode: () => { const ndsComValue = this.instance.goosePdu.ndsCom.getValue(undefined, (nodePath) => this.recordError(nodePath, 'Not Found')); if (ndsComValue === undefined) return; const ndsComNum = ndsComValue ? 1 : 0; const ndsComTLV = new node_tlv_1.default(0x89, Buffer.from(ndsComNum.toString(16).padStart(2, '0'), 'hex')); this.TLVChild.push(ndsComTLV); } }, numDatSetEntries: { type: 'integer', label: 'NumDatSetEntries', decode: () => { const numDatSetEntriesStr = this.TLVChild.find(tlv => tlv.getTag('number') === 0x8A)?.getValue('hex'); if (!numDatSetEntriesStr) return this.recordError(this.instance.goosePdu.numDatSetEntries.getPath(), 'Not Found'); this.instance.goosePdu.numDatSetEntries.setValue(parseInt(numDatSetEntriesStr, 16)); }, encode: () => { const numDatSetEntriesValue = this.instance.goosePdu.numDatSetEntries.getValue(undefined, (nodePath) => this.recordError(nodePath, 'Not Found')); if (numDatSetEntriesValue === undefined) return; const numDatSetEntriesTLV = new node_tlv_1.default(0x8A, (0, NumberToBERBuffer_1.UInt32ToBERBuffer)(numDatSetEntriesValue)); this.TLVChild.push(numDatSetEntriesTLV); } }, allData: { type: 'array', label: 'AllData', items: { anyOf: [ { type: 'object', label: ItemDataType.Boolean, properties: { dataType: { type: 'string', enum: [ItemDataType.Boolean] }, value: { type: 'boolean' } } }, { type: 'object', label: ItemDataType.INT8, properties: { dataType: { type: 'string', enum: [ItemDataType.INT8] }, value: { type: 'integer' } } }, { type: 'object', label: ItemDataType.INT16, properties: { dataType: { type: 'string', enum: [ItemDataType.INT16] }, value: { type: 'integer' } } }, { type: 'object', label: ItemDataType.INT32, properties: { dataType: { type: 'string', enum: [ItemDataType.INT32] }, value: { type: 'integer' } } }, { type: 'object', label: ItemDataType.INT64, properties: { dataType: { type: 'string', enum: [ItemDataType.INT64] }, value: { type: 'string', contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.BIGINT } } }, { type: 'object', label: ItemDataType.INT8U, properties: { dataType: { type: 'string', enum: [ItemDataType.INT8U] }, value: { type: 'integer' } } }, { type: 'object', label: ItemDataType.INT16U, properties: { dataType: { type: 'string', enum: [ItemDataType.INT16U] }, value: { type: 'integer' } } }, { type: 'object', label: ItemDataType.INT32U, properties: { dataType: { type: 'string', enum: [ItemDataType.INT32U] }, value: { type: 'integer' } } }, { type: 'object', label: ItemDataType.FLOAT32, properties: { dataType: { type: 'string', enum: [ItemDataType.FLOAT32] }, value: { type: 'number' } } }, { type: 'object', label: ItemDataType.CODEDENUM, properties: { dataType: { type: 'string', enum: [ItemDataType.CODEDENUM] }, value: { type: 'integer' } } }, { type: 'object', label: ItemDataType.OCTETSTRING, properties: { dataType: { type: 'string', enum: [ItemDataType.OCTETSTRING] }, value: { type: 'string', contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.HEX } } }, { type: 'object', label: ItemDataType.VISIBLESTRING, properties: { dataType: { type: 'string', enum: [ItemDataType.VISIBLESTRING] }, value: { type: 'string', contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.ASCII } } }, { type: 'object', properties: { dataType: { type: 'string', enum: [ItemDataType.TimeStamp] }, value: { type: 'string' } } }, { type: 'object', label: ItemDataType.Quality, properties: { dataType: { type: 'string', enum: [ItemDataType.Quality] }, value: { type: 'string', contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.BINARY } } }, { type: 'object', label: ItemDataType.Structure, properties: { dataType: { type: 'string', enum: [ItemDataType.Structure] }, value: { $ref: '#/properties/goosePdu/properties/allData' } } } ] }, /** * +-----------------------------------+-------------------+-------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ * | Data types according to IEC 61850-7-2 | ASN.1 Tag for Data | ASN.1 Length | Comments | * +-----------------------------------+-------------------+-------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ * | Boolean | 0x83 | 1 | 8 Bit set to 0 FALSE; anything else = TRUE | * | INT8 | 0x85 | 2 | 8 Bit Big Endian; signed | * | INT16 | 0x85 | 3 | 16 Bit Big Endian; signed | * | INT32 | 0x85 | 5 | 32 Bit Big Endian; signed | * | INT64 | 0x85 | 9 | 64Bit Big Endian; signed | * | INT8U | 0x86 | 2 | 8 Bit Big Endian; unsigned | * | INT16U | 0x86 | 3 | 16 Bit Big Endian; unsigned | * | INT24U | - | - | Not used | * | INT32U | 0x86 | 5 | 32 Bit Big Endian; unsigned | * | FLOAT32 | 0x87 | 4 | 32 Bit IEEE Floating Point (IEEE 754) | * | CODED-ENUM | 0x84 | 2 | Bit-string; depending on CODED ENUM definition – most of the time, can be encoded with 2 bytes (1st Byte = number of unused bit, 2nd Byte = Value) | * | OCTET-STRING | 0x89 | 20 | 20 Bytes ASCII Text, Null terminated | * | VISIBLE-STRING | 0x8a | 35 | 35 Bytes ASCII Text, Null terminated | * | TimeStamp | 0x91 | 8 | 64 Bit TimeStamp as defined in 8.1.3.7 IEC 6 | * | Quality | 0x84 | 3 | Bit-string | * +-----------------------------------+-------------------+-------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ */ decode: () => { const allDataTLV = this.TLVChild.find(tlv => tlv.getTag('number') === 0xAB); const dataTLVs = allDataTLV ? allDataTLV.getChild() : []; const allData = this.decodeDataTLVItem(dataTLVs); if (allData.length) this.instance.goosePdu.allData.setValue(allData); }, encode: () => { const allData = this.instance.goosePdu.allData.getValue([], (nodePath) => this.recordError(nodePath, 'Not Found')); const dataItemTLVs = this.encodeDataTLVItem(allData); if (dataItemTLVs.length) { const allDataTLV = new node_tlv_1.default(0xAB, Buffer.concat(dataItemTLVs.map((dataItemTLV) => Buffer.concat([dataItemTLV.bTag, dataItemTLV.bLength, dataItemTLV.bValue])))); this.TLVChild.push(allDataTLV); } } } } } } }; this.id = 'goose'; this.name = 'IEC61850 GOOSE'; this.nickname = 'GOOSE'; } /** * Decode data TLV items * @param dataTLVs * @protected */ decodeDataTLVItem(dataTLVs) { const dataItems = []; dataTLVs.forEach((dataTLV) => { const length = dataTLV.getLength('number'); const value = dataTLV.getValue('buffer'); switch (dataTLV.getTag('number')) { case 0x83: { dataItems.push({ dataType: ItemDataType.Boolean, value: !!parseInt(value.toString('hex'), 16) }); } break; case 0x84: { switch (length) { case 2: { dataItems.push({ dataType: ItemDataType.CODEDENUM, value: parseInt(value.toString('hex'), 16) }); } break; case 3: { dataItems.push({ dataType: ItemDataType.Quality, value: parseInt(value.toString('hex'), 16).toString(2).padStart(24, '0') }); } break; } } break; case 0x85: { const integerRealLength = (0, GetBERIntegerLengthFromBuffer_1.GetBERIntegerLengthFromBuffer)(value); if (integerRealLength === 1) { dataItems.push({ dataType: ItemDataType.INT8, value: (0, HexToNumber_1.HexToInt8)(value.toString('hex')) }); } else if (integerRealLength === 2) { dataItems.push({ dataType: ItemDataType.INT16, value: (0, HexToNumber_1.HexToInt16)(value.toString('hex')) }); } else if (integerRealLength === 4) { dataItems.push({ dataType: ItemDataType.INT32, value: (0, HexToNumber_1.HexToInt32)(value.toString('hex')) }); } else if (integerRealLength === 8) { dataItems.push({ dataType: ItemDataType.INT64, value: (0, HexToNumber_1.HexToInt64)(value.toString('hex')) }); } } break; case 0x86: { const unsignedIntegerRealLength = (0, GetBERIntegerLengthFromBuffer_1.GetBERIntegerLengthFromBuffer)(value); switch (unsignedIntegerRealLength) { case 1: { dataItems.push({ dataType: ItemDataType.INT8U, value: (0, HexToNumber_1.HexToUInt8)(value.toString('hex')) }); } break; case 2: { dataItems.push({ dataType: ItemDataType.INT16U, value: (0, HexToNumber_1.HexToUInt16)(value.toString('hex')) }); } break; case 4: { dataItems.push({ dataType: ItemDataType.INT32U, value: (0, HexToNumber_1.HexToUInt32)(value.toString('hex')) }); } break; } } break; case 0x87: { dataItems.push({ dataType: ItemDataType.FLOAT32, value: (0, HexToNumber_1.HexToFloat32)(value.toString('hex')) }); } break; case 0x89: { dataItems.push({ dataType: ItemDataType.OCTETSTRING, value: value.toString('hex') }); } break; case 0x8a: { dataItems.push({ dataType: ItemDataType.VISIBLESTRING, value: value.toString('ascii') }); } break; case 0x91: { dataItems.push({ dataType: ItemDataType.TimeStamp, value: parseInt(value.toString('hex'), 16).toString() }); } break; case 0xa2: { const subDataTLVs = node_tlv_1.default.parseList(value); dataItems.push({ dataType: ItemDataType.Structure, value: this.decodeDataTLVItem(subDataTLVs) }); } break; } }); return dataItems; } /** * Encode data TLV items * @param dataItems * @protected */ encodeDataTLVItem(dataItems) { return dataItems .map((dataItem, index) => { const errorNodePath = this.instance.goosePdu.allData.getPath(index); switch (dataItem.dataType) { case ItemDataType.Boolean: { const booleanIntValue = dataItem.value ? 1 : 0; return new node_tlv_1.default(0x83, Buffer.from(booleanIntValue.toString(16).padStart(2, '0'), 'hex')); } case ItemDataType.INT8: { let intValue = dataItem.value; if (isNaN(intValue)) this.recordError(errorNodePath, 'Invalid INT8 value'); intValue = intValue ? intValue : 0; if (intValue < -128 || intValue > 127) this.recordError(errorNodePath, 'Invalid INT8 value'); return new node_tlv_1.default(0x85, Buffer.from((0, NumberToBERHex_1.Int8ToBERHex)(intValue), 'hex')); } case ItemDataType.INT16: { let intValue = dataItem.value; if (isNaN(intValue)) this.recordError(errorNodePath, 'Invalid INT16 value'); intValue = intValue ? intValue : 0; if (intValue < -32768 || intValue > 32767) this.recordError(errorNodePath, 'Invalid INT16 value'); return new node_tlv_1.default(0x85, Buffer.from((0, NumberToBERHex_1.Int16ToBERHex)(intValue), 'hex')); } case ItemDataType.INT32: { let intValue = dataItem.value; if (isNaN(intValue)) this.recordError(errorNodePath, 'Invalid INT32 value'); intValue = intValue ? intValue : 0; if (intValue < -2147483648 || intValue > 2147483647) this.recordError(errorNodePath, 'Invalid INT32 value'); return new node_tlv_1.default(0x85, Buffer.from((0, NumberToBERHex_1.Int32ToBERHex)(intValue), 'hex')); } case ItemDataType.INT64: { const intValue = BigInt(dataItem.value); if (intValue < BigInt('-9223372036854775808') || intValue > BigInt('9223372036854775807')) this.recordError(errorNodePath, 'Invalid INT64 value'); return new node_tlv_1.default(0x85, Buffer.from((0, NumberToBERHex_1.Int64ToBERHex)(intValue), 'hex')); } case ItemDataType.INT8U: { let uintValue = dataItem.value; if (isNaN(uintValue)) this.recordError(errorNodePath, 'Invalid INT8U value'); uintValue = uintValue ? uintValue : 0; if (uintValue < 0 || uintValue > 255) this.recordError(errorNodePath, 'Invalid INT8U value'); return new node_tlv_1.default(0x86, Buffer.from((0, NumberToBERHex_1.UInt8ToBERHex)(uintValue), 'hex')); } case ItemDataType.INT16U: { let uintValue = dataItem.value; if (isNaN(uintValue)) this.recordError(errorNodePath, 'Invalid INT16U value'); uintValue = uintValue ? uintValue : 0; if (uintValue < 0 || uintValue > 65535) this.recordError(errorNodePath, 'Invalid INT16U value'); return new node_tlv_1.default(0x86, Buffer.from((0, NumberToBERHex_1.UInt16ToBERHex)(uintValue), 'hex')); } case ItemDataType.INT32U: { let uintValue = d