import {Buffer} from "buffer"; import {HdlcAddressPair} from "./HdlcAddressPair"; import {HdlcAddress} from "./HdlcAddress"; import {FcsCalc} from "./FcsCalc"; import {ReverseByteArrayInputStream} from "../ReverseByteArrayInputStream"; import {DataUtils} from "../DataUtils"; let CmdType = { CMD_RESERVE0: {value: 0, mask: 7}, CMD_LINK: {value: 1, mask: 7}, CMD_RESERVE2: {value: 2, mask: 7}, CMD_USERDATA: {value: 3, mask: 7}, CMD_RESERVE4: {value: 4, mask: 7}, CMD_RESERVE5: {value: 5, mask: 7}, CMD_RESERVE6: {value: 6, mask: 7}, CMD_RESERVE7: {value: 7, mask: 7}, } let FrameType = { CLI_RES: {value: 0x00, mask: 0xc0}, CLI_REQ: {value: 0x40, mask: 0xc0}, SRV_REQ: {value: 0x80, mask: 0xc0}, SRV_RES: {value: 0xc0, mask: 0xc0}, ERR_INVALID_TYPE : {value : 0xFF, mask : 0xFF}, } function cmdTypeFor(controlByte: number): number { for (let cmdTypeKey in CmdType) { const data = CmdType[cmdTypeKey as keyof typeof CmdType]; if ((data.mask & controlByte) == data.value) { return data.value; } } return CmdType.CMD_USERDATA.value; } function frameTypeFor(controlByte: number) : number{ for (let frameTypeKey in FrameType) { const data = FrameType[frameTypeKey as keyof typeof FrameType]; if ((data.mask & controlByte) == data.value) { return data.value; } } return FrameType.ERR_INVALID_TYPE.value; } export class HdlcFrame { FLAGBEG: number = 0x68; FLAGEND: number = 0x16; frameType: number = 0; controlField: number = 0; informationField: Buffer | null = null; segmented: boolean = false; addressPair: HdlcAddressPair | null = null; segframexh: number = 0; segframetype: number = 0; constructor() { } set_addpair_frametype(addressPair: HdlcAddressPair, frameType: number) { this.addressPair = addressPair; this.frameType = frameType; } set_all_param(frameType: number, informationField: Buffer, segmented: boolean, controlField: number, addressPair: HdlcAddressPair, segframexh: number, segframetype: number) { this.frameType = frameType; this.informationField = informationField; this.segmented = segmented; this.controlField = controlField; this.addressPair = addressPair; this.segframexh = segframexh; this.segframetype = segframetype; } static newCliReqFrame(addressPair: HdlcAddressPair, information: Buffer, segmented: boolean): HdlcFrame { let hdlcFrame = new HdlcFrame(); hdlcFrame.set_addpair_frametype(addressPair, FrameType.CLI_REQ.value); hdlcFrame.informationField = information; hdlcFrame.segmented = segmented; hdlcFrame.controlField = CmdType.CMD_USERDATA.value; return hdlcFrame; } decode(input : ReverseByteArrayInputStream) : HdlcFrame{ let fcsCalc = new FcsCalc(); let segframexh = 0; let segframetype = 0; let codePosition = 0; let frameFormatH = input.read(); if ((frameFormatH & 0xFF) != this.FLAGBEG) { throw new Error("Illegal frameformat"); } let lenframe = (input.read() & 0xff); lenframe += (input.read() << 8) & 0xff00; let code = Buffer.alloc(lenframe); code.writeUInt8(lenframe, 0); code.writeUInt8((lenframe & 0xff00) >> 8, 1); let controlField = input.read(); code.writeUInt8(controlField & 0xff, 2); codePosition += 3; fcsCalc.update(code, codePosition); // 获取控制码、帧 let cmdType = cmdTypeFor(controlField & 0xFF); let frameType = frameTypeFor(controlField & 0xFF); let segmented = (0x20 & controlField) == 0x20; // 地址 let srvaddr = HdlcFrame.decodeAddress(fcsCalc, input); console.log(srvaddr); let cliaddr = input.read(); console.log(cliaddr); fcsCalc.updates(cliaddr); let tempbyte = input.read(); console.log(tempbyte); fcsCalc.updates(tempbyte); tempbyte = input.read(); console.log(tempbyte); fcsCalc.updates(tempbyte); fcsCalc.validateCurrentFcsValue(); // let informationField : Buffer; let infoLength = lenframe - 8 - srvaddr.byteLength; console.log(infoLength); if (infoLength > 0) { if (segmented) { infoLength = infoLength - 2; let frameinfo = input.read(); segframexh = frameinfo & 0x3FFF; segframetype = (frameinfo >> 14) & 0x03; let codetemp = Buffer.alloc(1000); codetemp.writeUInt8((frameinfo)); fcsCalc.update(codetemp, 1); } informationField = Buffer.alloc(infoLength); for (let i = 0; i < infoLength; i++) { let data = input.read(); console.log("informationField " + data); fcsCalc.updates(data); informationField[i] = data; } tempbyte = input.read(); console.log(tempbyte); fcsCalc.updates(tempbyte); tempbyte = input.read(); console.log(tempbyte); fcsCalc.updates(tempbyte); fcsCalc.validateCurrentFcsValue(); } else { informationField = Buffer.alloc(0); tempbyte = input.read(); fcsCalc.updates(tempbyte); tempbyte = input.read(); fcsCalc.updates(tempbyte); fcsCalc.validateCurrentFcsValue(); } tempbyte = input.read(); console.log(tempbyte); let addressPair = new HdlcAddressPair(srvaddr, DataUtils.hexToBytes(cliaddr.toString(16))); let hdlcFrame = new HdlcFrame(); hdlcFrame.set_all_param(frameType, informationField, segmented, cmdType, addressPair, segframexh, segframetype); return hdlcFrame; } static decodeAddress(fcsCalc : FcsCalc, input : ReverseByteArrayInputStream) : HdlcAddress{ let data; let currentByte = input.read(); let length = (currentByte & 0x0f) + 1; data = Buffer.alloc(length + 1); fcsCalc.updates(currentByte); data[0] = currentByte; let i = 0; while (i < length) { currentByte = input.read(); fcsCalc.updates(currentByte); data[++i] = currentByte; } return HdlcAddress.decode(data); } encode(): Buffer { let data = this.encodeWithoutFlags(); let temp = Buffer.alloc(data.length + 2); temp.writeUInt8(this.FLAGBEG, 0); data.copy(temp, 1, 0, data.length); temp.writeUInt8(this.FLAGEND, data.length + 1); return temp; } encodeWithoutFlags(): Buffer { if(this.informationField != null){ let length = 8 + this.getSrvAddress().getByteLength();//9 if (this.containsInformation()) { length += this.informationField.length; } if (this.isSegmented()) { length += 2; } console.log(length); let codePosition = 0; let code = Buffer.alloc(length); code.writeUInt8(length & 0x00ff, 0); code.writeUInt8((length & 0xff00) >> 8, 1); code.writeUInt8((this.controlField & 0x03) | this.frameType | (this.isSegmented() ? 0x20 : 0x0), 2); codePosition += 3; let srvEncode = this.getSrvAddress().encode(); for (let i = 0; i < srvEncode.length; i++) { code.writeUInt8(srvEncode[i], i + codePosition); } codePosition += srvEncode.length; let cliEncode = this.getCliAddress(); for (let i = 0; i < cliEncode.length; i++) { code.writeUInt8(cliEncode[i], i + codePosition); } codePosition += cliEncode.length; let fcsCalc = new FcsCalc(); fcsCalc.update(code, codePosition); let hcsEncode = fcsCalc.fcsValueInBytes(); for (let i = 0; i < hcsEncode.length; i++) { code.writeUInt8(hcsEncode[i], i + codePosition); } codePosition += hcsEncode.length; fcsCalc.update(fcsCalc.fcsValueInBytes(), fcsCalc.fcsValueInBytes().length); console.log("hcs is update"); if (this.isSegmented()) { let segframeinfo = (this.segframexh & 0x3FFFF) | ((this.segframetype & 0x03) << 14); code.writeUInt8(segframeinfo & 0x00ff, codePosition + 1); code.writeUInt8((segframeinfo & 0xff00) >> 8, codePosition + 2); codePosition += 2; let segbyte = Buffer.alloc(2); code.copy(segbyte, 0, codePosition, codePosition + 2); fcsCalc.update(segbyte, 2); } if (this.containsInformation()) { for (let i = 0; i < this.informationField.length; i++) { code.writeUInt8(this.informationField[i], i + codePosition); } codePosition += this.informationField.length; fcsCalc.update(this.informationField, this.informationField.length); } let fcs = fcsCalc.fcsValueInBytes(); for (let i = 0; i < fcs.length; i++) { code.writeUInt8(fcs[i], i + codePosition); } return code; }else{ throw new Error("apdu data is null"); } } getSrvAddress(): HdlcAddress { if (this.addressPair != null) { return this.addressPair.getSrvAddr(); } else { throw new Error("addressPair is null"); } } getCliAddress(): Buffer { if (this.addressPair != null) { return this.addressPair.getCliAddr(); } else { throw new Error("addressPair is null"); } } getAddressPair(): HdlcAddressPair { if (this.addressPair != null) { return this.addressPair; } else { throw new Error("addressPair is null"); } } getFrameType(): number { return this.frameType; } getInformationField(): Buffer { if (this.informationField != null) { return this.informationField; } else { throw new Error("apdu data is null"); } } isSegmented(): boolean { return this.segmented; } containsInformation(): boolean { return this.informationField != null; } setSegFrameType(segframetype2: number) { this.segframetype = segframetype2; } setSegFrameXh(segframexh2: number) { this.segframexh = segframexh2; } getSegFrameType(): number { return this.segframetype; } getSegFrameXh(): number { return this.segframexh; } }