This commit is contained in:
chi
2025-06-30 13:48:19 +09:00
parent 02e71d7446
commit 00dd50192b
29 changed files with 2397 additions and 1136 deletions

View File

@@ -19,7 +19,7 @@ namespace Project.Device
public string buffer = string.Empty;
public System.Text.StringBuilder newbuffer = new StringBuilder();
public string errorMessage = string.Empty;
public DateTime LastStatusSendTime = DateTime.Now;
public DateTime LastStatusSendTime { get; set; } = DateTime.Now;
private EEProtocol proto;
public class MessageArgs : EventArgs

View File

@@ -26,16 +26,11 @@ namespace Project
return;
}
//사용자 스텝처리가 아닌경우에만 검사
//if (Pub.flag.get(eFlag.UserStepCheck) == false)
//가동불가 조건 확인
if (CheckStopCondition() == false)
{
//가동불가 조건 확인
if (CheckStopCondition() == false)
{
PUB.sm.SetNewStep(eSMStep.PAUSE);
return;
}
PUB.sm.SetNewStep(eSMStep.PAUSE);
return;
}
//이머전시상태라면 stop 처리한다.
@@ -46,13 +41,6 @@ namespace Project
PUB.sm.SetNewStep(eSMStep.IDLE);
}
//실행스텝보정
//if (Pub.sm.runStep == eRunStep.NOTSET && Pub.sm.runStepNew == eRunStep.NOTSET)
//{
// Pub.sm.setNewRunStep(eRunStep.IDLE);
// Pub.log.Add("RUnStep Initialize");
//}
//스텝이 변경되었다면?
if (PUB.sm.RunStep != PUB.sm.RunStepNew)
{
@@ -88,7 +76,7 @@ namespace Project
//if (PUB.Result != null && PUB.sm != null)
// EEMStatus.AddEEDBSQL(PUB.sm.Step, PUB.sm.RunStep.ToString(), PUB.Result.TargetPos.ToString());
PUB.Speak(Lang.) ;
PUB.Speak(Lang.);
PUB.sm.SetNewRunStep(ERunStep.CHARGECHECK);
return;
}
@@ -143,8 +131,8 @@ namespace Project
PUB.Speak(Lang.);
//230601
// if (PUB.Result != null && PUB.sm != null)
// EEMStatus.AddEEDBSQL(PUB.sm.Step, PUB.sm.RunStep.ToString(), PUB.Result.TargetPos.ToString());
// if (PUB.Result != null && PUB.sm != null)
// EEMStatus.AddEEDBSQL(PUB.sm.Step, PUB.sm.RunStep.ToString(), PUB.Result.TargetPos.ToString());
//QA를 제외한 경우에는 기본 QC로 이동한다
if (PUB.Result.NextPos == ePosition.QA)
@@ -184,7 +172,7 @@ namespace Project
PUB.sm.ClearRunStep();
PUB.Result.TargetPos = ePosition.QC;
PUB.sm.SetNewRunStep(ERunStep.GOHOME);
PUB.Speak( Lang.);
PUB.Speak(Lang.);
}
return;
}
@@ -198,7 +186,7 @@ namespace Project
else if (_SM_RUN_GOHOME(runStepisFirst, PUB.sm.GetRunSteptime))
{
//230601
// if (PUB.Result != null && PUB.sm != null)
// if (PUB.Result != null && PUB.sm != null)
// EEMStatus.AddEEDBSQL(PUB.sm.Step, PUB.sm.RunStep.ToString(), PUB.Result.TargetPos.ToString());
PUB.Speak(Lang.);
@@ -215,7 +203,7 @@ namespace Project
return true;
}
void CheckAGVMoveTo(eGoDir dir)
{
//계속내려간다
@@ -545,7 +533,7 @@ namespace Project
return false;
}
}//cvass
}

View File

@@ -13,12 +13,12 @@ namespace Project
{
public Boolean _SM_RUN_READY(bool isFirst, TimeSpan stepTime)
{
//이동 불가 조건이 걸려있다면 충전을 하지 못하게 한다.
Boolean bAutoChageOn = true;
if (PUB.AGV.system1.stop_by_front_detect) bAutoChageOn = false;
else if (PUB.AGV.error.Emergency) bAutoChageOn = false;
else if (VAR.BOOL[eVarBool.FLAG_CHARGEONA]) bAutoChageOn = false;
else if (VAR.BOOL[eVarBool.FLAG_CHARGEONM]) bAutoChageOn = false;
////이동 불가 조건이 걸려있다면 충전을 하지 못하게 한다.
//Boolean bAutoChageOn = true;
//if (PUB.AGV.system1.stop_by_front_detect) bAutoChageOn = false;
//else if (PUB.AGV.error.Emergency) bAutoChageOn = false;
//else if (VAR.BOOL[eVarBool.FLAG_CHARGEONA]) bAutoChageOn = false;
//else if (VAR.BOOL[eVarBool.FLAG_CHARGEONM]) bAutoChageOn = false;
//자동 충전 중이라면 최대 충전시간과 레벨을 체크한다
@@ -73,58 +73,58 @@ namespace Project
}
VAR.STR[eVarString.ChargeCheckMsg] = "현재 위치 모름";
}
else if (PUB.setting.Enable_AutoCharge == true )
{
if(bAutoChageOn)
{
VAR.BOOL[eVarBool.CHARGE_READY] = true;
if (PUB.BMS.Current_Level < PUB.setting.ChargeStartLevel)
{
//레벨에 의한 자동 충전간격은
var ts = VAR.TIME.RUN(eVarTime.ChargeTry);
if (ts.TotalSeconds >= PUB.setting.ChargeRetryTerm)
{
VAR.I32[eVarInt32.ChargeWaitSec] = 0;
VAR.BOOL[eVarBool.CHARGE_WAIT] = false;
PUB.log.Add($"자동충전레벨시작 {PUB.BMS.Current_Level}/{PUB.setting.ChargeStartLevel}");
PUB.sm.ClearRunStep();
PUB.sm.SetNewRunStep(ERunStep.GOCHARGE);
PUB.sm.SetNewStep(eSMStep.RUN);
PUB.AddEEDB($"자동충전레벨시작 {PUB.BMS.Current_Level}/{PUB.setting.ChargeStartLevel}");
}
else
{
VAR.I32[eVarInt32.ChargeWaitSec] = (int)(PUB.setting.ChargeRetryTerm - ts.TotalSeconds);
VAR.BOOL[eVarBool.CHARGE_WAIT] = true;
}
VAR.STR[eVarString.ChargeCheckMsg] = "배터리 충전 레벨 필요";
}
else
{
//아직 레벨이 높다
VAR.BOOL[eVarBool.CHARGE_READY] = false;
VAR.I32[eVarInt32.ChargeWaitSec] = 0;
VAR.BOOL[eVarBool.CHARGE_WAIT] = false;
VAR.STR[eVarString.ChargeCheckMsg] = "배터리 레벨상 충전 불필요";
}
}
else
{
VAR.BOOL[eVarBool.CHARGE_READY] = false;
VAR.I32[eVarInt32.ChargeWaitSec] = 0;
VAR.BOOL[eVarBool.CHARGE_WAIT] = false;
VAR.STR[eVarString.ChargeCheckMsg] = "충전 불가 조건";
//충전조건이 맞지 않는다
}
}
else
{
VAR.BOOL[eVarBool.CHARGE_READY] = false;
VAR.I32[eVarInt32.ChargeWaitSec] = 0;
VAR.BOOL[eVarBool.CHARGE_WAIT] = false;
//자동충전이 해제된 상태이므로 처리하지 않는다
VAR.STR[eVarString.ChargeCheckMsg] = "자동 충전 해제 됨";
}
//else if (PUB.setting.Enable_AutoCharge == true )
//{
// if(bAutoChageOn)
// {
// VAR.BOOL[eVarBool.CHARGE_READY] = true;
// if (PUB.BMS.Current_Level < PUB.setting.ChargeStartLevel)
// {
// //레벨에 의한 자동 충전간격은
// var ts = VAR.TIME.RUN(eVarTime.ChargeTry);
// if (ts.TotalSeconds >= PUB.setting.ChargeRetryTerm)
// {
// VAR.I32[eVarInt32.ChargeWaitSec] = 0;
// VAR.BOOL[eVarBool.CHARGE_WAIT] = false;
// PUB.log.Add($"자동충전레벨시작 {PUB.BMS.Current_Level}/{PUB.setting.ChargeStartLevel}");
// PUB.sm.ClearRunStep();
// PUB.sm.SetNewRunStep(ERunStep.GOCHARGE);
// PUB.sm.SetNewStep(eSMStep.RUN);
// PUB.AddEEDB($"자동충전레벨시작 {PUB.BMS.Current_Level}/{PUB.setting.ChargeStartLevel}");
// }
// else
// {
// VAR.I32[eVarInt32.ChargeWaitSec] = (int)(PUB.setting.ChargeRetryTerm - ts.TotalSeconds);
// VAR.BOOL[eVarBool.CHARGE_WAIT] = true;
// }
// VAR.STR[eVarString.ChargeCheckMsg] = "배터리 충전 레벨 필요";
// }
// else
// {
// //아직 레벨이 높다
// VAR.BOOL[eVarBool.CHARGE_READY] = false;
// VAR.I32[eVarInt32.ChargeWaitSec] = 0;
// VAR.BOOL[eVarBool.CHARGE_WAIT] = false;
// VAR.STR[eVarString.ChargeCheckMsg] = "배터리 레벨상 충전 불필요";
// }
// }
// else
// {
// VAR.BOOL[eVarBool.CHARGE_READY] = false;
// VAR.I32[eVarInt32.ChargeWaitSec] = 0;
// VAR.BOOL[eVarBool.CHARGE_WAIT] = false;
// VAR.STR[eVarString.ChargeCheckMsg] = "충전 불가 조건";
// //충전조건이 맞지 않는다
// }
//}
//else
//{
// VAR.BOOL[eVarBool.CHARGE_READY] = false;
// VAR.I32[eVarInt32.ChargeWaitSec] = 0;
// VAR.BOOL[eVarBool.CHARGE_WAIT] = false;
// //자동충전이 해제된 상태이므로 처리하지 않는다
// VAR.STR[eVarString.ChargeCheckMsg] = "자동 충전 해제 됨";
//}
//대기모드에서는 움직이지 않게 한다
if(PUB.AGV.system1.agv_run)

View File

@@ -41,31 +41,7 @@ namespace Project
{
try
{
if (PUB.mapctl != null)
{
var rlt = AGVControl.MapControlManager.PredictNextAction();
if (rlt.ReasonCode == AGVControl.AGVActionReasonCode.busy)
{
//var premsg = $"이전 예측작업이 완료되지 않았습니다";
//PUB.log.AddE(premsg);
//PUB.log.AddE(premsg);
//Console.WriteLine(premsg);
//predicterr += 1;
//if (predicterr > 10)
//{
// var premsg = $"행동예측 오류카운트 초과";
// PUB.AGV.AGVMoveStop(premsg);
// PUB.log.AddE(premsg);
// PUB.logagv.AddE(premsg);
// Console.WriteLine(premsg);
//}
}
}
//데이터 파싱
switch (e.DataType)
{
case arDev.Narumi.DataType.STS:
@@ -83,12 +59,12 @@ namespace Project
//모터방향 입력
if (PUB.AGV.data.Direction == 'B')
AGVControl.MapControlManager.agv.CurrentMOTDirection = AGVControl.Models.Direction.Backward;
PUB.mapctl.Manager.agv.CurrentMOTDirection = AGVControl.Direction.Backward;
else
AGVControl.MapControlManager.agv.CurrentMOTDirection = AGVControl.Models.Direction.Forward;
PUB.mapctl.Manager.agv.CurrentMOTDirection = AGVControl.Direction.Forward;
AGVControl.MapControlManager.agv.IsMoving = PUB.AGV.system1.agv_run;
AGVControl.MapControlManager.agv.IsMarkCheck = PUB.AGV.system1.Mark1_check || PUB.AGV.system1.Mark2_check;
PUB.mapctl.Manager.agv.IsMoving = PUB.AGV.system1.agv_run;
PUB.mapctl.Manager.agv.IsMarkCheck = PUB.AGV.system1.Mark1_check || PUB.AGV.system1.Mark2_check;
if (PUB.AGV.signal.mark_sensor == false)
{
@@ -201,10 +177,8 @@ namespace Project
else
{
//위치는 찾았다 해당 위치가 내 목적지라면 mark stop기능으로 전환한다
}
////자동, 상하차 모드일때 RFID 가 타겟위치에 올때는 - 멈춤을 설정해준다
//if (VAR.BOOL[eVarBool.FLAG_AUTORUN] == true &&
// PUB.Result.CurrentPos == PUB.Result.TargetPos &&
@@ -237,12 +211,19 @@ namespace Project
break;
}
//이 후 상황을 예측한다
if (PUB.mapctl != null)
{
var rlt = PUB.mapctl.Manager.PredictNextAction();
if (rlt.Changed)
Console.WriteLine($"[new] predict idx:{rlt.Idx}");
}
}
catch (Exception ex)
{
Console.WriteLine($"[AGV_DataReceive] {ex.Message}");
}
}
}
}

View File

