netkitty
Version:
Network tools kit
371 lines (370 loc) • 21.9 kB
JavaScript
"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;