diff --git a/Cs_HMI/SubProject/EnigProtocol b/Cs_HMI/SubProject/EnigProtocol
index 070aa84..e8cae2c 160000
--- a/Cs_HMI/SubProject/EnigProtocol
+++ b/Cs_HMI/SubProject/EnigProtocol
@@ -1 +1 @@
-Subproject commit 070aa848c96ec7097ae70b5a12f19f328fb6ae03
+Subproject commit e8cae2c4ee72b509f47a48bd7bc7d416d45e6a78
diff --git a/Cs_HMI/TestProject/Test_ACS/AppSettings.cs b/Cs_HMI/TestProject/Test_ACS/AppSettings.cs
new file mode 100644
index 0000000..49ef15b
--- /dev/null
+++ b/Cs_HMI/TestProject/Test_ACS/AppSettings.cs
@@ -0,0 +1,67 @@
+using System;
+using System.IO;
+using System.Windows.Forms;
+using Newtonsoft.Json;
+
+namespace Test_ACS
+{
+ ///
+ /// 애플리케이션 설정을 관리하는 클래스
+ ///
+ public class AppSettings
+ {
+ public string LastPort { get; set; } = "COM1";
+ public string LastBaudRate { get; set; } = "9600";
+ public string LastRFID { get; set; } = "0001";
+ public string LastAlias { get; set; } = "CHARGER1";
+ public int LastAGV { get; set; } = 11;
+
+ private static string GetConfigFilePath()
+ {
+ // 실행 파일과 같은 폴더에 같은 이름으로 .config 파일 생성
+ string exePath = Application.ExecutablePath;
+ string exeName = Path.GetFileNameWithoutExtension(exePath);
+ string configPath = Path.Combine(Path.GetDirectoryName(exePath), exeName + ".config");
+ return configPath;
+ }
+
+ ///
+ /// 설정 파일을 로드합니다
+ ///
+ public static AppSettings Load()
+ {
+ try
+ {
+ string configPath = GetConfigFilePath();
+ if (File.Exists(configPath))
+ {
+ string json = File.ReadAllText(configPath);
+ return JsonConvert.DeserializeObject(json);
+ }
+ }
+ catch (Exception)
+ {
+ // 로드 실패 시 기본값 반환
+ }
+
+ return new AppSettings();
+ }
+
+ ///
+ /// 설정을 파일에 저장합니다
+ ///
+ public void Save()
+ {
+ try
+ {
+ string configPath = GetConfigFilePath();
+ string json = JsonConvert.SerializeObject(this, Formatting.Indented);
+ File.WriteAllText(configPath, json);
+ }
+ catch (Exception)
+ {
+ // 저장 실패 시 무시
+ }
+ }
+ }
+}
diff --git a/Cs_HMI/TestProject/Test_ACS/CHANGELOG.md b/Cs_HMI/TestProject/Test_ACS/CHANGELOG.md
new file mode 100644
index 0000000..4387e2b
--- /dev/null
+++ b/Cs_HMI/TestProject/Test_ACS/CHANGELOG.md
@@ -0,0 +1,162 @@
+# Test_ACS 변경 이력
+
+## v1.4.0 (2025-01-12)
+
+### 설정 파일 저장 방식 변경
+- **실행 폴더에 설정 파일 저장**
+ - 이전: 사용자 프로파일 폴더 (`%LOCALAPPDATA%`)
+ - 변경: 실행 파일과 같은 폴더에 `Test_ACS.config` 저장
+ - 형식: JSON 형식으로 저장 (가독성 향상)
+
+### 코드 개선
+- `AppSettings` 클래스 신규 생성
+ - JSON 직렬화/역직렬화 지원
+ - 실행 파일 경로 자동 감지
+ - 설정 파일 자동 생성 및 로드
+- Newtonsoft.Json 패키지 참조 추가
+
+### 사용성 개선
+- 설정 파일을 직접 편집 가능 (JSON 형식)
+- 프로그램 이동 시에도 설정 파일 함께 이동
+- 여러 버전 동시 사용 가능 (각 폴더별 독립 설정)
+
+---
+
+## v1.3.0 (2025-01-12)
+
+### 신규 기능
+- **AGV 상태 실시간 표시**
+ - AGV 상태 그룹박스 추가
+ - 8가지 AGV 상태 정보 표시:
+ - 모드 (수동/자동)
+ - 실행상태 (정지/실행/에러)
+ - 방향 (직진/좌회전/우회전/마크정지)
+ - 도달완료 (OFF/ON)
+ - 충전 상태 (OFF/ON)
+ - 카트 감지 (없음/있음/알 수 없음)
+ - 리프트 위치 (하강/상승/알 수 없음)
+ - 현재 RFID 태그 번호 (6자리)
+ - 상태별 색상 표시로 직관적 모니터링
+ - AGV Status 메시지(cmd=3) 자동 수신 및 업데이트
+
+### UI 개선
+- AGV 상태 그룹박스 추가 (2열 x 4행 레이아웃)
+- 메인 폼 크기 확장 (539 → 588 픽셀)
+- 상태별 색상 구분:
+ - 수동(파란색) / 자동(녹색)
+ - 정지(회색) / 실행(녹색) / 에러(빨간색)
+ - 충전중(주황색)
+
+### 프로토콜 업데이트
+- ENIGProtocol ReadMe.MD 수정
+ - AGV Status 프로토콜 정의 명확화 (총 13바이트)
+ - LastTag 필드 크기 수정 (4바이트 → 6바이트)
+ - CurrentPath 필드 제거 (실제 구현과 일치)
+
+### 코드 개선
+- `UpdateAGVStatus()` 메서드 구현
+- Status 메시지 수신 처리 로직 추가
+- 스레드 안전성 보장 (InvokeRequired 체크)
+- 데이터 유효성 검사 추가
+
+---
+
+## v1.2.0 (2025-01-12)
+
+### 신규 기능
+- **설정 자동 저장/불러오기 기능**
+ - 마지막 사용 COM 포트 자동 저장
+ - 마지막 사용 보레이트 자동 저장
+ - 마지막 입력 RFID 번호 자동 저장
+ - 마지막 입력 별칭 자동 저장
+ - 마지막 선택 AGV (11/12) 자동 저장
+ - 프로그램 종료 시 자동 저장
+ - 프로그램 시작 시 자동 불러오기
+
+### 구현 상세
+- **Settings.settings 파일 확장**
+ - LastPort (string)
+ - LastBaudRate (string)
+ - LastRFID (string)
+ - LastAlias (string)
+ - LastAGV (int)
+
+- **자동 저장 이벤트**
+ - COM 포트 선택 변경 시
+ - 보레이트 텍스트 변경 시
+ - RFID 번호 텍스트 변경 시
+ - 별칭 텍스트 변경 시
+ - AGV 선택 변경 시
+ - 프로그램 종료 시 (OnFormClosing)
+
+- **자동 불러오기**
+ - 프로그램 시작 시 LoadSettings() 호출
+ - 포트 목록 로드 후 마지막 설정 적용
+
+### 사용자 경험 개선
+- 프로그램 재실행 시 이전 설정 자동 복원
+- 설정 저장/불러오기 상태 로그 표시
+- 에러 발생 시 로그에 에러 메시지 표시
+
+---
+
+## v1.1.0 (2025-01-12)
+
+### 신규 기능
+- **GotoAlias 명령어 추가**
+ - 별칭(Alias)을 사용한 AGV 이동 명령 지원
+ - RFID 번호 대신 의미 있는 이름으로 목적지 지정 가능
+ - 예: "CHARGER1", "BUFFER2", "STATION_A" 등
+
+### UI 개선
+- **별칭 입력 필드 추가**
+ - 위치: RFID 입력 필드 아래
+ - 기본값: "CHARGER1"
+
+- **GotoAlias 버튼 추가**
+ - 위치: Goto 버튼 우측
+ - 버튼명: "별칭 이동 (GotoAlias)"
+
+- **레이아웃 최적화**
+ - RFID 번호 입력: 라인 1
+ - 별칭 입력: 라인 2
+ - SetCurrent / GotoAlias 버튼: 라인 3
+ - Goto / GotoAlias 버튼: 라인 4
+ - Stop / Reset 버튼: 라인 5
+ - MarkStop 버튼 및 체크박스: 라인 6
+ - 수동 제어 / 리프트 제어: 하단 그룹
+
+### 프로토콜 변경
+- **AGVCommandHE Enum 확장**
+ - GotoAlias = 107 추가
+ - 데이터 형식: TargetID(2 hex) + Alias(ASCII string)
+
+### 코드 개선
+- `btnGotoAlias_Click` 이벤트 핸들러 구현
+- 별칭 유효성 검사 (빈 문자열 체크)
+- ASCII → HEX 변환 로직 추가
+
+### 문서 업데이트
+- README.md에 GotoAlias 사용법 추가
+- 프로토콜 명령어 표에 GotoAlias 추가
+- 버전 이력 업데이트
+
+---
+
+## v1.0.0 (2025-01-11)
+
+### 초기 릴리즈
+- ACS 시뮬레이터 기본 구현
+- ENIGProtocol 프로젝트 참조
+- RS232 통신 지원
+- 7가지 기본 ACS 명령어:
+ - SetCurrent (현재 위치 설정)
+ - Goto (RFID 이동)
+ - Stop (정지)
+ - Reset (에러 리셋)
+ - Manual (수동 제어)
+ - MarkStop (마크센서 정지)
+ - LiftControl (리프트 제어)
+- AGV 선택 기능 (AGV1/AGV2)
+- 로그 시스템 (TX/RX/Info 탭)
+- COM 포트 관리 (연결/해제/새로고침)
diff --git a/Cs_HMI/TestProject/Test_ACS/MainForm.Designer.cs b/Cs_HMI/TestProject/Test_ACS/MainForm.Designer.cs
new file mode 100644
index 0000000..5e4ac2d
--- /dev/null
+++ b/Cs_HMI/TestProject/Test_ACS/MainForm.Designer.cs
@@ -0,0 +1,828 @@
+namespace Test_ACS
+{
+ partial class MainForm
+ {
+ private System.ComponentModel.IContainer components = null;
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ private void InitializeComponent()
+ {
+ this.grpConnection = new System.Windows.Forms.GroupBox();
+ this.btnRefresh = new System.Windows.Forms.Button();
+ this.btnConnect = new System.Windows.Forms.Button();
+ this.txtBaudRate = new System.Windows.Forms.TextBox();
+ this.cmbPort = new System.Windows.Forms.ComboBox();
+ this.lblBaudRate = new System.Windows.Forms.Label();
+ this.lblPort = new System.Windows.Forms.Label();
+ this.grpAGV = new System.Windows.Forms.GroupBox();
+ this.rbAGV2 = new System.Windows.Forms.RadioButton();
+ this.rbAGV1 = new System.Windows.Forms.RadioButton();
+ this.grpCommands = new System.Windows.Forms.GroupBox();
+ this.grpLift = new System.Windows.Forms.GroupBox();
+ this.btnLiftStop = new System.Windows.Forms.Button();
+ this.btnLiftDown = new System.Windows.Forms.Button();
+ this.btnLiftUp = new System.Windows.Forms.Button();
+ this.grpManual = new System.Windows.Forms.GroupBox();
+ this.btnManual = new System.Windows.Forms.Button();
+ this.numRuntime = new System.Windows.Forms.NumericUpDown();
+ this.lblRuntime = new System.Windows.Forms.Label();
+ this.cmbSpeed = new System.Windows.Forms.ComboBox();
+ this.lblSpeed = new System.Windows.Forms.Label();
+ this.cmbDirection = new System.Windows.Forms.ComboBox();
+ this.lblDirection = new System.Windows.Forms.Label();
+ this.chkMarkStop = new System.Windows.Forms.CheckBox();
+ this.btnMarkStop = new System.Windows.Forms.Button();
+ this.btnReset = new System.Windows.Forms.Button();
+ this.btnStop = new System.Windows.Forms.Button();
+ this.btnGotoAlias = new System.Windows.Forms.Button();
+ this.btnGoto = new System.Windows.Forms.Button();
+ this.btnSetCurrent = new System.Windows.Forms.Button();
+ this.txtAlias = new System.Windows.Forms.TextBox();
+ this.lblAlias = new System.Windows.Forms.Label();
+ this.txtRFID = new System.Windows.Forms.TextBox();
+ this.lblRFID = new System.Windows.Forms.Label();
+ this.grpLogs = new System.Windows.Forms.GroupBox();
+ this.tabLogs = new System.Windows.Forms.TabControl();
+ this.tabRX = new System.Windows.Forms.TabPage();
+ this.txtRxLog = new System.Windows.Forms.TextBox();
+ this.tabTX = new System.Windows.Forms.TabPage();
+ this.txtTxLog = new System.Windows.Forms.TextBox();
+ this.tabInfo = new System.Windows.Forms.TabPage();
+ this.txtInfoLog = new System.Windows.Forms.TextBox();
+ this.grpAGVStatus = new System.Windows.Forms.GroupBox();
+ this.lblLastTagValue = new System.Windows.Forms.Label();
+ this.lblLastTag = new System.Windows.Forms.Label();
+ this.lblLiftStValue = new System.Windows.Forms.Label();
+ this.lblLiftSt = new System.Windows.Forms.Label();
+ this.lblCartStValue = new System.Windows.Forms.Label();
+ this.lblCartSt = new System.Windows.Forms.Label();
+ this.lblChargeStValue = new System.Windows.Forms.Label();
+ this.lblChargeSt = new System.Windows.Forms.Label();
+ this.lblInpositionValue = new System.Windows.Forms.Label();
+ this.lblInposition = new System.Windows.Forms.Label();
+ this.lblDirectionValue = new System.Windows.Forms.Label();
+ this.lblRunStValue = new System.Windows.Forms.Label();
+ this.lblRunSt = new System.Windows.Forms.Label();
+ this.lblModeValue = new System.Windows.Forms.Label();
+ this.lblMode = new System.Windows.Forms.Label();
+ this.grpConnection.SuspendLayout();
+ this.grpAGV.SuspendLayout();
+ this.grpCommands.SuspendLayout();
+ this.grpLift.SuspendLayout();
+ this.grpManual.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.numRuntime)).BeginInit();
+ this.grpLogs.SuspendLayout();
+ this.tabLogs.SuspendLayout();
+ this.tabRX.SuspendLayout();
+ this.tabTX.SuspendLayout();
+ this.tabInfo.SuspendLayout();
+ this.grpAGVStatus.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // grpConnection
+ //
+ this.grpConnection.Controls.Add(this.btnRefresh);
+ this.grpConnection.Controls.Add(this.btnConnect);
+ this.grpConnection.Controls.Add(this.txtBaudRate);
+ this.grpConnection.Controls.Add(this.cmbPort);
+ this.grpConnection.Controls.Add(this.lblBaudRate);
+ this.grpConnection.Controls.Add(this.lblPort);
+ this.grpConnection.Location = new System.Drawing.Point(12, 12);
+ this.grpConnection.Name = "grpConnection";
+ this.grpConnection.Size = new System.Drawing.Size(260, 120);
+ this.grpConnection.TabIndex = 0;
+ this.grpConnection.TabStop = false;
+ this.grpConnection.Text = "연결 설정";
+ //
+ // btnRefresh
+ //
+ this.btnRefresh.Location = new System.Drawing.Point(179, 22);
+ this.btnRefresh.Name = "btnRefresh";
+ this.btnRefresh.Size = new System.Drawing.Size(70, 23);
+ this.btnRefresh.TabIndex = 5;
+ this.btnRefresh.Text = "새로고침";
+ this.btnRefresh.UseVisualStyleBackColor = true;
+ this.btnRefresh.Click += new System.EventHandler(this.btnRefresh_Click);
+ //
+ // btnConnect
+ //
+ this.btnConnect.Location = new System.Drawing.Point(15, 81);
+ this.btnConnect.Name = "btnConnect";
+ this.btnConnect.Size = new System.Drawing.Size(234, 30);
+ this.btnConnect.TabIndex = 4;
+ this.btnConnect.Text = "연결";
+ this.btnConnect.UseVisualStyleBackColor = true;
+ this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click);
+ //
+ // txtBaudRate
+ //
+ this.txtBaudRate.Location = new System.Drawing.Point(85, 53);
+ this.txtBaudRate.Name = "txtBaudRate";
+ this.txtBaudRate.Size = new System.Drawing.Size(164, 21);
+ this.txtBaudRate.TabIndex = 3;
+ this.txtBaudRate.Text = "9600";
+ this.txtBaudRate.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+ this.txtBaudRate.TextChanged += new System.EventHandler(this.txtBaudRate_TextChanged);
+ //
+ // cmbPort
+ //
+ this.cmbPort.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.cmbPort.FormattingEnabled = true;
+ this.cmbPort.Location = new System.Drawing.Point(85, 23);
+ this.cmbPort.Name = "cmbPort";
+ this.cmbPort.Size = new System.Drawing.Size(88, 20);
+ this.cmbPort.TabIndex = 2;
+ this.cmbPort.SelectedIndexChanged += new System.EventHandler(this.cmbPort_SelectedIndexChanged);
+ //
+ // lblBaudRate
+ //
+ this.lblBaudRate.AutoSize = true;
+ this.lblBaudRate.Location = new System.Drawing.Point(15, 56);
+ this.lblBaudRate.Name = "lblBaudRate";
+ this.lblBaudRate.Size = new System.Drawing.Size(57, 12);
+ this.lblBaudRate.TabIndex = 1;
+ this.lblBaudRate.Text = "보레이트:";
+ //
+ // lblPort
+ //
+ this.lblPort.AutoSize = true;
+ this.lblPort.Location = new System.Drawing.Point(15, 26);
+ this.lblPort.Name = "lblPort";
+ this.lblPort.Size = new System.Drawing.Size(66, 12);
+ this.lblPort.TabIndex = 0;
+ this.lblPort.Text = "COM 포트:";
+ //
+ // grpAGV
+ //
+ this.grpAGV.Controls.Add(this.rbAGV2);
+ this.grpAGV.Controls.Add(this.rbAGV1);
+ this.grpAGV.Location = new System.Drawing.Point(278, 12);
+ this.grpAGV.Name = "grpAGV";
+ this.grpAGV.Size = new System.Drawing.Size(200, 120);
+ this.grpAGV.TabIndex = 1;
+ this.grpAGV.TabStop = false;
+ this.grpAGV.Text = "AGV 선택";
+ //
+ // rbAGV2
+ //
+ this.rbAGV2.AutoSize = true;
+ this.rbAGV2.Location = new System.Drawing.Point(20, 60);
+ this.rbAGV2.Name = "rbAGV2";
+ this.rbAGV2.Size = new System.Drawing.Size(95, 16);
+ this.rbAGV2.TabIndex = 1;
+ this.rbAGV2.Text = "AGV2 (ID:12)";
+ this.rbAGV2.UseVisualStyleBackColor = true;
+ this.rbAGV2.CheckedChanged += new System.EventHandler(this.rbAGV2_CheckedChanged);
+ //
+ // rbAGV1
+ //
+ this.rbAGV1.AutoSize = true;
+ this.rbAGV1.Checked = true;
+ this.rbAGV1.Location = new System.Drawing.Point(20, 30);
+ this.rbAGV1.Name = "rbAGV1";
+ this.rbAGV1.Size = new System.Drawing.Size(95, 16);
+ this.rbAGV1.TabIndex = 0;
+ this.rbAGV1.TabStop = true;
+ this.rbAGV1.Text = "AGV1 (ID:11)";
+ this.rbAGV1.UseVisualStyleBackColor = true;
+ this.rbAGV1.CheckedChanged += new System.EventHandler(this.rbAGV1_CheckedChanged);
+ //
+ // grpCommands
+ //
+ this.grpCommands.Controls.Add(this.grpLift);
+ this.grpCommands.Controls.Add(this.grpManual);
+ this.grpCommands.Controls.Add(this.chkMarkStop);
+ this.grpCommands.Controls.Add(this.btnMarkStop);
+ this.grpCommands.Controls.Add(this.btnReset);
+ this.grpCommands.Controls.Add(this.btnStop);
+ this.grpCommands.Controls.Add(this.btnGotoAlias);
+ this.grpCommands.Controls.Add(this.btnGoto);
+ this.grpCommands.Controls.Add(this.btnSetCurrent);
+ this.grpCommands.Controls.Add(this.txtAlias);
+ this.grpCommands.Controls.Add(this.lblAlias);
+ this.grpCommands.Controls.Add(this.txtRFID);
+ this.grpCommands.Controls.Add(this.lblRFID);
+ this.grpCommands.Location = new System.Drawing.Point(12, 138);
+ this.grpCommands.Name = "grpCommands";
+ this.grpCommands.Size = new System.Drawing.Size(466, 312);
+ this.grpCommands.TabIndex = 2;
+ this.grpCommands.TabStop = false;
+ this.grpCommands.Text = "ACS 명령";
+ //
+ // grpLift
+ //
+ this.grpLift.Controls.Add(this.btnLiftStop);
+ this.grpLift.Controls.Add(this.btnLiftDown);
+ this.grpLift.Controls.Add(this.btnLiftUp);
+ this.grpLift.Location = new System.Drawing.Point(240, 202);
+ this.grpLift.Name = "grpLift";
+ this.grpLift.Size = new System.Drawing.Size(210, 100);
+ this.grpLift.TabIndex = 9;
+ this.grpLift.TabStop = false;
+ this.grpLift.Text = "리프트 제어";
+ //
+ // btnLiftStop
+ //
+ this.btnLiftStop.Location = new System.Drawing.Point(135, 20);
+ this.btnLiftStop.Name = "btnLiftStop";
+ this.btnLiftStop.Size = new System.Drawing.Size(60, 70);
+ this.btnLiftStop.TabIndex = 2;
+ this.btnLiftStop.Text = "정지";
+ this.btnLiftStop.UseVisualStyleBackColor = true;
+ this.btnLiftStop.Click += new System.EventHandler(this.btnLiftStop_Click);
+ //
+ // btnLiftDown
+ //
+ this.btnLiftDown.Location = new System.Drawing.Point(70, 20);
+ this.btnLiftDown.Name = "btnLiftDown";
+ this.btnLiftDown.Size = new System.Drawing.Size(60, 70);
+ this.btnLiftDown.TabIndex = 1;
+ this.btnLiftDown.Text = "하강";
+ this.btnLiftDown.UseVisualStyleBackColor = true;
+ this.btnLiftDown.Click += new System.EventHandler(this.btnLiftDown_Click);
+ //
+ // btnLiftUp
+ //
+ this.btnLiftUp.Location = new System.Drawing.Point(5, 20);
+ this.btnLiftUp.Name = "btnLiftUp";
+ this.btnLiftUp.Size = new System.Drawing.Size(60, 70);
+ this.btnLiftUp.TabIndex = 0;
+ this.btnLiftUp.Text = "상승";
+ this.btnLiftUp.UseVisualStyleBackColor = true;
+ this.btnLiftUp.Click += new System.EventHandler(this.btnLiftUp_Click);
+ //
+ // grpManual
+ //
+ this.grpManual.Controls.Add(this.btnManual);
+ this.grpManual.Controls.Add(this.numRuntime);
+ this.grpManual.Controls.Add(this.lblRuntime);
+ this.grpManual.Controls.Add(this.cmbSpeed);
+ this.grpManual.Controls.Add(this.lblSpeed);
+ this.grpManual.Controls.Add(this.cmbDirection);
+ this.grpManual.Location = new System.Drawing.Point(15, 202);
+ this.grpManual.Name = "grpManual";
+ this.grpManual.Size = new System.Drawing.Size(215, 100);
+ this.grpManual.TabIndex = 8;
+ this.grpManual.TabStop = false;
+ this.grpManual.Text = "수동 제어";
+ //
+ // btnManual
+ //
+ this.btnManual.Location = new System.Drawing.Point(136, 16);
+ this.btnManual.Name = "btnManual";
+ this.btnManual.Size = new System.Drawing.Size(73, 74);
+ this.btnManual.TabIndex = 6;
+ this.btnManual.Text = "수동\r\n이동\r\n실행";
+ this.btnManual.UseVisualStyleBackColor = true;
+ this.btnManual.Click += new System.EventHandler(this.btnManual_Click);
+ //
+ // numRuntime
+ //
+ this.numRuntime.Location = new System.Drawing.Point(60, 66);
+ this.numRuntime.Maximum = new decimal(new int[] {
+ 255,
+ 0,
+ 0,
+ 0});
+ this.numRuntime.Name = "numRuntime";
+ this.numRuntime.Size = new System.Drawing.Size(70, 21);
+ this.numRuntime.TabIndex = 5;
+ this.numRuntime.Value = new decimal(new int[] {
+ 5,
+ 0,
+ 0,
+ 0});
+ //
+ // lblRuntime
+ //
+ this.lblRuntime.AutoSize = true;
+ this.lblRuntime.Location = new System.Drawing.Point(3, 70);
+ this.lblRuntime.Name = "lblRuntime";
+ this.lblRuntime.Size = new System.Drawing.Size(51, 12);
+ this.lblRuntime.TabIndex = 4;
+ this.lblRuntime.Text = "시간(초)";
+ //
+ // cmbSpeed
+ //
+ this.cmbSpeed.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.cmbSpeed.FormattingEnabled = true;
+ this.cmbSpeed.Items.AddRange(new object[] {
+ "느림",
+ "보통",
+ "빠름"});
+ this.cmbSpeed.Location = new System.Drawing.Point(60, 41);
+ this.cmbSpeed.Name = "cmbSpeed";
+ this.cmbSpeed.Size = new System.Drawing.Size(70, 20);
+ this.cmbSpeed.TabIndex = 3;
+ //
+ // lblSpeed
+ //
+ this.lblSpeed.AutoSize = true;
+ this.lblSpeed.Location = new System.Drawing.Point(14, 45);
+ this.lblSpeed.Name = "lblSpeed";
+ this.lblSpeed.Size = new System.Drawing.Size(29, 12);
+ this.lblSpeed.TabIndex = 2;
+ this.lblSpeed.Text = "속도";
+ //
+ // cmbDirection
+ //
+ this.cmbDirection.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.cmbDirection.FormattingEnabled = true;
+ this.cmbDirection.Items.AddRange(new object[] {
+ "후진",
+ "전진",
+ "좌",
+ "우"});
+ this.cmbDirection.Location = new System.Drawing.Point(60, 16);
+ this.cmbDirection.Name = "cmbDirection";
+ this.cmbDirection.Size = new System.Drawing.Size(70, 20);
+ this.cmbDirection.TabIndex = 1;
+ //
+ // lblDirection
+ //
+ this.lblDirection.AutoSize = true;
+ this.lblDirection.Location = new System.Drawing.Point(10, 48);
+ this.lblDirection.Name = "lblDirection";
+ this.lblDirection.Size = new System.Drawing.Size(33, 12);
+ this.lblDirection.TabIndex = 4;
+ this.lblDirection.Text = "방향:";
+ //
+ // chkMarkStop
+ //
+ this.chkMarkStop.AutoSize = true;
+ this.chkMarkStop.Location = new System.Drawing.Point(240, 174);
+ this.chkMarkStop.Name = "chkMarkStop";
+ this.chkMarkStop.Size = new System.Drawing.Size(76, 16);
+ this.chkMarkStop.TabIndex = 7;
+ this.chkMarkStop.Text = "정지 설정";
+ this.chkMarkStop.UseVisualStyleBackColor = true;
+ //
+ // btnMarkStop
+ //
+ this.btnMarkStop.Location = new System.Drawing.Point(15, 167);
+ this.btnMarkStop.Name = "btnMarkStop";
+ this.btnMarkStop.Size = new System.Drawing.Size(215, 30);
+ this.btnMarkStop.TabIndex = 6;
+ this.btnMarkStop.Text = "마크센서 정지";
+ this.btnMarkStop.UseVisualStyleBackColor = true;
+ this.btnMarkStop.Click += new System.EventHandler(this.btnMarkStop_Click);
+ //
+ // btnReset
+ //
+ this.btnReset.Location = new System.Drawing.Point(240, 132);
+ this.btnReset.Name = "btnReset";
+ this.btnReset.Size = new System.Drawing.Size(210, 30);
+ this.btnReset.TabIndex = 5;
+ this.btnReset.Text = "에러 리셋";
+ this.btnReset.UseVisualStyleBackColor = true;
+ this.btnReset.Click += new System.EventHandler(this.btnReset_Click);
+ //
+ // btnStop
+ //
+ this.btnStop.Location = new System.Drawing.Point(15, 132);
+ this.btnStop.Name = "btnStop";
+ this.btnStop.Size = new System.Drawing.Size(215, 30);
+ this.btnStop.TabIndex = 4;
+ this.btnStop.Text = "정지";
+ this.btnStop.UseVisualStyleBackColor = true;
+ this.btnStop.Click += new System.EventHandler(this.btnStop_Click);
+ //
+ // btnGotoAlias
+ //
+ this.btnGotoAlias.Location = new System.Drawing.Point(286, 94);
+ this.btnGotoAlias.Name = "btnGotoAlias";
+ this.btnGotoAlias.Size = new System.Drawing.Size(174, 30);
+ this.btnGotoAlias.TabIndex = 11;
+ this.btnGotoAlias.Text = "별칭 이동 (GotoAlias)";
+ this.btnGotoAlias.UseVisualStyleBackColor = true;
+ this.btnGotoAlias.Click += new System.EventHandler(this.btnGotoAlias_Click);
+ //
+ // btnGoto
+ //
+ this.btnGoto.Location = new System.Drawing.Point(286, 23);
+ this.btnGoto.Name = "btnGoto";
+ this.btnGoto.Size = new System.Drawing.Size(174, 30);
+ this.btnGoto.TabIndex = 3;
+ this.btnGoto.Text = "RFID 이동 (Goto)";
+ this.btnGoto.UseVisualStyleBackColor = true;
+ this.btnGoto.Click += new System.EventHandler(this.btnGoto_Click);
+ //
+ // btnSetCurrent
+ //
+ this.btnSetCurrent.Location = new System.Drawing.Point(85, 57);
+ this.btnSetCurrent.Name = "btnSetCurrent";
+ this.btnSetCurrent.Size = new System.Drawing.Size(195, 30);
+ this.btnSetCurrent.TabIndex = 2;
+ this.btnSetCurrent.Text = "현재 위치 설정 (SetCurrent)";
+ this.btnSetCurrent.UseVisualStyleBackColor = true;
+ this.btnSetCurrent.Click += new System.EventHandler(this.btnSetCurrent_Click);
+ //
+ // txtAlias
+ //
+ this.txtAlias.Font = new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.txtAlias.Location = new System.Drawing.Point(85, 96);
+ this.txtAlias.Name = "txtAlias";
+ this.txtAlias.Size = new System.Drawing.Size(195, 26);
+ this.txtAlias.TabIndex = 10;
+ this.txtAlias.Text = "CHARGER1";
+ this.txtAlias.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+ this.txtAlias.TextChanged += new System.EventHandler(this.txtAlias_TextChanged);
+ //
+ // lblAlias
+ //
+ this.lblAlias.AutoSize = true;
+ this.lblAlias.Location = new System.Drawing.Point(15, 103);
+ this.lblAlias.Name = "lblAlias";
+ this.lblAlias.Size = new System.Drawing.Size(71, 12);
+ this.lblAlias.TabIndex = 9;
+ this.lblAlias.Text = "별칭(Alias):";
+ //
+ // txtRFID
+ //
+ this.txtRFID.Font = new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.txtRFID.Location = new System.Drawing.Point(85, 25);
+ this.txtRFID.Name = "txtRFID";
+ this.txtRFID.Size = new System.Drawing.Size(195, 26);
+ this.txtRFID.TabIndex = 1;
+ this.txtRFID.Text = "0001";
+ this.txtRFID.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+ this.txtRFID.TextChanged += new System.EventHandler(this.txtRFID_TextChanged);
+ //
+ // lblRFID
+ //
+ this.lblRFID.AutoSize = true;
+ this.lblRFID.Location = new System.Drawing.Point(15, 32);
+ this.lblRFID.Name = "lblRFID";
+ this.lblRFID.Size = new System.Drawing.Size(63, 12);
+ this.lblRFID.TabIndex = 0;
+ this.lblRFID.Text = "RFID 번호:";
+ //
+ // grpLogs
+ //
+ this.grpLogs.Controls.Add(this.tabLogs);
+ this.grpLogs.Location = new System.Drawing.Point(484, 12);
+ this.grpLogs.Name = "grpLogs";
+ this.grpLogs.Size = new System.Drawing.Size(520, 564);
+ this.grpLogs.TabIndex = 3;
+ this.grpLogs.TabStop = false;
+ this.grpLogs.Text = "로그";
+ //
+ // tabLogs
+ //
+ this.tabLogs.Controls.Add(this.tabRX);
+ this.tabLogs.Controls.Add(this.tabTX);
+ this.tabLogs.Controls.Add(this.tabInfo);
+ this.tabLogs.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.tabLogs.Location = new System.Drawing.Point(3, 17);
+ this.tabLogs.Name = "tabLogs";
+ this.tabLogs.SelectedIndex = 0;
+ this.tabLogs.Size = new System.Drawing.Size(514, 544);
+ this.tabLogs.TabIndex = 0;
+ //
+ // tabRX
+ //
+ this.tabRX.Controls.Add(this.txtRxLog);
+ this.tabRX.Location = new System.Drawing.Point(4, 22);
+ this.tabRX.Name = "tabRX";
+ this.tabRX.Padding = new System.Windows.Forms.Padding(3);
+ this.tabRX.Size = new System.Drawing.Size(506, 518);
+ this.tabRX.TabIndex = 1;
+ this.tabRX.Text = "수신 (RX)";
+ this.tabRX.UseVisualStyleBackColor = true;
+ //
+ // txtRxLog
+ //
+ this.txtRxLog.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.txtRxLog.Font = new System.Drawing.Font("Consolas", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.txtRxLog.Location = new System.Drawing.Point(3, 3);
+ this.txtRxLog.Multiline = true;
+ this.txtRxLog.Name = "txtRxLog";
+ this.txtRxLog.ReadOnly = true;
+ this.txtRxLog.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+ this.txtRxLog.Size = new System.Drawing.Size(500, 512);
+ this.txtRxLog.TabIndex = 0;
+ //
+ // tabTX
+ //
+ this.tabTX.Controls.Add(this.txtTxLog);
+ this.tabTX.Location = new System.Drawing.Point(4, 22);
+ this.tabTX.Name = "tabTX";
+ this.tabTX.Padding = new System.Windows.Forms.Padding(3);
+ this.tabTX.Size = new System.Drawing.Size(506, 469);
+ this.tabTX.TabIndex = 0;
+ this.tabTX.Text = "송신 (TX)";
+ this.tabTX.UseVisualStyleBackColor = true;
+ //
+ // txtTxLog
+ //
+ this.txtTxLog.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.txtTxLog.Font = new System.Drawing.Font("Consolas", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.txtTxLog.Location = new System.Drawing.Point(3, 3);
+ this.txtTxLog.Multiline = true;
+ this.txtTxLog.Name = "txtTxLog";
+ this.txtTxLog.ReadOnly = true;
+ this.txtTxLog.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+ this.txtTxLog.Size = new System.Drawing.Size(500, 463);
+ this.txtTxLog.TabIndex = 0;
+ //
+ // tabInfo
+ //
+ this.tabInfo.Controls.Add(this.txtInfoLog);
+ this.tabInfo.Location = new System.Drawing.Point(4, 22);
+ this.tabInfo.Name = "tabInfo";
+ this.tabInfo.Size = new System.Drawing.Size(506, 469);
+ this.tabInfo.TabIndex = 2;
+ this.tabInfo.Text = "정보";
+ this.tabInfo.UseVisualStyleBackColor = true;
+ //
+ // txtInfoLog
+ //
+ this.txtInfoLog.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.txtInfoLog.Font = new System.Drawing.Font("Consolas", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.txtInfoLog.Location = new System.Drawing.Point(0, 0);
+ this.txtInfoLog.Multiline = true;
+ this.txtInfoLog.Name = "txtInfoLog";
+ this.txtInfoLog.ReadOnly = true;
+ this.txtInfoLog.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+ this.txtInfoLog.Size = new System.Drawing.Size(506, 469);
+ this.txtInfoLog.TabIndex = 0;
+ //
+ // grpAGVStatus
+ //
+ this.grpAGVStatus.Controls.Add(this.lblLastTagValue);
+ this.grpAGVStatus.Controls.Add(this.lblLastTag);
+ this.grpAGVStatus.Controls.Add(this.lblLiftStValue);
+ this.grpAGVStatus.Controls.Add(this.lblLiftSt);
+ this.grpAGVStatus.Controls.Add(this.lblCartStValue);
+ this.grpAGVStatus.Controls.Add(this.lblCartSt);
+ this.grpAGVStatus.Controls.Add(this.lblChargeStValue);
+ this.grpAGVStatus.Controls.Add(this.lblChargeSt);
+ this.grpAGVStatus.Controls.Add(this.lblInpositionValue);
+ this.grpAGVStatus.Controls.Add(this.lblInposition);
+ this.grpAGVStatus.Controls.Add(this.lblDirectionValue);
+ this.grpAGVStatus.Controls.Add(this.lblDirection);
+ this.grpAGVStatus.Controls.Add(this.lblRunStValue);
+ this.grpAGVStatus.Controls.Add(this.lblRunSt);
+ this.grpAGVStatus.Controls.Add(this.lblModeValue);
+ this.grpAGVStatus.Controls.Add(this.lblMode);
+ this.grpAGVStatus.Location = new System.Drawing.Point(12, 456);
+ this.grpAGVStatus.Name = "grpAGVStatus";
+ this.grpAGVStatus.Size = new System.Drawing.Size(466, 120);
+ this.grpAGVStatus.TabIndex = 4;
+ this.grpAGVStatus.TabStop = false;
+ this.grpAGVStatus.Text = "AGV 상태";
+ //
+ // lblLastTagValue
+ //
+ this.lblLastTagValue.AutoSize = true;
+ this.lblLastTagValue.Font = new System.Drawing.Font("Consolas", 9F, System.Drawing.FontStyle.Bold);
+ this.lblLastTagValue.Location = new System.Drawing.Point(310, 98);
+ this.lblLastTagValue.Name = "lblLastTagValue";
+ this.lblLastTagValue.Size = new System.Drawing.Size(14, 14);
+ this.lblLastTagValue.TabIndex = 15;
+ this.lblLastTagValue.Text = "-";
+ //
+ // lblLastTag
+ //
+ this.lblLastTag.AutoSize = true;
+ this.lblLastTag.Location = new System.Drawing.Point(240, 98);
+ this.lblLastTag.Name = "lblLastTag";
+ this.lblLastTag.Size = new System.Drawing.Size(57, 12);
+ this.lblLastTag.TabIndex = 14;
+ this.lblLastTag.Text = "현재태그:";
+ //
+ // lblLiftStValue
+ //
+ this.lblLiftStValue.AutoSize = true;
+ this.lblLiftStValue.Font = new System.Drawing.Font("굴림", 9F, System.Drawing.FontStyle.Bold);
+ this.lblLiftStValue.Location = new System.Drawing.Point(80, 98);
+ this.lblLiftStValue.Name = "lblLiftStValue";
+ this.lblLiftStValue.Size = new System.Drawing.Size(12, 12);
+ this.lblLiftStValue.TabIndex = 13;
+ this.lblLiftStValue.Text = "-";
+ //
+ // lblLiftSt
+ //
+ this.lblLiftSt.AutoSize = true;
+ this.lblLiftSt.Location = new System.Drawing.Point(10, 98);
+ this.lblLiftSt.Name = "lblLiftSt";
+ this.lblLiftSt.Size = new System.Drawing.Size(45, 12);
+ this.lblLiftSt.TabIndex = 12;
+ this.lblLiftSt.Text = "리프트:";
+ //
+ // lblCartStValue
+ //
+ this.lblCartStValue.AutoSize = true;
+ this.lblCartStValue.Font = new System.Drawing.Font("굴림", 9F, System.Drawing.FontStyle.Bold);
+ this.lblCartStValue.Location = new System.Drawing.Point(310, 73);
+ this.lblCartStValue.Name = "lblCartStValue";
+ this.lblCartStValue.Size = new System.Drawing.Size(12, 12);
+ this.lblCartStValue.TabIndex = 11;
+ this.lblCartStValue.Text = "-";
+ //
+ // lblCartSt
+ //
+ this.lblCartSt.AutoSize = true;
+ this.lblCartSt.Location = new System.Drawing.Point(240, 73);
+ this.lblCartSt.Name = "lblCartSt";
+ this.lblCartSt.Size = new System.Drawing.Size(33, 12);
+ this.lblCartSt.TabIndex = 10;
+ this.lblCartSt.Text = "카트:";
+ //
+ // lblChargeStValue
+ //
+ this.lblChargeStValue.AutoSize = true;
+ this.lblChargeStValue.Font = new System.Drawing.Font("굴림", 9F, System.Drawing.FontStyle.Bold);
+ this.lblChargeStValue.Location = new System.Drawing.Point(80, 73);
+ this.lblChargeStValue.Name = "lblChargeStValue";
+ this.lblChargeStValue.Size = new System.Drawing.Size(12, 12);
+ this.lblChargeStValue.TabIndex = 9;
+ this.lblChargeStValue.Text = "-";
+ //
+ // lblChargeSt
+ //
+ this.lblChargeSt.AutoSize = true;
+ this.lblChargeSt.Location = new System.Drawing.Point(10, 73);
+ this.lblChargeSt.Name = "lblChargeSt";
+ this.lblChargeSt.Size = new System.Drawing.Size(33, 12);
+ this.lblChargeSt.TabIndex = 8;
+ this.lblChargeSt.Text = "충전:";
+ //
+ // lblInpositionValue
+ //
+ this.lblInpositionValue.AutoSize = true;
+ this.lblInpositionValue.Font = new System.Drawing.Font("굴림", 9F, System.Drawing.FontStyle.Bold);
+ this.lblInpositionValue.Location = new System.Drawing.Point(310, 48);
+ this.lblInpositionValue.Name = "lblInpositionValue";
+ this.lblInpositionValue.Size = new System.Drawing.Size(12, 12);
+ this.lblInpositionValue.TabIndex = 7;
+ this.lblInpositionValue.Text = "-";
+ //
+ // lblInposition
+ //
+ this.lblInposition.AutoSize = true;
+ this.lblInposition.Location = new System.Drawing.Point(240, 48);
+ this.lblInposition.Name = "lblInposition";
+ this.lblInposition.Size = new System.Drawing.Size(57, 12);
+ this.lblInposition.TabIndex = 6;
+ this.lblInposition.Text = "도달완료:";
+ //
+ // lblDirectionValue
+ //
+ this.lblDirectionValue.AutoSize = true;
+ this.lblDirectionValue.Font = new System.Drawing.Font("굴림", 9F, System.Drawing.FontStyle.Bold);
+ this.lblDirectionValue.Location = new System.Drawing.Point(80, 48);
+ this.lblDirectionValue.Name = "lblDirectionValue";
+ this.lblDirectionValue.Size = new System.Drawing.Size(12, 12);
+ this.lblDirectionValue.TabIndex = 5;
+ this.lblDirectionValue.Text = "-";
+ //
+ // lblRunStValue
+ //
+ this.lblRunStValue.AutoSize = true;
+ this.lblRunStValue.Font = new System.Drawing.Font("굴림", 9F, System.Drawing.FontStyle.Bold);
+ this.lblRunStValue.Location = new System.Drawing.Point(310, 23);
+ this.lblRunStValue.Name = "lblRunStValue";
+ this.lblRunStValue.Size = new System.Drawing.Size(12, 12);
+ this.lblRunStValue.TabIndex = 3;
+ this.lblRunStValue.Text = "-";
+ //
+ // lblRunSt
+ //
+ this.lblRunSt.AutoSize = true;
+ this.lblRunSt.Location = new System.Drawing.Point(240, 23);
+ this.lblRunSt.Name = "lblRunSt";
+ this.lblRunSt.Size = new System.Drawing.Size(57, 12);
+ this.lblRunSt.TabIndex = 2;
+ this.lblRunSt.Text = "실행상태:";
+ //
+ // lblModeValue
+ //
+ this.lblModeValue.AutoSize = true;
+ this.lblModeValue.Font = new System.Drawing.Font("굴림", 9F, System.Drawing.FontStyle.Bold);
+ this.lblModeValue.Location = new System.Drawing.Point(80, 23);
+ this.lblModeValue.Name = "lblModeValue";
+ this.lblModeValue.Size = new System.Drawing.Size(12, 12);
+ this.lblModeValue.TabIndex = 1;
+ this.lblModeValue.Text = "-";
+ //
+ // lblMode
+ //
+ this.lblMode.AutoSize = true;
+ this.lblMode.Location = new System.Drawing.Point(10, 23);
+ this.lblMode.Name = "lblMode";
+ this.lblMode.Size = new System.Drawing.Size(33, 12);
+ this.lblMode.TabIndex = 0;
+ this.lblMode.Text = "모드:";
+ //
+ // MainForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(1016, 588);
+ this.Controls.Add(this.grpAGVStatus);
+ this.Controls.Add(this.grpLogs);
+ this.Controls.Add(this.grpCommands);
+ this.Controls.Add(this.grpAGV);
+ this.Controls.Add(this.grpConnection);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
+ this.MaximizeBox = false;
+ this.Name = "MainForm";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "ACS 시뮬레이터 - ENIG AGV 테스트";
+ this.grpConnection.ResumeLayout(false);
+ this.grpConnection.PerformLayout();
+ this.grpAGV.ResumeLayout(false);
+ this.grpAGV.PerformLayout();
+ this.grpCommands.ResumeLayout(false);
+ this.grpCommands.PerformLayout();
+ this.grpLift.ResumeLayout(false);
+ this.grpManual.ResumeLayout(false);
+ this.grpManual.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.numRuntime)).EndInit();
+ this.grpLogs.ResumeLayout(false);
+ this.tabLogs.ResumeLayout(false);
+ this.tabRX.ResumeLayout(false);
+ this.tabRX.PerformLayout();
+ this.tabTX.ResumeLayout(false);
+ this.tabTX.PerformLayout();
+ this.tabInfo.ResumeLayout(false);
+ this.tabInfo.PerformLayout();
+ this.grpAGVStatus.ResumeLayout(false);
+ this.grpAGVStatus.PerformLayout();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.GroupBox grpConnection;
+ private System.Windows.Forms.Button btnConnect;
+ private System.Windows.Forms.TextBox txtBaudRate;
+ private System.Windows.Forms.ComboBox cmbPort;
+ private System.Windows.Forms.Label lblBaudRate;
+ private System.Windows.Forms.Label lblPort;
+ private System.Windows.Forms.GroupBox grpAGV;
+ private System.Windows.Forms.RadioButton rbAGV2;
+ private System.Windows.Forms.RadioButton rbAGV1;
+ private System.Windows.Forms.GroupBox grpCommands;
+ private System.Windows.Forms.Button btnSetCurrent;
+ private System.Windows.Forms.TextBox txtRFID;
+ private System.Windows.Forms.Label lblRFID;
+ private System.Windows.Forms.Button btnGoto;
+ private System.Windows.Forms.Button btnStop;
+ private System.Windows.Forms.Button btnReset;
+ private System.Windows.Forms.Button btnMarkStop;
+ private System.Windows.Forms.CheckBox chkMarkStop;
+ private System.Windows.Forms.GroupBox grpManual;
+ private System.Windows.Forms.Button btnManual;
+ private System.Windows.Forms.NumericUpDown numRuntime;
+ private System.Windows.Forms.Label lblRuntime;
+ private System.Windows.Forms.ComboBox cmbSpeed;
+ private System.Windows.Forms.Label lblSpeed;
+ private System.Windows.Forms.ComboBox cmbDirection;
+ private System.Windows.Forms.GroupBox grpLift;
+ private System.Windows.Forms.Button btnLiftStop;
+ private System.Windows.Forms.Button btnLiftDown;
+ private System.Windows.Forms.Button btnLiftUp;
+ private System.Windows.Forms.GroupBox grpLogs;
+ private System.Windows.Forms.TabControl tabLogs;
+ private System.Windows.Forms.TabPage tabTX;
+ private System.Windows.Forms.TextBox txtTxLog;
+ private System.Windows.Forms.TabPage tabRX;
+ private System.Windows.Forms.TextBox txtRxLog;
+ private System.Windows.Forms.TabPage tabInfo;
+ private System.Windows.Forms.TextBox txtInfoLog;
+ private System.Windows.Forms.Button btnRefresh;
+ private System.Windows.Forms.Button btnGotoAlias;
+ private System.Windows.Forms.TextBox txtAlias;
+ private System.Windows.Forms.Label lblAlias;
+ private System.Windows.Forms.GroupBox grpAGVStatus;
+ private System.Windows.Forms.Label lblLastTagValue;
+ private System.Windows.Forms.Label lblLastTag;
+ private System.Windows.Forms.Label lblLiftStValue;
+ private System.Windows.Forms.Label lblLiftSt;
+ private System.Windows.Forms.Label lblCartStValue;
+ private System.Windows.Forms.Label lblCartSt;
+ private System.Windows.Forms.Label lblChargeStValue;
+ private System.Windows.Forms.Label lblChargeSt;
+ private System.Windows.Forms.Label lblInpositionValue;
+ private System.Windows.Forms.Label lblInposition;
+ private System.Windows.Forms.Label lblDirectionValue;
+ private System.Windows.Forms.Label lblDirection;
+ private System.Windows.Forms.Label lblRunStValue;
+ private System.Windows.Forms.Label lblRunSt;
+ private System.Windows.Forms.Label lblModeValue;
+ private System.Windows.Forms.Label lblMode;
+ }
+}
diff --git a/Cs_HMI/TestProject/Test_ACS/MainForm.cs b/Cs_HMI/TestProject/Test_ACS/MainForm.cs
new file mode 100644
index 0000000..fcf365a
--- /dev/null
+++ b/Cs_HMI/TestProject/Test_ACS/MainForm.cs
@@ -0,0 +1,515 @@
+using System;
+using System.Drawing;
+using System.IO.Ports;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using ENIG;
+using ENIGProtocol;
+
+namespace Test_ACS
+{
+ public partial class MainForm : Form
+ {
+ private SerialPort serialPort;
+ private EEProtocol protocol;
+ private byte selectedAGV = 11; // 기본값: AGV1 (11)
+ private AppSettings settings;
+
+ public MainForm()
+ {
+ InitializeComponent();
+ InitializeProtocol();
+ LoadPortList();
+ InitializeComboBoxes();
+ }
+
+ private void InitializeComboBoxes()
+ {
+ // Direction combobox default
+ if (cmbDirection.Items.Count > 0) cmbDirection.SelectedIndex = 1; // 전진
+
+ // Speed combobox default
+ if (cmbSpeed.Items.Count > 0) cmbSpeed.SelectedIndex = 1; // 보통
+ }
+
+ private void InitializeProtocol()
+ {
+ protocol = new EEProtocol();
+ protocol.OnDataReceived += Protocol_OnDataReceived;
+ protocol.OnMessage += Protocol_OnMessage;
+
+ serialPort = new SerialPort();
+ serialPort.ReadTimeout = 2000;
+ serialPort.WriteTimeout = 1000;
+ serialPort.DataReceived += SerialPort_DataReceived;
+ }
+
+ private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
+ {
+ var buffer = new byte[serialPort.BytesToRead];
+ serialPort.Read(buffer, 0, buffer.Length);
+ protocol.ProcessReceivedData(buffer);
+ }
+
+ private void Protocol_OnDataReceived(object sender, EEProtocol.DataEventArgs e)
+ {
+ var hexstrRaw = string.Join(" ", e.ReceivedPacket.RawData.Select(b => b.ToString("X2")));
+ var hexstr = string.Join(" ", e.ReceivedPacket.Data.Select(b => b.ToString("X2")));
+ var cmd = e.ReceivedPacket.Command.ToString("X2");
+ var id = e.ReceivedPacket.ID.ToString("X2");
+ AddLog($"RX: {hexstrRaw}\nID:{id}, CMD:{cmd}, DATA:{hexstr}", LogType.RX);
+
+ // AGV 상태 수신 처리 (cmd = 3)
+ if (e.ReceivedPacket.Command == (byte)ENIGProtocol.AGVCommandEH.Status)
+ {
+ UpdateAGVStatus(e.ReceivedPacket.Data);
+ }
+ }
+
+ private void Protocol_OnMessage(object sender, EEProtocol.MessageEventArgs e)
+ {
+ AddLog(e.Message, e.IsError ? LogType.Error : LogType.Info);
+ }
+
+ private void LoadPortList()
+ {
+ cmbPort.Items.Clear();
+ foreach (var port in SerialPort.GetPortNames())
+ {
+ cmbPort.Items.Add(port);
+ }
+
+ // 마지막 설정 불러오기
+ LoadSettings();
+ }
+
+ private void LoadSettings()
+ {
+ try
+ {
+ // 설정 파일 로드
+ settings = AppSettings.Load();
+
+ // 포트 설정
+ if (!string.IsNullOrEmpty(settings.LastPort) && cmbPort.Items.Contains(settings.LastPort))
+ {
+ cmbPort.SelectedItem = settings.LastPort;
+ }
+ else if (cmbPort.Items.Count > 0)
+ {
+ cmbPort.SelectedIndex = 0;
+ }
+
+ // 보레이트 설정
+ txtBaudRate.Text = settings.LastBaudRate;
+
+ // RFID 번호 설정
+ txtRFID.Text = settings.LastRFID;
+
+ // 별칭 설정
+ txtAlias.Text = settings.LastAlias;
+
+ // AGV 선택 설정
+ if (settings.LastAGV == 11)
+ {
+ rbAGV1.Checked = true;
+ }
+ else if (settings.LastAGV == 12)
+ {
+ rbAGV2.Checked = true;
+ }
+
+ AddLog("설정을 불러왔습니다.", LogType.Info);
+ }
+ catch (Exception ex)
+ {
+ settings = new AppSettings();
+ AddLog($"설정 불러오기 실패: {ex.Message}", LogType.Error);
+ }
+ }
+
+ private void SaveSettings()
+ {
+ try
+ {
+ if (settings == null)
+ settings = new AppSettings();
+
+ settings.LastPort = cmbPort.Text;
+ settings.LastBaudRate = txtBaudRate.Text;
+ settings.LastRFID = txtRFID.Text;
+ settings.LastAlias = txtAlias.Text;
+ settings.LastAGV = selectedAGV;
+ settings.Save();
+ }
+ catch (Exception ex)
+ {
+ AddLog($"설정 저장 실패: {ex.Message}", LogType.Error);
+ }
+ }
+
+ private void btnConnect_Click(object sender, EventArgs e)
+ {
+ if (serialPort.IsOpen)
+ {
+ serialPort.Close();
+ btnConnect.Text = "연결";
+ AddLog("포트 닫힘", LogType.Info);
+ }
+ else
+ {
+ try
+ {
+ serialPort.PortName = cmbPort.Text;
+ serialPort.BaudRate = int.Parse(txtBaudRate.Text);
+ serialPort.Open();
+ btnConnect.Text = "해제";
+ AddLog($"{serialPort.PortName}:{serialPort.BaudRate} 연결됨", LogType.Info);
+ }
+ catch (Exception ex)
+ {
+ AddLog($"연결 실패: {ex.Message}", LogType.Error);
+ }
+ }
+ }
+
+ private void btnRefresh_Click(object sender, EventArgs e)
+ {
+ LoadPortList();
+ }
+
+ private void cmbPort_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ SaveSettings();
+ }
+
+ private void txtBaudRate_TextChanged(object sender, EventArgs e)
+ {
+ SaveSettings();
+ }
+
+ private void txtRFID_TextChanged(object sender, EventArgs e)
+ {
+ SaveSettings();
+ }
+
+ private void txtAlias_TextChanged(object sender, EventArgs e)
+ {
+ SaveSettings();
+ }
+
+ private void rbAGV1_CheckedChanged(object sender, EventArgs e)
+ {
+ if (rbAGV1.Checked)
+ {
+ selectedAGV = 11;
+ SaveSettings();
+ }
+ }
+
+ private void rbAGV2_CheckedChanged(object sender, EventArgs e)
+ {
+ if (rbAGV2.Checked)
+ {
+ selectedAGV = 12;
+ SaveSettings();
+ }
+ }
+
+ private void btnSetCurrent_Click(object sender, EventArgs e)
+ {
+ // SetCurrent: data = TargetID(2 hex) + RFID(4 hex)
+ var rfid = txtRFID.Text.PadLeft(4, '0');
+ var targetID = selectedAGV.ToString("X2");
+ var dataStr = targetID + rfid;
+ SendCommand(AGVCommandHE.SetCurrent, dataStr);
+ }
+
+ private void btnGoto_Click(object sender, EventArgs e)
+ {
+ // Goto: data = TargetID(2 hex) + RFID(4 hex)
+ var rfid = txtRFID.Text.PadLeft(4, '0');
+ var targetID = selectedAGV.ToString("X2");
+ var dataStr = targetID + rfid;
+ SendCommand(AGVCommandHE.Goto, dataStr);
+ }
+
+ private void btnGotoAlias_Click(object sender, EventArgs e)
+ {
+ // GotoAlias: data = TargetID(2 hex) + Alias(ASCII string)
+ var alias = txtAlias.Text.Trim();
+ if (string.IsNullOrEmpty(alias))
+ {
+ AddLog("별칭을 입력하세요.", LogType.Error);
+ return;
+ }
+
+ var targetID = selectedAGV.ToString("X2");
+ var aliasBytes = Encoding.ASCII.GetBytes(alias);
+ var aliasHex = string.Join("", aliasBytes.Select(b => b.ToString("X2")));
+ var dataStr = targetID + aliasHex;
+ SendCommand(AGVCommandHE.GotoAlias, dataStr);
+ }
+
+ private void btnStop_Click(object sender, EventArgs e)
+ {
+ // Stop: data = TargetID(2 hex)
+ var targetID = selectedAGV.ToString("X2");
+ SendCommand(AGVCommandHE.Stop, targetID);
+ }
+
+ private void btnReset_Click(object sender, EventArgs e)
+ {
+ // Reset: data = TargetID(2 hex)
+ var targetID = selectedAGV.ToString("X2");
+ SendCommand(AGVCommandHE.Reset, targetID);
+ }
+
+ private void btnManual_Click(object sender, EventArgs e)
+ {
+ // Manual: data = TargetID(2 hex) + Direction(1 byte) + Speed(1 byte) + Runtime(1 byte)
+ var targetID = selectedAGV.ToString("X2");
+ var direction = (byte)cmbDirection.SelectedIndex;
+ var speed = (byte)cmbSpeed.SelectedIndex;
+ var runtime = (byte)numRuntime.Value;
+
+ var dataBytes = new byte[] { direction, speed, runtime };
+ var dataStr = targetID + string.Join("", dataBytes.Select(b => b.ToString("X2")));
+ SendCommand(AGVCommandHE.Manual, dataStr);
+ }
+
+ private void btnMarkStop_Click(object sender, EventArgs e)
+ {
+ // MarkStop: data = TargetID(2 hex) + MarkStop(1 byte)
+ var targetID = selectedAGV.ToString("X2");
+ var markStop = chkMarkStop.Checked ? "01" : "00";
+ SendCommand(AGVCommandHE.MarkStop, targetID + markStop);
+ }
+
+ private void btnLiftUp_Click(object sender, EventArgs e)
+ {
+ SendLiftCommand(1); // Up
+ }
+
+ private void btnLiftDown_Click(object sender, EventArgs e)
+ {
+ SendLiftCommand(2); // Down
+ }
+
+ private void btnLiftStop_Click(object sender, EventArgs e)
+ {
+ SendLiftCommand(0); // Stop
+ }
+
+ private void SendLiftCommand(byte liftCmd)
+ {
+ // LiftControl: data = TargetID(2 hex) + LiftCommand(1 byte)
+ var targetID = selectedAGV.ToString("X2");
+ var dataStr = targetID + liftCmd.ToString("X2");
+ SendCommand(AGVCommandHE.LiftControl, dataStr);
+ }
+
+ private void SendCommand(AGVCommandHE command, string dataHexString)
+ {
+ if (!serialPort.IsOpen)
+ {
+ AddLog("포트가 연결되지 않았습니다.", LogType.Error);
+ return;
+ }
+
+ try
+ {
+ // Hex 문자열을 byte 배열로 변환
+ byte[] dataBytes = new byte[dataHexString.Length / 2];
+ for (int i = 0; i < dataBytes.Length; i++)
+ {
+ dataBytes[i] = Convert.ToByte(dataHexString.Substring(i * 2, 2), 16);
+ }
+
+ // 패킷 생성 (ACS ID = 0)
+ byte[] packet = protocol.CreatePacket(0, (byte)command, dataBytes);
+
+ // 전송
+ serialPort.Write(packet, 0, packet.Length);
+
+ var hexString = string.Join(" ", packet.Select(b => b.ToString("X2")));
+ AddLog($"TX: {hexString}\nCMD: {command} ({(byte)command:X2}), DATA: {dataHexString}", LogType.TX);
+ }
+ catch (Exception ex)
+ {
+ AddLog($"전송 실패: {ex.Message}", LogType.Error);
+ }
+ }
+
+ private void UpdateAGVStatus(byte[] data)
+ {
+ if (data.Length < 13)
+ {
+ AddLog($"AGV 상태 데이터 길이 오류: {data.Length} bytes", LogType.Error);
+ return;
+ }
+
+ if (InvokeRequired)
+ {
+ BeginInvoke(new Action(() => UpdateAGVStatus(data)));
+ return;
+ }
+
+ try
+ {
+ // Mode[1]: 0=manual, 1=auto
+ lblModeValue.Text = data[0] == 0 ? "수동" : "자동";
+ lblModeValue.ForeColor = data[0] == 0 ? Color.Blue : Color.Green;
+
+ // RunSt[1]: 0=stop, 1=run, 2=error
+ switch (data[1])
+ {
+ case 0:
+ lblRunStValue.Text = "정지";
+ lblRunStValue.ForeColor = Color.Gray;
+ break;
+ case 1:
+ lblRunStValue.Text = "실행";
+ lblRunStValue.ForeColor = Color.Green;
+ break;
+ case 2:
+ lblRunStValue.Text = "에러";
+ lblRunStValue.ForeColor = Color.Red;
+ break;
+ default:
+ lblRunStValue.Text = "알 수 없음";
+ lblRunStValue.ForeColor = Color.Black;
+ break;
+ }
+
+ // Direction[1]: 0=straight, 1=left, 2=right, 3=markstop
+ switch (data[2])
+ {
+ case 0:
+ lblDirectionValue.Text = "직진";
+ break;
+ case 1:
+ lblDirectionValue.Text = "좌회전";
+ break;
+ case 2:
+ lblDirectionValue.Text = "우회전";
+ break;
+ case 3:
+ lblDirectionValue.Text = "마크정지";
+ break;
+ default:
+ lblDirectionValue.Text = "알 수 없음";
+ break;
+ }
+
+ // Inposition[1]: 0=off, 1=on
+ lblInpositionValue.Text = data[3] == 0 ? "OFF" : "ON";
+ lblInpositionValue.ForeColor = data[3] == 0 ? Color.Gray : Color.Green;
+
+ // ChargeSt[1]: 0=off, 1=on
+ lblChargeStValue.Text = data[4] == 0 ? "OFF" : "ON";
+ lblChargeStValue.ForeColor = data[4] == 0 ? Color.Gray : Color.Orange;
+
+ // CartSt[1]: 0=off, 1=on, 2=unknown
+ switch (data[5])
+ {
+ case 0:
+ lblCartStValue.Text = "없음";
+ lblCartStValue.ForeColor = Color.Gray;
+ break;
+ case 1:
+ lblCartStValue.Text = "있음";
+ lblCartStValue.ForeColor = Color.Green;
+ break;
+ case 2:
+ lblCartStValue.Text = "알 수 없음";
+ lblCartStValue.ForeColor = Color.Orange;
+ break;
+ default:
+ lblCartStValue.Text = "오류";
+ lblCartStValue.ForeColor = Color.Red;
+ break;
+ }
+
+ // LiftSt[1]: 0=down, 1=up, 2=unknown
+ switch (data[6])
+ {
+ case 0:
+ lblLiftStValue.Text = "하강";
+ lblLiftStValue.ForeColor = Color.Blue;
+ break;
+ case 1:
+ lblLiftStValue.Text = "상승";
+ lblLiftStValue.ForeColor = Color.Green;
+ break;
+ case 2:
+ lblLiftStValue.Text = "알 수 없음";
+ lblLiftStValue.ForeColor = Color.Orange;
+ break;
+ default:
+ lblLiftStValue.Text = "오류";
+ lblLiftStValue.ForeColor = Color.Red;
+ break;
+ }
+
+ // LastTag[6]: "000000"
+ string lastTag = Encoding.ASCII.GetString(data, 7, 6);
+ lblLastTagValue.Text = lastTag;
+ lblLastTagValue.ForeColor = Color.Black;
+ }
+ catch (Exception ex)
+ {
+ AddLog($"AGV 상태 업데이트 실패: {ex.Message}", LogType.Error);
+ }
+ }
+
+ private enum LogType { TX, RX, Info, Error }
+
+ private void AddLog(string message, LogType type)
+ {
+ if (InvokeRequired)
+ {
+ BeginInvoke(new Action(() => AddLog(message, type)));
+ return;
+ }
+
+ var timestamp = DateTime.Now.ToString("HH:mm:ss");
+ var logMessage = $"[{timestamp}] {message}\r\n";
+
+ switch (type)
+ {
+ case LogType.TX:
+ txtTxLog.AppendText(logMessage);
+ txtTxLog.ScrollToCaret();
+ break;
+ case LogType.RX:
+ txtRxLog.AppendText(logMessage);
+ txtRxLog.ScrollToCaret();
+ break;
+ case LogType.Info:
+ txtInfoLog.AppendText(logMessage);
+ txtInfoLog.ScrollToCaret();
+ break;
+ case LogType.Error:
+ txtInfoLog.ForeColor = Color.Red;
+ txtInfoLog.AppendText(logMessage);
+ txtInfoLog.ForeColor = Color.Black;
+ txtInfoLog.ScrollToCaret();
+ break;
+ }
+ }
+
+ protected override void OnFormClosing(FormClosingEventArgs e)
+ {
+ // 설정 저장
+ SaveSettings();
+
+ if (serialPort != null && serialPort.IsOpen)
+ {
+ serialPort.Close();
+ }
+ base.OnFormClosing(e);
+ }
+ }
+}
diff --git a/Cs_HMI/TestProject/Test_ACS/MainForm.resx b/Cs_HMI/TestProject/Test_ACS/MainForm.resx
new file mode 100644
index 0000000..d58980a
--- /dev/null
+++ b/Cs_HMI/TestProject/Test_ACS/MainForm.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Cs_HMI/TestProject/Test_ACS/Program.cs b/Cs_HMI/TestProject/Test_ACS/Program.cs
new file mode 100644
index 0000000..7029c4d
--- /dev/null
+++ b/Cs_HMI/TestProject/Test_ACS/Program.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Windows.Forms;
+
+namespace Test_ACS
+{
+ static class Program
+ {
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new MainForm());
+ }
+ }
+}
diff --git a/Cs_HMI/TestProject/Test_ACS/Properties/AssemblyInfo.cs b/Cs_HMI/TestProject/Test_ACS/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..6812718
--- /dev/null
+++ b/Cs_HMI/TestProject/Test_ACS/Properties/AssemblyInfo.cs
@@ -0,0 +1,19 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("Test_ACS")]
+[assembly: AssemblyDescription("ACS Simulator for ENIG AGV Testing")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("ENIG")]
+[assembly: AssemblyProduct("Test_ACS")]
+[assembly: AssemblyCopyright("Copyright © 2025")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+[assembly: ComVisible(false)]
+
+[assembly: Guid("a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d")]
+
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Cs_HMI/TestProject/Test_ACS/Properties/Resources.Designer.cs b/Cs_HMI/TestProject/Test_ACS/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..271cd0d
--- /dev/null
+++ b/Cs_HMI/TestProject/Test_ACS/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// 이 코드는 도구를 사용하여 생성되었습니다.
+// 런타임 버전:4.0.30319.42000
+//
+// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
+// 이러한 변경 내용이 손실됩니다.
+//
+//------------------------------------------------------------------------------
+
+namespace Test_ACS.Properties {
+ using System;
+
+
+ ///
+ /// 지역화된 문자열 등을 찾기 위한 강력한 형식의 리소스 클래스입니다.
+ ///
+ // 이 클래스는 ResGen 또는 Visual Studio와 같은 도구를 통해 StronglyTypedResourceBuilder
+ // 클래스에서 자동으로 생성되었습니다.
+ // 멤버를 추가하거나 제거하려면 .ResX 파일을 편집한 다음 /str 옵션을 사용하여 ResGen을
+ // 다시 실행하거나 VS 프로젝트를 다시 빌드하십시오.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// 이 클래스에서 사용하는 캐시된 ResourceManager 인스턴스를 반환합니다.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Test_ACS.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// 이 강력한 형식의 리소스 클래스를 사용하여 모든 리소스 조회에 대한 현재 스레드의 CurrentUICulture
+ /// 속성을 재정의합니다.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/Cs_HMI/TestProject/Test_ACS/Properties/Resources.resx b/Cs_HMI/TestProject/Test_ACS/Properties/Resources.resx
new file mode 100644
index 0000000..4fdb1b6
--- /dev/null
+++ b/Cs_HMI/TestProject/Test_ACS/Properties/Resources.resx
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 1.3
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Cs_HMI/TestProject/Test_ACS/Properties/Settings.Designer.cs b/Cs_HMI/TestProject/Test_ACS/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..e3262da
--- /dev/null
+++ b/Cs_HMI/TestProject/Test_ACS/Properties/Settings.Designer.cs
@@ -0,0 +1,86 @@
+//------------------------------------------------------------------------------
+//
+// 이 코드는 도구를 사용하여 생성되었습니다.
+// 런타임 버전:4.0.30319.42000
+//
+// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
+// 이러한 변경 내용이 손실됩니다.
+//
+//------------------------------------------------------------------------------
+
+namespace Test_ACS.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("COM1")]
+ public string LastPort {
+ get {
+ return ((string)(this["LastPort"]));
+ }
+ set {
+ this["LastPort"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("9600")]
+ public string LastBaudRate {
+ get {
+ return ((string)(this["LastBaudRate"]));
+ }
+ set {
+ this["LastBaudRate"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("0001")]
+ public string LastRFID {
+ get {
+ return ((string)(this["LastRFID"]));
+ }
+ set {
+ this["LastRFID"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("CHARGER1")]
+ public string LastAlias {
+ get {
+ return ((string)(this["LastAlias"]));
+ }
+ set {
+ this["LastAlias"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("11")]
+ public int LastAGV {
+ get {
+ return ((int)(this["LastAGV"]));
+ }
+ set {
+ this["LastAGV"] = value;
+ }
+ }
+ }
+}
diff --git a/Cs_HMI/TestProject/Test_ACS/Properties/Settings.settings b/Cs_HMI/TestProject/Test_ACS/Properties/Settings.settings
new file mode 100644
index 0000000..def4ca8
--- /dev/null
+++ b/Cs_HMI/TestProject/Test_ACS/Properties/Settings.settings
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+ COM1
+
+
+ 9600
+
+
+ 0001
+
+
+ CHARGER1
+
+
+ 11
+
+
+
diff --git a/Cs_HMI/TestProject/Test_ACS/README.md b/Cs_HMI/TestProject/Test_ACS/README.md
new file mode 100644
index 0000000..dfcb23b
--- /dev/null
+++ b/Cs_HMI/TestProject/Test_ACS/README.md
@@ -0,0 +1,242 @@
+# Test_ACS - ACS 시뮬레이터
+
+ENIG AGV 프로젝트를 위한 ACS(중앙제어시스템) 시뮬레이터입니다.
+
+## 프로젝트 개요
+
+ACS는 AGV에게 명령을 내리는 중앙 제어 시스템입니다. 이 프로그램은 실제 ACS 대신 테스트 목적으로 AGV에 명령을 보낼 수 있는 시뮬레이터입니다.
+
+### 통신 방식
+- **프로토콜**: ENIG Protocol (ENIGProtocol 프로젝트 사용)
+- **통신**: RS232 (Xbee 모듈)
+- **ACS Xbee ID**: 0
+- **AGV Xbee ID**:
+ - AGV1: 11
+ - AGV2: 12
+
+## 프로젝트 구조
+
+```
+Test_ACS/
+├── Test_ACS.csproj # 프로젝트 파일
+├── Program.cs # 진입점
+├── MainForm.cs # 메인 폼 로직
+├── MainForm.Designer.cs # 메인 폼 디자이너
+├── MainForm.resx # 메인 폼 리소스
+├── Properties/ # 프로젝트 속성
+│ ├── AssemblyInfo.cs
+│ ├── Resources.Designer.cs
+│ ├── Resources.resx
+│ ├── Settings.Designer.cs
+│ └── Settings.settings
+└── app.config # 애플리케이션 설정
+```
+
+## 빌드 방법
+
+1. Visual Studio 2022 또는 MSBuild 사용
+2. .NET Framework 4.8 필요
+3. ENIGProtocol 프로젝트 참조 필요
+
+```bash
+# Visual Studio에서 빌드
+- 솔루션 탐색기에서 Test_ACS 프로젝트 선택
+- 빌드 > 솔루션 빌드
+
+# 또는 MSBuild 사용
+msbuild Test_ACS.csproj /p:Configuration=Debug
+```
+
+## 사용 방법
+
+### 1. 연결 설정
+
+1. **COM 포트 선택**: Xbee 모듈이 연결된 COM 포트 선택
+2. **보레이트 입력**: 기본값 9600 (Xbee 설정에 맞춰 조정)
+3. **연결 버튼 클릭**: 포트 연결
+
+**자동 저장**: 포트와 보레이트는 변경 시 자동으로 저장되며, 다음 실행 시 자동으로 불러옵니다.
+
+### 2. AGV 선택
+
+- **AGV1 (ID:11)**: 첫 번째 AGV 선택
+- **AGV2 (ID:12)**: 두 번째 AGV 선택
+
+**자동 저장**: 선택한 AGV는 자동으로 저장되며, 다음 실행 시 자동으로 선택됩니다.
+
+### 3. 명령 전송
+
+#### SetCurrent (현재 위치 설정)
+- **RFID 번호 입력**: 예) 0001
+- **SetCurrent 버튼 클릭**: AGV의 현재 위치를 지정한 RFID로 설정
+- **자동 저장**: 입력한 RFID 번호는 자동으로 저장됩니다.
+
+#### Goto (RFID 이동 명령)
+- **RFID 번호 입력**: 목표 위치 RFID (예: 0001)
+- **Goto 버튼 클릭**: AGV를 지정한 RFID 위치로 이동
+- **자동 저장**: 입력한 RFID 번호는 자동으로 저장됩니다.
+
+#### GotoAlias (별칭 이동 명령)
+- **별칭(Alias) 입력**: 목표 위치 별칭 (예: CHARGER1, BUFFER2, STATION_A)
+- **GotoAlias 버튼 클릭**: AGV를 지정한 별칭 위치로 이동
+- **참고**: 별칭은 AGV에 미리 등록된 이름으로, RFID 대신 의미 있는 이름 사용
+- **자동 저장**: 입력한 별칭은 자동으로 저장됩니다.
+
+#### Stop (정지)
+- **Stop 버튼 클릭**: AGV 즉시 정지
+
+#### Reset (에러 리셋)
+- **Reset 버튼 클릭**: AGV 에러 상태 초기화
+
+#### Manual (수동 제어)
+- **방향 선택**: 후진, 전진, 좌회전, 우회전
+- **속도 선택**: 느림, 보통, 빠름
+- **시간(초) 입력**: 이동 시간
+- **수동 이동 실행 버튼 클릭**
+
+#### MarkStop (마크센서 정지)
+- **정지 설정 체크**: 마크센서 정지 활성화/비활성화
+- **마크센서 정지 버튼 클릭**
+
+#### LiftControl (리프트 제어)
+- **리프트 상승**: 리프트 올리기
+- **리프트 하강**: 리프트 내리기
+- **리프트 정지**: 리프트 동작 중지
+
+## AGV 상태 확인
+
+프로그램 하단의 "AGV 상태" 그룹박스에서 실시간 AGV 상태를 확인할 수 있습니다:
+
+- **모드**: 수동/자동
+- **실행상태**: 정지/실행/에러
+- **방향**: 직진/좌회전/우회전/마크정지
+- **도달완료**: 목적지 도달 여부 (OFF/ON)
+- **충전**: 충전 상태 (OFF/ON)
+- **카트**: 카트 감지 상태 (없음/있음/알 수 없음)
+- **리프트**: 리프트 위치 (하강/상승/알 수 없음)
+- **현재태그**: 마지막으로 인식한 RFID 태그 번호
+
+상태는 AGV가 주기적으로 전송하는 Status 메시지(cmd=3)를 수신하여 자동으로 업데이트됩니다.
+
+## 로그 확인
+
+프로그램 우측에 3개의 탭으로 로그를 확인할 수 있습니다:
+
+- **송신 (TX)**: ACS에서 AGV로 보낸 명령
+- **수신 (RX)**: AGV에서 ACS로 받은 응답
+- **정보**: 연결 상태, 설정 저장/불러오기, 에러 메시지
+
+## 설정 저장 위치
+
+모든 설정은 실행 파일과 같은 폴더에 저장됩니다:
+- **위치**: `Test_ACS.exe`와 같은 폴더의 `Test_ACS.config` 파일
+- **형식**: JSON 형식으로 저장
+- **저장 항목**:
+ - 마지막 사용 COM 포트
+ - 마지막 사용 보레이트
+ - 마지막 입력 RFID 번호
+ - 마지막 입력 별칭
+ - 마지막 선택 AGV (11 또는 12)
+- **자동 저장**: 설정 변경 시 자동 저장
+- **자동 불러오기**: 프로그램 시작 시 자동 불러오기
+
+예시 설정 파일 (`Test_ACS.config`):
+```json
+{
+ "LastPort": "COM3",
+ "LastBaudRate": "9600",
+ "LastRFID": "0001",
+ "LastAlias": "CHARGER1",
+ "LastAGV": 11
+}
+```
+
+## 프로토콜 상세
+
+### 패킷 구조
+```
+STX (0x02) + Length + ID + Command + Data + CRC16 (2 bytes) + ETX (0x03)
+```
+
+### ACS 명령어 (AGVCommandHE)
+
+| 명령 | 코드 | 데이터 형식 | 설명 |
+|------|------|-------------|------|
+| Goto | 100 | TargetID(2) + RFID(4) | RFID로 목표 위치로 이동 |
+| Stop | 101 | TargetID(2) | 정지 |
+| Reset | 102 | TargetID(2) | 에러 리셋 |
+| SetCurrent | 103 | TargetID(2) + RFID(4) | 현재 위치 설정 |
+| Manual | 104 | TargetID(2) + Direction(1) + Speed(1) + Runtime(1) | 수동 이동 |
+| MarkStop | 105 | TargetID(2) + MarkStop(1) | 마크센서 정지 |
+| LiftControl | 106 | TargetID(2) + LiftCommand(1) | 리프트 제어 |
+| **GotoAlias** | **107** | **TargetID(2) + Alias(ASCII)** | **별칭으로 목표 위치로 이동** |
+
+### 데이터 상세
+
+#### Direction (Manual 명령)
+- 0: 후진 (Back)
+- 1: 전진 (Forward)
+- 2: 좌회전 (Left)
+- 3: 우회전 (Right)
+
+#### Speed (Manual 명령)
+- 0: 느림 (Slow)
+- 1: 보통 (Normal)
+- 2: 빠름 (Fast)
+
+#### LiftCommand (LiftControl 명령)
+- 0: 정지 (Stop)
+- 1: 상승 (Up)
+- 2: 하강 (Down)
+
+## 참고 파일
+
+- **프로토콜 정의**: `SubProject\EnigProtocol\enigprotocol\Commands.cs`
+- **프로토콜 구현**: `SubProject\EnigProtocol\enigprotocol\EEProtocol.cs`
+- **AGV 수신 처리**: `Project\StateMachine\_Xbee.cs`
+
+## 개발자 노트
+
+### 프로젝트 참조
+- ENIGProtocol 프로젝트를 참조하여 프로토콜 기능 사용
+- ProjectReference GUID: {499d8912-4b96-41e5-a70d-cfe797883d65}
+
+### 주요 클래스
+- `EEProtocol`: 패킷 생성 및 파싱
+- `SerialPort`: RS232 통신 관리
+- `MainForm`: UI 및 명령 전송 로직
+
+### 디버깅 팁
+1. 로그 탭에서 송수신 패킷의 HEX 값 확인
+2. CRC 에러 발생 시 프로토콜 버전 확인
+3. 응답이 없을 경우 Xbee 모듈 설정 확인 (PAN ID: 46A5, Channel: 17)
+
+## 라이센스
+
+ENIG AGV 프로젝트의 일부로, 내부 테스트 용도로 사용됩니다.
+
+## 버전 이력
+
+- v1.4.0 (2025-01-12): 설정 파일 저장 방식 변경
+ - 실행 폴더에 JSON 형식으로 설정 저장 (Test_ACS.config)
+ - 설정 파일 직접 편집 가능
+ - 프로그램 이동 시 설정 파일도 함께 이동
+
+- v1.3.0 (2025-01-12): AGV 상태 실시간 표시 기능 추가
+ - AGV 상태 그룹박스 추가 (모드, 실행상태, 방향, 도달완료, 충전, 카트, 리프트, 현재태그)
+ - Status 메시지(cmd=3) 자동 수신 및 UI 업데이트
+ - 상태별 색상 표시로 직관적 모니터링
+ - 프로토콜 문서 업데이트 (LastTag 6바이트, CurrentPath 제거)
+
+- v1.2.0 (2025-01-12): 설정 자동 저장/불러오기
+ - COM 포트, 보레이트, RFID, 별칭, AGV 선택 자동 저장
+ - 프로그램 시작 시 마지막 설정 자동 복원
+
+- v1.1.0 (2025-01-12): GotoAlias 명령어 추가
+ - 별칭(Alias) 기반 이동 명령 지원
+ - UI 레이아웃 최적화
+
+- v1.0.0 (2025-01-11): 초기 버전 생성
+ - ACS 시뮬레이터 기본 기능
+ - ENIGProtocol 연동
+ - 7가지 ACS 명령어 지원 (Goto, Stop, Reset, SetCurrent, Manual, MarkStop, LiftControl)
diff --git a/Cs_HMI/TestProject/Test_ACS/Test_ACS.csproj b/Cs_HMI/TestProject/Test_ACS/Test_ACS.csproj
new file mode 100644
index 0000000..5323343
--- /dev/null
+++ b/Cs_HMI/TestProject/Test_ACS/Test_ACS.csproj
@@ -0,0 +1,92 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D}
+ WinExe
+ Test_ACS
+ Test_ACS
+ v4.8
+ 512
+ true
+
+
+
+ AnyCPU
+ true
+ full
+ false
+ ..\..\..\..\..\..\Amkor\AGV4\
+ DEBUG;TRACE
+ prompt
+ 4
+ false
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ false
+
+
+
+ ..\..\SubProject\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ MainForm.cs
+
+
+
+
+ True
+ True
+ Resources.resx
+
+
+ True
+ True
+ Settings.settings
+
+
+ MainForm.cs
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
+
+ {499d8912-4b96-41e5-a70d-cfe797883d65}
+ ENIGProtocol
+
+
+
+
\ No newline at end of file
diff --git a/Cs_HMI/TestProject/Test_ACS/app.config b/Cs_HMI/TestProject/Test_ACS/app.config
new file mode 100644
index 0000000..1634906
--- /dev/null
+++ b/Cs_HMI/TestProject/Test_ACS/app.config
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ COM1
+
+
+ 9600
+
+
+ 0001
+
+
+ CHARGER1
+
+
+ 11
+
+
+
+
diff --git a/Cs_HMI/TestProject/Test_ACS/packages.config b/Cs_HMI/TestProject/Test_ACS/packages.config
new file mode 100644
index 0000000..efd7b64
--- /dev/null
+++ b/Cs_HMI/TestProject/Test_ACS/packages.config
@@ -0,0 +1,4 @@
+
+
+
+