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 int senderrcnt = 0; /// /// 지그비장치에 데이터를 전송합니다 /// /// /// public bool Send(byte[] data) { try { this.Write(data, 0, data.Length); senderrcnt = 0; return true; } catch (Exception ex) { senderrcnt += 1; ErrorMessage = ex.Message; return false; } } public new bool Close() { try { base.Close(); return true; } catch { return false; } } public new bool Open() { try { base.Open(); senderrcnt = 0; 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); VAR.TIME[eVarTime.LastRecv_XBE] = DateTime.Now; } /// /// 이동완료 신호 전송 /// /// 목적지태그값 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}"); } StateMachine.ERunStep lastactioncmd = StateMachine.ERunStep.READY; DateTime lastactioncmdtime = DateTime.Now; /// /// 특정행동이 완료되었을때 전달함 /// /// public void SendActionComplete(StateMachine.ERunStep actionCmd) { if (lastactioncmd == actionCmd) { var ts = DateTime.Now - lastactioncmdtime; if(ts.TotalSeconds < 2) { return; } } var id = PUB.setting.XBE_ID; byte cmd = (byte)ENIGProtocol.AGVCommandEH.ActionComplete; var packet = proto.CreatePacket(id, cmd, null); if (Send(packet)) PUB.logxbee.AddI($"SendActionComplete [O] : {packet.Length} {packet.HexString()}"); else PUB.logxbee.AddE($"SendActionComplete [X] : {packet.Length} {packet.HexString()} {PUB.XBE.ErrorMessage}"); //최종액션저장 lastactioncmd = actionCmd; lastactioncmdtime = DateTime.Now; } /// /// 신규 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; //라이다로인해 멈춘경우 오류코드 추가 260204 if (value == 0 && PUB.AGV.system1.stop_by_front_detect) value = (byte)ENIGProtocol.AGVErrorCode.LIDAR_STOP; 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(); } } } }