Page 1 of 1

Reading %W memory from GE RX3i with T7A

Posted: Mon Mar 10, 2014 4:09 pm
by AMitchneck
I have a script running on my T7A which reads/writes %W memory on a GE RX3i. I'm unable to use the built-in iX driver since it does not support %W memory access.

For some reason, my T7A is having difficultly maintaining a connection to the RX3i. It tends to hang up on the connect process. I noticed the built-in driver has no issue maintaining the connection. What does the driver use to check its connection status/timeouts? I have timeouts built into my script, but it still somehow hangs.

Is it possible for me to see how the iX driver processes the connection? Any help is appreciated.

This is a snippet of the script I'm using to connect to the RX3i, send data, and receive data:

Code: Select all

        public bool Connect()
        {
            int bytesRecv;
            byte[] dummy;
            ControlInfo ci;
            IPEndPoint Rx3iAddr;

            Close(); // make sure no previous connection exists
            sequenceNumber = 0;

            try { Rx3iAddr = new IPEndPoint(IPAddress.Parse(plc_host), plc_port); }
            catch (ArgumentNullException) { return false; }
            catch (ArgumentOutOfRangeException) { return false; }
            catch (FormatException) { return false; }

            try
            {
                sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                AsyncState asyncState = new AsyncState(sock);
                sock.BeginConnect(Rx3iAddr, ProcessConnect, asyncState);
                if (asyncState.WaitForReturn(20000))
                {
                    if (sock.Connected) goto Estab;
                }
            }
            catch (SocketException) { }
            catch (ObjectDisposedException) { }

            // connection failed, close socket
            try { if (sock != null) sock.Close(); }
            finally { sock = null; }
            return false;

        Estab:
            if (SendAll(_SRTPconnection) < 0)
                goto Exit;
            bytesRecv = ReceiveAll(out dummy, 56);
            if ((bytesRecv != 56) || (dummy[0] != 1))
                goto Exit;

            if (SendAll(_EstabSession) < 0)
                goto Exit;
            bytesRecv = ReceiveAll(out dummy, 56);
            if ((bytesRecv != 56) || (dummy[0] != 3))
                goto Exit;

            if (!GetControlInfo(out ci))
                goto Exit;

            cpuMajorType = ci.CPUMajorType;
            cpuMinorType = ci.CPUMinorType;
            return true;

        Exit:
            Close();
            return false;
        }
        private void ProcessConnect(IAsyncResult asyncResult)
        {
            AsyncState asyncState = (AsyncState)(asyncResult.AsyncState);
            try { asyncState.socket.EndConnect(asyncResult); }
            catch (SocketException) { }
            catch (ArgumentException) { }
            catch (InvalidOperationException) { }
            finally { asyncState.Set(); }
        }

        private int SendAll(byte[] buffer, int offset, int size)
        {
            int i, bytesSent;

            if (buffer == null) throw new ArgumentNullException("buffer");
            if ((offset < 0) || (offset >= buffer.Length)) throw new ArgumentOutOfRangeException("offset");
            if ((size < 0) || (size > (buffer.Length + offset))) throw new ArgumentOutOfRangeException("size");
            if (!this.Connected) return -1;

            size += offset;
            AsyncState asyncState = new AsyncState(sock);
            for (i = offset; i < size; i += bytesSent)
            {
                try
                {
                    if (sock.Poll(5000000, SelectMode.SelectWrite)) // use send timeout of 5 seconds
                    {
                        //bytesSent = sock.Send(buffer, i, size - i, SocketFlags.None);
                        asyncState.Reset();
                        sock.BeginSend(buffer, i, size - i, SocketFlags.None, ProcessSend, asyncState);
                        if (asyncState.WaitForReturn(10000)) // use send timeout of 10 seconds
                            bytesSent = asyncState.result;
                        else
                        {
                            Close(); // send timed out - close socket
                            bytesSent = 0;
                        }
                    }
                    else
                    {
                        Close(); // send timed out - close socket
                        bytesSent = 0;
                    }
                }
                catch (SocketException) { bytesSent = 0; }
                catch (ObjectDisposedException) { bytesSent = 0; }
                if (bytesSent == 0) break; // no data sent -> connection lost
            }

            if (i != size)
                return -1;
            else
                return (size - offset);
        }
        private void ProcessSend(IAsyncResult asyncResult)
        {
            AsyncState asyncState = (AsyncState)(asyncResult.AsyncState);
            try { asyncState.result = asyncState.socket.EndSend(asyncResult); }
            catch (SocketException) { asyncState.result = 0; }
            catch (ArgumentException) { asyncState.result = 0; }
            catch (InvalidOperationException) { asyncState.result = 0; }
            finally { asyncState.Set(); }
        }

        private int ReceiveAll(out byte[] buffer, int size)
        {
            int i, bytesRecv;

            if (size < 0)
            {
                buffer = null;
                return -1;
            }
            else
            {
                buffer = new byte[size];
                if (!this.Connected) return -1;
            }

            for (i = 0; i < size; i += bytesRecv)
            {
                try
                {
                    if (sock.Poll(5000000, SelectMode.SelectRead)) // use receive timeout of 5 seconds
                        bytesRecv = sock.Receive(buffer, i, size - i, SocketFlags.None);
                    else
                    {
                        Close(); // receive timed out - close socket
                        bytesRecv = 0;
                    }
                }
                catch (SocketException) { bytesRecv = 0; }
                catch (ObjectDisposedException) { bytesRecv = 0; }
                if (bytesRecv == 0) break; // no data received -> connection lost
            }

            if (i != size)
                return -1;
            else
                return size;
        }

        private class AsyncState
        {
            private Socket sock;
            private System.Threading.ManualResetEvent evnt = new System.Threading.ManualResetEvent(false);
            public int result = 0;

            public AsyncState(Socket socket)
            {
                sock = socket;
            }
            public Socket socket
            {
                get { return sock; }
            }
            public void Set()
            {
                evnt.Set();
            }
            public void Reset()
            {
                evnt.Reset();
            }
            public bool WaitForReturn(int timeout)
            {
                return evnt.WaitOne(timeout, false);
            }
        }
Thank you

Re: Reading %W memory from GE RX3i with T7A

Posted: Mon Mar 24, 2014 3:15 pm
by stuartm
Here is a sample project (Send/Receive). To ensure your objects stay active, do not place your scripts in screens. Especially if you are using aliases. The screen object is destroyed. All of the objects gets re-instantiated. Also, using a normal class not just a partial class.

Re: Reading %W memory from GE RX3i with T7A

Posted: Mon Mar 24, 2014 3:58 pm
by AMitchneck
My TCP/IP connection is established using a class in my referenced dll. I have a script file which creates and initializes the class when the panel starts up. I don't understand why, but I found my code worked fine once I removed the "Thread.IsBackground = true; Thread.Priority = ThreadPriority.Normal;" statements making my "check TCP/IP connection is alive" thread no longer a background thread. Do these properties do something different on Windows CE than documented for standard .net?

The issue I was having is for some reason the "timeout" function in my connect function never would timeout. It's as if Windows paused at the timeout then decided to never continue running the thread ever again. This issue stopped when I removed the two lines of code making sure the thread was given normal priority and to run as background (i.e. quit without completion if process is shutting down). (NOTE: This same dll, compiled for non-compact framework, works perfectly fine without the change.)

It seems my issue runs into something deep within .Net 3.5 CF for Windows CE that I'm just not understanding.