Sic.Framework/MECF.Framework.RT.Equipment.../HardwareUnits/Efems/Rorzes/RorzeEfemConnection.cs

315 lines
9.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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}");
}
}
}
}