@@ -158,9 +158,10 @@ namespace Project
private void Bms_BMSDataReceive(object sender, EventArgs e)
{
AGVControl.MapControlManager.agv.BatteryLevel = PUB.BMS.Current_Level;
AGVControl.MapControlManager.agv.BatteryTemp1 = PUB.BMS.Current_temp1;
AGVControl.MapControlManager.agv.BatteryTemp2 = PUB.BMS.Current_temp2;
PUB.mapctl.Manager.agv.BatteryLevel = PUB.BMS.Current_Level;
PUB.mapctl.Manager.agv.BatteryTemp1 = PUB.BMS.Current_temp1;
PUB.mapctl.Manager.agv.BatteryTemp2 = PUB.BMS.Current_temp2;
if (PUB.BMS.Current_Level <= PUB.setting.ChargeStartLevel)
{
//배터리 레벨이 기준보다 낮다면 경고를 활성화 한다

View File

@@ -163,10 +163,7 @@ namespace Project
{
PUB.BMS.SendQuery();
}
Update_BatteryWarnSpeak();
}
}
}

View File

@@ -25,6 +25,25 @@ namespace Project
var data = e.ReceivedPacket.Data;
var dataStr = System.Text.Encoding.Default.GetString(data);
var cmd = (ENIGProtocol.AGVCommands)e.ReceivedPacket.Command;
var TargetID = 0;
if (dataStr.Length >= 2)
{
//대상디바이스
TargetID = Convert.ToByte(dataStr.Substring(0, 2), 16);
//데이터영역을 다시 설정
if (dataStr.Length > 2) dataStr = dataStr.Substring(2);
else dataStr = string.Empty;
}
else
{
PUB.log.Add($"ACS 데이터에서 TARGET ID가 없습니다(data : first byte)");
}
if (PUB.setting.XBE_ID != TargetID)
return;
switch (cmd)
{
@@ -60,7 +79,7 @@ namespace Project
case ENIGProtocol.AGVCommands.Goto: //move to tag
if (uint.TryParse(dataStr, out uint tagno2))
{
var currPos = AGVControl.MapControlManager.agv.CurrentRFID;///.AGVMoveToRFID(;
var currPos = PUB.mapctl.Manager.agv.CurrentRFID;///.AGVMoveToRFID(;
if (PUB.mapctl.SetTargetPosition(tagno2))
PUB.log.AddI($"New Target {tagno2}");
else

View File

@@ -172,7 +172,7 @@ namespace Project
MenuLift.Text = "LIFT";
toolTip1.SetToolTip(MenuLift, "I/O 및 FLAG를 확인 합니다");
MenuLift.UseVisualStyleBackColor = true;
MenuLift.Click += button3_Click;
MenuLift.Click += MenuLift_Click;
//
// MenuMAN
//
@@ -189,7 +189,7 @@ namespace Project
MenuMAN.Text = "MANUAL";
toolTip1.SetToolTip(MenuMAN, "작업 내역을 확인 합니다");
MenuMAN.UseVisualStyleBackColor = true;
MenuMAN.Click += button4_Click;
MenuMAN.Click += ManualMan_Click;
//
// MenuFlag
//
@@ -206,7 +206,7 @@ namespace Project
MenuFlag.Text = "FLAG";
toolTip1.SetToolTip(MenuFlag, "I/O 및 FLAG를 확인 합니다");
MenuFlag.UseVisualStyleBackColor = true;
MenuFlag.Click += button1_Click;
MenuFlag.Click += btMenuFlag_Click;
//
// MenuAuto
//
@@ -223,7 +223,7 @@ namespace Project
MenuAuto.Text = "AUTO";
toolTip1.SetToolTip(MenuAuto, "작업 내역을 확인 합니다");
MenuAuto.UseVisualStyleBackColor = true;
MenuAuto.Click += button2_Click;
MenuAuto.Click += btMenuAuto_Click;
//
// MenuLog
//
@@ -258,7 +258,7 @@ namespace Project
MenuAGV.Text = "AGV";
toolTip1.SetToolTip(MenuAGV, "I/O 및 FLAG를 확인 합니다");
MenuAGV.UseVisualStyleBackColor = false;
MenuAGV.Click += button1_Click_1;
MenuAGV.Click += btMenuAGV_Click_1;
//
// MenuBMS
//
@@ -275,7 +275,7 @@ namespace Project
MenuBMS.Text = "BMS";
toolTip1.SetToolTip(MenuBMS, "I/O 및 FLAG를 확인 합니다");
MenuBMS.UseVisualStyleBackColor = true;
MenuBMS.Click += button2_Click_1;
MenuBMS.Click += btMenuBMS_Click_1;
//
// btAutoRun
//
@@ -323,7 +323,7 @@ namespace Project
btAutoRun.TextShadow = true;
btAutoRun.TextVisible = true;
toolTip1.SetToolTip(btAutoRun, "작업상태(자동/수동)를 표시 합니다");
btAutoRun.Click += btStart_Click;
btAutoRun.Click += btAutorun_Click;
//
// btChargeA
//
@@ -837,14 +837,12 @@ namespace Project
gridviewTestToolStripMenuItem.Name = "gridviewTestToolStripMenuItem";
gridviewTestToolStripMenuItem.Size = new Size(228, 22);
gridviewTestToolStripMenuItem.Text = "GridviewTest";
gridviewTestToolStripMenuItem.Click += gridviewTestToolStripMenuItem_Click;
//
// 으ㅆㄷㄴㅅToolStripMenuItem
//
ToolStripMenuItem.Name = "으ㅆㄷㄴㅅToolStripMenuItem";
ToolStripMenuItem.Size = new Size(228, 22);
ToolStripMenuItem.Text = "Test DataMatrix StripID";
ToolStripMenuItem.Click += ToolStripMenuItem_Click;
//
// messageToolStripMenuItem
//
@@ -879,7 +877,6 @@ namespace Project
reloadLotListToolStripMenuItem.Name = "reloadLotListToolStripMenuItem";
reloadLotListToolStripMenuItem.Size = new Size(228, 22);
reloadLotListToolStripMenuItem.Text = "Reload Lot List";
reloadLotListToolStripMenuItem.Click += reloadLotListToolStripMenuItem_Click;
//
// moveSourceListToDestListToolStripMenuItem
//
@@ -1044,7 +1041,7 @@ namespace Project
btHome.TextAlign = ContentAlignment.MiddleCenter;
btHome.TextShadow = true;
btHome.TextVisible = true;
btHome.Click += arLabel1_Click;
btHome.Click += brHome_Click;
//
// btChargeM
//

View File

@@ -26,6 +26,7 @@ namespace Project
ViewForm.fFlag form_flag = null;
ViewForm.fAgv form_agv = null;
ViewForm.fBms form_bms = null;
Dialog.fLog form_log = null;
readonly usbdetect.DriveDetector usbdet;
public fMain()
@@ -59,6 +60,10 @@ namespace Project
this.FormClosing += __Closing;
if (PUB.setting.FullScreen) this.WindowState = FormWindowState.Maximized;
lbTime.Click += (s1,e1) => {
PUB.mapctl.ShowDesign();
};
}
protected override void WndProc(ref Message m)
@@ -240,10 +245,10 @@ namespace Project
this.btDebug.Visible = PUB.setting.UseDebugMode;
PUB.log.Add("Program Start");
UpdateControlText();
//수량표시
PUB.counter.PropertyChanged += Counter_PropertyChanged;
PUB.counter.PropertyChanged += (s1, e1) => Update_Count();
Update_Count();
PUB.log.Add("프로그램 실행 기록 추가");
@@ -256,15 +261,6 @@ namespace Project
}
private void Counter_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
//수량에 변화가 잇다면 업데이트 한다
Update_Count();
}
#region "Mouse Form Move"
private Boolean fMove = false;
@@ -296,6 +292,137 @@ namespace Project
}
#endregion
void socket_SendMessage(object sender, Device.Socket.SocketMessageEventArgs e)
{
//핑로그가 꺼져있는 상황일때 핑로그는 로그를 기록하지 않는다. 181205
if (!PUB.setting.Log_Ping && e.Message.Type == Device.Socket.eType.REPLY && e.Message.SType == Device.Socket.eSType.STATUS)
{
return;
}
PUB.log.Add("WS << " + e.rawData);
}
void socket_RecvMessage(object sender, Device.Socket.SocketMessageEventArgs e)
{
if (e.Message.isError)
PUB.log.AddE("WS >> " + e.Message.ErrorMessage + ",RAW=" + e.rawData);
else
{
switch (e.Message.Type)
{
case Device.Socket.eType.REQUEST:
if (e.Message.SType == Device.Socket.eSType.STATUS)
{
var packet = PUB.sock_debug.makeReplyStatus(Device.Socket.eStatus.IDLE);
var rlt = PUB.sock_debug.Send(PUB.setting.Asset, Device.Socket.eType.REPLY, Device.Socket.eSType.STATUS, packet);
if (!rlt)
{
PUB.log.AddE("Status Reply Error");
}
else
{
if (PUB.setting.Log_Ping) PUB.log.AddI("Server Status Reply OK");
}
}
else
{
PUB.log.Add("WS >> " + e.rawData);
}
break;
}
}
}
void socket_GetMessage(object sender, Device.Socket.MesasgeEventArgs e)
{
if (e.isError) PUB.log.AddE("WS:" + e.Message);
else PUB.log.Add("WS:" + e.Message);
}
delegate void SelectModelHandler(string modelName);
void SelectModelM(string modelName)
{
if (this.InvokeRequired)
{
this.Invoke(new SelectModelHandler(SelectModelM), new object[] { modelName });
return;
}
}
void func_sw_start(bool Prompt = false)
{
if (VAR.BOOL[eVarBool.FLAG_AUTORUN] == false) //자동상태가 아니라면
{
PUB.AGV.AGVErrorReset();
if (Prompt)
{
if (UTIL.MsgQ("AGV상태를 자동으로 전환 할까요?") != DialogResult.Yes) return;
}
//충전상태확인
if (PUB.CheckManualChargeMode() == false) return;
PUB.popup.needClose = true;
PUB.sm.bPause = false;
PUB.sm.SetNewStep(eSMStep.RUN);
if (PUB.Result.CurrentPos == ePosition.NONE || PUB.Result.TargetPos == ePosition.NONE)
{
PUB.sm.SetNewRunStep(ERunStep.GOHOME);
}
PUB.Speak(Lang.);
}
else
{
PUB.AGV.AGVCharge(PUB.setting.ChargerID, false); //230425 수동전환하면 충전 해제한다
PUB.sm.SetNewStep(eSMStep.IDLE);
PUB.Speak(Lang.);
}
}
void Resultclear()
{
PUB.Result.Clear();
PUB.log.AddI("Clear Resultclear");
}
void CheckFreeSpace()
{
try
{
if (PUB.path.FullName.StartsWith("\\"))
{
SSInfo.setTitle(0, 1, "UNC Path Detected");
SSInfo.setValue(0, 1, 2);
}
else
{
double freeSpaceRate_ = PUB.GetFreeSpace();
this.freeSpaceRate = freeSpaceRate_;
SSInfo.setTitle(0, 1, "FREE(" + PUB.path.FullName.Substring(0, 1) + ") : " + freeSpaceRate.ToString("N2") + "%");
if (freeSpaceRate < PUB.setting.AutoDeleteThreshold)
{
VAR.BOOL[eVarBool.MINSPACE] = true;
SSInfo.setValue(0, 1, 2); //lbFreeSpace.ForeColor = Color.Tomato;
}
else
{
VAR.BOOL[eVarBool.MINSPACE] = false;
SSInfo.setValue(0, 1, 3);// lbFreeSpace.ForeColor = Color.White;
}
}
//Pub.log.Add("남은디스크공간확인:" + freeSpaceRate.ToString("N2") + "%"); 190129
}
catch (Exception ex)
{
SSInfo.setTitle(0, 1, "FREE SPACE : -ERROR-");
PUB.log.AddE("check free space : " + ex.Message);
}
}
private void CtlPos1_ItemClick(object sender, CtlPos.ItemClickEventArgs e)
@@ -451,191 +578,16 @@ namespace Project
if (dlg != null) dlg.Dispose();
}
void socket_SendMessage(object sender, Device.Socket.SocketMessageEventArgs e)
{
//핑로그가 꺼져있는 상황일때 핑로그는 로그를 기록하지 않는다. 181205
if (!PUB.setting.Log_Ping && e.Message.Type == Device.Socket.eType.REPLY && e.Message.SType == Device.Socket.eSType.STATUS)
{
return;
}
PUB.log.Add("WS << " + e.rawData);
}
void socket_RecvMessage(object sender, Device.Socket.SocketMessageEventArgs e)
{
if (e.Message.isError)
PUB.log.AddE("WS >> " + e.Message.ErrorMessage + ",RAW=" + e.rawData);
else
{
switch (e.Message.Type)
{
case Device.Socket.eType.REQUEST:
if (e.Message.SType == Device.Socket.eSType.STATUS)
{
var packet = PUB.sock_debug.makeReplyStatus(Device.Socket.eStatus.IDLE);
var rlt = PUB.sock_debug.Send(PUB.setting.Asset, Device.Socket.eType.REPLY, Device.Socket.eSType.STATUS, packet);
if (!rlt)
{
PUB.log.AddE("Status Reply Error");
}
else
{
if (PUB.setting.Log_Ping) PUB.log.AddI("Server Status Reply OK");
}
}
else
{
PUB.log.Add("WS >> " + e.rawData);
}
break;
}
}
}
void socket_GetMessage(object sender, Device.Socket.MesasgeEventArgs e)
{
if (e.isError) PUB.log.AddE("WS:" + e.Message);
else PUB.log.Add("WS:" + e.Message);
}
delegate void SelectModelHandler(string modelName);
void SelectModelM(string modelName)
{
if (this.InvokeRequired)
{
this.Invoke(new SelectModelHandler(SelectModelM), new object[] { modelName });
return;
}
}
void func_sw_start(bool Prompt = false)
{
if (VAR.BOOL[eVarBool.FLAG_AUTORUN] == false) //자동상태가 아니라면
{
PUB.AGV.AGVErrorReset();
if (Prompt)
{
if (UTIL.MsgQ("AGV상태를 자동으로 전환 할까요?") != DialogResult.Yes) return;
}
//충전상태확인
if (PUB.CheckManualChargeMode() == false) return;
PUB.popup.needClose = true;
PUB.sm.bPause = false;
PUB.sm.SetNewStep(eSMStep.RUN);
if (PUB.Result.CurrentPos == ePosition.NONE || PUB.Result.TargetPos == ePosition.NONE)
{
PUB.sm.SetNewRunStep(ERunStep.GOHOME);
}
PUB.Speak(Lang.);
}
else
{
PUB.AGV.AGVCharge(PUB.setting.ChargerID, false); //230425 수동전환하면 충전 해제한다
PUB.sm.SetNewStep(eSMStep.IDLE);
PUB.Speak(Lang.);
}
}
void Resultclear()
{
PUB.Result.Clear();
PUB.log.AddI("Clear Resultclear");
}
void CheckFreeSpace()
{
try
{
if (PUB.path.FullName.StartsWith("\\"))
{
SSInfo.setTitle(0, 1, "UNC Path Detected");
SSInfo.setValue(0, 1, 2);
}
else
{
double freeSpaceRate_ = PUB.GetFreeSpace();
this.freeSpaceRate = freeSpaceRate_;
SSInfo.setTitle(0, 1, "FREE(" + PUB.path.FullName.Substring(0, 1) + ") : " + freeSpaceRate.ToString("N2") + "%");
if (freeSpaceRate < PUB.setting.AutoDeleteThreshold)
{
VAR.BOOL[eVarBool.MINSPACE] = true;
SSInfo.setValue(0, 1, 2); //lbFreeSpace.ForeColor = Color.Tomato;
}
else
{
VAR.BOOL[eVarBool.MINSPACE] = false;
SSInfo.setValue(0, 1, 3);// lbFreeSpace.ForeColor = Color.White;
}
}
//Pub.log.Add("남은디스크공간확인:" + freeSpaceRate.ToString("N2") + "%"); 190129
}
catch (Exception ex)
{
SSInfo.setTitle(0, 1, "FREE SPACE : -ERROR-");
PUB.log.AddE("check free space : " + ex.Message);
}
}
private void demoRunToolStripMenuItem_Click(object sender, EventArgs e)
{
PUB.Result.JobEndTime = DateTime.Now;
// Pub.flag.Toggle(eFlag.DemoRun);
// Pub.log.AddAT(string.Format("데모변경: {0}", Pub.flag.get(eFlag.DemoRun)));
}
private void openMapFileToolStripMenuItem_Click(object sender, EventArgs e)
{
using (OpenFileDialog od = new OpenFileDialog())
if (od.ShowDialog() != System.Windows.Forms.DialogResult.OK) return;
//if (orgImage != null) orgImage.Dispose();
}
private void setZValidToolStripMenuItem_Click(object sender, EventArgs e)
{
PUB.log.Add("user set z-home set on");
}
private void gridviewTestToolStripMenuItem_Click(object sender, EventArgs e)
{
}
private void ToolStripMenuItem_Click(object sender, EventArgs e)
{
/////HB9225-4280A 0901
//var striplist = new string[]{
// "HB9125-7560A 0704",
//"HB9125-7800A 0104",
//"HB9125-8480A 0701",
//"HB9130-8550A 5108",
//"HB9130-8620A 0701",
//"HB9131-9340A 0201",
//"HB9206-0810A 5301",
//"HB9206-0820A 0902",
//"HB9222-3020A 0208",
//"HB9222-3020A 0508",
//"HB9222-3720A 0205",
//"HB9222-3720A 0902",
//"HB9225-3790A 0604",
//"HB9225-4280A 0901",
//"HB9228-4840A 0104",
//"HB9228-4840A 5908",
//"HB9313-7600A 1006",
//"HB9319-9540A 6003",
//"ZGP490510700 1305"
//};
}
private void errorToolStripMenuItem_Click(object sender, EventArgs e)
{
PUB.popup.setMessage("error\berror message");
@@ -651,12 +603,6 @@ namespace Project
PUB.popup.setMessage("attention\nattention message", MessageWindow.eWindowType.attention);
}
private void reloadLotListToolStripMenuItem_Click(object sender, EventArgs e)
{
}
private void arLabel3_Click(object sender, EventArgs e)
{
@@ -676,11 +622,6 @@ namespace Project
this.Close();
}
void UpdateControlText()
{
}
private void arLabel5_Click(object sender, EventArgs e)
{
//SetScreen(form_setup);
@@ -700,7 +641,7 @@ namespace Project
}
VAR.BOOL[eVarBool.FLAG_SETUP] = false;// VAR.BOOL[eVarBool.FLAG_SETUP] = false;//VAR.BOOL[eVarBool.FLAG_SETUP] = false;
UpdateControlText();
if (popmsg) PUB.popup.Visible = true;
}
@@ -737,13 +678,13 @@ namespace Project
UTIL.RunExplorer(UTIL.CurrentPath);
}
private void button4_Click(object sender, EventArgs e)
private void ManualMan_Click(object sender, EventArgs e)
{
SetScreen(form_manu);
MenuMAN.ForeColor = Color.Gold;
}
private void button3_Click(object sender, EventArgs e)
private void MenuLift_Click(object sender, EventArgs e)
{
SetScreen(form_zlift);
MenuLift.ForeColor = Color.Gold;
@@ -755,7 +696,7 @@ namespace Project
this.cmDebug.Show(ctl, new Point((int)(ctl.Width / 1.5), (int)(ctl.Height / 1.5)));
}
private void btStart_Click(object sender, EventArgs e)
private void btAutorun_Click(object sender, EventArgs e)
{
var ctl = sender as arCtl.arLabel;
if (ctl.Enabled == false) return;
@@ -763,20 +704,18 @@ namespace Project
func_sw_start(true);
}
private void button2_Click(object sender, EventArgs e)
private void btMenuAuto_Click(object sender, EventArgs e)
{
SetScreen(form_auto);
MenuAuto.ForeColor = Color.Gold;
}
private void button1_Click(object sender, EventArgs e)
private void btMenuFlag_Click(object sender, EventArgs e)
{
SetScreen(form_flag);
MenuFlag.ForeColor = Color.Gold;
}
Dialog.fLog form_log = null;
private void btLog_Click(object sender, EventArgs e)
{
if (form_log == null || form_log.IsDisposed || form_log.Disposing)
@@ -844,8 +783,7 @@ namespace Project
PUB.Speak("고경석 수석님 밥은 드셨습니까?", true);
UpdateProgressStatus(20, 100, "progre");
}
private void arLabel1_Click(object sender, EventArgs e)
private void brHome_Click(object sender, EventArgs e)
{
var bCharge = PUB.sm.Step == eSMStep.RUN &&
(PUB.sm.RunStep == ERunStep.GOHOME);
@@ -878,30 +816,6 @@ namespace Project
}
//private void btChargeM_Click(object sender, EventArgs e)
//{
// var bCharge = PUB.flag.get(EFlag.FLAG_CHARGEONM);
// //충전을 시작해라ㅏ
// if (bCharge == true)
// {
// var dlg = Util.MsgQ("수동 충전 상태를 해제 할까요?");
// if (dlg == DialogResult.Yes)
// {
// PUB.flag.set(EFlag.FLAG_CHARGEONM, false);
// Pub.log.Add("수동 충전 상태 해제");
// }
// }
// else
// {
// var dlg = Util.MsgQ("수동 충전 상태를 설정 할까요?\n수동충전이 설정되면 AGV는 움직지 않습니다");
// if (dlg == DialogResult.Yes)
// {
// PUB.flag.set(EFlag.FLAG_CHARGEONM, true);
// Pub.log.Add("수동 충전 상태 설정");
// }
// }
//}
private void arLabel2_Click_1(object sender, EventArgs e)
{
@@ -911,17 +825,18 @@ namespace Project
private void lbCNtUp_Click(object sender, EventArgs e)
{
//down,up둘다 연결해야함
using (var f = new Dialog.fCounter())
f.ShowDialog();
}
private void button1_Click_1(object sender, EventArgs e)
private void btMenuAGV_Click_1(object sender, EventArgs e)
{
SetScreen(form_agv);
MenuAGV.ForeColor = Color.Gold;
}
private void button2_Click_1(object sender, EventArgs e)
private void btMenuBMS_Click_1(object sender, EventArgs e)
{
SetScreen(form_bms);
MenuBMS.ForeColor = Color.Gold;
@@ -971,5 +886,10 @@ namespace Project
PUB.log.Add("수동 충전 실행");
}
}
private void lbTime_Click(object sender, EventArgs e)
{
PUB.mapctl.ShowDesign();
}
}
}

