Welcome Guest ( Login | Register )



All times are UTC - 7 hours [ DST ]



Post new topic Reply to topic  [ 13 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: TCP IP Communication between Beijer HMI and other Devices
PostPosted: Tue Jun 05, 2018 6:29 am 

Joined: Wed Feb 22, 2012 12:01 am
Posts: 44

Offline
Hi all,

I would like to point out my current obstacle as below:
    - I'm currently using another device support TCP/IP Communication and successfully connect between my laptop (using Hercules or HyperTerminal to send/receive data.
    - However, I could NOT find TCP IP communication in iX Developer.

May I know what could be the solutions?

Thanks all!


 Profile  
 
 Post subject: Re: TCP IP Communication between Beijer HMI and other Device
PostPosted: Tue Jun 05, 2018 6:56 am 

Joined: Mon Jun 11, 2012 2:10 pm
Posts: 120

Offline
Hi ajack,

TCP IP just indicates the connection is over Ethernet. What is the underlying communication protocol? Based on your mention of hyperterminal I'm assuming it's ascii-based like telnet.

_________________
Adam M.
Controls Engineer
FlexEnergy


 Profile  
 
 Post subject: Re: TCP IP Communication between Beijer HMI and other Device
PostPosted: Tue Jun 05, 2018 8:45 am 

Joined: Wed Feb 22, 2012 12:01 am
Posts: 44

Offline
AMitchneck wrote:
Hi ajack,

TCP IP just indicates the connection is over Ethernet. What is the underlying communication protocol? Based on your mention of hyperterminal I'm assuming it's ascii-based like telnet.


Hi Adam,

Thanks so much for your response!

Yes, you're correct, the underlying communication protocol is ASCII-based. Moreover, I purely want to capture or send data with RAW Ethernet TCP/IP. Is that possible?

Thanks,


 Profile  
 
 Post subject: Re: TCP IP Communication between Beijer HMI and other Device
PostPosted: Tue Jun 05, 2018 9:18 am 

Joined: Mon Jun 11, 2012 2:10 pm
Posts: 120

Offline
Hi ajack,

You can do that by creating a custom script module and using a Socket. For example, below I have included the source code for a ModbusTCP client I created to read holding registers.

you will need to add the following using's to the head of your script module:
using System.Net;
using System.Net.Sockets;

To use the client you would do something like:
Code:
using (ModClient client = new ModClient())
{
   client.Connect(host, port);
   client.ReadHoldingRegisters(slave, address, 2, out buffer);
}

Note this method makes a new connection every time the client is used, then closes it.


Code:
   public class ModClient : IDisposable
   {
      private volatile Socket sock;
      private ushort transID;
      
      public ModClient()
      {
         sock = null;
         transID = 0;
      }
      public bool Connect(string host, int port)
      {
         Socket _sock = null;
         IPEndPoint ModAddr;
         
         Close(); // clean up any previous connection
         transID = 0;
         
         try { ModAddr = new IPEndPoint(IPAddress.Parse(host), 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(ModAddr, ProcessConnect, asyncState);
            if (asyncState.WaitForReturn(20000))
            {
               if (_sock.Connected)
               {
                  sock = _sock;
                  return true;
               }
            }
         }
         catch (SocketException) { }
         catch (ObjectDisposedException) { }
         catch
         {
            // unknown error, close socket and throw error
            if (_sock != null) _sock.Close();
            _sock = null;
            throw;
         }
         
         // connection failed, close socket
         if (_sock != null) _sock.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(); }
      }
      
      public bool Connected
      {
         get
         {
            if (sock == null) return false;
            return sock.Connected;
         }
      }
      
      public void Close()
      {
         Socket _sock = sock;
         if (_sock == null) return;
         sock = null;
         
         try { if (_sock.Connected) _sock.Shutdown(SocketShutdown.Both); }
         catch (SocketException) { }
         catch (ObjectDisposedException) { }
         catch (PlatformNotSupportedException) { }
         finally { _sock.Close(); }
      }
      public void Dispose()
      {
         Close();
      }
      
      public int ReadHoldingRegisters(ushort address, ushort registers, out byte[] buffer)
      {
         return ReadHoldingRegisters(1, address, registers, out buffer);
      }
      public int ReadHoldingRegisters(byte slave, ushort address, ushort registers, out byte[] buffer)
      {
         registers--;
         if ((registers >= 125) || ((0xFFFF - registers) < address))
         {
            buffer = null;
            return -1;
         }
         
         byte[] header, inbuff, outbuff;
         int length, i;
         ushort thisID = transID++;
         outbuff = new byte[12];
         
         registers++;
         buffer = new byte[registers * 2];
         if (!Connected) return -1;
         
         outbuff[0] = (byte)((thisID & 0xFF00) >> 8);
         outbuff[1] = (byte)(thisID & 0x00FF);
         outbuff[2] = 0;
         outbuff[3] = 0;
         outbuff[4] = 0;
         outbuff[5] = 6;
         outbuff[6] = slave;
         outbuff[7] = 3;
         outbuff[8] = (byte)((address & 0xFF00) >> 8);
         outbuff[9] = (byte)(address & 0x00FF);
         outbuff[10] = (byte)((registers & 0xFF00) >> 8);
         outbuff[11] = (byte)(registers & 0x00FF);
         if (!SendAll(outbuff)) return -1;
         
         for (; ; )
         {
            if (!ReceiveAll(out header, 8)) return -1;
            length = (int)((((ushort)header[4]) << 8) | (ushort)header[5]) - 2;
            if (length < 0)
            {
               Close();
               return -1;
            }
            if (!ReceiveAll(out inbuff, length)) return -1;
            
            if ((outbuff[0] == header[0]) && (outbuff[1] == header[1]) && (outbuff[7] == (header[7] & 0x7F)))
            {
               if ((header[7] & 0x80) != 0)
               {
                  if (length == 0)
                     buffer[0] = 0;
                  else
                     buffer[0] = inbuff[0];
                  return 0;
               }
               if ((length - 1) < buffer.Length)
               {
                  buffer[0] = 0;
                  return 0;
               }
               for (i = 0; i < buffer.Length; i++)
               {
                  buffer[i] = inbuff[i + 1];
               }
               return (int)registers;
            }
         }
      }
      
      private bool SendAll(byte[] buffer)
      {
         int i, bytesSent;
         
         if (buffer == null) throw new ArgumentNullException("buffer");
         if (!Connected) return false;
         
         AsyncState asyncState = new AsyncState(sock);
         for (i = 0; i < buffer.Length; i += bytesSent)
         {
            try
            {
               if (sock.Poll(5000000, SelectMode.SelectWrite)) // use send timeout of 5 seconds
               {
                  asyncState.Reset();
                  sock.BeginSend(buffer, i, buffer.Length - i, SocketFlags.None, ProcessSend, asyncState);
                  if (asyncState.WaitForReturn(10000)) // use send timeout of 10 seconds
                     bytesSent = asyncState.result;
                  else
                     bytesSent = 0; // send timed out
               }
               else
               {
                  bytesSent = 0; // send timed out
               }
            }
            catch (SocketException) { bytesSent = 0; }
            catch (ObjectDisposedException) { bytesSent = 0; }
            if (bytesSent == 0)
            {
               // no data sent -> connection lost
               Close(); // close socket
               return false;
            }
         }
         
         return true;
      }
      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 bool ReceiveAll(out byte[] buffer, int size)
      {
         int i, bytesRecv;
         
         if (size < 0)
         {
            buffer = null;
            return false;
         }
         else
         {
            buffer = new byte[size];
            if (!Connected) return false;
         }
         
         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
                  bytesRecv = 0; // receive timed out
            }
            catch (SocketException) { bytesRecv = 0; }
            catch (ObjectDisposedException) { bytesRecv = 0; }
            if (bytesRecv == 0)
            {
               // no data received -> connection lost
               Close(); // close socket
               return false;
            }
         }
         
         return true;
      }
      
      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);
         }
      }
   }

