public EnIPNetworkStatus ForwardOpen(EnIPAttribut Config, EnIPAttribut O2T, EnIPAttribut T2O, out ForwardClose_Packet ClosePacket, ForwardOpen_Config conf, bool WriteConfig = false) { ClosePacket = null; byte[] DataPath = GetForwardOpenPath(Config, O2T, T2O); if ((WriteConfig == true) && (Config != null)) // Add data segment { DataPath = EnIPPath.AddDataSegment(DataPath, Config.RawData); /* * byte[] FinaleFrame = new byte[DataPath.Length + 2 + Config.RawData.Length]; * Array.Copy(DataPath, FinaleFrame, DataPath.Length); * FinaleFrame[DataPath.Length] = 0x80; * FinaleFrame[DataPath.Length + 1] = (byte)(Config.RawData.Length / 2); // Certainly the lenght is always even !!! * Array.Copy(Config.RawData, 0, FinaleFrame, DataPath.Length + 2, Config.RawData.Length); * DataPath = FinaleFrame; */ } ForwardOpen_Packet FwPkt = new ForwardOpen_Packet(DataPath, conf); int Offset = 0; int Lenght = 0; byte[] packet; EnIPNetworkStatus Status; if (FwPkt.IsLargeForwardOpen) { Status = SendUCMM_RR_Packet(EnIPPath.GetPath(6, 1), CIPServiceCodes.LargeForwardOpen, FwPkt.toByteArray(), ref Offset, ref Lenght, out packet); } else { Status = SendUCMM_RR_Packet(EnIPPath.GetPath(6, 1), CIPServiceCodes.ForwardOpen, FwPkt.toByteArray(), ref Offset, ref Lenght, out packet); } if (Status == EnIPNetworkStatus.OnLine) { if (O2T != null) { O2T.O2T_ConnectionId = BitConverter.ToUInt32(packet, Offset); // badly made O2T.SequenceItem = new SequencedAddressItem(O2T.O2T_ConnectionId, 0, O2T.RawData); // ready to send } if (T2O != null) { T2O.Class1Enrolment(); T2O.T2O_ConnectionId = BitConverter.ToUInt32(packet, Offset + 4); } ClosePacket = new ForwardClose_Packet(FwPkt, T2O); } return(Status); }
// Only use for request up to now // O2T & T2O could be use at the same time // using a Connection_Path with more than 1 reference // 1 Path : path is for Consumption & Production // 2 Path : First path is for Consumption, second path is for Production. public ForwardOpen_Packet(byte[] Connection_Path, ForwardOpen_Config conf, uint?ConnectionId = null) { ConnectionSerialNumber = GlobalConnectionSerialNumber++; if ((conf.O2T_datasize > 511 - 2) || (conf.T2O_datasize > 511 - 6)) { IsLargeForwardOpen = true; } this.Connection_Path = Connection_Path; if (ConnectionId == null) { // volume 2 : 3-3.7.1.3 Pseudo-Random Connection ID Per Connection _ConnectionId += 2; _ConnectionId = _ConnectionId | (uint)(new Random().Next(65535) << 16); } else { _ConnectionId = ConnectionId.Value; } if (conf.IsO2T) { O2T_ConnectionId = _ConnectionId; } if (conf.IsT2O) { T2O_ConnectionId = _ConnectionId + 1; } /* * // Volume 1: chapter 3-5.5.1.1 * T->O Network Connection Parameters: 0x463b * 0... .... .... .... = Owner: Exclusive (0) * .10. .... .... .... = Connection Type: Point to Point (2) * .... 01.. .... .... = Priority: High Priority (1) * .... ..1. .... .... = Connection Size Type: Variable (1) * .... ...0 0011 1011 = Connection Size: 59 */ if (conf.IsT2O) { T2O_ConnectionParameters = 0x0000; // Fixed Datasize, Variable data size is 0x0200 T2O_ConnectionParameters = (uint)(T2O_ConnectionParameters + (conf.T2O_Priority & 0x03) << 10); if (conf.T2O_P2P) { T2O_ConnectionParameters = T2O_ConnectionParameters | 0x4000; } else { T2O_ConnectionParameters = T2O_ConnectionParameters | 0x2000; } if (conf.O2T_Exculsive) { T2O_ConnectionParameters = T2O_ConnectionParameters | 0x8000; } if (IsLargeForwardOpen) { T2O_ConnectionParameters = (T2O_ConnectionParameters << 16) + conf.T2O_datasize + 2; } else { T2O_ConnectionParameters += (ushort)(conf.T2O_datasize + 2); } T2O_RPI = conf.T2O_RPI; } if (conf.IsO2T) { O2T_ConnectionParameters = 0x0000; // Fixed Datasize, Variable data size is 0x0200 O2T_ConnectionParameters = (uint)(O2T_ConnectionParameters + (conf.O2T_Priority & 0x03) << 10); if (conf.O2T_P2P) { O2T_ConnectionParameters = O2T_ConnectionParameters | 0x4000; } else { O2T_ConnectionParameters = O2T_ConnectionParameters | 0x2000; } if (conf.O2T_Exculsive) { O2T_ConnectionParameters = O2T_ConnectionParameters | 0x8000; } // 2 bytes CIP class 1 sequence count + 4 bytes 32-bit real time header + datasize bytes application data if (conf.O2T_P2P) { O2T_ConnectionParameters = 0x4600; } else { O2T_ConnectionParameters = 0x2600; } if (IsLargeForwardOpen) { if (conf.O2T_datasize != 0) { O2T_ConnectionParameters = (O2T_ConnectionParameters << 16) + conf.O2T_datasize + 2 + 4; } else { O2T_ConnectionParameters = (O2T_ConnectionParameters << 16) + 2; } } else { if (conf.O2T_datasize != 0) { O2T_ConnectionParameters += (ushort)(conf.O2T_datasize + 2 + 4); } else { O2T_ConnectionParameters += (ushort)(2); } } O2T_RPI = conf.O2T_RPI; } }
public EnIPNetworkStatus ForwardOpen(EnIPAttribut Config, EnIPAttribut O2T, EnIPAttribut T2O, out ForwardClose_Packet ClosePacket, uint CycleTime, bool P2P = false, bool WriteConfig = false) { ForwardOpen_Config conf = new ForwardOpen_Config(O2T, T2O, P2P, CycleTime); return(ForwardOpen(Config, O2T, T2O, out ClosePacket, conf, WriteConfig)); }