View File

@@ -1,17 +1,17 @@
<?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
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>
@@ -26,36 +26,36 @@
<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
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
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
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
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
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
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
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->

View File

@@ -1,105 +1,152 @@
[RFID_POINTS]
100,486,517
173,488,516
230,493,515
309,489,514
370,490,513
437,487,512
483,459,511
511,421,510
543,371,509
569,329,508
608,289,507
661,279,506
701,297,505
698,349,504
698,391,503
699,449,502
691,491,501
570,275,400
517,264,401
454,264,402
388,262,403
315,258,404
639,234,600
621,182,601
641,183,602
657,101,603
627,82,604
560,73,605
499,65,606
432,65,607
264,232,405
363,60,608
654,508,500
96,542,100
159,542,101
226,542,102
309,541,103
369,542,104
483,165,753
735,163,700
523,170,752
565,175,751
597,182,750
665,181,703
700,176,702
722,170,701
100,486,517,False,,False
162,487,516,False,,False
230,493,515,False,,False
309,489,514,False,,False
370,490,513,False,,False
429,487,512,False,Forward,False
488,476,511,False,,False
538,445,510,False,,False
576,393,509,False,,False
598,343,508,False,,False
621,287,507,True,,False
671,293,506,False,,False
702,314,505,False,,False
711,354,504,False,,False
711,396,503,False,,False
707,454,502,False,,False
685,499,501,False,Forward,False
566,281,400,False,,False
504,274,401,False,,False
439,271,402,False,,False
383,267,403,False,,False
311,260,404,False,Forward,False
633,237,600,False,,False
609,186,601,False,,False
639,184,602,False,,False
657,101,603,False,,False
627,82,604,False,,False
560,73,605,False,,False
499,65,606,False,,False
432,65,607,False,Forward,False
242,239,405,False,Forward,True
363,60,608,False,Forward,True
633,547,500,False,Forward,True
96,542,100,False,Forward,True
159,542,101,False,Forward,True
226,542,102,False,Forward,True
310,541,103,False,Forward,True
369,542,104,False,Forward,True
397,166,753,False,Backward,True
847,152,700,False,Backward,True
484,169,752,False,Backward,False
535,176,751,False,,False
573,184,750,False,,False
665,181,703,False,,False
714,174,702,False,,False
756,165,701,False,Backward,False
[RFID_LINES]
100,486,173,488,517,516,False,73.02739
173,488,230,493,516,515,False,57.21888
230,493,309,489,515,514,False,79.1012
309,489,370,490,514,513,False,61.0082
370,490,437,487,513,512,False,67.06713
437,487,483,459,512,511,False,53.85165
483,459,511,421,511,510,False,47.20169
511,421,543,371,510,509,False,59.36329
543,371,569,329,509,508,False,49.39635
569,329,608,289,508,507,False,55.86591
608,289,639,234,507,600,False,63.13478
639,234,665,181,600,703,False,59.03389
665,181,657,101,703,603,False,80.399
657,101,627,82,603,604,False,35.51056
627,82,560,73,604,605,False,67.60178
560,73,499,65,605,606,False,61.52235
499,65,432,65,606,607,False,67
432,65,363,60,607,608,False,69.18092
641,183,665,181,602,703,False,24.08319
665,181,700,176,703,702,False,35.35534
700,176,722,170,702,701,False,22.80351
722,170,735,163,701,700,False,14.76482
641,183,621,182,602,601,False,20.02498
621,182,597,182,601,750,False,24
597,182,565,175,750,751,False,32.75668
565,175,523,170,751,752,False,42.29657
523,170,483,165,752,753,False,40.31129
264,232,315,258,405,404,False,57.24509
315,258,388,262,404,403,False,73.1095
388,262,454,264,403,402,False,66.0303
454,264,517,264,402,401,False,63
517,264,570,275,401,400,False,54.12947
570,275,608,289,400,507,False,40.49691
608,289,661,279,507,506,False,53.93515
661,279,701,297,506,505,False,43.86343
701,297,698,349,505,504,False,52.08647
698,349,698,391,504,503,False,42
698,391,699,449,503,502,False,58.00862
699,449,691,491,502,501,False,42.75512
691,491,654,508,501,500,False,40.71855
96,542,100,486,100,517,False,56.14267
159,542,173,488,101,516,False,55.7853
226,542,230,493,102,515,False,49.16299
309,541,309,489,103,514,False,52
369,542,370,490,104,513,False,52.00961
100,486,162,487,[RFIDPoint] 517,P:100,486,[RFIDPoint] 516,P:162,487,false,false,0
162,487,230,493,[RFIDPoint] 516,P:162,487,[RFIDPoint] 515,P:230,493,false,false,0
230,493,309,489,[RFIDPoint] 515,P:230,493,[RFIDPoint] 514,P:309,489,false,false,0
309,489,370,490,[RFIDPoint] 514,P:309,489,[RFIDPoint] 513,P:370,490,false,false,0
370,490,429,487,[RFIDPoint] 513,P:370,490,[RFIDPoint] 512,P:429,487,false,false,0
429,487,488,476,[RFIDPoint] 512,P:429,487,[RFIDPoint] 511,P:488,476,false,false,0
488,476,538,445,[RFIDPoint] 511,P:488,476,[RFIDPoint] 510,P:538,445,false,false,0
538,445,576,393,[RFIDPoint] 510,P:538,445,[RFIDPoint] 509,P:576,393,false,false,0
576,393,598,343,[RFIDPoint] 509,P:576,393,[RFIDPoint] 508,P:598,343,false,false,0
598,343,621,287,[RFIDPoint] 508,P:598,343,[RFIDPoint] 507,P:621,287,false,false,0
621,287,633,237,[RFIDPoint] 507,P:621,287,[RFIDPoint] 600,P:633,237,false,false,0
633,237,665,181,[RFIDPoint] 600,P:633,237,[RFIDPoint] 703,P:665,181,false,false,0
665,181,657,101,[RFIDPoint] 703,P:665,181,[RFIDPoint] 603,P:657,101,false,false,0
657,101,627,82,[RFIDPoint] 603,P:657,101,[RFIDPoint] 604,P:627,82,false,false,0
627,82,560,73,[RFIDPoint] 604,P:627,82,[RFIDPoint] 605,P:560,73,false,false,0
560,73,499,65,[RFIDPoint] 605,P:560,73,[RFIDPoint] 606,P:499,65,false,false,0
499,65,432,65,[RFIDPoint] 606,P:499,65,[RFIDPoint] 607,P:432,65,false,false,0
432,65,363,60,[RFIDPoint] 607,P:432,65,[RFIDPoint] 608,P:363,60,false,false,0
639,184,665,181,[RFIDPoint] 602,P:639,184,[RFIDPoint] 703,P:665,181,false,false,0
665,181,714,174,[RFIDPoint] 703,P:665,181,[RFIDPoint] 702,P:714,174,false,false,0
714,174,756,165,[RFIDPoint] 702,P:714,174,[RFIDPoint] 701,P:756,165,false,false,0
756,165,847,152,[RFIDPoint] 701,P:756,165,[RFIDPoint] 700,P:847,152,false,false,0
639,184,609,186,[RFIDPoint] 602,P:639,184,[RFIDPoint] 601,P:609,186,false,false,0
609,186,573,184,[RFIDPoint] 601,P:609,186,[RFIDPoint] 750,P:573,184,false,false,0
573,184,535,176,[RFIDPoint] 750,P:573,184,[RFIDPoint] 751,P:535,176,false,false,0
535,176,484,169,[RFIDPoint] 751,P:535,176,[RFIDPoint] 752,P:484,169,false,false,0
484,169,397,166,[RFIDPoint] 752,P:484,169,[RFIDPoint] 753,P:397,166,false,false,0
242,239,311,260,[RFIDPoint] 405,P:242,239,[RFIDPoint] 404,P:311,260,false,false,0
311,260,383,267,[RFIDPoint] 404,P:311,260,[RFIDPoint] 403,P:383,267,false,false,0
383,267,439,271,[RFIDPoint] 403,P:383,267,[RFIDPoint] 402,P:439,271,false,false,0
439,271,504,274,[RFIDPoint] 402,P:439,271,[RFIDPoint] 401,P:504,274,false,false,0
504,274,566,281,[RFIDPoint] 401,P:504,274,[RFIDPoint] 400,P:566,281,false,false,0
566,281,621,287,[RFIDPoint] 400,P:566,281,[RFIDPoint] 507,P:621,287,false,false,0
621,287,671,293,[RFIDPoint] 507,P:621,287,[RFIDPoint] 506,P:671,293,false,false,0
671,293,702,314,[RFIDPoint] 506,P:671,293,[RFIDPoint] 505,P:702,314,false,false,0
702,314,711,354,[RFIDPoint] 505,P:702,314,[RFIDPoint] 504,P:711,354,false,false,0
711,354,711,396,[RFIDPoint] 504,P:711,354,[RFIDPoint] 503,P:711,396,false,false,0
711,396,707,454,[RFIDPoint] 503,P:711,396,[RFIDPoint] 502,P:707,454,false,false,0
707,454,685,499,[RFIDPoint] 502,P:707,454,[RFIDPoint] 501,P:685,499,false,false,0
685,499,633,547,[RFIDPoint] 501,P:685,499,[RFIDPoint] 500,P:633,547,false,false,0
96,542,100,486,[RFIDPoint] 100,P:96,542,[RFIDPoint] 517,P:100,486,false,false,0
159,542,162,487,[RFIDPoint] 101,P:159,542,[RFIDPoint] 516,P:162,487,false,false,0
226,542,230,493,[RFIDPoint] 102,P:226,542,[RFIDPoint] 515,P:230,493,false,false,0
310,541,309,489,[RFIDPoint] 103,P:310,541,[RFIDPoint] 514,P:309,489,false,false,0
369,542,370,490,[RFIDPoint] 104,P:369,542,[RFIDPoint] 513,P:370,490,false,false,0
[RFID_CONNECTION]
100,486,162,487,517,516,1,,,
162,487,230,493,516,515,1,,,
230,493,309,489,515,514,1,,,
309,489,370,490,514,513,1,,,
370,490,429,487,513,512,1,,,
429,487,488,476,512,511,1,,,
488,476,538,445,511,510,1,,,
538,445,576,393,510,509,1,,,
576,393,598,343,509,508,1,,,
598,343,621,287,508,507,1,,,
621,287,633,237,507,600,1,,,
633,237,665,181,600,703,1,,,
665,181,657,101,703,603,1,,,
657,101,627,82,603,604,1,,,
627,82,560,73,604,605,1,,,
560,73,499,65,605,606,1,,,
499,65,432,65,606,607,1,,,
432,65,363,60,607,608,1,,,
639,184,665,181,602,703,1,,,
665,181,714,174,703,702,1,,,
714,174,756,165,702,701,1,,,
756,165,847,152,701,700,1,,,
639,184,609,186,602,601,1,,,
609,186,573,184,601,750,1,,,
573,184,535,176,750,751,1,,,
535,176,484,169,751,752,1,,,
484,169,397,166,752,753,1,,,
242,239,311,260,405,404,1,,,
311,260,383,267,404,403,1,,,
383,267,439,271,403,402,1,,,
439,271,504,274,402,401,1,,,
504,274,566,281,401,400,1,,,
566,281,621,287,400,507,1,,,
621,287,671,293,507,506,1,,,
671,293,702,314,506,505,1,,,
702,314,711,354,505,504,1,,,
711,354,711,396,504,503,1,,,
711,396,707,454,503,502,1,,,
707,454,685,499,502,501,1,,,
685,499,633,547,501,500,1,,,
96,542,100,486,100,517,1,,,
159,542,162,487,101,516,1,,,
226,542,230,493,102,515,1,,,
310,541,309,489,103,514,1,,,
369,542,370,490,104,513,1,,,
[MAP_TEXTS]
179,251,-1,-16777216,Arial,12,OPS-2
239,52,-256,-65408,Arial,12,SSOTRON-3
617,527,-16711936,-16777216,Arial,12,SSOTRON-1
87,551,-16777216,16777215,Arial,12,B1
150,550,-16777216,16777215,Arial,12,B2
227,553,-16777216,16777215,Arial,12,B3
299,555,-16777216,16777215,Arial,12,B4
367,554,-16777216,16777215,Arial,12,B5
453,128,-16777216,-8323073,Arial,12,CHG1
725,124,-16777216,-8323073,Arial,12,CHG2
231,193,-16777216,-2448096,Arial,12,TOPS-2
315,25,-256,-65408,Arial,12,SSOTRON-3
586,577,-16711936,-16777216,Arial,12,SSOTRON-1
81,564,-16777216,-1,Arial,12,B1
144,563,-16777216,-1,Arial,12,B2
214,561,-16777216,-1,Arial,12,B3
301,562,-16777216,-1,Arial,12,B4
359,562,-16777216,-1,Arial,12,B5
371,115,-16777216,-8323073,Arial,12,CHG1
822,110,-16777216,-8323073,Arial,12,CHG2
[CUSTOM_LINES]
[CUSTOM_LINES]