_________________
Adam M.
Controls Engineer
FlexEnergy


 Profile  
 
 Post subject: Re: TCP IP Communication between Beijer HMI and other Device
PostPosted: Tue Jun 05, 2018 9:53 am 

Joined: Wed Feb 22, 2012 12:01 am
Posts: 44

Offline
Hi Adam,

Thanks so much for your effort to provide detail Script!

Can I conclude that currently iX doesn't provide Raw Communication through TCP/IP? And, we need to handle in lower level so that we can capture and sending data through Socket of Ethernet Port?

Moreover, may I know whether you can provide the file with the script so that I can quickly implement in my program now?
It may cost some time for me to read through all this code before implementation...

Thanks,
Phong Duong


 Profile  
 
 Post subject: Re: TCP IP Communication between Beijer HMI and other Device
PostPosted: Tue Jun 05, 2018 10:06 am 

Joined: Mon Jun 11, 2012 2:10 pm
Posts: 120

Offline
I don't work for Beijer so you'd have to contact customer support to get exact answer, but as far as I know there is no raw communication driver.

What I could send you as a scripting module would only be a direct copy of what I attached in my prior response. The code was more for example of how you could use/manage the Socket.

_________________
Adam M.
Controls Engineer
FlexEnergy


 Profile  
 
 Post subject: Re: TCP IP Communication between Beijer HMI and other Device
