diff --git a/AGVEmulator/AGVEmulator.csproj b/AGVEmulator/AGVEmulator.csproj
index 4add5f4..9465bf3 100644
--- a/AGVEmulator/AGVEmulator.csproj
+++ b/AGVEmulator/AGVEmulator.csproj
@@ -68,6 +68,7 @@
+
Form
diff --git a/AGVEmulator/RemoteStatus.cs b/AGVEmulator/RemoteStatus.cs
new file mode 100644
index 0000000..557b8b1
--- /dev/null
+++ b/AGVEmulator/RemoteStatus.cs
@@ -0,0 +1,37 @@
+using System.Text;
+
+namespace AGVEmulator
+{
+
+ public class RemoteStatus
+ {
+ public byte Mode { get; set; } // 0=manual, 1=auto
+ public byte RunSt { get; set; } // 0=stop, 1=run, 2=error
+ public byte RunStep { get; set; }
+ public byte RunStepSeq { get; set; }
+ public byte MotorDir { get; set; } // 0=F, 1=B
+ public byte MagnetDir { get; set; } // 0=S, 1=L, 2=R
+ public byte ChargeSt { get; set; } // 0=off, 1=on
+ public byte CartSt { get; set; } // 0=off, 1=on, 2=unknown
+ public byte LiftSt { get; set; } // 0=down, 1=up, 2=unknown
+ public byte ErrorCode { get; set; }
+ public string LastTag { get; set; }
+
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.AppendLine($"Mode: {(Mode == 1 ? "Auto" : "Manual")}");
+ sb.AppendLine($"RunSt: {(RunSt == 0 ? "Stop" : (RunSt == 1 ? "Run" : "Error"))}");
+ sb.AppendLine($"Step: {RunStep}, Seq: {RunStepSeq}");
+ sb.AppendLine($"Dir: {(MotorDir == 1 ? "B" : "F")}, Mag: {(MagnetDir == 1 ? "L" : (MagnetDir == 2 ? "R" : "S"))}");
+ sb.AppendLine($"Charge: {(ChargeSt == 1 ? "ON" : "OFF")}");
+ sb.AppendLine($"Cart: {(CartSt == 1 ? "ON" : (CartSt == 0 ? "OFF" : "Unk"))}");
+ sb.AppendLine($"Lift: {(LiftSt == 1 ? "UP" : (LiftSt == 0 ? "DOWN" : "Unk"))}");
+ sb.Append($"Tag: {LastTag}");
+ return sb.ToString();
+ }
+ }
+
+}
+
+
diff --git a/AGVEmulator/RunCode/_AGV.cs b/AGVEmulator/RunCode/_AGV.cs
index f26ff10..9e76e12 100644
--- a/AGVEmulator/RunCode/_AGV.cs
+++ b/AGVEmulator/RunCode/_AGV.cs
@@ -80,6 +80,7 @@ namespace AGVEmulator
}
break;
}
+ UpdateUIStatus();
}
private void Agv_ValueChanged(object sender, DevAGV.ValueChangedArgs e)
diff --git a/AGVEmulator/RunCode/_XBEE.cs b/AGVEmulator/RunCode/_XBEE.cs
index 9d9696a..1029bce 100644
--- a/AGVEmulator/RunCode/_XBEE.cs
+++ b/AGVEmulator/RunCode/_XBEE.cs
@@ -24,15 +24,41 @@ namespace AGVEmulator
}
private void CAL_ProtocReceived(object sender, ENIG.EEProtocol.DataEventArgs e)
{
- //throw new NotImplementedException();
- var dev = (DeviceType)e.ReceivedPacket.ID;
- if (dev == DeviceType.AGV1 || dev == DeviceType.AGV2)
+ // HMI(Host)에서 호스트로 취급되는 HMI가 보낸 패킷은 ID가 0(ACS)임.
+ // 하지만 xbee.cs에서 CreatePacket 시 PUB.setting.XBE_ID를 사용함.
+ // 에뮬레이터에서는 이 패킷들을 수신하여 상태를 업데이트함.
+
+ var cmd = (ENIGProtocol.AGVCommandEH)e.ReceivedPacket.Command;
+ var data = e.ReceivedPacket.Data;
+
+ if (cmd == ENIGProtocol.AGVCommandEH.Status)
{
- //agv에서 들어오는 데이터
- var cmd = e.ReceivedPacket.Command;
- if(cmd == 3)
+ if (data.Length >= 14)
{
- //status
+ _remoteStatus.Mode = data[0];
+ _remoteStatus.RunSt = data[1];
+ _remoteStatus.RunStep = data[2];
+ _remoteStatus.RunStepSeq = data[3];
+ _remoteStatus.MotorDir = data[4];
+ _remoteStatus.MagnetDir = data[5];
+ _remoteStatus.ChargeSt = data[6];
+ _remoteStatus.CartSt = data[7];
+ _remoteStatus.LiftSt = data[8];
+ _remoteStatus.ErrorCode = data[9];
+ _remoteStatus.LastTag = Encoding.ASCII.GetString(data, 10, 4);
+
+ UpdateUIStatus();
+ }
+ }
+ else if (cmd == ENIGProtocol.AGVCommandEH.Error)
+ {
+ if (data.Length >= 1)
+ {
+ _remoteErrorCode = (ENIGProtocol.AGVErrorCode)data[0];
+ // _remoteErrorMessage = ... Error 메시지 자체는 패킷에 포함되지 않으므로 유틸리티 사용 가능
+ _remoteErrorMessage = ENIGProtocol.AGVUtility.GetAGVErrorMessage(_remoteErrorCode);
+
+ UpdateUIStatus();
}
}
}
diff --git a/AGVEmulator/fMain.Designer.cs b/AGVEmulator/fMain.Designer.cs
index 5c2203b..f20e904 100644
--- a/AGVEmulator/fMain.Designer.cs
+++ b/AGVEmulator/fMain.Designer.cs
@@ -32,34 +32,34 @@ namespace AGVEmulator
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
- AGVEmulator.UC.AgvViewer.ptdata ptdata113 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata114 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata115 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata116 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata117 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata118 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata119 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata120 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata121 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata122 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata123 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata124 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata125 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata126 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata127 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata128 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata129 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata130 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata131 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata132 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata133 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata134 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata135 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata136 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata137 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata138 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata139 = new AGVEmulator.UC.AgvViewer.ptdata();
- AGVEmulator.UC.AgvViewer.ptdata ptdata140 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata29 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata30 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata31 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata32 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata33 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata34 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata35 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata36 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata37 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata38 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata39 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata40 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata41 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata42 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata43 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata44 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata45 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata46 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata47 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata48 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata49 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata50 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata51 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata52 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata53 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata54 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata55 = new AGVEmulator.UC.AgvViewer.ptdata();
+ AGVEmulator.UC.AgvViewer.ptdata ptdata56 = new AGVEmulator.UC.AgvViewer.ptdata();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(fMain));
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.rtBMS = new arCtl.LogTextBox();
@@ -142,6 +142,10 @@ namespace AGVEmulator
this.tabPage2 = new System.Windows.Forms.TabPage();
this.tabPage3 = new System.Windows.Forms.TabPage();
this.panel3 = new System.Windows.Forms.Panel();
+ this.label13 = new System.Windows.Forms.Label();
+ this.button6 = new System.Windows.Forms.Button();
+ this.button13 = new System.Windows.Forms.Button();
+ this.label12 = new System.Windows.Forms.Label();
this.button3 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.nudIDAgv = new System.Windows.Forms.NumericUpDown();
@@ -170,10 +174,11 @@ namespace AGVEmulator
this.sbBMS = new System.Windows.Forms.ToolStripStatusLabel();
this.toolStripStatusLabel2 = new System.Windows.Forms.ToolStripStatusLabel();
this.sbCAL = new System.Windows.Forms.ToolStripStatusLabel();
- this.label12 = new System.Windows.Forms.Label();
- this.label13 = new System.Windows.Forms.Label();
- this.button6 = new System.Windows.Forms.Button();
- this.button13 = new System.Windows.Forms.Button();
+ this.groupBox12 = new System.Windows.Forms.GroupBox();
+ this.groupBox13 = new System.Windows.Forms.GroupBox();
+ this.tbErmsg = new System.Windows.Forms.TextBox();
+ this.tbErCode = new System.Windows.Forms.TextBox();
+ this.rtStatus = new System.Windows.Forms.RichTextBox();
this.groupBox1.SuspendLayout();
this.panel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.trbT2)).BeginInit();
@@ -205,6 +210,8 @@ namespace AGVEmulator
((System.ComponentModel.ISupportInitialize)(this.nudTagNo)).BeginInit();
this.toolStrip1.SuspendLayout();
this.statusStrip1.SuspendLayout();
+ this.groupBox12.SuspendLayout();
+ this.groupBox13.SuspendLayout();
this.SuspendLayout();
//
// groupBox1
@@ -1119,120 +1126,120 @@ namespace AGVEmulator
this.agvViewer1.lastmarkdir = "";
this.agvViewer1.lasttag = "";
this.agvViewer1.lasttagdir = "";
- ptdata113.active = false;
- ptdata113.data = "NOT";
- ptdata113.pos = 30F;
- ptdata114.active = false;
- ptdata114.data = "QA";
- ptdata114.pos = 200F;
- ptdata115.active = false;
- ptdata115.data = "CHG";
- ptdata115.pos = 300F;
- ptdata116.active = false;
- ptdata116.data = "QC";
- ptdata116.pos = 400F;
- ptdata117.active = false;
- ptdata117.data = "#FVI-1";
- ptdata117.pos = 500F;
- ptdata118.active = false;
- ptdata118.data = "#FVI-2";
- ptdata118.pos = 600F;
- ptdata119.active = false;
- ptdata119.data = "#FVI-3";
- ptdata119.pos = 700F;
- ptdata120.active = false;
- ptdata120.data = "#FVI-4";
- ptdata120.pos = 800F;
- ptdata121.active = false;
- ptdata121.data = "#FVI-5";
- ptdata121.pos = 900F;
- ptdata122.active = false;
- ptdata122.data = "POT";
- ptdata122.pos = 970F;
+ ptdata29.active = false;
+ ptdata29.data = "NOT";
+ ptdata29.pos = 30F;
+ ptdata30.active = false;
+ ptdata30.data = "QA";
+ ptdata30.pos = 200F;
+ ptdata31.active = false;
+ ptdata31.data = "CHG";
+ ptdata31.pos = 300F;
+ ptdata32.active = false;
+ ptdata32.data = "QC";
+ ptdata32.pos = 400F;
+ ptdata33.active = false;
+ ptdata33.data = "#FVI-1";
+ ptdata33.pos = 500F;
+ ptdata34.active = false;
+ ptdata34.data = "#FVI-2";
+ ptdata34.pos = 600F;
+ ptdata35.active = false;
+ ptdata35.data = "#FVI-3";
+ ptdata35.pos = 700F;
+ ptdata36.active = false;
+ ptdata36.data = "#FVI-4";
+ ptdata36.pos = 800F;
+ ptdata37.active = false;
+ ptdata37.data = "#FVI-5";
+ ptdata37.pos = 900F;
+ ptdata38.active = false;
+ ptdata38.data = "POT";
+ ptdata38.pos = 970F;
this.agvViewer1.listMRK = new AGVEmulator.UC.AgvViewer.ptdata[] {
- ptdata113,
- ptdata114,
- ptdata115,
- ptdata116,
- ptdata117,
- ptdata118,
- ptdata119,
- ptdata120,
- ptdata121,
- ptdata122};
- ptdata123.active = false;
- ptdata123.data = "9000";
- ptdata123.pos = 80F;
- ptdata124.active = false;
- ptdata124.data = "9001";
- ptdata124.pos = 120F;
- ptdata125.active = false;
- ptdata125.data = "9010";
- ptdata125.pos = 180F;
- ptdata126.active = false;
- ptdata126.data = "9011";
- ptdata126.pos = 220F;
- ptdata127.active = false;
- ptdata127.data = "9020";
- ptdata127.pos = 280F;
- ptdata128.active = false;
- ptdata128.data = "9021";
- ptdata128.pos = 320F;
- ptdata129.active = false;
- ptdata129.data = "9030";
- ptdata129.pos = 380F;
- ptdata130.active = false;
- ptdata130.data = "9031";
- ptdata130.pos = 420F;
- ptdata131.active = false;
- ptdata131.data = "9040";
- ptdata131.pos = 480F;
- ptdata132.active = false;
- ptdata132.data = "9041";
- ptdata132.pos = 520F;
- ptdata133.active = false;
- ptdata133.data = "9050";
- ptdata133.pos = 580F;
- ptdata134.active = false;
- ptdata134.data = "9051";
- ptdata134.pos = 620F;
- ptdata135.active = false;
- ptdata135.data = "9060";
- ptdata135.pos = 680F;
- ptdata136.active = false;
- ptdata136.data = "9061";
- ptdata136.pos = 720F;
- ptdata137.active = false;
- ptdata137.data = "9070";
- ptdata137.pos = 780F;
- ptdata138.active = false;
- ptdata138.data = "9071";
- ptdata138.pos = 820F;
- ptdata139.active = false;
- ptdata139.data = "9000";
- ptdata139.pos = 10F;
- ptdata140.active = false;
- ptdata140.data = "9001";
- ptdata140.pos = 50F;
+ ptdata29,
+ ptdata30,
+ ptdata31,
+ ptdata32,
+ ptdata33,
+ ptdata34,
+ ptdata35,
+ ptdata36,
+ ptdata37,
+ ptdata38};
+ ptdata39.active = false;
+ ptdata39.data = "9000";
+ ptdata39.pos = 80F;
+ ptdata40.active = false;
+ ptdata40.data = "9001";
+ ptdata40.pos = 120F;
+ ptdata41.active = false;
+ ptdata41.data = "9010";
+ ptdata41.pos = 180F;
+ ptdata42.active = false;
+ ptdata42.data = "9011";
+ ptdata42.pos = 220F;
+ ptdata43.active = false;
+ ptdata43.data = "9020";
+ ptdata43.pos = 280F;
+ ptdata44.active = false;
+ ptdata44.data = "9021";
+ ptdata44.pos = 320F;
+ ptdata45.active = false;
+ ptdata45.data = "9030";
+ ptdata45.pos = 380F;
+ ptdata46.active = false;
+ ptdata46.data = "9031";
+ ptdata46.pos = 420F;
+ ptdata47.active = false;
+ ptdata47.data = "9040";
+ ptdata47.pos = 480F;
+ ptdata48.active = false;
+ ptdata48.data = "9041";
+ ptdata48.pos = 520F;
+ ptdata49.active = false;
+ ptdata49.data = "9050";
+ ptdata49.pos = 580F;
+ ptdata50.active = false;
+ ptdata50.data = "9051";
+ ptdata50.pos = 620F;
+ ptdata51.active = false;
+ ptdata51.data = "9060";
+ ptdata51.pos = 680F;
+ ptdata52.active = false;
+ ptdata52.data = "9061";
+ ptdata52.pos = 720F;
+ ptdata53.active = false;
+ ptdata53.data = "9070";
+ ptdata53.pos = 780F;
+ ptdata54.active = false;
+ ptdata54.data = "9071";
+ ptdata54.pos = 820F;
+ ptdata55.active = false;
+ ptdata55.data = "9000";
+ ptdata55.pos = 10F;
+ ptdata56.active = false;
+ ptdata56.data = "9001";
+ ptdata56.pos = 50F;
this.agvViewer1.listTAG = new AGVEmulator.UC.AgvViewer.ptdata[] {
- ptdata123,
- ptdata124,
- ptdata125,
- ptdata126,
- ptdata127,
- ptdata128,
- ptdata129,
- ptdata130,
- ptdata131,
- ptdata132,
- ptdata133,
- ptdata134,
- ptdata135,
- ptdata136,
- ptdata137,
- ptdata138,
- ptdata139,
- ptdata140};
+ ptdata39,
+ ptdata40,
+ ptdata41,
+ ptdata42,
+ ptdata43,
+ ptdata44,
+ ptdata45,
+ ptdata46,
+ ptdata47,
+ ptdata48,
+ ptdata49,
+ ptdata50,
+ ptdata51,
+ ptdata52,
+ ptdata53,
+ ptdata54,
+ ptdata55,
+ ptdata56};
this.agvViewer1.Location = new System.Drawing.Point(241, 0);
this.agvViewer1.Name = "agvViewer1";
this.agvViewer1.Size = new System.Drawing.Size(899, 120);
@@ -1277,6 +1284,8 @@ namespace AGVEmulator
//
// panel3
//
+ this.panel3.Controls.Add(this.groupBox13);
+ this.panel3.Controls.Add(this.groupBox12);
this.panel3.Controls.Add(this.label13);
this.panel3.Controls.Add(this.button6);
this.panel3.Controls.Add(this.button13);
@@ -1301,6 +1310,46 @@ namespace AGVEmulator
this.panel3.Size = new System.Drawing.Size(364, 622);
this.panel3.TabIndex = 15;
//
+ // label13
+ //
+ this.label13.AutoSize = true;
+ this.label13.Location = new System.Drawing.Point(17, 362);
+ this.label13.Name = "label13";
+ this.label13.Size = new System.Drawing.Size(26, 12);
+ this.label13.TabIndex = 19;
+ this.label13.Text = "Exit";
+ //
+ // button6
+ //
+ this.button6.Location = new System.Drawing.Point(204, 349);
+ this.button6.Name = "button6";
+ this.button6.Size = new System.Drawing.Size(133, 38);
+ this.button6.TabIndex = 18;
+ this.button6.Tag = "--";
+ this.button6.Text = "Pick Off";
+ this.button6.UseVisualStyleBackColor = true;
+ this.button6.Click += new System.EventHandler(this.button6_Click_1);
+ //
+ // button13
+ //
+ this.button13.Location = new System.Drawing.Point(65, 349);
+ this.button13.Name = "button13";
+ this.button13.Size = new System.Drawing.Size(133, 38);
+ this.button13.TabIndex = 17;
+ this.button13.Tag = "--";
+ this.button13.Text = "Pick On";
+ this.button13.UseVisualStyleBackColor = true;
+ this.button13.Click += new System.EventHandler(this.button13_Click);
+ //
+ // label12
+ //
+ this.label12.AutoSize = true;
+ this.label12.Location = new System.Drawing.Point(17, 318);
+ this.label12.Name = "label12";
+ this.label12.Size = new System.Drawing.Size(34, 12);
+ this.label12.TabIndex = 16;
+ this.label12.Text = "Enter";
+ //
// button3
//
this.button3.Location = new System.Drawing.Point(204, 305);
@@ -1583,45 +1632,50 @@ namespace AGVEmulator
this.sbCAL.Size = new System.Drawing.Size(19, 17);
this.sbCAL.Text = "●";
//
- // label12
+ // groupBox12
//
- this.label12.AutoSize = true;
- this.label12.Location = new System.Drawing.Point(17, 318);
- this.label12.Name = "label12";
- this.label12.Size = new System.Drawing.Size(34, 12);
- this.label12.TabIndex = 16;
- this.label12.Text = "Enter";
+ this.groupBox12.Controls.Add(this.rtStatus);
+ this.groupBox12.Location = new System.Drawing.Point(6, 393);
+ this.groupBox12.Name = "groupBox12";
+ this.groupBox12.Size = new System.Drawing.Size(355, 147);
+ this.groupBox12.TabIndex = 20;
+ this.groupBox12.TabStop = false;
+ this.groupBox12.Text = "status";
//
- // label13
+ // groupBox13
//
- this.label13.AutoSize = true;
- this.label13.Location = new System.Drawing.Point(17, 362);
- this.label13.Name = "label13";
- this.label13.Size = new System.Drawing.Size(26, 12);
- this.label13.TabIndex = 19;
- this.label13.Text = "Exit";
+ this.groupBox13.Controls.Add(this.tbErCode);
+ this.groupBox13.Controls.Add(this.tbErmsg);
+ this.groupBox13.Dock = System.Windows.Forms.DockStyle.Bottom;
+ this.groupBox13.Location = new System.Drawing.Point(0, 546);
+ this.groupBox13.Name = "groupBox13";
+ this.groupBox13.Size = new System.Drawing.Size(364, 76);
+ this.groupBox13.TabIndex = 21;
+ this.groupBox13.TabStop = false;
+ this.groupBox13.Text = "error";
//
- // button6
+ // tbErmsg
//
- this.button6.Location = new System.Drawing.Point(204, 349);
- this.button6.Name = "button6";
- this.button6.Size = new System.Drawing.Size(133, 38);
- this.button6.TabIndex = 18;
- this.button6.Tag = "--";
- this.button6.Text = "Pick Off";
- this.button6.UseVisualStyleBackColor = true;
- this.button6.Click += new System.EventHandler(this.button6_Click_1);
+ this.tbErmsg.Location = new System.Drawing.Point(13, 45);
+ this.tbErmsg.Name = "tbErmsg";
+ this.tbErmsg.Size = new System.Drawing.Size(287, 21);
+ this.tbErmsg.TabIndex = 0;
//
- // button13
+ // tbErCode
//
- this.button13.Location = new System.Drawing.Point(65, 349);
- this.button13.Name = "button13";
- this.button13.Size = new System.Drawing.Size(133, 38);
- this.button13.TabIndex = 17;
- this.button13.Tag = "--";
- this.button13.Text = "Pick On";
- this.button13.UseVisualStyleBackColor = true;
- this.button13.Click += new System.EventHandler(this.button13_Click);
+ this.tbErCode.Location = new System.Drawing.Point(12, 18);
+ this.tbErCode.Name = "tbErCode";
+ this.tbErCode.Size = new System.Drawing.Size(287, 21);
+ this.tbErCode.TabIndex = 1;
+ //
+ // rtStatus
+ //
+ this.rtStatus.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.rtStatus.Location = new System.Drawing.Point(3, 17);
+ this.rtStatus.Name = "rtStatus";
+ this.rtStatus.Size = new System.Drawing.Size(349, 127);
+ this.rtStatus.TabIndex = 0;
+ this.rtStatus.Text = "";
//
// fMain
//
@@ -1678,6 +1732,9 @@ namespace AGVEmulator
this.toolStrip1.PerformLayout();
this.statusStrip1.ResumeLayout(false);
this.statusStrip1.PerformLayout();
+ this.groupBox12.ResumeLayout(false);
+ this.groupBox13.ResumeLayout(false);
+ this.groupBox13.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
@@ -1798,6 +1855,11 @@ namespace AGVEmulator
private Label label13;
private Button button6;
private Button button13;
+ private GroupBox groupBox13;
+ private GroupBox groupBox12;
+ private TextBox tbErCode;
+ private TextBox tbErmsg;
+ private RichTextBox rtStatus;
}
}
diff --git a/AGVEmulator/fMain.cs b/AGVEmulator/fMain.cs
index 315af05..1d3f375 100644
--- a/AGVEmulator/fMain.cs
+++ b/AGVEmulator/fMain.cs
@@ -8,7 +8,6 @@ using System.Globalization;
using System.IO;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
-using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using static AGVEmulator.DevAGV;
@@ -24,6 +23,10 @@ namespace AGVEmulator
DevAGV AGV;
DevXBE XBE;
+ public RemoteStatus _remoteStatus = new RemoteStatus();
+ public ENIGProtocol.AGVErrorCode _remoteErrorCode = ENIGProtocol.AGVErrorCode.None;
+ public string _remoteErrorMessage = "";
+
// Map Control
private UnifiedAGVCanvas _agvCanvas;
private VirtualAGV _visualAgv;
@@ -980,6 +983,30 @@ namespace AGVEmulator
var target = (byte)nudIDAgv.Value;
this.XBE.SendPickOffExit(target);
}
+
+ public void UpdateUIStatus()
+ {
+ if (this.InvokeRequired)
+ {
+ this.BeginInvoke(new Action(UpdateUIStatus));
+ return;
+ }
+
+ rtStatus.Text = _remoteStatus.ToString();
+ tbErCode.Text = _remoteErrorCode.ToString();
+ tbErmsg.Text = _remoteErrorMessage;
+
+ if (_remoteErrorCode != ENIGProtocol.AGVErrorCode.None)
+ {
+ tbErCode.BackColor = Color.Red;
+ tbErCode.ForeColor = Color.White;
+ }
+ else
+ {
+ tbErCode.BackColor = SystemColors.Window;
+ tbErCode.ForeColor = SystemColors.WindowText;
+ }
+ }
}
}
diff --git a/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.cs b/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.cs
index 3f30bb4..9136863 100644
--- a/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.cs
+++ b/AGVLogic/AGVNavigationCore/Controls/UnifiedAGVCanvas.cs
@@ -349,6 +349,20 @@ namespace AGVNavigationCore.Controls
public MapNode SelectedNode
{
get { return this._selectedNode as MapNode; }
+ set
+ {
+ _selectedNode = value;
+ if (value != null)
+ {
+ _selectedNodes.Clear();
+ _selectedNodes.Add(value);
+ }
+ else
+ {
+ _selectedNodes.Clear();
+ }
+ Invalidate();
+ }
}
///
@@ -393,6 +407,19 @@ namespace AGVNavigationCore.Controls
this.FitToNodes();
}
+ ///
+ /// 맵 데이터를 셋팅합니다
+ ///
+ public void SetMapData(List nodes, List labels = null, List images = null, List marks = null, List magnets = null)
+ {
+ this.Nodes = nodes;
+ this.Labels = labels ?? new List();
+ this.Images = images ?? new List();
+ this.Marks = marks ?? new List();
+ this.Magnets = magnets ?? new List();
+ this.FitToNodes();
+ }
+
///
/// 노드 목록
///
diff --git a/HMI/Project/AGV4.csproj b/HMI/Project/AGV4.csproj
index 497fa76..7b17160 100644
--- a/HMI/Project/AGV4.csproj
+++ b/HMI/Project/AGV4.csproj
@@ -197,6 +197,12 @@
fCounter.cs
+
+ Form
+
+
+ fSetCurrentPosition.cs
+
Form
@@ -412,6 +418,9 @@
fCounter.cs
+
+ fSetCurrentPosition.cs
+
fXbeeSetting.cs
@@ -573,9 +582,7 @@
CommData
-
-
-
+
diff --git a/HMI/Project/Device/Xbee.cs b/HMI/Project/Device/Xbee.cs
index 0b9c459..38727ec 100644
--- a/HMI/Project/Device/Xbee.cs
+++ b/HMI/Project/Device/Xbee.cs
@@ -181,20 +181,20 @@ namespace Project.Device
/// 오류코드를 호스트에 전송합니다
///
///
- public void SendError(ENIGProtocol.AGVErrorCode errcode, string errormessage)
+ public void SendError(ENIGProtocol.AGVErrorCode errcode)
{
// Update global error state so it persists in Status messages
PUB.Result.RunStepErrorCode = errcode;
- PUB.Result.ResultMessage = errormessage;
+ //PUB.Result.ResultMessage = errormessage;
var id = PUB.setting.XBE_ID;
byte cmd = (byte)ENIGProtocol.AGVCommandEH.Error;
- if (errormessage.Length > 30) errormessage = errormessage.Substring(0, 29);
+ // if (errormessage.Length > 30) errormessage = errormessage.Substring(0, 29);
var data = new List();
data.Add((byte)errcode);
- var datamsg = System.Text.Encoding.Default.GetBytes(errormessage);
- data.AddRange(datamsg);
+ //var datamsg = System.Text.Encoding.Default.GetBytes(errormessage);
+ // data.AddRange(datamsg);
var packet = proto.CreatePacket(id, cmd, data.ToArray());
Send(packet);
diff --git a/HMI/Project/Dialog/fSetCurrentPosition.Designer.cs b/HMI/Project/Dialog/fSetCurrentPosition.Designer.cs
new file mode 100644
index 0000000..4e43ab0
--- /dev/null
+++ b/HMI/Project/Dialog/fSetCurrentPosition.Designer.cs
@@ -0,0 +1,230 @@
+namespace Project.Dialog
+{
+ partial class fSetCurrentPosition
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.mainLayout = new System.Windows.Forms.TableLayoutPanel();
+ this.controlPanel = new System.Windows.Forms.Panel();
+ this._lblStatus = new System.Windows.Forms.Label();
+ this.btnForward = new System.Windows.Forms.Button();
+ this.btnBackward = new System.Windows.Forms.Button();
+ this.btnOK = new System.Windows.Forms.Button();
+ this.btnCancel = new System.Windows.Forms.Button();
+ this.btnTurnR90 = new System.Windows.Forms.Button();
+ this.lblTurn = new System.Windows.Forms.Label();
+ this.btnTurnNone = new System.Windows.Forms.Button();
+ this.btnTurnL90 = new System.Windows.Forms.Button();
+ this.label1 = new System.Windows.Forms.Label();
+ this.mainLayout.SuspendLayout();
+ this.controlPanel.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // mainLayout
+ //
+ this.mainLayout.ColumnCount = 1;
+ this.mainLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+ this.mainLayout.Controls.Add(this.controlPanel, 0, 2);
+ this.mainLayout.Controls.Add(this.label1, 0, 0);
+ this.mainLayout.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.mainLayout.Location = new System.Drawing.Point(0, 0);
+ this.mainLayout.Name = "mainLayout";
+ this.mainLayout.RowCount = 3;
+ this.mainLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F));
+ this.mainLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 84.60411F));
+ this.mainLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 15.39589F));
+ this.mainLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+ this.mainLayout.Size = new System.Drawing.Size(1264, 761);
+ this.mainLayout.TabIndex = 0;
+ //
+ // controlPanel
+ //
+ this.controlPanel.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(30)))), ((int)(((byte)(30)))));
+ this.controlPanel.Controls.Add(this._lblStatus);
+ this.controlPanel.Controls.Add(this.btnForward);
+ this.controlPanel.Controls.Add(this.btnBackward);
+ this.controlPanel.Controls.Add(this.btnOK);
+ this.controlPanel.Controls.Add(this.btnCancel);
+ this.controlPanel.Controls.Add(this.btnTurnR90);
+ this.controlPanel.Controls.Add(this.lblTurn);
+ this.controlPanel.Controls.Add(this.btnTurnNone);
+ this.controlPanel.Controls.Add(this.btnTurnL90);
+ this.controlPanel.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.controlPanel.Location = new System.Drawing.Point(3, 652);
+ this.controlPanel.Name = "controlPanel";
+ this.controlPanel.Padding = new System.Windows.Forms.Padding(10);
+ this.controlPanel.Size = new System.Drawing.Size(1258, 106);
+ this.controlPanel.TabIndex = 1;
+ //
+ // _lblStatus
+ //
+ this._lblStatus.Font = new System.Drawing.Font("맑은 고딕", 12F, System.Drawing.FontStyle.Bold);
+ this._lblStatus.ForeColor = System.Drawing.Color.White;
+ this._lblStatus.Location = new System.Drawing.Point(7, 7);
+ this._lblStatus.Margin = new System.Windows.Forms.Padding(3, 10, 20, 0);
+ this._lblStatus.Name = "_lblStatus";
+ this._lblStatus.Size = new System.Drawing.Size(653, 42);
+ this._lblStatus.TabIndex = 0;
+ this._lblStatus.Text = "위치를 선택해 주세요.";
+ this._lblStatus.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ //
+ // btnForward
+ //
+ this.btnForward.BackColor = System.Drawing.Color.DarkSlateGray;
+ this.btnForward.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.btnForward.ForeColor = System.Drawing.Color.White;
+ this.btnForward.Location = new System.Drawing.Point(721, 51);
+ this.btnForward.Name = "btnForward";
+ this.btnForward.Size = new System.Drawing.Size(120, 38);
+ this.btnForward.TabIndex = 1;
+ this.btnForward.Text = "전진 (Forward)";
+ this.btnForward.UseVisualStyleBackColor = false;
+ //
+ // btnBackward
+ //
+ this.btnBackward.BackColor = System.Drawing.Color.DarkSlateGray;
+ this.btnBackward.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.btnBackward.ForeColor = System.Drawing.Color.White;
+ this.btnBackward.Location = new System.Drawing.Point(847, 51);
+ this.btnBackward.Name = "btnBackward";
+ this.btnBackward.Size = new System.Drawing.Size(126, 38);
+ this.btnBackward.TabIndex = 2;
+ this.btnBackward.Text = "후진 (Backward)";
+ this.btnBackward.UseVisualStyleBackColor = false;
+ //
+ // btnOK
+ //
+ this.btnOK.BackColor = System.Drawing.Color.DarkGreen;
+ this.btnOK.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.btnOK.ForeColor = System.Drawing.Color.White;
+ this.btnOK.Location = new System.Drawing.Point(7, 51);
+ this.btnOK.Margin = new System.Windows.Forms.Padding(50, 3, 3, 3);
+ this.btnOK.Name = "btnOK";
+ this.btnOK.Size = new System.Drawing.Size(150, 38);
+ this.btnOK.TabIndex = 7;
+ this.btnOK.Text = "설정 완료";
+ this.btnOK.UseVisualStyleBackColor = false;
+ //
+ // btnCancel
+ //
+ this.btnCancel.BackColor = System.Drawing.Color.Maroon;
+ this.btnCancel.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.btnCancel.ForeColor = System.Drawing.Color.White;
+ this.btnCancel.Location = new System.Drawing.Point(163, 51);
+ this.btnCancel.Name = "btnCancel";
+ this.btnCancel.Size = new System.Drawing.Size(100, 38);
+ this.btnCancel.TabIndex = 8;
+ this.btnCancel.Text = "취소";
+ this.btnCancel.UseVisualStyleBackColor = false;
+ //
+ // btnTurnR90
+ //
+ this.btnTurnR90.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(60)))), ((int)(((byte)(60)))));
+ this.btnTurnR90.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.btnTurnR90.ForeColor = System.Drawing.Color.White;
+ this.btnTurnR90.Location = new System.Drawing.Point(893, 7);
+ this.btnTurnR90.Name = "btnTurnR90";
+ this.btnTurnR90.Size = new System.Drawing.Size(80, 40);
+ this.btnTurnR90.TabIndex = 6;
+ this.btnTurnR90.Text = "R90";
+ this.btnTurnR90.UseVisualStyleBackColor = false;
+ //
+ // lblTurn
+ //
+ this.lblTurn.AutoSize = true;
+ this.lblTurn.ForeColor = System.Drawing.Color.White;
+ this.lblTurn.Location = new System.Drawing.Point(677, 20);
+ this.lblTurn.Margin = new System.Windows.Forms.Padding(20, 10, 5, 0);
+ this.lblTurn.Name = "lblTurn";
+ this.lblTurn.Size = new System.Drawing.Size(35, 12);
+ this.lblTurn.TabIndex = 3;
+ this.lblTurn.Text = "Turn:";
+ //
+ // btnTurnNone
+ //
+ this.btnTurnNone.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(60)))), ((int)(((byte)(60)))));
+ this.btnTurnNone.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.btnTurnNone.ForeColor = System.Drawing.Color.White;
+ this.btnTurnNone.Location = new System.Drawing.Point(721, 7);
+ this.btnTurnNone.Name = "btnTurnNone";
+ this.btnTurnNone.Size = new System.Drawing.Size(80, 40);
+ this.btnTurnNone.TabIndex = 4;
+ this.btnTurnNone.Text = "None";
+ this.btnTurnNone.UseVisualStyleBackColor = false;
+ //
+ // btnTurnL90
+ //
+ this.btnTurnL90.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(60)))), ((int)(((byte)(60)))));
+ this.btnTurnL90.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.btnTurnL90.ForeColor = System.Drawing.Color.White;
+ this.btnTurnL90.Location = new System.Drawing.Point(807, 7);
+ this.btnTurnL90.Name = "btnTurnL90";
+ this.btnTurnL90.Size = new System.Drawing.Size(80, 40);
+ this.btnTurnL90.TabIndex = 5;
+ this.btnTurnL90.Text = "L90";
+ this.btnTurnL90.UseVisualStyleBackColor = false;
+ //
+ // label1
+ //
+ this.label1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.label1.Font = new System.Drawing.Font("맑은 고딕", 12F, System.Drawing.FontStyle.Bold);
+ this.label1.Location = new System.Drawing.Point(3, 0);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(1258, 40);
+ this.label1.TabIndex = 2;
+ this.label1.Text = "현재 위치에 해당하는 노드를 선택하세요";
+ this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ //
+ // fSetCurrentPosition
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(1264, 761);
+ this.Controls.Add(this.mainLayout);
+ this.Name = "fSetCurrentPosition";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "AGV 시작 위치 및 방향 설정";
+ this.mainLayout.ResumeLayout(false);
+ this.controlPanel.ResumeLayout(false);
+ this.controlPanel.PerformLayout();
+ this.ResumeLayout(false);
+
+ }
+
+
+ private System.Windows.Forms.TableLayoutPanel mainLayout;
+ private System.Windows.Forms.Panel controlPanel;
+ private System.Windows.Forms.Label _lblStatus;
+ private System.Windows.Forms.Button btnForward;
+ private System.Windows.Forms.Button btnBackward;
+ private System.Windows.Forms.Label lblTurn;
+ private System.Windows.Forms.Button btnTurnNone;
+ private System.Windows.Forms.Button btnTurnL90;
+ private System.Windows.Forms.Button btnTurnR90;
+ private System.Windows.Forms.Button btnOK;
+ private System.Windows.Forms.Button btnCancel;
+ private System.Windows.Forms.Label label1;
+ }
+}
\ No newline at end of file
diff --git a/HMI/Project/Dialog/fSetCurrentPosition.cs b/HMI/Project/Dialog/fSetCurrentPosition.cs
new file mode 100644
index 0000000..9dc5a78
--- /dev/null
+++ b/HMI/Project/Dialog/fSetCurrentPosition.cs
@@ -0,0 +1,128 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using AGVNavigationCore.Models;
+using AGVNavigationCore.Controls;
+
+namespace Project.Dialog
+{
+ public partial class fSetCurrentPosition : Form
+ {
+ private UnifiedAGVCanvas _canvas;
+ private MapNode _selectedNode;
+ private AgvDirection _selectedDirection = AgvDirection.Forward;
+ private AGVTurn _selectedTurn = AGVTurn.None;
+
+ public MapNode SelectedNode => _selectedNode;
+ public AgvDirection SelectedDirection => _selectedDirection;
+ public AGVTurn SelectedTurn => _selectedTurn;
+
+ public fSetCurrentPosition()
+ {
+ InitializeComponent();
+ if (PUB.setting.FullScreen) this.WindowState = FormWindowState.Maximized;
+ SetupCanvas();
+ WireEvents();
+ this.Load += FSetCurrentPosition_Load;
+
+ }
+
+ private void SetupCanvas()
+ {
+ _canvas = new UnifiedAGVCanvas
+ {
+ Dock = DockStyle.Fill,
+ Mode = UnifiedAGVCanvas.CanvasMode.Run,
+ BackColor = Color.FromArgb(45, 45, 48),
+ ShowGrid=false,
+ };
+ mainLayout.Controls.Add(_canvas, 1, 0);
+ }
+
+ private void WireEvents()
+ {
+ _canvas.NodeSelect += _canvas_NodeSelect;
+ btnForward.Click += (s, e) => { _selectedDirection = AgvDirection.Forward; UpdateStatus(); };
+ btnBackward.Click += (s, e) => { _selectedDirection = AgvDirection.Backward; UpdateStatus(); };
+ btnTurnNone.Click += (s, e) => { _selectedTurn = AGVTurn.None; UpdateStatus(); };
+ btnTurnL90.Click += (s, e) => { _selectedTurn = AGVTurn.L90; UpdateStatus(); };
+ btnTurnR90.Click += (s, e) => { _selectedTurn = AGVTurn.R90; UpdateStatus(); };
+ btnOK.Click += BtnOK_Click;
+ btnCancel.Click += (s, e) => { this.DialogResult = DialogResult.Cancel; this.Close(); };
+ }
+
+ private void FSetCurrentPosition_Load(object sender, EventArgs e)
+ {
+ // 맵 데이터 강제 복사 (PUB과 동일한 맵 사용)
+ if (PUB._mapCanvas != null)
+ {
+ _canvas.SetMapData(PUB._mapCanvas.Nodes, PUB._mapCanvas.Labels, PUB._mapCanvas.Images, PUB._mapCanvas.Marks, PUB._mapCanvas.Magnets);
+ }
+
+ // 마지막 위치 로드
+ var lastPos = PUB.LoadLastPosition();
+ if (lastPos != null)
+ {
+ _selectedNode = _canvas.Nodes.FirstOrDefault(n => n.Id == lastPos.NodeId);
+ _selectedDirection = lastPos.Direction;
+ _selectedTurn = lastPos.Turn;
+
+ if (_selectedNode != null)
+ {
+ _canvas.SelectedNode = _selectedNode;
+ _canvas.PanToNode(_selectedNode.Id);
+ UpdateStatus(isRestore: true);
+ }
+ }
+ this.Show();
+ _canvas.ResetZoom();
+ }
+
+ private void _canvas_NodeSelect(object sender, NodeBase node, MouseEventArgs e)
+ {
+ if (node is MapNode mapNode && mapNode.IsNavigationNode())
+ {
+ _selectedNode = mapNode;
+ _canvas.SelectedNode = mapNode;
+ UpdateStatus();
+ }
+ }
+
+ private void UpdateStatus(bool isRestore = false)
+ {
+ if (_selectedNode == null)
+ {
+ _lblStatus.Text = "위치를 선택해 주세요.";
+ _lblStatus.ForeColor = Color.White;
+ return;
+ }
+
+ string dirStr = _selectedDirection == AgvDirection.Forward ? "전진" : "후진";
+ _lblStatus.Text = $"{(isRestore ? "[복원됨] " : "")}위치: {_selectedNode.Id} ({_selectedNode.ID2}) | 방향: {dirStr} | Turn: {_selectedTurn}";
+ _lblStatus.ForeColor = isRestore ? Color.Yellow : Color.Cyan;
+
+ // 캔버스에 가상 AGV 미리보기 (선택 사항)
+ _canvas.Invalidate();
+ }
+
+ private void BtnOK_Click(object sender, EventArgs e)
+ {
+ if (_selectedNode == null)
+ {
+ MessageBox.Show("AGV의 현재 위치를 맵에서 클릭하여 선택해 주세요.", "알림", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ return;
+ }
+
+ this.DialogResult = DialogResult.OK;
+ this.Close();
+ }
+
+
+ }
+}
diff --git a/HMI/Project/Dialog/fSetCurrentPosition.resx b/HMI/Project/Dialog/fSetCurrentPosition.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/HMI/Project/Dialog/fSetCurrentPosition.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/HMI/Project/PUB.cs b/HMI/Project/PUB.cs
index 4b79f4d..4ce1c3b 100644
--- a/HMI/Project/PUB.cs
+++ b/HMI/Project/PUB.cs
@@ -8,6 +8,8 @@ using System.Media;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System;
+using System.IO;
+using Newtonsoft.Json;
#if SPEECH
using Microsoft.Speech.Synthesis;
@@ -23,6 +25,14 @@ using System.Drawing;
namespace Project
{
+ public class LastPositionData
+ {
+ public string NodeId { get; set; }
+ public AgvDirection Direction { get; set; }
+ public AGVTurn Turn { get; set; }
+ public DateTime SaveTime { get; set; }
+ }
+
public static class PUB
{
//public static Device.CFlag flag;
@@ -633,72 +643,8 @@ namespace Project
if (rfidValue.isEmpty()) return null;
return _mapNodes.Where(t => t.RfidId.Equals(rfidValue)).FirstOrDefault();
}
- public static List FindByNodeAlias(string alias)
- {
- var _mapNodes = PUB._mapCanvas.Nodes;
- if (_mapNodes == null || _mapNodes.Any() == false) return null;
- if (alias.isEmpty()) return null;
- var lst = _mapNodes.Where(t => t.AliasName.Equals(alias));
- if (lst.Any() == false) return null;
- return lst.ToList();
- }
- public static List FindByNodeType(AGVNavigationCore.Models.MapNode type)
- {
- var _mapNodes = PUB._mapCanvas.Nodes;
- if (_mapNodes == null || _mapNodes.Any() == false) return null;
- var lst = _mapNodes.Where(t => t.Type.Equals(type));
- if (lst.Any() == false) return null;
- return lst.ToList();
- }
- ///
- /// RFID 읽기 시 해당 노드 위치로 AGV 업데이트
- ///
- /// 읽은 RFID ID
- /// 모터 방향 (Forward/Backward)
- /// 업데이트 성공 여부
- public static bool UpdateAGVFromRFID(ushort rfidId, AgvDirection motorDirection = AgvDirection.Forward)
- {
- var _mapNodes = PUB._mapCanvas.Nodes;
- if (_virtualAGV == null || _mapNodes == null) return false;
+
- // RFID에 해당하는 노드 찾기
- var node = _mapNodes.FirstOrDefault(n => n.RfidId == rfidId);
- if (node != null)
- {
- _virtualAGV.SetPosition(node, motorDirection);
- RefreshAGVCanvas();
-
- log.Add($"[AGV] RFID {rfidId} 감지 → 노드 {node.Id} 위치 업데이트 (방향: {motorDirection})");
- return true;
- }
-
- log.Add($"[AGV] RFID {rfidId}에 해당하는 노드를 찾을 수 없음");
- return false;
- }
-
- ///
- /// 노드ID로 AGV 위치 업데이트
- ///
- /// 노드 ID
- /// 모터 방향 (Forward/Backward)
- /// 업데이트 성공 여부
- public static bool UpdateAGVToNode(string nodeId, AgvDirection motorDirection = AgvDirection.Forward)
- {
- var _mapNodes = PUB._mapCanvas.Nodes;
- if (_virtualAGV == null || _mapNodes == null) return false;
-
- var node = _mapNodes.FirstOrDefault(n => n.Id == nodeId);
- if (node != null)
- {
- _virtualAGV.SetPosition(node, motorDirection);
- RefreshAGVCanvas();
-
- log.Add($"[AGV] 노드 {nodeId} 위치로 이동 (방향: {motorDirection})");
- return true;
- }
-
- return false;
- }
///
/// 모든 로그를 플러시 합니다.
@@ -718,10 +664,14 @@ namespace Project
/// 새로운 방향
public static void UpdateAGVDirection(AgvDirection direction)
{
- if (_virtualAGV == null) return;
- _virtualAGV.CurrentDirection = direction;
- RefreshAGVCanvas();
+ if (_virtualAGV == null) return;
+ if(_virtualAGV.CurrentDirection != direction)
+ {
+ PUB.log.Add($"[PUB] AGV Direction Change {_virtualAGV.CurrentDirection}->{direction}");
+ _virtualAGV.CurrentDirection = direction;
+ RefreshAGVCanvas();
+ }
}
///
@@ -732,8 +682,13 @@ namespace Project
{
if (_virtualAGV == null) return;
- _virtualAGV.CurrentState = state;
- RefreshAGVCanvas();
+ if(_virtualAGV.CurrentState != state)
+ {
+ PUB.log.Add($"[PUB] AGV State Change {_virtualAGV.CurrentState}->{state}");
+ _virtualAGV.CurrentState = state;
+ RefreshAGVCanvas();
+ }
+
}
///
@@ -760,6 +715,51 @@ namespace Project
}
+ #region "Starting Position Persistence"
+
+ private static string LastPosFilePath => Path.Combine(UTIL.CurrentPath, "Data", "last_pos.json");
+
+ public static void SaveLastPosition()
+ {
+ if (_virtualAGV == null || _virtualAGV.CurrentNode == null) return;
+
+ try
+ {
+ var data = new LastPositionData
+ {
+ NodeId = _virtualAGV.CurrentNode.Id,
+ Direction = _virtualAGV.CurrentDirection,
+ Turn = _virtualAGV.Turn,
+ SaveTime = DateTime.Now
+ };
+
+ string json = JsonConvert.SerializeObject(data, Formatting.Indented);
+ File.WriteAllText(LastPosFilePath, json);
+ }
+ catch (Exception ex)
+ {
+ log.AddE($"[PUB] Failed to save last position: {ex.Message}");
+ }
+ }
+
+ public static LastPositionData LoadLastPosition()
+ {
+ try
+ {
+ if (!File.Exists(LastPosFilePath)) return null;
+
+ string json = File.ReadAllText(LastPosFilePath);
+ return JsonConvert.DeserializeObject(json);
+ }
+ catch (Exception ex)
+ {
+ log.AddE($"[PUB] Failed to load last position: {ex.Message}");
+ return null;
+ }
+ }
+
+ #endregion
+
#endregion
}
diff --git a/HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_IN.cs b/HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_IN.cs
index 55e9274..fec8238 100644
--- a/HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_IN.cs
+++ b/HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_IN.cs
@@ -39,6 +39,21 @@ namespace Project
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
+ {
+ //카트감지
+ if (PUB.NextWorkCmd == ENIGProtocol.AGVCommandHE.PickOnEnter)
+ {
+ //가지러 들어가야하는데 이미 카트가 감지되어있다면 진행할 수 없다.
+ if (PUB.AGV.signal2.cart_detect1 || PUB.AGV.signal2.cart_detect2)
+ {
+ SetRunStepError(ENIGProtocol.AGVErrorCode.CART_EXIST, $"[{funcname}-{PUB.sm.RunStepSeq}] 이미 카트가 감지되어 진입할 수 없습니다");
+ return false;
+ }
+ }
+ PUB.sm.UpdateRunStepSeq();
+ return false;
+ }
+ else if (PUB.sm.RunStepSeq == idx++)
{
//모션 전후진 제어
if (PUB._virtualAGV.Turn != AGVNavigationCore.Models.AGVTurn.L90)
@@ -69,27 +84,27 @@ namespace Project
else
{
//하드웨어 상태 확인
- var turnState = PUB.AGV.TurnInformation?.State ?? arDev.eNarumiTurn.None;
+ //var turnState = PUB.AGV.TurnInformation?.StateNew ?? arDev.eNarumiTurn.None;
- if (turnState == arDev.eNarumiTurn.Left || turnState == arDev.eNarumiTurn.LeftIng)
- {
- //이미 좌회전 중이거나 완료된 하드웨어 상태
- PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] 하드웨어 좌회전 상태 확인됨({turnState}). 명령을 건너뜁니다.");
- PUB.sm.UpdateRunStepSeq();
- }
- else if (turnState == arDev.eNarumiTurn.Right || turnState == arDev.eNarumiTurn.RightIng)
- {
- //비정상 상태 (우회전 중?)
- SetRunStepError(ENIGProtocol.AGVErrorCode.TURN_FAIL, $"[{funcname}-{PUB.sm.RunStepSeq}] 턴 방향 불일치(Current:{turnState}). 우회전 상태에서 좌회전을 시도할 수 없습니다.");
- }
- else
- {
- //정상 (None) -> 턴 명령 실행
- PUB.AGV.AGVMoveLeft180Turn();
- PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] AGV Left Turn");
- VAR.TIME.Update(eVarTime.LastTurnCommandTime);
- PUB.sm.UpdateRunStepSeq();
- }
+ //if (turnState == arDev.eNarumiTurn.Left || turnState == arDev.eNarumiTurn.LeftIng)
+ //{
+ // //이미 좌회전 중이거나 완료된 하드웨어 상태
+ // PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] 하드웨어 좌회전 상태 확인됨({turnState}). 명령을 건너뜁니다.");
+ // PUB.sm.UpdateRunStepSeq();
+ //}
+ //else if (turnState == arDev.eNarumiTurn.Right || turnState == arDev.eNarumiTurn.RightIng)
+ //{
+ // //비정상 상태 (우회전 중?)
+ // SetRunStepError(ENIGProtocol.AGVErrorCode.TURN_FAIL, $"[{funcname}-{PUB.sm.RunStepSeq}] 턴 방향 불일치(Current:{turnState}). 우회전 상태에서 좌회전을 시도할 수 없습니다.");
+ //}
+ //else
+ //{
+ //정상 (None) -> 턴 명령 실행
+ PUB.AGV.AGVMoveLeft180Turn();
+ PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] AGV Left Turn");
+ VAR.TIME.Update(eVarTime.LastTurnCommandTime);
+ PUB.sm.UpdateRunStepSeq();
+ //}
}
PUB._mapCanvas.SetAlertMessage($"턴 진행 중");
return false;
@@ -99,29 +114,31 @@ namespace Project
//이미 완료된 상태라면 대기 과정을 건너뛴다.
if (PUB._virtualAGV.Turn == AGVNavigationCore.Models.AGVTurn.L90)
{
- PUB.sm.UpdateRunStepSeq();
- return false;
+ PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] 이미 턴이완료된 상태입니다");
}
-
- //왼쪽턴이 완료되지 않은경우
- if (PUB.AGV.TurnInformation.State != arDev.eNarumiTurn.Left)
+ else
{
- //움직임 확인을 위해 3초간은 검증을 유예한다
- if (PUB.AGV.TurnInformation.Runtime.TotalSeconds < 3) return false;
-
- //턴 이동 상태가 확인되어야 한다.
- var overtime = 30;
- if (PUB.AGV.TurnInformation.Runtime.TotalSeconds > overtime)
+ //왼쪽턴이 완료되지 않은경우
+ if (PUB.AGV.TurnInformation.State != arDev.eNarumiTurn.Left)
{
- //30초동안 AGV까 움직이지 않았다면 오류 처리한다.
- SetRunStepError(ENIGProtocol.AGVErrorCode.TURN_FAIL, $"[{funcname}] {overtime}초이내 턴 감지 안됨");
+ //움직임 확인을 위해 3초간은 검증을 유예한다
+ if (PUB.AGV.TurnInformation.Runtime.TotalSeconds < 3) return false;
+
+ //턴 이동 상태가 확인되어야 한다.
+ var overtime = 30;
+ if (PUB.AGV.TurnInformation.Runtime.TotalSeconds > overtime)
+ {
+ //30초동안 AGV까 움직이지 않았다면 오류 처리한다.
+ SetRunStepError(ENIGProtocol.AGVErrorCode.TURN_FAIL, $"[{funcname}] {overtime}초이내 턴 감지 안됨");
+ return false;
+ }
+ else PUB._mapCanvas.SetAlertMessage($"턴 진행 중({PUB.AGV.TurnInformation.Runtime.TotalSeconds:N0}/{overtime})");
return false;
}
- else PUB._mapCanvas.SetAlertMessage($"턴 진행 중({PUB.AGV.TurnInformation.Runtime.TotalSeconds:N0}/{overtime})");
- return false;
+ PUB._virtualAGV.Turn = AGVNavigationCore.Models.AGVTurn.L90; //턴완료
+ PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] Turn(left) 완료");
}
- PUB._virtualAGV.Turn = AGVNavigationCore.Models.AGVTurn.L90; //턴완료
- PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] Turn(left) 완료");
+
PUB.sm.UpdateRunStepSeq(); //이미완료된상태이므로 다음으로 진행한다.
return false;
}
@@ -174,7 +191,7 @@ namespace Project
else if (PUB.sm.RunStepSeq == idx++)
{
//저속이동 (후진 진입)
-
+
// [Smart Restart] 재시작 시 안전 검사
// 이미 턴을 완료했고(L90), 현재 마크 센서가 감지된다면(ON),
// 이미 목적지(Mark 2)에 도착한 것으로 간주하여 후진을 생략한다.
@@ -203,7 +220,13 @@ namespace Project
return false;
}
- //후진이동을한다
+ //후진이동을한다
+ PUB.sm.UpdateRunStepSeq();
+ return false;
+ }
+ else if (PUB.sm.RunStepSeq == idx++)
+ {
+ //이동확인을 한다.
PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] 도킹을 위해 후진 이동 시작 (Dir:Backward, Spd:Low)");
PUB._mapCanvas.SetAlertMessage($"도킹을 위해 후진 이동 시작");
PUB.AGV.AGVMoveRun(arDev.Narumi.eRunOpt.Backward);
@@ -213,9 +236,9 @@ namespace Project
else if (PUB.sm.RunStepSeq == idx++)
{
//이동확인을 한다.
- if(PUB.AGV.system1.agv_run == false)
+ if (PUB.AGV.system1.agv_run == false)
{
- if(seqtime.TotalSeconds > 3)
+ if (seqtime.TotalSeconds > 10)
{
SetRunStepError(ENIGProtocol.AGVErrorCode.AGV_RUN_FAIL);
}
diff --git a/HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_OUT.cs b/HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_OUT.cs
index 5514f03..a94892e 100644
--- a/HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_OUT.cs
+++ b/HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_OUT.cs
@@ -80,69 +80,85 @@ namespace Project
}
else if (PUB.sm.RunStepSeq == idx++)
{
- //빈 상태로 아웃해야한다.
- var ret = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
+ if (PUB.AGV.signal1.mark_sensor == false)
{
- Bunki = arDev.Narumi.eBunki.Strate,
- Direction = arDev.Narumi.eMoveDir.Forward,
- PBSSensor = 0,
- Speed = arDev.Narumi.eMoveSpd.Low,
- });
- //명령이 실패되었다면 재시도를 한다
- if (ret != arDev.eNarumiCommandResult.Success)
- {
- if (ret >= arDev.eNarumiCommandResult.Error)
+ //빈 상태로 아웃해야한다.
+ var ret = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
{
- SetRunStepError(ENIGProtocol.AGVErrorCode.AGV_SPEED_SET_FAIL);
+ Bunki = arDev.Narumi.eBunki.Strate,
+ Direction = arDev.Narumi.eMoveDir.Forward,
+ PBSSensor = 0,
+ Speed = arDev.Narumi.eMoveSpd.Low,
+ });
+ //명령이 실패되었다면 재시도를 한다
+ if (ret != arDev.eNarumiCommandResult.Success)
+ {
+ if (ret >= arDev.eNarumiCommandResult.Error)
+ {
+ SetRunStepError(ENIGProtocol.AGVErrorCode.AGV_SPEED_SET_FAIL);
+ }
+ return false;
}
- return false;
+
+ PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] AGV 이동 설정 완료 (Dir:Forward, Spd:Low)");
}
- PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] AGV 이동 설정 완료 (Dir:Forward, Spd:Low)");
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//전진이동
- PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] AGV 전진 구동 시작");
- PUB.AGV.AGVMoveRun(arDev.Narumi.eRunOpt.Forward);
+ if (PUB.AGV.signal1.mark_sensor == false)
+ {
+ PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] AGV 전진 구동 시작");
+ PUB.AGV.AGVMoveRun(arDev.Narumi.eRunOpt.Forward);
+ }
+
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//AGV구동을 확인하고 마크스탑을 설정한다.
- if (PUB.AGV.system1.agv_run == false)
+ if (PUB.AGV.signal1.mark_sensor == false)
{
- if (seqtime.TotalSeconds > 3)
+ if (PUB.AGV.system1.agv_run == false)
{
- //구동이확인되지 않으면 오류처리를 한다.
- SetRunStepError(ENIGProtocol.AGVErrorCode.AGV_RUN_FAIL);
+ if (seqtime.TotalSeconds > 3)
+ {
+ //구동이확인되지 않으면 오류처리를 한다.
+ SetRunStepError(ENIGProtocol.AGVErrorCode.AGV_RUN_FAIL);
+ }
+ return false;
}
- return false;
- }
- PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] AGV 구동 확인 완료");
- //마크스탑설정
- PUB.AGV.AGVMoveStop(funcname, arDev.Narumi.eStopOpt.MarkStop);
- PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] MarkStop 명령 전송 (진출 정지 장소)");
+ PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] AGV 구동 확인 완료");
+ //마크스탑설정
+ PUB.AGV.AGVMoveStop(funcname, arDev.Narumi.eStopOpt.MarkStop);
+ PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] MarkStop 명령 전송 (진출 정지 장소)");
+ }
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
- //마크스탑신호가 3초이내로 들어와야 한다
- if (PUB.AGV.data.Speed != 'S')
+ if (PUB.AGV.signal1.mark_sensor == false)
{
- if (seqtime.TotalSeconds > 3)
+ //마크스탑신호가 3초이내로 들어와야 한다
+ if (PUB.AGV.data.Speed != 'S')
{
- SetRunStepError(ENIGProtocol.AGVErrorCode.MARK_TIMEOUT);
+ if (seqtime.TotalSeconds > 3)
+ {
+ SetRunStepError(ENIGProtocol.AGVErrorCode.MARK_TIMEOUT);
+ return false;
+ }
return false;
}
- return false;
+ PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] MarkStop 신구 확인 완료");
}
- PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] MarkStop 신구 확인 완료");
+ else PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}]마크스탑이 미리 들어와있어. 이동및 스탑을 하지 않습니다");
+
PUB.sm.UpdateRunStepSeq();
return false;
}
@@ -173,18 +189,18 @@ namespace Project
else
{
//하드웨어 상태 확인
- var turnState = PUB.AGV.TurnInformation?.State ?? arDev.eNarumiTurn.None;
- if (turnState == arDev.eNarumiTurn.Right)
- {
- SetRunStepError(ENIGProtocol.AGVErrorCode.TURN_FAIL, $"[{funcname}-{PUB.sm.RunStepSeq}] 턴 방향 불일치(Current:{turnState}). 버퍼진출시에는 LEFT-TURN 상태여야 합니다");
- return false;
- }
- else
- {
- //정상 (None) -> 턴 명령 실행
- PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] AGV Right Turn 명령 전송");
- PUB.AGV.AGVMoveRight180Turn();
- }
+ //var turnState = PUB.AGV.TurnInformation?.StateOld ?? arDev.eNarumiTurn.None;
+ //if (turnState == arDev.eNarumiTurn.Right)
+ //{
+ // SetRunStepError(ENIGProtocol.AGVErrorCode.TURN_FAIL, $"[{funcname}-{PUB.sm.RunStepSeq}] 턴 방향 불일치(Current:{turnState}). 버퍼진출시에는 LEFT-TURN 상태여야 합니다");
+ // return false;
+ //}
+ //else
+ //{
+ //정상 (None) -> 턴 명령 실행
+ PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] AGV Right Turn 명령 전송");
+ PUB.AGV.AGVMoveRight180Turn();
+ //}
}
PUB.sm.UpdateRunStepSeq();
return false;
diff --git a/HMI/Project/StateMachine/Step/_Util.cs b/HMI/Project/StateMachine/Step/_Util.cs
index b756173..ccc9056 100644
--- a/HMI/Project/StateMachine/Step/_Util.cs
+++ b/HMI/Project/StateMachine/Step/_Util.cs
@@ -80,6 +80,8 @@ namespace Project
{
errmsg = ENIGProtocol.AGVUtility.GetAGVErrorMessage(ecode);
}
+ PUB.Result.ResultMessage = errmsg;
+ PUB.XBE.SendError(ecode);
PUB.AGV.AGVMoveStop(errmsg);
PUB.log.AddE(errmsg);
diff --git a/HMI/Project/StateMachine/_AGV.cs b/HMI/Project/StateMachine/_AGV.cs
index e5669c5..acde730 100644
--- a/HMI/Project/StateMachine/_AGV.cs
+++ b/HMI/Project/StateMachine/_AGV.cs
@@ -61,12 +61,8 @@ namespace Project
var syncDir = PUB.AGV.data.Direction == 'B' ? AgvDirection.Backward : AgvDirection.Forward;
// [Sync] Update VirtualAGV Direction
- if (PUB._virtualAGV != null)
- {
- if (PUB._virtualAGV.CurrentDirection != syncDir)
- PUB.UpdateAGVDirection(syncDir);
- }
-
+ if (PUB._virtualAGV != null && PUB._virtualAGV.CurrentDirection != syncDir)
+ PUB.UpdateAGVDirection(syncDir);
// [Sync] Update VirtualAGV State
AGVState syncState = AGVState.Idle;
@@ -107,7 +103,7 @@ namespace Project
VAR.BOOL[eVarBool.FLAG_CHARGEONA] = agv_chg;
}
-
+ //충전기위치오류
if (PUB.AGV.error.Charger_pos_error != VAR.BOOL[eVarBool.CHG_POSERR])
{
if (PUB.AGV.error.Charger_pos_error)
@@ -117,15 +113,6 @@ namespace Project
VAR.BOOL[eVarBool.CHG_POSERR] = PUB.AGV.error.Charger_pos_error;
}
- ////나르미가 멈췄다면 다음 마크 이동 기능이 OFF 된다
- //if (agv_stp)
- //{
- // if (VAR.BOOL[eVarBool.NEXTSTOP_MARK])
- // {
- // VAR.BOOL[eVarBool.NEXTSTOP_MARK] = false;
- // PUB.logagv.Add($"NEXTSTOP_MARK 변경({VAR.BOOL[eVarBool.NEXTSTOP_MARK]})");
- // }
- //}
//마크센서 상태가 변경이 되었다면
if (VAR.BOOL[eVarBool.MARK_SENSOR] != PUB.AGV.signal1.mark_sensor)
@@ -155,9 +142,9 @@ namespace Project
case arDev.Narumi.DataType.TAG:
{
//자동 실행 중이다.
-
PUB.Result.LastTAG = PUB.AGV.data.TagNo;//.ToString("0000");
PUB.log.Add($"[_AGV] AGV 태그수신 : {PUB.AGV.data.TagNo} LastTag:{PUB.Result.LastTAG}");
+
//POT/NOT 보면 일단 바로 멈추게한다
if (PUB.Result.CurrentPos == ePosition.POT || PUB.Result.CurrentPos == ePosition.NOT)
{
@@ -197,8 +184,7 @@ namespace Project
var MotDireciton = PUB.AGV.data.Direction == 'B' ? AgvDirection.Backward : AgvDirection.Forward;
PUB._mapCanvas.SetAGVPosition(PUB.setting.MCID, CurrentNode, MotDireciton);
PUB._virtualAGV.SetPosition(CurrentNode, MotDireciton);
-
- //방향을 다시 확인하여. 기존 경로의 무결성을 검증한다, 필요한 경우 다시 계산할 필요가 있다.
+ PUB.SaveLastPosition();
}
//태그를 읽었다면 상태를 바로 전송한다
@@ -264,7 +250,6 @@ namespace Project
$"S/W 턴 상태: {PUB._virtualAGV.Turn}\n" +
$"H/W 턴 상태: {PUB.AGV.TurnInformation?.State}\n" +
$"위치 확정: {PUB._virtualAGV.IsPositionConfirmed} (RFID {PUB._virtualAGV.DetectedRfidCount}개)\n" +
-
$"대상 노드: {targetpos}\n" +
$"상세 경로: {pathdetail}";
diff --git a/HMI/Project/StateMachine/_Loop.cs b/HMI/Project/StateMachine/_Loop.cs
index 6bbc4e2..86304d6 100644
--- a/HMI/Project/StateMachine/_Loop.cs
+++ b/HMI/Project/StateMachine/_Loop.cs
@@ -206,7 +206,6 @@ namespace Project
if (PUB._mapCanvas != null)
PUB._mapCanvas.SetSyncStatus("설정 동기화", 0f, "환경설정 값으로 AGV컨트롤러를 설정 합니다");
}));
-
}
if (_SM_RUN_SYNC(runStepisFirst, PUB.sm.GetRunSteptime))
{
diff --git a/HMI/Project/StateMachine/_Xbee.cs b/HMI/Project/StateMachine/_Xbee.cs
index 72658ff..b2faf04 100644
--- a/HMI/Project/StateMachine/_Xbee.cs
+++ b/HMI/Project/StateMachine/_Xbee.cs
@@ -39,9 +39,17 @@ namespace Project
//대상디바이스
var TargetID = data[0];
- //해당 패킷의 대상이 나라면 처리한다.
+ //해당 패킷의 대상이 내가아니면 처리하지 않는다
if (PUB.setting.XBE_ID != TargetID) return;
+
+ //자동실행모드가 아니라면 무조건 에러를 반환한다
+ if (VAR.BOOL[eVarBool.FLAG_AUTORUN] == false)
+ {
+ SetRunStepError(ENIGProtocol.AGVErrorCode.ManualMode, "현재 자동실행 모드가 아닙니다");
+ return;
+ }
+
switch (cmd)
{
@@ -56,8 +64,8 @@ namespace Project
var node = PUB._mapCanvas.Nodes.FirstOrDefault(t => t.RfidId == currtagValue);
if (node == null)
{
- PUB.log.AddE($"[{logPrefix}-SetCurrent] 노드정보를 찾을 수 없습니다 RFID:{currTag}");
- PUB.XBE.SendError(ENIGProtocol.AGVErrorCode.EmptyNode, $"{currTag}");
+ var ermsg = ($"[{logPrefix}-SetCurrent] 노드정보를 찾을 수 없습니다 RFID:{currTag}");
+ SetRunStepError(ENIGProtocol.AGVErrorCode.EmptyNode, ermsg);
return;
}
else
@@ -83,16 +91,16 @@ namespace Project
var currNode = PUB._virtualAGV.CurrentNode;
if (currNode == null)
{
- PUB.log.AddE($"[{logPrefix}-{cmd}] 현재 노드를 알 수 없습니다");
- PUB.XBE.SendError(ENIGProtocol.AGVErrorCode.EmptyNode, "Unknown Current Node");
+ var msg = $"[{logPrefix}-{cmd}] 현재 노드를 알 수 없습니다";
+ SetRunStepError(ENIGProtocol.AGVErrorCode.EmptyNode, msg);
return;
}
var targetNode = PUB._virtualAGV.TargetNode;
if (targetNode == null)
{
- PUB.log.AddE($"[{logPrefix}-{cmd}] 목표 노드를 알 수 없습니다");
- PUB.XBE.SendError(ENIGProtocol.AGVErrorCode.EmptyNode, "Unknown Target Node");
+ var msg = $"[{logPrefix}-{cmd}] 목표 노드를 알 수 없습니다";
+ SetRunStepError(ENIGProtocol.AGVErrorCode.EmptyNode, msg);
return;
}
@@ -119,7 +127,7 @@ namespace Project
PUB.sm.SetNewRunStep(nextStep);
}
break;
- case ENIGProtocol.AGVCommandHE.PickOnExit:
+ case ENIGProtocol.AGVCommandHE.PickOnExit:
case ENIGProtocol.AGVCommandHE.PickOffExit:
{
Resultclear();
@@ -129,16 +137,16 @@ namespace Project
var currNode = PUB._virtualAGV.CurrentNode;
if (currNode == null)
{
- PUB.log.AddE($"[{logPrefix}-{cmd}] 현재 노드를 알 수 없습니다");
- PUB.XBE.SendError(ENIGProtocol.AGVErrorCode.EmptyNode, "Unknown Current Node");
+ var msg = $"[{logPrefix}-{cmd}] 현재 노드를 알 수 없습니다";
+ SetRunStepError(ENIGProtocol.AGVErrorCode.EmptyNode, msg);
return;
}
var targetNode = PUB._virtualAGV.TargetNode;
if (targetNode == null)
{
- PUB.log.AddE($"[{logPrefix}-{cmd}] 목표 노드를 알 수 없습니다");
- PUB.XBE.SendError(ENIGProtocol.AGVErrorCode.EmptyNode, "Unknown Target Node");
+ var msg = $"[{logPrefix}-{cmd}] 목표 노드를 알 수 없습니다";
+ SetRunStepError(ENIGProtocol.AGVErrorCode.EmptyNode, msg);
return;
}
@@ -198,8 +206,7 @@ namespace Project
//자동상태가아니라면 처리하지 않는다.
if (VAR.BOOL[eVarBool.FLAG_AUTORUN] == false)
{
- PUB.log.AddE($"[{logPrefix}-Goto] 자동실행상태가 아닙니다");
- PUB.XBE.SendError(ENIGProtocol.AGVErrorCode.ManualMode, $"{currTag}");
+ SetRunStepError(ENIGProtocol.AGVErrorCode.ManualMode, $"[{logPrefix}-Goto] 자동실행상태가 아닙니다");
return;
}
@@ -207,8 +214,7 @@ namespace Project
PUB._virtualAGV.TargetNode = targetNode;
if (targetNode == null)
{
- PUB.log.AddE($"[{logPrefix}-Goto] 노드정보를 찾을 수 없습니다 RFID:{currTag}");
- PUB.XBE.SendError(ENIGProtocol.AGVErrorCode.EmptyNode, $"{currTag}");
+ SetRunStepError(ENIGProtocol.AGVErrorCode.EmptyNode, $"[{logPrefix}-Goto] 노드정보를 찾을 수 없습니다 RFID:{currTag}");
return;
}
@@ -348,8 +354,7 @@ namespace Project
break;
default:
- PUB.logagv.AddE($"Unknown Command : {cmd} Sender:{e.ReceivedPacket.ID}, Target:{data[0]}");
- PUB.XBE.SendError(ENIGProtocol.AGVErrorCode.UnknownCommand, $"{cmd}");
+ SetRunStepError(ENIGProtocol.AGVErrorCode.UnknownCommand, $"Unknown Command : {cmd} Sender:{e.ReceivedPacket.ID}, Target:{data[0]}");
break;
}
}
diff --git a/HMI/Project/fMain.cs b/HMI/Project/fMain.cs
index bff14eb..bed37db 100644
--- a/HMI/Project/fMain.cs
+++ b/HMI/Project/fMain.cs
@@ -289,21 +289,17 @@ namespace Project
PUB._mapCanvas.MapFileName = filePath.FullName;
// 🔥 가상 AGV 초기화 (첫 노드 위치에 생성)
- if (PUB._virtualAGV == null && PUB._mapCanvas.Nodes.Count > 0)
+ if (PUB._virtualAGV == null)
{
- var startNode = PUB._mapCanvas.Nodes.FirstOrDefault(n => n.IsNavigationNode());
- if (startNode != null)
- {
- PUB._virtualAGV = new VirtualAGV(PUB.setting.MCID, startNode.Position, AgvDirection.Forward);
- PUB._virtualAGV.LowBatteryThreshold = PUB.setting.BatteryLimit_Low;
- PUB._virtualAGV.SetPosition(startNode, AgvDirection.Forward);
+ PUB._virtualAGV = new VirtualAGV(PUB.setting.MCID, Point.Empty, AgvDirection.Forward);
+ PUB._virtualAGV.LowBatteryThreshold = PUB.setting.BatteryLimit_Low;
+ //PUB._virtualAGV.SetPosition(startNode, AgvDirection.Forward);
- // 캔버스에 AGV 리스트 설정
- var agvList = new System.Collections.Generic.List { PUB._virtualAGV };
- PUB._mapCanvas.AGVList = agvList;
+ // 캔버스에 AGV 리스트 설정
+ var agvList = new System.Collections.Generic.List { PUB._virtualAGV };
+ PUB._mapCanvas.AGVList = agvList;
- PUB.log.Add($"가상 AGV 생성: {startNode.Id} 위치");
- }
+ PUB.log.Add($"가상 AGV 생성: PointZero 위치");
}
else if (PUB._virtualAGV != null)
{
@@ -313,6 +309,25 @@ namespace Project
PUB._mapCanvas.AGVList = agvList;
}
PUB.log.Add($"맵 파일 로드 완료: {filePath.Name}, 노드 수: {result.Nodes.Count}");
+
+ // 🔥 초기 위치 설정 및 확인 화면 표시
+ this.BeginInvoke(new Action(() =>
+ {
+ using (var f = new Dialog.fSetCurrentPosition())
+ {
+ if (f.ShowDialog() == DialogResult.OK)
+ {
+ if (f.SelectedNode != null)
+ {
+ PUB._virtualAGV.Turn = f.SelectedTurn;
+ PUB._virtualAGV.SetPosition(f.SelectedNode, f.SelectedDirection);
+ PUB._mapCanvas.SetAGVPosition(PUB.setting.MCID, f.SelectedNode, f.SelectedDirection);
+ PUB.SaveLastPosition();
+ PUB.log.Add($"[초기위치] 설정 완료: {f.SelectedNode.Id}, {f.SelectedDirection}, Turn:{f.SelectedTurn}");
+ }
+ }
+ }
+ }));
}
else
{
diff --git a/HMI/SubProject/AGV/Command.cs b/HMI/SubProject/AGV/Command.cs
index 29b62e9..625ddec 100644
--- a/HMI/SubProject/AGV/Command.cs
+++ b/HMI/SubProject/AGV/Command.cs
@@ -34,6 +34,7 @@ namespace arDev
}
}
public eNarumiTurn State { get; set; }
+ //public eNarumiTurn StateNew { get; set; }
public NarumiTurnInfo()
{
Start = new DateTime(1982, 11, 23);
diff --git a/HMI/SubProject/AGV/Narumi.cs b/HMI/SubProject/AGV/Narumi.cs
index 6a61665..95d048b 100644
--- a/HMI/SubProject/AGV/Narumi.cs
+++ b/HMI/SubProject/AGV/Narumi.cs
@@ -160,11 +160,19 @@ namespace arDev
// [Turn Completion Check]
if (frame.DataString.Contains("LEFT-TURN OK"))
{
- if (TurnInformation != null) { TurnInformation.State = eNarumiTurn.Left; TurnInformation.End = DateTime.Now; }
+ if (TurnInformation != null)
+ {
+ TurnInformation.State = eNarumiTurn.Left;
+ TurnInformation.End = DateTime.Now;
+ }
}
else if (frame.DataString.Contains("RIGHT-TURN OK"))
{
- if (TurnInformation != null) { TurnInformation.State = eNarumiTurn.Right; TurnInformation.End = DateTime.Now; }
+ if (TurnInformation != null)
+ {
+ TurnInformation.State = eNarumiTurn.Right;
+ TurnInformation.End = DateTime.Now;
+ }
}
// $로 시작되는 AGV 상태 표시
//var text_Sts_Etc = Encoding.Default.GetString(bRcvData, 3, bRcvData.Length - 2).TrimStart(' '); //20210311 김정만 - SmartX FrameWork 사용 안함으로 주석처리
@@ -278,23 +286,23 @@ namespace arDev
//agv가 멈춰있고 들어온경우, 턴 작업이었다면 턴 셋팅을 한다
// [REMOVED] Logic replaced by message-based check ($AGV...TURN OK)
- if (false && system1.agv_run == false && system1.agv_stop == true &&
- TurnInformation != null)
- {
- if (TurnInformation.Start.Year > 2000)
- {
- if (TurnInformation.State == eNarumiTurn.LeftIng || TurnInformation.State == eNarumiTurn.RightIng)
- {
- TurnInformation.End = DateTime.Now;
- if (TurnInformation.State == eNarumiTurn.LeftIng) TurnInformation.State = eNarumiTurn.Left;
- if (TurnInformation.State == eNarumiTurn.RightIng) TurnInformation.State = eNarumiTurn.Right;
- }
- }
- else
- {
- //시작시간이 설정되지 않았다면 처리하지 않는다.
- }
- }
+ //if (false && system1.agv_run == false && system1.agv_stop == true &&
+ // TurnInformation != null)
+ //{
+ // if (TurnInformation.Start.Year > 2000)
+ // {
+ // if (TurnInformation.StateNew == eNarumiTurn.LeftIng || TurnInformation.StateNew == eNarumiTurn.RightIng)
+ // {
+ // TurnInformation.End = DateTime.Now;
+ // if (TurnInformation.State == eNarumiTurn.LeftIng) TurnInformation.State = eNarumiTurn.Left;
+ // if (TurnInformation.State == eNarumiTurn.RightIng) TurnInformation.State = eNarumiTurn.Right;
+ // }
+ // }
+ // else
+ // {
+ // //시작시간이 설정되지 않았다면 처리하지 않는다.
+ // }
+ //}
if (idx <= rcvdNow.Length - 2)
{