using Aitex.Core.RT.Log;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using MECF.Framework.Common.Communications;
using MECF.Framework.Common.Equipment;
using MECF.Framework.RT.ModuleLibrary.VceModules;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Venus_Core;
namespace Venus_RT.Devices.VCE
{
//定义Vce动作
public enum VceCommand
{
Home,
DoorClose,
DoorOpen,
Goto,
Load,
UnLoad,
Map,
ReadMap,
}
public enum VceMessageHead
{
Action,
Read,
Set,
Petrify
}
///
/// 泓浒Vce驱动 下发指令等
///
public class HongHuVce : VceModuleBase
{
#region 私有变量
private AsyncSerialPort _serialport;
private string _portname;
private string _newline = "\n\r";//终止符 0A 0D
private object _locker = new object();
private bool _IsAsciiMode;
private LinkedList _lstAsciiMsgs = new LinkedList();
private PeriodicJob _thread;
private Regex _matchErrorCode = new Regex(@"(?<=_BKGERR )(.*)");
private ModuleName _moduleName;
private RState _status;
private string _currentMsg;
//后期补充
private Dictionary _ErrorCode2Reason = new Dictionary()
{
{"A6","设备动作,但是发生异常" },
{"A8","设备检查互锁,发现无法执行" },
};
//
private Dictionary _Command2Msg = new Dictionary()
{
//Action
{VceCommand.Home, "HM" },
{VceCommand.Load, "LOAD" },
{VceCommand.UnLoad, "UNLOAD"},
{VceCommand.Map, "MP" },
{VceCommand.Goto, "GC" },
//Read
{VceCommand.ReadMap, "MI" },
//Set
};
private Dictionary _Type2Head = new Dictionary()
{
{VceMessageHead.Action, "A"},
{VceMessageHead.Read, "R"},
{VceMessageHead.Set, "S"},
{VceMessageHead.Petrify, "P"},
};
#endregion
#region 暴露变量
public override bool IsConnected => _serialport.IsOpen();
public override RState Status => _status;
public override bool IsReady => _status == RState.Init || _status == RState.End;
public override bool IsError => _status == RState.Failed || _status == RState.Timeout;
public override bool IsInit => _status == RState.Init;
#endregion
//传入slot数量
public HongHuVce(int slot, ModuleName moduleName) : base(slot, moduleName)
{
_moduleName = moduleName;
_IsAsciiMode = true;
_portname = SC.GetStringValue("VCE.Port");
_serialport = new AsyncSerialPort(_portname, 9600, 8, Parity.None, StopBits.One, _newline, _IsAsciiMode);
_serialport.Open();
_status = RState.Init;
_serialport.OnDataChanged += onDataChange;
_thread = new PeriodicJob(50, fnTimer, "VCE", true);
}
///
/// 对处理过的数据list进行处理
/// 将每条数据进行解析
///
///
private bool fnTimer()
{
lock (_locker)
{
//采用ascii传输
if (_IsAsciiMode)
{
//有数据尚未处理
while (_lstAsciiMsgs.Count > 0)
{
string _needHandle = _lstAsciiMsgs.First.Value;
HandleSingleMsg(_needHandle);
_lstAsciiMsgs.RemoveFirst();
}
}
//采用binary
else
{
}
}
return true;
}
///
/// 处理单条信息的函数
/// 1、判断结束 2、判断错误
///
/// 需要处理的单条回复
private void HandleSingleMsg(string msg)
{
//
if (!string.IsNullOrEmpty(msg))
{
//动作
if (_currentMsg.Contains(",A,"))
{
switch (msg)
{
//设备收到 开始运行 目前状态在下发
case "_RDY":
break;
//设备执行完毕
case "_BKGRDY":
_status = RState.End;
break;
//异常处理
default:
_status = RState.Failed;
string reason = string.Empty;
if (_matchErrorCode.IsMatch(msg))
{
//若是匹配
//包含原因
string errorcode = _matchErrorCode.Match(msg).Value;
if (_ErrorCode2Reason.ContainsKey(errorcode))
{
reason = _ErrorCode2Reason[errorcode];
}
else
{
reason = "未找到相关Error Code";
}
}
else
{
//若不匹配
reason = "回复消息不符合标准格式";
}
LOG.Write(eEvent.ERR_DEVICE_INFO, _moduleName, reason);
break;
}
}
//读取
if (_currentMsg.Contains(",R,") && msg.Contains(",X,"))
{
string readtype = msg.Split(',')[2];
switch (readtype)
{
//处理wafer 信息为map数据
case "MI":
string waferinfo = "";
string[] waferitems = msg.Split(',');
for (int i = 3; i < waferitems.Length - 1; i++)
{
//从16进制字符转义回二进制
string wafersingleinfo = Convert.ToString(Convert.ToInt32(waferitems[i], 16), 2);
if (wafersingleinfo.Length < 4)
wafersingleinfo = '0' * (4 - wafersingleinfo.Length) + wafersingleinfo;//补位
waferinfo = wafersingleinfo + waferinfo;//添加到数据中
}
//请将数据按照反向槽位进行解析存入到wafermanager中
break;
}
}
}
}
///
/// 处理新到的数据
/// 利用linkedlist处理拆包 粘包情况
///
/// 新到数据
private void onDataChange(string oneLineMessage)
{
lock (_locker)
{
if (string.IsNullOrEmpty(_newline))//没有CR
{
_lstAsciiMsgs.AddLast(oneLineMessage);//将消息添加到最后
return;
}
string[] array = oneLineMessage.Split(_newline.ToCharArray());//按照cr分开通讯数据
foreach (string text in array)
{
if (!string.IsNullOrEmpty(text))
{
_lstAsciiMsgs.AddLast(text + _newline);//存进list中等待处理
}
}
}
}
public string Option2Message(VceMessageHead msgtype, VceCommand name, string param = "")
{
if (string.IsNullOrEmpty(param))//含尾参
return $"00,{_Type2Head[msgtype]},{_Command2Msg[name]}{_newline}";
else//不含尾参 目前只允许一个
return $"00,{_Type2Head[msgtype]},{_Command2Msg[name]},{param},{_newline}";
}
public override bool CloseDoor()
{
if (!CheckVceStatus())
return false;
_currentMsg = Option2Message(VceMessageHead.Action, VceCommand.DoorClose);
_status = RState.Running;
return _serialport.Write(_currentMsg);
}
public override bool HomeALL()
{
_currentMsg = Option2Message(VceMessageHead.Action, VceCommand.Home, "ALL");
_status = RState.Running;
return _serialport.Write(_currentMsg);
}
public override bool Home(string axis)
{
_currentMsg = Option2Message(VceMessageHead.Action, VceCommand.Home, axis);
_status = RState.Running;
return _serialport.Write(_currentMsg);
}
public override bool OpenDoor()
{
if (!CheckVceStatus())
return false;
_currentMsg = Option2Message(VceMessageHead.Action, VceCommand.DoorOpen);
_status = RState.Running;
return _serialport.Write(_currentMsg);
}
public override bool Load()
{
if (!CheckVceStatus())
return false;
_currentMsg = Option2Message(VceMessageHead.Action, VceCommand.Load);
_status = RState.Running;
return _serialport.Write(_currentMsg);
}
public override bool UnLoad()
{
if (!CheckVceStatus())
return false;
_currentMsg = Option2Message(VceMessageHead.Action, VceCommand.UnLoad);
_status = RState.Running;
return _serialport.Write(_currentMsg);
}
public override bool Map()
{
if (!CheckVceStatus())
return false;
_currentMsg = Option2Message(VceMessageHead.Action, VceCommand.Map);
_status = RState.Running;
return _serialport.Write(_currentMsg);
}
public override bool ReadMap()
{
if (!CheckVceStatus())
return false;
_currentMsg = Option2Message(VceMessageHead.Read, VceCommand.ReadMap);
_status = RState.Running;
return _serialport.Write(_currentMsg);
}
public override bool Goto(int Targetslot)
{
if (!CheckVceStatus())
return false;
_currentMsg = Option2Message(VceMessageHead.Action, VceCommand.Goto, Targetslot.ToString());
_status = RState.Running;
return _serialport.Write(_currentMsg);
}
}
}