示例#1
0
        //  Write %IW1530
        public static void TestWriteLoop()
        {
            IPEndPoint       ep      = new IPEndPoint(IPAddress.Parse("172.20.54.58"), 0xAF12);
            EnIPRemoteDevice WagoPlc = new EnIPRemoteDevice(ep);

            // class 166, instance 1, attribut 1
            EnIPClass    Class166        = new EnIPClass(WagoPlc, 166);
            EnIPInstance Instance1       = new EnIPInstance(Class166, 1);
            EnIPAttribut FirstMemoryByte = new EnIPAttribut(Instance1, 1);

            // Connect made & retry automatically
            WagoPlc.autoConnect         = true;
            WagoPlc.autoRegisterSession = true;

            ushort i = 0;

            for (; ;)
            {
                FirstMemoryByte.RawData = BitConverter.GetBytes(i++);
                if (FirstMemoryByte.WriteDataToNetwork() == EnIPNetworkStatus.OnLine)
                {
                    Console.WriteLine("OK");
                }

                Thread.Sleep(200);
            }
        }
示例#2
0
        private EnIPRemoteDevice getDevice()
        {
            EnIPRemoteDevice remotedevice;
            IPAddress        ip;

            if (cb_device.SelectedIndex == -1)
            {
                try
                {
                    ip = IPAddress.Parse(cb_device.Text);
                }
                catch
                {
                    // no valid ip:
                    cb_device.Text = "192.168.1.1";
                    ip             = IPAddress.Parse(cb_device.Text);
                }
                foreach (EnIPRemoteDevice rd in _selfCreatedRemoteDevicesOverIp) // connection to the adapter already opended somewhere here?
                {
                    if (rd.IPAdd().Equals(ip))
                    {
                        return(rd);
                    }
                }
                remotedevice = new EnIPRemoteDevice(new System.Net.IPEndPoint(ip, 0xAF12), Properties.Settings.Default.TCP_LAN_Timeout); // create new one
                _selfCreatedRemoteDevicesOverIp.Add(remotedevice);
            }
            else
            {
                remotedevice = ((ComboboxItem)cb_device.SelectedItem).RemoteDevice;
            }
            return(remotedevice);
        }
示例#3
0
        //  Read the first analog value on a Wago PLC 750-8xx
        public static void TestReadLoop()
        {
            IPEndPoint       ep      = new IPEndPoint(IPAddress.Parse("172.20.54.58"), 0xAF12);
            EnIPRemoteDevice WagoPlc = new EnIPRemoteDevice(ep);

            // class 103, instance 1, attribut 1
            // could be class 4, Instance 104 (with status) or 107 (wihout), attribut 3 for all Input data
            EnIPClass    Class103         = new EnIPClass(WagoPlc, 103);
            EnIPInstance Instance1        = new EnIPInstance(Class103, 1);
            EnIPAttribut FirstAnalogInput = new EnIPAttribut(Instance1, 1);

            WagoPlc.autoConnect         = false;
            WagoPlc.autoRegisterSession = true;

            for (; ;)
            {
                // Connect or try re-connect, could be made with a long delay
                if (!WagoPlc.IsConnected())
                {
                    WagoPlc.Connect();
                }
                if (!WagoPlc.IsConnected())
                {
                    return;
                }

                // all data will be put in the byte[] RawData member of EnIPInstanceAttribut
                if (FirstAnalogInput.ReadDataFromNetwork() == EnIPNetworkStatus.OnLine)
                {
                    Console.WriteLine((FirstAnalogInput.RawData[1] << 8) | FirstAnalogInput.RawData[0]);
                }

                Thread.Sleep(200);
            }
        }
        public ImplicitMessaging(TreeView devicetreeView)
        {
            InitializeComponent();

            ClassView.ImageList = devicetreeView.ImageList;

            TreeNode baseNode = devicetreeView.SelectedNode;

            while (baseNode.Parent != null)
            {
                baseNode = baseNode.Parent;
            }

            device = (EnIPRemoteDevice)baseNode.Tag;

            foreach (TreeNode t in baseNode.Nodes)
            {
                ClassView.Nodes.Add((TreeNode)t.Clone());
            }

            ClassView.ExpandAll();

            ClassView.ItemDrag += new ItemDragEventHandler(ClassView_ItemDrag);

            this.Text = "Implicit Messaging with " + baseNode.Text;

            try
            {
                IPEndPoint LocalEp = new IPEndPoint(IPAddress.Parse(Properties.Settings.Default.DefaultIPInterface), 0x8AE);
                // It's not a problem to do this with more than one remote device,
                // the underlying udp socket is static
                device.Class1Activate(LocalEp);
            }
            catch { }
        }
