using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports; // 시리얼 통신
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
/*
* 데이터를 읽어요
* 식별자에 맞게 파싱해요
* 객체에 넣어요 (Vo객체로 매핑)
* ui 바인딩해요
* db 업데이트해요
*/
namespace Honeywell
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
comboBox1.DataSource = SerialPort.GetPortNames(); // 시리얼 포트 목록 불러오기
comboBox1.SelectedIndex = 0; // 기본값=첫번째꺼
}
public Vo UiVer = new Vo(); // ui 바인딩용 객체 인스턴스
public Vo DbVer = new Vo(); // db 업데이트용 객체 인스턴스
// [ 연결부 ] /////////////////////////////////////////////////////////////////////
private void btnConnect_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(comboBox1.Text))
{
MessageBox.Show("포트를 선택하세요.");
return;
}
try
{
if (!serialPort1.IsOpen)
{
serialPort1.PortName = comboBox1.Text;
serialPort1.BaudRate = 115200;
serialPort1.DataBits = 8;
serialPort1.StopBits = StopBits.One;
serialPort1.Parity = Parity.None;
serialPort1.DataReceived += serialPort1_DataReceived;
serialPort1.Open();
comboBox1.Enabled = false; // 버튼 비활성화
MessageBox.Show("스캐너 연결 성공!");
}
}
catch (Exception ex)
{
MessageBox.Show("연결 실패: " + ex.Message);
}
}
private void btnDisconnect_Click(object sender, EventArgs e)
{
{
if (serialPort1.IsOpen) //시리얼포트가 열려 있으면
{
serialPort1.Close(); //시리얼포트 닫기
label_status.Text = "포트가 닫혔습니다.";
comboBox1.Enabled = true; //COM포트설정 콤보박스 활성화
}
else //시리얼포트가 닫혀 있으면
{
label_status.Text = "포트가 이미 닫혀 있습니다.";
}
}
}
// [ 데이터 ] /////////////////////////////////////////////////////////////////////
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string asciiString = ReadAscii(serialPort1); // 바이트를 아스키로 변환
HandleBarcodeData(asciiString); // 읽은 값을 넘김
}
private void HandleBarcodeData(string asciiString)
{
Vo parsedVo = ParseBarcode(asciiString); // 파싱해서 객체에 저장
// UI용
UiVer = parsedVo;
// UI 업데이트 (UI 스레드에서 실행)
this.Invoke(new Action(() => UpdateUI(UiVer)));
////////////////////////////////////////////////
// DB용
DbVer = new Vo
{
GTIN = parsedVo.GTIN,
Exp = parsedVo.Exp,
Lot = parsedVo.Lot,
Serial = parsedVo.Serial
};
// DB 저장
SaveToDatabase(DbVer);
}
private string ReadAscii(SerialPort port)
{
int bytes = port.BytesToRead; // 포트에 들어온 바이트를 가져와요
byte[] buffer = new byte[bytes]; // 바이트 배열에 담아요
port.Read(buffer, 0, bytes); // 버퍼를 바이트 크기만큼 읽어요
return Encoding.ASCII.GetString(buffer); // 아스키로 인코딩 후 string으로 형변환해서 반환
}
// [ 파싱 ] /////////////////////////////////////////////////////////////////////
private Vo ParseBarcode(string barcodeData)
{
Vo vo = new Vo();
// FNC1(ASCII 29) 기준으로 분리
string[] parts = barcodeData.Split('\x1D');
foreach (var part in parts)
{
if (string.IsNullOrWhiteSpace(part))
{
continue;
}
int index = 0;
while (index < part.Length)
{
// code = 식별자
string code = part.Substring(index, Math.Min(2, part.Length - index));
index += 2;
if (code == "01") // GTIN (고정 14자리)
{
int len = Math.Min(14, part.Length - index);
vo.GTIN = part.Substring(index, len);
index += len;
}
else if (code == "17") // 유효기간 (고정 6자리)
{
int len = Math.Min(6, part.Length - index);
vo.Exp = part.Substring(index, len);
index += len;
}
else if (code == "10") // LOT (가변, 나머지 전체)
{
vo.Lot = part.Substring(index);
break;
}
else if (code == "21") // SERIAL (가변, 나머지 전체)
{
vo.Serial = part.Substring(index);
break;
}
else
{
break;
}
}
}
return vo;
}
// 다음 AI 위치 찾는 헬퍼 메서드
private int FindNextAIIndex(string part, int start)
{
// 다음 AI가 시작되는 위치 찾기 (보통 숫자 2자리로 시작)
for (int i = start; i < part.Length - 1; i++)
{
if (char.IsDigit(part[i]) && char.IsDigit(part[i + 1]))
{
string possibleAi = part.Substring(i, 2);
if (possibleAi == "01" || possibleAi == "10" || possibleAi == "17" || possibleAi == "21")
return i;
}
}
return part.Length; // 다음 AI가 없으면 끝까지 읽기
}
// [ UI 바인딩 ] /////////////////////////////////////////////////////////////////////
private void UpdateUI(Vo vo)
{
textBoxGtin.Text = vo.GTIN;
textBoxExp.Text = vo.Exp;
textBoxLot.Text = vo.Lot;
textBoxSerial.Text = vo.Serial;
// 디버깅용
Console.WriteLine($"GTIN : {vo.GTIN}");
Console.WriteLine($"EXP : {vo.Exp}");
Console.WriteLine($"LOT : {vo.Lot}");
Console.WriteLine($"SERIAL : {vo.Serial}");
}
// [ DB ] /////////////////////////////////////////////////////////////////////
private void btnSend_Click(object sender, EventArgs e)
{
SaveToDatabase(DbVer);
}
private void SaveToDatabase(Vo vo)
{
// DB 연결 및 INSERT
}
}
}