Sic04/FrameworkLocal/RTEquipmentLibrary/HardwareUnits/Efems/Rorzes/RorzeEfemConnection.cs

315 lines
9.2 KiB
C#
Raw Normal View History

2022-09-19 09:16:33 +08:00
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}");
}
}
}
}