using System; using System.IO.Ports; namespace leak_test_project.Infrastructure { /// /// RS232 시리얼 통신을 담당하는 구현체. /// 연결 안정성 강화를 위한 예외 처리 및 상태 감지 로직 포함. /// public class SerialProvider : ICommunication, IDisposable { private SerialPort _serialPort; private bool _disposed = false; public string Name { get; private set; } public bool IsOpen => _serialPort != null && !_disposed && _serialPort.IsOpen; public event EventHandler DataReceived; public event EventHandler ConnectionStatusChanged; public SerialProvider(string portName, int baudRate) { Name = portName; _serialPort = new SerialPort(portName, baudRate, Parity.None, 8, StopBits.One); _serialPort.Handshake = Handshake.None; _serialPort.DtrEnable = true; // 터미널 프로그램(포트몬)과 동일하게 제어 신호 활성화 _serialPort.RtsEnable = true; _serialPort.ReadTimeout = 500; _serialPort.WriteTimeout = 500; _serialPort.DataReceived += (s, e) => { try { string data = _serialPort.ReadExisting(); if (!string.IsNullOrEmpty(data)) DataReceived?.Invoke(this, data); } catch (Exception ex) { Console.WriteLine($"[Serial Error] Read error on {Name}: {ex.Message}"); } }; // 기기가 끊겼을 때 감지 (일부 환경에서는 PinChanged 등으로 감지 가능) _serialPort.ErrorReceived += (s, e) => { ConnectionStatusChanged?.Invoke(this, false); }; } public bool Open() { if (_disposed) return false; try { if (IsOpen) return true; _serialPort.Open(); ConnectionStatusChanged?.Invoke(this, true); return true; } catch (Exception ex) { Console.WriteLine($"[Serial Error] Failed to open {Name}: {ex.Message}"); ConnectionStatusChanged?.Invoke(this, false); return false; } } public void Close() { try { if (IsOpen) { _serialPort.Close(); ConnectionStatusChanged?.Invoke(this, false); } } catch (Exception ex) { Console.WriteLine($"[Serial Error] Error closing {Name}: {ex.Message}"); } } public bool Write(string data) { if (!IsOpen) return false; try { _serialPort.Write(data); return true; } catch (Exception ex) { Console.WriteLine($"[Serial Error] Write error on {Name}: {ex.Message}"); return false; } } public void ClearBuffer() { if (IsOpen) { try { _serialPort.DiscardInBuffer(); _serialPort.DiscardOutBuffer(); _serialPort.ReadExisting(); } catch { } } } public void Dispose() { if (!_disposed) { _disposed = true; Close(); _serialPort?.Dispose(); _serialPort = null; } } } }