View File

@@ -0,0 +1,103 @@
namespace AGVControl.Dialog
{
partial class fMapDesign
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(fMapDesign));
this.panel1 = new System.Windows.Forms.Panel();
this.toolStrip1 = new System.Windows.Forms.ToolStrip();
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
this.btOK = new System.Windows.Forms.ToolStripButton();
this.toolStrip1.SuspendLayout();
this.SuspendLayout();
//
// panel1
//
this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel1.Font = new System.Drawing.Font("Tahoma", 8F, System.Drawing.FontStyle.Bold);
this.panel1.Location = new System.Drawing.Point(0, 47);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(888, 547);
this.panel1.TabIndex = 22;
//
// toolStrip1
//
this.toolStrip1.ImageScalingSize = new System.Drawing.Size(40, 40);
this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.btOK});
this.toolStrip1.Location = new System.Drawing.Point(0, 0);
this.toolStrip1.Name = "toolStrip1";
this.toolStrip1.Size = new System.Drawing.Size(888, 47);
this.toolStrip1.TabIndex = 23;
this.toolStrip1.Text = "toolStrip1";
//
// statusStrip1
//
this.statusStrip1.Location = new System.Drawing.Point(0, 594);
this.statusStrip1.Name = "statusStrip1";
this.statusStrip1.Size = new System.Drawing.Size(888, 22);
this.statusStrip1.TabIndex = 24;
this.statusStrip1.Text = "statusStrip1";
//
// btOK
//
this.btOK.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;
this.btOK.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this.btOK.Image = ((System.Drawing.Image)(resources.GetObject("btOK.Image")));
this.btOK.ImageTransparentColor = System.Drawing.Color.Magenta;
this.btOK.Name = "btOK";
this.btOK.Size = new System.Drawing.Size(44, 44);
this.btOK.Text = "toolStripButton1";
this.btOK.Click += new System.EventHandler(this.btOK_Click);
//
// fMapDesign
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(888, 616);
this.Controls.Add(this.panel1);
this.Controls.Add(this.statusStrip1);
this.Controls.Add(this.toolStrip1);
this.Name = "fMapDesign";
this.Text = "fMapDesign";
this.Load += new System.EventHandler(this.fMapDesign_Load);
this.toolStrip1.ResumeLayout(false);
this.toolStrip1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.ToolStrip toolStrip1;
private System.Windows.Forms.ToolStripButton btOK;
private System.Windows.Forms.StatusStrip statusStrip1;
}
}

View File

@@ -0,0 +1,48 @@
using AR;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace AGVControl.Dialog
{
public partial class fMapDesign : Form
{
AGVControl.MapControl mapctl;
public fMapDesign(string fn)
{
InitializeComponent();
mapctl = new AGVControl.MapControl();
mapctl.Dock = DockStyle.Fill;
mapctl.Visible = true;
mapctl.Font = this.panel1.Font;
mapctl.BackColor = Color.FromArgb(32, 32, 32);
this.panel1.Controls.Add(mapctl);
if (System.IO.File.Exists(fn))
{
//auto load
var rlt = mapctl.LoadFromFile(fn, out string errmsg);
if (rlt == false) AR.UTIL.MsgE(errmsg);
}
}
private void fMapDesign_Load(object sender, EventArgs e)
{
}
private void btOK_Click(object sender, EventArgs e)
{
this.mapctl.SaveToFile(this.mapctl.Filename);
DialogResult = DialogResult.OK;
}
}
}

View File

@@ -0,0 +1,142 @@
<?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>
<metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="btOK.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
TgDQASA1MVpwzwAAAABJRU5ErkJggg==
</value>
</data>
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>124, 17</value>
</metadata>
</root>

View File