PostPosted: Tue Jun 05, 2018 10:30 am 

Joined: Wed Feb 22, 2012 12:01 am
Posts: 44

Offline
AMitchneck wrote:
I don't work for Beijer so you'd have to contact customer support to get exact answer, but as far as I know there is no raw communication driver.

What I could send you as a scripting module would only be a direct copy of what I attached in my prior response. The code was more for example of how you could use/manage the Socket.


Hi Adam,

Thanks so much for your help!


 Profile  
 
 Post subject: Re: TCP IP Communication between Beijer HMI and other Device
PostPosted: Wed Jun 06, 2018 12:49 am 

Joined: Wed Feb 22, 2012 12:01 am
Posts: 44

Offline
Hi Adam,

Thanks for your help! I can do some simple communication between PC and HMI using Script C# with Socket class.

I would like to ask for some more questions:

1. Should we choose Asynchronous or Synchronous socket connection?

2. Where should we put main loop in HMI code? Or we can use ScreenOpened?

3. If we insert Script Module, every time we call the Class/Method by using
Code:
Globals.Script.<ScriptName>
?

Thanks and best regards,
Phong Duong


 Profile  
 
 Post subject: Re: TCP IP Communication between Beijer HMI and other Device
PostPosted: Wed Jun 06, 2018 8:23 am 

Joined: Wed Feb 22, 2012 12:01 am
Posts: 44

Offline
Hi all,

I already succeeded in implementing Sockets for Ethernet Transceiver. If anyone is interested can use attached file.

I do hope that anyone who faced same issues with me can save some time or even improve those codes.

Thanks,
Phong Duong


 Profile  
 
 Post subject: Re: TCP IP Communication between Beijer HMI and other Device
PostPosted: Wed Jun 06, 2018 8:33 am 

Joined: Mon Jun 11, 2012 2:10 pm
Posts: 120

Offline
Hi ajack,

1. Given the option, I typically use Asynchronous socket connections (as was in my sample script).

2. How acquainted are you with multi threading? What I typically use to drive a cyclic process is a System.Threading.Timer. Script modules have a "Created" event that fires during startup when the screen displays staring <script> which is where I put the initializer for the threading Timer (Proc_Timer = new Timer(Proc_Timer_Tick, null, 1000, 1000); // call timer function every second). This is more time-accurate than a form Timer, but can cause the Tick function to be called multiple times even if previous tick didn't complete. If this may be an issue, what I usually do is create a main processing thread with a loop that waits on an auto reset event that is set by the tick function.

3. That depends on how you declare the function. If you use public int test(), then you would need to call it through Globals.<scriptname>.test(), but if you declare it static than you don't need Globals.

_________________
Adam M.
Controls Engineer
FlexEnergy


 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 13 posts ]  Go to page 1, 2  Next

All times are UTC - 7 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron