using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Threading;
using COMM;
using ENIG;
using System.Security.Cryptography;
using AR;
using System.IO.Ports;
using System.Security.Cryptography.X509Certificates;
using System.Windows.Forms;
namespace Project.Device
{
public enum eDocStep : byte
{
NotSet = 0,
///
/// 투입준비됨
///
ReadyForEnter = 10,
///
/// 투입완료
///
EnterComplete = 11,
///
/// 투입(진행중)
///
EnterIng = 12,
///
/// 진출완료
///
ExitComplete = 21,
///
/// 진출중
///
ExitIng = 22,
}
public class Xbee : SerialPort, arDev.ISerialComm
{
public string buffer = string.Empty;
public System.Text.StringBuilder newbuffer = new StringBuilder();
public string ErrorMessage { get; set; } = string.Empty;
public DateTime LastStatusSendTime { get; set; } = DateTime.Now;
private EEProtocol proto;
public class MessageArgs : EventArgs
{
public bool IsError { get; set; }
public string Message { get; set; }
public MessageArgs(bool iserr, string m)
{
this.IsError = iserr;
this.Message = m;
}
}
public event EventHandler MessageReceived;
public event EventHandler ProtocReceived;
public Xbee()
{
this.WriteTimeout = 500;
this.ReadTimeout = 500;
this.DataReceived += Xbee_DataReceived;
proto = new EEProtocol();
proto.OnDataReceived += Proto_OnDataReceived;
proto.OnMessage += Proto_OnMessage;
}
~Xbee()
{
this.DataReceived -= Xbee_DataReceived;
proto.OnDataReceived -= Proto_OnDataReceived;
proto.OnMessage -= Proto_OnMessage;
}
///
/// 지그비장치에 데이터를 전송합니다
///
///
///
public bool Send(byte[] data)
{
try
{
this.Write(data, 0, data.Length);
return true;
}
catch (Exception ex)
{
ErrorMessage = ex.Message;
return false;
}
}
public new bool Close()
{
try
{
base.Close();
return true;
}
catch
{
return false;
}
}
public new bool Open()
{
try
{
base.Open();
return IsOpen;
}
catch (Exception ex)
{
ErrorMessage = ex.Message;
PUB.logxbee.AddE(ErrorMessage);
return false;
}
}
private void Proto_OnDataReceived(object sender, EEProtocol.DataEventArgs e)
{
var hexstrRaw = e.ReceivedPacket.RawData.HexString();
var hexstr = e.ReceivedPacket.Data.HexString();
var cmd = e.ReceivedPacket.Command.ToString("X2");
var id = e.ReceivedPacket.ID.ToString("X2");
PUB.logxbee.Add("RX", $"{hexstrRaw}\nID:{id},CMD:{cmd},DATA:{hexstr}");
ProtocReceived?.Invoke(this, e);
}
private void Proto_OnMessage(object sender, EEProtocol.MessageEventArgs e)
{
MessageReceived?.Invoke(this, new MessageArgs(e.IsError, e.Message));
}
private void Xbee_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
var dev = sender as System.IO.Ports.SerialPort;
var buffer = new byte[dev.BytesToRead];
dev.Read(buffer, 0, buffer.Length);
proto.ProcessReceivedData(buffer);
}
///
/// 이동완료 신호 전송
///
/// 목적지태그값
public void SendMoveComplete(string tag)
{
var id = PUB.setting.XBE_ID;
byte cmd = (byte)ENIGProtocol.AGVCommandEH.Arrived;
var data = System.Text.Encoding.Default.GetBytes(tag);
var packet = proto.CreatePacket(id, cmd, data);
if (Send(packet))
PUB.logxbee.AddI($"Send SendMoveComplete [O] : {packet.Length} {packet.HexString()}");
else
PUB.logxbee.AddE($"Send SendMoveComplete [X] : {packet.Length} {packet.HexString()} {PUB.XBE.ErrorMessage}");
}
///
/// 신규 RFID태그값이 읽혔다면 이명령을 통해서 전송한다
///
public void SendRFIDTag(string tag)
{
var id = PUB.setting.XBE_ID;
byte cmd = (byte)ENIGProtocol.AGVCommandEH.ReadRFID;
var data = System.Text.Encoding.Default.GetBytes(tag);
var packet = proto.CreatePacket(id, cmd, data);
if (Send(packet))
PUB.logxbee.AddI($"Send SendRFIDTag [O] : {packet.Length} {packet.HexString()}");
else
PUB.logxbee.AddE($"Send SendRFIDTag [X] : {packet.Length} {packet.HexString()} {PUB.XBE.ErrorMessage}");
}
///
/// 오류코드를 호스트에 전송합니다
///
///
public void SendError(ENIGProtocol.AGVErrorCode errcode)
{
// Update global error state so it persists in Status messages
PUB.Result.RunStepErrorCode = errcode;
//PUB.Result.ResultMessage = errormessage;
var id = PUB.setting.XBE_ID;
byte cmd = (byte)ENIGProtocol.AGVCommandEH.Error;
// if (errormessage.Length > 30) errormessage = errormessage.Substring(0, 29);
var data = new List();
data.Add((byte)errcode);
//var datamsg = System.Text.Encoding.Default.GetBytes(errormessage);
// data.AddRange(datamsg);
var packet = proto.CreatePacket(id, cmd, data.ToArray());
if (Send(packet))
PUB.logxbee.AddI($"Send SendError [O] : {packet.Length} {packet.HexString()}");
else
PUB.logxbee.AddE($"Send SendError [X] : {packet.Length} {packet.HexString()} {PUB.XBE.ErrorMessage}");
}
public eDocStep StepMC { get; set; } = eDocStep.NotSet;
ManualResetEvent sendlock = new ManualResetEvent(true);
///
/// AGV상태를 Xbee 로 전송한다
///
public void SendStatus()
{
if (this.IsOpen == false) return;
if (sendlock.WaitOne() == false) return;
sendlock.Reset();
/*
Mode[1] : 0=manual, 1=auto
RunSt[1] : 0=stop, 1=run, 2=error
RunStep[1] : (byte)PUB.sm.RunStep
RunStepSeq[1] : (byte)StepMC
MotorDir[1] : 0=F(Forward), 1=B(Backward)
MagnetDir[1] : 0=S(Straight), 1=L(Left), 2=R(Right)
ChargeSt[1] : 0=off, 1=on
CartSt[1] : 0=off, 1=on, 2=unknown
LiftSt[1] : 0=down , 1=up, 2=unknown
ErrorCode[1] : (byte)PUB.Result.ResultErrorCode
LastTag[4] : "0000"
*/
try
{
List data = new List();
byte value = 0;
// Autoron Mode
value = (byte)(VAR.BOOL[eVarBool.FLAG_AUTORUN] ? 1 : 0);
data.Add(value);
// RunSt
if (PUB.AGV.error.Value > 0)
value = 2; // error
else if (PUB.AGV.system1.agv_run)
value = 1; // run
else
value = 0; // stop
data.Add(value);
//나르미오류코드전송필요 260202
//agv\structure\errorflag.cs 파일의 public enum eflag 에 내용있음
data.AddRange(BitConverter.GetBytes(PUB.AGV.error.Value));
//runstep
value = (byte)PUB.sm.RunStep;
data.Add(value);
//runstepseq
value = (byte)StepMC;
data.Add(value);
// Motor Direction
if (PUB.AGV.data.Direction == 'F')
value = 0;
else if (PUB.AGV.data.Direction == 'B')
value = 1;
else
value = 0xff; //unknown
data.Add(value);
// Magnet Direction
if (PUB.AGV.data.Sts == 'L')
value = 1; // left
else if (PUB.AGV.data.Sts == 'R')
value = 2; // right
else if (PUB.AGV.data.Sts == 'S')
value = 0; // straight
else
value = 0xFF; //unknown
data.Add(value);
// ChargeSt
value = (byte)((VAR.BOOL[eVarBool.FLAG_CHARGEONA] || VAR.BOOL[eVarBool.FLAG_CHARGEONM]) ? 1 : 0);
data.Add(value);
// CartSt
if (PUB.AGV.signal2.cart_detect1 && PUB.AGV.signal2.cart_detect2)
value = 1; // 센서두개가 모두 감지되는 경우
else if (PUB.AGV.signal2.cart_detect1 == false && PUB.AGV.signal2.cart_detect2 == false)
value = 0; // 센서두개가 모두 감지되지 않는 경우
else
value = 2; // 센서하나만 감지되는 경우
data.Add(value);
// LiftSt
if (PUB.AGV.signal1.lift_up)
value = 1; // 위로 올라가는 경우
else if (PUB.AGV.signal1.lift_down)
value = 0; // 아래로 내려가는 경우
else
value = 2; // unknown (기본값)
data.Add(value);
// ErrorCode [New RunStepErrorCode]
value = (byte)PUB.Result.RunStepErrorCode;
data.Add(value);
// LastTag
string lastTag = PUB.AGV.data.TagNo.ToString("0000") ?? "0000";
byte[] tagBytes = Encoding.ASCII.GetBytes(lastTag.PadRight(4, '0'));
data.AddRange(tagBytes);
// 데이터 전송
var cmd = (byte)ENIGProtocol.AGVCommandEH.Status;
var packet = proto.CreatePacket(PUB.setting.XBE_ID, cmd, data.ToArray());
if (Send(packet))
PUB.logxbee.AddI($"Send status [O] : {packet.Length} {packet.HexString()}");
else
PUB.logxbee.AddE($"Send status [X] : {packet.Length} {packet.HexString()} {PUB.XBE.ErrorMessage}");
LastStatusSendTime = DateTime.Now;
}
catch (Exception ex)
{
ErrorMessage = ex.Message;
PUB.logxbee.AddE(ErrorMessage);
}
finally
{
sendlock.Set();
}
}
}
}