@@ -0,0 +1,158 @@
namespace AGVControl.Dialog
{
partial class fPropertyRFIDPoint
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.propertyGrid1 = new System.Windows.Forms.PropertyGrid();
this.comboBox1 = new System.Windows.Forms.ComboBox();
this.propertyGrid2 = new System.Windows.Forms.PropertyGrid();
this.panel1 = new System.Windows.Forms.Panel();
this.label2 = new System.Windows.Forms.Label();
this.panel2 = new System.Windows.Forms.Panel();
this.label1 = new System.Windows.Forms.Label();
this.button1 = new System.Windows.Forms.Button();
this.panel1.SuspendLayout();
this.panel2.SuspendLayout();
this.SuspendLayout();
//
// propertyGrid1
//
this.propertyGrid1.Dock = System.Windows.Forms.DockStyle.Fill;
this.propertyGrid1.Location = new System.Drawing.Point(0, 31);
this.propertyGrid1.Name = "propertyGrid1";
this.propertyGrid1.Size = new System.Drawing.Size(346, 456);
this.propertyGrid1.TabIndex = 0;
//
// comboBox1
//
this.comboBox1.Dock = System.Windows.Forms.DockStyle.Top;
this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBox1.Font = new System.Drawing.Font("굴림", 18F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(129)));
this.comboBox1.FormattingEnabled = true;
this.comboBox1.Location = new System.Drawing.Point(1, 32);
this.comboBox1.Name = "comboBox1";
this.comboBox1.Size = new System.Drawing.Size(519, 32);
this.comboBox1.TabIndex = 1;
this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged);
//
// propertyGrid2
//
this.propertyGrid2.Dock = System.Windows.Forms.DockStyle.Fill;
this.propertyGrid2.Location = new System.Drawing.Point(1, 64);
this.propertyGrid2.Name = "propertyGrid2";
this.propertyGrid2.Size = new System.Drawing.Size(519, 362);
this.propertyGrid2.TabIndex = 2;
//
// panel1
//
this.panel1.BackColor = System.Drawing.Color.Gray;
this.panel1.Controls.Add(this.propertyGrid2);
this.panel1.Controls.Add(this.button1);
this.panel1.Controls.Add(this.comboBox1);
this.panel1.Controls.Add(this.label2);
this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel1.Location = new System.Drawing.Point(346, 0);
this.panel1.Name = "panel1";
this.panel1.Padding = new System.Windows.Forms.Padding(1);
this.panel1.Size = new System.Drawing.Size(521, 487);
this.panel1.TabIndex = 3;
//
// label2
//
this.label2.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
this.label2.Dock = System.Windows.Forms.DockStyle.Top;
this.label2.Font = new System.Drawing.Font("굴림", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(129)));
this.label2.Location = new System.Drawing.Point(1, 1);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(519, 31);
this.label2.TabIndex = 3;
this.label2.Text = "Connection Information";
this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// panel2
//
this.panel2.Controls.Add(this.propertyGrid1);
this.panel2.Controls.Add(this.label1);
this.panel2.Dock = System.Windows.Forms.DockStyle.Left;
this.panel2.Location = new System.Drawing.Point(0, 0);
this.panel2.Name = "panel2";
this.panel2.Size = new System.Drawing.Size(346, 487);
this.panel2.TabIndex = 4;
//
// label1
//
this.label1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
this.label1.Dock = System.Windows.Forms.DockStyle.Top;
this.label1.Font = new System.Drawing.Font("굴림", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(129)));
this.label1.Location = new System.Drawing.Point(0, 0);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(346, 31);
this.label1.TabIndex = 0;
this.label1.Text = "Point Information";
this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// button1
//
this.button1.Dock = System.Windows.Forms.DockStyle.Bottom;
this.button1.Font = new System.Drawing.Font("Arial Rounded MT Bold", 27.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.button1.Location = new System.Drawing.Point(1, 426);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(519, 60);
this.button1.TabIndex = 4;
this.button1.Text = "P1 ↔ P2";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// fPropertyRFIDPoint
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(867, 487);
this.Controls.Add(this.panel1);
this.Controls.Add(this.panel2);
this.Name = "fPropertyRFIDPoint";
this.Text = "fPropertyRFIDPoint";
this.Load += new System.EventHandler(this.fPropertyRFIDPoint_Load);
this.panel1.ResumeLayout(false);
this.panel2.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.PropertyGrid propertyGrid1;
private System.Windows.Forms.ComboBox comboBox1;
private System.Windows.Forms.PropertyGrid propertyGrid2;
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.Panel panel2;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Button button1;
}
}

View File

@@ -0,0 +1,55 @@
using AGVControl.Models;
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;
namespace AGVControl.Dialog
{
public partial class fPropertyRFIDPoint : Form
{
RFIDPoint RFIDPt;
List<RFIDConnection> Connections;
public fPropertyRFIDPoint(RFIDPoint point, List<RFIDConnection> connection)
{
InitializeComponent();
this.RFIDPt = point;
this.Connections = connection;
this.propertyGrid1.SelectedObject = point;
this.KeyPreview = true;
this.KeyDown += (s1, e1) => {
if (e1.KeyCode == Keys.Escape) this.Close();
};
}
private void fPropertyRFIDPoint_Load(object sender, EventArgs e)
{
foreach (var item in Connections)
comboBox1.Items.Add($"{item.P1.Value} ↔ {item.P2.Value}");
if(comboBox1.Items.Count > 0)
comboBox1.SelectedIndex = 0;
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
this.propertyGrid2.SelectedObject = this.Connections[this.comboBox1.SelectedIndex];
}
private void button1_Click(object sender, EventArgs e)
{
var item = this.Connections[this.comboBox1.SelectedIndex];
var p1 = item.P1;
var p2 = item.P2;
item.P2 = p1;// item.P1;
item.P1 = p2;// p1;
this.propertyGrid2.SelectedObject = item;
this.Validate();
}
}
}

View 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>

File diff suppressed because it is too large Load Diff

View File

