using PlcSiemens.O; using PlcSiemens.Protocol.Common; using PlcSiemens.Protocol.Header; namespace PlcSiemens.Protocol.Iso { public class IsoControlPdu : IBuildRequest, IBuildResponse { public TpktHeader Tpkt { get; set; } // TPKT Header public CotpHeader Cotp { get; set; } // COPT Header for CONNECTION stuffs public int IsoPduSize { get; set; } public ushort SrcRef { get; set; } public ushort DstRef { get; set; } public ushort SrcTSap { get; set; } public ushort DstTSap { get; set; } /// /// 该报发送长度和接受长度都应该为22 /// public IsoControlPdu() { Tpkt = new TpktHeader(); Cotp = new CotpHeader(); } public void Build() { Cotp.Params.PduSizeCode = 0xC0; Cotp.Params.PduSizeLen = 0x01; switch (IsoPduSize) { case 128: Cotp.Params.PduSizeVal = 0x07; break; case 256: Cotp.Params.PduSizeVal = 0x08; break; case 512: Cotp.Params.PduSizeVal = 0x09; break; case 1024: Cotp.Params.PduSizeVal = 0x0A; break; case 2048: Cotp.Params.PduSizeVal = 0x0B; break; case 4096: Cotp.Params.PduSizeVal = 0x0C; break; case 8192: Cotp.Params.PduSizeVal = 0x0D; break; default: Cotp.Params.PduSizeVal = 0x0B; // Our Default break; } // Build TSAPs Cotp.Params.Tsap[0] = 0xC1; // code that identifies source TSAP Cotp.Params.Tsap[1] = 2; // source TSAP Len Cotp.Params.Tsap[2] = (byte)((SrcTSap >> 8) & 0xFF); // HI part Cotp.Params.Tsap[3] = (byte)(SrcTSap & 0xFF); // LO part Cotp.Params.Tsap[4] = 0xC2; // code that identifies dest TSAP Cotp.Params.Tsap[5] = 2; // dest TSAP Len Cotp.Params.Tsap[6] = (byte)((DstTSap >> 8) & 0xFF); // HI part Cotp.Params.Tsap[7] = (byte)(DstTSap & 0xFF); // LO part Cotp.Params.TsapLenth = 8; // Params length var parLen = 11; // 2 Src TSAP (Code+field Len) + // 2 Src TSAP len + // 2 Dst TSAP (Code+field Len) + // 2 Src TSAP len + // 3 PDU size (Code+field Len+Val) = 11 // Telegram length var isoLen = 4 + // TPKT Header 7 + // COTP Header Size without params parLen; // COTP params Tpkt.Version = StaticConst.IsoTcpVersion; Tpkt.Reserved = 0; Tpkt.Length = (ushort)isoLen; Cotp.Length = (byte)(parLen + 6); // <-- 6 = 7 - 1 (COTP Header size - 1) Cotp.PduType = (byte)PduType.ConnRequest; // Connection Request Cotp.DstRef = DstRef; // Destination reference Cotp.SrcRef = SrcRef; // Source reference Cotp.CoR = 0x00; // Class + Option : RFC0983 states that it must be always 0x40 // but for some equipment (S7) must be 0 in disaccord of specifications !!! } public void Build(byte[] resBytes) { ByteBuffer buffer = ByteBuffer.Allocate(); buffer.Push(resBytes); Tpkt.InitByBuffer(buffer); Cotp.InitByBuffer(buffer); } public ByteBuffer GetBuffer() { ByteBuffer buffer = ByteBuffer.Allocate(); Tpkt.GetByteBuffer(buffer); Cotp.GetByteBuffer(buffer); return buffer; } public void Build(ByteBuffer buffer) { Tpkt.InitByBuffer(buffer); Cotp.InitByBuffer(buffer); } } }