示例#5
0
        static void client_DeviceArrival(EnIPRemoteDevice device)
        {
            Console.WriteLine("Arrvial of : " + device.IPAdd().ToString() + " - " + device.ProductName);
            // Query the object list : Assembly object, instance 1, atribut 1
            Console.WriteLine("Classes inside :");
            device.GetObjectList();
            foreach (EnIPClass cl in device.SupportedClassLists)
            {
                Console.WriteLine("\t" + ((CIPObjectLibrary)cl.Id).ToString());
            }

            // Close pending connection
            device.Dispose();
        }
示例#6
0
        // Menu Item
        private TreeNode AddRemoteDevice(EnIPRemoteDevice remotedevice)
        {
            foreach (TreeNode tn in devicesTreeView.Nodes)
            {
                if ((tn.Tag as EnIPRemoteDevice).Equals(remotedevice))
                {
                    return(tn);
                }
            }

            TreeNode tn2 = new TreeNode(remotedevice.IPAdd().ToString() + " - " + remotedevice.ProductName, 1, 1);

            tn2.Tag = remotedevice;
            devicesTreeView.Nodes.Add(tn2);

            return(tn2);
        }
示例#7
0
        //  Read 4.104.3 on an Eurotherm Epack
        public static void TestReadLoop()
        {
            IPEndPoint       ep    = new IPEndPoint(IPAddress.Parse("172.20.54.119"), 0xAF12);
            EnIPRemoteDevice EPack = new EnIPRemoteDevice(ep);

            // class 4, Instance 100, attribut 3 for all Input data
            EnIPClass Class4 = new EnIPClass(EPack, 4);
            // here we gives the decoder class (subclass of CIPObject) in the 3rd parameter
            EnIPInstance Instance100 = new EnIPInstance(Class4, 100, typeof(InstanceDecoder));
            EnIPAttribut AllInputs   = new EnIPAttribut(Instance100, 3);

            EPack.autoConnect         = false;
            EPack.autoRegisterSession = true;

            for (; ;)
            {
                // Connect or try re-connect, could be made with a long delay
                if (!EPack.IsConnected())
                {
                    EPack.Connect();
                }
                if (!EPack.IsConnected())
                {
                    return;
                }

                // all data will be put in the byte[] RawData member of EnIPInstanceAttribut
                // ... but decoded in the DecoderMemeber
                if (AllInputs.ReadDataFromNetwork() == EnIPNetworkStatus.OnLine)
                {
                    // rawdata basic technic
                    // Console.WriteLine((AllInputs.RawData[1] << 8) | AllInputs.RawData[0]);
                    InstanceDecoder decoded = (InstanceDecoder)AllInputs.DecodedMembers;
                    Console.WriteLine(decoded.AnalogInput);
                    Console.WriteLine(decoded.Frequency / 10.0);
                    // and so on
                }

                Thread.Sleep(200);

                // If a Forward Open is done such as in Class1Sample application sample,
                // the decoder is always called : a first ReadDataFromNetwork is mandatory
                // before that.
            }
        }
示例#8
0
        static void Main(string[] args)
        {
            Console.WriteLine("Starting");

            IPEndPoint       ep      = new IPEndPoint(IPAddress.Parse("172.20.54.58"), 0xAF12);
            EnIPRemoteDevice WagoPlc = new EnIPRemoteDevice(ep);

            WagoPlc.autoConnect         = true;
            WagoPlc.autoRegisterSession = true;

            // class 4, instance 107, attribut 3 : Input Data
            EnIPClass    Class4      = new EnIPClass(WagoPlc, 4);
            EnIPInstance Instance107 = new EnIPInstance(Class4, 107);
            EnIPAttribut Inputs      = new EnIPAttribut(Instance107, 3);

            // Read require, it provides the data size in the RawData field
            // If not, one have to make a new on it with the good size before
            // calling ForwardOpen : Inputs.RawData=new byte[xx]
            Inputs.ReadDataFromNetwork();

            // Open an Udp endpoint, server mode is mandatory : default port 0x8AE
            // Local IP should be given if more than 1 ethernet/wifi interface is present
            IPEndPoint LocalEp = new IPEndPoint(IPAddress.Parse(""), 0x8AE);

            // It's not a problem to do this with more than one remote device,
            // the underlying udp socket is static
            WagoPlc.Class1Activate(LocalEp);
            // Not required in P2P mode
            WagoPlc.Class1AddMulticast("239.192.72.32");

            // Attach concerned attributs to the UDP callback handler : here just one
            Inputs.Class1Enrolment();

            // Register me to get notified
            Inputs.T2OEvent += new T2OEventHandler(Inputs_T2OEvent);

            // ForwardOpen in Multicast, T2O, cycle 200 ms, duration infinite (-1)
            Inputs.ForwardOpen(false, true, false, 200, -1);

            Console.WriteLine("Running, hit a key to stop");

            Console.ReadKey();

            Inputs.ForwardClose();
        }
