1097 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			1097 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.Linq;
 | |
| using System.Text;
 | |
| using System.ComponentModel;
 | |
| using System.Threading;
 | |
| 
 | |
| namespace Project.Device
 | |
| {
 | |
|     public class Barcode : IDisposable
 | |
|     {
 | |
|         protected Boolean _isinit = false;
 | |
| 
 | |
|         #region "Event Args"
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 데이터를 수신할떄 사용함(RAW 포함)
 | |
|         /// </summary>
 | |
|         public class ReceiveDataEventArgs : EventArgs
 | |
|         {
 | |
|             private byte[] _buffer = null;
 | |
| 
 | |
|             /// <summary>
 | |
|             /// 바이트배열의 버퍼값
 | |
|             /// </summary>
 | |
|             public byte[] Value { get { return _buffer; } }
 | |
| 
 | |
|             /// <summary>
 | |
|             /// 버퍼(바이트배열)의 데이터를 문자로 반환합니다.
 | |
|             /// </summary>
 | |
|             public string StrValue
 | |
|             {
 | |
|                 get
 | |
|                 {
 | |
|                     //return string.Empty; 
 | |
| 
 | |
|                     if (_buffer == null || _buffer.Length < 1) return string.Empty;
 | |
|                     else return System.Text.Encoding.Default.GetString(_buffer);
 | |
|                 }
 | |
|             }
 | |
|             public ReceiveDataEventArgs(byte[] buffer)
 | |
|             {
 | |
|                 _buffer = buffer;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public class MessageEventArgs : EventArgs
 | |
|         {
 | |
|             private Boolean _isError = false;
 | |
|             public Boolean IsError { get { return _isError; } }
 | |
|             private string _message = string.Empty;
 | |
|             public string Message { get { return _message; } }
 | |
|             public MessageEventArgs(Boolean isError, string Message)
 | |
|             {
 | |
|                 _isError = isError;
 | |
|                 _message = Message;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         #endregion
 | |
| 
 | |
|         #region "Enum & Structure"
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 데이터수신시 해당 데이터의 끝을 결정하는 방식을 설정합니다.
 | |
|         /// </summary>
 | |
|         public enum eTerminal : byte
 | |
|         {
 | |
|             /// <summary>
 | |
|             /// line feed
 | |
|             /// </summary>
 | |
|             LF = 0,
 | |
| 
 | |
|             /// <summary>
 | |
|             /// carrige return
 | |
|             /// </summary>
 | |
|             CR,
 | |
| 
 | |
|             /// <summary>
 | |
|             /// cr+lf
 | |
|             /// </summary>
 | |
|             CrLf,
 | |
| 
 | |
|             /// <summary>
 | |
|             /// stx +  ETx 구성된 프로토콜을 감지합니다. stx,etx는 임의 지정이 가능하며 기본값으로는 stx = 0x02, etx = 0x03 을 가지고 있습니다.
 | |
|             /// </summary>
 | |
|             ETX,
 | |
| 
 | |
|             /// <summary>
 | |
|             /// 데이터의 길이를 가지고 판단합니다.
 | |
|             /// </summary>
 | |
|             Length,
 | |
| 
 | |
|             /// <summary>
 | |
|             /// 설정없음 .. 일정시간동안 대기한 후 버퍼의 내용을 모두 데이터로 인정합니다.
 | |
|             /// </summary>
 | |
|             None,
 | |
| 
 | |
|             /// <summary>
 | |
|             /// 내부 Receive 이벤트를 사용하지 않고 Raw 이벤트를 사용합니다.
 | |
|             /// 이 값을 설정할 경우 내부 Receivce 이벤트 내에서 메세지 수신 이벤트가 발생하지 않습니다.
 | |
|             /// DataParSER을 상속하여 해당 파서에서 데이터를 분리하세요. True 이면 분리성공, false 이면 완료될때까지 대기합니다.
 | |
|             /// </summary>
 | |
|             CustomParser
 | |
|         }
 | |
| 
 | |
|         #endregion
 | |
| 
 | |
|         #region "Public variable"
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 오류가 발생했다면 이 변수에 그 내용이 기록됩니다.
 | |
|         /// </summary>
 | |
|         public string errorMessage = string.Empty;
 | |
| 
 | |
|         ///// <summary>
 | |
|         ///// WriteDataSync 명령 사용시 최대로 기다리는 시간
 | |
|         ///// </summary>
 | |
|         //public int syncTimeout = 5000;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 이 값은 종단기호 형식이 Length 일때 사용됩니다. 버퍼의 갯수이 이 값과 일치하면 수신 이벤트를 발생합니다.
 | |
|         /// </summary>
 | |
|         public int MaxDataLength = 0x0d;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 마지막으로 데이터는 전송한 시간
 | |
|         /// </summary>
 | |
|         public DateTime lastSendTime;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 최종 전송 메세지
 | |
|         /// </summary>
 | |
|         public byte[] lastSendBuffer;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 마지막으로 데이터를 받은 시간
 | |
|         /// </summary>
 | |
|         public DateTime lastRecvTime = DateTime.Parse("1982-11-23");
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 데이터 전송시 전송메세지를 발생할것인가? 171113
 | |
|         /// </summary>
 | |
|         public Boolean EnableTxMessage { get; set; }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// terminal 이 stx 일때에만 사용하며 기본값은 0x03
 | |
|         /// </summary>
 | |
|         [Description("종단기호형식이 ETX일때 사용하는 데이터의 종료문자값입니다. 바이트값이므로 0~255 사이로 입력하세요.")]
 | |
|         [Category("설정"), DisplayName("Data End Byte")]
 | |
|         public byte ETX { get; set; }
 | |
| 
 | |
|         #endregion
 | |
| 
 | |
|         #region "Protect & private Variable"
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 메세지 수신시 사용하는 내부버퍼
 | |
|         /// </summary>
 | |
|         protected List<byte> _buffer = new List<byte>();
 | |
| 
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 데이터의 끝을 분석하는 종단기호의 설정
 | |
|         /// </summary>
 | |
|         private eTerminal _term = eTerminal.LF;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// WriteDataSync 명령사용시 활성화됨
 | |
|         /// </summary>
 | |
|         protected Boolean _isSync = false;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// sync timeOUt체크시 사용합니다.
 | |
|         /// </summary>
 | |
|         private System.Diagnostics.Stopwatch _wat = new System.Diagnostics.Stopwatch();
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Serialport Device
 | |
|         /// </summary>
 | |
|         protected System.IO.Ports.SerialPort _device;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// for autoreset events
 | |
|         /// </summary>
 | |
|         protected ManualResetEvent _mre;
 | |
| 
 | |
|         protected Boolean isDisposed = false;
 | |
| 
 | |
|         #endregion
 | |
| 
 | |
|         #region "Internal Events"
 | |
| 
 | |
|         void barcode_ErrorReceived(object sender, System.IO.Ports.SerialErrorReceivedEventArgs e)
 | |
|         {
 | |
|             if (Message != null) Message(this, new MessageEventArgs(true, e.ToString()));
 | |
|         }
 | |
| 
 | |
|         
 | |
| 
 | |
|         void barcode_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
 | |
|         {
 | |
|             if (_isSync) return; //싱크모드일경우에는 해당 루틴에서 직접 읽는다
 | |
|             _isSync = false;
 | |
|             //none일경우에는 100ms 정도 기다려준다.
 | |
|             if (_term == eTerminal.None)
 | |
|             {
 | |
|                 //none 일경우에는 무조건 데이터로 취급한다.
 | |
|                 System.Threading.Thread.Sleep(200);
 | |
|                 _buffer.Clear();
 | |
|             }
 | |
| 
 | |
|             try
 | |
|             {
 | |
|                 int ReadCount = _device.BytesToRead;
 | |
| 
 | |
|                 byte[] buffer = new byte[ReadCount];
 | |
|                 _device.Read(buffer, 0, buffer.Length);
 | |
| 
 | |
|                 if (ReceiveData_Raw != null) ReceiveData_Raw(this, new ReceiveDataEventArgs(buffer));
 | |
|                 System.Text.StringBuilder LogMsg = new StringBuilder();
 | |
| 
 | |
|                 if (Terminal == eTerminal.CustomParser)
 | |
|                 {
 | |
|                     byte[] remainBuffer;
 | |
|                 Repeat:
 | |
|                     if (CustomParser(buffer, out remainBuffer))
 | |
|                     {
 | |
|                         //parser ok
 | |
|                         RaiseRecvData(_buffer.ToArray());
 | |
|                         _buffer.Clear();
 | |
|                         if (remainBuffer != null && remainBuffer.Length > 0)
 | |
|                         {
 | |
|                             //버퍼를 변경해서 다시 전송을 해준다.
 | |
|                             buffer = new byte[remainBuffer.Length];
 | |
|                             Array.Copy(remainBuffer, buffer, buffer.Length);
 | |
|                             goto Repeat; //남은 버퍼가 있다면 진행을 해준다.
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     foreach (byte bb in buffer)
 | |
|                     {
 | |
|                         switch (_term)
 | |
|                         {
 | |
| 
 | |
|                             case eTerminal.CR:
 | |
|                                 if (bb == 0x0D)
 | |
|                                 {
 | |
|                                     RaiseRecvData(_buffer.ToArray()); ;
 | |
|                                     _buffer.Clear();
 | |
|                                 }
 | |
|                                 else _buffer.Add(bb);
 | |
|                                 break;
 | |
|                             case eTerminal.LF:
 | |
|                                 if (bb == 0x0A)
 | |
|                                 {
 | |
|                                     RaiseRecvData(_buffer.ToArray()); ;
 | |
|                                     _buffer.Clear();
 | |
|                                 }
 | |
|                                 else _buffer.Add(bb);
 | |
|                                 break;
 | |
|                             case eTerminal.CrLf:
 | |
|                                 if (bb == 0x0A)
 | |
|                                 {
 | |
|                                     RaiseRecvData(_buffer.ToArray()); ;
 | |
|                                     _buffer.Clear();
 | |
|                                 }
 | |
|                                 else if (bb == 0x0D)
 | |
|                                 {
 | |
|                                     //0d는 그냥 넘어간다.
 | |
|                                 }
 | |
|                                 else _buffer.Add(bb);
 | |
|                                 break;
 | |
|                             case eTerminal.Length:
 | |
|                                 _buffer.Add(bb);
 | |
|                                 if (_buffer.Count == MaxDataLength)
 | |
|                                 {
 | |
|                                     RaiseRecvData(_buffer.ToArray()); ;
 | |
|                                     _buffer.Clear();
 | |
|                                 }
 | |
|                                 else if (_buffer.Count > MaxDataLength)
 | |
|                                 {
 | |
|                                     RaiseMessage("Buffer Length Error " + _buffer.Count.ToString() + "/" + MaxDataLength.ToString(), true);
 | |
|                                     _buffer.Clear();
 | |
|                                 }
 | |
|                                 break;
 | |
|                             case eTerminal.ETX: //asc타입의 프로토콜에서는 STX,ETX가 고유값이다.
 | |
|                                 if (bb == STX)
 | |
|                                 {
 | |
|                                     _buffer.Clear();
 | |
|                                 }
 | |
|                                 else if (bb == ETX)
 | |
|                                 {
 | |
|                                     RaiseRecvData(_buffer.ToArray()); ;
 | |
|                                     _buffer.Clear();
 | |
|                                 }
 | |
|                                 else _buffer.Add(bb);
 | |
|                                 break;
 | |
|                             case eTerminal.None:
 | |
|                                 _buffer.Add(bb);
 | |
|                                 break;
 | |
|                         }
 | |
|                     }
 | |
| 
 | |
|                     //170802
 | |
|                     if (_term == eTerminal.None)
 | |
|                     {
 | |
|                         RaiseRecvData(_buffer.ToArray()); ;
 | |
|                         _buffer.Clear();
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 if (IsOpen)
 | |
|                 {
 | |
|                     //_device.DiscardInBuffer();
 | |
|                     //_device.DiscardOutBuffer();
 | |
|                 }
 | |
|                 errorMessage = ex.Message;
 | |
|                 RaiseMessage(ex.Message, true);
 | |
|             }
 | |
| 
 | |
|         }
 | |
| 
 | |
| 
 | |
|         #endregion
 | |
| 
 | |
|         #region "External Events"
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 바코드에서 들어오는 데이터의 원본 메세지
 | |
|         /// </summary>
 | |
|         public event EventHandler<ReceiveDataEventArgs> ReceiveData_Raw;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 데이터가 들어올 경우 발생합니다 (종단기호=Termianl) 문자열이 발견된 후에 발생함
 | |
|         /// </summary>
 | |
|         public event EventHandler<ReceiveDataEventArgs> ReceiveData;
 | |
| 
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 데이터를 전송할 때 해당 이벤트가 발생합니다.
 | |
|         /// </summary>
 | |
|         public event EventHandler<ReceiveDataEventArgs> SendData;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 오류 및 기타 일반 메세지
 | |
|         /// </summary>
 | |
|         public event EventHandler<MessageEventArgs> Message;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 시리얼포트의 핀 상태값이 변경될 때 발생합니다.
 | |
|         /// </summary>
 | |
|         //public event EventHandler<System.IO.Ports.SerialPinChangedEventArgs> serialPinchanged;
 | |
| 
 | |
| 
 | |
|         #endregion
 | |
| 
 | |
|         #region "Properties"
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 식별번호(임의지정가능) - 장치 생성시 입력
 | |
|         /// </summary>
 | |
|         [Description("이 장치의 식별 ID(임의 지정가능)")]
 | |
|         [Category("설정"), DisplayName("Device No")]
 | |
|         public int ID { get; set; }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// terminal 이 etx 일때에만 사용하며 기본값은 0x02
 | |
|         /// </summary>
 | |
|         [Description("종단기호형식이 ETX일때 사용하는 데이터의 시작문자값입니다. 바이트값이므로 0~255 사이로 입력하세요.")]
 | |
|         [Category("설정"), DisplayName("Data Start Byte")]
 | |
|         public byte STX { get; set; }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 내장 분석기(Parser)를 사용할 경우 최종 데이터에서 CR,LF를 제거할지 선택합니다.
 | |
|         /// </summary>
 | |
|         [Description("내장분석기(Parser)를 사용할 경우 최종 데이터에서 CR.LF를 제거할지 선택합니다.")]
 | |
|         [Category("기타"), DisplayName("CRLF 제거")]
 | |
|         public Boolean RemoveCRLFNULL { get; set; }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 종단기호 형식
 | |
|         /// </summary>
 | |
|         [Description("데이터의 종단기호를 설정합니다. 지정한 데이터가 올경우")]
 | |
|         [Category("설정"), DisplayName("종단기호")]
 | |
|         public eTerminal Terminal { get { return _term; } set { _term = value; } }
 | |
| 
 | |
|         [Category("설정")]
 | |
|         public System.IO.Ports.Parity Parity
 | |
|         {
 | |
|             get
 | |
|             {
 | |
| 
 | |
|                 return _device.Parity;
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 _device.Parity = value;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         [Category("설정")]
 | |
|         public int DataBits
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return _device.DataBits;
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 _device.DataBits = value;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         [Category("설정")]
 | |
|         public System.IO.Ports.StopBits StopBits
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return _device.StopBits;
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 _device.StopBits = value;
 | |
|             }
 | |
| 
 | |
|         }
 | |
| 
 | |
|         [Category("설정")]
 | |
|         public System.IO.Ports.Handshake Handshake
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return _device.Handshake;
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 _device.Handshake = value;
 | |
|             }
 | |
| 
 | |
|         }
 | |
| 
 | |
|         #region "pin state & pin setting"
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Data Terminal Ready
 | |
|         /// </summary>
 | |
|         [Description("Data Terminal Ready 신호의 사용여부")]
 | |
|         [Category("PIN")]
 | |
|         public Boolean DtrEnable
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return _device.DtrEnable;
 | |
| 
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 _device.DtrEnable = value;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Request To Send
 | |
|         /// </summary>
 | |
|         [Description("Request to Send 신호의 사용여부")]
 | |
|         [Category("PIN")]
 | |
|         public Boolean RtsEnable
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return _device.RtsEnable;
 | |
| 
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 _device.RtsEnable = value;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Data set Ready 신호 상태
 | |
|         /// </summary>
 | |
|         [Description("Data Set Ready 신호 상태")]
 | |
|         [Category("PIN")]
 | |
|         public Boolean PIN_DSR
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 if (!IsOpen) return false;
 | |
|                 return _device.DsrHolding;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Carrier Detect
 | |
|         /// </summary>
 | |
|         [Description("Carrier Detect 신호 상태")]
 | |
|         [Category("PIN")]
 | |
|         public Boolean PIN_CD
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 if (!IsOpen) return false;
 | |
|                 return _device.CDHolding;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Clear to Send
 | |
|         /// </summary>
 | |
|         [Description("Clear to Send 신호 상태")]
 | |
|         [Category("PIN")]
 | |
|         public Boolean PIN_CTS
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 if (!IsOpen) return false;
 | |
|                 return _device.CtsHolding;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Break State
 | |
|         /// </summary>
 | |
|         [Description("중단신호 상태")]
 | |
|         [Category("PIN")]
 | |
|         public Boolean PIN_BreakState
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 if (!IsOpen) return false;
 | |
|                 return _device.BreakState;
 | |
|             }
 | |
|         }
 | |
| 
 | |
| 
 | |
|         #endregion
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 포트가 열려있는지 확인
 | |
|         /// </summary>
 | |
|         [Description("현재 시리얼포트가 열려있는지 확인합니다")]
 | |
|         [Category("정보"), DisplayName("Port Open")]
 | |
|         public virtual Boolean IsOpen
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 if (_device == null) return false;
 | |
|                 return _device.IsOpen;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 초기화등이 성공했는지 확인합니다.close 되었다면 실패입니다. isinit 변수값을 적절히 수정하시기 바랍니다.
 | |
|         /// </summary>
 | |
|         [Description("초기화성공여부 별도의 초기화 코드가없다면 isOpen 과 동일합니다.")]
 | |
|         [Category("정보"), DisplayName("Init OK?")]
 | |
|         public virtual Boolean IsInit
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 if (!IsOpen || !_isinit) return false;
 | |
|                 return true;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 쓰기타임아웃
 | |
|         /// </summary>
 | |
|         [Description("쓰기명령어의 최대대기시간(단위:ms)\r\n지정 시간을 초과할 경우 오류가 발생합니다.")]
 | |
|         [Category("설정"), DisplayName("쓰기 제한시간")]
 | |
|         public int WriteTimeout
 | |
|         {
 | |
|             get { return _device.WriteTimeout; }
 | |
|             set { _device.WriteTimeout = value; }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 읽기타임아웃
 | |
|         /// </summary>
 | |
|         [Description("읽기명령어의 최대대기시간(단위:ms)\r\n지정 시간을 초과할 경우 오류가 발생합니다.")]
 | |
|         [Category("설정"), DisplayName("읽기 제한시간")]
 | |
|         public int ReadTimeout
 | |
|         {
 | |
|             get { return _device.ReadTimeout; }
 | |
|             set { _device.ReadTimeout = value; }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 포트이름
 | |
|         /// </summary>
 | |
|         [Description("시리얼 포트 이름")]
 | |
|         [Category("설정"), DisplayName("Port Name")]
 | |
|         public string PortName { get { return _device.PortName; } set { _device.PortName = value; } }
 | |
|         /// <summary>
 | |
|         /// RS232 Baud Rate
 | |
|         /// </summary>
 | |
|         [Description("시리얼 포트 전송 속도")]
 | |
|         [Category("설정"), DisplayName("Baud Rate")]
 | |
|         public int BaudRate { get { return _device.BaudRate; } set { _device.BaudRate = value; } }
 | |
| 
 | |
|         #endregion
 | |
| 
 | |
|         #region "Method"
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 쓰기버퍼비우기
 | |
|         /// </summary>
 | |
|         public void ClearWriteBuffer()
 | |
|         {
 | |
|             if (_device.IsOpen) _device.DiscardOutBuffer();
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 읽기버퍼비우기
 | |
|         /// </summary>
 | |
|         public void ClearReadBuffer()
 | |
|         {
 | |
|             if (_device.IsOpen) _device.DiscardInBuffer();
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 장치의 초기화작업을 수행합니다.(이 값은 기본값으로 true가 무조건 설정됩니다) 오버라이드하여 각 상황에 맞게 처리하세요.
 | |
|         /// </summary>
 | |
|         protected virtual void Init()
 | |
|         {
 | |
|             if (!IsOpen) _isinit = false;
 | |
|             else _isinit = true;
 | |
|         }
 | |
| 
 | |
| 
 | |
| 
 | |
|         protected virtual Boolean CustomParser(byte[] buf, out byte[] remainBuffer)
 | |
|         {
 | |
|             remainBuffer = new byte[] { };
 | |
|             return true;
 | |
|         }
 | |
| 
 | |
|         #region "Raise Message Events (임의로 메세지를 발생시킵니다)"
 | |
| 
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 보낸메세지 이벤트를 발생
 | |
|         /// </summary>
 | |
|         /// <param name="data">String Data</param>
 | |
|         public void RaiseSendData(string data)
 | |
|         {
 | |
|             RaiseSendData(System.Text.Encoding.Default.GetBytes(data));
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 보낸메세지 이벤트를 발생 합니다.
 | |
|         /// </summary>
 | |
|         /// <param name="data">Byte Array</param>
 | |
|         public void RaiseSendData(byte[] data)
 | |
|         {
 | |
|             try
 | |
|             {
 | |
|                 if (SendData != null) SendData(this, new ReceiveDataEventArgs(data));
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 RaiseMessage("RaiseSendData:" + ex.Message, true);
 | |
|             }
 | |
| 
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 지정한 데이터로 바코드가 수신된것처럼 발생시킵니다.
 | |
|         /// </summary>
 | |
|         /// <param name="b"></param>
 | |
|         public void RaiseRecvData(byte[] b)
 | |
|         {
 | |
|             byte[] Data;
 | |
| 
 | |
|             if (RemoveCRLFNULL) //제거해야하는경우에만 처리 170822
 | |
|                 Data = RemoveCRLF(b);
 | |
|             else
 | |
|                 Data = b;
 | |
| 
 | |
|             try
 | |
|             {
 | |
|                 if (ReceiveData != null) ReceiveData(this, new ReceiveDataEventArgs(Data));
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 RaiseMessage("RaiseDataMessage:" + ex.Message, true);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 지정한 데이터로 바코드가 수신된것처럼 발생시킵니다.
 | |
|         /// </summary>
 | |
|         /// <param name="data"></param>
 | |
|         public void RaiseRecvData(string data)
 | |
|         {
 | |
|             RaiseRecvData(System.Text.Encoding.Default.GetBytes(data));
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 메세지이벤트를 발생합니다. 오류메세지일 경우 2번째 파라미터를 true 로 입력하세요.
 | |
|         /// </summary>
 | |
|         /// <param name="message">메세지</param>
 | |
|         /// <param name="isError">오류라면 True로 설정하세요. 기본값=False</param>
 | |
|         public void RaiseMessage(string message, Boolean isError = false)
 | |
|         {
 | |
|             if (isError) errorMessage = message; //170920
 | |
|             if (Message != null) Message(this, new MessageEventArgs(isError, message));
 | |
|         }
 | |
| 
 | |
| 
 | |
|         #endregion
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 포트열기(실패시 False)를 반환
 | |
|         /// </summary>
 | |
|         public virtual Boolean Open(Boolean runInit = true)
 | |
|         {
 | |
|             try
 | |
|             {
 | |
|                 _device.Open();
 | |
|                 if (_device.IsOpen)
 | |
|                 {
 | |
|                     Init();
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     _isinit = false;
 | |
|                 }
 | |
| 
 | |
|                 return _isinit;
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 errorMessage = ex.Message;
 | |
|                 RaiseMessage(ex.Message, true);
 | |
|                 return false;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 포트닫기
 | |
|         /// </summary>
 | |
|         public virtual void Close(Boolean PortClose = true)
 | |
|         {
 | |
|             if (_device != null && _device.IsOpen)
 | |
|             {
 | |
|                 _isinit = false;
 | |
|                 _device.DiscardInBuffer();
 | |
|                 _device.DiscardOutBuffer();
 | |
|                 if (PortClose) _device.Close(); //dispose에서는 포트를 직접 클리어하지 않게 해뒀다.
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 메세지내용중 Cr,LF 를 제거합니다.
 | |
|         /// </summary>
 | |
|         protected byte[] RemoveCRLF(byte[] src)
 | |
|         {
 | |
|             List<byte> bcdbuf = new List<byte>();
 | |
|             foreach (byte by in src)
 | |
|             {
 | |
|                 if (by == 0x00 || by == 0x0d || by == 0x0a || by == 0x02 || by == 0x03) continue;
 | |
|                 bcdbuf.Add(by);
 | |
|             }
 | |
|             return bcdbuf.ToArray();
 | |
|         }
 | |
| 
 | |
|         #endregion
 | |
| 
 | |
|         #region "Method Write Data"
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 포트에 쓰기(barcode_DataReceived 이벤트로 메세지수신)
 | |
|         /// </summary>
 | |
|         public virtual Boolean WriteData(string data)
 | |
|         {
 | |
|             byte[] buf = System.Text.Encoding.Default.GetBytes(data);
 | |
|             return WriteData(buf);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 포트에 쓰기 반환될 때까지 기다림(SyncTimeOut 값까지 기다림)
 | |
|         /// </summary>
 | |
|         public virtual byte[] WriteDataSync(string data)
 | |
|         {
 | |
|             byte[] buf = System.Text.Encoding.Default.GetBytes(data);
 | |
|             return WriteDataSync(buf);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// _buffer를 클리어하고 입력된 데이터를 버퍼에 추가합니다.
 | |
|         /// </summary>
 | |
|         /// <param name="buf"></param>
 | |
|         public void setRecvBuffer(byte[] buf)
 | |
|         {
 | |
|             this._buffer.Clear();
 | |
|             this._buffer.AddRange(buf);
 | |
|         }
 | |
| 
 | |
|         public int WriteError = 0;
 | |
|         public string WriteErrorMessage = string.Empty;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 포트에 쓰기 반환될 때까지 기다림(SyncTimeOut 값까지 기다림)
 | |
|         /// </summary>
 | |
|         public virtual byte[] WriteDataSync(byte[] data, Boolean useReset = true)
 | |
|         {
 | |
|             errorMessage = string.Empty;
 | |
|             _isSync = true;
 | |
|             byte[] recvbuf = null;
 | |
|          //   Boolean bRet = false;
 | |
| 
 | |
|             //171214
 | |
|             if (!IsOpen)
 | |
|             {
 | |
|                 errorMessage = "Port Closed";
 | |
|                 return null;
 | |
|             }
 | |
| 
 | |
|             //171205 : 타임아웃시간추가
 | |
|             if (useReset)
 | |
|             {
 | |
|                 if (!_mre.WaitOne(3000))
 | |
|                 {
 | |
|                     errorMessage = string.Format("WriteDataSync:MRE:WaitOne:TimeOut 3000ms");
 | |
|                     RaiseMessage(errorMessage, true);
 | |
|                     return null;
 | |
|                 }
 | |
| 
 | |
|                 _mre.Reset();
 | |
|             }
 | |
| 
 | |
| 
 | |
|             //save last command
 | |
|             lastSendTime = DateTime.Now;
 | |
|             if (lastSendBuffer == null) lastSendBuffer = new byte[data.Length]; //171113
 | |
|             else Array.Resize(ref lastSendBuffer, data.Length);
 | |
|             Array.Copy(data, lastSendBuffer, data.Length);
 | |
|             Boolean sendOK = false;
 | |
| 
 | |
|             try
 | |
|             {
 | |
|                 _device.DiscardInBuffer();
 | |
|                 _device.DiscardOutBuffer();
 | |
|                 _buffer.Clear();    //171205
 | |
|                 _device.Write(data, 0, data.Length);
 | |
|                 WriteError = 0;
 | |
|                 WriteErrorMessage = string.Empty;
 | |
|                 sendOK = true;
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 WriteError += 1;
 | |
|                 WriteErrorMessage = ex.Message;
 | |
|             }
 | |
| 
 | |
|             if (sendOK)
 | |
|             {
 | |
|                 try
 | |
|                 {
 | |
|                     //171113
 | |
|                     if (EnableTxMessage && SendData != null) SendData(this, new ReceiveDataEventArgs(data));
 | |
| 
 | |
|                     _wat.Restart();
 | |
|                     Boolean bTimeOut = false;
 | |
|                     _buffer.Clear();
 | |
|                     Boolean bDone = false;
 | |
|                     while (!bDone)
 | |
|                     {
 | |
|                         if (_wat.ElapsedMilliseconds > WriteTimeout)
 | |
|                         {
 | |
|                             errorMessage = "(Sync)WriteTimeOut";
 | |
|                             bTimeOut = true;
 | |
|                             break;
 | |
|                         }
 | |
|                         else
 | |
|                         {
 | |
|                             int RecvCnt = _device.BytesToRead;
 | |
|                             if (RecvCnt > 0)
 | |
|                             {
 | |
|                                 byte[] rbuf = new byte[RecvCnt];
 | |
|                                 _device.Read(rbuf, 0, rbuf.Length);
 | |
|                                 if (_term == eTerminal.CustomParser)
 | |
|                                 {
 | |
|                                     byte[] remainBuffer;
 | |
|                                 Repeat:
 | |
|                                     if (CustomParser(rbuf, out remainBuffer))
 | |
|                                     {
 | |
|                                         RaiseRecvData(_buffer.ToArray());
 | |
|                                         bDone = true;
 | |
|                                         if (remainBuffer != null && remainBuffer.Length > 0)
 | |
|                                         {
 | |
|                                             rbuf = new byte[remainBuffer.Length];
 | |
|                                             Array.Copy(remainBuffer, rbuf, rbuf.Length);
 | |
|                                             goto Repeat;
 | |
|                                         }
 | |
|                                     }
 | |
|                                 }
 | |
|                                 else
 | |
|                                 {
 | |
|                                     foreach (byte b in rbuf)
 | |
|                                     {
 | |
|                                         switch (_term)
 | |
|                                         {
 | |
|                                             case eTerminal.CR:
 | |
|                                                 if (b == 0x0D)
 | |
|                                                 {
 | |
|                                                     bDone = true;
 | |
|                                                     break;
 | |
|                                                 }
 | |
|                                                 else _buffer.Add(b);
 | |
|                                                 break;
 | |
|                                             case eTerminal.LF:
 | |
|                                                 if (b == 0x0A)
 | |
|                                                 {
 | |
|                                                     bDone = true;
 | |
|                                                     break;
 | |
|                                                 }
 | |
|                                                 else _buffer.Add(b);
 | |
|                                                 break;
 | |
|                                             case eTerminal.CrLf:
 | |
|                                                 if (b == 0x0A)
 | |
|                                                 {
 | |
|                                                     bDone = true;
 | |
|                                                     break;
 | |
|                                                 }
 | |
|                                                 else if (b == 0x0d)
 | |
|                                                 {
 | |
|                                                     //pass
 | |
|                                                 }
 | |
|                                                 else
 | |
|                                                 {
 | |
|                                                     _buffer.Add(b);
 | |
|                                                 }
 | |
|                                                 break;
 | |
|                                             case eTerminal.Length:
 | |
|                                                 _buffer.Add(b);
 | |
|                                                 if (_buffer.Count == MaxDataLength)
 | |
|                                                 {
 | |
|                                                     bDone = true;
 | |
|                                                     break;
 | |
|                                                 }
 | |
|                                                 else if (_buffer.Count > MaxDataLength)
 | |
|                                                 {
 | |
|                                                     RaiseMessage("Buffer Length Error " + _buffer.Count.ToString() + "/" + MaxDataLength.ToString(), true);
 | |
|                                                     _buffer.Clear();
 | |
|                                                 }
 | |
| 
 | |
|                                                 break;
 | |
|                                             case eTerminal.ETX:
 | |
| 
 | |
|                                                 if (b == STX)
 | |
|                                                 {
 | |
|                                                     _buffer.Clear();
 | |
|                                                 }
 | |
|                                                 else if (b == ETX)
 | |
|                                                 {
 | |
|                                                     bDone = true;
 | |
|                                                     break;
 | |
|                                                 }
 | |
|                                                 else _buffer.Add(b);
 | |
|                                                 break;
 | |
|                                         }
 | |
|                                     }
 | |
|                                 }
 | |
|                             }
 | |
| 
 | |
|                         }
 | |
|                     }
 | |
|                     _wat.Stop();
 | |
|                     if (!bTimeOut)
 | |
|                     {
 | |
|                         recvbuf = _buffer.ToArray();
 | |
|                         //bRet = true;
 | |
|                     }
 | |
|                 }
 | |
|                 catch (Exception ex)
 | |
|                 {
 | |
|                     errorMessage = ex.Message;
 | |
|                     //bRet = false;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if (useReset)
 | |
|                 _mre.Set();//release
 | |
| 
 | |
|             //syncmode off
 | |
|             _isSync = false;
 | |
|             return recvbuf;
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 포트에 쓰기(barcode_DataReceived 이벤트로 메세지수신)
 | |
|         /// </summary>
 | |
|         public virtual Boolean WriteData(byte[] data)
 | |
|         {
 | |
|             Boolean bRet = false;
 | |
| 
 | |
|             //171205 : 타임아웃시간추가
 | |
|             if (!_mre.WaitOne(3000))
 | |
|             {
 | |
|                 errorMessage = string.Format("WriteData:MRE:WaitOne:TimeOut 3000ms");
 | |
|                 RaiseMessage(errorMessage, true);
 | |
|                 return false;
 | |
|             }
 | |
| 
 | |
|             _mre.Reset();
 | |
| 
 | |
|             //Array.Resize(ref data, data.Length + 2);
 | |
| 
 | |
|             try
 | |
|             {
 | |
|                 lastSendTime = DateTime.Now;
 | |
|                 if (lastSendBuffer == null) lastSendBuffer = new byte[data.Length]; //171113
 | |
|                 else Array.Resize(ref lastSendBuffer, data.Length);
 | |
|                 Array.Copy(data, lastSendBuffer, data.Length);
 | |
|                 _device.Write(data, 0, data.Length);
 | |
| 
 | |
|                 //171113
 | |
|                 if (EnableTxMessage && SendData != null) SendData(this, new ReceiveDataEventArgs(data));
 | |
| 
 | |
|                 bRet = true;
 | |
|                 WriteError = 0;
 | |
|                 WriteErrorMessage = string.Empty;
 | |
|             }
 | |
|             catch (Exception ex)
 | |
|             {
 | |
|                 // this.isinit = false;
 | |
|                 RaiseMessage(ex.Message, true);// if (ReceivceData != null) ReceivceData(this, true, ex.Message);
 | |
|                 bRet = false;
 | |
|                 WriteError += 1; //연속쓰기오류횟수
 | |
|                 WriteErrorMessage = ex.Message;
 | |
|             }
 | |
|             finally
 | |
|             {
 | |
|                 _mre.Set();
 | |
|             }
 | |
|             return bRet;
 | |
|         }
 | |
| 
 | |
|         #endregion
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 장치를 생성합니다.
 | |
|         /// </summary>
 | |
|         public Barcode() : this(0) { }
 | |
|         /// <summary>
 | |
|         /// 지정한ID를 가진 장치를 생성합니다.
 | |
|         /// </summary>
 | |
|         /// <param name="id"></param>
 | |
|         public Barcode(int id)
 | |
|         {
 | |
|             _mre = new ManualResetEvent(true);
 | |
|             this.ID = id;
 | |
|             this._device = new System.IO.Ports.SerialPort();
 | |
|             _device.DataReceived += barcode_DataReceived;
 | |
|             _device.ErrorReceived += barcode_ErrorReceived;
 | |
|             _device.ReadTimeout = 2000;
 | |
|             _device.WriteTimeout = 2000;
 | |
|             _term = eTerminal.CrLf;
 | |
|             STX = 0x02;
 | |
|             ETX = 0x03;
 | |
|             RemoveCRLFNULL = false;
 | |
|             EnableTxMessage = false;
 | |
|         }
 | |
| 
 | |
|         ~Barcode()
 | |
|         {
 | |
|             Dispose();
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// close를 호출합니다.
 | |
|         /// </summary>
 | |
|         public virtual void Dispose()
 | |
|         {
 | |
|             if (!isDisposed) //180219
 | |
|             {
 | |
|                 _isinit = false;
 | |
|                 _device.DataReceived -= barcode_DataReceived;
 | |
|                 _device.ErrorReceived -= barcode_ErrorReceived;
 | |
|                 //Close(false);
 | |
|                 isDisposed = true;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | 
