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: Select all
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: Select all
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