Coppermine-SP
클라우드인터렉티브
기술블로그
Coppermine-SP
전체 방문자
오늘
어제
  • 분류 전체보기 (23)
    • Server (12)
      • General (1)
      • Synology (4)
      • Windows Server (7)
    • Network (8)
      • General (2)
      • UniFi (6)
    • Operating System (0)
      • Windows (0)
      • macOS (0)
    • Imaging (1)
      • Camera (1)
    • Programming (2)
      • C++ (1)
      • C# (1)

티스토리

hELLO · Designed By 정상우.
Coppermine-SP
Programming/C#

무선 TCP 시리얼 서버 (EW11, EW10) C# 소켓 통신

무선 TCP 시리얼 서버 (EW11, EW10) C# 소켓 통신
Programming/C#

무선 TCP 시리얼 서버 (EW11, EW10) C# 소켓 통신

2021. 10. 26. 23:43

개요

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 코드)를 송 수신 할 수 있게 하는 간단한 클래스입니다. 

본 코드는 테스트되지 않았으며, 최적의 성능으로 동작 하는 것을 보장할 수 없습니다.
프로덕션 환경에서 이 코드를 그대로 사용하지 마십시오.

 

 

저작자표시 비영리 변경금지 (새창열림)
  • 개요
  • TCP 서버 모드 변경하기
  • C# TCP Socket을 통한 시리얼 서버 통신 예제 코드
Coppermine-SP
Coppermine-SP
사람과 세상을 연결하는 기술.

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.