개요
EW11 / 10은 RS485 / 232 신호를 WIFI를 통해 송수신 할 수 있게 해주는 무선 시리얼 서버입니다.
이 무선 시리얼 서버를 통하여 응용 프로그램을 개발하거나 HA를 구축하려면 PC와 연결되어야 합니다. C#을 통해 해당 장치들과 TCP 서버 모드로 쉽게 통신 할 수 있습니다.단순하게 시리얼 통신 내용을 모니터링 하는 용도로는 SerialPortMon(https://blog.daum.net/pg365/276) 라는 아주 좋은 프로그램이 있으니 참조하세요.
TCP 서버 모드 변경하기
EW11 / 10 관리 페이지로 접속하여 좌측 매뉴의 Advanced Settings 내의 Protocol을 TCP Server로 지정하고 포트를 적절하게 지정하여 주세요.
C# TCP Socket을 통한 시리얼 서버 통신 예제 코드
using System;
using System.Net;
using System.Net.Sockets;
using System.Linq;
using System.Timers;
namespace CloudInteractive.TCPEngine
{
///<summary>
/// Client for serial tcp server. (EW11, EW10)
///</summary>
public class SerialClient
{
private string _ip;
private int _port;
private Socket _socket;
private bool _connected = false;
private const int bufferSize = 1024;
private const int connectionCheckTime = 3000;
private byte[] _buffer;
private Timer _CheckTimer;
public event EventHandler<LogEventArgs> LogEvent;
public event EventHandler<ReceiveEventArgs> Received;
public event EventHandler Disconnected;
public class ReceiveEventArgs : EventArgs
{
public string Content;
public ReceiveEventArgs(string content)
{
Content = content;
}
}
public SerialClient(string ip, int port)
{
_ip = ip;
_port = port;
_CheckTimer = new Timer();
_CheckTimer.Interval = connectionCheckTime;
_CheckTimer.Elapsed += _CheckTimer_Elapsed;
}
private void _CheckTimer_Elapsed(object sender, ElapsedEventArgs e)
{
bool status;
try
{
status = !(_socket.Poll(1, SelectMode.SelectRead) && _socket.Available == 0);
}
catch (Exception)
{
if (LogEvent != null)
LogEvent(this, new LogEventArgs(LogEventArgs.LogType.Error, "Connection keep-alive check failed. Disconnecting.. "));
Disconnect();
}
}
public void Connect()
{
if (_connected == true) throw new InvalidOperationException("Already connected.");
IPEndPoint iep = new IPEndPoint(IPAddress.Parse(_ip), _port);
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_buffer = new byte[bufferSize];
try
{
if (LogEvent != null)
LogEvent(this, new LogEventArgs(LogEventArgs.LogType.Info, $"Connecting to {_ip}:{_port}..."));
_socket.Connect(iep);
_socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(_ReceivePacket), _socket);
_CheckTimer.Start();
}
catch (Exception e)
{
if (LogEvent != null)
LogEvent(this, new LogEventArgs(LogEventArgs.LogType.Error, "Connection Failed : " + e.ToString()));
throw e;
}
if (LogEvent != null)
LogEvent(this, new LogEventArgs(LogEventArgs.LogType.Info, "Connected."));
_connected = true;
}
public async void Disconnect()
{
if (_connected == false) throw new InvalidOperationException("Not connected.");
_socket.Disconnect(false);
if (LogEvent != null)
LogEvent(this, new LogEventArgs(LogEventArgs.LogType.Info, "Disconnected."));
_CheckTimer.Stop();
_socket.Dispose();
_connected = false;
if (Disconnected != null)
Disconnected(this, EventArgs.Empty);
}
private void _ReceivePacket(IAsyncResult asyncResult)
{
Socket asyncSocket = (Socket)asyncResult.AsyncState;
try
{
int recv = asyncSocket.EndReceive(asyncResult);
if (recv == 0) return;
string receivedString = BitConverter.ToString(_buffer, 0, recv);
if (Received != null)
Received(this, new ReceiveEventArgs(receivedString.Replace("-", String.Empty)));
asyncSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None,
new AsyncCallback(_ReceivePacket), asyncSocket);
}
catch (Exception e)
{
if (LogEvent != null)
LogEvent(this, new LogEventArgs(LogEventArgs.LogType.Error, "Exception on receive : " + e.ToString()));
Disconnect();
return;
}
}
public async void SendPacket(string hex)
{
byte[] message;
try
{
message = HexToByte(hex);
}
catch (Exception e)
{
if (LogEvent != null)
LogEvent(this, new LogEventArgs(LogEventArgs.LogType.Error, "Exception on parsing hex : " + e.ToString()));
return;
}
try
{
_socket.Send(message, 0, message.Length, SocketFlags.None);
if (LogEvent != null)
LogEvent(this, new LogEventArgs(LogEventArgs.LogType.Debug, "Send : " + hex));
}
catch (Exception e)
{
if(LogEvent != null)
LogEvent(this, new LogEventArgs(LogEventArgs.LogType.Error, "Exception on send : " + e.ToString()));
Disconnect();
return;
}
}
public static byte[] HexToByte(string hex)
{
hex = hex.Trim();
hex = hex.Replace("-", String.Empty);
hex = hex.Replace(" ", String.Empty);
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
}
public class LogEventArgs : EventArgs
{
public enum LogType { Info, Warning, Error, Debug };
public LogType Type;
public string Content;
public Exception Ex;
public LogEventArgs(LogType type, string content, Exception e = null)
{
Type = type;
Content = content;
Ex = e;
}
public override string ToString()
{
if (Ex != null) return String.Format("[{0}]{1} : {2}", Type.ToString(), Content, Ex.ToString());
return String.Format("[{0}] {1}", Type.ToString(), Content);
}
}
}
이 코드는 TCP Socket을 통해 16진수 데이터 (HEX 코드)를 송 수신 할 수 있게 하는 간단한 클래스입니다.
본 코드는 테스트되지 않았으며, 최적의 성능으로 동작 하는 것을 보장할 수 없습니다.
프로덕션 환경에서 이 코드를 그대로 사용하지 마십시오.