@@ -3,25 +3,37 @@ using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TextBox;
namespace AGVControl
{
public static class MapControlManager
public class MapControlManager
{
public static AGVActionPrediction PredictResult = null;
public static AGV agv = new AGV();
public static List<RFIDPoint> RFIDPoints = new List<RFIDPoint>();
public static HashSet<RFIDConnection> rfidConnections = new HashSet<RFIDConnection>();
public AGVActionPrediction PredictResult = null;
public AGV agv = new AGV();
public List<RFIDPoint> RFIDPoints = new List<RFIDPoint>();
public HashSet<RFIDConnection> rfidConnections = new HashSet<RFIDConnection>();
private static ManualResetEvent mrepredict = new ManualResetEvent(true);
private ManualResetEvent mrepredict = new ManualResetEvent(true);
public MapControlManager()
{
}
~MapControlManager()
{
}
/// <summary>
/// 목표지정으로 모터방향이 이동하고 있는가?
/// history 데이터가 있어야 하며 기준데이터가 없는 경우 null 반환
/// </summary>
/// <returns></returns>
public static bool? IsMotDirection_To_Target()
public bool? IsMotDirection_To_Target()
{
if (agv.MovementHistory.Any() == false || agv.MovementHistory.Count < 2) return null;
if (agv.MainPath.Any() == false) return null;
@@ -38,27 +50,24 @@ namespace AGVControl
//지정된경로 반대방향으로 이동하고 있다
return preidx < curidx;
}
public static float GetDistance(Point p1, Point p2)
public float GetDistance(Point p1, Point p2)
{
float dx = p1.X - p2.X;
float dy = p1.Y - p2.Y;
return (float)Math.Sqrt(dx * dx + dy * dy); // double을 float로 명시적 캐스팅
}
public static AGVActionPrediction PredictNextAction()
public AGVActionPrediction PredictNextAction()
{
if (mrepredict.WaitOne(1) == false)
{
PredictResult = new AGVActionPrediction
{
Reason = "이전 작업이 완료되지 않았습니다",
ReasonCode = AGVActionReasonCode.busy,
MoveState = AGVMoveState.Stop,
Direction = agv.CurrentMOTDirection,
};
PredictResult = CreatePrediction("이전 작업이 완료되지 않았습니다",
AGVActionReasonCode.busy,
AGVMoveState.Stop,
agv.CurrentMOTDirection, false);
return PredictResult;
}
mrepredict.Reset();
try
{
@@ -68,58 +77,70 @@ namespace AGVControl
// 1. 위치를 모를 때 (CurrentRFID가 0 또는 미설정)
if (agv.CurrentRFID.Value == 0)
{
PredictResult = new AGVActionPrediction
{
Direction = Direction.Backward,
NextRFID = null,
Reason = "AGV 위치 미확정(처음 기동)",
ReasonCode = AGVActionReasonCode.NoPosition,
MoveState = AGVMoveState.Run
};
PredictResult = CreatePrediction("AGV 위치 미확정(처음 기동)",
AGVActionReasonCode.NoPosition,
AGVMoveState.Run,
Direction.Backward, true,
moveSpeed: AgvSpeed.Low,
moveDiv: AgvRunDirection.Straight);
return PredictResult;
}
//2. 이동방향을 모른다
if (agv.MovementHistory.Any() == false || agv.MovementHistory.Count < 2)
{
PredictResult = new AGVActionPrediction
{
Direction = Direction.Backward,
NextRFID = null,
Reason = "AGV이동방향 알수없음",
ReasonCode = AGVActionReasonCode.NoDirection,
MoveState = AGVMoveState.Run
};
PredictResult = CreatePrediction("AGV이동방향 알수없음",
AGVActionReasonCode.NoDirection,
AGVMoveState.Run,
Direction.Backward, true,
moveSpeed: AgvSpeed.Low,
moveDiv: AgvRunDirection.Straight);
return PredictResult;
}
// 3. 경로가 없거나 현재 위치가 경로에 없음
if ((agv.MainPath?.Count ?? 0) < 2)
if ((agv.MainPath?.Count ?? 0) < 2 || agv.MainPath.Last().Value != agv.TargetRFID.Value)
{
PredictResult = new AGVActionPrediction
//목적지가 없다면 진행할 수 없다
if (agv.TargetRFID == null)
{
Direction = agv.CurrentMOTDirection,
NextRFID = null,
Reason = "경로 없음 또는 현재 위치 미확정",
ReasonCode = AGVActionReasonCode.NoPath,
MoveState = AGVMoveState.Stop
};
return PredictResult;
PredictResult = CreatePrediction("경로 없음 또는 현재 위치 미확정",
AGVActionReasonCode.NoPath,
AGVMoveState.Stop,
agv.CurrentMOTDirection, true);
return PredictResult;
}
else
{
//목적지가 있는데 경로가 없다면 경로 예측을 진행해야한다.
var CurPt = agv.MovementHistory.Last();
var prlt = CalculatePath(CurPt, agv.TargetRFID);
if (prlt.Success == false)
{
PredictResult = CreatePrediction("목적지 경로 예측 실패",
AGVActionReasonCode.Unknown,
AGVMoveState.Stop,
agv.CurrentMOTDirection, true,
nextRFID: agv.TargetRFID);
return PredictResult;
}
else
{
//신규목적지에 대한 경로예측이 성공했다
agv.SubPath.Clear();
agv.MainPath = prlt.Path;
}
}
}
// 4. 경로상에서 다음 RFID 예측
int idx = agv.MainPath.FindIndex(p => p.Value == agv.CurrentRFID.Value);
if (idx < 0)
{
PredictResult = new AGVActionPrediction
{
Direction = agv.CurrentMOTDirection,
NextRFID = null,
Reason = "현재 위치가 경로에 없음",
ReasonCode = AGVActionReasonCode.NotOnPath,
MoveState = AGVMoveState.Stop
};
PredictResult = CreatePrediction("현재 위치가 경로에 없음",
AGVActionReasonCode.NotOnPath,
AGVMoveState.Stop,
agv.CurrentMOTDirection, true);
return PredictResult;
}
@@ -135,30 +156,25 @@ namespace AGVControl
//모션이동방향이 맞는가?
var IsMotDir = IsMotDirection_To_Target() ?? false;
var PrePT = agv.MovementHistory.Skip(agv.MovementHistory.Count - 1).First();
var PrePT = agv.MovementHistory.Skip(agv.MovementHistory.Count - 2).First();
var curPT = agv.MovementHistory.Last();
//리프트방향이 맞지 않다면 회전가능한 위치로 이동을 해야한다
if (IsLiftDir == false)
{
AgvSpeed? agv_spd = null;
AgvRunDirection? agv_dir = null;
//회전가능한 위치로 이동을 해야한다
//1. 가까운 회전위치를 찾는다
var nearTurnPoint = RFIDPoints.Where(t => t.IsRotatable)?.OrderBy(t => GetDistance(t.Location, agv.CurrentRFID.Location)).FirstOrDefault() ?? null;
if (nearTurnPoint == null)
{
PredictResult= new AGVActionPrediction
{
Direction = agv.CurrentMOTDirection,
NextRFID = null,
Reason = "회전 가능한 위치가 없습니다",
ReasonCode = AGVActionReasonCode.NoTurnPoint,
MoveState = AGVMoveState.Stop
};
PredictResult = CreatePrediction("회전 가능한 위치가 없습니다",
AGVActionReasonCode.NoTurnPoint,
AGVMoveState.Stop,
agv.CurrentMOTDirection, true);
return PredictResult;
}
@@ -168,22 +184,19 @@ namespace AGVControl
if (agv.CurrentRFID.Value != nearTurnPoint.Value)
{
if (agv.SubPath.Any() == false || agv.SubPath.Count < 2 ||
agv.SubPath.First().Value != PrePT.Value ||
agv.SubPath.First().Value != agv.CurrentRFID.Value ||
agv.SubPath.Last().Value != nearTurnPoint.Value)
{
var rlt = CalculatePath(PrePT, nearTurnPoint, true); //이전포인트도 추가를 해준다
var rlt = CalculatePath(agv.CurrentRFID, nearTurnPoint); //이전포인트도 추가를 해준다
if (rlt.Success) agv.SubPath = rlt.Path;
else
{
agv.SubPath.Clear();
PredictResult= new AGVActionPrediction
{
Direction = agv.CurrentMOTDirection,
NextRFID = nearTurnPoint,
Reason = "회전 위치까지의 경로를 계산할 수 없습니다",
ReasonCode = AGVActionReasonCode.PathCalcError,
MoveState = AGVMoveState.Stop
};
PredictResult = CreatePrediction("회전 위치까지의 경로를 계산할 수 없습니다",
AGVActionReasonCode.PathCalcError,
AGVMoveState.Stop,
agv.CurrentMOTDirection, true,
nextRFID: nearTurnPoint);
return PredictResult;
}
}
@@ -194,6 +207,9 @@ namespace AGVControl
var preidx = agv.SubPath.FindIndex(t => t.Value == PrePT.Value);
Direction newdirection = agv.CurrentMOTDirection;
string message = "턴위치로 이동중";
if (preidx > curidx)
{
//지정경로를 거꾸로 이동하고 있다
@@ -202,31 +218,44 @@ namespace AGVControl
else
newdirection = Direction.Forward;
message += "(방향전환)";
}
PredictResult= new AGVActionPrediction
{
Direction = newdirection,
NextRFID = nearTurnPoint,
Reason = message,
ReasonCode = AGVActionReasonCode.MoveForTurn,
MoveState = AGVMoveState.Run,
};
//도로정보를 확인하여 속도와 분기명령을 실행한다
var roadinfo = GetRoadInfo(agv.SubPath, curPT);
agv_spd = roadinfo.spd;
agv_dir = roadinfo.dir;
PredictResult = CreatePrediction(message,
AGVActionReasonCode.MoveForTurn,
AGVMoveState.Run,
newdirection, true,
moveSpeed: agv_spd,
moveDiv: agv_dir,
nextRFID: nearTurnPoint);
return PredictResult;
}
var roadinfo2 = GetRoadInfo(agv.SubPath.Any() ? agv.SubPath : agv.MainPath, curPT);
agv_spd = roadinfo2.spd;
agv_dir = roadinfo2.dir;
PredictResult = new AGVActionPrediction
{
Direction = agv.CurrentMOTDirection,
NextRFID = nearTurnPoint,
Reason = "턴 완료 대기",
ReasonCode = AGVActionReasonCode.NeedTurn,
MoveState = AGVMoveState.Stop
};
PredictResult = CreatePrediction("턴 완료 대기",
AGVActionReasonCode.NeedTurn,
AGVMoveState.Stop,
agv.CurrentMOTDirection, true,
moveSpeed: agv_spd,
moveDiv: agv_dir,
nextRFID: nearTurnPoint);
return PredictResult;
}
//보조이동선제거
if (agv.SubPath != null && agv.SubPath.Any())
agv.SubPath.Clear();
//3. 목적지위치까지 이동이 완료되지 않았다면 계속 이동을 하게한다
if (agv.CurrentRFID.Value != destRFID.Value)
{
@@ -247,39 +276,35 @@ namespace AGVControl
//경로상 바로 다음 위치를 확인한다
var nexstRFID = agv.MainPath.Skip(agv.MainPath.FindIndex(t => t.Value == curPT.Value) + 1).First();
PredictResult = new AGVActionPrediction
{
Direction = newdirection,
NextRFID = nexstRFID,
Reason = message,
ReasonCode = AGVActionReasonCode.Normal,
MoveState = AGVMoveState.Run,
};
var roadinfo = GetRoadInfo(agv.MainPath, curPT);
PredictResult = CreatePrediction(message,
AGVActionReasonCode.Normal,
AGVMoveState.Run,
newdirection, true,
moveSpeed: roadinfo.spd,
moveDiv: roadinfo.dir,
nextRFID: nexstRFID);
return PredictResult;
}
// 5. 목적지 도달 시
PredictResult = new AGVActionPrediction
{
Direction = agv.CurrentMOTDirection,
NextRFID = destRFID,
Reason = "경로의 마지막 지점(목적지 도달)",
ReasonCode = AGVActionReasonCode.Arrived,
MoveState = AGVMoveState.Stop
};
PredictResult = CreatePrediction("경로의 마지막 지점(목적지 도달)",
AGVActionReasonCode.Arrived,
AGVMoveState.Stop,
agv.CurrentMOTDirection, true,
nextRFID: destRFID);
return PredictResult;
}
catch (Exception ex)
{
PredictResult = new AGVActionPrediction
{
Direction = agv.CurrentMOTDirection,
NextRFID = null,
Reason = $"ERR:{ex.Message}",
ReasonCode = AGVActionReasonCode.Unknown,
MoveState = AGVMoveState.Stop
};
PredictResult = CreatePrediction($"ERR:{ex.Message}",
AGVActionReasonCode.Unknown,
AGVMoveState.Stop,
agv.CurrentMOTDirection, true);
return PredictResult;
}
finally
@@ -289,13 +314,43 @@ namespace AGVControl
}
(AgvSpeed? spd, AgvRunDirection? dir, RFIDConnection info) GetRoadInfo(List<RFIDPoint> paths, RFIDPoint curPT)
{
//도로정보를 확인하여 속도와 분기명령을 실행한다
AgvSpeed? agv_spd = null;
AgvRunDirection? agv_div = null;
RFIDConnection info = null;
var nextpt = paths.Skip(paths.FindIndex(t => t.Value == curPT.Value) + 1).FirstOrDefault();
if (nextpt != null)
{
var p1 = rfidConnections.Where(t => t.P1.Value == curPT.Value && t.P2.Value == nextpt.Value).FirstOrDefault();
if (p1 != null)
{
//positive
agv_spd = p1.MoveSpeedP;
agv_div = p1.MoveDirectionP;
info = p1;
}
var p2 = rfidConnections.Where(t => t.P2.Value == curPT.Value && t.P1.Value == nextpt.Value).FirstOrDefault();
if (p2 != null)
{
//negative
agv_spd = p2.MoveSpeedN;
agv_div = p2.MoveDirectionN;
info = p2;
}
}
return (agv_spd, agv_div, info);
}
/// <summary>
/// 이웃포인터를 반환합니다
/// </summary>
/// <param name="point"></param>
/// <returns></returns>
public static List<RFIDPoint> GetNeighbors(RFIDPoint pt)
public List<RFIDPoint> GetNeighbors(RFIDPoint pt)
{
var neighbors = new List<RFIDPoint>();
@@ -322,17 +377,17 @@ namespace AGVControl
return neighbors.Distinct().ToList();
}
public static RFIDPoint FindRFIDPoint(uint rfidValue)
public RFIDPoint FindRFIDPoint(uint rfidValue)
{
if (RFIDPoints == null || RFIDPoints.Any() == false) return null;
return RFIDPoints.FirstOrDefault(r => r.Value == rfidValue);
}
private static float Heuristic(Point a, Point b)
private float Heuristic(Point a, Point b)
{
return (float)Math.Sqrt(Math.Pow(a.X - b.X, 2) + Math.Pow(a.Y - b.Y, 2));
}
private static PathResult ReconstructPath(Dictionary<uint, RFIDPoint> cameFrom, RFIDPoint current)
private PathResult ReconstructPath(Dictionary<uint, RFIDPoint> cameFrom, RFIDPoint current)
{
var path = new List<RFIDPoint> { current };
while (cameFrom.ContainsKey(current.Value))
@@ -348,7 +403,7 @@ namespace AGVControl
Path = path,
};
}
public static PathResult CalculatePath(RFIDPoint start, RFIDPoint end, bool autorun)
public PathResult CalculatePath(RFIDPoint start, RFIDPoint end)
{
var openList = new List<RFIDPoint> { start };
var closedList = new List<RFIDPoint>();
@@ -410,7 +465,7 @@ namespace AGVControl
};
}
public static PathResult CalculatePath(uint tagStrt, uint tagEnd)
public PathResult CalculatePath(uint tagStrt, uint tagEnd)
{
var retval = new PathResult
{
@@ -426,7 +481,7 @@ namespace AGVControl
return retval;
}
retval = CalculatePath(startPoint, endPoint, false);
retval = CalculatePath(startPoint, endPoint);
if (retval.Success == false)
retval.Message = "경로를 찾을 수 없습니다";
@@ -439,7 +494,7 @@ namespace AGVControl
/// 이동경로정보가 없거나 목적지가 없으면 null 이 반환됨
/// </summary>
/// <returns></returns>
public static bool? IsLiftDirectionMatch()
public bool? IsLiftDirectionMatch()
{
if (agv.MovementHistory.Any() && agv.MovementHistory.Count > 1)
@@ -498,7 +553,40 @@ namespace AGVControl
}
}
// Changed 속성 설정을 위한 헬퍼 메서드
private bool IsPredictionChanged(AGVActionPrediction newPrediction)
{
if (PredictResult == null) return true; // 이전 예측이 없으면 변경됨
// Idx와 Changed를 제외하고 비교
return !PredictResult.Equals(newPrediction);
}
private AGVActionPrediction CreatePrediction(
string reason,
AGVActionReasonCode reasonCode,
AGVMoveState moveState,
Direction direction, bool IDXUpdate = true,
AgvSpeed? moveSpeed = null,
AgvRunDirection? moveDiv = null,
RFIDPoint nextRFID = null
)
{
var newPrediction = new AGVActionPrediction
{
NextRFID = nextRFID,
Reason = reason,
ReasonCode = reasonCode,
MoveState = moveState,
Direction = direction,
MoveSpeed = moveSpeed,
MoveDiv = moveDiv,
Idx = IDXUpdate ? (PredictResult?.Idx + 1 ?? 1) : (PredictResult?.Idx ?? 0)
};
newPrediction.Changed = IsPredictionChanged(newPrediction);
return newPrediction;
}
}
}

View File

