This commit is contained in:
backuppc
2025-11-10 14:43:47 +09:00
parent 68745f23bb
commit 6e54633c08
57 changed files with 4432 additions and 1018 deletions

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
</configuration>

View File

@@ -0,0 +1,561 @@
using System;
using System.Linq;
using System.ComponentModel;
using System.Drawing.Design;
using System.Runtime.CompilerServices;
using System.Management;
using AR;
namespace Project
{
public class MyUITypeEditor : UITypeEditor
{
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
using (var f = new System.Windows.Forms.Form
{
WindowState = System.Windows.Forms.FormWindowState.Normal,
StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen,
Size = new System.Drawing.Size(800, 400),
MaximizeBox = false,
MinimizeBox = false,
Text = "Select Port",
FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog
})
{
var lst = new System.Windows.Forms.ListBox
{
Font = new System.Drawing.Font("Consolas", 15, System.Drawing.FontStyle.Bold),
Dock = System.Windows.Forms.DockStyle.Fill,
};
lst.DoubleClick += (s1, e1) =>
{
if (lst.SelectedItem != null) f.DialogResult = System.Windows.Forms.DialogResult.OK;
};
using (var searcher = new ManagementObjectSearcher("SELECT * FROM WIN32_SerialPort"))
{
var portnames = System.IO.Ports.SerialPort.GetPortNames().OrderBy(t => t);
var ports = searcher.Get().Cast<ManagementBaseObject>().ToList();
foreach (var port in portnames)
{
var desc = "";
var portInfo = ports.Where(t => t["DeviceId"].ToString() == port).FirstOrDefault();
if (portInfo != null) desc = portInfo["Caption"].ToString();
lst.Items.Add(string.Format("{0} - {1}", port, desc));
}
}
f.Controls.Add(lst);
if (f.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
var name = lst.SelectedItem.ToString().Split('-');
return name[0].Trim();
}
else
{
return base.EditValue(context, provider, value);
}
}
}
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.Modal;
}
}
public class CSetting : AR.Setting
{
#region "log"
[Category("System Log"), DisplayName("Digital Input/Output"),
Description("입/출력 장치의 상태 변화를 기록 합니다.")]
public Boolean Log_IO { get; set; }
[Category("System Log"), DisplayName("Network Alive Check(Ping)"),
Description("서버와의 통신검사 로그를 기록 합니다")]
public Boolean Log_Ping { get; set; }
[Category("System Log"), DisplayName("S/M Step Change"),
Description("상태머신의 변화 상태를 기록 합니다.")]
public Boolean Log_StepChange { get; set; }
[Category("System Log"), DisplayName("Socket Recv Message"),
Description("서버 수신 메세지를 기록 합니다.")]
public Boolean LOg_SocketRecv { get; set; }
#endregion
#region "Communication"
[Category("Commnunication Setting"), DisplayName("XBee PortName"), Editor(typeof(MyUITypeEditor), typeof(UITypeEditor))]
public string Port_XBE { get; set; }
[Category("Commnunication Setting"), DisplayName("RFID PortName"), Editor(typeof(MyUITypeEditor), typeof(UITypeEditor))]
public string Port_AGV { get; set; }
[Category("Commnunication Setting"), DisplayName("Xbee ID"), Editor(typeof(MyUITypeEditor), typeof(UITypeEditor))]
public byte XBE_ID { get; set; }
[Category("Commnunication Setting"), DisplayName("BMS PortName"), Editor(typeof(MyUITypeEditor), typeof(UITypeEditor))]
public string Port_BAT { get; set; }
public int ChargerID { get; set; }
public int Baud_AGV { get; set; }
public int Baud_BAT { get; set; }
//public int Baud_PLC { get; set; }
public int Baud_XBE { get; set; }
//public int QueryInterval_BAT { get; set; }
#endregion
#region "Debug"
[Category("Developer Setting"), DisplayName("Listening Port"),
Description("서버와의 통신을 위한 대기 포트(TCP) - 기본값 : 7979")]
public int listenPort { get; set; }
[Category("Developer Setting")]
public Boolean UseDebugMode { get; set; }
#endregion
#region "Count Reset Setting"
[Category("Count Reset Setting"), DisplayName("A/M Clear Enable"),
Description("오전 초기화 여부\n작업수량을 초기화 하려면 True 로 설정하세요")]
public Boolean datetime_Check_1 { get; set; }
[Category("Count Reset Setting"), DisplayName("P/M Clear Enable"),
Description("오후 초기화 여부\n작업수량을 초기화 하려면 True 로 설정하세요")]
public Boolean datetime_Check_2 { get; set; }
[Category("Count Reset Setting"), DisplayName("A/M Clear Time(HH:mm)"),
Description("오전 초기화 시간(시:분)\n예) 09:00")]
public string datetime_Reset_1 { get; set; }
[Category("Count Reset Setting"), DisplayName("P/M Clear Time(HH:mm)"),
Description("오후 초기화 시간(시:분)\n예) 19:00")]
public string datetime_Reset_2 { get; set; }
#endregion
#region "general"
[Category("General Setting"), DisplayName("Enable Popup Message"),
Description("오류 발생시 별도의 메세지 창으로 표시합니다. 사용하지 않을 경우에는 우측 상단의 결과창의 메세지를 확인합니다.")]
public Boolean ShowPopUpMessage { get; set; }
[Category("General Setting"), DisplayName("Asset Number"),
Description("자산번호(서버에 값 전송 시 사용됩니다)")]
public string Asset { get; set; }
[Category("General Setting"),
Description("데이터 자동 소거 기간(일) 비활성=0")]
public int AutoDeleteDay { get; set; }
[Category("General Setting"),
Description("데이터 자동 소거 조건(남은용량 %)")]
public int AutoDeleteThreshold { get; set; }
[Category("General Setting"), PasswordPropertyText(true)]
public string Password_Setup { get; set; }
[Category("General Setting"), Browsable(false)]
public string Language { get; set; }
[Category("General Setting"), DisplayName("Full Screen Window State"),
Description("화면을 전체화면으로 사용 합니다.")]
public Boolean FullScreen { get; set; }
public bool DetectManualCharge { get; set; }
public Boolean StartLog { get; set; }
#endregion
#region "TAGS"
public int TAGPOT { get; set; }
public int TAGNOT { get; set; }
public int TAG_F2_F3 { get; set; }
public int TAG_QC_F1 { get; set; }
public int TAG_F1_F2 { get; set; }
public int TAG_F3_F4 { get; set; }
public int TAG_F4_F5 { get; set; }
public int TAG_QA_QC { get; set; }
public int TAGQAB { get; set; }
public int TAGQAA { get; set; }
public int TAGQCB { get; set; }
public int TAGQCA { get; set; }
public int TAGF1A { get; set; }
public int TAGF2A { get; set; }
public int TAGF3A { get; set; }
public int TAGF4A { get; set; }
public int TAGF5A { get; set; }
public int TAGF1B { get; set; }
public int TAGF2B { get; set; }
public int TAGF3B { get; set; }
public int TAGF4B { get; set; }
public int TAGF5B { get; set; }
#endregion
#region "Charge"
public int chargerpos { get; set; }
public int ChargetWaitSec { get; set; }
public int ChargeEmergencyLevel { get; set; }
public int ChargeMaxLevel { get; set; }
public int ChargeStartLevel { get; set; }
public Boolean Enable_AutoCharge { get; set; }
public int ChargeRetryTerm { get; set; }
//public int ChargeIdleInterval { get; set; }
public int ChargeMaxTime { get; set; }
public int ChargeSearchTime { get; set; }
#endregion
#region "AGV"
public bool AutoModeOffAndClearPosition { get; set; }
public string musicfile { get; set; }
/// <summary>
/// FVI로 가능 방향이 Backward 인가?
/// Forward 방향이라면 false 를 한다
/// </summary>
public Boolean AGV_Direction_FVI_Backward { get; set; }
public Boolean Enable_Speak { get; set; }
//public Boolean Disable_BMS { get; set; }
//public Boolean Log_BMS_Tx { get; set; }
//public Boolean Log_BMS_Rx { get; set; }
//public double ChargeLimitLow { get; set; }
//public double ChargeLimitHigh { get; set; }
public string AGV_PANID { get; set; }
public string AGV_CHANNEL { get; set; }
public string AGV_ADDRESS { get; set; }
public int SCK { get; set; }
public int SSK { get; set; }
public int STT { get; set; }
public int SAD { get; set; }
public byte ZSpeed { get; set; }
public int SPD_L { get; set; }
public int SPD_M { get; set; }
public int SPD_H { get; set; }
public int SPD_DRIVE { get; set; }
public int SPD_S { get; set; }
public int SPD_R { get; set; }
public int PID_PH { get; set; }
public int PID_PM { get; set; }
public int PID_PL { get; set; }
public int PID_IH { get; set; }
public int PID_IM { get; set; }
public int PID_IL { get; set; }
public int PID_DH { get; set; }
public int PID_DM { get; set; }
public int PID_DL { get; set; }
public int PID_PS { get; set; }
public int PID_IS { get; set; }
public int PID_DS { get; set; }
public double WheelSpeedCharge { get; set; }
public byte HomePositionValue { get; set; }
public byte HomeKitNo { get; set; }
public Single interval_xbe { get; set; }
public int interval_bms { get; set; }
public int doorSoundTerm { get; set; }
public int musicvol { get; set; }
public bool Enable_Music { get; set; }
#endregion
[Category("Report"),
Description("상태기록시 장비 식별코드(4자리)"),
DisplayName("M/C ID")]
public string MCID { get; set; }
[Category("Report"),
Description("작업 기록을 장비기술(EE) Database 에 기록 합니다. 원격으로 장비 현황을 모니터링 할 수 있습니다"),
DisplayName("SAVE EE-DB")]
public Boolean Save_EEDatabase { get; set; }
[Category("Report"), Description("상태값을 전송하는 간격(초)")]
public int StatusInterval { get; set; }
[Category("AutoReboot"),
DisplayName("자동재부팅시간"),
Description("기본값 14:00:00~14:05:00 , 재부팅은 장비가 대기(IDLE)일 때에만 동작하며 지정 시간 범위를 벗어나면 동작하지 않습니다")]
public String AutoRebootTimeStart { get; set; }
[Category("AutoReboot")]
public string AUtoRebootLastTime { get; set; }
public bool SetAutoModeOn { get; set; }
public override void AfterLoad()
{
if (StatusInterval < 10) StatusInterval = 300; //5분간격
if (SAD == 0) SAD = 999;
if (TAGF1A == 0)
{
TAGNOT = 9000;
TAGQAB = 9200;
TAGQCB = 9300;
TAGF1B = 9400;
TAGF2B = 9500;
TAGF3B = 9600;
TAGF4B = 9700;
TAGF5B = 9800;
TAGQAA = 9201;
TAGQCA = 9301;
TAGF1A = 9401;
TAGF2A = 9501;
TAGF3A = 9601;
TAGF4A = 9701;
TAGF5A = 9801;
TAGPOT = 9900;
TAG_QA_QC = 9250;
TAG_QC_F1 = 9350;
TAG_F1_F2 = 9450;
TAG_F2_F3 = 9550;
TAG_F3_F4 = 9650;
TAG_F4_F5 = 9750;
}
if(TAG_F4_F5 == 0)
{
TAG_F4_F5 = 9750;
TAGF5B = 9800;
TAGF5A = 9801;
}
if (SCK == 0) SCK = 10;
if (SSK == 0) SSK = 10;
if (STT == 0) STT = 30;
if (ChargerID == 0) ChargerID = 203;
if (ChargerID < 200) ChargerID += 200;
//자동충전요건
if (ChargetWaitSec == 0) ChargetWaitSec = 3;
if (ChargeStartLevel == 0) ChargeStartLevel = 85;
if (ChargeMaxLevel == 0) ChargeMaxLevel = 85;
if (ChargeEmergencyLevel == 0) ChargeEmergencyLevel = 30;
if (interval_bms == 0) interval_bms = 10;
//충전은 10분간격으로 재시도 한다
if (ChargeRetryTerm == 0) ChargeRetryTerm = 600;
if (doorSoundTerm == 0) doorSoundTerm = 15; //기본 15초
if (ChargeSearchTime == 0) ChargeSearchTime = 25;
//최대 충전진행 시간(기본 1시간)
if (ChargeMaxTime == 0) ChargeMaxTime = 3600;
// if (interval_iostate == 0 || interval_iostate == 255) interval_iostate = 100;
if (ZSpeed == 0) ZSpeed = 20;
if (interval_xbe == 0) interval_xbe = 5.0f;
if (HomePositionValue == 0) HomePositionValue = 4;
if (HomeKitNo == 0) HomeKitNo = 2;
if (datetime_Reset_1 == "") datetime_Reset_1 = "00:00";
if (datetime_Reset_2 == "") datetime_Reset_2 = "00:00";
if (SPD_H == 0)
{
SPD_DRIVE = 200;
SPD_H = 110;
SPD_M = 70;
SPD_L = 30;
SPD_S = 61;
SPD_R = 70;
}
if (PID_PH == 0)
{
PID_PH = 180; PID_PM = 240; PID_PL = 260;
PID_IH = 610; PID_IM = 640; PID_IL = 660;
PID_DH = 110; PID_DM = 140; PID_DL = 160;
PID_PS = 200; PID_IS = 620; PID_DS = 120;
}
if (WheelSpeedCharge == 0) WheelSpeedCharge = 10;
if (AutoDeleteThreshold == 0) AutoDeleteThreshold = 20;
if (Asset == "") Asset = "DEV_SPLIT";
if (listenPort == 0) listenPort = 7979;
if (Port_XBE == "") Port_XBE = "COM8";
if (Language.isEmpty()) Language = "Kor";
if (Password_Setup.isEmpty()) Password_Setup = "0000";
if (musicfile.isEmpty()) musicfile = UTIL.CurrentPath + "music.mp3";
if (musicvol == 0) musicvol = 50;
if (string.IsNullOrEmpty(Port_AGV)) Port_AGV = "COM1";
// if (string.IsNullOrEmpty(Port_PLC)) Port_PLC = "COM2";
if (string.IsNullOrEmpty(Port_XBE)) Port_XBE = "COM4";
if (string.IsNullOrEmpty(Port_BAT)) Port_BAT = "COM7";
if (Baud_AGV == 0) Baud_AGV = 57600;
//if (Baud_PLC == 0) Baud_PLC = 19200;
if (Baud_XBE == 0) Baud_XBE = 9600;
if (Baud_BAT == 0) Baud_BAT = 9600;
}
public override void AfterSave()
{
//throw new NotImplementedException();
}
public void CopyTo(CSetting dest)
{
//이곳의 모든 쓰기가능한 속성값을 대상에 써준다.
Type thClass = this.GetType();
foreach (var method in thClass.GetMethods())
{
//var parameters = method.GetParameters();
if (!method.Name.StartsWith("get_")) continue;
string keyname = method.Name.Substring(4);
string methodName = method.Name;
object odata = GetType().GetMethod(methodName).Invoke(this, null);
var wMethod = dest.GetType().GetMethod(Convert.ToString("set_") + keyname);
if (wMethod != null) wMethod.Invoke(dest, new object[] { odata });
}
}
}
public class CounterSetting : AR.Setting, INotifyPropertyChanged
{
public DateTime CountReset { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private int countUp1 = 0;
private int countUp2 = 0;
private int countUp3 = 0;
private int countUp4 = 0;
// private int countUp5 = 0;
private int countchgaerr = 0;
private int countchga = 0;
private int countchgm = 0;
//private int countdn = 0;
private int countqa = 0;
private int countqc = 0;
//메인카운터
public int CountUp1
{
get { return countUp1; }
set { if (value != countUp1) { countUp1 = value; NotifyPropertyChanged(); } }
}
public int CountUp2
{
get { return countUp2; }
set { if (value != countUp2) { countUp2 = value; NotifyPropertyChanged(); } }
}
public int CountUp3
{
get { return countUp3; }
set { if (value != countUp3) { countUp3 = value; NotifyPropertyChanged(); } }
}
public int CountUp4
{
get { return countUp4; }
set { if (value != countUp4) { countUp4 = value; NotifyPropertyChanged(); } }
}
//public int CountUp5
//{
// get { return countUp5; }
// set { if (value != countUp5) { countUp5 = value; NotifyPropertyChanged(); } }
//}
/// <summary>
/// 상차수량(FVI 1+2+3+4)
/// </summary>
public int CountUp
{
get
{
return CountUp1 + CountUp2 + CountUp3 + CountUp4;// + CountUp5;
}
}
public int CountChargeE
{
get { return this.countchgaerr; }
set { if (value != countchgaerr) { countchgaerr = value; NotifyPropertyChanged(); } }
}
public int CountChargeA
{
get { return this.countchga; }
set { if (value != countchga) { countchga = value; NotifyPropertyChanged(); } }
}
public int CountChargeM
{
get { return this.countchgm; }
set { if (value != countchgm) { countchgm = value; NotifyPropertyChanged(); } }
}
/// <summary>
/// 하차수량(QC+QA)
/// </summary>
public int CountDn
{
get { return this.countqa + this.countqc; }
//set { if (value != countdn) { countdn = value; NotifyPropertyChanged(); } }
}
public int CountQA
{
get { return this.countqa; }
set { if (value != countqa) { countqa = value; NotifyPropertyChanged(); } }
}
public int CountQC
{
get { return this.countqc; }
set { if (value != countqc) { countqc = value; NotifyPropertyChanged(); } }
}
public void CountClear()
{
CountUp1 = 0;
CountUp2 = 0;
CountUp3 = 0;
CountUp4 = 0;
// CountUp5 = 0;
CountQC = 0;
CountQA = 0;
//CountQa2 = 0;
CountReset = DateTime.Now;
PUB.log.Add("Count Clear");
this.Save();
}
public CounterSetting()
{
this.filename = AR.UTIL.CurrentPath + "counter.xml";
}
public override void AfterLoad()
{
if (CountReset == null) CountReset = DateTime.Parse("1982-11-23");
}
public override void AfterSave()
{
//throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,225 @@
namespace Project
{
partial class Form1
{
/// <summary>
/// 필수 디자이너 변수입니다.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 사용 중인 모든 리소스를 정리합니다.
/// </summary>
/// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form
/// <summary>
/// 디자이너 지원에 필요한 메서드입니다.
/// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.cmbPortAGV = new System.Windows.Forms.ComboBox();
this.cmbPortBMS = new System.Windows.Forms.ComboBox();
this.tbBaudAGV = new System.Windows.Forms.TextBox();
this.tbBaudBMS = new System.Windows.Forms.TextBox();
this.btTestAGV = new System.Windows.Forms.Button();
this.btTestBMS = new System.Windows.Forms.Button();
this.rtLog = new System.Windows.Forms.RichTextBox();
this.btFindPort = new System.Windows.Forms.Button();
this.panel1 = new System.Windows.Forms.Panel();
this.toolStrip1 = new System.Windows.Forms.ToolStrip();
this.toolStripButton1 = new System.Windows.Forms.ToolStripButton();
this.toolStripButton2 = new System.Windows.Forms.ToolStripButton();
this.panel1.SuspendLayout();
this.toolStrip1.SuspendLayout();
this.SuspendLayout();
//
// label1
//
this.label1.Location = new System.Drawing.Point(16, 10);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(30, 20);
this.label1.TabIndex = 0;
this.label1.Text = "agv";
this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// label2
//
this.label2.Location = new System.Drawing.Point(16, 36);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(30, 20);
this.label2.TabIndex = 0;
this.label2.Text = "bms";
this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// cmbPortAGV
//
this.cmbPortAGV.FormattingEnabled = true;
this.cmbPortAGV.Location = new System.Drawing.Point(60, 10);
this.cmbPortAGV.Name = "cmbPortAGV";
this.cmbPortAGV.Size = new System.Drawing.Size(121, 20);
this.cmbPortAGV.TabIndex = 1;
//
// cmbPortBMS
//
this.cmbPortBMS.FormattingEnabled = true;
this.cmbPortBMS.Location = new System.Drawing.Point(60, 36);
this.cmbPortBMS.Name = "cmbPortBMS";
this.cmbPortBMS.Size = new System.Drawing.Size(121, 20);
this.cmbPortBMS.TabIndex = 1;
//
// tbBaudAGV
//
this.tbBaudAGV.Location = new System.Drawing.Point(187, 10);
this.tbBaudAGV.Name = "tbBaudAGV";
this.tbBaudAGV.Size = new System.Drawing.Size(100, 21);
this.tbBaudAGV.TabIndex = 2;
//
// tbBaudBMS
//
this.tbBaudBMS.Location = new System.Drawing.Point(187, 36);
this.tbBaudBMS.Name = "tbBaudBMS";
this.tbBaudBMS.Size = new System.Drawing.Size(100, 21);
this.tbBaudBMS.TabIndex = 2;
//
// btTestAGV
//
this.btTestAGV.Location = new System.Drawing.Point(294, 8);
this.btTestAGV.Name = "btTestAGV";
this.btTestAGV.Size = new System.Drawing.Size(75, 24);
this.btTestAGV.TabIndex = 3;
this.btTestAGV.Text = "Test";
this.btTestAGV.UseVisualStyleBackColor = true;
this.btTestAGV.Click += new System.EventHandler(this.btTestAGV_Click);
//
// btTestBMS
//
this.btTestBMS.Location = new System.Drawing.Point(294, 34);
this.btTestBMS.Name = "btTestBMS";
this.btTestBMS.Size = new System.Drawing.Size(75, 24);
this.btTestBMS.TabIndex = 3;
this.btTestBMS.Text = "Test";
this.btTestBMS.UseVisualStyleBackColor = true;
this.btTestBMS.Click += new System.EventHandler(this.btTestBMS_Click);
//
// rtLog
//
this.rtLog.Dock = System.Windows.Forms.DockStyle.Fill;
this.rtLog.Location = new System.Drawing.Point(0, 92);
this.rtLog.Name = "rtLog";
this.rtLog.Size = new System.Drawing.Size(450, 215);
this.rtLog.TabIndex = 4;
this.rtLog.Text = "";
//
// btFindPort
//
this.btFindPort.Location = new System.Drawing.Point(375, 11);
this.btFindPort.Name = "btFindPort";
this.btFindPort.Size = new System.Drawing.Size(71, 47);
this.btFindPort.TabIndex = 5;
this.btFindPort.Text = "find port";
this.btFindPort.UseVisualStyleBackColor = true;
this.btFindPort.Click += new System.EventHandler(this.btFindPort_Click);
//
// panel1
//
this.panel1.Controls.Add(this.cmbPortAGV);
this.panel1.Controls.Add(this.btFindPort);
this.panel1.Controls.Add(this.label1);
this.panel1.Controls.Add(this.label2);
this.panel1.Controls.Add(this.btTestBMS);
this.panel1.Controls.Add(this.cmbPortBMS);
this.panel1.Controls.Add(this.tbBaudAGV);
this.panel1.Controls.Add(this.tbBaudBMS);
this.panel1.Controls.Add(this.btTestAGV);
this.panel1.Dock = System.Windows.Forms.DockStyle.Top;
this.panel1.Location = new System.Drawing.Point(0, 25);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(450, 67);
this.panel1.TabIndex = 6;
//
// toolStrip1
//
this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripButton1,
this.toolStripButton2});
this.toolStrip1.Location = new System.Drawing.Point(0, 0);
this.toolStrip1.Name = "toolStrip1";
this.toolStrip1.Size = new System.Drawing.Size(450, 25);
this.toolStrip1.TabIndex = 7;
this.toolStrip1.Text = "toolStrip1";
//
// toolStripButton1
//
this.toolStripButton1.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton1.Image")));
this.toolStripButton1.ImageTransparentColor = System.Drawing.Color.Magenta;
this.toolStripButton1.Name = "toolStripButton1";
this.toolStripButton1.Size = new System.Drawing.Size(53, 22);
this.toolStripButton1.Text = "Load";
this.toolStripButton1.Click += new System.EventHandler(this.toolStripButton1_Click);
//
// toolStripButton2
//
this.toolStripButton2.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;
this.toolStripButton2.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton2.Image")));
this.toolStripButton2.ImageTransparentColor = System.Drawing.Color.Magenta;
this.toolStripButton2.Name = "toolStripButton2";
this.toolStripButton2.Size = new System.Drawing.Size(52, 22);
this.toolStripButton2.Text = "Save";
this.toolStripButton2.Click += new System.EventHandler(this.toolStripButton2_Click);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(450, 307);
this.Controls.Add(this.rtLog);
this.Controls.Add(this.panel1);
this.Controls.Add(this.toolStrip1);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "Form1";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "AGV Port Scanner";
this.Load += new System.EventHandler(this.Form1_Load);
this.panel1.ResumeLayout(false);
this.panel1.PerformLayout();
this.toolStrip1.ResumeLayout(false);
this.toolStrip1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.ComboBox cmbPortAGV;
private System.Windows.Forms.ComboBox cmbPortBMS;
private System.Windows.Forms.TextBox tbBaudAGV;
private System.Windows.Forms.TextBox tbBaudBMS;
private System.Windows.Forms.Button btTestAGV;
private System.Windows.Forms.Button btTestBMS;
private System.Windows.Forms.RichTextBox rtLog;
private System.Windows.Forms.Button btFindPort;
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.ToolStrip toolStrip1;
private System.Windows.Forms.ToolStripButton toolStripButton1;
private System.Windows.Forms.ToolStripButton toolStripButton2;
}
}

View File

@@ -0,0 +1,715 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
using System.IO;
using AR;
namespace Project
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
PUB.init();
// 현재 설치되어있는 시리얼포트목록을 조회해서 cmbPort... 컨트롤에 미리 입력한다.
RefreshPortList();
// 기본 BaudRate 설정
tbBaudAGV.Text = "115200";
tbBaudBMS.Text = "9600";
}
/// <summary>
/// 시리얼 포트 목록을 새로고침하여 콤보박스에 추가
/// </summary>
private void RefreshPortList()
{
try
{
string[] ports = SerialPort.GetPortNames();
cmbPortAGV.Items.Clear();
cmbPortBMS.Items.Clear();
foreach (string port in ports)
{
cmbPortAGV.Items.Add(port);
cmbPortBMS.Items.Add(port);
}
addLog($"포트 목록 새로고침 완료: {ports.Length}개 포트 발견");
}
catch (Exception ex)
{
addLog($"포트 목록 조회 오류: {ex.Message}");
}
}
/// <summary>
/// 설정파일에서 데이터를 읽어서 컨트롤에 설정한다
/// </summary>
void LoadSetting()
{
try
{
// AGV 설정
if (!string.IsNullOrEmpty(PUB.setting.Port_AGV))
{
this.cmbPortAGV.Text = PUB.setting.Port_AGV;
}
tbBaudAGV.Text = PUB.setting.Baud_AGV.ToString();
// BMS 설정
if (!string.IsNullOrEmpty(PUB.setting.Port_BAT))
{
cmbPortBMS.Text = PUB.setting.Port_BAT;
}
tbBaudBMS.Text = PUB.setting.Baud_BAT.ToString();
addLog("설정 파일 로드 완료");
}
catch (Exception ex)
{
addLog($"설정 로드 오류: {ex.Message}");
}
}
/// <summary>
/// 현재 설정된 값을 확인하고 셋팅파일에 기록한다
/// </summary>
void SaveSetting()
{
try
{
// 현재 UI 값을 설정 객체에 반영
PUB.setting.Port_AGV = cmbPortAGV.SelectedItem?.ToString() ?? "";
PUB.setting.Baud_AGV = int.TryParse(tbBaudAGV.Text, out int agvBaud) ? agvBaud : 115200;
PUB.setting.Port_BAT = cmbPortBMS.SelectedItem?.ToString() ?? "";
PUB.setting.Baud_BAT = int.TryParse(tbBaudBMS.Text, out int bmsBaud) ? bmsBaud : 9600;
// 파일에 저장
PUB.setting.Save();
addLog("설정 파일 저장 완료");
}
catch (Exception ex)
{
addLog($"설정 저장 오류: {ex.Message}");
}
}
private void Form1_Load(object sender, EventArgs e)
{
LoadSetting();
}
private void btLoadSetting_Click(object sender, EventArgs e)
{
LoadSetting();
}
private void btSaveSetting_Click(object sender, EventArgs e)
{
SaveSetting();
}
private void btTestAGV_Click(object sender, EventArgs e)
{
// AGV 용 프로토콜을 전송해서 올바르게 피드백이 오는지 확인한다
// AGV Protocol: STX(0x02) + Data + ETX(0x03)
if (cmbPortAGV.SelectedItem == null)
{
addLog("[AGV] 포트를 선택해주세요");
return;
}
if (!int.TryParse(tbBaudAGV.Text, out int baudRate))
{
addLog("[AGV] BaudRate가 올바르지 않습니다");
return;
}
try
{
addLog($"[AGV] 테스트 시작: {cmbPortAGV.SelectedItem} @ {baudRate}bps");
using (arDev.Narumi port = new arDev.Narumi())
{
port.PortName = cmbPortAGV.SelectedItem.ToString();
port.BaudRate = baudRate;
port.Message += (s1, e1) =>{
addLog($"[AGV] 응답 수신: {e1.Message}");
};
port.Open();
addLog($"[AGV] 포트 열기 성공");
DateTime sendtime = DateTime.Now;
port.AGVMoveStop("test");//
addLog($"[AGV] 테스트 명령 전송:");
// 응답 대기
System.Threading.Thread.Sleep(1200);
if (port.lastRecvTime > sendtime)
{
// STX, ETX 확인
//if (response.Length >= 2 && response[0] == 0x02 && response[response.Length - 1] == 0x03)
//{
addLog($"[AGV] ✓ 통신 성공 - 올바른 프로토콜 응답");
//}
//else
//{
// addLog($"[AGV] ⚠ 응답은 받았으나 프로토콜 형식이 다름");
//}
}
else
{
addLog($"[AGV] ⚠ 응답 없음 - 포트는 열렸으나 장치 응답 없음");
}
port.Close();
addLog($"[AGV] 포트 닫기 완료");
}
}
catch (Exception ex)
{
addLog($"[AGV] ✗ 오류 발생: {ex.Message}");
}
}
private void btTestBMS_Click(object sender, EventArgs e)
{
// BMS 용 프로토콜을 전송해서 올바르게 피드백이 오는지 확인한다
// BMS Protocol: STX(0xDD) + Data(32 bytes) + ETX(0x77)
if (cmbPortBMS.SelectedItem == null)
{
addLog("[BMS] 포트를 선택해주세요");
return;
}
if (!int.TryParse(tbBaudBMS.Text, out int baudRate))
{
addLog("[BMS] BaudRate가 올바르지 않습니다");
return;
}
try
{
addLog($"[BMS] 테스트 시작: {cmbPortBMS.SelectedItem} @ {baudRate}bps");
using (SerialPort port = new SerialPort())
{
port.PortName = cmbPortBMS.SelectedItem.ToString();
port.BaudRate = baudRate;
port.DataBits = 8;
port.Parity = Parity.None;
port.StopBits = StopBits.One;
port.ReadTimeout = 3000;
port.WriteTimeout = 3000;
port.Open();
addLog($"[BMS] 포트 열기 성공");
// 간단한 테스트 명령 전송
var testCmd = new List<byte>();
testCmd.Add(0xDD);
testCmd.Add(0xA5);
testCmd.Add(0x03);
testCmd.Add(0x00);
testCmd.Add(0xFF);
testCmd.Add(0xFD);
testCmd.Add(0x77);
testCmd.Add(0x0D);
port.Write(testCmd.ToArray(), 0, testCmd.Count);//.Length);
addLog($"[BMS] 테스트 명령 전송: {BitConverter.ToString(testCmd.ToArray())}");
// 응답 대기
System.Threading.Thread.Sleep(1200);
if (port.BytesToRead > 0)
{
byte[] response = new byte[port.BytesToRead];
port.Read(response, 0, response.Length);
addLog($"[BMS] 응답 수신 ({response.Length} bytes): {BitConverter.ToString(response)}");
// STX, ETX 확인
if (response.Length >= 2 && response[0] == 0xDD && response[response.Length - 1] == 0x77)
{
addLog($"[BMS] ✓ 통신 성공 - 올바른 프로토콜 응답");
if (response.Length == 34 || response.Length == 23)
{
addLog($"[BMS] ✓ 데이터 길이 확인 ({response.Length} bytes)");
}
}
else
{
addLog($"[BMS] ⚠ 응답은 받았으나 프로토콜 형식이 다름");
}
}
else
{
addLog($"[BMS] ⚠ 응답 없음 - 포트는 열렸으나 장치 응답 없음");
}
port.Close();
addLog($"[BMS] 포트 닫기 완료");
}
}
catch (Exception ex)
{
addLog($"[BMS] ✗ 오류 발생: {ex.Message}");
}
}
void addLog(string msg)
{
// rtLog 컨트롤에 메세지를 추가하고, 추가된 메세지에 맞게 커서가 자동이동되게 한다
if (rtLog.InvokeRequired)
{
rtLog.Invoke(new Action(() => addLog(msg)));
}
else
{
string timestamp = DateTime.Now.ToString("HH:mm:ss.fff");
rtLog.AppendText($"[{timestamp}] {msg}\r\n");
rtLog.SelectionStart = rtLog.Text.Length;
rtLog.ScrollToCaret();
}
}
private async void btFindPort_Click(object sender, EventArgs e)
{
// 버튼 비활성화 (중복 실행 방지)
btFindPort.Enabled = false;
try
{
await Task.Run(() => FindPortsAsync());
}
finally
{
// 버튼 재활성화
btFindPort.Enabled = true;
}
}
private void FindPortsAsync()
{
// AGV와 BMS의 응답 포트를 병렬로 동시에 찾는다
addLog("===== 포트 자동 검색 시작 (병렬 모드) =====");
string[] ports = SerialPort.GetPortNames();
if (ports.Length == 0)
{
addLog("사용 가능한 포트가 없습니다");
return;
}
addLog($"총 {ports.Length}개 포트 검색 중...");
// 병렬 검색을 위한 변수
object lockObj = new object();
string foundAGVPort = null;
string foundBMSPort = null;
int agvBaud = 115200;
int bmsBaud = 9600;
bool bothFound = false;
// 현재 설정된 포트 (우선순위 표시용)
string currentAGVPort = null;
string currentBMSPort = null;
this.Invoke(new Action(() =>
{
currentAGVPort = cmbPortAGV.SelectedItem?.ToString();
currentBMSPort = cmbPortBMS.SelectedItem?.ToString();
}));
// 현재 설정 확인 로그
addLog($"현재 AGV 설정: {(string.IsNullOrEmpty(currentAGVPort) ? "( )" : currentAGVPort)}");
addLog($"현재 BMS 설정: {(string.IsNullOrEmpty(currentBMSPort) ? "( )" : currentBMSPort)}");
// === 1단계: 현재 설정된 포트 우선 테스트 ===
addLog("--- 1단계: 현재 설정 포트 우선 테스트 ---");
// AGV 현재 포트 우선 테스트
if (!string.IsNullOrEmpty(currentAGVPort) && ports.Contains(currentAGVPort))
{
addLog($"[우선] AGV 현재 포트 테스트: {currentAGVPort}");
for (int retry = 1; retry <= 3; retry++)
{
if (TestAGVPort(currentAGVPort, agvBaud))
{
foundAGVPort = currentAGVPort;
addLog($"✓ 현재 설정 포트에서 AGV 발견: {currentAGVPort}");
break;
}
if (retry < 3) System.Threading.Thread.Sleep(500);
}
}
// BMS 현재 포트 우선 테스트
if (!string.IsNullOrEmpty(currentBMSPort) && ports.Contains(currentBMSPort))
{
addLog($"[우선] BMS 현재 포트 테스트: {currentBMSPort}");
for (int retry = 1; retry <= 3; retry++)
{
if (TestBMSPort(currentBMSPort, bmsBaud))
{
foundBMSPort = currentBMSPort;
addLog($"✓ 현재 설정 포트에서 BMS 발견: {currentBMSPort}");
break;
}
if (retry < 3) System.Threading.Thread.Sleep(500);
}
}
// 둘 다 찾았으면 즉시 종료
if (foundAGVPort != null && foundBMSPort != null)
{
addLog("현재 설정 포트에서 모두 발견! 검색 종료");
ApplyFoundPorts(foundAGVPort, foundBMSPort, agvBaud, bmsBaud);
addLog("===== 포트 자동 검색 완료 =====");
return;
}
// === 2단계: 나머지 포트 병렬 검색 ===
if (foundAGVPort == null || foundBMSPort == null)
{
addLog("--- 2단계: 나머지 포트 병렬 검색 ---");
}
// 모든 포트를 병렬로 테스트 (단, 이미 테스트한 포트 제외)
List<Task> tasks = new List<Task>();
foreach (string portName in ports)
{
string port = portName; // 클로저 캡처용
// 이미 우선 테스트에서 체크한 포트는 제외
if (port == currentAGVPort || port == currentBMSPort)
continue;
Task task = Task.Run(() =>
{
// 이미 둘 다 찾았으면 즉시 종료
if (bothFound) return;
addLog($"[{port}] 검사 시작...");
// AGV 테스트 (3회 재시도)
for (int retry = 1; retry <= 3; retry++)
{
// 첫 번째 시도에서는 조기 종료하지 않고 전체 대기 시간 보장
if (retry > 1 && bothFound) return;
try
{
if (foundAGVPort == null && TestAGVPort(port, agvBaud))
{
lock (lockObj)
{
if (foundAGVPort == null)
{
foundAGVPort = port;
addLog($"[{port}] ✓ AGV 발견! (재시도: {retry}/3)");
// 둘 다 찾았는지 확인
if (foundBMSPort != null)
{
bothFound = true;
addLog("AGV와 BMS 모두 발견! 검색 종료");
}
}
}
break;
}
}
catch { }
if (retry < 3 && foundAGVPort == null && !bothFound)
{
System.Threading.Thread.Sleep(500);
}
}
// BMS 테스트 (3회 재시도)
for (int retry = 1; retry <= 3; retry++)
{
// 첫 번째 시도에서는 조기 종료하지 않고 전체 대기 시간 보장
if (retry > 1 && bothFound) return;
try
{
if (foundBMSPort == null && TestBMSPort(port, bmsBaud))
{
lock (lockObj)
{
if (foundBMSPort == null)
{
foundBMSPort = port;
addLog($"[{port}] ✓ BMS 발견! (재시도: {retry}/3)");
// 둘 다 찾았는지 확인
if (foundAGVPort != null)
{
bothFound = true;
addLog("AGV와 BMS 모두 발견! 검색 종료");
}
}
}
break;
}
}
catch { }
if (retry < 3 && foundBMSPort == null && !bothFound)
{
System.Threading.Thread.Sleep(500);
}
}
// 둘 다 실패한 경우에만 로그
if (!bothFound && foundAGVPort != port && foundBMSPort != port)
{
addLog($"[{port}] ✗ 응답 없음");
}
});
tasks.Add(task);
}
// 나머지 포트가 있을 경우만 대기
if (tasks.Count > 0)
{
addLog("나머지 포트 테스트 진행 중...");
// 주기적으로 체크하면서 둘 다 찾았으면 즉시 종료
while (!Task.WaitAll(tasks.ToArray(), 100))
{
if (bothFound)
{
addLog("검색 조기 종료 - 모든 포트 발견");
break;
}
}
}
// 결과 적용
ApplyFoundPorts(foundAGVPort, foundBMSPort, agvBaud, bmsBaud);
addLog("===== 포트 자동 검색 완료 =====");
}
/// <summary>
/// 발견된 포트를 UI에 적용
/// </summary>
private void ApplyFoundPorts(string agvPort, string bmsPort, int agvBaud, int bmsBaud)
{
if (agvPort != null)
{
this.Invoke(new Action(() =>
{
int idx = cmbPortAGV.Items.IndexOf(agvPort);
if (idx >= 0)
{
cmbPortAGV.SelectedIndex = idx;
tbBaudAGV.Text = agvBaud.ToString();
}
}));
addLog($"✓ AGV 포트: {agvPort} (Baud: {agvBaud})");
}
else
{
addLog("⚠ AGV 포트를 찾지 못했습니다");
}
if (bmsPort != null)
{
this.Invoke(new Action(() =>
{
int idx = cmbPortBMS.Items.IndexOf(bmsPort);
if (idx >= 0)
{
cmbPortBMS.SelectedIndex = idx;
tbBaudBMS.Text = bmsBaud.ToString();
}
}));
addLog($"✓ BMS 포트: {bmsPort} (Baud: {bmsBaud})");
}
else
{
addLog("⚠ BMS 포트를 찾지 못했습니다");
}
}
/// <summary>
/// AGV 포트인지 테스트 (btTestAGV_Click 코드 사용)
/// </summary>
private bool TestAGVPort(string portName, int baudRate)
{
try
{
using (arDev.Narumi port = new arDev.Narumi())
{
port.PortName = portName;
port.BaudRate = baudRate;
addLog($" >> AGV 테스트 시작: {portName} @ {baudRate}bps");
port.Open();
addLog($" >> AGV 포트 열기 성공: {portName}");
DateTime sendtime = DateTime.Now;
port.AGVMoveStop("test");
addLog($" >> AGV 명령 전송: {portName} (시간: {sendtime:HH:mm:ss.fff})");
// 응답 대기 (더 길게, 주기적으로 체크)
int maxWait = 2000; // 최대 2초 대기
int waitStep = 100;
int totalWait = 0;
while (totalWait < maxWait)
{
System.Threading.Thread.Sleep(waitStep);
totalWait += waitStep;
// lastRecvTime 확인
if (port.lastRecvTime > sendtime)
{
addLog($" >> ✓✓✓ AGV 응답 수신: {portName} (응답시간: {port.lastRecvTime:HH:mm:ss.fff}, 대기: {totalWait}ms)");
addLog($" >> 응답 데이터: {port.LastRecvString}");
port.Close();
return true;
}
// LastRecvString도 확인 (lastRecvTime이 업데이트 안 될 수도 있음)
if (!string.IsNullOrEmpty(port.LastRecvString))
{
addLog($" >> ✓✓✓ AGV 응답 감지 (문자열): {portName} (대기: {totalWait}ms)");
addLog($" >> 응답 데이터: {port.LastRecvString}");
port.Close();
return true;
}
}
addLog($" >> AGV 응답 없음: {portName} (최종 대기: {totalWait}ms, 마지막수신: {port.lastRecvTime:HH:mm:ss.fff})");
port.Close();
}
}
catch (Exception ex)
{
addLog($" >> AGV 테스트 오류: {portName} - {ex.Message}");
}
return false;
}
/// <summary>
/// BMS 포트인지 테스트 (btTestBMS_Click 코드 사용)
/// </summary>
private bool TestBMSPort(string portName, int baudRate)
{
try
{
using (SerialPort port = new SerialPort())
{
port.PortName = portName;
port.BaudRate = baudRate;
port.DataBits = 8;
port.Parity = Parity.None;
port.StopBits = StopBits.One;
port.ReadTimeout = 500;
port.WriteTimeout = 500;
addLog($" >> BMS 테스트 시작: {portName} @ {baudRate}bps");
port.Open();
addLog($" >> BMS 포트 열기 성공: {portName}");
// BMS 테스트 명령 전송 (테스트 버튼과 동일한 명령)
var testCmd = new List<byte>();
testCmd.Add(0xDD);
testCmd.Add(0xA5);
testCmd.Add(0x03);
testCmd.Add(0x00);
testCmd.Add(0xFF);
testCmd.Add(0xFD);
testCmd.Add(0x77);
testCmd.Add(0x0D);
port.Write(testCmd.ToArray(), 0, testCmd.Count);
addLog($" >> BMS 명령 전송: {portName} - {BitConverter.ToString(testCmd.ToArray())}");
// 응답 대기
System.Threading.Thread.Sleep(300);
if (port.BytesToRead > 0)
{
byte[] response = new byte[port.BytesToRead];
port.Read(response, 0, response.Length);
addLog($" >> BMS 응답 수신: {portName} ({response.Length} bytes) - {BitConverter.ToString(response)}");
// BMS 프로토콜 확인 (STX=0xDD, ETX=0x77)
if (response.Length >= 2 && response[0] == 0xDD && response[response.Length - 1] == 0x77)
{
addLog($" >> ✓✓✓ BMS 프로토콜 확인: {portName}");
port.Close();
return true;
}
else
{
addLog($" >> BMS 프로토콜 불일치: {portName}");
}
}
else
{
addLog($" >> BMS 응답 없음: {portName}");
}
port.Close();
}
}
catch (Exception ex)
{
addLog($" >> BMS 테스트 오류: {portName} - {ex.Message}");
}
return false;
}
private void toolStripButton1_Click(object sender, EventArgs e)
{
LoadSetting();
}
private void toolStripButton2_Click(object sender, EventArgs e)
{
SaveSetting();
}
}
}

