Test_ACS 프로젝트 추가 - ACS 시뮬레이터 (v1.4.0)
## 신규 기능 - ACS(중앙제어시스템) 시뮬레이터 프로젝트 생성 - 8가지 AGV 제어 명령어 지원: * SetCurrent: 현재 위치 설정 * Goto: RFID 이동 * GotoAlias: 별칭 이동 (v1.1.0) * Stop: 정지 * Reset: 에러 리셋 * Manual: 수동 제어 * MarkStop: 마크센서 정지 * LiftControl: 리프트 제어 ## AGV 상태 실시간 표시 (v1.3.0) - AGV 상태 그룹박스 추가 (8가지 상태 정보) - Status 메시지(cmd=3) 자동 수신 및 UI 업데이트 - 상태별 색상 표시로 직관적 모니터링 ## 설정 관리 - 실행 폴더에 JSON 형식 설정 파일 저장 (v1.4.0) - COM 포트, 보레이트, RFID, 별칭, AGV 선택 자동 저장 - 설정 파일 직접 편집 가능 ## 기술 스택 - .NET Framework 4.8 - ENIGProtocol 프로젝트 참조 - RS232/Xbee 통신 - Newtonsoft.Json 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Submodule Cs_HMI/SubProject/EnigProtocol updated: 070aa848c9...e8cae2c4ee
67
Cs_HMI/TestProject/Test_ACS/AppSettings.cs
Normal file
67
Cs_HMI/TestProject/Test_ACS/AppSettings.cs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Test_ACS
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 애플리케이션 설정을 관리하는 클래스
|
||||||
|
/// </summary>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 설정 파일을 로드합니다
|
||||||
|
/// </summary>
|
||||||
|
public static AppSettings Load()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string configPath = GetConfigFilePath();
|
||||||
|
if (File.Exists(configPath))
|
||||||
|
{
|
||||||
|
string json = File.ReadAllText(configPath);
|
||||||
|
return JsonConvert.DeserializeObject<AppSettings>(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// 로드 실패 시 기본값 반환
|
||||||
|
}
|
||||||
|
|
||||||
|
return new AppSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 설정을 파일에 저장합니다
|
||||||
|
/// </summary>
|
||||||
|
public void Save()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string configPath = GetConfigFilePath();
|
||||||
|
string json = JsonConvert.SerializeObject(this, Formatting.Indented);
|
||||||
|
File.WriteAllText(configPath, json);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// 저장 실패 시 무시
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
162
Cs_HMI/TestProject/Test_ACS/CHANGELOG.md
Normal file
162
Cs_HMI/TestProject/Test_ACS/CHANGELOG.md
Normal file
@@ -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 포트 관리 (연결/해제/새로고침)
|
||||||
828
Cs_HMI/TestProject/Test_ACS/MainForm.Designer.cs
generated
Normal file
828
Cs_HMI/TestProject/Test_ACS/MainForm.Designer.cs
generated
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
515
Cs_HMI/TestProject/Test_ACS/MainForm.cs
Normal file
515
Cs_HMI/TestProject/Test_ACS/MainForm.cs
Normal file
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
120
Cs_HMI/TestProject/Test_ACS/MainForm.resx
Normal file
120
Cs_HMI/TestProject/Test_ACS/MainForm.resx
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
16
Cs_HMI/TestProject/Test_ACS/Program.cs
Normal file
16
Cs_HMI/TestProject/Test_ACS/Program.cs
Normal file
@@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
19
Cs_HMI/TestProject/Test_ACS/Properties/AssemblyInfo.cs
Normal file
19
Cs_HMI/TestProject/Test_ACS/Properties/AssemblyInfo.cs
Normal file
@@ -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")]
|
||||||
63
Cs_HMI/TestProject/Test_ACS/Properties/Resources.Designer.cs
generated
Normal file
63
Cs_HMI/TestProject/Test_ACS/Properties/Resources.Designer.cs
generated
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// 이 코드는 도구를 사용하여 생성되었습니다.
|
||||||
|
// 런타임 버전:4.0.30319.42000
|
||||||
|
//
|
||||||
|
// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
|
||||||
|
// 이러한 변경 내용이 손실됩니다.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace Test_ACS.Properties {
|
||||||
|
using System;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 지역화된 문자열 등을 찾기 위한 강력한 형식의 리소스 클래스입니다.
|
||||||
|
/// </summary>
|
||||||
|
// 이 클래스는 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() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 이 클래스에서 사용하는 캐시된 ResourceManager 인스턴스를 반환합니다.
|
||||||
|
/// </summary>
|
||||||
|
[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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 이 강력한 형식의 리소스 클래스를 사용하여 모든 리소스 조회에 대한 현재 스레드의 CurrentUICulture
|
||||||
|
/// 속성을 재정의합니다.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Globalization.CultureInfo Culture {
|
||||||
|
get {
|
||||||
|
return resourceCulture;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
resourceCulture = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
101
Cs_HMI/TestProject/Test_ACS/Properties/Resources.resx
Normal file
101
Cs_HMI/TestProject/Test_ACS/Properties/Resources.resx
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 1.3
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">1.3</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1">this is my long string</data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
[base64 mime encoded serialized .NET Framework object]
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>1.3</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
86
Cs_HMI/TestProject/Test_ACS/Properties/Settings.Designer.cs
generated
Normal file
86
Cs_HMI/TestProject/Test_ACS/Properties/Settings.Designer.cs
generated
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// 이 코드는 도구를 사용하여 생성되었습니다.
|
||||||
|
// 런타임 버전:4.0.30319.42000
|
||||||
|
//
|
||||||
|
// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
|
||||||
|
// 이러한 변경 내용이 손실됩니다.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
Cs_HMI/TestProject/Test_ACS/Properties/Settings.settings
Normal file
23
Cs_HMI/TestProject/Test_ACS/Properties/Settings.settings
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="Test_ACS.Properties" GeneratedClassName="Settings">
|
||||||
|
<Profiles>
|
||||||
|
<Profile Name="(Default)" />
|
||||||
|
</Profiles>
|
||||||
|
<Settings>
|
||||||
|
<Setting Name="LastPort" Type="System.String" Scope="User">
|
||||||
|
<Value Profile="(Default)">COM1</Value>
|
||||||
|
</Setting>
|
||||||
|
<Setting Name="LastBaudRate" Type="System.String" Scope="User">
|
||||||
|
<Value Profile="(Default)">9600</Value>
|
||||||
|
</Setting>
|
||||||
|
<Setting Name="LastRFID" Type="System.String" Scope="User">
|
||||||
|
<Value Profile="(Default)">0001</Value>
|
||||||
|
</Setting>
|
||||||
|
<Setting Name="LastAlias" Type="System.String" Scope="User">
|
||||||
|
<Value Profile="(Default)">CHARGER1</Value>
|
||||||
|
</Setting>
|
||||||
|
<Setting Name="LastAGV" Type="System.Int32" Scope="User">
|
||||||
|
<Value Profile="(Default)">11</Value>
|
||||||
|
</Setting>
|
||||||
|
</Settings>
|
||||||
|
</SettingsFile>
|
||||||
242
Cs_HMI/TestProject/Test_ACS/README.md
Normal file
242
Cs_HMI/TestProject/Test_ACS/README.md
Normal file
@@ -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)
|
||||||
92
Cs_HMI/TestProject/Test_ACS/Test_ACS.csproj
Normal file
92
Cs_HMI/TestProject/Test_ACS/Test_ACS.csproj
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D}</ProjectGuid>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<RootNamespace>Test_ACS</RootNamespace>
|
||||||
|
<AssemblyName>Test_ACS</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<Deterministic>true</Deterministic>
|
||||||
|
<TargetFrameworkProfile />
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>..\..\..\..\..\..\Amkor\AGV4\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\..\SubProject\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Deployment" />
|
||||||
|
<Reference Include="System.Drawing" />
|
||||||
|
<Reference Include="System.Windows.Forms" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="AppSettings.cs" />
|
||||||
|
<Compile Include="MainForm.cs">
|
||||||
|
<SubType>Form</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="MainForm.Designer.cs">
|
||||||
|
<DependentUpon>MainForm.cs</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Program.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="Properties\Resources.Designer.cs">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Properties\Settings.Designer.cs">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||||
|
<DependentUpon>Settings.settings</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<EmbeddedResource Include="MainForm.resx">
|
||||||
|
<DependentUpon>MainForm.cs</DependentUpon>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Properties\Resources.resx">
|
||||||
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<None Include="app.config" />
|
||||||
|
<None Include="Properties\Settings.settings">
|
||||||
|
<Generator>SettingsSingleFileGenerator</Generator>
|
||||||
|
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\SubProject\EnigProtocol\enigprotocol\ENIGProtocol.csproj">
|
||||||
|
<Project>{499d8912-4b96-41e5-a70d-cfe797883d65}</Project>
|
||||||
|
<Name>ENIGProtocol</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
</Project>
|
||||||
30
Cs_HMI/TestProject/Test_ACS/app.config
Normal file
30
Cs_HMI/TestProject/Test_ACS/app.config
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<configSections>
|
||||||
|
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
|
||||||
|
<section name="Test_ACS.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
|
||||||
|
</sectionGroup>
|
||||||
|
</configSections>
|
||||||
|
<startup>
|
||||||
|
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
|
||||||
|
</startup>
|
||||||
|
<userSettings>
|
||||||
|
<Test_ACS.Properties.Settings>
|
||||||
|
<setting name="LastPort" serializeAs="String">
|
||||||
|
<value>COM1</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="LastBaudRate" serializeAs="String">
|
||||||
|
<value>9600</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="LastRFID" serializeAs="String">
|
||||||
|
<value>0001</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="LastAlias" serializeAs="String">
|
||||||
|
<value>CHARGER1</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="LastAGV" serializeAs="String">
|
||||||
|
<value>11</value>
|
||||||
|
</setting>
|
||||||
|
</Test_ACS.Properties.Settings>
|
||||||
|
</userSettings>
|
||||||
|
</configuration>
|
||||||
4
Cs_HMI/TestProject/Test_ACS/packages.config
Normal file
4
Cs_HMI/TestProject/Test_ACS/packages.config
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net48" />
|
||||||
|
</packages>
|
||||||
Reference in New Issue
Block a user