파일정리
This commit is contained in:
414
HMI/SubProject/AGV/Command.cs
Normal file
414
HMI/SubProject/AGV/Command.cs
Normal file
@@ -0,0 +1,414 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.ComponentModel;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections;
|
||||
using COMM;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using AR;
|
||||
|
||||
namespace arDev
|
||||
{
|
||||
public enum eNarumiTurn
|
||||
{
|
||||
None = 0,
|
||||
LeftIng,
|
||||
Left,
|
||||
RightIng,
|
||||
Right,
|
||||
}
|
||||
public class NarumiTurnInfo
|
||||
{
|
||||
public DateTime Start { get; set; }
|
||||
public DateTime End { get; set; }
|
||||
public TimeSpan Runtime
|
||||
{
|
||||
get
|
||||
{
|
||||
if (End.Year < 2000) return DateTime.Now - Start;
|
||||
if (End < Start) return DateTime.Now - Start;
|
||||
else return End - Start;
|
||||
}
|
||||
}
|
||||
public eNarumiTurn State { get; set; }
|
||||
public NarumiTurnInfo()
|
||||
{
|
||||
Start = new DateTime(1982, 11, 23);
|
||||
End = new DateTime(1982, 11, 23);
|
||||
State = eNarumiTurn.None;
|
||||
}
|
||||
}
|
||||
public class NarumiCommandTime
|
||||
{
|
||||
public DateTime Time { get; set; }
|
||||
public ushort count { get; set; }
|
||||
public NarumiCommandTime(ushort cnt)
|
||||
{
|
||||
Time = DateTime.Now;
|
||||
this.count = cnt;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// error 이상은모두 처리불가한 오류 조건을 의미한다
|
||||
/// </summary>
|
||||
public enum eNarumiCommandResult : byte
|
||||
{
|
||||
Fail = 0,
|
||||
Success = 1,
|
||||
Wait = 2,
|
||||
Error = 100,
|
||||
Timeout,
|
||||
|
||||
}
|
||||
public partial class Narumi
|
||||
{
|
||||
public NarumiTurnInfo TurnInformation { get; set; } = null;
|
||||
Dictionary<string, NarumiCommandTime> SendCommandFailList { get; set; } = new Dictionary<string, NarumiCommandTime>();
|
||||
|
||||
public eNarumiCommandResult AGVMoveSet(BunkiData opt)
|
||||
{
|
||||
var param = opt.ToString();
|
||||
return AddCommand(eAgvCmd.MoveSet, param);
|
||||
}
|
||||
|
||||
public eNarumiCommandResult AGVMoveManual(ManulOpt opt, Speed spd, Sensor ss)
|
||||
{
|
||||
var param = opt.ToString() + spd.ToString()[0] + ((int)ss).ToString();
|
||||
return AddCommand(eAgvCmd.ManualMove, param);
|
||||
}
|
||||
public eNarumiCommandResult AGVMoveRun(eRunOpt opt = eRunOpt.NotSet)
|
||||
{
|
||||
System.Text.StringBuilder sb = new StringBuilder();
|
||||
if (opt == eRunOpt.Backward) sb.Append("B");
|
||||
else if (opt == eRunOpt.Forward) sb.Append("F");
|
||||
else sb.Append("0");
|
||||
sb.Append("000");
|
||||
return AddCommand(eAgvCmd.MoveStart, sb.ToString());
|
||||
}
|
||||
|
||||
public eNarumiCommandResult AGVSetSpeed(eSetSpeed item, int speed)
|
||||
{
|
||||
string cmd = "SS";
|
||||
if (item == eSetSpeed.Rotation) cmd = "SRS";
|
||||
else cmd += item.ToString()[0];
|
||||
cmd += speed.ToString("0000");
|
||||
return AddCommand(cmd);
|
||||
}
|
||||
public eNarumiCommandResult AGVMoveStop(string Reason, eStopOpt opt = eStopOpt.Stop)
|
||||
{
|
||||
System.Text.StringBuilder sb = new StringBuilder();
|
||||
if (opt == eStopOpt.MarkStop) sb.Append("MS");
|
||||
else if (opt == eStopOpt.MarkRotateLeft) sb.Append("TL");
|
||||
else if (opt == eStopOpt.MarkRotateRight) sb.Append("TR");
|
||||
else if (opt == eStopOpt.MarkChangeDirection) sb.Append("BS");
|
||||
else sb.Append("0S");
|
||||
sb.Append("00");
|
||||
sb.Append("0000"); //재기동시간
|
||||
|
||||
//동작중이면 이 멈춤 명령을 기록으로 남긴다 230116
|
||||
if (this.system1.agv_run)
|
||||
RaiseMessage(MessageType.Normal, $"stop command from {Reason}");
|
||||
var retval = AddCommand(eAgvCmd.MoveStop, sb.ToString());
|
||||
//if (retval == eNarumiCommandResult.Success && opt == eStopOpt.MarkStop)
|
||||
// VAR.BOOL[eVarBool.NEXTSTOP_MARK] = true;
|
||||
|
||||
return retval;
|
||||
}
|
||||
public eNarumiCommandResult AGVCommand(string cmd, string data)
|
||||
{
|
||||
return AddCommand(cmd + data);
|
||||
}
|
||||
|
||||
public eNarumiCommandResult LiftControl(LiftCommand cmd)
|
||||
{
|
||||
return AddCommand(eAgvCmd.LiftControl, cmd.ToString());
|
||||
}
|
||||
public eNarumiCommandResult AGVCharge(int chargetID, bool on, int waittime = 3)
|
||||
{
|
||||
if (on)
|
||||
return AddCommand(eAgvCmd.ChargeOn, chargetID.ToString("0000"));
|
||||
else
|
||||
return AddCommand(eAgvCmd.ChargeOf, chargetID.ToString("0000"));
|
||||
}
|
||||
public eNarumiCommandResult SetBackturnTime(int time)
|
||||
{
|
||||
return AddCommand(eAgvCmd.BackTrunResumeTime, time.ToString("0000"));
|
||||
}
|
||||
public eNarumiCommandResult SetGateOutOffTime(int time)
|
||||
{
|
||||
return AddCommand(eAgvCmd.GateoutTime, time.ToString("0000"));
|
||||
}
|
||||
|
||||
public eNarumiCommandResult TurnGDSCenterScope(UInt16 time)
|
||||
{
|
||||
if (time > 2000) time = 2000;
|
||||
return AddCommand(eAgvCmd.TurnGDSCenterScope, time.ToString("0000"));
|
||||
}
|
||||
public eNarumiCommandResult AGVMoveLeft180Turn()
|
||||
{
|
||||
return AddCommand(eAgvCmd.TurnLeft);
|
||||
}
|
||||
public eNarumiCommandResult AGVMoveRight180Turn()
|
||||
{
|
||||
return AddCommand(eAgvCmd.TurnRight);
|
||||
}
|
||||
public eNarumiCommandResult AGVMoveBack180Turn(bool leftTurn)
|
||||
{
|
||||
var dir = leftTurn ? "L" : "R";
|
||||
return AddCommand(eAgvCmd.BackAndTurn, dir);
|
||||
}
|
||||
|
||||
public eNarumiCommandResult AGVErrorReset()
|
||||
{
|
||||
return AddCommand(eAgvCmd.ErrorReset, "FFFF");
|
||||
}
|
||||
public eNarumiCommandResult AGVTowerLamp(bool on)
|
||||
{
|
||||
return AddCommand(eAgvCmd.TowerLamp, (on ? "I" : "O"));
|
||||
}
|
||||
public eNarumiCommandResult AGVSetAddress(int value)
|
||||
{
|
||||
return AddCommand($"SAD{value:0000}");
|
||||
}
|
||||
public eNarumiCommandResult AGVSetPanID(string value)
|
||||
{
|
||||
value = value.PadLeft(4, '0');
|
||||
return AddCommand($"SPN{value}");
|
||||
}
|
||||
public eNarumiCommandResult AGVSetChannel(string value)
|
||||
{
|
||||
value = value.PadLeft(4, '0');
|
||||
return AddCommand($"SCH{value}");
|
||||
}
|
||||
|
||||
public eNarumiCommandResult AGVSetTagReinputTime(int value)
|
||||
{
|
||||
return AddCommand($"STT{value:0000}");
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
///// 전송에 성공한 명령시간
|
||||
///// </summary>
|
||||
////public Dictionary<String, DateTime> LastCommandOKTime { get; set; }
|
||||
protected bool SendCommand(string cmdline)
|
||||
{
|
||||
bool ret = true;
|
||||
ACKData = string.Empty;
|
||||
var fullcmd = MakeCheckSum(cmdline);
|
||||
if (WriteData(fullcmd) == false) ret = false;
|
||||
System.Threading.Thread.Sleep(1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ManualResetEvent mrecmd = new ManualResetEvent(true);
|
||||
public eNarumiCommandResult AddCommand(string cmd, int waitms = 1)
|
||||
{
|
||||
if (mrecmd.WaitOne(waitms) == false)
|
||||
{
|
||||
//다른명령을 처리하는 중이므로 대기상태로 반환한다
|
||||
return eNarumiCommandResult.Wait;
|
||||
}
|
||||
|
||||
//다른신호를 처리하지 못하게한다.
|
||||
mrecmd.Reset();
|
||||
|
||||
try
|
||||
{
|
||||
if (SendCommandFailList.ContainsKey(cmd) == false)
|
||||
{
|
||||
//실패기록이 없다
|
||||
var ret = SendCommand(cmd);
|
||||
if (ret == false)
|
||||
{
|
||||
SendCommandFailList.Add(cmd, new NarumiCommandTime(1));
|
||||
return eNarumiCommandResult.Fail;
|
||||
}
|
||||
else return eNarumiCommandResult.Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
//실패기록이 존재한다.
|
||||
//1.동일 명령이 아니면 바로 전송한다
|
||||
var precmd = SendCommandFailList[cmd];
|
||||
|
||||
//동일명령의 실패기록이 존재한다.
|
||||
//2초간의 간격을 둔다
|
||||
var ts = DateTime.Now - precmd.Time;
|
||||
if (ts.TotalSeconds < 2)
|
||||
{
|
||||
precmd.Time = DateTime.Now;
|
||||
SendCommandFailList[cmd] = precmd;
|
||||
return eNarumiCommandResult.Wait; //대기한다
|
||||
}
|
||||
else
|
||||
{
|
||||
//오류가 누적되었다.
|
||||
var ret = SendCommand(cmd);
|
||||
if (ret == false)
|
||||
{
|
||||
precmd.Time = DateTime.Now;
|
||||
precmd.count += 1;
|
||||
SendCommandFailList[cmd] = precmd;
|
||||
|
||||
//5회연속 실패했다면 타임아웃처리한다
|
||||
if (precmd.count > 5)
|
||||
{
|
||||
//타임아웃
|
||||
return eNarumiCommandResult.Timeout;
|
||||
}
|
||||
else
|
||||
{
|
||||
//실패
|
||||
return eNarumiCommandResult.Fail;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//전송이성공했으니 키를 제거한다.
|
||||
SendCommandFailList.Remove(cmd);
|
||||
return eNarumiCommandResult.Success;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"narumi addCommand error : {ex.Message}");
|
||||
return eNarumiCommandResult.Error;
|
||||
}
|
||||
finally
|
||||
{
|
||||
mrecmd.Set();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected eNarumiCommandResult AddCommand(eAgvCmd command, BunkiData param)
|
||||
{
|
||||
return AddCommand(command, param.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// CBR커맨드를 사용하여 옵션값을 전송 합니다
|
||||
/// 11.분기명령 = CBR
|
||||
/// </summary>
|
||||
/// <param name="param"></param>
|
||||
/// <param name="Repeat"></param>
|
||||
protected eNarumiCommandResult AddCommand(BunkiData param)
|
||||
{
|
||||
return AddCommand(eAgvCmd.MoveSet, param.ToString());
|
||||
}
|
||||
|
||||
protected eNarumiCommandResult AddCommand(eAgvCmd command, string param = "")
|
||||
{
|
||||
string cmdString;
|
||||
eNarumiCommandResult retval = eNarumiCommandResult.Error;
|
||||
switch (command)
|
||||
{
|
||||
case eAgvCmd.ErrorReset:
|
||||
cmdString = $"SFR{param}";
|
||||
retval = AddCommand(cmdString);
|
||||
break;
|
||||
case eAgvCmd.TowerLamp:
|
||||
cmdString = $"CBZ" + $"0299{param}0000";
|
||||
retval = AddCommand(cmdString);
|
||||
break;
|
||||
case eAgvCmd.MoveStop:
|
||||
cmdString = $"CST{param}";
|
||||
system1.agv_run_manual = false;
|
||||
retval = AddCommand(cmdString);
|
||||
break;
|
||||
case eAgvCmd.MoveStart:
|
||||
cmdString = $"CRN{param}";
|
||||
retval = AddCommand(cmdString);
|
||||
break;
|
||||
|
||||
case eAgvCmd.ChargeOf:
|
||||
cmdString = $"CBT{param}O0003"; ///0003=충전대기시간
|
||||
retval = AddCommand(cmdString);
|
||||
RaiseMessage(NarumiSerialComm.MessageType.Normal, "충전취소전송");
|
||||
break;
|
||||
case eAgvCmd.ChargeOn:
|
||||
cmdString = $"CBT{param}I0003"; ///0003=충전대기시간
|
||||
retval = AddCommand(cmdString);
|
||||
RaiseMessage(NarumiSerialComm.MessageType.Normal, "충전명령전송");
|
||||
break;
|
||||
|
||||
case eAgvCmd.TurnLeft:
|
||||
cmdString = $"CTL0000";
|
||||
retval = AddCommand(cmdString);
|
||||
if (retval == eNarumiCommandResult.Success)
|
||||
{
|
||||
if (TurnInformation == null) TurnInformation = new NarumiTurnInfo();
|
||||
TurnInformation.Start = DateTime.Now;
|
||||
TurnInformation.End = new DateTime(1982, 11, 23);
|
||||
TurnInformation.State = eNarumiTurn.LeftIng;
|
||||
}
|
||||
break;
|
||||
case eAgvCmd.TurnRight:
|
||||
cmdString = $"CTR0000";
|
||||
retval = AddCommand(cmdString);
|
||||
if (retval == eNarumiCommandResult.Success)
|
||||
{
|
||||
if (TurnInformation == null) TurnInformation = new NarumiTurnInfo();
|
||||
TurnInformation.Start = DateTime.Now;
|
||||
TurnInformation.End = new DateTime(1982, 11, 23);
|
||||
TurnInformation.State = eNarumiTurn.RightIng;
|
||||
}
|
||||
break;
|
||||
case eAgvCmd.BackAndTurn:
|
||||
if (param.isEmpty()) param = "L";
|
||||
cmdString = $"CTB000{param}";
|
||||
retval = AddCommand(cmdString);
|
||||
break;
|
||||
case eAgvCmd.CallCancle:
|
||||
cmdString = $"CCL0{param}010000";
|
||||
retval = AddCommand(cmdString);
|
||||
break;
|
||||
|
||||
|
||||
case eAgvCmd.MoveSet:
|
||||
cmdString = $"CBR{param}";
|
||||
retval = AddCommand(cmdString);
|
||||
break;
|
||||
case eAgvCmd.ManualMove:
|
||||
system1.agv_run_manual = true;
|
||||
cmdString = $"CRT{param}";
|
||||
retval = AddCommand(cmdString);
|
||||
break;
|
||||
|
||||
case eAgvCmd.LiftControl:
|
||||
cmdString = "CLF" + param.PadRight(6, '0');
|
||||
retval = AddCommand(cmdString);
|
||||
break;
|
||||
|
||||
case eAgvCmd.CPUReset:
|
||||
cmdString = "CRS0000";
|
||||
retval = AddCommand(cmdString);
|
||||
break;
|
||||
case eAgvCmd.TurnGDSCenterScope:
|
||||
if (param.isEmpty()) param = "1000";
|
||||
cmdString = $"SGS{param}";
|
||||
retval = AddCommand(cmdString);
|
||||
break;
|
||||
case eAgvCmd.BackTrunResumeTime:
|
||||
cmdString = $"SST{param}";
|
||||
retval = AddCommand(cmdString);
|
||||
break;
|
||||
case eAgvCmd.GateoutTime:
|
||||
cmdString = $"SGT{param}";
|
||||
retval = AddCommand(cmdString);
|
||||
break;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
19
HMI/SubProject/AGV/DataEventArgs.cs
Normal file
19
HMI/SubProject/AGV/DataEventArgs.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
|
||||
namespace arDev
|
||||
{
|
||||
public partial class Narumi
|
||||
{
|
||||
public class DataEventArgs : EventArgs
|
||||
{
|
||||
public DataType DataType { get; set; }
|
||||
|
||||
public DataEventArgs(DataType type)
|
||||
{
|
||||
DataType = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
69
HMI/SubProject/AGV/Dataframe.cs
Normal file
69
HMI/SubProject/AGV/Dataframe.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using AR;
|
||||
|
||||
namespace arDev
|
||||
{
|
||||
public partial class Narumi
|
||||
{
|
||||
public class Dataframe
|
||||
{
|
||||
public byte STX { get; private set; }
|
||||
public byte ETX { get; private set; }
|
||||
public byte[] Data { get; private set; }
|
||||
public string DataString { get; private set; }
|
||||
public byte[] checksum { get; private set; } = new byte[2];
|
||||
public bool Valid { get; private set; } = false;
|
||||
public string Message { get; private set; } = string.Empty;
|
||||
public byte[] Buffer { get; private set; }
|
||||
public string Cmd { get; private set; } = string.Empty;
|
||||
|
||||
public bool Parse(byte[] data, int MinRecvLength = 0)
|
||||
{
|
||||
if (data == null || data.Any() == false)
|
||||
{
|
||||
this.Message = string.Format("수신 데이터가 없습니다");
|
||||
return false;
|
||||
}
|
||||
else if (data.Length < 5)
|
||||
{
|
||||
this.Message = $"데이터의 길이가 5보다 작습니다 길이={data.Length}";
|
||||
return false;
|
||||
}
|
||||
else if (MinRecvLength > 0 && data.Length < MinRecvLength)
|
||||
{
|
||||
this.Message = $"데이터의 길이가 {MinRecvLength}보다 작습니다 길이={data.Length}";
|
||||
return false;
|
||||
}
|
||||
else if (data[0] != 0x02 || data[data.Length - 1] != 0x03)
|
||||
{
|
||||
this.Message = $"STX/ETX Error";
|
||||
return false;
|
||||
}
|
||||
Buffer = new byte[data.Length];
|
||||
Array.Copy(data, Buffer, data.Length);
|
||||
STX = data[0];
|
||||
ETX = data[data.Length - 1];
|
||||
Array.Copy(data, data.Length - 3, checksum, 0, 2);
|
||||
|
||||
Data = new byte[data.Length - 4];
|
||||
Array.Copy(data, 1, Data, 0, data.Length - 4);
|
||||
|
||||
if (data.Length > 2) Cmd = System.Text.Encoding.Default.GetString(Data, 0, 3);
|
||||
|
||||
this.DataString = System.Text.Encoding.Default.GetString(Data);
|
||||
|
||||
|
||||
Valid = true;
|
||||
return true;
|
||||
}
|
||||
public Dataframe(byte[] buffer = null, int minlen = 0)
|
||||
{
|
||||
if (buffer != null) Parse(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
221
HMI/SubProject/AGV/EnumData.cs
Normal file
221
HMI/SubProject/AGV/EnumData.cs
Normal file
@@ -0,0 +1,221 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace arDev
|
||||
{
|
||||
public partial class Narumi
|
||||
{
|
||||
public enum eMoveDir
|
||||
{
|
||||
Forward,
|
||||
Backward,
|
||||
}
|
||||
public enum eMoveSpd
|
||||
{
|
||||
High,
|
||||
Mid,
|
||||
Low,
|
||||
}
|
||||
public enum eSetPIDSpeed
|
||||
{
|
||||
High,
|
||||
Middle,
|
||||
Low,
|
||||
Stop,
|
||||
}
|
||||
public enum eSetSpeed
|
||||
{
|
||||
High,
|
||||
Middle,
|
||||
Low,
|
||||
Stop,
|
||||
Rotation,
|
||||
}
|
||||
public enum eBunki
|
||||
{
|
||||
Right,
|
||||
Strate,
|
||||
Left,
|
||||
}
|
||||
|
||||
public enum Messagetype
|
||||
{
|
||||
Normal,
|
||||
Error,
|
||||
Send,
|
||||
Recv,
|
||||
}
|
||||
public enum DataType
|
||||
{
|
||||
UNKNOWN,
|
||||
TAG,
|
||||
CALL,
|
||||
STS,
|
||||
ACK,
|
||||
NAK,
|
||||
CCA,
|
||||
}
|
||||
public class BunkiData
|
||||
{
|
||||
public BunkiData()
|
||||
{
|
||||
|
||||
}
|
||||
public BunkiData(char dir, char bunki, char speed)
|
||||
{
|
||||
if (dir == 'F') Direction = eMoveDir.Forward;
|
||||
else if (dir == 'B') Direction = eMoveDir.Backward;
|
||||
|
||||
if (bunki == 'S') Bunki = eBunki.Strate;
|
||||
else if (bunki == 'L') Bunki = eBunki.Left;
|
||||
else if (bunki == 'R') Bunki = eBunki.Right;
|
||||
|
||||
if (speed == 'H') this.Speed = eMoveSpd.High;
|
||||
else if (speed == 'M') this.Speed = eMoveSpd.Mid;
|
||||
else if (speed == 'L') this.Speed = eMoveSpd.Low;
|
||||
}
|
||||
public eMoveDir Direction { get; set; } = eMoveDir.Forward;
|
||||
public eBunki Bunki { get; set; } = eBunki.Strate;
|
||||
public eMoveSpd Speed { get; set; } = eMoveSpd.Mid;
|
||||
public int PBSSensor { get; set; } = 1;
|
||||
public override string ToString()
|
||||
{
|
||||
System.Text.StringBuilder sb = new StringBuilder();
|
||||
sb.Append(Direction.ToString()[0]);
|
||||
sb.Append(Bunki.ToString()[0]);
|
||||
sb.Append(Speed.ToString()[0]);
|
||||
sb.Append(PBSSensor.ToString()[0]);
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
public enum eAgvCmd
|
||||
{
|
||||
/// <summary>
|
||||
/// 충전시작
|
||||
/// CMD : CBT02{nBatteryNo}I0103
|
||||
/// </summary>
|
||||
ChargeOn,
|
||||
|
||||
/// <summary>
|
||||
/// 충전취소
|
||||
/// CMD : CBT02{nBatteryNo}O0103
|
||||
/// </summary>
|
||||
ChargeOf,
|
||||
|
||||
/// <summary>
|
||||
/// 이동명령(파라미터필요)
|
||||
/// 이동대상,속도(H,M,L),센서사용여부(1,0)
|
||||
/// ex) BSLTH0
|
||||
/// CMD : CRT{param}
|
||||
/// </summary>
|
||||
ManualMove,
|
||||
|
||||
/// <summary>
|
||||
/// 기동명령
|
||||
/// CMD : CRN0000
|
||||
/// </summary>
|
||||
MoveStart,
|
||||
|
||||
/// <summary>
|
||||
/// 분기명령
|
||||
/// CMD : CBR{param}
|
||||
/// </summary>
|
||||
MoveSet,
|
||||
|
||||
/// <summary>
|
||||
/// 정지 명령
|
||||
/// CMD : CST0S000000
|
||||
/// </summary>
|
||||
MoveStop,
|
||||
|
||||
/// <summary>
|
||||
/// 콜 취소,
|
||||
/// Param : 번호 char(1)
|
||||
/// CMD : CCL0{param}010000
|
||||
/// </summary>
|
||||
CallCancle,
|
||||
|
||||
/// <summary>
|
||||
/// CMD : CTL0000
|
||||
/// </summary>
|
||||
TurnLeft,
|
||||
|
||||
/// <summary>
|
||||
/// CMD : CTR0000
|
||||
/// </summary>
|
||||
TurnRight,
|
||||
|
||||
/// <summary>
|
||||
/// CMD : CTB0000
|
||||
/// </summary>
|
||||
BackAndTurn,
|
||||
|
||||
/// <summary>
|
||||
/// CMD : CBZ
|
||||
/// </summary>
|
||||
TowerLamp,
|
||||
|
||||
/// <summary>
|
||||
/// CMD : SFR
|
||||
/// </summary>
|
||||
ErrorReset,
|
||||
|
||||
/// <summary>
|
||||
/// CMD : CLF
|
||||
/// </summary>
|
||||
LiftControl,
|
||||
|
||||
/// <summary>
|
||||
/// SS(H/M/L/S)
|
||||
/// SRS
|
||||
/// </summary>
|
||||
SetSpeed,
|
||||
|
||||
CPUReset,
|
||||
|
||||
TurnGDSCenterScope,
|
||||
|
||||
BackTrunResumeTime,
|
||||
GateoutTime,
|
||||
|
||||
}
|
||||
public enum eForm
|
||||
{
|
||||
DriveControl,
|
||||
ManualControl,
|
||||
RouteSelect,
|
||||
Setting,
|
||||
ModeChange,
|
||||
}
|
||||
public enum eNotify
|
||||
{
|
||||
ReadTag,
|
||||
IpAddresschanged,
|
||||
NameChanged,
|
||||
ReadViewStep,
|
||||
ReadViewCall,
|
||||
WatchError,
|
||||
|
||||
/// <summary>
|
||||
/// 통신에서받은 AGV의 상태값이며, 속도 진행 방향을 가지고 있음
|
||||
/// Dashboardform 하단에 상태 표시 함
|
||||
/// </summary>
|
||||
StatusDisplay,
|
||||
StatusComm,
|
||||
StatusRiv,
|
||||
StatusETC,
|
||||
|
||||
ChangeMode,
|
||||
/// <summary>
|
||||
/// 편집대상경로는 아래 변수에 저장되어잇음
|
||||
/// datamanager.sEditrRoute
|
||||
/// </summary>
|
||||
EditRoute,
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
69
HMI/SubProject/AGV/NARUMI.csproj
Normal file
69
HMI/SubProject/AGV/NARUMI.csproj
Normal file
@@ -0,0 +1,69 @@
|
||||
<?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>{8BAE0EAC-3D25-402F-9A65-2BA1ECFE28B7}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>arDevice</RootNamespace>
|
||||
<AssemblyName>Narumi</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="arCommUtil">
|
||||
<HintPath>..\..\..\DLL\arCommUtil.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="DataEventArgs.cs" />
|
||||
<Compile Include="Dataframe.cs" />
|
||||
<Compile Include="EnumData.cs" />
|
||||
<Compile Include="Command.cs" />
|
||||
<Compile Include="NarumiSerialComm.cs" />
|
||||
<Compile Include="Structure\ErrorFlag.cs" />
|
||||
<Compile Include="Narumi.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Structure\SystemFlag0.cs" />
|
||||
<Compile Include="Structure\AgvData.cs" />
|
||||
<Compile Include="Structure\Signals.cs" />
|
||||
<Compile Include="Structure\SystemFlag1.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CommData\CommData.csproj">
|
||||
<Project>{14e8c9a5-013e-49ba-b435-efefc77dd623}</Project>
|
||||
<Name>CommData</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
519
HMI/SubProject/AGV/Narumi.cs
Normal file
519
HMI/SubProject/AGV/Narumi.cs
Normal file
@@ -0,0 +1,519 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.ComponentModel;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections;
|
||||
using COMM;
|
||||
using AR;
|
||||
using System.Xml;
|
||||
|
||||
namespace arDev
|
||||
{
|
||||
public partial class Narumi : arDev.NarumiSerialComm
|
||||
{
|
||||
Hashtable SystemCheck, ErrorCheck;
|
||||
private Queue Errlog; // 에러발생시 코드 임시 저장용(쓰레드 동기화용)
|
||||
|
||||
public int nBatteryNo { get; set; } = 0;
|
||||
|
||||
public Narumi()
|
||||
{
|
||||
SystemCheck = new Hashtable();
|
||||
SystemCheck.Add(15, "100");
|
||||
SystemCheck.Add(14, "9");
|
||||
SystemCheck.Add(13, "8");
|
||||
SystemCheck.Add(12, "53");
|
||||
SystemCheck.Add(11, "3");
|
||||
//SystemCheck.Add(10, "66");
|
||||
//SystemCheck.Add(9, "56");
|
||||
SystemCheck.Add(8, "6");
|
||||
SystemCheck.Add(7, "5");
|
||||
SystemCheck.Add(6, "60");
|
||||
SystemCheck.Add(5, "1");
|
||||
SystemCheck.Add(4, "2");
|
||||
//SystemCheck.Add(3, "65");
|
||||
//SystemCheck.Add(2, "55");
|
||||
//SystemCheck.Add(1, "11");
|
||||
//SystemCheck.Add(0, "22");
|
||||
|
||||
ErrorCheck = new Hashtable();
|
||||
ErrorCheck.Add(15, "17");
|
||||
ErrorCheck.Add(14, "15");
|
||||
ErrorCheck.Add(13, "18");
|
||||
ErrorCheck.Add(12, "19");
|
||||
//ErrorCheck.Add(11, "300");
|
||||
ErrorCheck.Add(10, "299");
|
||||
ErrorCheck.Add(9, "298");
|
||||
ErrorCheck.Add(8, "297");
|
||||
ErrorCheck.Add(7, "296");
|
||||
//ErrorCheck.Add(6,"");
|
||||
ErrorCheck.Add(5, "12");
|
||||
ErrorCheck.Add(4, "13");
|
||||
ErrorCheck.Add(3, "14");
|
||||
ErrorCheck.Add(2, "16");
|
||||
ErrorCheck.Add(1, "11");
|
||||
ErrorCheck.Add(0, "10");
|
||||
|
||||
Errlog = new Queue();
|
||||
MinRecvLength = 4;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#region "External Events"
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 분석완료된 데이터 이벤트
|
||||
/// </summary>
|
||||
public event EventHandler<DataEventArgs> DataReceive;
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
protected override bool CustomParser(byte[] buf, out byte[] remainBuffer)
|
||||
{
|
||||
List<byte> remain = new List<byte>();
|
||||
|
||||
//데이터는 총 34byt 이며 , DD~77로 구성됨
|
||||
Boolean bComplete = false;
|
||||
for (int i = 0; i < buf.Length; i++)
|
||||
{
|
||||
var incomByte = buf[i];
|
||||
if (bComplete == true)
|
||||
{
|
||||
remain.Add(incomByte);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (incomByte == 0x02)
|
||||
{
|
||||
findSTX = true;
|
||||
tempBuffer.Clear();
|
||||
tempBuffer.Add(incomByte);
|
||||
}
|
||||
else if (incomByte == 0x03)
|
||||
{
|
||||
//데이터가 맞게 수신됨
|
||||
//tempBuffer.Add(incomByte);
|
||||
tempBuffer.Add(incomByte);
|
||||
findSTX = false;
|
||||
bComplete = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
tempBuffer.Add(incomByte);
|
||||
if (tempBuffer.Count == 150) //data overload
|
||||
{
|
||||
findSTX = false;
|
||||
tempBuffer.Clear();
|
||||
bComplete = false;
|
||||
RaiseMessage(MessageType.Error, "Buffer Over");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
remainBuffer = remain.ToArray();
|
||||
return bComplete;
|
||||
}
|
||||
|
||||
public override bool ProcessRecvData(byte[] data)
|
||||
{
|
||||
//LastReceiveBuffer
|
||||
var frame = new Dataframe(data, MinRecvLength);
|
||||
if (frame.Valid == false)
|
||||
{
|
||||
RaiseMessage(MessageType.Error, frame.Message);
|
||||
return false;
|
||||
}
|
||||
else if (frame.DataString.StartsWith("$") == false && CheckSum(data) == false)
|
||||
{
|
||||
RaiseMessage(MessageType.Error, "Checksum Error MSG=" + frame.DataString);
|
||||
return false;
|
||||
}
|
||||
|
||||
var retval = true;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
if (frame.Cmd.Equals("ACK") || frame.Cmd.Equals("NAK"))
|
||||
{ // 응답확인값 수신 : Header(ACX), Length(9), CheckSum 확인
|
||||
RevACK(frame);
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
else if (frame.Cmd.Equals("STS"))
|
||||
{ // AGV 상태 정보 : Header(STS), Length(30), CheckSum 확인
|
||||
RevSTS(frame);
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
else if ((frame.Cmd.Equals("TAG") || frame.Cmd.Equals("CAL") || frame.Cmd.Equals("CCA")))
|
||||
{ // TAG ID 정보 : Header(STX), Length(13), CheckSum 확인
|
||||
RevTAG(frame);
|
||||
}
|
||||
else if (frame.DataString.StartsWith("$"))
|
||||
{
|
||||
// $로 시작되는 AGV 상태 표시
|
||||
//var text_Sts_Etc = Encoding.Default.GetString(bRcvData, 3, bRcvData.Length - 2).TrimStart(' '); //20210311 김정만 - SmartX FrameWork 사용 안함으로 주석처리
|
||||
//var sMessageOther = Encoding.Default.GetString(bRcvData, 3, bRcvData.Length - 2).TrimStart(' ');
|
||||
RaiseMessage(MessageType.Normal, "$메세지수신:" + frame.DataString);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
DataReceive?.Invoke(this, new DataEventArgs(DataType.UNKNOWN));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
RaiseMessage(MessageType.Error, ex.Message);
|
||||
retval = false;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
|
||||
|
||||
}
|
||||
|
||||
#region [수신] ACK(응답확인값) 분석
|
||||
|
||||
public string ACKData { get; set; } = string.Empty;
|
||||
public DateTime ACKtime { get; set; } = DateTime.Now;
|
||||
private void RevACK(Dataframe frame)
|
||||
{
|
||||
//ACKSADA7
|
||||
var rcvdNow = frame.DataString;
|
||||
var bRcvData = frame.Buffer;
|
||||
|
||||
ACKData = rcvdNow.Substring(3);
|
||||
ACKtime = DateTime.Now;
|
||||
|
||||
if (rcvdNow.StartsWith("ACK"))
|
||||
{
|
||||
//RaiseMessage("get ack");
|
||||
DataReceive?.Invoke(this, new DataEventArgs(DataType.ACK));
|
||||
//if (datamanager.commandQueue.Count != 0)
|
||||
//{
|
||||
// byte[] bCmdData = encoding.GetBytes((String)datamanager.commandQueue.Peek());
|
||||
// if (bCmdData[1] == bRcvData[4] && bCmdData[2] == bRcvData[5] && bCmdData[3] == bRcvData[6]) //보낸값이 맞는지 확인후 Dequeue
|
||||
// {
|
||||
// nSendCount = 0;
|
||||
// datamanager.commandQueue.Dequeue();
|
||||
// sSendCommandString = "";
|
||||
// }
|
||||
//}
|
||||
}
|
||||
else if (rcvdNow.StartsWith("NAK"))
|
||||
{
|
||||
//RaiseMessage("get nak");
|
||||
DataReceive?.Invoke(this, new DataEventArgs(DataType.NAK));
|
||||
//nSendCount = 0; //NAK - 재전송이 날아왔을때 nSendCommandCounter 초기화
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public SystemFlag0 system0 = new SystemFlag0();
|
||||
public SystemFlag1 system1 = new SystemFlag1();
|
||||
public ErrorFlag error = new ErrorFlag();
|
||||
public AgvData data = new AgvData();
|
||||
public Signal1 signal1 = new Signal1();
|
||||
public Signal2 signal2 = new Signal2();
|
||||
|
||||
#region [수신] STS(AGV상태정보) 분석
|
||||
public string LastSTS { get; set; } = string.Empty;
|
||||
private void RevSTS(Dataframe frame)
|
||||
{
|
||||
LastSTS = frame.DataString;
|
||||
string rcvdNow = frame.DataString.Replace("\0", "");
|
||||
byte[] bRcvData = frame.Buffer;
|
||||
var encoding = System.Text.Encoding.Default;
|
||||
try
|
||||
{
|
||||
|
||||
// AGV 베터리 잔량 표시 flag (4~6) /////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
var idx = 3;
|
||||
var battery = int.Parse(rcvdNow.Substring(idx, 3)) / 10f;// Convert.ToDouble(encoding.GetString(rcvdNow, 3, 3)) / 10;
|
||||
idx += 3;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// AGV 장치연결상태 flag (7~10) - System Flag 0
|
||||
var nDataTemp = Convert.ToInt16(rcvdNow.Substring(idx, 4), 16);
|
||||
system0.SetValue(nDataTemp);
|
||||
idx += 4;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// AGV Sts(현재 상태) flag (11~14) - System Flag 1
|
||||
nDataTemp = Convert.ToInt16(rcvdNow.Substring(idx, 4), 16);
|
||||
system1.SetValue(nDataTemp);
|
||||
idx += 4;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// AGV Error flag (15~18) - Error Flag
|
||||
nDataTemp = Convert.ToInt16(rcvdNow.Substring(idx, 4), 16);
|
||||
error.SetValue(nDataTemp);
|
||||
idx += 4;
|
||||
|
||||
data.Speed = rcvdNow.Substring(idx, 1)[0]; idx += 1; //L,M.H
|
||||
data.Sts = rcvdNow.Substring(idx, 1)[0]; idx += 1; //S(직진),L(좌분기),R(우분기)
|
||||
data.Direction = rcvdNow.Substring(idx, 1)[0]; idx += 1; //F,B,L,R
|
||||
data.guidesensor = int.Parse(rcvdNow.Substring(idx, 1)); idx += 1; //가이드 좌측부터 1~9
|
||||
|
||||
nDataTemp = Convert.ToByte(rcvdNow.Substring(idx, 2), 16);
|
||||
signal1.SetValue(nDataTemp); idx += 2;
|
||||
|
||||
//agv가 멈춰있고 마크센서가 들어온경우, 턴 작업이었다면 턴 셋팅을 한다
|
||||
if (system1.agv_run == false && system1.agv_stop == true &&
|
||||
TurnInformation != null && signal1.mark_sensor)
|
||||
{
|
||||
if (TurnInformation.Start.Year > 2000)
|
||||
{
|
||||
if (TurnInformation.State == eNarumiTurn.LeftIng || TurnInformation.State == eNarumiTurn.RightIng)
|
||||
{
|
||||
TurnInformation.End = DateTime.Now;
|
||||
if (TurnInformation.State == eNarumiTurn.LeftIng) TurnInformation.State = eNarumiTurn.Left;
|
||||
if (TurnInformation.State == eNarumiTurn.RightIng) TurnInformation.State = eNarumiTurn.Right;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//시작시간이 설정되지 않았다면 처리하지 않는다.
|
||||
}
|
||||
}
|
||||
|
||||
if (idx <= rcvdNow.Length - 2)
|
||||
{
|
||||
nDataTemp = Convert.ToByte(rcvdNow.Substring(idx, 2), 16);
|
||||
signal2.SetValue(nDataTemp);
|
||||
}
|
||||
|
||||
|
||||
DataReceive?.Invoke(this, new DataEventArgs(DataType.STS));
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
RaiseMessage(MessageType.Error, $"Parse Error(STS) = {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#region [수신] TAG(태그정보) 분석
|
||||
|
||||
System.Text.Encoding encoding = System.Text.Encoding.Default;
|
||||
string old_TagString = string.Empty;
|
||||
string old_CALString = string.Empty;
|
||||
string old_CCAString = string.Empty;
|
||||
private void RevTAG(Dataframe frame)
|
||||
{
|
||||
string rcvdNow = frame.DataString;
|
||||
byte[] bRcvData = frame.Buffer;
|
||||
if (rcvdNow.StartsWith("TAG"))
|
||||
{
|
||||
//221123 chi 숫자로변경
|
||||
var tagnostr = rcvdNow.Substring(3);
|
||||
if (ushort.TryParse(tagnostr, out ushort tagnoint))
|
||||
{
|
||||
var Changed = !old_TagString.Equals(tagnostr);
|
||||
data.TagString = tagnostr;
|
||||
data.TagNo = tagnoint;
|
||||
old_TagString = tagnostr;
|
||||
DataReceive?.Invoke(this, new DataEventArgs(DataType.TAG));
|
||||
}
|
||||
|
||||
WriteData(MakeCheckSum("ACKTAG"));
|
||||
|
||||
}
|
||||
else if (rcvdNow.StartsWith("CAL"))
|
||||
{
|
||||
|
||||
var tagnostr = encoding.GetString(bRcvData, 4, 4);
|
||||
if (int.TryParse(tagnostr, out int tagnoint))
|
||||
{
|
||||
var Changed = !old_CALString.Equals(tagnostr);
|
||||
data.CallString = tagnostr;
|
||||
data.CallNo = tagnoint;
|
||||
old_CALString = tagnostr;
|
||||
if (Changed) DataReceive?.Invoke(this, new DataEventArgs(DataType.CALL));
|
||||
}
|
||||
WriteData(MakeCheckSum("ACKCAL"));
|
||||
}
|
||||
else if (rcvdNow.StartsWith("CCA")) //능동형 Call에 의하여 들어 오는 구문
|
||||
{
|
||||
|
||||
var tagnostr = encoding.GetString(bRcvData, 4, 4);
|
||||
if (int.TryParse(tagnostr, out int tagnoint))
|
||||
{
|
||||
var Changed = !old_CCAString.Equals(tagnostr);
|
||||
data.CCAString = tagnostr;
|
||||
data.CCANo = tagnoint;
|
||||
old_CCAString = tagnostr;
|
||||
if (Changed) DataReceive?.Invoke(this, new DataEventArgs(DataType.CCA));
|
||||
}
|
||||
WriteData(MakeCheckSum("ACKCCA"));
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
private string MakeCheckSum(string sCommand)
|
||||
{
|
||||
//sCommand = sCommand.ToUpper();
|
||||
|
||||
List<byte> buffer = new List<byte>();
|
||||
buffer.Add(0x02);
|
||||
|
||||
//byte[] bCommand = System.Text.ASCIIEncoding.ASCII.GetBytes(sCommand);
|
||||
buffer.AddRange(System.Text.ASCIIEncoding.ASCII.GetBytes(sCommand));
|
||||
|
||||
//make sum
|
||||
int nSum = 0;
|
||||
for (int nCnt = 1; nCnt < buffer.Count; nCnt++)
|
||||
nSum += buffer[nCnt];
|
||||
|
||||
string sSum = nSum.ToString("X2").ToUpper();// Convert.ToString(nSum, 16).ToUpper();
|
||||
if (sSum.Length < 2) sSum = "0" + sSum;
|
||||
sSum = sSum.Substring(sSum.Length - 2);
|
||||
|
||||
//if (sSum.Length == 3)
|
||||
// sSum = sSum.Remove(0, 1);
|
||||
//else if (sSum.Length == 4)
|
||||
// sSum = sSum.Remove(0, 2);
|
||||
|
||||
buffer.AddRange(System.Text.ASCIIEncoding.Default.GetBytes(sSum));
|
||||
buffer.Add(0x03);
|
||||
|
||||
// byte[] bStxEtx = { 0x02, 0x03 };
|
||||
|
||||
|
||||
|
||||
//var orgstr = (System.Text.ASCIIEncoding.ASCII.GetString(bStxEtx, 0, 1) + sCommand + sSum + System.Text.ASCIIEncoding.ASCII.GetString(bStxEtx, 1, 1));
|
||||
var newstr = System.Text.Encoding.Default.GetString(buffer.ToArray());
|
||||
return newstr;
|
||||
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
///// commandQueue에 명령을 추가합니다(체크섬은 자동 추가됨)
|
||||
///// </summary>
|
||||
///// <param name="cmd">체크섬을 제외한 평문</param>
|
||||
///// <param name="addlog">sendlog 에 추가할 경우 true를 입력하세요</param>
|
||||
//public void AddCommand(string cmd, bool addlog = true, int Repeat = 1)
|
||||
//{
|
||||
// var fullcmd = MakeCheckSum(cmd);
|
||||
// for (int i = 0; i < Repeat; i++)
|
||||
// commandQueue.Enqueue(fullcmd);
|
||||
// if (addlog)
|
||||
// {
|
||||
// Message?.Invoke(this, new MessageEventArgs()
|
||||
// }
|
||||
//}
|
||||
|
||||
public enum eStopOpt
|
||||
{
|
||||
Stop = 0,
|
||||
MarkStop,
|
||||
MarkRotateLeft,
|
||||
MarkRotateRight,
|
||||
MarkChangeDirection,
|
||||
}
|
||||
public enum eRunOpt
|
||||
{
|
||||
NotSet,
|
||||
Forward,
|
||||
Backward,
|
||||
}
|
||||
|
||||
public enum ManulOpt
|
||||
{
|
||||
FS,
|
||||
BS,
|
||||
RT,
|
||||
LT,
|
||||
FL,
|
||||
FR,
|
||||
BL,
|
||||
BR,
|
||||
}
|
||||
public enum Sensor
|
||||
{
|
||||
PBSOff = 0,
|
||||
PBSOn,
|
||||
AllOn,
|
||||
}
|
||||
public enum Speed
|
||||
{
|
||||
High,
|
||||
Mid,
|
||||
Low,
|
||||
}
|
||||
public enum LiftCommand
|
||||
{
|
||||
/// <summary>
|
||||
/// lift up
|
||||
/// </summary>
|
||||
UP,
|
||||
/// <summary>
|
||||
/// lift down
|
||||
/// </summary>
|
||||
DN,
|
||||
/// <summary>
|
||||
/// lift 동작 정지
|
||||
/// </summary>
|
||||
STP,
|
||||
/// <summary>
|
||||
/// magnet holder on
|
||||
/// </summary>
|
||||
ON,
|
||||
/// <summary>
|
||||
/// magnet holder off
|
||||
/// </summary>
|
||||
OFF
|
||||
}
|
||||
|
||||
|
||||
private bool CheckSum(byte[] bData)
|
||||
{
|
||||
if (bData.Length < 2) // 데이터 길이가 2이하일 경우 비정상 처리
|
||||
return false;
|
||||
|
||||
int nSum = 0;
|
||||
// byte[] bData = encoding.GetBytes(sData);
|
||||
|
||||
for (int nCnt = 1; nCnt < bData.Length - 3; nCnt++)
|
||||
{
|
||||
nSum += bData[nCnt];
|
||||
}
|
||||
|
||||
|
||||
string sSum = Convert.ToString(nSum, 16).ToUpper();
|
||||
|
||||
string sCSTemp = string.Empty;
|
||||
|
||||
if (sSum.Length == 3)
|
||||
sCSTemp = sSum.Remove(0, 1);
|
||||
else if (sSum.Length == 4)
|
||||
sCSTemp = sSum.Remove(0, 2);
|
||||
|
||||
if (bData[bData.Length - 2] == '*' && bData[bData.Length - 3] == '*')
|
||||
return true;
|
||||
|
||||
if (sCSTemp[0] == (char)(bData[bData.Length - 3]) && sCSTemp[1] == (char)(bData[bData.Length - 2]))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
609
HMI/SubProject/AGV/NarumiSerialComm.cs
Normal file
609
HMI/SubProject/AGV/NarumiSerialComm.cs
Normal file
@@ -0,0 +1,609 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace arDev
|
||||
{
|
||||
public abstract class NarumiSerialComm : ISerialComm, IDisposable
|
||||
{
|
||||
protected System.IO.Ports.SerialPort _device;
|
||||
protected ManualResetEvent _mre;
|
||||
protected byte[] LastReceiveBuffer = new byte[] { };
|
||||
/// <summary>
|
||||
/// 최종 전송 메세지
|
||||
/// </summary>
|
||||
public byte[] lastSendBuffer = new byte[] { };
|
||||
//public int ValidCheckTimeMSec { get; set; } = 5000;
|
||||
protected List<byte> tempBuffer = new List<byte>();
|
||||
protected Boolean findSTX = false;
|
||||
public string ErrorMessage { get; set; }
|
||||
public DateTime LastConnTime { get; set; }
|
||||
public DateTime LastConnTryTime { get; set; }
|
||||
public DateTime lastSendTime;
|
||||
/// <summary>
|
||||
/// 메세지 수신시 사용하는 내부버퍼
|
||||
/// </summary>
|
||||
protected List<byte> _buffer = new List<byte>();
|
||||
/// <summary>
|
||||
/// 데이터조회간격(초)
|
||||
/// </summary>
|
||||
public float ScanInterval { get; set; }
|
||||
|
||||
// public byte[] LastRecvData;
|
||||
public string LastRecvString
|
||||
{
|
||||
get
|
||||
{
|
||||
if (LastReceiveBuffer == null) return String.Empty;
|
||||
else return System.Text.Encoding.Default.GetString(LastReceiveBuffer);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 마지막으로 데이터를 받은 시간
|
||||
/// </summary>
|
||||
public DateTime lastRecvTime;
|
||||
|
||||
|
||||
public int WriteError = 0;
|
||||
public string WriteErrorMessage = string.Empty;
|
||||
public int WaitTimeout { get; set; } = 1000;
|
||||
public int MinRecvLength { get; set; } = 1;
|
||||
|
||||
// Polling Thread related
|
||||
protected Thread _recvThread;
|
||||
protected volatile bool _isReading = false;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 포트이름
|
||||
/// </summary>
|
||||
[Description("시리얼 포트 이름")]
|
||||
[Category("설정"), DisplayName("Port Name")]
|
||||
public string PortName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_device == null) return string.Empty;
|
||||
else return _device.PortName;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (this.IsOpen)
|
||||
{
|
||||
Message?.Invoke(this, new MessageEventArgs("포트가 열려있어 포트이름을 변경할 수 없습니다", true));
|
||||
}
|
||||
else if (String.IsNullOrEmpty(value) == false)
|
||||
_device.PortName = value;
|
||||
else
|
||||
{
|
||||
Message?.Invoke(this, new MessageEventArgs("No PortName", true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int BaudRate
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_device == null) return 0;
|
||||
else return _device.BaudRate;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (this.IsOpen)
|
||||
{
|
||||
Message?.Invoke(this, new MessageEventArgs("포트가 열려있어 BaudRate(를) 변경할 수 없습니다", true));
|
||||
}
|
||||
else if (value != 0)
|
||||
_device.BaudRate = value;
|
||||
else Message?.Invoke(this, new MessageEventArgs("No baud rate", true));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public NarumiSerialComm()
|
||||
{
|
||||
_device = new System.IO.Ports.SerialPort();
|
||||
this.BaudRate = 57600;
|
||||
ScanInterval = 10;
|
||||
// _device.DataReceived += barcode_DataReceived; // Removed event handler
|
||||
_device.ErrorReceived += this.barcode_ErrorReceived;
|
||||
_device.WriteTimeout = 3000;
|
||||
_device.ReadTimeout = 3000;
|
||||
_device.ReadBufferSize = 8192;
|
||||
_device.WriteBufferSize = 8192;
|
||||
//_device.DiscardInBuffer();
|
||||
//_device.DiscardOutBuffer();
|
||||
ErrorMessage = string.Empty;
|
||||
lastRecvTime = DateTime.Parse("1982-11-23");
|
||||
LastConnTime = DateTime.Parse("1982-11-23");
|
||||
LastConnTryTime = DateTime.Parse("1982-11-23");
|
||||
lastRecvTime = DateTime.Parse("1982-11-23");
|
||||
this._mre = new ManualResetEvent(true);
|
||||
}
|
||||
|
||||
~NarumiSerialComm()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
|
||||
// Flag: Has Dispose already been called?
|
||||
bool disposed = false;
|
||||
|
||||
// Public implementation of Dispose pattern callable by consumers.
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
// Protected implementation of Dispose pattern.
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
// Free any other managed objects here.
|
||||
//
|
||||
}
|
||||
|
||||
// Stop reading thread
|
||||
_isReading = false;
|
||||
|
||||
// _device.DataReceived -= barcode_DataReceived; // Removed event handler
|
||||
_device.ErrorReceived -= this.barcode_ErrorReceived;
|
||||
|
||||
if (_recvThread != null && _recvThread.IsAlive)
|
||||
{
|
||||
_recvThread.Join(500);
|
||||
}
|
||||
|
||||
if (_device != null)
|
||||
{
|
||||
if (_device.IsOpen) _device.Close();
|
||||
_device.Dispose();
|
||||
}
|
||||
|
||||
// Free any unmanaged objects here.
|
||||
//
|
||||
disposed = true;
|
||||
}
|
||||
|
||||
public Boolean Open()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_device.IsOpen == false)
|
||||
{
|
||||
_device.Open();
|
||||
}
|
||||
|
||||
if (_device.IsOpen)
|
||||
{
|
||||
// Start polling thread
|
||||
if (_isReading == false)
|
||||
{
|
||||
_isReading = true;
|
||||
_recvThread = new Thread(ReadPort);
|
||||
_recvThread.IsBackground = true;
|
||||
_recvThread.Start();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ErrorMessage = ex.Message;
|
||||
Message.Invoke(this, new MessageEventArgs(ex.Message, true));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public string GetHexString(Byte[] input)
|
||||
{
|
||||
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
||||
foreach (byte b in input)
|
||||
sb.Append(" " + b.ToString("X2"));
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 포트가 열려있는지 확인
|
||||
/// </summary>
|
||||
[Description("현재 시리얼포트가 열려있는지 확인합니다")]
|
||||
[Category("정보"), DisplayName("Port Open")]
|
||||
public Boolean IsOpen
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_device == null) return false;
|
||||
return _device.IsOpen;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool Close()
|
||||
{
|
||||
try
|
||||
{
|
||||
_isReading = false; // Stop thread loop
|
||||
|
||||
if (_recvThread != null && _recvThread.IsAlive)
|
||||
{
|
||||
if (!_recvThread.Join(500)) // Wait for thread to finish
|
||||
{
|
||||
// _recvThread.Abort(); // Avoid Abort if possible
|
||||
}
|
||||
}
|
||||
|
||||
if (_device != null && _device.IsOpen)
|
||||
{
|
||||
_device.DiscardInBuffer();
|
||||
_device.DiscardOutBuffer();
|
||||
_device.Close(); //dispose에서는 포트를 직접 클리어하지 않게 해뒀다.
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
protected Boolean RaiseRecvData()
|
||||
{
|
||||
return RaiseRecvData(LastReceiveBuffer.ToArray(), false);
|
||||
}
|
||||
/// <summary>
|
||||
/// 수신받은 메세지를 발생 시킵니다
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Boolean RaiseRecvData(byte[] Data, bool udpatelastbuffer)
|
||||
{
|
||||
//181206 - 최종수신 메세지 기록
|
||||
lastRecvTime = DateTime.Now;
|
||||
if (udpatelastbuffer && Data != null)
|
||||
{
|
||||
if (LastReceiveBuffer == null || LastReceiveBuffer.Length != Data.Length)
|
||||
{
|
||||
LastReceiveBuffer = new byte[Data.Length];
|
||||
Array.Copy(Data, LastReceiveBuffer, Data.Length);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// UI update might need Invoke if this event handler updates UI directly,
|
||||
// but usually the subscriber handles Invoke.
|
||||
// Since we are running on a background thread now, subscribers must be aware.
|
||||
Message?.Invoke(this, new MessageEventArgs(Data, true)); //recvmessage
|
||||
if (ProcessRecvData(Data) == false)
|
||||
{
|
||||
//Message?.Invoke(this, new MessageEventArgs(Data, true)); //recvmessage
|
||||
Message?.Invoke(this, new MessageEventArgs(this.ErrorMessage, true)); //errormessage
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.ErrorMessage = ex.Message;
|
||||
this.Message?.Invoke(this, new MessageEventArgs(ex.Message, true));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 수신받은 자료를 처리한다
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public abstract bool ProcessRecvData(byte[] data);
|
||||
|
||||
#region "Internal Events"
|
||||
|
||||
void barcode_ErrorReceived(object sender, System.IO.Ports.SerialErrorReceivedEventArgs e)
|
||||
{
|
||||
Message?.Invoke(this, new MessageEventArgs(e.ToString(), true));
|
||||
}
|
||||
|
||||
byte[] buffer = new byte[] { };
|
||||
|
||||
// Replaced with ReadPort Loop
|
||||
/*
|
||||
void barcode_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
int ReadCount = _device.BytesToRead;
|
||||
|
||||
buffer = new byte[ReadCount];
|
||||
_device.Read(buffer, 0, buffer.Length);
|
||||
|
||||
System.Text.StringBuilder LogMsg = new StringBuilder();
|
||||
|
||||
byte[] remainBuffer;
|
||||
Repeat:
|
||||
if (CustomParser(buffer, out remainBuffer))
|
||||
{
|
||||
//분석완료이므로 받은 데이터를 버퍼에 기록한다
|
||||
if (LastReceiveBuffer == null || (LastReceiveBuffer.Length != tempBuffer.Count))
|
||||
Array.Resize(ref LastReceiveBuffer, tempBuffer.Count);
|
||||
Array.Copy(tempBuffer.ToArray(), LastReceiveBuffer, tempBuffer.Count);
|
||||
tempBuffer.Clear();
|
||||
|
||||
//수신메세지발생
|
||||
RaiseRecvData();
|
||||
if (remainBuffer != null && remainBuffer.Length > 0)
|
||||
{
|
||||
//버퍼를 변경해서 다시 전송을 해준다.
|
||||
Array.Resize(ref buffer, remainBuffer.Length);
|
||||
Array.Copy(remainBuffer, buffer, remainBuffer.Length);
|
||||
goto Repeat; //남은 버퍼가 있다면 진행을 해준다.
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//if (IsOpen)
|
||||
//{
|
||||
// //_device.DiscardInBuffer();
|
||||
// //_device.DiscardOutBuffer();
|
||||
//}
|
||||
ErrorMessage = ex.Message;
|
||||
this.Message?.Invoke(this, new MessageEventArgs(ex.Message, true));
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
void ReadPort()
|
||||
{
|
||||
while (_isReading)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_device == null || !_device.IsOpen)
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
continue;
|
||||
}
|
||||
|
||||
int readCount = _device.BytesToRead;
|
||||
if (readCount > 0)
|
||||
{
|
||||
byte[] buffer = new byte[readCount];
|
||||
_device.Read(buffer, 0, buffer.Length);
|
||||
|
||||
byte[] remainBuffer;
|
||||
Repeat:
|
||||
if (CustomParser(buffer, out remainBuffer))
|
||||
{
|
||||
//분석완료이므로 받은 데이터를 버퍼에 기록한다
|
||||
if (LastReceiveBuffer == null || (LastReceiveBuffer.Length != tempBuffer.Count))
|
||||
Array.Resize(ref LastReceiveBuffer, tempBuffer.Count);
|
||||
Array.Copy(tempBuffer.ToArray(), LastReceiveBuffer, tempBuffer.Count);
|
||||
tempBuffer.Clear();
|
||||
|
||||
//수신메세지발생
|
||||
RaiseRecvData();
|
||||
if (remainBuffer != null && remainBuffer.Length > 0)
|
||||
{
|
||||
//버퍼를 변경해서 다시 전송을 해준다.
|
||||
buffer = new byte[remainBuffer.Length]; // Reallocate buffer for remaining data
|
||||
Array.Copy(remainBuffer, buffer, remainBuffer.Length);
|
||||
goto Repeat; //남은 버퍼가 있다면 진행을 해준다.
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.Sleep(20); // Data 없음, 대기
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Thread 상에서 Exception 발생 시 로그 남기고 계속 진행 여부 결정
|
||||
// 여기서는 에러 메시지 발생시키고 Sleep
|
||||
ErrorMessage = ex.Message;
|
||||
this.Message?.Invoke(this, new MessageEventArgs(ex.Message, true));
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region "External Events"
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 오류 및 기타 일반 메세지
|
||||
/// </summary>
|
||||
public event EventHandler<MessageEventArgs> Message;
|
||||
|
||||
#endregion
|
||||
|
||||
#region "Event Args"
|
||||
|
||||
/// <summary>
|
||||
/// 데이터를 수신할떄 사용함(RAW 포함)
|
||||
/// </summary>
|
||||
public class ReceiveDataEventArgs : EventArgs
|
||||
{
|
||||
private byte[] _buffer = null;
|
||||
|
||||
/// <summary>
|
||||
/// 바이트배열의 버퍼값
|
||||
/// </summary>
|
||||
public byte[] Value { get { return _buffer; } }
|
||||
|
||||
/// <summary>
|
||||
/// 버퍼(바이트배열)의 데이터를 문자로 반환합니다.
|
||||
/// </summary>
|
||||
public string StrValue
|
||||
{
|
||||
get
|
||||
{
|
||||
//return string.Empty;
|
||||
|
||||
if (_buffer == null || _buffer.Length < 1) return string.Empty;
|
||||
else return System.Text.Encoding.Default.GetString(_buffer);
|
||||
}
|
||||
}
|
||||
public ReceiveDataEventArgs(byte[] buffer)
|
||||
{
|
||||
_buffer = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 메세지를 강제 발생
|
||||
/// </summary>
|
||||
/// <param name="mt"></param>
|
||||
/// <param name="message"></param>
|
||||
protected virtual void RaiseMessage(MessageType mt, string message)
|
||||
{
|
||||
this.Message?.Invoke(this, new MessageEventArgs(mt, message));
|
||||
}
|
||||
public enum MessageType
|
||||
{
|
||||
Normal,
|
||||
Error,
|
||||
Send,
|
||||
Recv,
|
||||
}
|
||||
|
||||
public class MessageEventArgs : EventArgs
|
||||
{
|
||||
public MessageType MsgType { get; set; }
|
||||
private string _message = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Recv,Send,Normal,Error 모두 지원
|
||||
/// </summary>
|
||||
public string Message { get { return _message; } }
|
||||
|
||||
private byte[] _data = null;
|
||||
|
||||
/// <summary>
|
||||
/// Recv,Send에서만 값이 존재 합니다
|
||||
/// </summary>
|
||||
public byte[] Data { get { return _data; } }
|
||||
public MessageEventArgs(string Message, bool isError = false)
|
||||
{
|
||||
if (isError) MsgType = MessageType.Error;
|
||||
else MsgType = MessageType.Normal;
|
||||
_message = Message;
|
||||
}
|
||||
public MessageEventArgs(MessageType msgtype, string Message)
|
||||
{
|
||||
MsgType = msgtype;
|
||||
_message = Message;
|
||||
_data = System.Text.Encoding.Default.GetBytes(Message);
|
||||
}
|
||||
|
||||
public MessageEventArgs(byte[] buffer, bool isRecv = true)
|
||||
{
|
||||
if (isRecv) MsgType = MessageType.Recv;
|
||||
else MsgType = MessageType.Send;
|
||||
_data = new byte[buffer.Length];
|
||||
Array.Copy(buffer, _data, Data.Length);
|
||||
_message = System.Text.Encoding.Default.GetString(_data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
protected abstract bool CustomParser(byte[] buf, out byte[] remainBuffer);
|
||||
|
||||
/// <summary>
|
||||
/// 포트가 열려있거나 데이터 수신시간이 없는경우 false를 반환합니다
|
||||
/// </summary>
|
||||
public Boolean IsValid
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsOpen == false) return false;
|
||||
if (lastRecvTime.Year == 1982) return false;
|
||||
var ts = DateTime.Now - lastRecvTime;
|
||||
if (ts.TotalSeconds > (this.ScanInterval * 2.5)) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
protected bool WriteData(string cmd)
|
||||
{
|
||||
return WriteData(System.Text.Encoding.Default.GetBytes(cmd));
|
||||
}
|
||||
/// <summary>
|
||||
/// 포트에 쓰기(barcode_DataReceived 이벤트로 메세지수신)
|
||||
/// </summary>
|
||||
protected Boolean WriteData(byte[] data)
|
||||
{
|
||||
Boolean bRet = false;
|
||||
|
||||
//171205 : 타임아웃시간추가
|
||||
if (!_mre.WaitOne(WaitTimeout))
|
||||
{
|
||||
ErrorMessage = $"WriteData:MRE:WaitOne:TimeOut {WaitTimeout}ms";
|
||||
this.Message?.Invoke(this, new MessageEventArgs(ErrorMessage, true));
|
||||
return false;
|
||||
}
|
||||
|
||||
_mre.Reset();
|
||||
|
||||
//Array.Resize(ref data, data.Length + 2);
|
||||
|
||||
try
|
||||
{
|
||||
lastSendTime = DateTime.Now;
|
||||
if (lastSendBuffer == null) lastSendBuffer = new byte[data.Length]; //171113
|
||||
else Array.Resize(ref lastSendBuffer, data.Length);
|
||||
Array.Copy(data, lastSendBuffer, data.Length);
|
||||
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
_device.Write(data, i, 1);
|
||||
|
||||
//_device.Write(data, 0, data.Length);
|
||||
|
||||
//171113
|
||||
this.Message?.Invoke(this, new MessageEventArgs(data, false));
|
||||
|
||||
bRet = true;
|
||||
WriteError = 0;
|
||||
WriteErrorMessage = string.Empty;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// this.isinit = false;
|
||||
this.Message?.Invoke(this, new MessageEventArgs(ex.Message, true));
|
||||
bRet = false;
|
||||
WriteError += 1; //연속쓰기오류횟수
|
||||
WriteErrorMessage = ex.Message;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_mre.Set();
|
||||
}
|
||||
return bRet;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
36
HMI/SubProject/AGV/Properties/AssemblyInfo.cs
Normal file
36
HMI/SubProject/AGV/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해
|
||||
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
|
||||
// 이러한 특성 값을 변경하세요.
|
||||
[assembly: AssemblyTitle("BMS Commnunication Module")]
|
||||
[assembly: AssemblyDescription("BMS Commnunication Module")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("ATK4")]
|
||||
[assembly: AssemblyProduct("BMS Commnunication Module")]
|
||||
[assembly: AssemblyCopyright("Copyright ©ATK4 2020")]
|
||||
[assembly: AssemblyTrademark("ATK4")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에
|
||||
// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면
|
||||
// 해당 형식에 대해 ComVisible 특성을 true로 설정하세요.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다.
|
||||
[assembly: Guid("7a94c30c-6772-4f71-bf9c-111071a1bc70")]
|
||||
|
||||
// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다.
|
||||
//
|
||||
// 주 버전
|
||||
// 부 버전
|
||||
// 빌드 번호
|
||||
// 수정 버전
|
||||
//
|
||||
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를
|
||||
// 기본값으로 할 수 있습니다.
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("20.03.09.0000")]
|
||||
[assembly: AssemblyFileVersion("20.03.09.0000")]
|
||||
86
HMI/SubProject/AGV/Structure/AgvData.cs
Normal file
86
HMI/SubProject/AGV/Structure/AgvData.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
|
||||
namespace arDev
|
||||
{
|
||||
public partial class Narumi
|
||||
{
|
||||
|
||||
public class AgvData
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// S: Straight
|
||||
/// L: Left
|
||||
/// R: Right
|
||||
/// </summary>
|
||||
public char Sts { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// H : High
|
||||
/// M : Middle
|
||||
/// L : Low
|
||||
/// S : Mark Stop
|
||||
/// </summary>
|
||||
public char Speed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// F : Front
|
||||
/// B : Back
|
||||
/// </summary>
|
||||
public char Direction { get; set; }
|
||||
|
||||
public int guidesensor { get; set; }
|
||||
|
||||
|
||||
public string TagString { get; set; } = string.Empty;
|
||||
public ushort TagNo { get; set; } = 0;
|
||||
public string CallString { get; set; } = string.Empty;
|
||||
public int CallNo { get; set; } = -1;
|
||||
public string CCAString { get; set; } = string.Empty;
|
||||
public int CCANo { get; set; } = -1;
|
||||
|
||||
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
//모든사태값을 탭으로 구분하여 문자를 생성한다
|
||||
var sb = new System.Text.StringBuilder();
|
||||
|
||||
sb.AppendLine($"[Sts] : {Sts}");
|
||||
sb.AppendLine($"[Speed] : {Speed}");
|
||||
sb.AppendLine($"[Direction] : {Direction}");
|
||||
sb.AppendLine($"[guidesensor] : {guidesensor}");
|
||||
|
||||
sb.AppendLine($"[TagNo] : {TagNo}");
|
||||
sb.AppendLine($"[CallNo] : {CallNo}");
|
||||
sb.AppendLine($"[CCANo] : {CCANo}");
|
||||
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public string ToRtfString()
|
||||
{
|
||||
var sb = new System.Text.StringBuilder();
|
||||
sb.AppendLine(@"{\rtf1\ansi\deff0");
|
||||
sb.AppendLine(@"{\colortbl ;\red0\green0\blue255;}"); // Color 1 = Blue
|
||||
|
||||
sb.AppendLine($"[Sts] : {Sts}" + @"\line");
|
||||
sb.AppendLine($"[Speed] : {Speed}" + @"\line");
|
||||
sb.AppendLine($"[Direction] : {Direction}" + @"\line");
|
||||
sb.AppendLine($"[guidesensor] : {guidesensor}" + @"\line");
|
||||
sb.AppendLine($"[TagNo] : {TagNo}" + @"\line");
|
||||
sb.AppendLine($"[CallNo] : {CallNo}" + @"\line");
|
||||
sb.AppendLine($"[CCANo] : {CCANo}" + @"\line");
|
||||
|
||||
sb.AppendLine("}");
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
142
HMI/SubProject/AGV/Structure/ErrorFlag.cs
Normal file
142
HMI/SubProject/AGV/Structure/ErrorFlag.cs
Normal file
@@ -0,0 +1,142 @@
|
||||
using System;
|
||||
|
||||
namespace arDev
|
||||
{
|
||||
public partial class Narumi
|
||||
{
|
||||
|
||||
public class ErrorFlag
|
||||
{
|
||||
private COMM.Flag _value { get; set; } = new COMM.Flag(16);
|
||||
public void SetValue(Int16 value) { this._value.writeValue(value); }
|
||||
public UInt16 Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return (UInt16)_value.Value;
|
||||
}
|
||||
}
|
||||
public enum eflag
|
||||
{
|
||||
Emergency = 0,
|
||||
Overcurrent,
|
||||
Charger_run_error,
|
||||
Charger_pos_error,
|
||||
line_out_error = 4,
|
||||
|
||||
/// <summary>
|
||||
/// 기동시 자석 감지 에러
|
||||
/// </summary>
|
||||
runerror_by_no_magent_line=5,
|
||||
/// <summary>
|
||||
/// 호출제어기 통신 오류
|
||||
/// </summary>
|
||||
controller_comm_error =6,
|
||||
|
||||
/// <summary>
|
||||
/// 배터리 저전압
|
||||
/// </summary>
|
||||
battery_low_voltage=7,
|
||||
|
||||
spare08=8,
|
||||
|
||||
lift_timeout=9,
|
||||
lift_driver_overcurrent=10,
|
||||
lift_driver_emergency = 11,
|
||||
|
||||
/// <summary>
|
||||
/// 도착경보기 통신 오류
|
||||
/// </summary>
|
||||
arrive_ctl_comm_error,
|
||||
|
||||
/// <summary>
|
||||
/// 자동문제어기 통신 오류
|
||||
/// </summary>
|
||||
door_ctl_comm_error,
|
||||
|
||||
/// <summary>
|
||||
/// 자동충전기 통신 오류
|
||||
/// </summary>
|
||||
charger_comm_error,
|
||||
|
||||
/// <summary>
|
||||
/// 교차로 제어기 통신 오류
|
||||
/// </summary>
|
||||
cross_ctrl_comm_error,
|
||||
}
|
||||
|
||||
public bool GetValue(eflag idx)
|
||||
{
|
||||
return _value.Get((int)idx);
|
||||
}
|
||||
public bool GetChanged(eflag idx)
|
||||
{
|
||||
return _value.GetChanged((int)idx);
|
||||
}
|
||||
|
||||
public bool Emergency { get { return GetValue(eflag.Emergency); } }
|
||||
public bool Overcurrent { get { return GetValue(eflag.Overcurrent); } }
|
||||
public bool Charger_run_error { get { return GetValue(eflag.Charger_run_error); } }
|
||||
public bool Charger_pos_error { get { return GetValue(eflag.Charger_pos_error); } }
|
||||
public bool line_out_error { get { return GetValue(eflag.line_out_error); } }
|
||||
public bool runerror_by_no_magent_line { get { return GetValue(eflag.runerror_by_no_magent_line); } }
|
||||
public bool controller_comm_error { get { return GetValue(eflag.controller_comm_error); } }
|
||||
public bool arrive_ctl_comm_error { get { return GetValue(eflag.arrive_ctl_comm_error); } }
|
||||
public bool door_ctl_comm_error { get { return GetValue(eflag.door_ctl_comm_error); } }
|
||||
public bool charger_comm_error { get { return GetValue(eflag.charger_comm_error); } }
|
||||
public bool cross_ctrl_comm_error { get { return GetValue(eflag.cross_ctrl_comm_error); } }
|
||||
public override string ToString()
|
||||
{
|
||||
//모든사태값을 탭으로 구분하여 문자를 생성한다
|
||||
var sb = new System.Text.StringBuilder();
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
var def = Enum.IsDefined(typeof(eflag), i);
|
||||
if (def)
|
||||
{
|
||||
var flag = (eflag)i;
|
||||
var value = _value.Get(i);
|
||||
sb.AppendLine($"[{i:00}][{flag}] : {value}");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public string ToRtfString()
|
||||
{
|
||||
var sb = new System.Text.StringBuilder();
|
||||
sb.AppendLine(@"{\rtf1\ansi\deff0");
|
||||
sb.AppendLine(@"{\colortbl ;\red0\green0\blue255;}"); // Color 1 = Blue
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
var def = Enum.IsDefined(typeof(eflag), i);
|
||||
if (def)
|
||||
{
|
||||
var flag = (eflag)i;
|
||||
var value = _value.Get(i);
|
||||
string line = $"[{i:00}][{flag}] : {value}";
|
||||
|
||||
// : true가 포함된 줄은 파란색
|
||||
if (value == true)
|
||||
{
|
||||
sb.AppendLine(@"\cf1 " + line + @"\cf0\line");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine(line + @"\line");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sb.AppendLine("}");
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
187
HMI/SubProject/AGV/Structure/Signals.cs
Normal file
187
HMI/SubProject/AGV/Structure/Signals.cs
Normal file
@@ -0,0 +1,187 @@
|
||||
using System;
|
||||
|
||||
namespace arDev
|
||||
{
|
||||
public partial class Narumi
|
||||
{
|
||||
public enum eSignal1
|
||||
{
|
||||
front_gate_out = 0,
|
||||
rear_gte_out,
|
||||
mark_sensor_1,
|
||||
mark_sensor_2,
|
||||
lift_down_sensor,
|
||||
lift_up_sensor,
|
||||
magnet_relay,
|
||||
charger_align_sensor,
|
||||
}
|
||||
public enum eSignal2
|
||||
{
|
||||
cart_detect1 = 0,
|
||||
cart_detect2,
|
||||
}
|
||||
|
||||
public class Signal1
|
||||
{
|
||||
private COMM.Flag _value { get; set; } = new COMM.Flag(8);
|
||||
public void SetValue(Int16 value) { this._value.writeValue(value); }
|
||||
public UInt16 Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return (UInt16)_value.Value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public bool GetValue(eSignal1 idx)
|
||||
{
|
||||
return _value.Get((int)idx);
|
||||
}
|
||||
public bool GetChanged(eSignal1 idx)
|
||||
{
|
||||
return _value.GetChanged((int)idx);
|
||||
}
|
||||
|
||||
public Boolean front_gate_out { get { return GetValue(eSignal1.front_gate_out); } }
|
||||
public Boolean rear_sensor_out { get { return GetValue(eSignal1.rear_gte_out); } }
|
||||
public Boolean mark_sensor_1 { get { return GetValue(eSignal1.mark_sensor_1); } }
|
||||
public Boolean mark_sensor_2 { get { return GetValue(eSignal1.mark_sensor_2); } }
|
||||
public Boolean mark_sensor { get { return mark_sensor_1 || mark_sensor_2; } }
|
||||
public Boolean charger_align_sensor { get { return GetValue(eSignal1.charger_align_sensor); } }
|
||||
public Boolean lift_up { get { return GetValue(eSignal1.lift_up_sensor); } }
|
||||
public Boolean lift_down { get { return GetValue(eSignal1.lift_down_sensor); } }
|
||||
public Boolean magnet_on { get { return GetValue(eSignal1.magnet_relay); } }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
//모든사태값을 탭으로 구분하여 문자를 생성한다
|
||||
var sb = new System.Text.StringBuilder();
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
var def = Enum.IsDefined(typeof(eSignal1), i);
|
||||
if (def)
|
||||
{
|
||||
var flag = (eSignal1)i;
|
||||
var value = _value.Get(i);
|
||||
sb.AppendLine($"[{i:00}][{flag}] : {value}");
|
||||
}
|
||||
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public string ToRtfString()
|
||||
{
|
||||
var sb = new System.Text.StringBuilder();
|
||||
sb.AppendLine(@"{\rtf1\ansi\deff0");
|
||||
sb.AppendLine(@"{\colortbl ;\red0\green0\blue255;}"); // Color 1 = Blue
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
var def = Enum.IsDefined(typeof(eSignal1), i);
|
||||
if (def)
|
||||
{
|
||||
var flag = (eSignal1)i;
|
||||
var value = _value.Get(i);
|
||||
string line = $"[{i:00}][{flag}] : {value}";
|
||||
|
||||
// : true가 포함된 줄은 파란색
|
||||
if (value == true)
|
||||
{
|
||||
sb.AppendLine(@"\cf1 " + line + @"\cf0\line");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine(line + @"\line");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sb.AppendLine("}");
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class Signal2
|
||||
{
|
||||
private COMM.Flag _value { get; set; } = new COMM.Flag(8);
|
||||
public void SetValue(Int16 value) { this._value.writeValue(value); }
|
||||
public UInt16 Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return (UInt16)_value.Value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public bool GetValue(eSignal2 idx)
|
||||
{
|
||||
return _value.Get((int)idx);
|
||||
}
|
||||
public bool GetChanged(eSignal2 idx)
|
||||
{
|
||||
return _value.GetChanged((int)idx);
|
||||
}
|
||||
|
||||
|
||||
public Boolean cart_detect1 { get { return GetValue(eSignal2.cart_detect1); } }
|
||||
public Boolean cart_detect2 { get { return GetValue(eSignal2.cart_detect2); } }
|
||||
public override string ToString()
|
||||
{
|
||||
//모든사태값을 탭으로 구분하여 문자를 생성한다
|
||||
var sb = new System.Text.StringBuilder();
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
var def = Enum.IsDefined(typeof(eSignal2), i);
|
||||
if(def)
|
||||
{
|
||||
var flag = (eSignal2)i;
|
||||
var value = _value.Get(i);
|
||||
sb.AppendLine($"[{i:00}][{flag}] : {value}");
|
||||
}
|
||||
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public string ToRtfString()
|
||||
{
|
||||
var sb = new System.Text.StringBuilder();
|
||||
sb.AppendLine(@"{\rtf1\ansi\deff0");
|
||||
sb.AppendLine(@"{\colortbl ;\red0\green0\blue255;}"); // Color 1 = Blue
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
var def = Enum.IsDefined(typeof(eSignal2), i);
|
||||
if (def)
|
||||
{
|
||||
var flag = (eSignal2)i;
|
||||
var value = _value.Get(i);
|
||||
string line = $"[{i:00}][{flag}] : {value}";
|
||||
|
||||
// : true가 포함된 줄은 파란색
|
||||
if (value == true)
|
||||
{
|
||||
sb.AppendLine(@"\cf1 " + line + @"\cf0\line");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine(line + @"\line");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sb.AppendLine("}");
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
108
HMI/SubProject/AGV/Structure/SystemFlag0.cs
Normal file
108
HMI/SubProject/AGV/Structure/SystemFlag0.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
using System;
|
||||
|
||||
namespace arDev
|
||||
{
|
||||
public partial class Narumi
|
||||
{
|
||||
|
||||
public class SystemFlag0
|
||||
{
|
||||
private COMM.Flag _value { get; set; } = new COMM.Flag(16);
|
||||
public void SetValue(Int16 value) { this._value.writeValue(value); }
|
||||
public UInt16 Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return (UInt16)_value.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public enum eflag
|
||||
{
|
||||
Memory_RW_State = 5,
|
||||
EXT_IO_Conn_State,
|
||||
RFID_Conn_State,
|
||||
M5E_Module_Run_State = 8,
|
||||
Front_Ultrasonic_Conn_State,
|
||||
Front_Untrasonic_Sensor_State,
|
||||
Side_Ultrasonic_Conn_State,
|
||||
Side_Ultrasonic_Sensor_State = 12,
|
||||
Front_Guide_Sensor_State,
|
||||
Rear_Guide_Sensor_State,
|
||||
Battery_Level_Check
|
||||
}
|
||||
|
||||
public bool GetValue(eflag idx)
|
||||
{
|
||||
return _value.Get((int)idx);
|
||||
}
|
||||
public bool GetChanged(eflag idx)
|
||||
{
|
||||
return _value.GetChanged((int)idx);
|
||||
}
|
||||
public bool Memory_RW_State { get { return GetValue(eflag.Memory_RW_State); } }
|
||||
public bool EXT_IO_Conn_State { get { return GetValue(eflag.EXT_IO_Conn_State); } }
|
||||
public bool RFID_Conn_State { get { return GetValue(eflag.RFID_Conn_State); } }
|
||||
public bool M5E_Module_Run_State { get { return GetValue(eflag.M5E_Module_Run_State); } }
|
||||
public bool Front_Ultrasonic_Conn_State { get { return GetValue(eflag.Front_Ultrasonic_Conn_State); } }
|
||||
public bool Front_Untrasonic_Sensor_State { get { return GetValue(eflag.Front_Untrasonic_Sensor_State); } }
|
||||
public bool Side_Ultrasonic_Conn_State { get { return GetValue(eflag.Side_Ultrasonic_Conn_State); } }
|
||||
public bool Side_Ultrasonic_Sensor_State { get { return GetValue(eflag.Side_Ultrasonic_Sensor_State); } }
|
||||
public bool Front_Guide_Sensor_State { get { return GetValue(eflag.Front_Guide_Sensor_State); } }
|
||||
public bool Rear_Guide_Sensor_State { get { return GetValue(eflag.Rear_Guide_Sensor_State); } }
|
||||
public bool Battery_Level_Check { get { return GetValue(eflag.Battery_Level_Check); } }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
//모든사태값을 탭으로 구분하여 문자를 생성한다
|
||||
var sb = new System.Text.StringBuilder();
|
||||
for(int i = 0; i < 16; i++)
|
||||
{
|
||||
var def = Enum.IsDefined(typeof(eflag), i);
|
||||
if (def)
|
||||
{
|
||||
var flag = (eflag)i;
|
||||
var value = _value.Get(i);
|
||||
sb.AppendLine($"[{i:00}][{flag}] : {value}");
|
||||
}
|
||||
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public string ToRtfString()
|
||||
{
|
||||
var sb = new System.Text.StringBuilder();
|
||||
sb.AppendLine(@"{\rtf1\ansi\deff0");
|
||||
sb.AppendLine(@"{\colortbl ;\red0\green0\blue255;}"); // Color 1 = Blue
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
var def = Enum.IsDefined(typeof(eflag), i);
|
||||
if (def)
|
||||
{
|
||||
var flag = (eflag)i;
|
||||
var value = _value.Get(i);
|
||||
string line = $"[{i:00}][{flag}] : {value}";
|
||||
|
||||
// : true가 포함된 줄은 파란색
|
||||
if (value == true)
|
||||
{
|
||||
sb.AppendLine(@"\cf1 " + line + @"\cf0\line");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine(line + @"\line");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sb.AppendLine("}");
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
128
HMI/SubProject/AGV/Structure/SystemFlag1.cs
Normal file
128
HMI/SubProject/AGV/Structure/SystemFlag1.cs
Normal file
@@ -0,0 +1,128 @@
|
||||
using System;
|
||||
|
||||
namespace arDev
|
||||
{
|
||||
public partial class Narumi
|
||||
{
|
||||
|
||||
public class SystemFlag1
|
||||
{
|
||||
private COMM.Flag _value { get; set; } = new COMM.Flag(16);
|
||||
public void SetValue(Int16 value) { this._value.writeValue(value); }
|
||||
|
||||
public UInt16 Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return (UInt16)_value.Value;
|
||||
}
|
||||
}
|
||||
public enum eflag
|
||||
{
|
||||
Side_Detect_Ignore = 3,
|
||||
Melody_check,
|
||||
Mark2_check,
|
||||
Mark1_check,
|
||||
gateout_check,
|
||||
Battery_charging = 8,
|
||||
re_Start,
|
||||
|
||||
/// <summary>
|
||||
/// 전방 감지 무시
|
||||
/// </summary>
|
||||
front_detect_ignore,
|
||||
|
||||
/// <summary>
|
||||
/// 전방장애물감지상태
|
||||
/// </summary>
|
||||
front_detect_check,
|
||||
|
||||
/// <summary>
|
||||
/// 전방감지 후 정지 상태
|
||||
/// </summary>
|
||||
stop_by_front_detect = 12,
|
||||
/// <summary>
|
||||
/// 교차로 진입 후 정지 상태
|
||||
/// </summary>
|
||||
stop_by_cross_in,
|
||||
agv_stop,
|
||||
agv_run
|
||||
}
|
||||
|
||||
public bool GetValue(eflag idx)
|
||||
{
|
||||
return _value.Get((int)idx);
|
||||
}
|
||||
public bool GetChanged(eflag idx)
|
||||
{
|
||||
return _value.GetChanged((int)idx);
|
||||
}
|
||||
public bool Side_Detect_Ignore { get { return GetValue(eflag.Side_Detect_Ignore); } }
|
||||
public bool Melody_check { get { return GetValue(eflag.Melody_check); } }
|
||||
public bool Mark2_check { get { return GetValue(eflag.Mark2_check); } }
|
||||
public bool Mark1_check { get { return GetValue(eflag.Mark1_check); } }
|
||||
public bool gateout_check { get { return GetValue(eflag.gateout_check); } }
|
||||
public bool Battery_charging { get { return GetValue(eflag.Battery_charging); } }
|
||||
public bool re_Start { get { return GetValue(eflag.re_Start); } }
|
||||
public bool front_detect_ignore { get { return GetValue(eflag.front_detect_ignore); } }
|
||||
public bool front_detect_check { get { return GetValue(eflag.front_detect_check); } }
|
||||
public bool stop_by_front_detect { get { return GetValue(eflag.stop_by_front_detect); } }
|
||||
public bool stop_by_cross_in { get { return GetValue(eflag.stop_by_cross_in); } }
|
||||
public bool agv_stop { get { return GetValue(eflag.agv_stop); } }
|
||||
public bool agv_run { get { return GetValue(eflag.agv_run); } }
|
||||
public bool agv_run_manual { get; set; }
|
||||
public override string ToString()
|
||||
{
|
||||
//모든사태값을 탭으로 구분하여 문자를 생성한다
|
||||
var sb = new System.Text.StringBuilder();
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
var def = Enum.IsDefined(typeof(eflag), i);
|
||||
if (def)
|
||||
{
|
||||
var flag = (eflag)i;
|
||||
var value = _value.Get(i);
|
||||
sb.AppendLine($"[{i:00}][{flag}] : {value}");
|
||||
}
|
||||
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public string ToRtfString()
|
||||
{
|
||||
var sb = new System.Text.StringBuilder();
|
||||
sb.AppendLine(@"{\rtf1\ansi\deff0");
|
||||
sb.AppendLine(@"{\colortbl ;\red0\green0\blue255;}"); // Color 1 = Blue
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
var def = Enum.IsDefined(typeof(eflag), i);
|
||||
if (def)
|
||||
{
|
||||
var flag = (eflag)i;
|
||||
var value = _value.Get(i);
|
||||
string line = $"[{i:00}][{flag}] : {value}";
|
||||
|
||||
// : true가 포함된 줄은 파란색
|
||||
if (value == true)
|
||||
{
|
||||
sb.AppendLine(@"\cf1 " + line + @"\cf0\line");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine(line + @"\line");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sb.AppendLine("}");
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
24
HMI/SubProject/AGVControl/AGVControl.sln
Normal file
24
HMI/SubProject/AGVControl/AGVControl.sln
Normal file
@@ -0,0 +1,24 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.5.2.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "agvControl", "agvControl.csproj", "{EB23DC0D-9A07-407C-762D-DF1CC8B3D822}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{EB23DC0D-9A07-407C-762D-DF1CC8B3D822}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EB23DC0D-9A07-407C-762D-DF1CC8B3D822}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EB23DC0D-9A07-407C-762D-DF1CC8B3D822}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EB23DC0D-9A07-407C-762D-DF1CC8B3D822}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {586342A4-FEA6-4584-82F4-39BA06630ABB}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
37
HMI/SubProject/AGVControl/BatteryLevelGauge.Designer.cs
generated
Normal file
37
HMI/SubProject/AGVControl/BatteryLevelGauge.Designer.cs
generated
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
namespace AGVControl
|
||||
{
|
||||
partial class BatteryLevelGauge
|
||||
{
|
||||
/// <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 구성 요소 디자이너에서 생성한 코드
|
||||
|
||||
/// <summary>
|
||||
/// 디자이너 지원에 필요한 메서드입니다.
|
||||
/// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
93
HMI/SubProject/AGVControl/BatteryLevelGauge.cs
Normal file
93
HMI/SubProject/AGVControl/BatteryLevelGauge.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace AGVControl
|
||||
{
|
||||
public partial class BatteryLevelGauge : Control
|
||||
{
|
||||
float _vlevel = 50;
|
||||
public float VLevel { get { return _vlevel; } set { _vlevel = value; } }
|
||||
public float Volt { get; set; } = 0;
|
||||
public String sign { get; set; } = "%";
|
||||
public float CurA { get; set; } = 0;
|
||||
public float MaxA { get; set; } = 0;
|
||||
|
||||
bool isopen = false;
|
||||
public Boolean IsOpen { get { return isopen; } set { isopen = value; this.Invalidate(); } }
|
||||
|
||||
public Color BorderColor { get; set; } = Color.DimGray;
|
||||
|
||||
public BatteryLevelGauge()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// Set Optimized Double Buffer to reduce flickering
|
||||
this.SetStyle(ControlStyles.UserPaint, true);
|
||||
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
||||
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
|
||||
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
|
||||
|
||||
// Redraw when resized
|
||||
this.SetStyle(ControlStyles.ResizeRedraw, true);
|
||||
|
||||
this.Resize += arLabel_Resize;
|
||||
}
|
||||
|
||||
|
||||
protected override void OnPaint(PaintEventArgs pe)
|
||||
{
|
||||
pe.Graphics.InterpolationMode = InterpolationMode.High;
|
||||
pe.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
pe.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
|
||||
//base.OnPaint(pe);
|
||||
pe.Graphics.FillRectangle(new SolidBrush(BackColor), DisplayRectangle);
|
||||
|
||||
var r = new RectangleF(this.DisplayRectangle.Left + Padding.Left,
|
||||
this.DisplayRectangle.Top + Padding.Top,
|
||||
this.DisplayRectangle.Width - Padding.Left - Padding.Right,
|
||||
this.DisplayRectangle.Height - Padding.Top - Padding.Bottom);
|
||||
|
||||
pe.Graphics.FillRectangle(new SolidBrush(this.BackColor), r);
|
||||
|
||||
|
||||
var w = r.Width * (this.VLevel / 100f);
|
||||
var lr = new RectangleF(r.Left, r.Top, w, r.Height);
|
||||
|
||||
Color bColor = Color.Red;
|
||||
if (VLevel > 80) bColor = Color.YellowGreen;
|
||||
else if (VLevel > 60) bColor = Color.Yellow;
|
||||
else if (VLevel > 40) bColor = Color.Orange;
|
||||
else if (VLevel > 20) bColor = Color.Tomato;
|
||||
else bColor = Color.Red;
|
||||
pe.Graphics.FillRectangle(new SolidBrush(bColor), lr);
|
||||
|
||||
Color textcolor = this.ForeColor;
|
||||
if (IsOpen == false) textcolor = Color.Black;
|
||||
var smg = IsOpen ? $"{ this.VLevel:N0}{ this.sign}" : "연결안됨";
|
||||
|
||||
pe.Graphics.DrawString(smg, this.Font, new SolidBrush(textcolor), r,
|
||||
new StringFormat
|
||||
{
|
||||
Alignment = StringAlignment.Center,
|
||||
LineAlignment = StringAlignment.Center
|
||||
});
|
||||
|
||||
pe.Graphics.DrawRectangle(Pens.Black, r.Left, r.Top, r.Width, r.Height);
|
||||
|
||||
|
||||
}
|
||||
void arLabel_Resize(object sender, EventArgs e)
|
||||
{
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
103
HMI/SubProject/AGVControl/Dialog/fMapDesign.Designer.cs
generated
Normal file
103
HMI/SubProject/AGVControl/Dialog/fMapDesign.Designer.cs
generated
Normal 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;
|
||||
}
|
||||
}
|
||||
48
HMI/SubProject/AGVControl/Dialog/fMapDesign.cs
Normal file
48
HMI/SubProject/AGVControl/Dialog/fMapDesign.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
142
HMI/SubProject/AGVControl/Dialog/fMapDesign.resx
Normal file
142
HMI/SubProject/AGVControl/Dialog/fMapDesign.resx
Normal 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>
|
||||
158
HMI/SubProject/AGVControl/Dialog/fPropertyRFIDPoint.Designer.cs
generated
Normal file
158
HMI/SubProject/AGVControl/Dialog/fPropertyRFIDPoint.Designer.cs
generated
Normal 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;
|
||||
}
|
||||
}
|
||||
55
HMI/SubProject/AGVControl/Dialog/fPropertyRFIDPoint.cs
Normal file
55
HMI/SubProject/AGVControl/Dialog/fPropertyRFIDPoint.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
120
HMI/SubProject/AGVControl/Dialog/fPropertyRFIDPoint.resx
Normal file
120
HMI/SubProject/AGVControl/Dialog/fPropertyRFIDPoint.resx
Normal file
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
23
HMI/SubProject/AGVControl/GridView/ColorListItem.cs
Normal file
23
HMI/SubProject/AGVControl/GridView/ColorListItem.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace arFrame.Control
|
||||
{
|
||||
[TypeConverterAttribute(typeof(ExpandableObjectConverter))]
|
||||
public class ColorListItem
|
||||
{
|
||||
public System.Drawing.Color BackColor1 { get; set; }
|
||||
public System.Drawing.Color BackColor2 { get; set; }
|
||||
public string Remark { get; set; }
|
||||
|
||||
public ColorListItem()
|
||||
{
|
||||
BackColor1 = System.Drawing.Color.Transparent;
|
||||
BackColor2 = System.Drawing.Color.Transparent;
|
||||
Remark = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
50
HMI/SubProject/AGVControl/GridView/GridItem.cs
Normal file
50
HMI/SubProject/AGVControl/GridView/GridItem.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace arFrame.Control
|
||||
{
|
||||
[TypeConverterAttribute(typeof(ExpandableObjectConverter))]
|
||||
public class GridViewItem
|
||||
{
|
||||
public int row { get; private set; }
|
||||
public int col { get; private set; }
|
||||
|
||||
public int idx { get; private set; }
|
||||
[Category("arFrame"), DisplayName("Tag")]
|
||||
public string Tag { get; set; }
|
||||
[Category("arFrame"), DisplayName("글자 정렬 방식")]
|
||||
public System.Drawing.ContentAlignment TextAlign { get; set; }
|
||||
[Category("arFrame"), DisplayName("글자 여백")]
|
||||
public System.Windows.Forms.Padding Padding { get; set; }
|
||||
[Category("arFrame"), DisplayName("메뉴 사용여부"), Description("활성화시 메뉴의 클릭이벤트가 발생하지 않습니다")]
|
||||
public Boolean Enable { get; set; }
|
||||
|
||||
public System.Drawing.Color BackColor1 { get; set; }
|
||||
public System.Drawing.Color BackColor2 { get; set; }
|
||||
|
||||
public Boolean Dirty { get; set; }
|
||||
|
||||
public System.Drawing.RectangleF rect { get; set; }
|
||||
|
||||
[Category("arFrame"), DisplayName("번호")]
|
||||
public int No { get; set; }
|
||||
|
||||
public GridViewItem(int idx_,int _r,int _c)
|
||||
{
|
||||
this.row = _r;
|
||||
this.col = _c;
|
||||
BackColor1 = System.Drawing.Color.Transparent;
|
||||
BackColor2 = System.Drawing.Color.Transparent;
|
||||
rect = System.Drawing.RectangleF.Empty;
|
||||
Enable = true;
|
||||
this.idx = idx_;
|
||||
TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
Padding = new System.Windows.Forms.Padding(0, 0, 0, 0);
|
||||
No = 0;
|
||||
this.Dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
36
HMI/SubProject/AGVControl/GridView/GridView.Designer.cs
generated
Normal file
36
HMI/SubProject/AGVControl/GridView/GridView.Designer.cs
generated
Normal file
@@ -0,0 +1,36 @@
|
||||
namespace arFrame.Control
|
||||
{
|
||||
partial class GridView
|
||||
{
|
||||
/// <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 구성 요소 디자이너에서 생성한 코드
|
||||
|
||||
/// <summary>
|
||||
/// 디자이너 지원에 필요한 메서드입니다.
|
||||
/// 이 메서드의 내용을 코드 편집기로 수정하지 마십시오.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
624
HMI/SubProject/AGVControl/GridView/GridView.cs
Normal file
624
HMI/SubProject/AGVControl/GridView/GridView.cs
Normal file
@@ -0,0 +1,624 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace arFrame.Control
|
||||
{
|
||||
public partial class GridView : System.Windows.Forms.Control
|
||||
{
|
||||
private int bordersize = 0;
|
||||
private int menubordersize = 1;
|
||||
private int menugap = 5;
|
||||
private System.Windows.Forms.Padding padding = new Padding(3, 3, 3, 3);
|
||||
private System.Drawing.Color backcolor = System.Drawing.Color.White;
|
||||
private System.Drawing.Color bordercolor = System.Drawing.Color.Black;
|
||||
private Boolean textattachtoimage = true;
|
||||
private Boolean _showIndexString = true;
|
||||
|
||||
private System.Drawing.Color _shadowColor = System.Drawing.Color.Transparent;
|
||||
private System.Drawing.Color foreColorPin = System.Drawing.Color.WhiteSmoke;
|
||||
private System.Drawing.Font fontPin = new Font("Consolas", 8, FontStyle.Bold);
|
||||
|
||||
private Point _matrixsize = new Point(8, 2);
|
||||
public Point MatrixSize { get { return _matrixsize; } set { _matrixsize = value; ResetArray(); RemakeChartRect(); } }
|
||||
|
||||
[Browsable(false)]
|
||||
public int ColumnCount { get { return _matrixsize.X; } }
|
||||
[Browsable(false)]
|
||||
public int RowCount { get { return _matrixsize.Y; } }
|
||||
public int ItemCount { get { return ColumnCount * RowCount; } }
|
||||
|
||||
private GridViewItem[] Items;
|
||||
|
||||
private UInt16[] _values;
|
||||
private string[] _titles;
|
||||
private string[] _tags;
|
||||
private string[] _names;
|
||||
private ColorListItem[] _colorlist;
|
||||
public ColorListItem[] ColorList { get { return _colorlist; } set { _colorlist = value; this.Invalidate(); } }
|
||||
|
||||
public string[] Names { get { return _names; } set { _names = value; Invalidate(); } }
|
||||
public string[] Titles { get { return _titles; } set { _titles = value; Invalidate(); } }
|
||||
public UInt16[] Values { get { return _values; } set { _values = value; Invalidate(); } }
|
||||
public string[] Tags { get { return _tags; } set { _tags = value; } }
|
||||
|
||||
private bool _showdebuginfo = false;
|
||||
public Boolean showDebugInfo { get { return _showdebuginfo; } set { _showdebuginfo = value; Invalidate(); } }
|
||||
|
||||
public void setNames(string[] value)
|
||||
{
|
||||
_names = value;
|
||||
}
|
||||
|
||||
public void setTitle(string[] value)
|
||||
{
|
||||
List<string> titlerows = new List<string>();
|
||||
List<string> tagrows = new List<string>();
|
||||
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
{
|
||||
var r = (int)(Math.Floor((double)(i / ColumnCount)));
|
||||
var c = i % ColumnCount;
|
||||
|
||||
if (titlerows.Count < r + 1) titlerows.Add(string.Empty);
|
||||
if (tagrows.Count < r + 1) tagrows.Add(string.Empty);
|
||||
|
||||
var prestr = titlerows[r];
|
||||
if (prestr != "") prestr += "|";
|
||||
titlerows[r] = prestr + value[i];
|
||||
|
||||
var prestr_t = tagrows[r];
|
||||
if (prestr_t != "") prestr_t += "|";
|
||||
tagrows[r] = prestr_t + "";
|
||||
|
||||
if (i < itemCount) this.Items[i].Enable = true;
|
||||
}
|
||||
this._titles = titlerows.ToArray();
|
||||
this._tags = tagrows.ToArray();
|
||||
}
|
||||
|
||||
public Boolean setTitle(int row, int col, string value, string itemtag = "")
|
||||
{
|
||||
if (_titles == null) _titles = new string[0];
|
||||
if (_tags == null) _tags = new string[0];
|
||||
|
||||
if ( row >= _titles.Length) Array.Resize(ref _titles, row + 1);
|
||||
if( row >= _tags.Length) Array.Resize(ref _tags, row+1);
|
||||
|
||||
if (_titles[row] == null) _titles[row] = string.Empty;
|
||||
if (_tags[row] == null) _tags[row] = string.Empty;
|
||||
|
||||
var linebuf = _titles[row].Split('|');
|
||||
var linebuf_t = _tags[row].Split('|');
|
||||
|
||||
if (col >= linebuf.Length) Array.Resize(ref linebuf, col + 1);
|
||||
if (col >= linebuf_t.Length) Array.Resize(ref linebuf_t, col + 1);
|
||||
|
||||
linebuf[col] = value;
|
||||
linebuf_t[col] = itemtag;
|
||||
|
||||
_titles[row] = string.Join("|", linebuf);
|
||||
_tags[row] = string.Join("|", linebuf_t);
|
||||
return true;
|
||||
//var idx = row * this.ColumnCount + col;
|
||||
//return setTitle(idx, value);
|
||||
}
|
||||
public Boolean setTitle(int idx, string value)
|
||||
{
|
||||
if (idx < ColumnCount) return setTitle(0, idx, value);
|
||||
else
|
||||
{
|
||||
//줄값이 필요하다
|
||||
var row = (int)(Math.Floor((double)(idx / ColumnCount)));
|
||||
var col = idx % ColumnCount;
|
||||
return setTitle(row, col, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setValue(bool[] value)
|
||||
{
|
||||
var v = new UInt16[value.Length];
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
v[i] = (UInt16)(value[i] ? 1 : 0);
|
||||
_values = v;
|
||||
}
|
||||
public void setValue(UInt16[] value)
|
||||
{
|
||||
_values = value;
|
||||
}
|
||||
public Boolean setValue(int idx, ushort value)
|
||||
{
|
||||
if (this._values == null) _values = new ushort[idx + 1];
|
||||
if (idx >= this._values.Length) Array.Resize(ref _values, idx + 1);
|
||||
this._values[idx] = value;
|
||||
return true;
|
||||
}
|
||||
public Boolean setTag(string[] value)
|
||||
{
|
||||
this._tags = value;
|
||||
return true;
|
||||
}
|
||||
public Boolean setTag(int idx, string value)
|
||||
{
|
||||
if (this._tags == null) Tags = new string[idx + 1];
|
||||
if (idx >= this.Tags.Length) Array.Resize(ref _tags, idx + 1);
|
||||
this._tags[idx] = value;
|
||||
return true;
|
||||
}
|
||||
public void ClearValue(ushort defaultValue = 0)
|
||||
{
|
||||
if (_values != null)
|
||||
for(int i = 0; i < _values.Length;i++)
|
||||
_values[i] = defaultValue;
|
||||
}
|
||||
public void ClearTitle(string defaultValue = "")
|
||||
{
|
||||
if (_values != null)
|
||||
for (int i = 0; i < _titles.Length; i++)
|
||||
_titles[i] = defaultValue;
|
||||
}
|
||||
public void ClearTag(string defaultValue = "")
|
||||
{
|
||||
if (_tags != null)
|
||||
for (int i = 0; i < _tags.Length; i++)
|
||||
_tags[i] = defaultValue;
|
||||
}
|
||||
public void setValue(ushort value)
|
||||
{
|
||||
for(int i = 0; i < _values.Length;i++)
|
||||
this._values[i] = value;
|
||||
}
|
||||
public void setItemEnable(int idx, bool value)
|
||||
{
|
||||
if (idx >= _values.Length || idx >= this.Items.Length) return;
|
||||
this.Items[idx].Enable = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 지정된 컬러태그값을 입력한다.
|
||||
/// </summary>
|
||||
/// <param name="idx"></param>
|
||||
/// <param name="tagString"></param>
|
||||
/// <returns></returns>
|
||||
public Boolean setValue(int idx, string tagString)
|
||||
{
|
||||
//동일태그값을 찾는다
|
||||
if (idx >= _values.Length) return false;
|
||||
|
||||
int value = -1;
|
||||
for (int i = 0; i < ColorList.Length; i++)
|
||||
if (ColorList[i].Remark.ToLower() == tagString.ToLower())
|
||||
{
|
||||
value = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (value != -1)
|
||||
{
|
||||
this._values[idx] = (ushort)value;
|
||||
this.Items[idx].Enable = true;
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
|
||||
|
||||
}
|
||||
public Boolean setValue(int idx, bool value)
|
||||
{
|
||||
return setValue(idx, (ushort)(value ? 1 : 0));
|
||||
}
|
||||
public Boolean setValue(int row, int col, ushort value)
|
||||
{
|
||||
var idx = row * this.ColumnCount + col;
|
||||
return setValue(idx, value);
|
||||
}
|
||||
public Boolean setValue(int row, int col, int value)
|
||||
{
|
||||
var idx = row * this.ColumnCount + col;
|
||||
return setValue(idx, (ushort)value);
|
||||
}
|
||||
public Boolean setValueToggle(int row, int col, ushort value1,ushort value2)
|
||||
{
|
||||
var idx = row * this.ColumnCount + col;
|
||||
if(getValue(idx) == value1) return setValue(idx, value2);
|
||||
else return setValue(idx, value1);
|
||||
}
|
||||
public Boolean setValue(int row, int col, bool value)
|
||||
{
|
||||
var idx = row * this.ColumnCount + col;
|
||||
return setValue(idx, (ushort)(value ? 1 : 0));
|
||||
}
|
||||
public Boolean setValue(int row, int col, string value)
|
||||
{
|
||||
var idx = row * this.ColumnCount + col;
|
||||
return setValue(idx, value);
|
||||
}
|
||||
|
||||
public ushort getValue(int idx)
|
||||
{
|
||||
if (idx >= _values.Length) return 0;
|
||||
return _values[idx];
|
||||
}
|
||||
public ushort getValue(int row, int col)
|
||||
{
|
||||
var idx = row * this.ColumnCount + col;
|
||||
return getValue(idx);
|
||||
}
|
||||
|
||||
[Category("arFrame")]
|
||||
public bool ShowIndexString { get { return _showIndexString; } set { _showIndexString = value; Invalidate(); } }
|
||||
|
||||
[Category("arFrame"), DisplayName("테두리 굵기")]
|
||||
public int BorderSize { get { return bordersize; } set { this.bordersize = value; Invalidate(); } }
|
||||
[Category("arFrame"), DisplayName("메뉴 테두리 굵기")]
|
||||
public int MenuBorderSize { get { return menubordersize; } set { this.menubordersize = value; Invalidate(); } }
|
||||
[Category("arFrame"), DisplayName("메뉴 간격")]
|
||||
public int MenuGap { get { return menugap; } set { this.menugap = value; RemakeChartRect(); Invalidate(); } }
|
||||
[Category("arFrame"), DisplayName("글자를 이미지 다음에 표시"), Description("이미지가 있는 경우 해당 이미지 옆에 글자를 붙입니다")]
|
||||
public Boolean TextAttachToImage { get { return textattachtoimage; } set { this.textattachtoimage = value; Invalidate(); } }
|
||||
|
||||
[Category("arFrame"), DisplayName("색상-테두리")]
|
||||
public System.Drawing.Color BorderColor { get { return bordercolor; } set { this.bordercolor = value; Invalidate(); } }
|
||||
[Category("arFrame"), DisplayName("내부 여백")]
|
||||
public new System.Windows.Forms.Padding Padding { get { return padding; } set { this.padding = value; RemakeChartRect(); Invalidate(); } }
|
||||
|
||||
[Category("arFrame"), DisplayName("색상-전체배경색")]
|
||||
public override System.Drawing.Color BackColor { get { return backcolor; } set { this.backcolor = value; Invalidate(); } }
|
||||
|
||||
[Category("arFrame"), DisplayName("색상-글자(그림자)")]
|
||||
public System.Drawing.Color ShadowColor { get { return _shadowColor; } set { _shadowColor = value; this.Invalidate(); } }
|
||||
|
||||
[Category("arFrame"), DisplayName("색상-글자")]
|
||||
public override Color ForeColor { get { return base.ForeColor; } set { base.ForeColor = value; } }
|
||||
|
||||
[Category("arFrame"), DisplayName("색상-글자(번호)")]
|
||||
public Color ForeColorPin { get { return foreColorPin; } set { foreColorPin = value; } }
|
||||
|
||||
[Category("arFrame"), DisplayName("글꼴-번호")]
|
||||
public Font FontPin { get { return fontPin; } set { fontPin = value; Invalidate(); } }
|
||||
[Category("arFrame"), DisplayName("글꼴-항목")]
|
||||
public override Font Font { get { return base.Font; } set { base.Font = value; Invalidate(); } }
|
||||
|
||||
private int mouseOverItemIndex = -1;
|
||||
public GridView()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// Set Optimized Double Buffer to reduce flickering
|
||||
this.SetStyle(ControlStyles.UserPaint, true);
|
||||
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
||||
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
|
||||
|
||||
// Redraw when resized
|
||||
this.SetStyle(ControlStyles.ResizeRedraw, true);
|
||||
|
||||
//값과 이름은 외부의 값을 사용한다
|
||||
ResetArray();
|
||||
|
||||
if (MinimumSize.Width == 0 || MinimumSize.Height == 0)
|
||||
MinimumSize = new Size(100, 50);
|
||||
}
|
||||
|
||||
|
||||
void ResetArray()
|
||||
{
|
||||
if (this._values != null) Array.Resize(ref this._values, itemCount);// = new UInt16[itemCount];
|
||||
// if (this._titles != null) Array.Resize(ref this._titles, itemCount);//
|
||||
// if (this._names != null) Array.Resize(ref this._names, itemCount);//
|
||||
}
|
||||
|
||||
int itemCount { get { return ColumnCount * RowCount; } }
|
||||
protected override void OnSizeChanged(EventArgs e)
|
||||
{
|
||||
base.OnSizeChanged(e);
|
||||
RemakeChartRect();
|
||||
}
|
||||
|
||||
public event EventHandler<ItemClickEventArgs> ItemClick;
|
||||
public class ItemClickEventArgs : EventArgs
|
||||
{
|
||||
public int idx { get; set; }
|
||||
public GridViewItem Item { get; set; }
|
||||
public ItemClickEventArgs(int idx_, GridViewItem item)
|
||||
{
|
||||
this.Item = item;
|
||||
this.idx = idx_;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnMouseClick(MouseEventArgs e)
|
||||
{
|
||||
//마우스클릭시 해당 버튼을 찾아서 반환한다.
|
||||
if (Items == null || Items.Length < 1) return;
|
||||
for (int i = 0; i < Items.Length; i++)
|
||||
{
|
||||
var rect = Items[i].rect;//[i];
|
||||
if (rect.Contains(e.Location))
|
||||
{
|
||||
var menu = Items[i];
|
||||
|
||||
//미사용개체는 이벤트를 아에 발생하지 않는다
|
||||
if (menu.Enable == true && ItemClick != null)
|
||||
ItemClick(this, new ItemClickEventArgs(i, menu));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnMouseLeave(EventArgs e)
|
||||
{
|
||||
this.mouseOverItemIndex = -1;
|
||||
this.Invalidate();
|
||||
}
|
||||
protected override void OnMouseMove(MouseEventArgs e)
|
||||
{
|
||||
if (Items == null || Items.Length < 1)
|
||||
{
|
||||
this.mouseOverItemIndex = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < Items.Length; i++)
|
||||
{
|
||||
var rect = Items[i].rect;// rects[i];
|
||||
if (rect.Contains(e.Location))
|
||||
{
|
||||
if (i != mouseOverItemIndex)
|
||||
{
|
||||
mouseOverItemIndex = i;
|
||||
this.Invalidate();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void setItemTextAlign(int row, int col, System.Drawing.ContentAlignment TextAlign)
|
||||
{
|
||||
var item = this.Items.Where(t => t.row == row && t.col == col).FirstOrDefault();
|
||||
if (item != null) item.TextAlign = TextAlign;
|
||||
}
|
||||
public void setItemTextAlign(System.Drawing.ContentAlignment TextAlign)
|
||||
{
|
||||
foreach (var item in this.Items)
|
||||
item.TextAlign = TextAlign;
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs pe)
|
||||
{
|
||||
//배경그리기
|
||||
//using (var sb = new System.Drawing.Drawing2D.LinearGradientBrush(DisplayRectangle, BackColor, BackColor2On, System.Drawing.Drawing2D.LinearGradientMode.Vertical))
|
||||
pe.Graphics.FillRectangle(new SolidBrush(BackColor), DisplayRectangle);
|
||||
|
||||
if (Items == null)
|
||||
{
|
||||
pe.Graphics.DrawString("no items", this.Font, Brushes.Red, 100, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
var items = Items.OrderBy(t => t.No);
|
||||
foreach (var menu in items)
|
||||
{
|
||||
drawItem(menu.idx, pe.Graphics);
|
||||
}
|
||||
|
||||
//테두리 그리기
|
||||
if (BorderSize > 0)
|
||||
{
|
||||
pe.Graphics.DrawRectangle(new Pen(this.BorderColor, BorderSize),
|
||||
this.DisplayRectangle.Left,
|
||||
this.DisplayRectangle.Top,
|
||||
this.DisplayRectangle.Width - 1,
|
||||
this.DisplayRectangle.Height - 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void drawItem(int itemIndex, Graphics g = null)
|
||||
{
|
||||
if (g == null) g = this.CreateGraphics();
|
||||
var menu = this.Items[itemIndex];
|
||||
|
||||
if (menu.rect == RectangleF.Empty) return;
|
||||
|
||||
var rect = menu.rect;// rects[i];
|
||||
|
||||
var diplayText = string.Empty;
|
||||
|
||||
//타이틀이 줄번호별로 처리됨
|
||||
if (_titles != null && menu.row < _titles.Length && _titles[menu.row] != null )
|
||||
{
|
||||
var linebif = _titles[menu.row].Split('|');
|
||||
if (menu.col < linebif.Length)
|
||||
diplayText = linebif[menu.col];
|
||||
}
|
||||
|
||||
UInt16 Value = 0;
|
||||
if (_values != null && menu.idx < _values.Length) Value = _values[menu.idx];
|
||||
|
||||
//배경이 투명이 아니라면 그린다.
|
||||
var bgColor1 = Color.FromArgb(30, 30, 30);// BackColor1Off;
|
||||
var bgColor2 = Color.FromArgb(30, 30, 30);// BackColor2Off;
|
||||
|
||||
//해당 값에 따른 컬러값을 읽는다.
|
||||
if (ColorList != null && Value < ColorList.Length)
|
||||
{
|
||||
bgColor1 = this.ColorList[Value].BackColor1;
|
||||
bgColor2 = this.ColorList[Value].BackColor2;
|
||||
}
|
||||
|
||||
using (var sb = new System.Drawing.Drawing2D.LinearGradientBrush(rect, bgColor1, bgColor2, System.Drawing.Drawing2D.LinearGradientMode.Vertical))
|
||||
g.FillRectangle(sb, rect);
|
||||
|
||||
// if (mouseOverItemIndex == menu.idx)
|
||||
// this.Cursor = Cursors.Hand;
|
||||
// else
|
||||
// this.Cursor = Cursors.Arrow;
|
||||
|
||||
//테두리를 그리는 속성과 트기가 설정된 경우에만 표시
|
||||
//if (mouseOverItemIndex == i)
|
||||
// {
|
||||
// pe.Graphics.DrawRectangle(new Pen(Color.DeepSkyBlue), rect.Left, rect.Top, rect.Width, rect.Height);
|
||||
//}
|
||||
//else
|
||||
{
|
||||
if (MenuBorderSize > 0)
|
||||
{
|
||||
using (var p = new Pen(BorderColor, MenuBorderSize))
|
||||
g.DrawRectangle(p, rect.Left, rect.Top, rect.Width, rect.Height);
|
||||
}
|
||||
}
|
||||
|
||||
//인덱스번호 출력
|
||||
if (ShowIndexString && _names != null && menu.idx < _names.Length)
|
||||
{
|
||||
//표시글자
|
||||
var idxstr = string.Format("[{0}] {1}", menu.idx, _names[menu.idx]);
|
||||
|
||||
//그림자 추가
|
||||
if (ShadowColor != System.Drawing.Color.Transparent)
|
||||
g.DrawString(idxstr, FontPin, new SolidBrush(ShadowColor), menu.rect.Left + 4, menu.rect.Top + 4);
|
||||
|
||||
//일반글자표시
|
||||
g.DrawString(idxstr, FontPin, new SolidBrush(this.ForeColorPin), menu.rect.Left + 3, menu.rect.Top + 3);
|
||||
}
|
||||
|
||||
if (diplayText != "")
|
||||
{
|
||||
using (StringFormat sf = new StringFormat(StringFormatFlags.NoClip))
|
||||
{
|
||||
//글자를 텍스트 이후에 붙이는 거라면?
|
||||
if (menu.TextAlign == ContentAlignment.BottomCenter || menu.TextAlign == ContentAlignment.BottomLeft ||
|
||||
menu.TextAlign == ContentAlignment.BottomRight) sf.LineAlignment = StringAlignment.Far;
|
||||
else if (menu.TextAlign == ContentAlignment.MiddleCenter || menu.TextAlign == ContentAlignment.MiddleLeft ||
|
||||
menu.TextAlign == ContentAlignment.MiddleRight) sf.LineAlignment = StringAlignment.Center;
|
||||
else if (menu.TextAlign == ContentAlignment.TopCenter || menu.TextAlign == ContentAlignment.TopLeft ||
|
||||
menu.TextAlign == ContentAlignment.TopRight) sf.LineAlignment = StringAlignment.Near;
|
||||
|
||||
if (menu.TextAlign == ContentAlignment.BottomCenter || menu.TextAlign == ContentAlignment.MiddleCenter ||
|
||||
menu.TextAlign == ContentAlignment.TopCenter) sf.Alignment = StringAlignment.Center;
|
||||
else if (menu.TextAlign == ContentAlignment.BottomLeft || menu.TextAlign == ContentAlignment.MiddleLeft ||
|
||||
menu.TextAlign == ContentAlignment.TopLeft) sf.Alignment = StringAlignment.Near;
|
||||
else if (menu.TextAlign == ContentAlignment.BottomRight || menu.TextAlign == ContentAlignment.MiddleRight ||
|
||||
menu.TextAlign == ContentAlignment.TopRight) sf.Alignment = StringAlignment.Far;
|
||||
|
||||
//그림자 추가
|
||||
if (ShadowColor != System.Drawing.Color.Transparent)
|
||||
g.DrawString(diplayText, this.Font, new SolidBrush(ShadowColor),
|
||||
new RectangleF((float)(rect.Left + 1f), (float)(rect.Top + 1f), (float)rect.Width, (float)rect.Height), sf);
|
||||
|
||||
g.DrawString(diplayText, this.Font, new SolidBrush(ForeColor), rect, sf);
|
||||
}
|
||||
}
|
||||
|
||||
if (showDebugInfo)
|
||||
{
|
||||
g.DrawString(Value.ToString(), this.fontPin, Brushes.SkyBlue, rect.Left, rect.Top);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// arFrame 전용 속성값을 복사 합니다
|
||||
/// </summary>
|
||||
/// <param name="ctl"></param>
|
||||
public void copyTo(GridView ctl)
|
||||
{
|
||||
ctl.backcolor = this.backcolor;
|
||||
ctl.menugap = this.menugap;
|
||||
ctl.Items = this.Items;
|
||||
ctl.menubordersize = this.menubordersize;
|
||||
ctl.padding = this.padding;
|
||||
ctl.ForeColor = this.ForeColor;
|
||||
ctl.Font = this.Font;
|
||||
ctl.TextAttachToImage = this.TextAttachToImage;
|
||||
ctl.bordercolor = this.bordercolor;
|
||||
ctl.bordersize = this.bordersize;
|
||||
}
|
||||
|
||||
public void RemakeChartRect()
|
||||
{
|
||||
if (DisplayRectangle == Rectangle.Empty) return;
|
||||
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
double w = DisplayRectangle.Width / (ColumnCount * 1.0);
|
||||
double h = DisplayRectangle.Height / (RowCount * 1.0);
|
||||
|
||||
if (this.Items == null || itemCount != this.Items.Length)
|
||||
{
|
||||
//아이템갯수가 달라졌으므로 다시 갱신해야함
|
||||
GridViewItem[] item = new GridViewItem[RowCount * ColumnCount];
|
||||
for (int r = 0; r < RowCount; r++)
|
||||
{
|
||||
for (int c = 0; c < ColumnCount; c++)
|
||||
{
|
||||
int idx = r * ColumnCount + c;
|
||||
item[idx] = new GridViewItem(idx, r, c);
|
||||
item[idx].Enable = false;
|
||||
item[idx].Padding = new Padding(0, 0, 0, 0);
|
||||
item[idx].TextAlign = ContentAlignment.MiddleCenter;
|
||||
x = (c * w);
|
||||
y = (r * h);
|
||||
item[idx].rect = new RectangleF((float)x, (float)y, (float)w, (float)h);
|
||||
}
|
||||
}
|
||||
|
||||
this.Items = item;
|
||||
}
|
||||
else
|
||||
{
|
||||
//아이템의 갯수는 같으므로 좌표값만 변경해준다.
|
||||
for (int r = 0; r < RowCount; r++)
|
||||
{
|
||||
for (int c = 0; c < ColumnCount; c++)
|
||||
{
|
||||
int idx = r * ColumnCount + c;
|
||||
var item = Items[idx];
|
||||
x = (c * w);
|
||||
y = (r * h);
|
||||
item.Dirty = true;
|
||||
item.rect = new RectangleF((float)x, (float)y, (float)w, (float)h);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.Invalidate();
|
||||
|
||||
//int i = 0;
|
||||
//var menuList = this.Items.OrderBy(t => t.No).ToArray();
|
||||
//foreach (var menu in menuList)
|
||||
//{
|
||||
// int x, y, w, h;
|
||||
// // var menu = menus[i];
|
||||
|
||||
// var mWidth = menuwidth;
|
||||
// if (menu.MenuWidth > 0) mWidth = menu.MenuWidth;
|
||||
|
||||
// w = mWidth;
|
||||
// h = DisplayRectangle.Height - Padding.Top - Padding.Bottom;
|
||||
|
||||
// if (menu.isRightMenu)
|
||||
// {
|
||||
// x = DisplayRectangle.Right - Padding.Right - (rightAcc) - (MenuGap * rightIdx);
|
||||
// y = DisplayRectangle.Top + Padding.Top;
|
||||
// rightAcc += 0;// = 0;// x;
|
||||
// rightIdx += 1;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// x = DisplayRectangle.Left + Padding.Left + leftAcc + (MenuGap * leftIdx);
|
||||
// y = DisplayRectangle.Top + Padding.Top;
|
||||
// leftAcc += mWidth;
|
||||
// leftIdx += 1;
|
||||
// }
|
||||
// rects[i] = new Rectangle(x, y, w, h);
|
||||
// i += 1;
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
37
HMI/SubProject/AGVControl/GuideSensor.Designer.cs
generated
Normal file
37
HMI/SubProject/AGVControl/GuideSensor.Designer.cs
generated
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
namespace Narumi.UC
|
||||
{
|
||||
partial class GuideSensor
|
||||
{
|
||||
/// <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 구성 요소 디자이너에서 생성한 코드
|
||||
|
||||
/// <summary>
|
||||
/// 디자이너 지원에 필요한 메서드입니다.
|
||||
/// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
106
HMI/SubProject/AGVControl/GuideSensor.cs
Normal file
106
HMI/SubProject/AGVControl/GuideSensor.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
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 Narumi.UC
|
||||
{
|
||||
public partial class GuideSensor : Control
|
||||
{
|
||||
public int SensorValue { get; set; } = 0;
|
||||
public bool LMark { get; set; } = false;
|
||||
public bool RMark { get; set; } = false;
|
||||
|
||||
public GuideSensor()
|
||||
{
|
||||
InitializeComponent();
|
||||
// Set Optimized Double Buffer to reduce flickering
|
||||
this.SetStyle(ControlStyles.UserPaint, true);
|
||||
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
||||
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
|
||||
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
|
||||
|
||||
// Redraw when resized
|
||||
this.SetStyle(ControlStyles.ResizeRedraw, true);
|
||||
|
||||
this.Resize += arLabel_Resize;
|
||||
}
|
||||
void arLabel_Resize(object sender, EventArgs e)
|
||||
{
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs pe)
|
||||
{
|
||||
var boxcount = 11;
|
||||
|
||||
var r = new RectangleF(this.DisplayRectangle.Left + Padding.Left,
|
||||
this.DisplayRectangle.Top + Padding.Top,
|
||||
this.DisplayRectangle.Width - Padding.Left - Padding.Right,
|
||||
this.DisplayRectangle.Height - Padding.Top - Padding.Bottom);
|
||||
|
||||
var term = 3;
|
||||
var w = ((r.Width -1) - (term * (boxcount - 1))) / boxcount;
|
||||
var h = r.Height -1;
|
||||
|
||||
pe.Graphics.FillRectangle(new SolidBrush(this.BackColor), this.DisplayRectangle);
|
||||
//pe.Graphics.DrawRectangle(Pens.Red, r.Left, r.Top, r.Width, r.Height);
|
||||
|
||||
for (int i = 0; i < boxcount; i++)
|
||||
{
|
||||
var x = r.Left + i * term + i * w;
|
||||
var y = r.Top;
|
||||
var r2 = new RectangleF(x, y, w, h);
|
||||
|
||||
if (this.Enabled == false)
|
||||
{
|
||||
pe.Graphics.FillRectangle(Brushes.LightGray, r2);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
if (LMark)
|
||||
pe.Graphics.FillRectangle(Brushes.SkyBlue, r2);
|
||||
else
|
||||
pe.Graphics.FillRectangle(Brushes.LightGray, r2);
|
||||
}
|
||||
else if (i == 9)
|
||||
{
|
||||
if (RMark)
|
||||
pe.Graphics.FillRectangle(Brushes.SkyBlue, r2);
|
||||
else
|
||||
pe.Graphics.FillRectangle(Brushes.LightGray, r2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SensorValue == i)
|
||||
pe.Graphics.FillRectangle(Brushes.Tomato, r2);
|
||||
else
|
||||
pe.Graphics.FillRectangle(Brushes.LightGray, r2);
|
||||
}
|
||||
|
||||
pe.Graphics.DrawRectangle(Pens.DimGray, r2.Left,r2.Top,r2.Width,r2.Height);
|
||||
|
||||
if (i == 0 || i == 10)
|
||||
{
|
||||
pe.Graphics.DrawString("M/K", this.Font,
|
||||
new SolidBrush(this.ForeColor), r2,
|
||||
new StringFormat
|
||||
{
|
||||
Alignment = StringAlignment.Center,
|
||||
LineAlignment = StringAlignment.Center
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
37
HMI/SubProject/AGVControl/MapControl.Designer.cs
generated
Normal file
37
HMI/SubProject/AGVControl/MapControl.Designer.cs
generated
Normal file
@@ -0,0 +1,37 @@
|
||||
namespace AGVControl
|
||||
{
|
||||
partial class MapControl
|
||||
{
|
||||
/// <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 Component 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()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
this.ClientSize = new System.Drawing.Size(800, 450);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
2180
HMI/SubProject/AGVControl/MapControl.cs
Normal file
2180
HMI/SubProject/AGVControl/MapControl.cs
Normal file
File diff suppressed because it is too large
Load Diff
120
HMI/SubProject/AGVControl/MapControl.resx
Normal file
120
HMI/SubProject/AGVControl/MapControl.resx
Normal file
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
621
HMI/SubProject/AGVControl/MapControlManager.cs
Normal file
621
HMI/SubProject/AGVControl/MapControlManager.cs
Normal file
@@ -0,0 +1,621 @@
|
||||
using AGVControl.Models;
|
||||
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 class MapControlManager
|
||||
{
|
||||
public AGVActionPrediction PredictResult = null;
|
||||
public AGV agv = new AGV();
|
||||
public List<RFIDPoint> RFIDPoints = new List<RFIDPoint>();
|
||||
public HashSet<RFIDConnection> rfidConnections = new HashSet<RFIDConnection>();
|
||||
|
||||
private ManualResetEvent mrepredict = new ManualResetEvent(true);
|
||||
|
||||
public MapControlManager()
|
||||
{
|
||||
|
||||
}
|
||||
~MapControlManager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 목표지정으로 모터방향이 이동하고 있는가?
|
||||
/// history 데이터가 있어야 하며 기준데이터가 없는 경우 null 반환
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool? IsMotDirection_To_Target()
|
||||
{
|
||||
if (agv.MovementHistory.Any() == false || agv.MovementHistory.Count < 2) return null;
|
||||
if (agv.MainPath.Any() == false) return null;
|
||||
|
||||
|
||||
var prept = agv.MovementHistory.Skip(agv.MovementHistory.Count - 2).First();
|
||||
var lstpt = agv.MovementHistory.Last();
|
||||
|
||||
//현재 이후의 경로를 가져온다
|
||||
var curidx = agv.MainPath.FindIndex(t => t.Value == lstpt.Value);
|
||||
var preidx = agv.MainPath.FindIndex(t => t.Value == prept.Value);
|
||||
if (curidx == -1 || preidx == -1) return null;
|
||||
|
||||
//지정된경로 반대방향으로 이동하고 있다
|
||||
return preidx < curidx;
|
||||
}
|
||||
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 AGVActionPrediction PredictNextAction()
|
||||
{
|
||||
if (mrepredict.WaitOne(1) == false)
|
||||
{
|
||||
PredictResult = CreatePrediction("이전 작업이 완료되지 않았습니다",
|
||||
AGVActionReasonCode.busy,
|
||||
AGVMoveState.Stop,
|
||||
agv.Current_Motor_Direction, false);
|
||||
return PredictResult;
|
||||
}
|
||||
|
||||
mrepredict.Reset();
|
||||
try
|
||||
{
|
||||
// 0. 설정경로와 리프트 방향 체크 (경로설정이 없을때에는 직선이동경로내의 방향들과 체크한다)
|
||||
agv.IsTargetDirectionMatch = IsLiftDirectionMatch() ?? false;
|
||||
|
||||
// 1. 위치를 모를 때 (CurrentRFID가 0 또는 미설정)
|
||||
if (agv.CurrentRFID.Value == 0)
|
||||
{
|
||||
PredictResult = CreatePrediction("AGV 위치 미확정(처음 기동)",
|
||||
AGVActionReasonCode.NoPosition,
|
||||
AGVMoveState.Run,
|
||||
AgvDir.Backward, true,
|
||||
moveSpeed: AgvSpeed.Low,
|
||||
moveDiv: AgvSts.Straight);
|
||||
return PredictResult;
|
||||
}
|
||||
|
||||
//2. 이동방향을 모른다
|
||||
if (agv.MovementHistory.Any() == false || agv.MovementHistory.Count < 2)
|
||||
{
|
||||
PredictResult = CreatePrediction("AGV이동방향 알수없음",
|
||||
AGVActionReasonCode.NoDirection,
|
||||
AGVMoveState.Run,
|
||||
AgvDir.Backward, true,
|
||||
moveSpeed: AgvSpeed.Low,
|
||||
moveDiv: AgvSts.Straight);
|
||||
return PredictResult;
|
||||
}
|
||||
|
||||
// 3. 경로가 없거나 현재 위치가 경로에 없음
|
||||
if ((agv.MainPath?.Count ?? 0) < 2 || agv.MainPath.Last().Value != agv.TargetRFID.Value)
|
||||
{
|
||||
//목적지가 없다면 진행할 수 없다
|
||||
if (agv.TargetRFID == null)
|
||||
{
|
||||
PredictResult = CreatePrediction("경로 없음 또는 현재 위치 미확정",
|
||||
AGVActionReasonCode.NoPath,
|
||||
AGVMoveState.Stop,
|
||||
agv.Current_Motor_Direction, 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.Current_Motor_Direction, 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 = CreatePrediction("현재 위치가 경로에 없음",
|
||||
AGVActionReasonCode.NotOnPath,
|
||||
AGVMoveState.Stop,
|
||||
agv.Current_Motor_Direction, true);
|
||||
return PredictResult;
|
||||
}
|
||||
|
||||
// 4. 목적지 도달 전, 회전이 필요한경우인가?
|
||||
// 목적지 RFID 정보
|
||||
var destRFID = agv.MainPath.Last();
|
||||
|
||||
//리프트 방향이 맞는가?
|
||||
var IsLiftDir = IsLiftDirectionMatch() ?? false;
|
||||
|
||||
//모션이동방향이 맞는가?
|
||||
var IsMotDir = IsMotDirection_To_Target() ?? false;
|
||||
|
||||
var PrePT = agv.MovementHistory.Skip(agv.MovementHistory.Count - 2).First();
|
||||
var curPT = agv.MovementHistory.Last();
|
||||
|
||||
//리프트방향이 맞지 않다면 회전가능한 위치로 이동을 해야한다
|
||||
if (IsLiftDir == false)
|
||||
{
|
||||
AgvSpeed? agv_spd = null;
|
||||
AgvSts? 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 = CreatePrediction("회전 가능한 위치가 없습니다",
|
||||
AGVActionReasonCode.NoTurnPoint,
|
||||
AGVMoveState.Stop,
|
||||
agv.Current_Motor_Direction, true);
|
||||
return PredictResult;
|
||||
}
|
||||
|
||||
//2. 이동하기위한 경로계산 및 이동을 한다 (생성조건)
|
||||
//2-1. 서브경로가없는경우
|
||||
//2-2. 시작과 종료번호가 다른 경우(경로가 변경이 되는 조건이다)
|
||||
if (agv.CurrentRFID.Value != nearTurnPoint.Value)
|
||||
{
|
||||
if (agv.SubPath.Any() == false || agv.SubPath.Count < 2 ||
|
||||
agv.SubPath.First().Value != agv.CurrentRFID.Value ||
|
||||
agv.SubPath.Last().Value != nearTurnPoint.Value)
|
||||
{
|
||||
var rlt = CalculatePath(agv.CurrentRFID, nearTurnPoint); //이전포인트도 추가를 해준다
|
||||
if (rlt.Success) agv.SubPath = rlt.Path;
|
||||
else
|
||||
{
|
||||
agv.SubPath.Clear();
|
||||
PredictResult = CreatePrediction("회전 위치까지의 경로를 계산할 수 없습니다",
|
||||
AGVActionReasonCode.PathCalcError,
|
||||
AGVMoveState.Stop,
|
||||
agv.Current_Motor_Direction, true,
|
||||
nextRFID: nearTurnPoint);
|
||||
return PredictResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//현재 모터방향을 확인하여 대상까지 이동하도록 해야한다
|
||||
var curidx = agv.SubPath.FindIndex(t => t.Value == curPT.Value);
|
||||
var preidx = agv.SubPath.FindIndex(t => t.Value == PrePT.Value);
|
||||
AgvDir newdirection = agv.Current_Motor_Direction;
|
||||
string message = "턴위치로 이동중";
|
||||
|
||||
|
||||
|
||||
if (preidx > curidx)
|
||||
{
|
||||
//지정경로를 거꾸로 이동하고 있다
|
||||
if (agv.Current_Motor_Direction == AgvDir.Forward)
|
||||
newdirection = AgvDir.Backward;
|
||||
else
|
||||
newdirection = AgvDir.Forward;
|
||||
message += "(방향전환)";
|
||||
}
|
||||
|
||||
//도로정보를 확인하여 속도와 분기명령을 실행한다
|
||||
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 = CreatePrediction("턴(이동) 완료 대기",
|
||||
AGVActionReasonCode.NeedTurnMove,
|
||||
AGVMoveState.Stop,
|
||||
agv.Current_Motor_Direction, true,
|
||||
moveSpeed: agv_spd,
|
||||
moveDiv: agv_dir,
|
||||
nextRFID: nearTurnPoint);
|
||||
return PredictResult;
|
||||
}
|
||||
|
||||
//보조이동선제거
|
||||
if (agv.SubPath != null && agv.SubPath.Any())
|
||||
agv.SubPath.Clear();
|
||||
|
||||
//현재위치의 RFID에서 턴이 필요한경우
|
||||
if (agv.CurrentRFID.NeedTurn)
|
||||
{
|
||||
//Turn이 완료되지 않았다면 턴 완료를 대기한다.
|
||||
if (agv.CurrentRFID.TurnOK == false)
|
||||
{
|
||||
//아직 턴위치에 멈추지 않았다
|
||||
if (agv.CurrentRFID.TurnStop == false)
|
||||
{
|
||||
//현재위치로 마크스탑이동을 하게한다
|
||||
PredictResult = CreatePrediction("Wait for Turn(P)-Mark Stop",
|
||||
AGVActionReasonCode.WaitForMarkStop,
|
||||
AGVMoveState.Run,
|
||||
agv.Current_Motor_Direction, true,
|
||||
moveSpeed: agv.CurrentSpeed,
|
||||
moveDiv: agv.CurrentSTS);
|
||||
}
|
||||
else
|
||||
{
|
||||
//턴위치에 정지했으니. 턴완료를 기다려야 한다
|
||||
PredictResult = CreatePrediction("Wait for Turn(P)",
|
||||
AGVActionReasonCode.NeedTurnPoint,
|
||||
AGVMoveState.Run,
|
||||
agv.Current_Motor_Direction, true,
|
||||
moveSpeed: agv.CurrentSpeed,
|
||||
moveDiv: agv.CurrentSTS);
|
||||
}
|
||||
return PredictResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//3. 목적지위치까지 이동이 완료되지 않았다면 계속 이동을 하게한다
|
||||
if (agv.CurrentRFID.Value != destRFID.Value)
|
||||
{
|
||||
//현재 모터방향을 확인하여 대상까지 이동하도록 해야한다
|
||||
var curidx = agv.MainPath.FindIndex(t => t.Value == curPT.Value);
|
||||
var preidx = agv.MainPath.FindIndex(t => t.Value == PrePT.Value);
|
||||
AgvDir newdirection = agv.Current_Motor_Direction;
|
||||
string message = "목적지 이동중";
|
||||
if (preidx > curidx)
|
||||
{
|
||||
//지정경로를 거꾸로 이동하고 있다
|
||||
if (agv.Current_Motor_Direction == AgvDir.Forward)
|
||||
newdirection = AgvDir.Backward;
|
||||
else
|
||||
newdirection = AgvDir.Forward;
|
||||
message += "(방향전환)";
|
||||
}
|
||||
|
||||
//경로상 바로 다음 위치를 확인한다
|
||||
var nexstRFID = agv.MainPath.Skip(agv.MainPath.FindIndex(t => t.Value == curPT.Value) + 1).First();
|
||||
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 = CreatePrediction("경로의 마지막 지점(목적지 도달)",
|
||||
AGVActionReasonCode.Arrived,
|
||||
AGVMoveState.Stop,
|
||||
agv.Current_Motor_Direction, true,
|
||||
nextRFID: destRFID);
|
||||
return PredictResult;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
PredictResult = CreatePrediction($"ERR:{ex.Message}",
|
||||
AGVActionReasonCode.Unknown,
|
||||
AGVMoveState.Stop,
|
||||
agv.Current_Motor_Direction, true);
|
||||
return PredictResult;
|
||||
}
|
||||
finally
|
||||
{
|
||||
mrepredict.Set();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
(AgvSpeed? spd, AgvSts? dir, RFIDConnection info) GetRoadInfo(List<RFIDPoint> paths, RFIDPoint curPT)
|
||||
{
|
||||
//도로정보를 확인하여 속도와 분기명령을 실행한다
|
||||
AgvSpeed? agv_spd = null;
|
||||
AgvSts? 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 List<RFIDPoint> GetNeighbors(RFIDPoint pt)
|
||||
{
|
||||
var neighbors = new List<RFIDPoint>();
|
||||
|
||||
//값이 없는 경우 오류 반환
|
||||
if (pt == null) return neighbors;
|
||||
|
||||
//연결정보에서 데이터를 찾은 후 반환한다
|
||||
foreach (var connection in rfidConnections)
|
||||
{
|
||||
RFIDPoint nPT = null;
|
||||
if (connection.P1.Value == pt.Value)
|
||||
{
|
||||
nPT = connection.P2;
|
||||
}
|
||||
else if (connection.P2.Value == pt.Value)
|
||||
{
|
||||
nPT = connection.P1;
|
||||
}
|
||||
|
||||
if (nPT != null) neighbors.Add(nPT);
|
||||
}
|
||||
|
||||
//중복제거후 반한
|
||||
return neighbors.Distinct().ToList();
|
||||
}
|
||||
|
||||
public RFIDPoint FindRFIDPoint(uint rfidValue)
|
||||
{
|
||||
if (RFIDPoints == null || RFIDPoints.Any() == false) return null;
|
||||
return RFIDPoints.FirstOrDefault(r => r.Value == rfidValue);
|
||||
}
|
||||
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 PathResult ReconstructPath(Dictionary<uint, RFIDPoint> cameFrom, RFIDPoint current)
|
||||
{
|
||||
var path = new List<RFIDPoint> { current };
|
||||
while (cameFrom.ContainsKey(current.Value))
|
||||
{
|
||||
current = cameFrom[current.Value];
|
||||
if (path.Contains(current) == false)
|
||||
path.Insert(0, current);
|
||||
else
|
||||
break; //왜인지 반복되는경우가있어 종료한다
|
||||
}
|
||||
return new PathResult
|
||||
{
|
||||
Path = path,
|
||||
};
|
||||
}
|
||||
public PathResult CalculatePath(RFIDPoint start, RFIDPoint end)
|
||||
{
|
||||
var openList = new List<RFIDPoint> { start };
|
||||
var closedList = new List<RFIDPoint>();
|
||||
var cameFrom = new Dictionary<uint, RFIDPoint>();
|
||||
var gScore = new Dictionary<RFIDPoint, float> { { start, 0 } };
|
||||
var fScore = new Dictionary<RFIDPoint, float> { { start, Heuristic(start.Location, end.Location) } };
|
||||
|
||||
|
||||
|
||||
if (start.Value == end.Value)
|
||||
{
|
||||
return new PathResult
|
||||
{
|
||||
Message = "시작위치와 대상위치가 동일 합니다",
|
||||
Path = null,
|
||||
};
|
||||
}
|
||||
|
||||
//if (autorun) openList.Clear();
|
||||
|
||||
|
||||
while (openList.Count > 0)
|
||||
{
|
||||
var current = openList.OrderBy(p => fScore.ContainsKey(p) ? fScore[p] : float.MaxValue).First();
|
||||
|
||||
if (current.Value == end.Value)
|
||||
{
|
||||
return ReconstructPath(cameFrom, current);
|
||||
}
|
||||
|
||||
openList.Remove(current);
|
||||
closedList.Add(current);
|
||||
|
||||
var nb = GetNeighbors(current);
|
||||
foreach (var neighbor in nb)
|
||||
{
|
||||
if (closedList.Contains(neighbor))
|
||||
continue;
|
||||
|
||||
float tentativeGScore = gScore[current] + GetDistance(current.Location, neighbor.Location);
|
||||
|
||||
if (!openList.Contains(neighbor))
|
||||
openList.Add(neighbor);
|
||||
else if (tentativeGScore >= gScore[neighbor])
|
||||
continue;
|
||||
|
||||
cameFrom[neighbor.Value] = (RFIDPoint)current;
|
||||
gScore[neighbor] = tentativeGScore;
|
||||
fScore[neighbor] = gScore[neighbor] + Heuristic(neighbor.Location, end.Location);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return new PathResult
|
||||
{
|
||||
Path = openList,
|
||||
};
|
||||
|
||||
}
|
||||
public PathResult CalculatePath(uint tagStrt, uint tagEnd)
|
||||
{
|
||||
var retval = new PathResult
|
||||
{
|
||||
Message = string.Empty,
|
||||
Path = new List<RFIDPoint>(),
|
||||
};
|
||||
|
||||
var startPoint = FindRFIDPoint(tagStrt);
|
||||
var endPoint = FindRFIDPoint(tagEnd);
|
||||
if (startPoint == null || endPoint == null)
|
||||
{
|
||||
retval.Message = "유효한 RFID 값을 입력해주세요.";
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = CalculatePath(startPoint, endPoint);
|
||||
if (retval.Success == false)
|
||||
retval.Message = "경로를 찾을 수 없습니다";
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 리프트방향과 대상위치와의 방향이 일치하는가?
|
||||
/// 목적지경로가 셋팅된 경우 현재 이동방향이 목적지방향과 일치하는가?
|
||||
/// 이동경로정보가 없거나 목적지가 없으면 null 이 반환됨
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool? IsLiftDirectionMatch()
|
||||
{
|
||||
|
||||
if (agv.MovementHistory.Any() && agv.MovementHistory.Count > 1)
|
||||
{
|
||||
RFIDPoint TargetPT = null;
|
||||
var prept = agv.MovementHistory.Skip(agv.MovementHistory.Count - 2).First();
|
||||
var lstpt = agv.MovementHistory.Last();
|
||||
|
||||
//뒤로이동하는경우라면 이전위치에 리프트가 있다.
|
||||
if (lstpt.Direction == AgvDir.Backward)
|
||||
{
|
||||
TargetPT = prept;
|
||||
}
|
||||
else //앞으로 이동한다면 이동방향과 동일하다
|
||||
{
|
||||
//이전위치는 제거 하고 처음발견된 것을 대상으로 한다
|
||||
TargetPT = GetNeighbors(lstpt).Where(t => t.Value != prept.Value).FirstOrDefault();
|
||||
}
|
||||
|
||||
//목적지가 있다면 목적지의 방향과 일치하는지 확인해야한다
|
||||
//남은경로중에 방향이 고정된 핀이 있다면 그것과 일치하는지 확인해야 한다
|
||||
if (agv.MainPath.Any())
|
||||
{
|
||||
//지정된경로 반대방향으로 이동하고 있다
|
||||
if ((IsMotDirection_To_Target() ?? false) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
var nextRoutes = agv.MainPath.Skip(agv.MainPath.FindIndex(t => t.Value == lstpt.Value) + 1).ToList();
|
||||
var DirectionMatch = true;
|
||||
foreach (var item in nextRoutes)
|
||||
{
|
||||
if (item.FixedDirection != null && item.FixedDirection != lstpt.Direction)
|
||||
{
|
||||
DirectionMatch = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return DirectionMatch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//대상포인트와의 방향만 체크한다.
|
||||
//고정대상이없다면 방향이 맞는것으로 한다
|
||||
return (TargetPT.FixedDirection ?? lstpt.Direction) == lstpt.Direction;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//이동된경로정보가 없다면 리프트 방향을 체크할 수 없으므로 대상과 위치가 맞지 않는걸로 기본값을 설정한다
|
||||
//이렇게 설정하면 대상으로 이동불가하고 뒤로 가도록 유도된다
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 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,
|
||||
AgvDir direction, bool IDXUpdate = true,
|
||||
AgvSpeed? moveSpeed = null,
|
||||
AgvSts? 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),
|
||||
CreateTime = DateTime.Now,
|
||||
};
|
||||
|
||||
newPrediction.Changed = IsPredictionChanged(newPrediction);
|
||||
return newPrediction;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
352
HMI/SubProject/AGVControl/Models/AGV.cs
Normal file
352
HMI/SubProject/AGVControl/Models/AGV.cs
Normal file
@@ -0,0 +1,352 @@
|
||||
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 AgvDir 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 Speed
|
||||
/// </summary>
|
||||
public AgvSpeed CurrentSpeed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// AGV STS
|
||||
/// </summary>
|
||||
public AgvSts CurrentSTS { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// AGV Motor Direction
|
||||
/// </summary>
|
||||
public AgvDir Current_Motor_Direction { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 현재위치가 수산되면 목적지까지의 방향값이 계산됩니다.
|
||||
/// </summary>
|
||||
public AgvDir? TargetDirection { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// AGV.System1.agv_Run
|
||||
/// </summary>
|
||||
public bool IsMoving { get; set; }
|
||||
/// <summary>
|
||||
/// AGV.System1.Mark1_Check | Mark2_Check
|
||||
/// </summary>
|
||||
public bool IsMarkCheck { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 이동대상과 AGV의 머리방향이 일치하는지?
|
||||
/// </summary>
|
||||
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 = AgvDir.Forward;
|
||||
// BodyAngle = null;
|
||||
}
|
||||
|
||||
|
||||
// 이동 경로에 새로운 RFID 추가
|
||||
public void AddToMovementHistory(UInt16 rfidValue, Point position, AgvDir 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);
|
||||
}
|
||||
|
||||
// 위치 업데이트 시 자동으로 히스토리 파일에 저장
|
||||
SaveHistoryOnUpdate();
|
||||
}
|
||||
|
||||
// 연결 정보 기반 실제 이동 방향 계산
|
||||
public AgvDir? 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 AgvDir.Forward; // Start -> End 방향으로 이동
|
||||
}
|
||||
else
|
||||
{
|
||||
return AgvDir.Backward; // End -> Start 방향으로 이동
|
||||
}
|
||||
}
|
||||
|
||||
// 연결 정보 기반 방향 불일치 검증 및 정정
|
||||
public bool ValidateAndCorrectDirectionByConnection(AgvDir 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 AgvDir? 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 AgvDir.Forward; // RFID 값이 증가하면 전진
|
||||
}
|
||||
else if (currentRFID.Value < prevRFID.Value)
|
||||
{
|
||||
return AgvDir.Backward; // RFID 값이 감소하면 후진
|
||||
}
|
||||
else
|
||||
{
|
||||
return null; // 같은 RFID 값이면 방향 판단 불가
|
||||
}
|
||||
}
|
||||
|
||||
// 위치 히스토리 파일 저장 (최근 3개만 저장)
|
||||
public void SavePositionHistory(string filePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 최근 3개의 히스토리만 저장
|
||||
var recentHistory = MovementHistory.Skip(Math.Max(0, MovementHistory.Count - 3)).ToList();
|
||||
|
||||
var lines = new List<string>();
|
||||
lines.Add($"# AGV Position History - {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
|
||||
lines.Add("# Format: RFID,Direction,X,Y,Timestamp");
|
||||
|
||||
foreach (var history in recentHistory)
|
||||
{
|
||||
lines.Add($"{history.Value},{history.Direction},{history.Location.X},{history.Location.Y},{DateTime.Now:yyyy-MM-dd HH:mm:ss}");
|
||||
}
|
||||
|
||||
System.IO.File.WriteAllLines(filePath, lines);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 로그 기록 (실제 환경에서는 로깅 시스템 사용)
|
||||
System.Diagnostics.Debug.WriteLine($"SavePositionHistory Error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
// 위치 히스토리 파일 로드
|
||||
public bool LoadPositionHistory(string filePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!System.IO.File.Exists(filePath))
|
||||
return false;
|
||||
|
||||
var lines = System.IO.File.ReadAllLines(filePath);
|
||||
MovementHistory.Clear();
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
// 주석 라인 건너뛰기
|
||||
if (line.StartsWith("#") || string.IsNullOrWhiteSpace(line))
|
||||
continue;
|
||||
|
||||
var parts = line.Split(',');
|
||||
if (parts.Length >= 4)
|
||||
{
|
||||
if (UInt16.TryParse(parts[0], out UInt16 rfidValue) &&
|
||||
Enum.TryParse<AgvDir>(parts[1], out AgvDir direction) &&
|
||||
int.TryParse(parts[2], out int x) &&
|
||||
int.TryParse(parts[3], out int y))
|
||||
{
|
||||
MovementHistory.Add(new movehistorydata
|
||||
{
|
||||
Value = rfidValue,
|
||||
Direction = direction,
|
||||
Location = new Point(x, y)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MovementHistory.Count > 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"LoadPositionHistory Error: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 시작 시 위치 히스토리 자동 로드
|
||||
public void LoadHistoryOnStartup()
|
||||
{
|
||||
string historyFilePath = System.IO.Path.Combine(
|
||||
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location),
|
||||
"agv_position_history.dat"
|
||||
);
|
||||
|
||||
LoadPositionHistory(historyFilePath);
|
||||
}
|
||||
|
||||
// 위치 업데이트 시 자동 저장
|
||||
public void SaveHistoryOnUpdate()
|
||||
{
|
||||
string historyFilePath = System.IO.Path.Combine(
|
||||
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location),
|
||||
"agv_position_history.dat"
|
||||
);
|
||||
|
||||
SavePositionHistory(historyFilePath);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
58
HMI/SubProject/AGVControl/Models/AGVActionPrediction.cs
Normal file
58
HMI/SubProject/AGVControl/Models/AGVActionPrediction.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using AGVControl.Models;
|
||||
using System;
|
||||
|
||||
namespace AGVControl
|
||||
{
|
||||
public class AGVActionPrediction
|
||||
{
|
||||
public AgvDir Direction { get; set; }
|
||||
public RFIDPoint NextRFID { get; set; }
|
||||
public string Reason { get; set; }
|
||||
public AGVActionReasonCode ReasonCode { get; set; }
|
||||
public AGVMoveState MoveState { get; set; } // RUN 또는 STOP
|
||||
public AgvSpeed? MoveSpeed { get; set; }
|
||||
public AgvSts? MoveDiv { get; set; }
|
||||
public UInt32 Idx { get; set; }
|
||||
public bool Changed { get; set; }
|
||||
public DateTime CreateTime { 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
HMI/SubProject/AGVControl/Models/CustomLine.cs
Normal file
14
HMI/SubProject/AGVControl/Models/CustomLine.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System.Drawing;
|
||||
using System;
|
||||
|
||||
|
||||
namespace AGVControl.Models
|
||||
{
|
||||
public class CustomLine
|
||||
{
|
||||
public Point StartPoint { get; set; }
|
||||
public Point EndPoint { get; set; }
|
||||
public Color LineColor { get; set; }
|
||||
public int LineWidth { get; set; }
|
||||
}
|
||||
}
|
||||
86
HMI/SubProject/AGVControl/Models/MagnetLine.cs
Normal file
86
HMI/SubProject/AGVControl/Models/MagnetLine.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using System.Drawing;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace AGVControl.Models
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 도로특성정보
|
||||
/// </summary>
|
||||
public class RoadInformation
|
||||
{
|
||||
/// <summary>
|
||||
/// 시작지점
|
||||
/// </summary>
|
||||
public RFIDPoint P1 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 종료지점
|
||||
/// </summary>
|
||||
public RFIDPoint P2 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 도로의 사용여부
|
||||
/// </summary>
|
||||
public bool Enable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// AGV의 이동방향(리프트방향)
|
||||
/// 목적지 방향과의 일치를 위해 해당 방향을 설정할 수 있따
|
||||
/// </summary>
|
||||
public AgvDir? LiftDirection { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// AGV이동시 속도 (high, middle, low)
|
||||
/// </summary>
|
||||
public AgvSpeed? MoveSpeed { get; set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// AGV이동시 방향모드(좌분기, 전진, 우분기)
|
||||
/// </summary>
|
||||
public AgvSts? MoveDirection { get; set; }
|
||||
|
||||
public RoadInformation()
|
||||
{
|
||||
P1 = null;
|
||||
P2 = null;
|
||||
LiftDirection = null;
|
||||
MoveSpeed = null;
|
||||
MoveDirection = null;
|
||||
Enable = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 값이 설정되어있는지
|
||||
/// </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; }
|
||||
public Point EndPoint { get; set; }
|
||||
public List<Point> BranchPoints { get; set; }
|
||||
public Dictionary<Point, BranchDirection> BranchDirections { get; set; }
|
||||
|
||||
public MagnetLine()
|
||||
{
|
||||
BranchPoints = new List<Point>();
|
||||
BranchDirections = new Dictionary<Point, BranchDirection>();
|
||||
}
|
||||
}
|
||||
}
|
||||
13
HMI/SubProject/AGVControl/Models/MapElements.cs
Normal file
13
HMI/SubProject/AGVControl/Models/MapElements.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System.Drawing;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AGVControl.Models
|
||||
{
|
||||
public enum BranchDirection
|
||||
{
|
||||
Left,
|
||||
Straight,
|
||||
Right
|
||||
}
|
||||
}
|
||||
63
HMI/SubProject/AGVControl/Models/MapText.cs
Normal file
63
HMI/SubProject/AGVControl/Models/MapText.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using System.Drawing;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
namespace AGVControl.Models
|
||||
{
|
||||
public class MapText
|
||||
{
|
||||
private bool _dirty = true;
|
||||
private Point _location;
|
||||
private string _text;
|
||||
private Font _font;
|
||||
|
||||
public bool Dirty
|
||||
{
|
||||
get => _dirty;
|
||||
set => _dirty = value;
|
||||
}
|
||||
|
||||
public Point Location
|
||||
{
|
||||
get => _location;
|
||||
set
|
||||
{
|
||||
if (_location != value)
|
||||
{
|
||||
_location = value;
|
||||
_dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string Text
|
||||
{
|
||||
get => _text;
|
||||
set
|
||||
{
|
||||
if (_text != value)
|
||||
{
|
||||
_text = value;
|
||||
_dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Color TextColor { get; set; }
|
||||
public Color BackgroundColor { get; set; }
|
||||
|
||||
public Font Font
|
||||
{
|
||||
get => _font;
|
||||
set
|
||||
{
|
||||
if (_font != value)
|
||||
{
|
||||
_font = value;
|
||||
_dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public RectangleF Bounds { get; set; }
|
||||
}
|
||||
}
|
||||
23
HMI/SubProject/AGVControl/Models/PathResult.cs
Normal file
23
HMI/SubProject/AGVControl/Models/PathResult.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using AGVControl.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace AGVControl
|
||||
{
|
||||
public class PathResult
|
||||
|
||||
{
|
||||
public bool Success
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path != null && Path.Any();
|
||||
}
|
||||
}
|
||||
public string Message { get; set; }
|
||||
public List<RFIDPoint> Path { get; set; }
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
214
HMI/SubProject/AGVControl/Models/RFIDConnection.cs
Normal file
214
HMI/SubProject/AGVControl/Models/RFIDConnection.cs
Normal file
@@ -0,0 +1,214 @@
|
||||
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; }
|
||||
|
||||
/// <summary>
|
||||
/// 도로의 사용여부
|
||||
/// </summary>
|
||||
public bool EnableP { get; set; }
|
||||
public bool EnableN { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// AGV의 이동방향(리프트방향)
|
||||
/// 목적지 방향과의 일치를 위해 해당 방향을 설정할 수 있따
|
||||
/// </summary>
|
||||
public AgvDir? LiftDirectionP { get; set; }
|
||||
public AgvDir? LiftDirectionN { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// AGV이동시 속도 (high, middle, low)
|
||||
/// </summary>
|
||||
public AgvSpeed? MoveSpeedP { get; set; }
|
||||
public AgvSpeed? MoveSpeedN { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// AGV이동시 방향모드(좌분기, 전진, 우분기)
|
||||
/// </summary>
|
||||
public AgvSts? MoveDirectionP { get; set; }
|
||||
public AgvSts? 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 = ushort.Parse(buf[4]);
|
||||
var p2v = ushort.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 = (AgvDir)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 = (AgvSts)int.Parse(StrP[3]);
|
||||
|
||||
//Negative
|
||||
this.EnableN = StrN[0] == "1";
|
||||
|
||||
if (StrN[1].isEmpty()) LiftDirectionN = null;
|
||||
else LiftDirectionN = (AgvDir)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 = (AgvSts)int.Parse(StrN[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.EnableP = buf[6] == "1";
|
||||
|
||||
if (buf[7].isEmpty()) LiftDirectionP = null;
|
||||
else LiftDirectionP = (AgvDir)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 = (AgvSts)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)
|
||||
{
|
||||
if (obj is RFIDConnection other)
|
||||
{
|
||||
return (P1 == other.P1 && P2 == other.P2);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return P1.GetHashCode() ^ P2.GetHashCode();
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
//연결정보를 확인
|
||||
return $"{P1.Value} ↔ {P2.Value},ENB:{(EnableP ? "O" : "X")}|{(EnableN ? "O" : "X")}";
|
||||
}
|
||||
}
|
||||
}
|
||||
30
HMI/SubProject/AGVControl/Models/RFIDLine.cs
Normal file
30
HMI/SubProject/AGVControl/Models/RFIDLine.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System.Drawing;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AGVControl.Models
|
||||
{
|
||||
public class RFIDLine
|
||||
{
|
||||
public Point StartPoint { get; set; }
|
||||
public Point EndPoint { get; set; }
|
||||
|
||||
public float Distance
|
||||
{
|
||||
get {
|
||||
float dx = StartPoint.X - EndPoint.X;
|
||||
float dy = StartPoint.Y - EndPoint.Y;
|
||||
return (float)Math.Sqrt(dx * dx + dy * dy); // double을 float로 명시적 캐스팅
|
||||
}
|
||||
}
|
||||
|
||||
//public uint StartRFID { get; set; }
|
||||
//public uint EndRFID { get; set; }
|
||||
//public bool IsBidirectional { get; set; } = true; // 양방향 이동 가능 여부
|
||||
//public float Distance { get; set; } // 두 RFID 포인트 사이의 거리
|
||||
|
||||
//public List<uint> ConnectedRFIDs { get; set; } = new List<uint>(); // 연결된 모든 RFID 값들
|
||||
//public Dictionary<uint, uint> NextRFID { get; set; } = new Dictionary<uint, uint>(); // 각 RFID의 다음 RFID
|
||||
//public Dictionary<uint, uint> PrevRFID { get; set; } = new Dictionary<uint, uint>(); // 각 RFID의 이전 RFID
|
||||
}
|
||||
}
|
||||
59
HMI/SubProject/AGVControl/Models/RFIDPoint.cs
Normal file
59
HMI/SubProject/AGVControl/Models/RFIDPoint.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using System.Drawing;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
namespace AGVControl.Models
|
||||
{
|
||||
public class RFIDPoint
|
||||
{
|
||||
public Point Location { get; set; }
|
||||
public ushort Value { get; set; }
|
||||
public string NextRFID { get; set; } // 다음 RFID 포인트의 값
|
||||
public bool IsBidirectional { get; set; } // 양방향 연결 여부
|
||||
public bool IsRotatable { get; set; } // 회전 가능 여부
|
||||
public AgvDir? FixedDirection { get; set; } // 고정 방향(없으면 null)
|
||||
public bool IsTerminal { get; set; } // 종단 여부
|
||||
public bool NeedTurn { get; set; }
|
||||
|
||||
public bool TurnStop { get; set; }
|
||||
public bool TurnOK { get; set; }
|
||||
public DateTime TurnStart { get; set; }
|
||||
public DateTime TurnEnd { get; set; }
|
||||
|
||||
[Browsable(false)]
|
||||
public RectangleF Bounds { get; set; }
|
||||
public void Clear()
|
||||
{
|
||||
this.Location = Point.Empty;
|
||||
this.Value = 0;
|
||||
TurnStop = false;
|
||||
TurnOK = false;
|
||||
TurnStart = new DateTime(1982, 11, 23);
|
||||
TurnEnd = new DateTime(1982, 11, 23);
|
||||
}
|
||||
|
||||
public bool IsEmpty
|
||||
{
|
||||
get
|
||||
{
|
||||
//RFID값이나 위치 값이 없으면 비어있는 것으로 한다.
|
||||
if (this.Location.IsEmpty) return true;
|
||||
if ((this.Value < 1)) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public RFIDPoint()
|
||||
{
|
||||
IsRotatable = false; // 기본값은 회전 불가능
|
||||
IsBidirectional = true; // 기본값은 양방향
|
||||
FixedDirection = null;
|
||||
IsTerminal = false; // 기본값은 종단 아님
|
||||
Clear();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"[RFIDPoint] {Value},P:{Location.X},{Location.Y}";
|
||||
}
|
||||
}
|
||||
}
|
||||
34
HMI/SubProject/AGVControl/Models/ToolBarItem.cs
Normal file
34
HMI/SubProject/AGVControl/Models/ToolBarItem.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System.Drawing;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace AGVControl.Models
|
||||
{
|
||||
public class ToolBarItem
|
||||
{
|
||||
private bool _ishovering = false;
|
||||
public int Idx { get; set; }
|
||||
public Rectangle Bounds { get; set; }
|
||||
public bool isHovering
|
||||
{
|
||||
get { return _ishovering; }
|
||||
set
|
||||
{
|
||||
Dirty = _ishovering != value;
|
||||
_ishovering = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string Title { get; set; }
|
||||
public bool Dirty { get; private set; }
|
||||
|
||||
public ToolBarItem()
|
||||
{
|
||||
Bounds = Rectangle.Empty;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
72
HMI/SubProject/AGVControl/Models/enumStruct.cs
Normal file
72
HMI/SubProject/AGVControl/Models/enumStruct.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AGVControl
|
||||
{
|
||||
/// <summary>
|
||||
/// 실제 AGV컨트롤러의 STS값에는 F,B의 값이 들어있고
|
||||
/// 아래 항목은 해당 문자의 ASCII코드값이다 첫자를 byte로 변경하고 변환하면 된다
|
||||
/// </summary>
|
||||
public enum AgvDir : byte
|
||||
{
|
||||
Forward = 0x46,
|
||||
Backward = 0x42,
|
||||
}
|
||||
|
||||
public enum AGVMoveState
|
||||
{
|
||||
Stop = 0,
|
||||
Run
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 실제 AGV컨트롤러의 STS값에는 H,L,M,S의 값이 들어있고
|
||||
/// 아래 항목은 해당 문자의 ASCII코드값이다 첫자를 byte로 변경하고 변환하면 된다
|
||||
/// </summary>
|
||||
public enum AgvSpeed : byte
|
||||
{
|
||||
High = 0x48,
|
||||
Middle = 0x4D,
|
||||
Low = 0x4C,
|
||||
MarkStop = 0x53,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// STS : S,L,R
|
||||
/// </summary>
|
||||
public enum AgvSts : byte
|
||||
{
|
||||
Straight = 0x53,
|
||||
Left = 0x4c,
|
||||
Right = 0x052,
|
||||
}
|
||||
|
||||
public enum AGVActionReasonCode
|
||||
{
|
||||
Unknown = 0,
|
||||
NoPosition, // 위치 미확정(처음 기동)
|
||||
NoPath, // 경로 없음 또는 현재 위치 미확정
|
||||
NotOnPath, // 현재 위치가 경로에 없음
|
||||
Arrived, // 경로의 마지막 지점(목적지 도달)
|
||||
Normal, // 정상(다음 RFID 있음)
|
||||
|
||||
/// <summary>
|
||||
/// 방향전환을 위한 턴이다
|
||||
/// </summary>
|
||||
NeedTurnMove,
|
||||
|
||||
/// <summary>
|
||||
/// 지정된 RFID위치에서 TURN이 요청되었다
|
||||
/// </summary>
|
||||
NeedTurnPoint,
|
||||
NoTurnPoint,
|
||||
PathCalcError,
|
||||
NoDirection,
|
||||
MoveForTurn,
|
||||
busy,
|
||||
WaitForMarkStop,
|
||||
}
|
||||
}
|
||||
37
HMI/SubProject/AGVControl/MyRadioButton.Designer.cs
generated
Normal file
37
HMI/SubProject/AGVControl/MyRadioButton.Designer.cs
generated
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
namespace AGVControl
|
||||
{
|
||||
partial class MyRadioButton
|
||||
{
|
||||
/// <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 구성 요소 디자이너에서 생성한 코드
|
||||
|
||||
/// <summary>
|
||||
/// 디자이너 지원에 필요한 메서드입니다.
|
||||
/// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
88
HMI/SubProject/AGVControl/MyRadioButton.cs
Normal file
88
HMI/SubProject/AGVControl/MyRadioButton.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace AGVControl
|
||||
{
|
||||
public partial class MyRadioButton : RadioButton
|
||||
{
|
||||
public int CheckWidth { get; set; } = 30;
|
||||
public Color CheckOnColor { get; set; } = Color.OrangeRed;
|
||||
public Color CheckOffColor { get; set; } = Color.DimGray;
|
||||
public Color Bordercolor { get; set; } = Color.DimGray;
|
||||
public int BorderSize { get; set; } = 2;
|
||||
public int BorderRadius { get; set; } = 7;
|
||||
public MyRadioButton()
|
||||
{
|
||||
InitializeComponent();
|
||||
// Set Optimized Double Buffer to reduce flickering
|
||||
this.SetStyle(ControlStyles.UserPaint, true);
|
||||
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
||||
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
|
||||
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
|
||||
|
||||
// Redraw when resized
|
||||
this.SetStyle(ControlStyles.ResizeRedraw, true);
|
||||
|
||||
this.Resize += arLabel_Resize;
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs pe)
|
||||
{
|
||||
pe.Graphics.InterpolationMode = InterpolationMode.High;
|
||||
pe.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
pe.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
|
||||
pe.Graphics.Clear(this.BackColor);
|
||||
|
||||
var XPosition = this.DisplayRectangle.Left;
|
||||
var YPosition = this.DisplayRectangle.Top;
|
||||
using (GraphicsPath Path = new GraphicsPath())
|
||||
{
|
||||
Path.AddLine(XPosition + BorderRadius, YPosition, XPosition + Width - (BorderRadius * 2), YPosition);
|
||||
Path.AddArc(XPosition + Width - (BorderRadius * 2), YPosition, BorderRadius * 2, BorderRadius * 2, 270, 90);
|
||||
Path.AddLine(XPosition + Width, YPosition + BorderRadius, XPosition + Width, YPosition + Height - (BorderRadius * 2));
|
||||
Path.AddArc(XPosition + Width - (BorderRadius * 2), YPosition + Height - (BorderRadius * 2), BorderRadius * 2, BorderRadius * 2, 0, 90);
|
||||
Path.AddLine(XPosition + Width - (BorderRadius * 2), YPosition + Height, XPosition + BorderRadius, YPosition + Height);
|
||||
Path.AddArc(XPosition, YPosition + Height - (BorderRadius * 2), BorderRadius * 2, BorderRadius * 2, 90, 90);
|
||||
Path.AddLine(XPosition, YPosition + Height - (BorderRadius * 2), XPosition, YPosition + BorderRadius);
|
||||
Path.AddArc(XPosition, YPosition, BorderRadius * 2, BorderRadius * 2, 180, 90);
|
||||
Path.CloseFigure();
|
||||
|
||||
|
||||
|
||||
|
||||
var r1 = new Rectangle(
|
||||
DisplayRectangle.Left, DisplayRectangle.Top,
|
||||
CheckWidth,
|
||||
DisplayRectangle.Height - 1);
|
||||
var r2 = new Rectangle(r1.Right + 3, r1.Top, DisplayRectangle.Width - r1.Width - 3 - Padding.Right, r1.Height);
|
||||
var CC = Checked ? CheckOnColor : CheckOffColor;
|
||||
pe.Graphics.FillRectangle(new SolidBrush(CC), r1);
|
||||
StringFormat sf = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center };
|
||||
if (this.TextAlign == ContentAlignment.MiddleLeft) sf.Alignment = StringAlignment.Near;
|
||||
else if (this.TextAlign == ContentAlignment.MiddleRight) sf.Alignment = StringAlignment.Far;
|
||||
pe.Graphics.DrawString(this.Text, this.Font, new SolidBrush(ForeColor), r2, sf);
|
||||
//pe.Graphics.DrawRectangle(new Pen(this.Bordercolor, this.BorderSize), DisplayRectangle);
|
||||
this.Region = new System.Drawing.Region(Path);
|
||||
|
||||
|
||||
pe.Graphics.DrawPath(new Pen(this.Bordercolor, this.BorderSize), Path);
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
void arLabel_Resize(object sender, EventArgs e)
|
||||
{
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
36
HMI/SubProject/AGVControl/Properties/AssemblyInfo.cs
Normal file
36
HMI/SubProject/AGVControl/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해
|
||||
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
|
||||
// 이러한 특성 값을 변경하세요.
|
||||
[assembly: AssemblyTitle("AGVControl")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("AGVControl")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에
|
||||
// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면
|
||||
// 해당 형식에 대해 ComVisible 특성을 true로 설정하세요.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다.
|
||||
[assembly: Guid("8cb883c0-99c3-4dd4-b017-f9b92010a806")]
|
||||
|
||||
// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다.
|
||||
//
|
||||
// 주 버전
|
||||
// 부 버전
|
||||
// 빌드 번호
|
||||
// 수정 버전
|
||||
//
|
||||
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를
|
||||
// 기본값으로 할 수 있습니다.
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
73
HMI/SubProject/AGVControl/Properties/Resources.Designer.cs
generated
Normal file
73
HMI/SubProject/AGVControl/Properties/Resources.Designer.cs
generated
Normal file
@@ -0,0 +1,73 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 이 코드는 도구를 사용하여 생성되었습니다.
|
||||
// 런타임 버전:4.0.30319.42000
|
||||
//
|
||||
// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
|
||||
// 이러한 변경 내용이 손실됩니다.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace AGVControl.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("AGVControl.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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap ico_navi_40 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("ico_navi_40", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
124
HMI/SubProject/AGVControl/Properties/Resources.resx
Normal file
124
HMI/SubProject/AGVControl/Properties/Resources.resx
Normal file
@@ -0,0 +1,124 @@
|
||||
<?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>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="ico_navi_40" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\ico_navi_40.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
||||
BIN
HMI/SubProject/AGVControl/Resources/ico_navi_40.png
Normal file
BIN
HMI/SubProject/AGVControl/Resources/ico_navi_40.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 718 B |
37
HMI/SubProject/AGVControl/RoundButton.Designer.cs
generated
Normal file
37
HMI/SubProject/AGVControl/RoundButton.Designer.cs
generated
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
namespace AGVControl
|
||||
{
|
||||
partial class RoundButton
|
||||
{
|
||||
/// <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 구성 요소 디자이너에서 생성한 코드
|
||||
|
||||
/// <summary>
|
||||
/// 디자이너 지원에 필요한 메서드입니다.
|
||||
/// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
63
HMI/SubProject/AGVControl/RoundButton.cs
Normal file
63
HMI/SubProject/AGVControl/RoundButton.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace AGVControl
|
||||
{
|
||||
public partial class RoundButton : Button
|
||||
{
|
||||
public int CornerRadius { get; set; } = 7;
|
||||
public RoundButton()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// Set Optimized Double Buffer to reduce flickering
|
||||
this.SetStyle(ControlStyles.UserPaint, true);
|
||||
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
||||
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
|
||||
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
|
||||
|
||||
// Redraw when resized
|
||||
this.SetStyle(ControlStyles.ResizeRedraw, true);
|
||||
|
||||
this.Resize += arLabel_Resize;
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs pevent)
|
||||
{
|
||||
pevent.Graphics.InterpolationMode = InterpolationMode.High;
|
||||
pevent.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
pevent.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
|
||||
var XPosition = this.DisplayRectangle.Left;
|
||||
var YPosition = this.DisplayRectangle.Top;
|
||||
using (GraphicsPath Path = new GraphicsPath())
|
||||
{
|
||||
Path.AddLine(XPosition + CornerRadius, YPosition, XPosition + Width - (CornerRadius * 2), YPosition);
|
||||
Path.AddArc(XPosition + Width - (CornerRadius * 2), YPosition, CornerRadius * 2, CornerRadius * 2, 270, 90);
|
||||
Path.AddLine(XPosition + Width, YPosition + CornerRadius, XPosition + Width, YPosition + Height - (CornerRadius * 2));
|
||||
Path.AddArc(XPosition + Width - (CornerRadius * 2), YPosition + Height - (CornerRadius * 2), CornerRadius * 2, CornerRadius * 2, 0, 90);
|
||||
Path.AddLine(XPosition + Width - (CornerRadius * 2), YPosition + Height, XPosition + CornerRadius, YPosition + Height);
|
||||
Path.AddArc(XPosition, YPosition + Height - (CornerRadius * 2), CornerRadius * 2, CornerRadius * 2, 90, 90);
|
||||
Path.AddLine(XPosition, YPosition + Height - (CornerRadius * 2), XPosition, YPosition + CornerRadius);
|
||||
Path.AddArc(XPosition, YPosition, CornerRadius * 2, CornerRadius * 2, 180, 90);
|
||||
Path.CloseFigure();
|
||||
this.Region = new System.Drawing.Region(Path);
|
||||
}
|
||||
base.OnPaint(pevent);
|
||||
}
|
||||
|
||||
void arLabel_Resize(object sender, EventArgs e)
|
||||
{
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
36
HMI/SubProject/AGVControl/ValueSelect.Designer.cs
generated
Normal file
36
HMI/SubProject/AGVControl/ValueSelect.Designer.cs
generated
Normal file
@@ -0,0 +1,36 @@
|
||||
namespace AGVControl
|
||||
{
|
||||
partial class ValueSelect
|
||||
{
|
||||
/// <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 구성 요소 디자이너에서 생성한 코드
|
||||
|
||||
/// <summary>
|
||||
/// 디자이너 지원에 필요한 메서드입니다.
|
||||
/// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
262
HMI/SubProject/AGVControl/ValueSelect.cs
Normal file
262
HMI/SubProject/AGVControl/ValueSelect.cs
Normal file
@@ -0,0 +1,262 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace AGVControl
|
||||
{
|
||||
public partial class ValueSelect : Control
|
||||
{
|
||||
public ValueSelect()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// Set Optimized Double Buffer to reduce flickering
|
||||
this.SetStyle(ControlStyles.UserPaint, true);
|
||||
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
||||
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
|
||||
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
|
||||
|
||||
// Redraw when resized
|
||||
this.SetStyle(ControlStyles.ResizeRedraw, true);
|
||||
this.Resize += arLabel_Resize;
|
||||
this.MouseClick += ValueSelect_MouseClick;
|
||||
this.MouseEnter += (s1, e1) => { this.Cursor = Cursors.Hand; };
|
||||
this.MouseLeave += (s1, e1) => { this.Cursor = Cursors.Default; };
|
||||
}
|
||||
|
||||
private void ValueSelect_MouseClick(object sender, MouseEventArgs e)
|
||||
{
|
||||
//마우스클릭
|
||||
if (rectLButton.IsEmpty == false && rectLButton.Contains(e.Location))
|
||||
{
|
||||
if (SideButtonClickValue != 0.0)
|
||||
{
|
||||
var newvalue = this.Value - SideButtonClickValue;
|
||||
if (newvalue < MinValue) newvalue = MinValue;
|
||||
this.Value = newvalue;
|
||||
}
|
||||
|
||||
if (ButtonClick != null) ButtonClick(this, new ButtonClickEventArgs(MouseButtons.Left));
|
||||
}
|
||||
|
||||
|
||||
if (rectRButton.IsEmpty == false && rectRButton.Contains(e.Location))
|
||||
{
|
||||
if (SideButtonClickValue != 0.0)
|
||||
{
|
||||
var newvalue = this.Value + SideButtonClickValue;
|
||||
if (newvalue > MaxValue) newvalue = MaxValue;
|
||||
this.Value = newvalue;
|
||||
}
|
||||
|
||||
if (ButtonClick != null) ButtonClick(this, new ButtonClickEventArgs(MouseButtons.Right));
|
||||
}
|
||||
|
||||
|
||||
if (rectCButton.IsEmpty == false && rectCButton.Contains(e.Location))
|
||||
if (ButtonClick != null) ButtonClick(this, new ButtonClickEventArgs(MouseButtons.Middle));
|
||||
}
|
||||
|
||||
private Rectangle rectLButton;
|
||||
private Rectangle rectRButton;
|
||||
private Rectangle rectCButton;
|
||||
private Boolean bMakeRect = true;
|
||||
|
||||
private double _minvalue = 0.0;
|
||||
private double _maxvalue = 9999999999.0;
|
||||
public double MinValue { get { return _minvalue; } set { _minvalue = value; Invalidate(); } }
|
||||
|
||||
public double MaxValue { get { return _maxvalue; } set { _maxvalue = value; Invalidate(); } }
|
||||
|
||||
|
||||
|
||||
private UInt16 _decimalposition = 0;
|
||||
private string _buttonwdith = string.Empty;
|
||||
private double _value = 0;
|
||||
private Color _border = Color.Lime;
|
||||
private double buttongabp;
|
||||
public double SideButtonClickValue { get { return buttongabp; } set { buttongabp = value; Invalidate(); } }
|
||||
|
||||
private Color _backbutton = Color.White;
|
||||
private Color _sidebutto = Color.Black;
|
||||
|
||||
public Color BackColorButton { get { return _backbutton; } set { _backbutton = value; Invalidate(); } }
|
||||
public Color ForeColorButton { get { return _sidebutto; } set { _sidebutto = value; Invalidate(); } }
|
||||
|
||||
|
||||
|
||||
public Color ColorBorder { get { return _border; } set { _border = value; Invalidate(); } }
|
||||
|
||||
public override string Text
|
||||
{
|
||||
get => Value.ToString();
|
||||
set
|
||||
{
|
||||
if (double.TryParse(value, out double dblval) == true)
|
||||
this.Value = dblval;
|
||||
}
|
||||
}
|
||||
|
||||
public double Value
|
||||
{
|
||||
get { return _value; }
|
||||
set
|
||||
{
|
||||
if (_value != value)
|
||||
{
|
||||
//이 값이 범위를 초과했는지 확인
|
||||
if (value < MinValue)
|
||||
{
|
||||
_value = MinValue;
|
||||
//throw new Exception(string.Format("입력값이 컨트롤의 최소값보다 작습니다(입력:{0},최소값:{1})",value,MinValue));
|
||||
}
|
||||
else if (value > MaxValue)
|
||||
{
|
||||
_value = MaxValue;
|
||||
//throw new Exception(string.Format("입력값이 컨트롤의 최대값보다 작습니다(입력:{0},최대값:{1})", value, MaxValue));
|
||||
}
|
||||
else
|
||||
{
|
||||
_value = value;
|
||||
|
||||
}
|
||||
Invalidate();
|
||||
if (ValueChanged != null) ValueChanged(this, new EventArgs());
|
||||
}
|
||||
}
|
||||
}
|
||||
public UInt16 DecimalPosition { get { return _decimalposition; } set { _decimalposition = value; Invalidate(); } }
|
||||
public string ButtonWidth { get { return _buttonwdith; } set { _buttonwdith = value; Invalidate(); } }
|
||||
|
||||
private string _nulldisplay = string.Empty;
|
||||
public string NullDisplay { get { return _nulldisplay; } set { _nulldisplay = value; Invalidate(); } }
|
||||
|
||||
private Font _sidefont;
|
||||
public Font FontSideButton { get { if (_sidefont == null) return this.Font; else return _sidefont; } set { _sidefont = value; Invalidate(); } }
|
||||
|
||||
void arLabel_Resize(object sender, EventArgs e)
|
||||
{
|
||||
this.bMakeRect = true;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
public class ButtonClickEventArgs : EventArgs
|
||||
{
|
||||
public MouseButtons Button;
|
||||
public ButtonClickEventArgs(MouseButtons button)
|
||||
{
|
||||
this.Button = button;
|
||||
// Console.WriteLine("button clickc : " +button.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler<ButtonClickEventArgs> ButtonClick;
|
||||
public event EventHandler ValueChanged;
|
||||
|
||||
protected override void OnPaint(PaintEventArgs pe)
|
||||
{
|
||||
//base.OnPaint(pe);
|
||||
if (bMakeRect) MakeRect();
|
||||
|
||||
|
||||
|
||||
StringFormat sf = new StringFormat();
|
||||
sf.Alignment = StringAlignment.Center;
|
||||
sf.LineAlignment = StringAlignment.Center;
|
||||
sf.Trimming = StringTrimming.None;
|
||||
sf.FormatFlags = StringFormatFlags.NoWrap;
|
||||
|
||||
//좌측버튼표시
|
||||
if (rectLButton.IsEmpty == false)
|
||||
{
|
||||
pe.Graphics.FillRectangle(new SolidBrush(BackColorButton), rectLButton);
|
||||
pe.Graphics.DrawString("<<", this.FontSideButton, new SolidBrush(this.ForeColorButton), rectLButton, sf);
|
||||
}
|
||||
|
||||
if (rectRButton.IsEmpty == false)
|
||||
{
|
||||
pe.Graphics.FillRectangle(new SolidBrush(BackColorButton), rectRButton);
|
||||
pe.Graphics.DrawString(">>", this.FontSideButton, new SolidBrush(this.ForeColorButton), rectRButton, sf);
|
||||
}
|
||||
|
||||
//값표시
|
||||
string valuestr;
|
||||
if (Value == 0.0 && string.IsNullOrEmpty(NullDisplay) == false)
|
||||
valuestr = NullDisplay;
|
||||
else
|
||||
valuestr = Value.ToString("N" + DecimalPosition.ToString());
|
||||
|
||||
pe.Graphics.FillRectangle(new SolidBrush(BackColor), rectCButton);
|
||||
pe.Graphics.DrawString(valuestr, this.Font, new SolidBrush(this.ForeColor), rectCButton, sf);
|
||||
sf.Dispose();
|
||||
|
||||
|
||||
//테두리표시
|
||||
if (rectLButton.IsEmpty == false)
|
||||
pe.Graphics.DrawRectangle(new Pen(ColorBorder), rectLButton);
|
||||
if (rectRButton.IsEmpty == false)
|
||||
pe.Graphics.DrawRectangle(new Pen(ColorBorder), rectRButton);
|
||||
pe.Graphics.DrawRectangle(new Pen(ColorBorder), rectCButton);
|
||||
}
|
||||
|
||||
void MakeRect()
|
||||
{
|
||||
int bWidth;
|
||||
if (string.IsNullOrEmpty(ButtonWidth) == false)
|
||||
{
|
||||
if (ButtonWidth.EndsWith("%"))
|
||||
{
|
||||
if (int.TryParse(ButtonWidth.Substring(0, ButtonWidth.Length - 1), out bWidth) == false)
|
||||
bWidth = 0; //숫자로 바꾸는거 실패
|
||||
else bWidth = (int)(this.DisplayRectangle.Width * (bWidth / 100.0));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (int.TryParse(ButtonWidth, out bWidth) == false)
|
||||
bWidth = 0;
|
||||
}
|
||||
}
|
||||
else bWidth = 0;
|
||||
|
||||
if (bWidth > 0)
|
||||
{
|
||||
int buttongap = 1;
|
||||
//각버튼간 2px 간격을 띄운다.
|
||||
bWidth = bWidth - buttongap * 2;
|
||||
rectLButton = new Rectangle(
|
||||
DisplayRectangle.Left,
|
||||
DisplayRectangle.Top,
|
||||
bWidth,
|
||||
DisplayRectangle.Height - 1);
|
||||
|
||||
rectCButton = new Rectangle(
|
||||
rectLButton.Right + buttongap,
|
||||
DisplayRectangle.Top,
|
||||
DisplayRectangle.Width - rectLButton.Width * 2 - buttongap * 2,
|
||||
DisplayRectangle.Height - 1);
|
||||
|
||||
rectRButton = new Rectangle(
|
||||
rectCButton.Right + buttongap,
|
||||
DisplayRectangle.Top,
|
||||
bWidth - 1,
|
||||
DisplayRectangle.Height - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
rectLButton = Rectangle.Empty;
|
||||
rectRButton = Rectangle.Empty;
|
||||
rectCButton = new Rectangle(DisplayRectangle.Left,
|
||||
DisplayRectangle.Top,
|
||||
DisplayRectangle.Width - 1,
|
||||
DisplayRectangle.Height - 1);
|
||||
}
|
||||
bMakeRect = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
153
HMI/SubProject/AGVControl/agvControl.csproj
Normal file
153
HMI/SubProject/AGVControl/agvControl.csproj
Normal file
@@ -0,0 +1,153 @@
|
||||
<?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>{8CB883C0-99C3-4DD4-B017-F9B92010A806}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>AGVControl</RootNamespace>
|
||||
<AssemblyName>AGVControl</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="arCommUtil">
|
||||
<HintPath>..\..\..\DLL\arCommUtil.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<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="GridView\ColorListItem.cs" />
|
||||
<Compile Include="GridView\GridItem.cs" />
|
||||
<Compile Include="GridView\GridView.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="GridView\GridView.Designer.cs">
|
||||
<DependentUpon>GridView.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="MapControlManager.cs" />
|
||||
<Compile Include="Models\AGVActionPrediction.cs" />
|
||||
<Compile Include="BatteryLevelGauge.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="BatteryLevelGauge.Designer.cs">
|
||||
<DependentUpon>BatteryLevelGauge.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="GuideSensor.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="GuideSensor.Designer.cs">
|
||||
<DependentUpon>GuideSensor.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="MapControl.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MapControl.Designer.cs">
|
||||
<DependentUpon>MapControl.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Models\AGV.cs" />
|
||||
<Compile Include="Models\CustomLine.cs" />
|
||||
<Compile Include="Models\enumStruct.cs" />
|
||||
<Compile Include="Models\MagnetLine.cs" />
|
||||
<Compile Include="Models\MapElements.cs" />
|
||||
<Compile Include="Models\MapText.cs" />
|
||||
<Compile Include="Models\PathResult.cs" />
|
||||
<Compile Include="Models\RFIDLine.cs" />
|
||||
<Compile Include="Models\RFIDPoint.cs" />
|
||||
<Compile Include="Models\ToolBarItem.cs" />
|
||||
<Compile Include="MyRadioButton.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MyRadioButton.Designer.cs">
|
||||
<DependentUpon>MyRadioButton.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Models\RFIDConnection.cs" />
|
||||
<Compile Include="RoundButton.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="RoundButton.Designer.cs">
|
||||
<DependentUpon>RoundButton.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ValueSelect.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ValueSelect.Designer.cs">
|
||||
<DependentUpon>ValueSelect.cs</DependentUpon>
|
||||
</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>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CommData\CommData.csproj">
|
||||
<Project>{14e8c9a5-013e-49ba-b435-efefc77dd623}</Project>
|
||||
<Name>CommData</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\ico_navi_40.png" />
|
||||
<None Include="sample.route" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
105
HMI/SubProject/AGVControl/sample.route
Normal file
105
HMI/SubProject/AGVControl/sample.route
Normal file
@@ -0,0 +1,105 @@
|
||||
[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
|
||||
[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
|
||||
[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
|
||||
[CUSTOM_LINES]
|
||||
54
HMI/SubProject/CommData/CommData.csproj
Normal file
54
HMI/SubProject/CommData/CommData.csproj
Normal file
@@ -0,0 +1,54 @@
|
||||
<?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>{14E8C9A5-013E-49BA-B435-EFEFC77DD623}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>VarData</RootNamespace>
|
||||
<AssemblyName>VarData</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Flag.cs" />
|
||||
<Compile Include="ISerialComm.cs" />
|
||||
<Compile Include="RS232.cs" />
|
||||
<Compile Include="Var.cs" />
|
||||
<Compile Include="Enum.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
217
HMI/SubProject/CommData/Enum.cs
Normal file
217
HMI/SubProject/CommData/Enum.cs
Normal file
@@ -0,0 +1,217 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace COMM
|
||||
{
|
||||
public enum eVarInt32
|
||||
{
|
||||
PickOnCount = 0,
|
||||
PickOfCount,
|
||||
LPickOnCount,
|
||||
SumQty,
|
||||
ChargeWaitSec,
|
||||
SyncItemCount,
|
||||
PathValidationError,
|
||||
}
|
||||
public enum eVarUInt32
|
||||
{
|
||||
Spare=0,
|
||||
}
|
||||
|
||||
public enum eVarDBL
|
||||
{
|
||||
LeftJogSpeed,
|
||||
RightJogSpeed,
|
||||
CurrentLeftJogSpeed,
|
||||
CurrentRightJogSpeed,
|
||||
SpeedOffsetCW,
|
||||
SpeedOffsetCCW,
|
||||
MaxSpeedCW,
|
||||
MaxSpeedCCW,
|
||||
SQLConnection,
|
||||
}
|
||||
|
||||
public enum eVarByte
|
||||
{
|
||||
None = 0,
|
||||
/// <summary>
|
||||
/// 충전명련전송횟수
|
||||
/// </summary>
|
||||
CHARGE_CMDCNT,
|
||||
ButtonJog,
|
||||
DataIndex ,
|
||||
}
|
||||
|
||||
public enum eVarBool
|
||||
{
|
||||
//comm area start(0~31)
|
||||
None = 0,
|
||||
DebugMode,
|
||||
SQLCONN,
|
||||
|
||||
//plc area start (32~63)
|
||||
FLAG_STOPZ = 32,
|
||||
FLAG_SETUP,
|
||||
FLAG_SYNC,
|
||||
FLAG_WAIT,
|
||||
/// <summary>
|
||||
/// 상태머신이 동작중인가
|
||||
/// 장비동작은 AGV_RUN 플래그를 확인 하세요.
|
||||
/// </summary>
|
||||
FLAG_AUTORUN,
|
||||
FLAG_MANUALRUN,
|
||||
FLAG_LIMITHIGH,
|
||||
FLAG_LIMITLOW,
|
||||
FLAG_POWERLOSS,
|
||||
|
||||
/// <summary>
|
||||
/// AGV 진행방향(UP = backward, DOWN = forward)
|
||||
/// </summary>
|
||||
AGVDIR_BACK,
|
||||
|
||||
/// <summary>
|
||||
/// 마크센서가 감지되면 활성화됨
|
||||
/// (알림용으로도 쓰니 삭제 안됨)
|
||||
/// </summary>
|
||||
MARK_SENSOR,
|
||||
MARK_SENSOROFF,
|
||||
FLAG_LEFT_RUN,
|
||||
FLAG_RIGHT_RUN,
|
||||
FLAG_RUN_CMD,
|
||||
FLAG_GO_CHAGER,
|
||||
FLAG_NEXTSTOP_ALIGN,
|
||||
///NEXTSTOP_MARK,
|
||||
|
||||
/// <summary>
|
||||
/// mark 1 혹은 2 의 값이 들어오면 설정됨
|
||||
/// </summary>
|
||||
//SENSOR_MARK,
|
||||
CHG_POSERR,
|
||||
FLAG_CHARGEONA,
|
||||
FLAG_CHARGEONM,
|
||||
OVERLOAD,
|
||||
OVERLOADL,
|
||||
OVERLOADR,
|
||||
BATTERY_LOW,
|
||||
BATTERY_HIGH,
|
||||
MINSPACE,
|
||||
CHARGE_CMDCNT,
|
||||
CHARGE_READY,
|
||||
CHARGE_WAIT,
|
||||
|
||||
AGV_ERROR,
|
||||
WAIT_COVER_DOWN,
|
||||
WAIT_COVER_UP,
|
||||
EMERGENCY,
|
||||
|
||||
ITEMON,
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 충전시작명령을 전송했다
|
||||
/// </summary>
|
||||
WAIT_CHARGEACK,
|
||||
|
||||
//agv area start ( 64 ~ 95)
|
||||
DISABLE_AUTOCONN_XBEE,
|
||||
|
||||
//area start (96~127)
|
||||
|
||||
}
|
||||
|
||||
public enum eVarString
|
||||
{
|
||||
|
||||
MCStatus,
|
||||
DataIndex,
|
||||
StatusMessage,
|
||||
JOBType,
|
||||
JOBCustCode,
|
||||
SWVersion,
|
||||
ChargeCheckMsg,
|
||||
}
|
||||
|
||||
public enum eVarTime
|
||||
{
|
||||
LastConnTry_PLC,
|
||||
LastConn_PLC,
|
||||
LastRecv_PLC,
|
||||
|
||||
LastConnTry_XBE,
|
||||
LastConn_XBE,
|
||||
LastRecv_XBE,
|
||||
|
||||
LastConnTry_BAT,
|
||||
LastConn_BAT,
|
||||
LastRecv_BAT,
|
||||
LastSend_CMD,
|
||||
LastSend_BAT,
|
||||
|
||||
LastConnTry_AGV,
|
||||
LastConn_AGV,
|
||||
LastRecv_AGV,
|
||||
|
||||
/// <summary>
|
||||
/// 상태머신이 IDLE 전환시 설정
|
||||
/// </summary>
|
||||
IdleStart,
|
||||
/// <summary>
|
||||
/// 충전시도시 설정
|
||||
/// </summary>
|
||||
ChargeTry,
|
||||
/// <summary>
|
||||
/// 충전시작(확인)시 설정
|
||||
/// </summary>
|
||||
ChargeStart,
|
||||
|
||||
/// <summary>
|
||||
/// 충전종료시점
|
||||
/// </summary>
|
||||
ChargeEnd,
|
||||
/// <summary>
|
||||
/// 장비가동중 READY상태 전환시 설정
|
||||
/// </summary>
|
||||
ReadyStart,
|
||||
|
||||
MarkSensorOn,
|
||||
MarkSensorOff,
|
||||
|
||||
/// <summary>
|
||||
/// 상태머신이 RUN되는 경우에 설정
|
||||
/// 단 세부스텝이 READY 인 경우는 제외
|
||||
/// </summary>
|
||||
RunStart,
|
||||
|
||||
SendChargeOff,
|
||||
ChargeSearch,
|
||||
|
||||
BatWarnTime,
|
||||
IdleStopTime,
|
||||
StatusReporttime,
|
||||
|
||||
CheckGotoTargetSet,
|
||||
SendGotoCommand,
|
||||
|
||||
/// <summary>
|
||||
/// 마지막으로 멈춤 명령을 전송한 시간
|
||||
/// </summary>
|
||||
LastStopCommandTime,
|
||||
|
||||
/// <summary>
|
||||
/// 마지막으로 멈춤(마크스탑) 명령을 전송한 시간
|
||||
/// </summary>
|
||||
LastMarkStopCommandTime,
|
||||
|
||||
/// <summary>
|
||||
/// 마지막으로 턴 명령을 전송한 시간
|
||||
/// </summary>
|
||||
LastTurnCommandTime,
|
||||
|
||||
/// <summary>
|
||||
/// 마지막을 실행 명령을 전송한 시간
|
||||
/// </summary>
|
||||
LastRunCommandTime,
|
||||
}
|
||||
}
|
||||
108
HMI/SubProject/CommData/Flag.cs
Normal file
108
HMI/SubProject/CommData/Flag.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace COMM
|
||||
{
|
||||
public class Flag
|
||||
{
|
||||
public Boolean IsInit; //H/W설정이 안된경우에만 FALSE로 한다
|
||||
public string errorMessage;
|
||||
|
||||
public int PortCount;
|
||||
private UInt64 _value;
|
||||
private UInt64 _changed;
|
||||
public string[] Name;
|
||||
|
||||
public UInt64 Value { get { return _value; } }
|
||||
|
||||
public event EventHandler<ValueEventArgs> ValueChanged;
|
||||
public class ValueEventArgs : EventArgs
|
||||
{
|
||||
private int _arridx;
|
||||
private Boolean _oldvalue;
|
||||
private Boolean _newvalue;
|
||||
|
||||
public int ArrIDX { get { return _arridx; } }
|
||||
public Boolean OldValue { get { return _oldvalue; } }
|
||||
public Boolean NewValue { get { return _newvalue; } }
|
||||
|
||||
public ValueEventArgs(int arridx, Boolean oldvalue, Boolean newvalue)
|
||||
{
|
||||
_arridx = arridx;
|
||||
_oldvalue = oldvalue;
|
||||
_newvalue = newvalue;
|
||||
}
|
||||
}
|
||||
|
||||
public Flag(int pcnt)
|
||||
{
|
||||
if (pcnt > 64) throw new Exception("Max count is 64");
|
||||
PortCount = pcnt;
|
||||
IsInit = true;
|
||||
errorMessage = string.Empty;
|
||||
_value = 0;
|
||||
_changed = 0;
|
||||
Name = new string[PortCount];
|
||||
for (int i = 0; i < Name.Length; i++)
|
||||
{
|
||||
Name[i] = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public void writeValue(Int16 val)
|
||||
{
|
||||
var NewValue = (ulong)val;
|
||||
_changed = this._value ^ NewValue;
|
||||
this._value = NewValue;
|
||||
}
|
||||
|
||||
//private Boolean readValue(ref UInt64 value, int idx)
|
||||
//{
|
||||
// var offset = (UInt64)(1 << idx);
|
||||
// return ((value & offset) != 0);
|
||||
//}
|
||||
|
||||
public Boolean Get(int idx)
|
||||
{
|
||||
var offset = (UInt64)(1 << idx);
|
||||
return (_value & offset) != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 변경여부를 확인 합니다
|
||||
/// </summary>
|
||||
/// <param name="idx"></param>
|
||||
/// <returns></returns>
|
||||
public Boolean GetChanged(int idx)
|
||||
{
|
||||
var offset = (UInt64)(1 << idx);
|
||||
return (this._changed & offset) != 0;
|
||||
}
|
||||
|
||||
public void Set(int idx, Boolean value)
|
||||
{
|
||||
var oldvalue = Get(idx);
|
||||
|
||||
if (value)
|
||||
{
|
||||
var offset = (UInt64)(1 << idx);
|
||||
_value = _value | offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
var offset = (UInt64)(~(1 << idx));
|
||||
_value = _value & offset;
|
||||
}
|
||||
|
||||
if (oldvalue != value)
|
||||
{
|
||||
if (ValueChanged != null)
|
||||
ValueChanged(this, new ValueEventArgs(idx, oldvalue, value));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
18
HMI/SubProject/CommData/ISerialComm.cs
Normal file
18
HMI/SubProject/CommData/ISerialComm.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace arDev
|
||||
{
|
||||
/// <summary>
|
||||
/// 시리얼통신모듈의기본형태정의
|
||||
/// </summary>
|
||||
public interface ISerialComm
|
||||
{
|
||||
string PortName { get; set; }
|
||||
int BaudRate { get; set; }
|
||||
bool IsOpen { get; }
|
||||
string ErrorMessage { get; set; }
|
||||
|
||||
Boolean Open();
|
||||
Boolean Close();
|
||||
}
|
||||
}
|
||||
36
HMI/SubProject/CommData/Properties/AssemblyInfo.cs
Normal file
36
HMI/SubProject/CommData/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해
|
||||
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
|
||||
// 이러한 특성 값을 변경하세요.
|
||||
[assembly: AssemblyTitle("VarData")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("VarData")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2022")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에
|
||||
// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면
|
||||
// 해당 형식에 대해 ComVisible 특성을 true로 설정하세요.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다.
|
||||
[assembly: Guid("14e8c9a5-013e-49ba-b435-efefc77dd623")]
|
||||
|
||||
// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다.
|
||||
//
|
||||
// 주 버전
|
||||
// 부 버전
|
||||
// 빌드 번호
|
||||
// 수정 버전
|
||||
//
|
||||
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를
|
||||
// 기본값으로 할 수 있습니다.
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
493
HMI/SubProject/CommData/RS232.cs
Normal file
493
HMI/SubProject/CommData/RS232.cs
Normal file
@@ -0,0 +1,493 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace arDev
|
||||
{
|
||||
|
||||
public abstract partial class arRS232 : ISerialComm, IDisposable
|
||||
{
|
||||
protected System.IO.Ports.SerialPort _device;
|
||||
protected ManualResetEvent _mre;
|
||||
protected byte[] LastReceiveBuffer = new byte[] { };
|
||||
/// <summary>
|
||||
/// 최종 전송 메세지
|
||||
/// </summary>
|
||||
public byte[] lastSendBuffer = new byte[] { };
|
||||
//public int ValidCheckTimeMSec { get; set; } = 5000;
|
||||
protected List<byte> tempBuffer = new List<byte>();
|
||||
protected Boolean findSTX = false;
|
||||
public string ErrorMessage { get; set; }
|
||||
public DateTime LastConnTime { get; set; }
|
||||
public DateTime LastConnTryTime { get; set; }
|
||||
public DateTime lastSendTime;
|
||||
/// <summary>
|
||||
/// 메세지 수신시 사용하는 내부버퍼
|
||||
/// </summary>
|
||||
protected List<byte> _buffer = new List<byte>();
|
||||
/// <summary>
|
||||
/// 데이터조회간격(초)
|
||||
/// </summary>
|
||||
public float ScanInterval { get; set; }
|
||||
|
||||
// public byte[] LastRecvData;
|
||||
public string LastRecvString
|
||||
{
|
||||
get
|
||||
{
|
||||
if (LastReceiveBuffer == null) return String.Empty;
|
||||
else return System.Text.Encoding.Default.GetString(LastReceiveBuffer);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 마지막으로 데이터를 받은 시간
|
||||
/// </summary>
|
||||
public DateTime lastRecvTime;
|
||||
|
||||
|
||||
public int WriteError = 0;
|
||||
public string WriteErrorMessage = string.Empty;
|
||||
public int WaitTimeout { get; set; } = 1000;
|
||||
public int MinRecvLength { get; set; } = 1;
|
||||
/// <summary>
|
||||
/// 포트이름
|
||||
/// </summary>
|
||||
[Description("시리얼 포트 이름")]
|
||||
[Category("설정"), DisplayName("Port Name")]
|
||||
public string PortName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_device == null) return string.Empty;
|
||||
else return _device.PortName;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (this.IsOpen)
|
||||
{
|
||||
Message?.Invoke(this, new MessageEventArgs("포트가 열려있어 포트이름을 변경할 수 없습니다", true));
|
||||
}
|
||||
else if (String.IsNullOrEmpty(value) == false)
|
||||
_device.PortName = value;
|
||||
else
|
||||
{
|
||||
Message?.Invoke(this, new MessageEventArgs("No PortName", true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int BaudRate
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_device == null) return 0;
|
||||
else return _device.BaudRate;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (this.IsOpen)
|
||||
{
|
||||
Message?.Invoke(this, new MessageEventArgs("포트가 열려있어 BaudRate(를) 변경할 수 없습니다", true));
|
||||
}
|
||||
else if (value != 0)
|
||||
_device.BaudRate = value;
|
||||
else Message?.Invoke(this, new MessageEventArgs("No baud rate", true));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public arRS232()
|
||||
{
|
||||
_device = new System.IO.Ports.SerialPort();
|
||||
this.BaudRate = 9600;
|
||||
ScanInterval = 10;
|
||||
_device.DataReceived += barcode_DataReceived;
|
||||
_device.ErrorReceived += this.barcode_ErrorReceived;
|
||||
_device.WriteTimeout = 5000;
|
||||
_device.ReadTimeout = 5000;
|
||||
// _device.DtrEnable = false;
|
||||
_device.ReadBufferSize = 8192;
|
||||
_device.WriteBufferSize = 8192;
|
||||
|
||||
ErrorMessage = string.Empty;
|
||||
lastRecvTime = DateTime.Parse("1982-11-23");
|
||||
LastConnTime = DateTime.Parse("1982-11-23");
|
||||
LastConnTryTime = DateTime.Parse("1982-11-23");
|
||||
lastRecvTime = DateTime.Parse("1982-11-23");
|
||||
this._mre = new ManualResetEvent(true);
|
||||
}
|
||||
|
||||
~arRS232()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
|
||||
// Flag: Has Dispose already been called?
|
||||
bool disposed = false;
|
||||
|
||||
// Public implementation of Dispose pattern callable by consumers.
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
// Protected implementation of Dispose pattern.
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
// Free any other managed objects here.
|
||||
//
|
||||
}
|
||||
|
||||
_device.DataReceived -= barcode_DataReceived;
|
||||
_device.ErrorReceived -= this.barcode_ErrorReceived;
|
||||
|
||||
// Free any unmanaged objects here.
|
||||
//
|
||||
disposed = true;
|
||||
}
|
||||
|
||||
public Boolean Open()
|
||||
{
|
||||
try
|
||||
{
|
||||
_device.Open();
|
||||
return IsOpen;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ErrorMessage = ex.Message;
|
||||
Message.Invoke(this, new MessageEventArgs(ex.Message, true));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public string GetHexString(Byte[] input)
|
||||
{
|
||||
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
||||
foreach (byte b in input)
|
||||
sb.Append(" " + b.ToString("X2"));
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 포트가 열려있는지 확인
|
||||
/// </summary>
|
||||
[Description("현재 시리얼포트가 열려있는지 확인합니다")]
|
||||
[Category("정보"), DisplayName("Port Open")]
|
||||
public Boolean IsOpen
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_device == null) return false;
|
||||
return _device.IsOpen;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool Close()
|
||||
{
|
||||
if (_device != null && _device.IsOpen)
|
||||
{
|
||||
_device.DiscardInBuffer();
|
||||
_device.DiscardOutBuffer();
|
||||
_device.Close(); //dispose에서는 포트를 직접 클리어하지 않게 해뒀다.
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
protected Boolean RaiseRecvData()
|
||||
{
|
||||
return RaiseRecvData(LastReceiveBuffer.ToArray(), false);
|
||||
}
|
||||
/// <summary>
|
||||
/// 수신받은 메세지를 발생 시킵니다
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Boolean RaiseRecvData(byte[] Data, bool udpatelastbuffer)
|
||||
{
|
||||
//181206 - 최종수신 메세지 기록
|
||||
lastRecvTime = DateTime.Now;
|
||||
if (udpatelastbuffer && Data != null)
|
||||
{
|
||||
if (LastReceiveBuffer == null || LastReceiveBuffer.Length != Data.Length)
|
||||
{
|
||||
LastReceiveBuffer = new byte[Data.Length];
|
||||
Array.Copy(Data, LastReceiveBuffer, Data.Length);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Message?.Invoke(this, new MessageEventArgs(Data, true)); //recvmessage
|
||||
if (ProcessRecvData(Data) == false)
|
||||
{
|
||||
//Message?.Invoke(this, new MessageEventArgs(Data, true)); //recvmessage
|
||||
Message?.Invoke(this, new MessageEventArgs(this.ErrorMessage, true)); //errormessage
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.ErrorMessage = ex.Message;
|
||||
this.Message?.Invoke(this, new MessageEventArgs(ex.Message, true));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 수신받은 자료를 처리한다
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public abstract bool ProcessRecvData(byte[] data);
|
||||
|
||||
#region "Internal Events"
|
||||
|
||||
void barcode_ErrorReceived(object sender, System.IO.Ports.SerialErrorReceivedEventArgs e)
|
||||
{
|
||||
Message?.Invoke(this, new MessageEventArgs(e.ToString(), true));
|
||||
}
|
||||
|
||||
byte[] buffer = new byte[] { };
|
||||
void barcode_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
int ReadCount = _device.BytesToRead;
|
||||
|
||||
buffer = new byte[ReadCount];
|
||||
_device.Read(buffer, 0, buffer.Length);
|
||||
|
||||
System.Text.StringBuilder LogMsg = new StringBuilder();
|
||||
|
||||
byte[] remainBuffer;
|
||||
Repeat:
|
||||
if (CustomParser(buffer, out remainBuffer))
|
||||
{
|
||||
//분석완료이므로 받은 데이터를 버퍼에 기록한다
|
||||
if (LastReceiveBuffer == null || (LastReceiveBuffer.Length != tempBuffer.Count))
|
||||
Array.Resize(ref LastReceiveBuffer, tempBuffer.Count);
|
||||
Array.Copy(tempBuffer.ToArray(), LastReceiveBuffer, tempBuffer.Count);
|
||||
tempBuffer.Clear();
|
||||
|
||||
//수신메세지발생
|
||||
RaiseRecvData();
|
||||
if (remainBuffer != null && remainBuffer.Length > 0)
|
||||
{
|
||||
//버퍼를 변경해서 다시 전송을 해준다.
|
||||
Array.Resize(ref buffer, remainBuffer.Length);
|
||||
Array.Copy(remainBuffer, buffer, remainBuffer.Length);
|
||||
goto Repeat; //남은 버퍼가 있다면 진행을 해준다.
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//if (IsOpen)
|
||||
//{
|
||||
// //_device.DiscardInBuffer();
|
||||
// //_device.DiscardOutBuffer();
|
||||
//}
|
||||
ErrorMessage = ex.Message;
|
||||
this.Message?.Invoke(this, new MessageEventArgs(ex.Message, true));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region "External Events"
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 오류 및 기타 일반 메세지
|
||||
/// </summary>
|
||||
public event EventHandler<MessageEventArgs> Message;
|
||||
|
||||
#endregion
|
||||
|
||||
#region "Event Args"
|
||||
|
||||
/// <summary>
|
||||
/// 데이터를 수신할떄 사용함(RAW 포함)
|
||||
/// </summary>
|
||||
public class ReceiveDataEventArgs : EventArgs
|
||||
{
|
||||
private byte[] _buffer = null;
|
||||
|
||||
/// <summary>
|
||||
/// 바이트배열의 버퍼값
|
||||
/// </summary>
|
||||
public byte[] Value { get { return _buffer; } }
|
||||
|
||||
/// <summary>
|
||||
/// 버퍼(바이트배열)의 데이터를 문자로 반환합니다.
|
||||
/// </summary>
|
||||
public string StrValue
|
||||
{
|
||||
get
|
||||
{
|
||||
//return string.Empty;
|
||||
|
||||
if (_buffer == null || _buffer.Length < 1) return string.Empty;
|
||||
else return System.Text.Encoding.Default.GetString(_buffer);
|
||||
}
|
||||
}
|
||||
public ReceiveDataEventArgs(byte[] buffer)
|
||||
{
|
||||
_buffer = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 메세지를 강제 발생
|
||||
/// </summary>
|
||||
/// <param name="mt"></param>
|
||||
/// <param name="message"></param>
|
||||
protected virtual void RaiseMessage(MessageType mt, string message)
|
||||
{
|
||||
this.Message?.Invoke(this, new MessageEventArgs(mt, message));
|
||||
}
|
||||
public enum MessageType
|
||||
{
|
||||
Normal,
|
||||
Error,
|
||||
Send,
|
||||
Recv,
|
||||
}
|
||||
|
||||
public class MessageEventArgs : EventArgs
|
||||
{
|
||||
public MessageType MsgType { get; set; }
|
||||
private string _message = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Recv,Send,Normal,Error 모두 지원
|
||||
/// </summary>
|
||||
public string Message { get { return _message; } }
|
||||
|
||||
private byte[] _data = null;
|
||||
|
||||
/// <summary>
|
||||
/// Recv,Send에서만 값이 존재 합니다
|
||||
/// </summary>
|
||||
public byte[] Data { get { return _data; } }
|
||||
public MessageEventArgs(string Message, bool isError = false)
|
||||
{
|
||||
if (isError) MsgType = MessageType.Error;
|
||||
else MsgType = MessageType.Normal;
|
||||
_message = Message;
|
||||
}
|
||||
public MessageEventArgs(MessageType msgtype, string Message)
|
||||
{
|
||||
MsgType = msgtype;
|
||||
_message = Message;
|
||||
_data = System.Text.Encoding.Default.GetBytes(Message);
|
||||
}
|
||||
|
||||
public MessageEventArgs(byte[] buffer, bool isRecv = true)
|
||||
{
|
||||
if (isRecv) MsgType = MessageType.Recv;
|
||||
else MsgType = MessageType.Send;
|
||||
_data = new byte[buffer.Length];
|
||||
Array.Copy(buffer, _data, Data.Length);
|
||||
_message = System.Text.Encoding.Default.GetString(_data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
protected abstract bool CustomParser(byte[] buf, out byte[] remainBuffer);
|
||||
|
||||
/// <summary>
|
||||
/// 포트가 열려있거나 데이터 수신시간이 없는경우 false를 반환합니다
|
||||
/// </summary>
|
||||
public Boolean IsValid
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsOpen == false) return false;
|
||||
if (lastRecvTime.Year == 1982) return false;
|
||||
var ts = DateTime.Now - lastRecvTime;
|
||||
if (ts.TotalSeconds > (this.ScanInterval * 2.5)) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
protected bool WriteData(string cmd)
|
||||
{
|
||||
return WriteData(System.Text.Encoding.Default.GetBytes(cmd));
|
||||
}
|
||||
/// <summary>
|
||||
/// 포트에 쓰기(barcode_DataReceived 이벤트로 메세지수신)
|
||||
/// </summary>
|
||||
protected Boolean WriteData(byte[] data)
|
||||
{
|
||||
Boolean bRet = false;
|
||||
|
||||
//171205 : 타임아웃시간추가
|
||||
if (!_mre.WaitOne(WaitTimeout))
|
||||
{
|
||||
ErrorMessage = $"WriteData:MRE:WaitOne:TimeOut {WaitTimeout}ms";
|
||||
this.Message?.Invoke(this, new MessageEventArgs(ErrorMessage, true));
|
||||
return false;
|
||||
}
|
||||
|
||||
_mre.Reset();
|
||||
|
||||
//Array.Resize(ref data, data.Length + 2);
|
||||
|
||||
try
|
||||
{
|
||||
lastSendTime = DateTime.Now;
|
||||
if (lastSendBuffer == null) lastSendBuffer = new byte[data.Length]; //171113
|
||||
else Array.Resize(ref lastSendBuffer, data.Length);
|
||||
Array.Copy(data, lastSendBuffer, data.Length);
|
||||
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
_device.Write(data, i, 1);
|
||||
|
||||
//_device.Write(data, 0, data.Length);
|
||||
|
||||
//171113
|
||||
this.Message?.Invoke(this, new MessageEventArgs(data, false));
|
||||
|
||||
bRet = true;
|
||||
WriteError = 0;
|
||||
WriteErrorMessage = string.Empty;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// this.isinit = false;
|
||||
this.Message?.Invoke(this, new MessageEventArgs(ex.Message, true));
|
||||
bRet = false;
|
||||
WriteError += 1; //연속쓰기오류횟수
|
||||
WriteErrorMessage = ex.Message;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_mre.Set();
|
||||
}
|
||||
return bRet;
|
||||
}
|
||||
}
|
||||
}
|
||||
340
HMI/SubProject/CommData/Var.cs
Normal file
340
HMI/SubProject/CommData/Var.cs
Normal file
@@ -0,0 +1,340 @@
|
||||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.ComponentModel;
|
||||
//using System.Linq;
|
||||
//using System.Text;
|
||||
|
||||
//namespace COMM
|
||||
//{
|
||||
// public abstract class VarData<T> : INotifyPropertyChanged
|
||||
// {
|
||||
// protected T[] _values;
|
||||
// protected T defaultvalue;
|
||||
// protected string[] _code;
|
||||
// protected string[] _desc;
|
||||
|
||||
// public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
// protected void OnPropertyChanged(string name)
|
||||
// {
|
||||
// PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
|
||||
// }
|
||||
|
||||
// public T this[int idx]
|
||||
// {
|
||||
// get { return Get(idx); }
|
||||
// set { Set(idx, value); }
|
||||
// }
|
||||
|
||||
// public string StrType
|
||||
// {
|
||||
// get
|
||||
// {
|
||||
// return typeof(T).ToString();
|
||||
// }
|
||||
// }
|
||||
// public VarData(int capa, T defvalue = default(T))
|
||||
// {
|
||||
// _values = new T[capa];
|
||||
// _code = new string[capa];
|
||||
// _desc = new string[capa];
|
||||
|
||||
// defaultvalue = defvalue;
|
||||
// Clear();
|
||||
|
||||
// if (typeof(T) == typeof(UInt16)) SupportAdd = true;
|
||||
// else if (typeof(T) == typeof(UInt32)) SupportAdd = true;
|
||||
// else if (typeof(T) == typeof(Int16)) SupportAdd = true;
|
||||
// else if (typeof(T) == typeof(Int32)) SupportAdd = true;
|
||||
// else if (typeof(T) == typeof(Int64)) SupportAdd = true;
|
||||
// else if (typeof(T) == typeof(UInt64)) SupportAdd = true;
|
||||
// else if (typeof(T) == typeof(byte)) SupportAdd = true;
|
||||
// else if (typeof(T) == typeof(double)) SupportAdd = true;
|
||||
// else if (typeof(T) == typeof(Single)) SupportAdd = true;
|
||||
// else if (typeof(T) == typeof(string)) SupportAdd = false;
|
||||
// else if (typeof(T) == typeof(bool)) SupportAdd = false;
|
||||
// else if (typeof(T) == typeof(DateTime)) SupportAdd = false;
|
||||
// else throw new Exception($"Support Data Type : {typeof(T)}");
|
||||
// }
|
||||
|
||||
// public virtual void Set(int idx, T value)
|
||||
// {
|
||||
// var changed = _values[idx].Equals(value);
|
||||
// _values[idx] = value;
|
||||
// if (changed) OnPropertyChanged($"{idx}|{value}"); //idx값을 알림한다
|
||||
// }
|
||||
// public virtual T Get(int idx)
|
||||
// {
|
||||
// return _values[idx];
|
||||
// }
|
||||
|
||||
// public virtual void Clear(T value)
|
||||
// {
|
||||
// for (int i = 0; i < _values.Length; i++)
|
||||
// _values[i] = value;
|
||||
// }
|
||||
// public virtual void Clear()
|
||||
// {
|
||||
// Clear(defaultvalue);
|
||||
// }
|
||||
// public void Clear(int idx)
|
||||
// {
|
||||
// _values[idx] = defaultvalue;
|
||||
// }
|
||||
// public Tuple<string, string> GetCodeDesc(int idx)
|
||||
// {
|
||||
// return new Tuple<string, string>(_code[idx], _desc[idx]);
|
||||
// }
|
||||
// public virtual bool SupportAdd { get; private set; }
|
||||
// }
|
||||
|
||||
// public abstract class VarDataNumber<T> : VarData<T>
|
||||
// {
|
||||
// public VarDataNumber(int capa) : base(capa) { }
|
||||
|
||||
// public abstract void Add(T value);
|
||||
// public abstract void Add(int idx, T value);
|
||||
// }
|
||||
|
||||
// public class VarDataI32 : VarDataNumber<Int32>
|
||||
// {
|
||||
// public VarDataI32(int capa) : base(capa) { }
|
||||
|
||||
// public override void Add(Int32 value)
|
||||
// {
|
||||
// for (int i = 0; i < _values.Length; i++)
|
||||
// _values[i] += value;
|
||||
// }
|
||||
|
||||
// public override void Add(int idx, Int32 value)
|
||||
// {
|
||||
// _values[idx] += value;
|
||||
// }
|
||||
// public void Add(eVarInt32 idx, Int32 value = 1)
|
||||
// {
|
||||
// Add((int)idx, value);
|
||||
// }
|
||||
// public void Clear(eVarInt32 idx)
|
||||
// {
|
||||
// Clear((int)idx);
|
||||
// }
|
||||
// public Int32 this[eVarInt32 idx]
|
||||
// {
|
||||
// get { return Get((int)idx); }
|
||||
// set { Set((int)idx, value); }
|
||||
// }
|
||||
|
||||
// }
|
||||
// public class VarDataDBL : VarDataNumber<double>
|
||||
// {
|
||||
// public VarDataDBL(int capa) : base(capa) { }
|
||||
|
||||
// public override void Add(double value)
|
||||
// {
|
||||
// for (int i = 0; i < _values.Length; i++)
|
||||
// _values[i] += value;
|
||||
// }
|
||||
|
||||
// public override void Add(int idx, double value)
|
||||
// {
|
||||
// _values[idx] += value;
|
||||
// }
|
||||
// public void Add(eVarDBL idx, double value = 1)
|
||||
// {
|
||||
// Add((int)idx, value);
|
||||
// }
|
||||
// public void Clear(eVarDBL idx)
|
||||
// {
|
||||
// Clear((int)idx);
|
||||
// }
|
||||
// public double this[eVarDBL idx]
|
||||
// {
|
||||
// get { return Get((int)idx); }
|
||||
// set { Set((int)idx, value); }
|
||||
// }
|
||||
// }
|
||||
// public class VarDataUI32 : VarDataNumber<UInt32>
|
||||
// {
|
||||
// public VarDataUI32(int capa) : base(capa) { }
|
||||
|
||||
// public override void Add(UInt32 value)
|
||||
// {
|
||||
// for (int i = 0; i < _values.Length; i++)
|
||||
// _values[i] += value;
|
||||
// }
|
||||
|
||||
// public override void Add(int idx, UInt32 value)
|
||||
// {
|
||||
// _values[idx] += value;
|
||||
// }
|
||||
// public void Add(eVarUInt32 idx, UInt32 value = 1)
|
||||
// {
|
||||
// Add((int)idx, value);
|
||||
// }
|
||||
// public void Clear(eVarUInt32 idx)
|
||||
// {
|
||||
// Clear((int)idx);
|
||||
// }
|
||||
// public UInt32 this[eVarUInt32 idx]
|
||||
// {
|
||||
// get { return Get((int)idx); }
|
||||
// set { Set((int)idx, value); }
|
||||
// }
|
||||
// }
|
||||
|
||||
// public class VarDataByte : VarDataNumber<byte>
|
||||
// {
|
||||
// public VarDataByte(int capa) : base(capa) { }
|
||||
|
||||
// public override void Add(byte value)
|
||||
// {
|
||||
// for (int i = 0; i < _values.Length; i++)
|
||||
// _values[i] += value;
|
||||
// }
|
||||
// public override void Add(int idx, byte value)
|
||||
// {
|
||||
// _values[idx] += value;
|
||||
// }
|
||||
// public void Add(eVarByte idx, byte value)
|
||||
// {
|
||||
// Add((int)idx, value);
|
||||
// }
|
||||
// public byte this[eVarByte idx]
|
||||
// {
|
||||
// get
|
||||
// {
|
||||
// return Get((int)idx);
|
||||
// }
|
||||
// set
|
||||
// {
|
||||
// Set((int)idx, value);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// public class VarDataBool : VarData<bool>
|
||||
// {
|
||||
// public VarDataBool(int capa) : base(capa) { }
|
||||
|
||||
// public bool this[eVarBool idx]
|
||||
// {
|
||||
// get
|
||||
// {
|
||||
// return Get(idx);
|
||||
// }
|
||||
// set
|
||||
// {
|
||||
// Set(idx, value);
|
||||
// }
|
||||
// }
|
||||
// public bool Get(eVarBool idx)
|
||||
// {
|
||||
// return Get((int)idx);
|
||||
// }
|
||||
// public void Set(eVarBool idx, bool value)
|
||||
// {
|
||||
// Set((int)idx, value);
|
||||
// }
|
||||
// }
|
||||
|
||||
// public class VarDataStr : VarData<string>
|
||||
// {
|
||||
// public VarDataStr(int capa) : base(capa, string.Empty) { }
|
||||
// public string Get(eVarString idx)
|
||||
// {
|
||||
// return Get((int)idx);
|
||||
// }
|
||||
// public void Set(eVarString idx, string value)
|
||||
// {
|
||||
// Set((int)idx, value);
|
||||
// }
|
||||
// public string this[eVarString idx]
|
||||
// {
|
||||
// get { return Get(idx); }
|
||||
// set { Set(idx, value); }
|
||||
// }
|
||||
// }
|
||||
// public class VarDataDateTime : VarData<DateTime>
|
||||
// {
|
||||
// public VarDataDateTime(int capa) : base(capa, new DateTime(1982, 11, 23)) { }
|
||||
|
||||
// public DateTime this[eVarTime idx]
|
||||
// {
|
||||
// get
|
||||
// {
|
||||
// return Get((int)idx);
|
||||
// }
|
||||
// set
|
||||
// {
|
||||
// Set(idx, value);
|
||||
// }
|
||||
// }
|
||||
|
||||
// public TimeSpan RUN(int idx)
|
||||
// {
|
||||
// return DateTime.Now - _values[idx];
|
||||
// }
|
||||
// public TimeSpan RUN(eVarTime idx)
|
||||
// {
|
||||
// return RUN((int)idx);
|
||||
// }
|
||||
// [Browsable(false)]
|
||||
// public void Add(int idx, TimeSpan value)
|
||||
// {
|
||||
// _values[idx] += value;
|
||||
// }
|
||||
|
||||
// public void Add(eVarTime idx, TimeSpan value)
|
||||
// {
|
||||
// Add((int)idx, value);
|
||||
// }
|
||||
// /// <summary>
|
||||
// /// 지정된 시간으로 업데이트 합니다
|
||||
// /// </summary>
|
||||
// /// <param name="idx"></param>
|
||||
// /// <param name="value"></param>
|
||||
// public void Set(eVarTime idx, DateTime value)
|
||||
// {
|
||||
// Set((int)idx, value);
|
||||
// }
|
||||
// /// <summary>
|
||||
// /// 현재시간으로 업데이트 합니다
|
||||
// /// </summary>
|
||||
// /// <param name="idx"></param>
|
||||
// public void Set(eVarTime idx)
|
||||
// {
|
||||
// Set(idx, DateTime.Now);
|
||||
// }
|
||||
// public bool IsSet(eVarTime idx)
|
||||
// {
|
||||
// return this[idx].Year != 1982;
|
||||
// }
|
||||
// }
|
||||
// //공용변수(시간)
|
||||
// public static class VAR
|
||||
// {
|
||||
// public static VarDataBool BOOL;
|
||||
// public static VarDataByte BYTE;
|
||||
// public static VarDataStr STR;
|
||||
// public static VarDataDateTime TIME;
|
||||
// public static VarDataI32 I32;
|
||||
// public static VarDataUI32 U32;
|
||||
// public static VarDataDBL DBL;
|
||||
|
||||
// public static bool isInit { get; private set; } = false;
|
||||
|
||||
// public static void Init(int varlen)
|
||||
// {
|
||||
// if (isInit) return; //already init
|
||||
// //가변 데이트타임변수
|
||||
// BOOL = new VarDataBool(varlen);
|
||||
// BYTE = new VarDataByte(varlen);
|
||||
// STR = new VarDataStr(varlen);
|
||||
// TIME = new VarDataDateTime(varlen);
|
||||
// I32 = new VarDataI32(varlen);
|
||||
// U32 = new VarDataUI32(varlen);
|
||||
// DBL = new VarDataDBL(varlen);
|
||||
// isInit = true;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
5
HMI/SubProject/GitUpdate.bat
Normal file
5
HMI/SubProject/GitUpdate.bat
Normal file
@@ -0,0 +1,5 @@
|
||||
@echo off
|
||||
echo Git AutoUpdate
|
||||
echo tindevil@nate.com
|
||||
for /d %%i in (*) do echo Enterinng "%i" | cd "%i" | git.exe pull --progress -v --no-rebase "origin" master | cd ..
|
||||
@pause
|
||||
6
HMI/SubProject/Patch/App.config
Normal file
6
HMI/SubProject/Patch/App.config
Normal 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>
|
||||
63
HMI/SubProject/Patch/Form1.Designer.cs
generated
Normal file
63
HMI/SubProject/Patch/Form1.Designer.cs
generated
Normal file
@@ -0,0 +1,63 @@
|
||||
namespace Patch
|
||||
{
|
||||
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()
|
||||
{
|
||||
this.progressBar1 = new System.Windows.Forms.ProgressBar();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// progressBar1
|
||||
//
|
||||
this.progressBar1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.progressBar1.Location = new System.Drawing.Point(0, 0);
|
||||
this.progressBar1.Name = "progressBar1";
|
||||
this.progressBar1.Size = new System.Drawing.Size(481, 68);
|
||||
this.progressBar1.Style = System.Windows.Forms.ProgressBarStyle.Marquee;
|
||||
this.progressBar1.TabIndex = 1;
|
||||
//
|
||||
// Form1
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(481, 68);
|
||||
this.Controls.Add(this.progressBar1);
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "Form1";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "Form1";
|
||||
this.Load += new System.EventHandler(this.Form1_Load);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
private System.Windows.Forms.ProgressBar progressBar1;
|
||||
}
|
||||
}
|
||||
|
||||
122
HMI/SubProject/Patch/Form1.cs
Normal file
122
HMI/SubProject/Patch/Form1.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
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 Patch
|
||||
{
|
||||
public partial class Form1 : Form
|
||||
{
|
||||
public Form1()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Form1_Load(object sender, EventArgs e)
|
||||
{
|
||||
this.Text = "Software Patch";
|
||||
this.Show();
|
||||
|
||||
Application.DoEvents();
|
||||
|
||||
//현재폴더에서 _patch 폴더 찾는다
|
||||
Boolean runClient = true;
|
||||
var srcpath = new System.IO.DirectoryInfo ( System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "_patch"));
|
||||
if (srcpath.Exists == true)
|
||||
{
|
||||
//기존 프로그램 종료될떄까지 기다린다
|
||||
this.Text = "기존 프로그램 종료 대기";
|
||||
Application.DoEvents();
|
||||
bool closeok = true;
|
||||
System.Diagnostics.Stopwatch wat = new System.Diagnostics.Stopwatch();
|
||||
wat.Restart();
|
||||
while (CheckExistProcess("Amkor") == true)
|
||||
{
|
||||
Application.DoEvents();
|
||||
System.Threading.Thread.Sleep(10);
|
||||
if(wat.ElapsedMilliseconds >= 10000)
|
||||
{
|
||||
MessageBox.Show("기존프로그램이 종료되지 않았습니다", "패치실패", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
closeok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (CheckExistProcess("Amkor") == false)
|
||||
{
|
||||
|
||||
//버젼체크하고 파일 복사해준다
|
||||
var files = srcpath.GetFiles();
|
||||
this.progressBar1.Maximum = files.Length;
|
||||
this.progressBar1.Value = 0;
|
||||
this.progressBar1.Style = ProgressBarStyle.Continuous;
|
||||
|
||||
var myPath = new System.IO.DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var file in files)
|
||||
{
|
||||
this.Text = "패치파일 : " + file.Name;
|
||||
Application.DoEvents();
|
||||
|
||||
file.CopyTo(System.IO.Path.Combine(file.Directory.Parent.FullName, file.Name), true); // System.IO.File.Copy(file, myPath.FullName, true);
|
||||
this.progressBar1.Value += 1;
|
||||
System.Threading.Thread.Sleep(100);
|
||||
}
|
||||
|
||||
//패치파일을 삭제한다
|
||||
srcpath.Delete(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show(ex.Message);
|
||||
}
|
||||
}
|
||||
else runClient = false;
|
||||
}
|
||||
|
||||
//클라이언트실행
|
||||
if(runClient==true)
|
||||
{
|
||||
var file_run = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Amkor.exe");
|
||||
RunProcess(file_run);
|
||||
}
|
||||
|
||||
//프로그래램 종료
|
||||
this.Close();
|
||||
}
|
||||
|
||||
public Boolean CheckExistProcess(string ProcessName)
|
||||
{
|
||||
foreach (var prc in System.Diagnostics.Process.GetProcesses())
|
||||
{
|
||||
if (prc.ProcessName.StartsWith("svchost")) continue;
|
||||
if (prc.ProcessName.ToUpper() == ProcessName.ToUpper()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Boolean RunProcess(string file, string arg = "")
|
||||
{
|
||||
var fi = new System.IO.FileInfo(file);
|
||||
if (!fi.Exists)
|
||||
{
|
||||
//Pub.log.AddE("Run Error : " + file);
|
||||
return false;
|
||||
}
|
||||
System.Diagnostics.Process prc = new System.Diagnostics.Process();
|
||||
System.Diagnostics.ProcessStartInfo si = new System.Diagnostics.ProcessStartInfo(file);
|
||||
si.Arguments = arg;
|
||||
prc.StartInfo = si;
|
||||
prc.Start();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
120
HMI/SubProject/Patch/Form1.resx
Normal file
120
HMI/SubProject/Patch/Form1.resx
Normal file
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
22
HMI/SubProject/Patch/Program.cs
Normal file
22
HMI/SubProject/Patch/Program.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Patch
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// 해당 애플리케이션의 주 진입점입니다.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new Form1());
|
||||
}
|
||||
}
|
||||
}
|
||||
36
HMI/SubProject/Patch/Properties/AssemblyInfo.cs
Normal file
36
HMI/SubProject/Patch/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해
|
||||
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
|
||||
// 이러한 특성 값을 변경하세요.
|
||||
[assembly: AssemblyTitle("Patch")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Patch")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에
|
||||
// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면
|
||||
// 해당 형식에 대해 ComVisible 특성을 true로 설정하세요.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다.
|
||||
[assembly: Guid("37dc0bae-50bf-41e4-baab-b0e211467ad1")]
|
||||
|
||||
// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다.
|
||||
//
|
||||
// 주 버전
|
||||
// 부 버전
|
||||
// 빌드 번호
|
||||
// 수정 버전
|
||||
//
|
||||
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를
|
||||
// 기본값으로 할 수 있습니다.
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
63
HMI/SubProject/Patch/Properties/Resources.Designer.cs
generated
Normal file
63
HMI/SubProject/Patch/Properties/Resources.Designer.cs
generated
Normal file
@@ -0,0 +1,63 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 이 코드는 도구를 사용하여 생성되었습니다.
|
||||
// 런타임 버전:4.0.30319.42000
|
||||
//
|
||||
// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
|
||||
// 이러한 변경 내용이 손실됩니다.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Patch.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 지역화된 문자열 등을 찾기 위한 강력한 형식의 리소스 클래스입니다.
|
||||
/// </summary>
|
||||
// 이 클래스는 ResGen 또는 Visual Studio와 같은 도구를 통해 StronglyTypedResourceBuilder
|
||||
// 클래스에서 자동으로 생성되었습니다.
|
||||
// 멤버를 추가하거나 제거하려면 .ResX 파일을 편집한 다음 /str 옵션을 사용하여 ResGen을
|
||||
// 다시 실행하거나 VS 프로젝트를 다시 빌드하십시오.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.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("Patch.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
117
HMI/SubProject/Patch/Properties/Resources.resx
Normal file
117
HMI/SubProject/Patch/Properties/Resources.resx
Normal 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>
|
||||
26
HMI/SubProject/Patch/Properties/Settings.Designer.cs
generated
Normal file
26
HMI/SubProject/Patch/Properties/Settings.Designer.cs
generated
Normal file
@@ -0,0 +1,26 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 이 코드는 도구를 사용하여 생성되었습니다.
|
||||
// 런타임 버전:4.0.30319.42000
|
||||
//
|
||||
// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
|
||||
// 이러한 변경 내용이 손실됩니다.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Patch.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.4.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
7
HMI/SubProject/Patch/Properties/Settings.settings
Normal file
7
HMI/SubProject/Patch/Properties/Settings.settings
Normal 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>
|
||||
84
HMI/SubProject/Patch/SWPatch.csproj
Normal file
84
HMI/SubProject/Patch/SWPatch.csproj
Normal file
@@ -0,0 +1,84 @@
|
||||
<?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>{37DC0BAE-50BF-41E4-BAAB-B0E211467AD1}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>Patch</RootNamespace>
|
||||
<AssemblyName>SWPatch</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\..\..\..\..\Amkor\AGV4\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</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="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<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" />
|
||||
<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>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
1
HMI/SubProject/arCtl
Submodule
1
HMI/SubProject/arCtl
Submodule
Submodule HMI/SubProject/arCtl added at 768d71ebca
Reference in New Issue
Block a user