@@ -1,248 +1,242 @@
using System;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using System.Security.Permissions;
using System.Windows.Forms;
namespace AGVControl.Models
{
public enum Direction
{
Forward = 0,
Backward = 1,
Stop = 2
}
//public class CRFIDData
//{
// public UInt16 Value { get; set; }
// public Point Location { get; set; }
// public override string ToString()
// {
// return $"RFID:{Value},P:{Location.X},{Location.Y}";
// }
//}
public class movehistorydata : RFIDPoint
{
public Direction Direction { get; set; }
public override string ToString()
{
return $"RFID:{Value},DIR:{Direction},P:{Location.X},{Location.Y}";
}
}
public class AGV
{
/// <summary>
/// RFID 번호
/// </summary>
public RFIDPoint CurrentRFID { get; set; }
/// <summary>
/// 목적지가 셋팅된경우 해당 값
/// </summary>
public RFIDPoint TargetRFID { get; set; }
/// <summary>
/// 배터리잔량(%)
/// </summary>
public float BatteryLevel { get; set; } = 0f;
/// <summary>
/// 배터리온도(board)
/// </summary>
public double BatteryTemp1 { get; set; } = 0;
/// <summary>
/// 배터리온도(cell)
/// </summary>
public double BatteryTemp2 { get; set; } = 0;
/// <summary>
/// AGV
/// </summary>
public Direction CurrentAGVDirection { get; set; }
/// <summary>
/// AGV모터 방향
/// 외부에서 값이 상시 업데이트 됩니다.
/// </summary>
public Direction CurrentMOTDirection { get; set; }
/// <summary>
/// 현재위치가 수산되면 목적지까지의 방향값이 계산됩니다.
/// </summary>
public Direction TargetDirection { get; set; } = Direction.Stop;
public bool IsMoving { get; set; }
public bool IsMarkCheck { get; set; }
public bool IsTargetDirectionMatch { get; set; }
/// <summary>
/// 메인경로
/// 경로검색으로 입력된 경로
/// </summary>
public List<RFIDPoint> MainPath { get; set; } = new List<RFIDPoint>();
/// <summary>
/// 메인경로외에 거쳐가는 중간 경로
/// </summary>
public List<RFIDPoint> SubPath { get; set; }
public List<string> PathRFIDs { get; set; }
// 이동 경로 기록을 위한 새로운 속성들
public List<movehistorydata> MovementHistory { get; } = new List<movehistorydata>();
public const int HISTORY_SIZE = 10; // 최근 4개 위치 기록
public AGV()
{
MainPath = new List<RFIDPoint>();
SubPath = new List<RFIDPoint>();
PathRFIDs = new List<string>();
CurrentRFID = new RFIDPoint();
TargetRFID = new RFIDPoint();
TargetDirection = Direction.Forward;
// BodyAngle = null;
}
// 이동 경로에 새로운 RFID 추가
public void AddToMovementHistory(UInt16 rfidValue, Point position, Direction direction)
{
// 중복 RFID가 연속으로 들어오는 경우 무시
if (MovementHistory.Count > 0 && MovementHistory.Last().Value == rfidValue)
return;
MovementHistory.Add(new movehistorydata { Value = rfidValue, Direction = direction, Location = position });
// 기록 크기 제한
if (MovementHistory.Count > HISTORY_SIZE)
{
MovementHistory.RemoveAt(0);
}
//최초방향과 마지막 방향이 일치하지 않으면 그 이전의 데이터는 삭제한다.
if (MovementHistory.Count > 2 && MovementHistory.First().Direction != MovementHistory.Last().Direction)
{
var lastTwo = MovementHistory.Skip(MovementHistory.Count - 2).Take(2).ToArray(); // [9, 10]
MovementHistory.Clear();
MovementHistory.AddRange(lastTwo);
}
}
// 연결 정보 기반 실제 이동 방향 계산
public Direction? CalculateActualDirectionByConnection(uint currentRFID, uint previousRFID, List<RFIDConnection> connections)
{
if (connections == null || connections.Count == 0)
return null;
// 이전 RFID에서 현재 RFID로의 연결 확인
var connection = connections.FirstOrDefault(c =>
(c.P1.Value == previousRFID && c.P2.Value == currentRFID) ||
(c.P1.Value == currentRFID && c.P2.Value == previousRFID));
if (connection == null)
return null; // 연결되지 않은 경로
// 연결 방향에 따라 실제 이동 방향 결정
if (connection.P1.Value == previousRFID && connection.P2.Value == currentRFID)
{
return Direction.Forward; // Start -> End 방향으로 이동
}
else
{
return Direction.Backward; // End -> Start 방향으로 이동
}
}
// 연결 정보 기반 방향 불일치 검증 및 정정
public bool ValidateAndCorrectDirectionByConnection(Direction expectedDirection, List<RFIDConnection> connections)
{
if (MovementHistory.Count < 2 || connections == null)
return true; // 검증 불가능한 경우
// 최근 두 RFID 값 가져오기
var recentRFIDs = MovementHistory.Skip(MovementHistory.Count - 2).Take(2).ToList();
if (recentRFIDs.Count < 2)
return true;
var previousRFID = recentRFIDs[0];
var currentRFID = recentRFIDs[1];
var actualDirection = CalculateActualDirectionByConnection(currentRFID.Value, previousRFID.Value, connections);
if (!actualDirection.HasValue)
return true; // 연결 정보로 방향 판단 불가
// 방향이 일치하지 않는 경우
if (actualDirection.Value != expectedDirection)
{
// AGV 모터 방향을 실제 이동 방향으로 정정
CurrentAGVDirection = actualDirection.Value;
TargetDirection = actualDirection.Value;
return false; // 정정됨을 알림
}
return true; // 방향 일치
}
// RFID 순서 기반 실제 이동 방향 계산 (기존 메서드 - 호환성 유지)
public Direction? CalculateActualDirectionByRFID()
{
if (MovementHistory.Count < 2)
return null;
// 최근 두 RFID 값으로부터 실제 이동 방향 계산
var recentRFIDs = MovementHistory.Skip(Math.Max(0, MovementHistory.Count - 2)).Take(2).ToList();
if (recentRFIDs.Count < 2)
return null;
var prevRFID = recentRFIDs[0];
var currentRFID = recentRFIDs[1];
// RFID 값의 증가/감소로 방향 판단
if (currentRFID.Value > prevRFID.Value)
{
return Direction.Forward; // RFID 값이 증가하면 전진
}
else if (currentRFID.Value < prevRFID.Value)
{
return Direction.Backward; // RFID 값이 감소하면 후진
}
else
{
return null; // 같은 RFID 값이면 방향 판단 불가
}
}
}
public class PathNode
{
public Point Location { get; set; }
public string RFID { get; set; }
public double G { get; set; } // 시작점에서 현재 노드까지의 비용
public double H { get; set; } // 현재 노드에서 목표점까지의 예상 비용
public double F => G + H; // 총 비용
public PathNode Parent { get; set; }
public PathNode(Point location, string rfid)
{
Location = location;
RFID = rfid;
G = 0;
H = 0;
Parent = null;
}
}
using System;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using System.Security.Permissions;
using System.Windows.Forms;
namespace AGVControl.Models
{
//public class CRFIDData
//{
// public UInt16 Value { get; set; }
// public Point Location { get; set; }
// public override string ToString()
// {
// return $"RFID:{Value},P:{Location.X},{Location.Y}";
// }
//}
public class movehistorydata : RFIDPoint
{
public Direction Direction { get; set; }
public override string ToString()
{
return $"RFID:{Value},DIR:{Direction},P:{Location.X},{Location.Y}";
}
}
public class AGV
{
/// <summary>
/// RFID 번호
/// </summary>
public RFIDPoint CurrentRFID { get; set; }
/// <summary>
/// 목적지가 셋팅된경우 해당 값
/// </summary>
public RFIDPoint TargetRFID { get; set; }
/// <summary>
/// 배터리잔량(%)
/// </summary>
public float BatteryLevel { get; set; } = 0f;
/// <summary>
/// 배터리온도(board)
/// </summary>
public double BatteryTemp1 { get; set; } = 0;
/// <summary>
/// 배터리온도(cell)
/// </summary>
public double BatteryTemp2 { get; set; } = 0;
/// <summary>
/// AGV
/// </summary>
public Direction CurrentAGVDirection { get; set; }
/// <summary>
/// AGV모터 방향
/// 외부에서 값이 상시 업데이트 됩니다.
/// </summary>
public Direction CurrentMOTDirection { get; set; }
/// <summary>
/// 현재위치가 수산되면 목적지까지의 방향값이 계산됩니다.
/// </summary>
public Direction TargetDirection { get; set; } = Direction.Stop;
public bool IsMoving { get; set; }
public bool IsMarkCheck { get; set; }
public bool IsTargetDirectionMatch { get; set; }
/// <summary>
/// 메인경로
/// 경로검색으로 입력된 경로
/// </summary>
public List<RFIDPoint> MainPath { get; set; } = new List<RFIDPoint>();
/// <summary>
/// 메인경로외에 거쳐가는 중간 경로
/// </summary>
public List<RFIDPoint> SubPath { get; set; }
public List<string> PathRFIDs { get; set; }
// 이동 경로 기록을 위한 새로운 속성들
public List<movehistorydata> MovementHistory { get; } = new List<movehistorydata>();
public const int HISTORY_SIZE = 10; // 최근 4개 위치 기록
public AGV()
{
MainPath = new List<RFIDPoint>();
SubPath = new List<RFIDPoint>();
PathRFIDs = new List<string>();
CurrentRFID = new RFIDPoint();
TargetRFID = new RFIDPoint();
TargetDirection = Direction.Forward;
// BodyAngle = null;
}
// 이동 경로에 새로운 RFID 추가
public void AddToMovementHistory(UInt16 rfidValue, Point position, Direction direction)
{
// 중복 RFID가 연속으로 들어오는 경우 무시
if (MovementHistory.Count > 0 && MovementHistory.Last().Value == rfidValue)
return;
MovementHistory.Add(new movehistorydata { Value = rfidValue, Direction = direction, Location = position });
// 기록 크기 제한
if (MovementHistory.Count > HISTORY_SIZE)
{
MovementHistory.RemoveAt(0);
}
//최초방향과 마지막 방향이 일치하지 않으면 그 이전의 데이터는 삭제한다.
if (MovementHistory.Count > 2 && MovementHistory.First().Direction != MovementHistory.Last().Direction)
{
var lastTwo = MovementHistory.Skip(MovementHistory.Count - 2).Take(2).ToArray(); // [9, 10]
MovementHistory.Clear();
MovementHistory.AddRange(lastTwo);
}
}
// 연결 정보 기반 실제 이동 방향 계산
public Direction? CalculateActualDirectionByConnection(uint currentRFID, uint previousRFID, List<RFIDConnection> connections)
{
if (connections == null || connections.Count == 0)
return null;
// 이전 RFID에서 현재 RFID로의 연결 확인
var connection = connections.FirstOrDefault(c =>
(c.P1.Value == previousRFID && c.P2.Value == currentRFID) ||
(c.P1.Value == currentRFID && c.P2.Value == previousRFID));
if (connection == null)
return null; // 연결되지 않은 경로
// 연결 방향에 따라 실제 이동 방향 결정
if (connection.P1.Value == previousRFID && connection.P2.Value == currentRFID)
{
return Direction.Forward; // Start -> End 방향으로 이동
}
else
{
return Direction.Backward; // End -> Start 방향으로 이동
}
}
// 연결 정보 기반 방향 불일치 검증 및 정정
public bool ValidateAndCorrectDirectionByConnection(Direction expectedDirection, List<RFIDConnection> connections)
{
if (MovementHistory.Count < 2 || connections == null)
return true; // 검증 불가능한 경우
// 최근 두 RFID 값 가져오기
var recentRFIDs = MovementHistory.Skip(MovementHistory.Count - 2).Take(2).ToList();
if (recentRFIDs.Count < 2)
return true;
var previousRFID = recentRFIDs[0];
var currentRFID = recentRFIDs[1];
var actualDirection = CalculateActualDirectionByConnection(currentRFID.Value, previousRFID.Value, connections);
if (!actualDirection.HasValue)
return true; // 연결 정보로 방향 판단 불가
// 방향이 일치하지 않는 경우
if (actualDirection.Value != expectedDirection)
{
// AGV 모터 방향을 실제 이동 방향으로 정정
CurrentAGVDirection = actualDirection.Value;
TargetDirection = actualDirection.Value;
return false; // 정정됨을 알림
}
return true; // 방향 일치
}
// RFID 순서 기반 실제 이동 방향 계산 (기존 메서드 - 호환성 유지)
public Direction? CalculateActualDirectionByRFID()
{
if (MovementHistory.Count < 2)
return null;
// 최근 두 RFID 값으로부터 실제 이동 방향 계산
var recentRFIDs = MovementHistory.Skip(Math.Max(0, MovementHistory.Count - 2)).Take(2).ToList();
if (recentRFIDs.Count < 2)
return null;
var prevRFID = recentRFIDs[0];
var currentRFID = recentRFIDs[1];
// RFID 값의 증가/감소로 방향 판단
if (currentRFID.Value > prevRFID.Value)
{
return Direction.Forward; // RFID 값이 증가하면 전진
}
else if (currentRFID.Value < prevRFID.Value)
{
return Direction.Backward; // RFID 값이 감소하면 후진
}
else
{
return null; // 같은 RFID 값이면 방향 판단 불가
}
}
}
public class PathNode
{
public Point Location { get; set; }
public string RFID { get; set; }
public double G { get; set; } // 시작점에서 현재 노드까지의 비용
public double H { get; set; } // 현재 노드에서 목표점까지의 예상 비용
public double F => G + H; // 총 비용
public PathNode Parent { get; set; }
public PathNode(Point location, string rfid)
{
Location = location;
RFID = rfid;
G = 0;
H = 0;
Parent = null;
}
}
}

View File

@@ -1,4 +1,5 @@
using AGVControl.Models;
using System;
namespace AGVControl
{
@@ -9,6 +10,48 @@ namespace AGVControl
public string Reason { get; set; }
public AGVActionReasonCode ReasonCode { get; set; }
public AGVMoveState MoveState { get; set; } // RUN 또는 STOP
}
public AgvSpeed? MoveSpeed { get; set; }
public AgvRunDirection? MoveDiv { get; set; }
public UInt32 Idx { get; set; }
public bool Changed { get; set; }
// override object.Equals
public bool Equals(AGVActionPrediction obj)
{
// null 체크
if (obj == null) return false;
// 참조가 같으면 true
if (ReferenceEquals(this, obj)) return true;
// 핵심 속성들만 비교 (Idx, Changed 제외)
if (obj.Direction != this.Direction) return false;
if (obj.ReasonCode != this.ReasonCode) return false;
if (obj.MoveState != this.MoveState) return false;
if (obj.MoveSpeed != this.MoveSpeed) return false;
if (obj.MoveDiv != this.MoveDiv) return false;
// NextRFID 비교 (null 체크 포함)
if (obj.NextRFID == null || this.NextRFID == null)
{
if (obj.NextRFID != this.NextRFID) return false; // 하나만 null이면 false
}
else
{
if (obj.NextRFID.Value != this.NextRFID.Value) return false;
}
// Reason 비교 (null 체크 포함)
if (obj.Reason == null || this.Reason == null)
{
if (obj.Reason != this.Reason) return false; // 하나만 null이면 false
}
else
{
if (obj.Reason != this.Reason) return false;
}
return true;
}
}
}

View File

