315 lines
9.2 KiB
C#
315 lines
9.2 KiB
C#
|
using Aitex.Core.RT.Event;
|
|||
|
using Aitex.Core.RT.Log;
|
|||
|
using MECF.Framework.Common.Communications;
|
|||
|
using MECF.Framework.Common.Equipment;
|
|||
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
|
|||
|
namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Efems.Rorzes
|
|||
|
{
|
|||
|
|
|||
|
public class RorzeEfemMessage : AsciiMessage
|
|||
|
{
|
|||
|
public ModuleName TargetModule { get; set; }
|
|||
|
|
|||
|
public RorzeEfemMessageType MessageType { get; set; }
|
|||
|
|
|||
|
public RorzeEfemBasicMessage BasicMessage { get; set; }
|
|||
|
|
|||
|
public string Parameter { get; set; }
|
|||
|
|
|||
|
public string NakFactor { get; set; }
|
|||
|
|
|||
|
public bool WaitAck { get; set; }
|
|||
|
|
|||
|
public bool WaitInf { get; set; }
|
|||
|
|
|||
|
//ABS : Message* | ERROR / Parameter1 / Parameter2 ;
|
|||
|
//ERROR / Parameter1 / Parameter2
|
|||
|
public string AbsError { get; set; }
|
|||
|
|
|||
|
//CAN : Message* | Factor / Place ;
|
|||
|
//Factor / Place
|
|||
|
public string CanError { get; set; }
|
|||
|
}
|
|||
|
|
|||
|
public class RorzeEfemConnection : FsmConnection
|
|||
|
{
|
|||
|
private string _cachedBuffer = string.Empty;
|
|||
|
|
|||
|
private object _lockerHandler = new object();
|
|||
|
|
|||
|
private IConnectionContext _config;
|
|||
|
|
|||
|
List<HandlerBase> _handlers = new List<HandlerBase>();
|
|||
|
|
|||
|
private Dictionary<RorzeEfemBasicMessage, HandlerBase> _eventHandler = new Dictionary<RorzeEfemBasicMessage, HandlerBase>();
|
|||
|
|
|||
|
public RorzeEfemConnection(IConnectionContext config)
|
|||
|
{
|
|||
|
_config = config;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
public bool IsBusy(int mutexId)
|
|||
|
{
|
|||
|
lock (_lockerHandler)
|
|||
|
{
|
|||
|
foreach (var handlerBase in _handlers)
|
|||
|
{
|
|||
|
if (handlerBase.MutexId == mutexId)
|
|||
|
{
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
public void AddEventHandler(RorzeEfemBasicMessage type, RorzeEfemHandler handler)
|
|||
|
{
|
|||
|
System.Diagnostics.Debug.Assert(!_eventHandler.ContainsKey(type));
|
|||
|
|
|||
|
_eventHandler[type] = handler;
|
|||
|
}
|
|||
|
|
|||
|
public void Initialize()
|
|||
|
{
|
|||
|
base.Initialize(100, new SocketClient(_config), _config);
|
|||
|
}
|
|||
|
|
|||
|
protected override void OnConnect()
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
protected override void OnDisconnect()
|
|||
|
{
|
|||
|
lock (_lockerHandler)
|
|||
|
{
|
|||
|
_cachedBuffer = string.Empty;
|
|||
|
_handlers.Clear();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
protected override void OnConnectMonitor()
|
|||
|
{
|
|||
|
MonitorTimeout();
|
|||
|
|
|||
|
base.OnConnectMonitor();
|
|||
|
}
|
|||
|
|
|||
|
private HandlerBase MonitorTimeout()
|
|||
|
{
|
|||
|
HandlerBase result = null;
|
|||
|
lock (_lockerHandler)
|
|||
|
{
|
|||
|
foreach (var handlerBase in _handlers)
|
|||
|
{
|
|||
|
if (handlerBase.CheckTimeout())
|
|||
|
{
|
|||
|
EV.PostWarningLog("System", $"execute {handlerBase.Name} timeout");
|
|||
|
result = handlerBase;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (result != null)
|
|||
|
{
|
|||
|
_handlers.Remove(result);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
public bool Execute(HandlerBase handler, out string reason)
|
|||
|
{
|
|||
|
lock (_lockerHandler)
|
|||
|
{
|
|||
|
foreach (var handlerBase in _handlers)
|
|||
|
{
|
|||
|
if (handlerBase.MutexId == handler.MutexId && handler.MutexId!=-1)
|
|||
|
{
|
|||
|
reason = $"Can not execute {handler.Name} while execute {handlerBase.Name}";
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
_handlers.Add(handler);
|
|||
|
|
|||
|
handler.SetState(EnumHandlerState.Sent);
|
|||
|
|
|||
|
if (_config.IsAscii)
|
|||
|
{
|
|||
|
InvokeSendData(handler.SendText);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
InvokeSendData(handler.SendBinary);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
reason = string.Empty;
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
public void Reset()
|
|||
|
{
|
|||
|
InvokeReset();
|
|||
|
}
|
|||
|
|
|||
|
protected override void OnReceiveData(string message)
|
|||
|
{
|
|||
|
_cachedBuffer += message;
|
|||
|
|
|||
|
int enderIndex = _cachedBuffer.IndexOf(";\r");
|
|||
|
while (enderIndex != -1)
|
|||
|
{
|
|||
|
if (enderIndex > 0)
|
|||
|
{
|
|||
|
ProceedResponse(_cachedBuffer.Substring(0, enderIndex));
|
|||
|
}
|
|||
|
|
|||
|
_cachedBuffer = _cachedBuffer.Remove(0, enderIndex + 2);
|
|||
|
enderIndex = _cachedBuffer.IndexOf(";\r");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void AckInfo(string message)
|
|||
|
{
|
|||
|
if (message.StartsWith("INF:"))
|
|||
|
{
|
|||
|
InvokeSendData(message.Replace("INF:", "ACK:") + ";\r");
|
|||
|
}
|
|||
|
else if (message.StartsWith("ABS:"))
|
|||
|
{
|
|||
|
InvokeSendData(message.Replace("ABS:", "ACK:") + ";\r");
|
|||
|
}
|
|||
|
else if (message.StartsWith("NAK:"))
|
|||
|
{
|
|||
|
InvokeSendData(message.Replace("NAK:", "ACK:") + ";\r");
|
|||
|
}
|
|||
|
else if (message.StartsWith("CAN:"))
|
|||
|
{
|
|||
|
InvokeSendData(message.Replace("CAN:", "ACK:") + ";\r");
|
|||
|
}
|
|||
|
}
|
|||
|
protected void ProceedResponse(string rawMessage)
|
|||
|
{
|
|||
|
RorzeEfemMessage msg = new RorzeEfemMessage();
|
|||
|
msg.RawMessage = rawMessage;
|
|||
|
if (rawMessage == "INF:READY/COMM")
|
|||
|
{
|
|||
|
_eventHandler[RorzeEfemBasicMessage.READY].HandleMessage(msg, out _);
|
|||
|
|
|||
|
AckInfo(rawMessage);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
string[] words = rawMessage.Split(new char[5] { ':', '/', '>', '|', ';' }, StringSplitOptions.RemoveEmptyEntries);
|
|||
|
msg.MessagePart = words;
|
|||
|
|
|||
|
if (!Enum.TryParse<RorzeEfemMessageType>(words[0], out RorzeEfemMessageType type))
|
|||
|
{
|
|||
|
LOG.Write($"{rawMessage} is not a valid EFEM message format");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (type == RorzeEfemMessageType.MOV || type == RorzeEfemMessageType.GET ||
|
|||
|
type == RorzeEfemMessageType.SET)
|
|||
|
{
|
|||
|
LOG.Write($"{rawMessage} is not a valid EFEM message format, {type} is TO EFEM");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
msg.MessageType = type;
|
|||
|
msg.IsEvent = msg.MessageType == RorzeEfemMessageType.EVT;
|
|||
|
|
|||
|
int messageIndex = msg.MessageType == RorzeEfemMessageType.NAK ? 2 : 1;
|
|||
|
|
|||
|
if (words.Length <= messageIndex || !Enum.TryParse<RorzeEfemBasicMessage>(words[messageIndex], out RorzeEfemBasicMessage basicMessage))
|
|||
|
{
|
|||
|
LOG.Write($"{rawMessage} is not a valid EFEM message format");
|
|||
|
return;
|
|||
|
}
|
|||
|
msg.BasicMessage = basicMessage;
|
|||
|
|
|||
|
if (msg.MessageType == RorzeEfemMessageType.NAK)
|
|||
|
{
|
|||
|
msg.NakFactor = words[1];
|
|||
|
msg.Parameter = rawMessage.Substring(rawMessage.IndexOf('/') + 1);
|
|||
|
}
|
|||
|
else if (msg.MessageType == RorzeEfemMessageType.CAN)
|
|||
|
{
|
|||
|
msg.CanError = rawMessage.Substring(rawMessage.IndexOf('|'));
|
|||
|
msg.Parameter = rawMessage.Substring(rawMessage.IndexOf('/') + 1, rawMessage.IndexOf('|') - rawMessage.IndexOf('/'));
|
|||
|
}
|
|||
|
else if (msg.MessageType == RorzeEfemMessageType.ABS)
|
|||
|
{
|
|||
|
msg.AbsError = rawMessage.Substring(rawMessage.IndexOf('|'));
|
|||
|
msg.Parameter = rawMessage.Substring(rawMessage.IndexOf('/') + 1, rawMessage.IndexOf('|') - rawMessage.IndexOf('/'));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
msg.Parameter = rawMessage.Substring(rawMessage.IndexOf('/') + 1);
|
|||
|
}
|
|||
|
|
|||
|
if (msg.IsEvent)
|
|||
|
{
|
|||
|
ProceedEvent(msg);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
ProceedMessage(msg);
|
|||
|
}
|
|||
|
|
|||
|
private void ProceedMessage(RorzeEfemMessage msg)
|
|||
|
{
|
|||
|
lock (_lockerHandler)
|
|||
|
{
|
|||
|
HandlerBase handlerDone = null;
|
|||
|
|
|||
|
bool matchMessage = false;
|
|||
|
foreach (var handler in _handlers)
|
|||
|
{
|
|||
|
matchMessage = handler.HandleMessage(msg, out bool completed);
|
|||
|
if (completed)
|
|||
|
{
|
|||
|
handlerDone = handler;
|
|||
|
AckInfo(msg.RawMessage);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (matchMessage)
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (!matchMessage)
|
|||
|
{
|
|||
|
LOG.Write($"No handler for message, {msg.RawMessage}");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
_handlers.Remove(handlerDone);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void ProceedEvent(RorzeEfemMessage msg)
|
|||
|
{
|
|||
|
if (_eventHandler.ContainsKey(msg.BasicMessage))
|
|||
|
{
|
|||
|
_eventHandler[msg.BasicMessage].HandleMessage(msg, out _);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
LOG.Write($"No handler for event {msg.RawMessage}");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|