Sic.Framework-Nanjing-Baishi/MECF.Framework.RT.Equipment.../HardwareUnits/MFCs/HoribaMFC/HoribaConnection.cs

332 lines
11 KiB
C#

using Aitex.Core.RT.Device;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using MECF.Framework.Common.Communications;
using MECF.Framework.Common.Device.Bases;
using MECF.Framework.Common.Equipment;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Threading;
namespace LsOneRT.Devices.HoribaMFC
{
public class HoribaMessage : BinaryMessage
{
public string DeviceAddress { get; set; }
public string Action { get; set; }
public string Parameter { get; set; }
public int DataLength { get; set; }
public string ErrorText { get; set; }
public byte[] Datas { get; set; }
}
public class HoribaConnection: Singleton<HoribaConnection>
{
public HoribaConnectionBase Horiba { get; private set; }
public HoribaConnection()
{
Horiba = new HoribaConnectionBase();
}
}
public class HoribaConnectionBase : SerialPortConnectionBase
{
private const int STX = 0x02;
private const int ETX = 0x03;
private const int NAK = 0x15;
private List<byte> _lstCacheBuffer = new List<byte>();
private PeriodicJob _thread;
private bool _activeMonitorStatus;
private R_TRIG _trigWarningMessage = new R_TRIG();
private R_TRIG _trigCommunicationError = new R_TRIG();
private R_TRIG _trigRetryConnect = new R_TRIG();
private LinkedList<HandlerBase> _lstHandler = new LinkedList<HandlerBase>();
private object _locker = new object();
private bool _enableLog = true;
private bool _isFirstTime = true;
private int _reconnectCount = 0;
private DeviceTimer _QueryScaleTimer = new DeviceTimer();
private readonly int _QueryScaleInterval = 3000;
private List<MfcBase> MFCList = new List<MfcBase>();
public HoribaConnectionBase():base(SC.GetStringValue($"{ModuleName.PM}.MFCSerialPortName"), 38400, 7, Parity.Odd, StopBits.One, "\r", false)
{
_activeMonitorStatus = true;
Module = ModuleName.PM.ToString();
Name = "HoribaConnection";
_enableLog = SC.GetValue<bool>($"{Module}.MFCEnableLogMessage");
EnableLog(_enableLog);
if (Connect())
{
EV.PostInfoLog(Module, $"{Module}.{Name} connected");
}
Thread.Sleep(2000);
if (SC.ContainsItem("System.IsSimulatorMode") && SC.GetValue<bool>("System.IsSimulatorMode"))
_thread = new PeriodicJob(200, OnTimer, $"{Module}.{Name} MonitorHandler", true);
else
_thread = new PeriodicJob(100, OnTimer, $"{Module}.{Name} MonitorHandler", true);
}
public HoribaConnectionBase(string module) : base(SC.GetStringValue($"{module}.MFCSerialPortName"), 38400, 7, Parity.Odd, StopBits.One, "\r", false)
{
_activeMonitorStatus = true;
Module = module;
Name = "HoribaConnection";
_enableLog = SC.GetValue<bool>($"{Module}.MFCEnableLogMessage");
EnableLog(_enableLog);
if (Connect())
{
EV.PostInfoLog(Module, $"{Module}.{Name} connected");
}
Thread.Sleep(2000);
_QueryScaleTimer.Start(_QueryScaleInterval);
if (SC.ContainsItem("System.IsSimulatorMode") && SC.GetValue<bool>("System.IsSimulatorMode"))
_thread = new PeriodicJob(200, OnTimer, $"{Module}.{Name} MonitorHandler", true);
else
_thread = new PeriodicJob(100, OnTimer, $"{Module}.{Name} MonitorHandler", true);
}
public string Module { get; set; }
public string Name { get; set; }
private bool OnTimer()
{
try
{
MonitorTimeout();
if (!IsConnected || IsCommunicationError)
{
_trigRetryConnect.CLK = !IsConnected;
if (_trigRetryConnect.Q)
{
EV.PostAlarmLog(Module, $"Disconnect with {Module}.{Name} {SC.GetStringValue($"{ModuleName.PM}.MFCSerialPortName")}");
_reconnectCount = 0;
}
if (_reconnectCount <= SC.GetValue<int>($"{Module}.MFCReconnectCount"))
{
//SetPortAddress(SC.GetStringValue($"{Module}.MFCSerialPortName"));
Connect();
Thread.Sleep(2000);
if (IsConnected)
{
Reset();
EV.PostInfoLog(Module, $"Reconnect with {Module}.{Name} {SC.GetStringValue($"{ModuleName.PM}.MFCSerialPortName")} successed");
}
else
{
EV.PostWarningLog(Module, $"Can not connect with {Module}.{Name} {SC.GetStringValue($"{ModuleName.PM}.MFCSerialPortName")}, retry {_reconnectCount}");
Thread.Sleep(1000);
}
}
lock (_locker)
{
_lstHandler.Clear();
_reconnectCount++;
}
return true;
}
HandlerBase handler = null;
if (!IsBusy)
{
lock (_locker)
{
if (_lstHandler.Count == 0 && _activeMonitorStatus)
{
foreach(var mfc in MFCList)
{
_lstHandler.AddLast(new HoribaMFCQueryFlow(mfc, mfc.DeviceID));
if(_QueryScaleTimer.IsTimeout())
_lstHandler.AddLast(new HoribaMFCQueryScale(mfc, mfc.DeviceID));
if (_isFirstTime)
{
_lstHandler.AddLast(new HoribaMFCQueryScale(mfc, mfc.DeviceID));
_lstHandler.AddLast(new HoribaMFCSetDigitalMode(mfc, mfc.DeviceID));
}
}
if (_QueryScaleTimer.IsTimeout())
_QueryScaleTimer.Start(_QueryScaleInterval);
_isFirstTime = false;
}
if (_lstHandler.Count > 0)
{
handler = _lstHandler.First.Value;
_lstHandler.RemoveFirst();
}
}
if (handler != null)
{
Execute(handler);
}
}
EnableLog(_enableLog);
_trigCommunicationError.CLK = IsCommunicationError;
if (_trigCommunicationError.Q)
{
EV.PostAlarmLog(Module, $"{Module}.{Name} communication error");
}
}
catch (Exception ex)
{
LOG.Write(ex);
}
return true;
}
public void AddHandler(HandlerBase handler)
{
lock (_locker)
{
_lstHandler.AddLast(handler);
}
}
public void AddMFC(MfcBase mfc)
{
MFCList.Add(mfc);
}
public void Reset()
{
_trigWarningMessage.RST = true;
SetCommunicationError(false, "");
_trigCommunicationError.RST = true;
_enableLog = SC.GetValue<bool>($"{Module}.MFCEnableLogMessage");
_trigRetryConnect.RST = true;
_reconnectCount = 0;
}
public override bool SendMessage(byte[] message)
{
_lstCacheBuffer.Clear();
return base.SendMessage(message);
}
public void Terminate()
{
}
public void SetError(byte[] content)
{
string reason = System.Text.Encoding.ASCII.GetString(content);
_trigWarningMessage.CLK = true;
if (_trigWarningMessage.Q)
{
EV.PostWarningLog(Module, $"{Module}.{Name} error, {reason}");
}
}
protected override MessageBase ParseResponse(byte[] rawMessage)
{
_lstCacheBuffer.AddRange(rawMessage);
byte[] temps = _lstCacheBuffer.ToArray();
HoribaMessage msg = new HoribaMessage();
msg.IsResponse = false;
msg.IsAck = false;
msg.IsComplete = false;
msg.RawMessage = _lstCacheBuffer.ToArray();
if (_lstCacheBuffer.Count < 4 || _lstCacheBuffer[_lstCacheBuffer.Count - 2] != ETX)
return msg;
if (temps.Length > 0 && (int)temps[0] == NAK)
{
LOG.Error($"NAK, " + temps);
msg.IsNak = true;
return msg;
}
if (temps.Length < 4)
{
LOG.Error($"text length check failed");
msg.IsFormatError = true;
return msg;
}
if ((int)temps[0] != STX)
{
LOG.Error($"text check STX failed");
msg.IsFormatError = true;
return msg;
}
int etxIndex = 0;
foreach (var item in temps)
{
if ((int)item == ETX)
break;
etxIndex++;
}
if(etxIndex >= temps.Length)
{
LOG.Error($"text check ETX failed");
msg.IsFormatError = true;
return msg;
}
msg.DataLength = etxIndex - 1;
msg.Datas = new byte[etxIndex - 1];
///STX msg ETX BCC
Array.Copy(temps, 1, msg.Datas, 0, etxIndex - 1);
var bcc = (int)temps[etxIndex + 1];
int checkBCC = 0;
foreach (var item in msg.Datas)
{
checkBCC += (int)item;
}
checkBCC += ETX;
if (checkBCC % 128 != bcc)
{
LOG.Error($"check BCC failed");
msg.IsFormatError = true;
return msg;
}
msg.IsResponse = true;
msg.IsAck = true;
msg.IsComplete = true;
return msg;
}
}
}