@@ -1,9 +1,75 @@
using System.Drawing;
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace AGVControl.Models
{
{
/// <summary>
/// <20><><EFBFBD><EFBFBD>Ư<EFBFBD><C6AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public class RoadInformation
{
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public RFIDPoint P1 { get; set; }
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public RFIDPoint P2 { get; set; }
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EBBFA9>
/// </summary>
public bool Enable { get; set; }
/// <summary>
/// AGV<47><56> <20>̵<EFBFBD><CCB5><EFBFBD><EFBFBD><EFBFBD>(<28><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE><EFBFBD><EFBFBD>)
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ġ<EFBFBD><C4A1> <20><><EFBFBD><EFBFBD> <20>ش<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20>ֵ<EFBFBD>
/// </summary>
public Direction? LiftDirection { get; set; }
/// <summary>
/// AGV<47>̵<EFBFBD><CCB5><EFBFBD> <20>ӵ<EFBFBD> (high, middle, low)
/// </summary>
public AgvSpeed? MoveSpeed { get; set; }
/// <summary>
/// AGV<47>̵<EFBFBD><CCB5><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<28>ºб<C2BA>, <20><><EFBFBD><EFBFBD>, <20><><EFBFBD>б<EFBFBD>)
/// </summary>
public AgvRunDirection? MoveDirection { get; set; }
public RoadInformation()
{
P1 = null;
P2 = null;
LiftDirection = null;
MoveSpeed = null;
MoveDirection = null;
Enable = false;
}
/// <summary>
/// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ǿ<EFBFBD><C7BE>ִ<EFBFBD><D6B4><EFBFBD>
/// </summary>
public bool HasValue
{
get
{
if (P1 == null || P2 == null) return false;
if (LiftDirection == null && MoveSpeed == null && MoveDirection == null) return false;
return true;
}
}
}
public class MagnetLine
{
public Point StartPoint { get; set; }

View File

@@ -1,14 +1,195 @@
using AGVControl.Models;
using AR;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics.Tracing;
namespace AGVControl
{
public class RFIDConnection
{
/// <summary>
/// 시작지점
/// </summary>
public RFIDPoint P1 { get; set; }
/// <summary>
/// 종료지점
/// </summary>
public RFIDPoint P2 { get; set; }
public bool DisableP1_to_P2 { get; set; }
public bool DisableP2_to_P1 { get; set; }
public float Distance { get; set; }
/// <summary>
/// 도로의 사용여부
/// </summary>
public bool EnableP { get; set; }
public bool EnableN { get; set; }
/// <summary>
/// AGV의 이동방향(리프트방향)
/// 목적지 방향과의 일치를 위해 해당 방향을 설정할 수 있따
/// </summary>
public Direction? LiftDirectionP { get; set; }
public Direction? LiftDirectionN { get; set; }
/// <summary>
/// AGV이동시 속도 (high, middle, low)
/// </summary>
public AgvSpeed? MoveSpeedP { get; set; }
public AgvSpeed? MoveSpeedN { get; set; }
/// <summary>
/// AGV이동시 방향모드(좌분기, 전진, 우분기)
/// </summary>
public AgvRunDirection? MoveDirectionP { get; set; }
public AgvRunDirection? MoveDirectionN { get; set; }
/// <summary>
/// 파일저장 및 불러오기시 사용하는 문자열로 반환
/// </summary>
[Browsable(false)]
public string DataFileString
{
get
{
var str_enbP = EnableP ? "1" : "0";
var str_liftP = "";
if (LiftDirectionP != null) str_liftP = ((int)LiftDirectionP).ToString();
var str_movespeedP = "";
if (MoveSpeedP != null) str_movespeedP = ((int)MoveSpeedP).ToString();
var str_movdirP = "";
if (MoveDirectionP != null) str_movdirP = ((int)MoveDirectionP).ToString();
var str_enbN = EnableP ? "1" : "0";
var str_liftN = "";
if (LiftDirectionN != null) str_liftN = ((int)LiftDirectionN).ToString();
var str_movespeedN = "";
if (MoveSpeedN != null) str_movespeedN = ((int)MoveSpeedN).ToString();
var str_movdirN = "";
if (MoveDirectionN != null) str_movdirN = ((int)MoveDirectionN).ToString();
var PStr= $"{P1.Location.X},{P1.Location.Y},{P2.Location.X},{P2.Location.Y}," + //location
$"{P1.Value},{P2.Value}," + //rfid values
$"{str_enbP};{str_liftP};{str_movespeedP};{str_movdirP}," +
$"{str_enbN};{str_liftN};{str_movespeedN};{str_movdirN}";
return $"{PStr}";
}
set
{
var buf = value.Split(',');
if (buf.Length >= 2)
{
var p1x = int.Parse(buf[0]);
var p1y = int.Parse(buf[1]);
var p2x = int.Parse(buf[2]);
var p2y = int.Parse(buf[3]);
var p1v = uint.Parse(buf[4]);
var p2v = uint.Parse(buf[5]);
if (P1 == null) P1 = new RFIDPoint();
P1.Location = new System.Drawing.Point(p1x, p1y);
P1.Value = p1v;
if (P2 == null) P2 = new RFIDPoint();
P2.Location = new System.Drawing.Point(p2x, p2y);
P2.Value = p2v;
if (buf[6].Contains(";")) //양방향 정보
{
var StrP = buf[6].Split(';');
var StrN = buf[7].Split(';');
//Positive
this.EnableP = StrP[0] == "1";
if (StrP[1].isEmpty()) LiftDirectionP = null;
else LiftDirectionP = (Direction)int.Parse(StrP[1]);
if (StrP[2].isEmpty()) MoveSpeedP = null;
else MoveSpeedP = (AgvSpeed)int.Parse(StrP[2]);
if (StrP[3].isEmpty()) MoveDirectionP = null;
else MoveDirectionP = (AgvRunDirection)int.Parse(StrP[3]);
//Negative
this.EnableN = StrN[0] == "1";
if (StrN[1].isEmpty()) LiftDirectionN = null;
else LiftDirectionN = (Direction)int.Parse(StrN[1]);
if (StrN[2].isEmpty()) MoveSpeedN = null;
else MoveSpeedN = (AgvSpeed)int.Parse(StrN[2]);
if (StrN[3].isEmpty()) MoveDirectionN = null;
else MoveDirectionN = (AgvRunDirection)int.Parse(StrN[3]);
}
else
{
this.EnableP = buf[6] == "1";
if (buf[7].isEmpty()) LiftDirectionP = null;
else LiftDirectionP = (Direction)int.Parse(buf[7]);
if (buf[8].isEmpty()) MoveSpeedP = null;
else MoveSpeedP = (AgvSpeed)int.Parse(buf[8]);
if (buf[9].isEmpty()) MoveDirectionP = null;
else MoveDirectionP = (AgvRunDirection)int.Parse(buf[9]);
this.EnableN = this.EnableP;
this.LiftDirectionN = this.LiftDirectionP;
this.MoveSpeedN = this.MoveSpeedP;
this.MoveDirectionN = this.MoveDirectionP;
}
}
}
}
public RFIDConnection(string dataline = "")
{
P1 = null;
P2 = null;
LiftDirectionP = null;
MoveSpeedP = null;
MoveDirectionP = null;
EnableP = false;
LiftDirectionN = null;
MoveSpeedN = null;
MoveDirectionP = null;
EnableP = false;
if (dataline.isEmpty() == false) DataFileString = dataline;
}
/// <summary>
/// 값이 설정되어있는지
/// </summary>
public bool HasValue
{
get
{
if (P1 == null || P2 == null) return false;
if (LiftDirectionP == null && MoveSpeedP == null && MoveDirectionP == null &&
LiftDirectionN == null && MoveSpeedN == null && MoveDirectionN == null) return false;
return true;
}
}
public override bool Equals(object obj)
@@ -27,7 +208,7 @@ namespace AGVControl
public override string ToString()
{
//연결정보를 확인
return $"{P1.Value} ↔ {P2.Value},P1-2:{(DisableP1_to_P2 ? "X" : "O")},P2-1:{(DisableP2_to_P1 ? "X" : "O")}";
return $"{P1.Value} ↔ {P2.Value},ENB:{(EnableP ? "O" : "X")}|{(EnableN ? "O" : "X")}";
}
}
}

View File

@@ -1,6 +1,7 @@
using System.Drawing;
using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace AGVControl.Models
{
public class RFIDPoint
@@ -11,7 +12,9 @@ namespace AGVControl.Models
public bool IsBidirectional { get; set; } // 양방향 연결 여부
public bool IsRotatable { get; set; } // 회전 가능 여부
public Direction? FixedDirection { get; set; } // 고정 방향(없으면 null)
public bool IsTerminal { get; set; } // 종단 여부
public bool IsTerminal { get; set; } // 종단 여부
[Browsable(false)]
public RectangleF Bounds { get; set; }
public void Clear()
{

View File

@@ -6,12 +6,32 @@ using System.Threading.Tasks;
namespace AGVControl
{
public enum Direction
{
Forward = 0,
Backward = 1,
Stop = 2
}
public enum AGVMoveState
{
Stop = 0,
Run
}
public enum AgvSpeed
{
High,
Middle,
Low,
}
public enum AgvRunDirection
{
Straight,
Left,
Right,
}
public enum AGVActionReasonCode
{

View File

@@ -45,6 +45,18 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Dialog\fMapDesign.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Dialog\fMapDesign.Designer.cs">
<DependentUpon>fMapDesign.cs</DependentUpon>
</Compile>
<Compile Include="Dialog\fPropertyRFIDPoint.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Dialog\fPropertyRFIDPoint.Designer.cs">
<DependentUpon>fPropertyRFIDPoint.cs</DependentUpon>
</Compile>
<Compile Include="MapControlManager.cs" />
<Compile Include="Models\AGVActionPrediction.cs" />
<Compile Include="BatteryLevelGauge.cs">
@@ -103,6 +115,12 @@
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Dialog\fMapDesign.resx">
<DependentUpon>fMapDesign.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Dialog\fPropertyRFIDPoint.resx">
<DependentUpon>fPropertyRFIDPoint.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="MapControl.resx">
<DependentUpon>MapControl.cs</DependentUpon>
</EmbeddedResource>

View File

@@ -109,15 +109,16 @@ namespace arDev
return false;
}
if (QueryIndex == 0)
if (data[1] == 0x03)
{
return ParseBMSInfo();
}
else
else if (data[1] == 0x04)
{
return ParseBMSCellVoltage();
}
else return false;
}
bool ParseBMSCellVoltage()
@@ -376,6 +377,7 @@ namespace arDev
}
else
{
return SendQuery_ReadStatue();
}
}
@@ -398,14 +400,14 @@ namespace arDev
{
Recv0 = false;
var cmd = new List<byte>();
cmd.Add(0xDD);
cmd.Add(0xA5);
cmd.Add(0x03);
cmd.Add(0xDD); //stx
cmd.Add(0xA5); //read
cmd.Add(0x03); //command
cmd.Add(0x00);
cmd.Add(0xFF);
cmd.Add(0xFD);
cmd.Add(0x77);
cmd.Add(0x0D);
cmd.Add(0xFD); //checksum1
cmd.Add(0x77); //checksum2
cmd.Add(0x0D); //etx
return WriteData(cmd.ToArray());
}

View File

@@ -1,4 +1,6 @@

using System.Windows.Forms;
namespace AGVEmulator
{
partial class Form1
@@ -116,7 +118,7 @@ namespace AGVEmulator
this.chkSimulation = new System.Windows.Forms.CheckBox();
this.checkBox3 = new System.Windows.Forms.CheckBox();
this.panel10 = new System.Windows.Forms.Panel();
this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
this.numericUpDown1 = new System.Windows.Forms.TextBox();
this.button18 = new System.Windows.Forms.Button();
this.button17 = new System.Windows.Forms.Button();
this.button15 = new System.Windows.Forms.Button();
@@ -178,7 +180,6 @@ namespace AGVEmulator
this.groupBox5.SuspendLayout();
this.panel13.SuspendLayout();
this.panel10.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
this.groupBox3.SuspendLayout();
this.tabControl1.SuspendLayout();
this.tabPage1.SuspendLayout();
@@ -878,20 +879,11 @@ namespace AGVEmulator
//
this.numericUpDown1.Font = new System.Drawing.Font("굴림", 20F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(129)));
this.numericUpDown1.Location = new System.Drawing.Point(19, 220);
this.numericUpDown1.Maximum = new decimal(new int[] {
9999999,
0,
0,
0});
this.numericUpDown1.Name = "numericUpDown1";
this.numericUpDown1.Size = new System.Drawing.Size(130, 38);
this.numericUpDown1.TabIndex = 9;
this.numericUpDown1.Text = "101";
this.numericUpDown1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.numericUpDown1.Value = new decimal(new int[] {
9900,
0,
0,
0});
this.numericUpDown1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.numericUpDown1_KeyDown);
//
// button18
@@ -1533,7 +1525,7 @@ namespace AGVEmulator
this.groupBox5.PerformLayout();
this.panel13.ResumeLayout(false);
this.panel10.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
this.panel10.PerformLayout();
this.groupBox3.ResumeLayout(false);
this.tabControl1.ResumeLayout(false);
this.tabPage1.ResumeLayout(false);
@@ -1615,7 +1607,7 @@ namespace AGVEmulator
private System.Windows.Forms.Button button15;
private System.Windows.Forms.Button button17;
private System.Windows.Forms.Button button18;
private System.Windows.Forms.NumericUpDown numericUpDown1;
private TextBox numericUpDown1;
private System.Windows.Forms.Panel panel12;
private UC.AgvViewer agvViewer1;
private System.Windows.Forms.Panel panel13;

View File

@@ -338,7 +338,7 @@ namespace AGVEmulator
private void AgvViewer1_TagTouched(object sender, UC.AgvViewer.TagArgs e)
{
logAGV.Add($"tag touch:{e.Data}");
numericUpDown1.Value = decimal.Parse(e.Data);
numericUpDown1.Text = e.Data;// decimal.Parse(e.Data);
button18.PerformClick();
}
@@ -552,7 +552,12 @@ namespace AGVEmulator
private void button18_Click(object sender, EventArgs e)
{
AGV.SendTag(numericUpDown1.Value.ToString());
if(int.TryParse(numericUpDown1.Text, out int tagno))
{
AGV.SendTag(tagno.ToString());
numericUpDown1.SelectAll();
numericUpDown1.Focus();
}
}
private void agvViewer1_MouseDown(object sender, MouseEventArgs e)