Files
ENIG/Cs_HMI/TestProject/Test_ACS/MainForm.cs
backuppc 1f37871336 ..
2025-12-17 14:54:33 +09:00

577 lines
19 KiB
C#

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();
}
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)
var device = e.ReceivedPacket.ID;
var command = (ENIGProtocol.AGVCommandEH)e.ReceivedPacket.Command;
switch (command)
{
case AGVCommandEH.Status:
UpdateAGVStatus(e.ReceivedPacket.Data);
break;
case AGVCommandEH.Error:
var errorcode = (AGVErrorCode)e.ReceivedPacket.Data[0];
var errorMessage = System.Text.Encoding.UTF8.GetString(e.ReceivedPacket.Data, 1, e.ReceivedPacket.Data.Length - 1);
AddLog($"Error Received : {errorcode} ID:{e.ReceivedPacket.ID} MSG:{errorMessage}", LogType.Info);
break;
default:
AddLog($"unknown command:{command}", LogType.Error);
break;
}
}
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);
SaveSettings();
}
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 targetID = selectedAGV.ToString("X2");
var rfidBytes = Encoding.ASCII.GetBytes(txtRFID.Text.PadLeft(4, '0'));
var rfidHex = string.Join("", rfidBytes.Select(b => b.ToString("X2")));
var dataStr = targetID + rfidHex;
SendCommand(AGVCommandHE.SetCurrent, dataStr);
}
private void btnGoto_Click(object sender, EventArgs e)
{
// Goto: data = TargetID(2 hex) + RFID(4 hex)
var targetID = selectedAGV.ToString("X2");
var rfidBytes = Encoding.ASCII.GetBytes(txtRFID.Text.PadLeft(4, '0'));
var rfidHex = string.Join("", rfidBytes.Select(b => b.ToString("X2")));
var dataStr = targetID + rfidHex;
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);
SaveSettings();
}
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)
{
var but = sender as Button;
if (but.Tag == null) return;
var tagstr = but.Tag.ToString();
var targetID = selectedAGV.ToString("X2");
var direction = byte.Parse(tagstr);// //back
var speed = (byte)0;// cmbSpeed.SelectedIndex;
if (radSpdM.Checked) speed = 1;
else if (radSpdH.Checked) speed = 2;
var dataBytes = new byte[] { direction, speed };
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")));
//정보를 조금더 추출한다.
var Sender = packet[2];
if (Sender == 0x00)
{
var Receiver = packet[4];
var strdata = System.Text.Encoding.Default.GetString(dataBytes, 1, dataBytes.Length - 1);// (dataHexString.Substring(2), 16);
AddLog($"{hexString}|{command}({(byte)command:X2}) From:{Sender} To:{Receiver} => {dataHexString} STR:{strdata}", LogType.TX);
}
else
{
AddLog($"{hexString}|{command}({(byte)command:X2}) From:{Sender} => {dataHexString}", LogType.TX);
}
}
catch (Exception ex)
{
AddLog($"전송 실패: {ex.Message}", LogType.Error);
}
}
private void UpdateAGVStatus(byte[] data)
{
if (data.Length < 12)
{
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;
}
// Mot Direction[1]: 0=forward, 1:backward
switch (data[2])
{
case 0:
lblDirectionValue.Text = "전진";
break;
case 1:
lblDirectionValue.Text = "후진";
break;
default:
lblDirectionValue.Text = "??";
break;
}
// Direction[1]: 0=straight, 1=left, 2=right, 3=markstop
switch (data[3])
{
case 0:
lblDirectionValue.Text += "/직진";
break;
case 1:
lblDirectionValue.Text += "/좌회전";
break;
case 2:
lblDirectionValue.Text += "/우회전";
break;
default:
lblDirectionValue.Text += "/??";
break;
}
// Inposition[1]: 0=off, 1=on
lblInpositionValue.Text = data[4] == 0 ? "OFF" : "ON";
lblInpositionValue.ForeColor = data[4] == 0 ? Color.Gray : Color.Green;
// ChargeSt[1]: 0=off, 1=on
lblChargeStValue.Text = data[5] == 0 ? "OFF" : "ON";
lblChargeStValue.ForeColor = data[5] == 0 ? Color.Gray : Color.Orange;
// CartSt[1]: 0=off, 1=on, 2=unknown
switch (data[6])
{
case 0:
lblCartStValue.Text = "없음";
lblCartStValue.ForeColor = Color.Gray;
break;
case 1:
lblCartStValue.Text = "있음";
lblCartStValue.ForeColor = Color.Green;
break;
default:
lblCartStValue.Text = "??";
lblCartStValue.ForeColor = Color.Red;
break;
}
// LiftSt[1]: 0=down, 1=up, 2=unknown
switch (data[7])
{
case 0:
lblLiftStValue.Text = "하강";
lblLiftStValue.ForeColor = Color.Blue;
break;
case 1:
lblLiftStValue.Text = "상승";
lblLiftStValue.ForeColor = Color.Green;
break;
default:
lblLiftStValue.Text = "??";
lblLiftStValue.ForeColor = Color.Red;
break;
}
string lastTag = Encoding.ASCII.GetString(data, 8, 4);
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)
{
if (serialPort != null && serialPort.IsOpen)
{
serialPort.Close();
}
base.OnFormClosing(e);
}
private void btAMove_Click(object sender, EventArgs e)
{
var targetID = selectedAGV.ToString("X2");
byte Motdirection = 0;// (byte)cmbMotDirection.SelectedIndex;
if (radForw.Checked) Motdirection = 1;
byte Magdirection = 0;
if (radLeft.Checked) Magdirection = 1;
else if (radRight.Checked) Magdirection = 2;
byte speed = 0;// (byte)cmbAutoSpeed.SelectedIndex;
if (radSpdM.Checked) speed = 1;
else if (radSpdH.Checked) speed = 2;
var dataBytes = new byte[] { Motdirection, Magdirection, speed };
var dataStr = targetID + string.Join("", dataBytes.Select(b => b.ToString("X2")));
SendCommand(AGVCommandHE.AutoMove, dataStr);
}
private void button2_Click(object sender, EventArgs e)
{
// Stop: data = TargetID(2 hex)
var targetID = selectedAGV.ToString("X2");
SendCommand(AGVCommandHE.Stop, targetID);
}
private void groupBox2_Enter(object sender, EventArgs e)
{
}
}
}