View File

@@ -0,0 +1,154 @@
<?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="toolStripButton1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIFSURBVDhPpZLtS1NhGMbPPxJmmlYSgqHiKzGU1EDxg4iK
YKyG2WBogqMYJQOtCEVRFBGdTBCJfRnkS4VaaWNT5sqx1BUxRXxDHYxAJLvkusEeBaPAB+5z4Jzn+t3X
/aLhnEfjo8m+dCoa+7/C3O2Hqe0zDC+8KG+cRZHZhdzaaWTVTCLDMIY0vfM04Nfh77/G/sEhwpEDbO3t
I7TxE8urEVy99fT/AL5gWDLrTB/hnF4XsW0khCu5ln8DmJliT2AXrcNBsU1gj/MH4nMeKwBrPktM28xM
cX79DFKrHHD5d9D26hvicx4pABt2lpg10zYzU0zr7+e3xXGcrkEB2O2TNec9nJFwB3alZn5jZorfeDZh
6Q3g8s06BeCoKF4MRURoH1+BY2oNCbeb0TIclIYxOhzf8frTOuo7FxCbbVIAzpni0iceEc8vhzEwGkJD
lx83ymxifejdKjRNk/8PWnyIyTQqAJek0jqHwfEVscu31baIu8+90sTE4nY025dQ2/5FIPpnXlzKuK8A
HBUzHot52djqQ6HZhfR7IwK4mKpHtvEDMqvfCiQ6zaAAXM8x94aIWTNrLLG4kVUzgaTSPlzLtyJOZxbb
1wtfyg4Q+AfA3aZlButjSfxGcUJBk4g5tuP3haQKRKXcUQDOmbvNTpPOJeFFjordZmbWTNvMTHFUcpUC
nOccAdABIDXXE1nzAAAAAElFTkSuQmCC
</value>
</data>
<data name="toolStripButton2.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIFSURBVDhPpZLtS1NhGMbPPxJmmlYSgqHiKzGU1EDxg4iK
YKyG2WBogqMYJQOtCEVRFBGdTBCJfRnkS4VaaWNT5sqx1BUxRXxDHYxAJLvkusEeBaPAB+5z4Jzn+t3X
/aLhnEfjo8m+dCoa+7/C3O2Hqe0zDC+8KG+cRZHZhdzaaWTVTCLDMIY0vfM04Nfh77/G/sEhwpEDbO3t
I7TxE8urEVy99fT/AL5gWDLrTB/hnF4XsW0khCu5ln8DmJliT2AXrcNBsU1gj/MH4nMeKwBrPktM28xM
cX79DFKrHHD5d9D26hvicx4pABt2lpg10zYzU0zr7+e3xXGcrkEB2O2TNec9nJFwB3alZn5jZorfeDZh
6Q3g8s06BeCoKF4MRURoH1+BY2oNCbeb0TIclIYxOhzf8frTOuo7FxCbbVIAzpni0iceEc8vhzEwGkJD
lx83ymxifejdKjRNk/8PWnyIyTQqAJek0jqHwfEVscu31baIu8+90sTE4nY025dQ2/5FIPpnXlzKuK8A
HBUzHot52djqQ6HZhfR7IwK4mKpHtvEDMqvfCiQ6zaAAXM8x94aIWTNrLLG4kVUzgaTSPlzLtyJOZxbb
1wtfyg4Q+AfA3aZlButjSfxGcUJBk4g5tuP3haQKRKXcUQDOmbvNTpPOJeFFjordZmbWTNvMTHFUcpUC
nOccAdABIDXXE1nzAAAAAElFTkSuQmCC
</value>
</data>
</root>

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Project
{
public static class PUB
{
public static AR.Log log;
public static Project.CSetting setting;
public static void init()
{
log = new AR.Log();
setting = new Project.CSetting();
setting.Load();
}
}
}

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Project
{
static class Program
{
/// <summary>
/// 해당 응용 프로그램의 주 진입점입니다.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
// 이러한 특성 값을 변경하세요.
[assembly: AssemblyTitle("Test_Port")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Test_Port")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에
// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면
// 해당 형식에 대해 ComVisible 특성을 true로 설정하세요.
[assembly: ComVisible(false)]
// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다.
[assembly: Guid("ccfa2ce7-a539-4adc-b803-f759284c3463")]
// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다.
//
// 주 버전
// 부 버전
// 빌드 번호
// 수정 버전
//
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호가 자동으로
// 지정되도록 할 수 있습니다.
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 이 코드는 도구를 사용하여 생성되었습니다.
// 런타임 버전:4.0.30319.42000
//
// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
// 이러한 변경 내용이 손실됩니다.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Project.Properties {
using System;
/// <summary>
/// 지역화된 문자열 등을 찾기 위한 강력한 형식의 리소스 클래스입니다.
/// </summary>
// 이 클래스는 ResGen 또는 Visual Studio와 같은 도구를 통해 StronglyTypedResourceBuilder
// 클래스에서 자동으로 생성되었습니다.
// 멤버를 추가하거나 제거하려면 .ResX 파일을 편집한 다음 /str 옵션을 사용하여 ResGen을
// 다시 실행하거나 VS 프로젝트를 다시 빌드하십시오.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// 이 클래스에서 사용하는 캐시된 ResourceManager 인스턴스를 반환합니다.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Project.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// 이 강력한 형식의 리소스 클래스를 사용하여 모든 리소스 조회에 대한 현재 스레드의 CurrentUICulture
/// 속성을 재정의합니다.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}

View File

@@ -0,0 +1,117 @@
<?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.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</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" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 이 코드는 도구를 사용하여 생성되었습니다.
// 런타임 버전:4.0.30319.42000
//
// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
// 이러한 변경 내용이 손실됩니다.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Project.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}

View File

@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@@ -0,0 +1,103 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{CCFA2CE7-A539-4ADC-B803-F759284C3463}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>Project</RootNamespace>
<AssemblyName>Test_Port</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\..\..\..\..\Amkor\AGV4\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="arCommUtil">
<HintPath>..\..\DLL\arCommUtil.dll</HintPath>
</Reference>
<Reference Include="arControl.Net4">
<HintPath>..\..\DLL\arControl.Net4.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Management" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="CSetting.cs" />
<Compile Include="Form1.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form1.Designer.cs">
<DependentUpon>Form1.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PUB.cs" />
<EmbeddedResource Include="Form1.resx">
<DependentUpon>Form1.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\SubProject\AGV\NARUMI.csproj">
<Project>{8bae0eac-3d25-402f-9a65-2ba1ecfe28b7}</Project>
<Name>NARUMI</Name>
</ProjectReference>
<ProjectReference Include="..\..\SubProject\CommData\CommData.csproj">
<Project>{14e8c9a5-013e-49ba-b435-efefc77dd623}</Project>
<Name>CommData</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>