示例#9
0
        // Menu Item
        // Delete a Device, a class, an instance, an attribut
        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TreeNode tn = devicesTreeView.SelectedNode;

            if (tn == null)
            {
                return;
            }

            DialogResult deleteOK = DialogResult.OK;

            if (tn.Tag is EnIPRemoteDevice)
            {
                // confirm
                if (Properties.Settings.Default.ConfirmDeleteDevice)
                {
                    deleteOK = MessageBox.Show("Delete this device", tn.Text, MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
                }

                if (deleteOK == DialogResult.OK)
                {
                    EnIPRemoteDevice device = (tn.Tag as EnIPRemoteDevice);

                    device.Disconnect();                    // close the tcp connection
                    devicesTreeView.Nodes.Remove(tn);       // remove from the tree
                }
            }
            else
            {
                // confirm
                if (Properties.Settings.Default.ConfirmDeleteOthers)
                {
                    deleteOK = MessageBox.Show("Delete", tn.Text, MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
                }
                if (deleteOK == DialogResult.OK)
                {
                    devicesTreeView.Nodes.Remove(tn);   // only remove from the list
                }
            }
        }
示例#10
0
        // Each time we received a response to udp broadcast or udp/tcp unicast ListIdentity
        void On_DeviceArrival(EnIPRemoteDevice device)
        {
            if (InvokeRequired)
            {
                Invoke(new DeviceArrivalHandler(On_DeviceArrival), new object[] { device });
                return;
            }

            // Device already present ?
            foreach (TreeNode tn in devicesTreeView.Nodes)
            {
                EnIPRemoteDevice oldRemoteDevice = (EnIPRemoteDevice)tn.Tag;
                if (oldRemoteDevice.Equals(device))
                {
                    oldRemoteDevice.CopyData(device);
                    // change the icon if needed
                    if (tn.SelectedImageIndex != 0)
                    {
                        tn.ImageIndex = tn.SelectedImageIndex = 0;
                    }
                    // change the Text maybe
                    tn.Text = device.IPAdd().ToString() + " - " + device.ProductName;

                    if (devicesTreeView.SelectedNode == tn)
                    {
                        devicesTreeView.SelectedNode = null;
                    }

                    return;
                }
            }

            TreeNode tn2 = new TreeNode(device.IPAdd().ToString() + " - " + device.ProductName, 0, 0);

            tn2.Tag = device;
            devicesTreeView.Nodes.Add(tn2);

            // Queue connection
            ThreadPool.QueueUserWorkItem((o) => device.Connect());
        }
示例#11
0
        // Menu Item
        private void saveConfigurationAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                SaveFileDialog dlg = new SaveFileDialog();
                dlg.FileName = Properties.Settings.Default.DefaultTreeFile;
                dlg.Filter   = "csv|*.csv";
                if (dlg.ShowDialog(this) != System.Windows.Forms.DialogResult.OK)
                {
                    return;
                }

                string filename = dlg.FileName;
                Properties.Settings.Default.DefaultTreeFile = filename;

                StreamWriter sw = new StreamWriter(filename);

                char s = Properties.Settings.Default.CSVSeparator;

                sw.WriteLine("Device IP" + s + "Name" + s + "Class" + s + "ClassName" + s + "Instance" + s + "InstanceName" + s + "Attribute" + s + "AttributeName");
                sw.WriteLine("// EnIPExplorer Device Tree, can be modified with a spreadsheet");

                foreach (TreeNode tn in devicesTreeView.Nodes)
                {
                    EnIPRemoteDevice remote = (EnIPRemoteDevice)tn.Tag;
                    sw.WriteLine(remote.IPAdd().ToString() + s + remote.ProductName);
                    SaveFileEnIPOject(sw, s.ToString() + s.ToString(), tn.Nodes);
                }

                sw.Close();
                MessageBox.Show("Done", "File Save", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch
            {
                MessageBox.Show("File Error", "EnIPExplorer", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
示例#12
0
        // Menu Item
        // Add a new device not discovery using the broadcast technic : outside the local net
        private void addRemoteDeviceToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (client == null)
            {
                return;
            }

            var Input =
                new GenericInputBoxExtended <TextBox>("Remote device", "IP address",
                                                      (o) =>
            {
                o.Text = Properties.Settings.Default.DefaultRemoteDevice;
            });

            DialogResult res = Input.ShowDialog();

            if (res != DialogResult.OK)
            {
                return;
            }

            try
            {
                EnIPRemoteDevice remotedevice = new EnIPRemoteDevice(new System.Net.IPEndPoint(IPAddress.Parse(Input.genericInput.Text), 0xAF12), Properties.Settings.Default.TCP_WAN_TimeOut);
                remotedevice.ProductName = "EnIPExplorer temporary ProductName";
                AddRemoteDevice(remotedevice);

                remotedevice.DeviceArrival += new DeviceArrivalHandler(On_DeviceArrival);
                remotedevice.DiscoverServer();

                Properties.Settings.Default.DefaultRemoteDevice = Input.genericInput.Text;
            }
            catch
            {
                Trace.WriteLine("Error with IP : " + Input.genericInput.Text);
            }
        }
示例#13
0
        private void devicesTreeView_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (client == null)
            {
                return;
            }

            EnIPNetworkStatus ReadRet = EnIPNetworkStatus.OnLine;

            Cursor Memcurs = this.Cursor;

            this.Cursor = Cursors.WaitCursor;

            // It's a Device : top level
            if (e.Node.Tag is EnIPRemoteDevice)
            {
                EnIPRemoteDevice device = (EnIPRemoteDevice)e.Node.Tag;

                propertyGrid.SelectedObject = device;

                popupAddCToolStripMenuItem.Visible        = true;
                popupAddIToolStripMenuItem.Visible        = false;
                popupAddAToolStripMenuItem.Visible        = false;
                decodeAttributAsToolStripMenuItem.Visible = false;

                popupDeleteToolStripMenuItem.Text = deleteToolStripMenuItem.Text = "Delete current Device";

                if (device.SupportedClassLists.Count == 0) // certainly never discovers
                {
                    if (device.IsConnected() == false)
                    {
                        device.Connect();
                        if (device.IsConnected() == false)
                        {
                            propertyGrid.Enabled = false;
                            CurrentRemoteDeviceIcon(EnIPNetworkStatus.OffLine);
                            this.Cursor = Memcurs;
                            return;
                        }
                    }

                    // never discovers
                    if (device.DataLength == 0)
                    {
                        device.DiscoverServer();
                    }

                    device.GetObjectList();
                    propertyGrid.Enabled = true;
                }

                // change the Text maybe
                String txt = device.IPAdd().ToString() + " - " + device.ProductName;
                if (e.Node.Text != txt)
                {
                    e.Node.Text = txt;
                }

                foreach (EnIPClass clId in device.SupportedClassLists)
                {
                    bool alreadyexist = false;
                    foreach (TreeNode tn in e.Node.Nodes)
                    {
                        if ((tn.Tag as EnIPClass).Id == clId.Id)
                        {
                            alreadyexist = true;
                            break;
                        }
                    }

                    if (!alreadyexist)
                    {
                        e.Node.Nodes.Add(ClassToTreeNode(clId));
                    }
                }
                e.Node.Expand();
            }

            // It's a Class
            else if (e.Node.Tag is EnIPClass)
            {
                // Read it from the remote devie
                EnIPClass EnClass = (EnIPClass)e.Node.Tag;
                ReadRet = EnClass.ReadDataFromNetwork();
                LastReadNetworkStatus = EnIPNetworkStatus.OffLine; // to avoid periodic reading
                // In the Grid
                propertyGrid.SelectedObject = EnClass;
                propertyGrid.ExpandAllGridItems();
                // Popup menu adaptation
                popupAddCToolStripMenuItem.Visible        = true;
                popupAddIToolStripMenuItem.Visible        = true;
                popupAddAToolStripMenuItem.Visible        = false;
                decodeAttributAsToolStripMenuItem.Visible = false;
                popupDeleteToolStripMenuItem.Text         = deleteToolStripMenuItem.Text = "Delete current Class";
            }
            // It's an Instance
            else if (e.Node.Tag is EnIPInstance)
            {
                // Read it from the remote devie
                EnIPInstance Instance = (EnIPInstance)e.Node.Tag;

                LastReadNetworkStatus = ReadRet = Instance.ReadDataFromNetwork();

                // remove properties litse filter based on CIPAttribut
                // in order to show all atrbiuts in the property grid
                if (Instance.DecodedMembers != null)
                {
                    Instance.DecodedMembers.FilterAttribut(-1);
                }

                LastReadNetworkStatus = ReadRet = Instance.ReadDataFromNetwork();
                // In the Grid
                propertyGrid.SelectedObject = Instance;
                propertyGrid.ExpandAllGridItems();
                // Popup menu adaptation
                popupAddCToolStripMenuItem.Visible        = true;
                popupAddIToolStripMenuItem.Visible        = true;
                popupAddAToolStripMenuItem.Visible        = true;
                decodeAttributAsToolStripMenuItem.Visible = false;
                popupDeleteToolStripMenuItem.Text         = deleteToolStripMenuItem.Text = "Delete current Instance";
            }
            // It's an Attribut
            else if (e.Node.Tag is EnIPAttribut)
            {
                // Read it from the remote devie
                EnIPAttribut Att = (EnIPAttribut)e.Node.Tag;

                LastReadNetworkStatus = ReadRet = Att.ReadDataFromNetwork();

                // filter properties list for only the given attribut
                // remove instance undecoded bytes if exist
                if (Att.DecodedMembers != null)
                {
                    Att.DecodedMembers.FilterAttribut(Att.Id);
                    Att.DecodedMembers.Remain_Undecoded_Bytes = null;
                }

                // In the Grid
                propertyGrid.SelectedObject = Att;
                propertyGrid.ExpandAllGridItems();
                // Popup menu adaptation
                popupAddCToolStripMenuItem.Visible        = true;
                popupAddIToolStripMenuItem.Visible        = true;
                popupAddAToolStripMenuItem.Visible        = true;
                decodeAttributAsToolStripMenuItem.Visible = true;
                popupDeleteToolStripMenuItem.Text         = deleteToolStripMenuItem.Text = "Delete current Attribute";
            }

            propertyGrid.Enabled = (ReadRet == EnIPNetworkStatus.OnLine);
            CurrentRemoteDeviceIcon(ReadRet);
            this.Cursor = Memcurs;
        }
示例#14
0
        // Usage by Load file menu
        private void AddNodesFromFile(StreamReader sr, ref int line)
        {
            TreeNode         ParentDeviceTreeNode = null, ParentClassTreeNode = null, ParentInstanceTreeNode = null;
            EnIPRemoteDevice remotedevice = null; EnIPClass Class = null; EnIPInstance Instance = null;

            while (!sr.EndOfStream)
            {
                try
                {
                    String str = sr.ReadLine(); line++;
                    if ((str != null) && (str[0] != '/'))
                    {
                        String[] Strs   = str.Split(Properties.Settings.Default.CSVSeparator);
                        int      Length = Strs.Length;
                        while (Length != 1)
                        {
                            if (Strs[Length - 1] == "")
                            {
                                Length--;
                            }
                            else
                            {
                                break;
                            }
                        }

                        switch (Length)
                        {
                        case 2:     // A device, assume LAN timeout and not WAN
                            remotedevice             = new EnIPRemoteDevice(new System.Net.IPEndPoint(IPAddress.Parse(Strs[0]), 0xAF12), Properties.Settings.Default.TCP_LAN_Timeout);
                            remotedevice.ProductName = Strs[1];
                            ParentDeviceTreeNode     = AddRemoteDevice(remotedevice);
                            break;

                        case 4:     // A class
                            Class = new EnIPClass(remotedevice, Convert.ToUInt16(Strs[2]));
                            int ico;
                            if (Enum.IsDefined(typeof(CIPObjectLibrary), Class.Id))
                            {
                                ico = Classe2Ico((CIPObjectLibrary)Class.Id);
                            }
                            else
                            {
                                ico = 2;
                            }
                            ParentClassTreeNode             = AddeNode(ParentDeviceTreeNode, Class, Strs[3], ico);
                            ParentClassTreeNode.ToolTipText = "Node " + IdStr(Class.Id);
                            break;

                        case 6:     // An instance
                            Instance = new EnIPInstance(Class, Convert.ToByte(Strs[4]));
                            ParentInstanceTreeNode             = AddeNode(ParentClassTreeNode, Instance, Strs[5], 9);
                            ParentInstanceTreeNode.ToolTipText = ParentClassTreeNode.ToolTipText + "." + IdStr(Instance.Id);
                            break;

                        case 8:     // An attribut
                            EnIPAttribut Attribut = new EnIPAttribut(Instance, Convert.ToByte(Strs[6]));
                            TreeNode     tnAtt    = AddeNode(ParentInstanceTreeNode, Attribut, Strs[7], 10);
                            tnAtt.ToolTipText = ParentInstanceTreeNode.ToolTipText + "." + IdStr(Attribut.Id);
                            break;

                        default:
                            throw new Exception("Not the good number of colums");
                        }
                    }
                }
                catch { throw new Exception("Line content error"); }
            }
        }
示例#15
0
 public ComboboxItem(EnIPRemoteDevice rd)
 {
     RemoteDevice = rd;
     Text         = rd.IPAdd().ToString() + " - " + rd.ProductName;
 }
示例#16
0
        static void Main(string[] args)
        {
            Console.WriteLine("Starting");

            IPEndPoint       ep     = new IPEndPoint(IPAddress.Parse("100.75.137.27"), 0xAF12);
            EnIPRemoteDevice OpENer = new EnIPRemoteDevice(ep);

            OpENer.autoConnect         = true;
            OpENer.autoRegisterSession = true;

            // class 4, instance 151, attribut 3 : Config Data
            EnIPClass    Class4      = new EnIPClass(OpENer, 4);
            EnIPInstance Instance151 = new EnIPInstance(Class4, 151);
            EnIPAttribut Config      = new EnIPAttribut(Instance151, 3);

            // class 4, instance 150, attribut 3 : Output Data
            EnIPInstance Instance150 = new EnIPInstance(Class4, 150);
            EnIPAttribut Outputs     = new EnIPAttribut(Instance150, 3);

            // class 4, instance 100, attribut 3 : Input Data
            EnIPInstance Instance100 = new EnIPInstance(Class4, 100);
            EnIPAttribut Inputs      = new EnIPAttribut(Instance100, 3);

            // Read require, it provides the data size in the RawData field
            // If not, one have to make a new on it with the good size before
            // calling ForwardOpen : Inputs.RawData=new byte[xx]
            Config.ReadDataFromNetwork();
            Inputs.ReadDataFromNetwork();
            Outputs.ReadDataFromNetwork();

            IPEndPoint LocalEp = new IPEndPoint(IPAddress.Any, 0x8AE);

            // It's not a problem to do this with more than one remote device,
            // the underlying udp socket is static
            OpENer.Class1Activate(LocalEp);

            // ForwardOpen in P2P, cycle 200 ms
            ForwardOpen_Config conf = new ForwardOpen_Config(Outputs, Inputs, true, 200 * 1000);
            // here can change conf for exemple to set Exclusive use, change priority or CycleTime not equal in the both direction

            // Attributes order cannot be changed, last optional attribute true
            // will write the config value Config.RawData (modifies it after ReadDataFromNetwork before this call)
            ForwardClose_Packet CloseData;
            EnIPNetworkStatus   result = OpENer.ForwardOpen(Config, Outputs, Inputs, out CloseData, conf, false);

            if (result == EnIPNetworkStatus.OnLine)
            {
                // Register Inputs events to get notified
                Inputs.T2OEvent += new T2OEventHandler(Inputs_T2OEvent);

                Console.WriteLine("Running, hit a key to stop");
                while (!Console.KeyAvailable)
                {
                    Outputs.RawData[0] = (byte)(Outputs.RawData[0] + 1);
                    Outputs.Class1UpdateO2T(); // must be called even if no data changed to maintain the link (Heartbeat)
                    Thread.Sleep(200);
                }
                OpENer.ForwardClose(CloseData);
            }
            else
            {
                Console.WriteLine("Fail");
            }
        }