파일정리

This commit is contained in:
ChiKyun Kim
2026-01-29 14:03:17 +09:00
parent 00cc0ef5b7
commit 58ca67150d
440 changed files with 47236 additions and 99165 deletions

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

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

View 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);
}
}
}
}

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

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

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

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

View 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")]

View 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();
}
}
}
}

View 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();
}
}
}
}

View 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();
}
}
}
}

View 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();
}
}
}
}

View 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();
}
}
}
}