UNPKG

netkitty

Version:
371 lines (370 loc) 21.9 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.IEC61850SampledValues = 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 BufferToNumber_1 = require("../../helper/BufferToNumber"); const NumberToBuffer_1 = require("../../helper/NumberToBuffer"); class IEC61850SampledValues 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', 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(); 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); } } } }, svPdu: { type: 'object', label: 'Sampled Values PDU', decode: () => { const buffer = this.readBytes(8, (this.instance.length.getValue()) - 8); this.TLVInstance = node_tlv_1.default.parse(buffer); this.TLVChild = this.TLVInstance.getChild(); this.instance.svPdu.setValue({}); }, encode: () => { let buffer = Buffer.from([]); this.TLVChild.forEach(TLVItem => buffer = Buffer.concat([buffer, TLVItem.bTag, TLVItem.bLength, TLVItem.bValue])); const svPduTLV = new node_tlv_1.default(0x60, buffer); const svPduBuffer = Buffer.concat([svPduTLV.bTag, svPduTLV.bLength, svPduTLV.bValue]); this.writeBytes(8, svPduBuffer); /** * Update the length only if it is not set * Update length(APPID's length + Length's length + Reserved1's length + Reserved2's length + svPdu's length) */ if (this.instance.length.getValue() > 0) return; this.instance.length.setValue(2 + 2 + 2 + 2 + svPduBuffer.length); }, properties: { noASDU: { type: 'integer', minimum: 1, maximum: 65535, label: 'Number of ASDU', decode: () => { const noASDUTLV = this.TLVChild.find(tlv => tlv.getTag('number') === 0x80); if (!noASDUTLV) return this.recordError(this.instance.svPdu.noASDU.getPath(), 'Not Found'); const noASDUNum = (0, HexToNumber_1.HexToUInt16)(noASDUTLV.getValue('hex')); if (!noASDUNum) this.recordError(this.instance.svPdu.noASDU.getPath(), 'Number of ASDU should be greater or equal to 1'); this.instance.svPdu.noASDU.setValue(noASDUNum); }, encode: () => { const noASDU = this.instance.svPdu.noASDU.getValue(0, (nodePath) => this.recordError(nodePath, 'noASDU is not set')); this.TLVChild.push(new node_tlv_1.default(0x80, (0, NumberToBERHex_1.UInt16ToBERHex)(noASDU))); } }, seqASDU: { type: 'array', label: 'Sequence ASDU', items: { type: 'object', properties: { svID: { type: 'string', contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.ASCII, label: 'SvID' }, dataSet: { type: 'string', contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.ASCII, label: 'DatSet' }, smpCnt: { type: 'integer', label: 'SmpCnt' }, confRev: { type: 'integer', label: 'ConfRev' }, refrTm: { type: 'string', contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.BIGINT, label: 'RefrTm' }, smpSynch: { type: 'integer', label: 'SmpSynch' }, smpRate: { type: 'integer', label: 'SmpRate' }, sample: { type: 'string', contentEncoding: StringContentEncodingEnum_1.StringContentEncodingEnum.HEX, label: 'Sample' }, smpMod: { type: 'integer', label: 'SmpMod' } } }, decode: () => { const seqASDU = []; const seqASDUTLV = this.TLVChild.find(tlv => tlv.getTag('number') === 0xa2); if (!seqASDUTLV) { this.instance.svPdu.seqASDU.setValue(seqASDU); return; } const ASDUTLVs = seqASDUTLV.getChild(); ASDUTLVs.forEach((ASDUTLV, index) => { const errorNodePath = this.instance.svPdu.seqASDU.getPath(index); if (ASDUTLV.getTag('number') !== 0x30) this.recordError(errorNodePath, 'Invalid ASDU item tag'); const ASDUAttributeTLVs = ASDUTLV.getChild(); let svID; let dataSet; let smpCnt; let confRev; let refrTm; let smpSynch; let smpRate; let sample; let smpMod; //svID const svIDTLV = ASDUAttributeTLVs.find(tlv => tlv.getTag('number') === 0x80); if (svIDTLV) { svID = svIDTLV.getValue('buffer').toString('ascii'); } else { this.recordError(errorNodePath, 'svID Not Found'); } //dataSet (optional) const dataSetTLV = ASDUAttributeTLVs.find(tlv => tlv.getTag('number') === 0x81); if (dataSetTLV) { dataSet = dataSetTLV.getValue('buffer').toString('ascii'); } //smpCnt const smpCntTLV = ASDUAttributeTLVs.find(tlv => tlv.getTag('number') === 0x82); if (smpCntTLV) { smpCnt = (0, BufferToNumber_1.BufferToUInt16)(smpCntTLV.getValue('buffer')); } else { this.recordError(errorNodePath, 'smpCnt Not Found'); } //confRev const confRevTLV = ASDUAttributeTLVs.find(tlv => tlv.getTag('number') === 0x83); if (confRevTLV) { confRev = (0, BufferToNumber_1.BufferToUInt32)(confRevTLV.getValue('buffer')); } else { this.recordError(errorNodePath, 'confRev Not Found'); } //refrTm (optional) const refrTmTLV = ASDUAttributeTLVs.find(tlv => tlv.getTag('number') === 0x84); if (refrTmTLV) { refrTm = (0, BufferToNumber_1.BufferToUInt64)(refrTmTLV.getValue('buffer')).toString(); } //smpSynch const smpSynchTLV = ASDUAttributeTLVs.find(tlv => tlv.getTag('number') === 0x85); if (smpSynchTLV) { smpSynch = (0, BufferToNumber_1.BufferToUInt8)(smpSynchTLV.getValue('buffer')); } else { this.recordError(errorNodePath, 'smpSynch Not Found'); } //smpRate (optional) const smpRateTLV = ASDUAttributeTLVs.find(tlv => tlv.getTag('number') === 0x86); if (smpRateTLV) { smpRate = (0, BufferToNumber_1.BufferToUInt16)(smpRateTLV.getValue('buffer')); } //sample const sampleTLV = ASDUAttributeTLVs.find(tlv => tlv.getTag('number') === 0x87); if (sampleTLV) { sample = sampleTLV.getValue('hex'); } else { this.recordError(errorNodePath, 'sample Not Found'); } //smpMod (optional) const smpModTLV = ASDUAttributeTLVs.find(tlv => tlv.getTag('number') === 0x86); if (smpModTLV) { smpMod = (0, BufferToNumber_1.BufferToUInt16)(smpModTLV.getValue('buffer')); } seqASDU.push({ svID: svID, dataSet: dataSet, smpCnt: smpCnt, confRev: confRev, refrTm: refrTm, smpSynch: smpSynch, smpRate: smpRate, sample: sample, smpMod: smpMod }); }); this.instance.svPdu.seqASDU.setValue(seqASDU); }, encode: () => { const seqASDU = this.instance.svPdu.seqASDU.isUndefined() ? [] : this.instance.svPdu.seqASDU.getValue(); const seqASDUTLVs = []; seqASDU.forEach((seqASDUItem, index) => { const errorNodePath = this.instance.svPdu.seqASDU.getPath(index); const seqASDUItemTLVs = []; //svID if (seqASDUItem.svID !== undefined) { seqASDUItemTLVs.push(new node_tlv_1.default(0x80, Buffer.from(seqASDUItem.svID ? seqASDUItem.svID : '', 'ascii'))); } else { this.recordError(errorNodePath, 'No svID'); } //dataSet if (seqASDUItem.dataSet !== undefined) seqASDUItemTLVs.push(new node_tlv_1.default(0x81, Buffer.from(seqASDUItem.dataSet ? seqASDUItem.dataSet : '', 'ascii'))); // smpCnt if (seqASDUItem.smpCnt !== undefined) { seqASDUItemTLVs.push(new node_tlv_1.default(0x82, (0, NumberToHex_1.UInt16ToHex)(seqASDUItem.smpCnt))); } else { this.recordError(errorNodePath, 'No smpCnt'); } // confRev if (seqASDUItem.confRev !== undefined) { seqASDUItemTLVs.push(new node_tlv_1.default(0x83, (0, NumberToHex_1.UInt32ToHex)(seqASDUItem.confRev))); } else { this.recordError(errorNodePath, 'No confRev'); } // refrTm if (seqASDUItem.refrTm !== undefined) seqASDUItemTLVs.push(new node_tlv_1.default(0x84, Buffer.from(BigInt(seqASDUItem.refrTm).toString(16).padStart(8 * 2, '0'), 'hex'))); // smpSynch if (seqASDUItem.smpSynch !== undefined) { seqASDUItemTLVs.push(new node_tlv_1.default(0x85, (0, NumberToHex_1.UInt8ToHex)(seqASDUItem.smpSynch))); } else { this.recordError(errorNodePath, 'No smpSynch'); } // smpRate if (seqASDUItem.smpRate !== undefined) seqASDUItemTLVs.push(new node_tlv_1.default(0x86, (0, NumberToHex_1.UInt16ToHex)(seqASDUItem.smpRate))); // sample if (seqASDUItem.sample !== undefined) { seqASDUItemTLVs.push(new node_tlv_1.default(0x87, Buffer.from(seqASDUItem.sample, 'hex'))); } else { this.recordError(errorNodePath, 'No sample'); } // smpMod if (seqASDUItem.smpMod !== undefined) seqASDUItemTLVs.push(new node_tlv_1.default(0x88, (0, NumberToHex_1.UInt16ToHex)(seqASDUItem.smpMod))); if (!seqASDUItemTLVs.length) return; let seqASDUItemBuffer = Buffer.from([]); seqASDUItemTLVs.forEach(seqASDUItemTLV => seqASDUItemBuffer = Buffer.concat([seqASDUItemBuffer, seqASDUItemTLV.bTag, seqASDUItemTLV.bLength, seqASDUItemTLV.bValue])); seqASDUTLVs.push(new node_tlv_1.default(0x30, seqASDUItemBuffer)); }); let seqASDUBuffer = Buffer.from([]); seqASDUTLVs.forEach(seqASDUTLV => seqASDUBuffer = Buffer.concat([seqASDUBuffer, seqASDUTLV.bTag, seqASDUTLV.bLength, seqASDUTLV.bValue])); this.TLVChild.push(new node_tlv_1.default(0xa2, seqASDUBuffer)); } } } } } }; this.id = 'sv'; this.name = 'IEC61850 Sampled Values'; this.nickname = 'SV'; } match() { if (!this.prevCodecModule) return false; return this.prevCodecModule.instance.etherType.getValue() === (0, NumberToHex_1.UInt16ToHex)(0x88ba); } } exports.IEC61850SampledValues = IEC61850SampledValues;