Files
JP_KDDI_LFPS_48100/LFP_Manager/Threads/csUartThread.cs
2025-12-19 13:59:34 +09:00

781 lines
32 KiB
C#

using System;
using System.Threading;
using System.IO.Ports;
using System.Windows.Forms;
using LFP_Manager.DataStructure;
using LFP_Manager.Function;
using LFP_Manager.Utils;
using DevExpress.XtraGauges.Core.Model;
using System.Collections.Concurrent;
using System.ComponentModel;
namespace LFP_Manager.Threads
{
#region DELEGATE
// 표준 이벤트 패턴
public sealed class DataRecvEventArgs : EventArgs
{
public byte[] Data { get; }
public DataRecvEventArgs(byte[] data) => Data = data;
}
public sealed class PrintEventArgs : EventArgs
{
public int Id { get; }
public string Message { get; }
public PrintEventArgs(int id, string message)
=> (Id, Message) = (id, message);
}
#endregion
class csUartThread
{
#region DELEGATE
// 표준 이벤트 패턴
public sealed class ModuleDataEventArgs : EventArgs
{
public CsDeviceData.DeviceModuleData Module { get; }
public ModuleDataEventArgs(CsDeviceData.DeviceModuleData module) => Module = module;
}
#endregion
#region CONSTANTS
private const int RX_PACKET_BUFFER_SIZE = 512;
#endregion
#region VARIABLES
private readonly CommConfig Config;
private CsDeviceData.DeviceModuleData ModuleData;
private Thread _serialComm = null;
private SerialPort sPort = null;
private CancellationTokenSource _cts;
private volatile bool _serialPortThreadEnd = true;
private readonly ISynchronizeInvoke _ui; // 보통 Form 또는 Control
public int ModuleId = 0;
private bool UartPolling = false;
private bool AutoUartTx = true;
private int addr_ch = 0;
private ushort RequestRegAddr = 0x0000; //Byul Init 0x0000
private ushort RequestRegLen = 50;
private bool rFlag = false;
private int rFlag2 = 0;
private ushort ReadRegAddr = 0x0000; //Byul Init 0x0000
private ushort ReadRegLen = 0x0000; //Byul Init 0x0000
private ushort WriteRegAddr = 0x0000; //Byul Init 0x0000
private short WriteCoilRegData = 0;
private byte[] WriteRegData;
private readonly ConcurrentQueue<byte> _rxQ = new ConcurrentQueue<byte>();
private TUartTxBuff UartTxBuff;
// 이벤트
public event EventHandler<ModuleDataEventArgs> OnUpdate;
public event EventHandler<DataRecvEventArgs> OnDataRecv;
public event EventHandler<PrintEventArgs> OnPrint;
#endregion
#region CONSTRUCTORS
public csUartThread(int mId,
CommConfig aConfig,
ISynchronizeInvoke uiInvoker, // ← 추가
CsDeviceData.DeviceModuleData aModuleData)
{
ModuleId = mId;
Config = aConfig;
ModuleData = aModuleData;
_ui = uiInvoker; // Form(this) 또는 어떤 Control
UartTxBuff = new TUartTxBuff();
}
public bool Start(ref CommConfig aConfig, int sId, bool aPolling)
{
ModuleId = sId;
UartPolling = aPolling;
//if (!Open(aConfig.UartPort, aConfig.UartBaudrate))
if (!Open(aConfig.UartPort, 115200))
return false;
// 이중 시작 방지
if (_serialComm != null && _serialComm.IsAlive)
return true;
_serialPortThreadEnd = false;
_cts = new CancellationTokenSource();
_serialComm = new Thread(() => uartCommThread(_cts.Token))
{
IsBackground = true,
Name = "UartCommThread"
};
_serialComm.Start();
return true;
}
private void Stop()
{
_serialPortThreadEnd = true;
var cts = _cts;
_cts = null;
if (cts != null && !cts.IsCancellationRequested)
cts.Cancel();
var t = _serialComm;
_serialComm = null;
if (t != null && t.IsAlive)
{
try { t.Join(500); } catch { /* timeout 시 로그만 */ }
}
Close(); // SerialPort 닫기 및 핸들러 해제
}
public void Dispose()
{
Stop();
}
#endregion
#region COMMPORT CONTROLS
private void sDataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
var sp = (SerialPort)sender;
int available = sp.BytesToRead;
if (available <= 0) return;
byte[] tmp = new byte[available];
int read = sp.Read(tmp, 0, tmp.Length);
for (int i = 0; i < read; i++)
_rxQ.Enqueue(tmp[i]);
}
catch (Exception)
{
/* 필요시 로그 */
}
}
private void sErrorReceived(object sender, System.IO.Ports.SerialErrorReceivedEventArgs e)
{
//
//csMakeDataFunction.SetData()
}
private void sPinChanged(object sender, System.IO.Ports.SerialPinChangedEventArgs e)
{
//
}
private bool Open(string cPort, int cBaudrate)
{
sPort = new SerialPort();
sPort.PortName = cPort;
sPort.BaudRate = cBaudrate;
sPort.DataReceived += sDataReceived;
sPort.ErrorReceived += sErrorReceived;
sPort.PinChanged += sPinChanged;
try
{
sPort.Open();
}
catch (Exception ex)
{
throw new Exception("Error Open - " + ex.Message);
}
return sPort.IsOpen;
}
private void Close()
{
if (sPort != null)
{
try
{
sPort.DataReceived -= sDataReceived;
sPort.ErrorReceived -= sErrorReceived;
sPort.PinChanged -= sPinChanged;
if (sPort.IsOpen) sPort.Close();
}
finally
{
sPort.Dispose();
sPort = null;
}
}
}
#endregion
#region PUBLIC FUNCTION
public void SetPolling(bool flag, int sId, ref CsDeviceData.DeviceModuleData aSystemData)
{
ModuleId = sId;
UartPolling = flag;
ModuleData = aSystemData;
ModuleData.mNo = ModuleId;
}
public void SetAutoTx(bool autoTx)
{
AutoUartTx = autoTx;
}
public void SetWriteReg(ushort WriteAddr, byte[] WriteData, bool ReplyFlag, int type)
{
WriteRegAddr = WriteAddr;
TUartTRxData uartTRxData = new TUartTRxData();
uartTRxData.type = type;
uartTRxData.data = WriteData;
uartTRxData.length = uartTRxData.data.Length;
UartTxBuff?.PutBuff(uartTRxData);
}
public void SetParam(ushort WriteAddr, short[] WriteData)
{
short[] wData = new short[1];
wData[0] = WriteData[0];
byte[] sData = CsModbusFunction.MakeWriteRegisterData((ushort)ModuleId, WriteAddr, wData);
if (sData != null)
{
TUartTRxData aData = new TUartTRxData();
aData.length = sData.Length;
aData.data = sData;
UartTxBuff.PutBuff(aData);
}
}
public void SendProcessFromApp(int sId, int mode, int index, int flag
, ref CsDeviceData.DeviceModuleData.DeviceParamData aParam, ref CsDeviceData.DeviceModuleData.DeviceCalibration aCalib)
{
short[] data = null;
switch (mode)
{
case csConstData.UART_PARAM_LIST.CELL_UNDER_VOLTAGE: // Cell Under Volatge Parameter
data = new short[1];
data[0] = aParam.CellUnderVoltageWarning; SetParam((ushort)(mode + 0), data);
data[0] = aParam.CellUnderVoltageTrip; SetParam((ushort)(mode + 1), data);
data[0] = aParam.CellUnderVoltageRelease; SetParam((ushort)(mode + 2), data);
break;
case csConstData.UART_PARAM_LIST.CELL_OVER_VOLTAGE: // Cell Over Volatge Parameter
data = new short[1];
data[0] = aParam.CellOverVoltageWarning; SetParam((ushort)(mode + 0), data);
data[0] = aParam.CellOverVoltageTrip; SetParam((ushort)(mode + 1), data);
data[0] = aParam.CellOverVoltageRelease; SetParam((ushort)(mode + 2), data);
break;
case csConstData.UART_PARAM_LIST.PACK_UNDER_VOLTAGE: // Pack Under Volatge Parameter
data = new short[1];
data[0] = (short)(aParam.SysUnderVoltageWarning * 10); SetParam((ushort)(mode + 0), data);
data[0] = (short)(aParam.SysUnderVoltageTrip * 10); SetParam((ushort)(mode + 1), data);
data[0] = (short)(aParam.SysUnderVoltageRelease * 10); SetParam((ushort)(mode + 2), data);
break;
case csConstData.UART_PARAM_LIST.PACK_OVER_VOLTAGE: // Pack Over Volatge Parameter
data = new short[1];
data[0] = (short)(aParam.SysOverVoltageWarning * 10); SetParam((ushort)(mode + 0), data);
data[0] = (short)(aParam.SysOverVoltageTrip * 10); SetParam((ushort)(mode + 1), data);
data[0] = (short)(aParam.SysOverVoltageRelease * 10); SetParam((ushort)(mode + 2), data);
break;
case csConstData.UART_PARAM_LIST.CHG_LOW_TEMPERATURE: // Charge Low Temperature Parameter
data = new short[1];
data[0] = (short)(aParam.ChaLowTempWarning + 50); SetParam((ushort)(mode + 0), data);
data[0] = (short)(aParam.ChaLowTempTrip + 50); SetParam((ushort)(mode + 1), data);
data[0] = (short)(aParam.ChaLowTempRelease + 50); SetParam((ushort)(mode + 2), data);
break;
case csConstData.UART_PARAM_LIST.CHG_HIGH_TEMPERATURE: // Pack High Temperature Parameter
data = new short[1];
data[0] = (short)(aParam.ChaHighTempWarning + 50); SetParam((ushort)(mode + 0), data);
data[0] = (short)(aParam.ChaHighTempTrip + 50); SetParam((ushort)(mode + 1), data);
data[0] = (short)(aParam.ChaHighTempRelease + 50); SetParam((ushort)(mode + 2), data);
break;
case csConstData.UART_PARAM_LIST.DCH_LOW_TEMPERATURE: // Charge Low Temperature Parameter
data = new short[1];
data[0] = (short)(aParam.DchLowTempWarning + 50); SetParam((ushort)(mode + 0), data);
data[0] = (short)(aParam.DchLowTempTrip + 50); SetParam((ushort)(mode + 1), data);
data[0] = (short)(aParam.DchLowTempRelease + 50); SetParam((ushort)(mode + 2), data);
break;
case csConstData.UART_PARAM_LIST.DCH_HIGH_TEMPERATURE: // Pack High Temperature Parameter
data = new short[1];
data[0] = (short)(aParam.DchHighTempWarning + 50); SetParam((ushort)(mode + 0), data);
data[0] = (short)(aParam.DchHighTempTrip + 50); SetParam((ushort)(mode + 1), data);
data[0] = (short)(aParam.DchHighTempRelease + 50); SetParam((ushort)(mode + 2), data);
break;
case csConstData.UART_PARAM_LIST.CHG_OVER_CURRENT: // Charge Over Current Parameter
data = new short[1];
data[0] = (short)(aParam.ChaOverCurrentReleaseTime * 1); SetParam((ushort)(mode + 0), data);
data[0] = (short)(aParam.ChaOverCurrentTrip1 * 10); SetParam((ushort)(mode + 2), data);
data[0] = (short)(aParam.ChaOverCurrentTrip2 * 10); SetParam((ushort)(mode + 5), data);
break;
case csConstData.UART_PARAM_LIST.DCH_OVER_CURRENT: // Discharge Over Current Parameter
data = new short[1];
data[0] = (short)(aParam.DchOverCurrentReleaseTime * 1); SetParam((ushort)(mode + 0), data);
data[0] = (short)(aParam.DchOverCurrentTrip1 * 10); SetParam((ushort)(mode + 2), data);
data[0] = (short)(aParam.DchOverCurrentTrip2 * 10); SetParam((ushort)(mode + 5), data);
break;
case csConstData.UART_PARAM_LIST.LOW_CAPACITY:
data = new short[1];
data[0] = aParam.LowSocWarning; SetParam((ushort)(mode + 0), data);
break;
case csConstData.UART_PARAM_LIST.DEFAULT_PARAM: // Default Parameter
int i = 0;
Forms.fmxWait WaitForm = new Forms.fmxWait();
WaitForm.StartPosition = FormStartPosition.CenterScreen;
try
{
//WaitForm.Show();
data = new short[1];
i = csConstData.UART_PARAM_LIST.CELL_UNDER_VOLTAGE;
data[0] = csConstData.UART_PARAM_DEFAULT.Warn_Cell_UV; SetParam((ushort)(i + 0), data);
data[0] = csConstData.UART_PARAM_DEFAULT.Protect_Cell_UV; SetParam((ushort)(i + 1), data);
data[0] = csConstData.UART_PARAM_DEFAULT.Release_Cell_UV; SetParam((ushort)(i + 2), data);
i = csConstData.UART_PARAM_LIST.PACK_UNDER_VOLTAGE;
data[0] = csConstData.UART_PARAM_DEFAULT.Warn_Pack_UV; SetParam((ushort)(i + 0), data);
data[0] = csConstData.UART_PARAM_DEFAULT.Protect_Pack_UV; SetParam((ushort)(i + 1), data);
data[0] = csConstData.UART_PARAM_DEFAULT.Release_Pack_UV; SetParam((ushort)(i + 2), data);
i = csConstData.UART_PARAM_LIST.CELL_OVER_VOLTAGE;
data[0] = csConstData.UART_PARAM_DEFAULT.Warn_Cell_OV; SetParam((ushort)(i + 0), data);
data[0] = csConstData.UART_PARAM_DEFAULT.Protect_Cell_OV; SetParam((ushort)(i + 1), data);
data[0] = csConstData.UART_PARAM_DEFAULT.Release_Cell_OV; SetParam((ushort)(i + 2), data);
i = csConstData.UART_PARAM_LIST.PACK_OVER_VOLTAGE;
data[0] = csConstData.UART_PARAM_DEFAULT.Warn_Pack_OV; SetParam((ushort)(i + 0), data);
data[0] = csConstData.UART_PARAM_DEFAULT.Protect_Pack_OV; SetParam((ushort)(i + 1), data);
data[0] = csConstData.UART_PARAM_DEFAULT.Release_Pack_OV; SetParam((ushort)(i + 2), data);
i = csConstData.UART_PARAM_LIST.CHG_OVER_CURRENT;
data[0] = csConstData.UART_PARAM_DEFAULT.Times_Charge_OC; SetParam((ushort)(i - 2), data);
data[0] = csConstData.UART_PARAM_DEFAULT.ReleaseTime_Charge_OC; SetParam((ushort)(i + 0), data);
data[0] = csConstData.UART_PARAM_DEFAULT.Protect_Charge_OC1; SetParam((ushort)(i + 2), data);
data[0] = csConstData.UART_PARAM_DEFAULT.Protect_Charge_OC2; SetParam((ushort)(i + 5), data);
data[0] = csConstData.UART_PARAM_DEFAULT.Delay_Charge_OC1; SetParam((ushort)(i + 8), data);
data[0] = csConstData.UART_PARAM_DEFAULT.Delay_Charge_OC2; SetParam((ushort)(i + 9), data);
i = csConstData.UART_PARAM_LIST.DCH_OVER_CURRENT;
data[0] = csConstData.UART_PARAM_DEFAULT.Times_Discharge_OC; SetParam((ushort)(i - 2), data);
data[0] = csConstData.UART_PARAM_DEFAULT.ReleaseTime_Discharge_OC; SetParam((ushort)(i + 0), data);
data[0] = csConstData.UART_PARAM_DEFAULT.Protect_Discharge_OC1; SetParam((ushort)(i + 2), data);
data[0] = csConstData.UART_PARAM_DEFAULT.Protect_Discharge_OC2; SetParam((ushort)(i + 5), data);
data[0] = csConstData.UART_PARAM_DEFAULT.Delay_Discharge_OC1; SetParam((ushort)(i + 8), data);
data[0] = csConstData.UART_PARAM_DEFAULT.Delay_Discharge_OC2; SetParam((ushort)(i + 9), data);
i = csConstData.UART_PARAM_LIST.CHG_LOW_TEMPERATURE;
data[0] = (short)(csConstData.UART_PARAM_DEFAULT.Warn_Charge_UT + 50); SetParam((ushort)(i + 0), data);
data[0] = (short)(csConstData.UART_PARAM_DEFAULT.Protect_Charge_UT + 50); SetParam((ushort)(i + 1), data);
data[0] = (short)(csConstData.UART_PARAM_DEFAULT.Release_Charge_UT + 50); SetParam((ushort)(i + 2), data);
i = csConstData.UART_PARAM_LIST.CHG_HIGH_TEMPERATURE;
data[0] = (short)(csConstData.UART_PARAM_DEFAULT.Warn_Charge_OT + 50); SetParam((ushort)(i + 0), data);
data[0] = (short)(csConstData.UART_PARAM_DEFAULT.Protect_Charge_OT + 50); SetParam((ushort)(i + 1), data);
data[0] = (short)(csConstData.UART_PARAM_DEFAULT.Release_Charge_OT + 50); SetParam((ushort)(i + 2), data);
i = csConstData.UART_PARAM_LIST.DCH_LOW_TEMPERATURE;
data[0] = (short)(csConstData.UART_PARAM_DEFAULT.Warn_Discharge_UT + 50); SetParam((ushort)(i + 0), data);
data[0] = (short)(csConstData.UART_PARAM_DEFAULT.Protect_Discharge_UT + 50); SetParam((ushort)(i + 1), data);
data[0] = (short)(csConstData.UART_PARAM_DEFAULT.Release_Discharge_UT + 50); SetParam((ushort)(i + 2), data);
i = csConstData.UART_PARAM_LIST.DCH_HIGH_TEMPERATURE;
data[0] = (short)(csConstData.UART_PARAM_DEFAULT.Warn_Discharge_OT + 50); SetParam((ushort)(i + 0), data);
data[0] = (short)(csConstData.UART_PARAM_DEFAULT.Protect_Discharge_OT + 50); SetParam((ushort)(i + 1), data);
data[0] = (short)(csConstData.UART_PARAM_DEFAULT.Release_Discharge_OT + 50); SetParam((ushort)(i + 2), data);
i = csConstData.UART_PARAM_LIST.LOW_CAPACITY;
data[0] = csConstData.UART_PARAM_DEFAULT.Warn_Low_Capacity + 0; SetParam((ushort)(i + 0), data);
i = csConstData.UART_PARAM_LIST.ENV_LOW_TEMPERATURE;
data[0] = 0; SetParam((ushort)(i + 0), data);
data[0] = 0; SetParam((ushort)(i + 1), data);
data[0] = 0; SetParam((ushort)(i + 2), data);
i = csConstData.UART_PARAM_LIST.ENV_HIGH_TEMPERATURE;
data[0] = 0; SetParam((ushort)(i + 0), data);
data[0] = 0; SetParam((ushort)(i + 1), data);
data[0] = 0; SetParam((ushort)(i + 2), data);
}
catch (Exception)
{
}
finally
{
//WaitForm?.Close();
}
break;
case 15: // Capcity change
data = new short[1];
i = csConstData.UART_PARAM_LIST.DESIGN_CAPACITY;
data[0] = (short)aCalib.CapCalib.DesignCapacity; SetParam((ushort)(i + 0), data);
i = csConstData.UART_PARAM_LIST.SOC_VALUE;
data[0] = (short)aCalib.CapCalib.SocValue; SetParam((ushort)(i + 0), data);
break;
case 16: // Charge Mode
data = new short[1];
i = csConstData.UART_CALIB_ADDR_LIST.CHAGE_MODE;
data[0] = (short)aCalib.ChaMode.Mode; SetParam((ushort)(i + 0), data);
data[0] = (short)aCalib.ChaMode.Value; SetParam((ushort)(i + 1), data);
break;
case 17: // BMS DateTime Set
data = new short[2];
i = csConstData.UART_CALIB_ADDR_LIST.BMS_DATETIME;
data[0] = (short)aCalib.BmsDateTime.sValue[0];
data[1] = (short)aCalib.BmsDateTime.sValue[1]; SetParam((ushort)(i + 0), data);
break;
case 18:
data = new short[1];
i = csConstData.UART_CALIB_ADDR_LIST.ANTI_THEFT_GYRO;
data[0] = (short)aCalib.AntiTheft.GyroScope; SetParam((ushort)(i + 0), data);
break;
case 19: // Clear Protect
data = new short[1];
i = csConstData.UART_CALIB_ADDR_LIST.ANTI_THEFT_GYRO;
data[0] = (short)0; SetParam((ushort)(i + 0), data);
data[0] = (short)aCalib.AntiTheft.GyroScope; SetParam((ushort)(i + 0), data);
break;
case 20:
data = new short[1];
i = csConstData.UART_CALIB_ADDR_LIST.ANTI_THEFT_COMM;
data[0] = (short)aCalib.AntiTheft.Comm; SetParam((ushort)(i + 0), data);
break;
default:
break;
}
}
#endregion
#region RX BUFFERING
private int GetBuff()
{
return _rxQ.TryDequeue(out var b) ? (0x0100 | b) : 0;
}
private void FlushBuff()
{
while (_rxQ.TryDequeue(out _)) { }
}
#endregion
#region TX BUFFERING
private byte[] MakeWriteRegData(ushort DevID, ushort WriteAddr, ushort WriteLen, ref ushort[] WriteData)
{
byte[] wData = null;
if (WriteLen > 0)
{
}
return wData;
}
private string MakeCheckSum(byte[] sData, int len)
{
string result = "";
int checksum = 0;
for (int i = 0; i < len; i++)
{
checksum += sData[i + 1];
}
checksum = ~checksum + 1;
result = String.Format("{0:X2}{1:X2}", (byte)(checksum >> 8), (byte)checksum);
return result;
}
private byte[] MakeTxDataUart()
{
byte[] sData = null;
rFlag2 = 0;
if ((UartTxBuff != null) && (UartTxBuff.CheckBuff()))
{
TUartTRxData sBuff = UartTxBuff.GetBuff();
if (sBuff != null)
{
sData = sBuff.data;
rFlag = true;
rFlag2 = sBuff.type;
}
}
else
{
if (UartPolling && AutoUartTx)
{
ushort sCmd;
switch (addr_ch)
{
case 0:
addr_ch = 1;
RequestRegAddr = 0x0000; //Byul Init 0x0000
RequestRegLen = 0x0040;
sCmd = csSerialCommFunction.READ_HOLDING_REG;
rFlag = true;
break;
case 1:
addr_ch = 2;
RequestRegAddr = 0x0040;
RequestRegLen = 0x0040;
sCmd = csSerialCommFunction.READ_HOLDING_REG;
rFlag = true;
break;
case 2:
addr_ch = 3;
RequestRegAddr = 0x0080;
RequestRegLen = 0x0020 + 7;
sCmd = csSerialCommFunction.READ_HOLDING_REG;
rFlag = true;
break;
case 3:
if (Config.ModuleQty > 1)
{
ModuleId++;
if (ModuleId > Config.ModuleQty)
{
ModuleId = 1;
}
}
addr_ch = 0;
sCmd = csSerialCommFunction.NO_CMD;
rFlag = false;
break;
default:
addr_ch = 0;
RequestRegAddr = 0x0000; //Byul Init 0x0000
RequestRegLen = 100;
sCmd = csSerialCommFunction.READ_HOLDING_REG;
break;
}
if (sCmd == csSerialCommFunction.NO_CMD)
{
sData = null;
}
else
{
sData = csSerialCommFunction.MakeReadRegisterData((ushort)ModuleId, sCmd, RequestRegAddr, RequestRegLen);
}
}
}
return sData;
}
#endregion
#region COMM THREAD
private readonly byte[] ReadBuf = new byte[RX_PACKET_BUFFER_SIZE];
ushort rPosition = 0;
bool BuffStart = false;
private void RecvPacketInit()
{
BuffStart = false;
rPosition = 0;
}
private void uartCommThread(CancellationToken token)
{
int RecvTimeout = Config.RecvWaitTime;
int TimeOutCount = 0;
StartSend:
while (!token.IsCancellationRequested && !_serialPortThreadEnd)
{
if (sPort == null || !sPort.IsOpen) { Thread.Sleep(50); continue; }
FlushBuff();
byte[] txData = MakeTxDataUart();
if (txData != null)
{
try
{
sPort.Write(txData, 0, txData.Length);
RaiseOnPrint(txData[0], csLog.trx_data_print(txData, txData.Length, 0));
}
catch
{
/* 로그 */
RaiseOnPrint(ModuleId, "UART-232 Thread - TX Buff Error !");
}
}
if (rFlag == true)
{
var deadline = DateTime.UtcNow.AddMilliseconds(RecvTimeout);
RecvPacketInit();
while (DateTime.UtcNow < deadline)
{
int gd = GetBuff();
if ((gd & 0x0100) == 0) { Thread.Sleep(1); continue; }
byte cData = (byte)(gd & 0xFF);
if (!BuffStart)
{
if (cData == (byte)ModuleId || cData == 0x7F)
{
rPosition = 0;
ReadBuf[rPosition++] = cData;
BuffStart = true;
}
}
else
{
if (rPosition >= ReadBuf.Length) { RecvPacketInit(); continue; }
ReadBuf[rPosition++] = cData;
int chk = CsSerialCommFunctionDelta.ModbusPacketFromSlaveCheck(ReadBuf, rPosition);
if (chk == 0) continue;
RaiseOnPrint(ReadBuf[0], csLog.trx_data_print(ReadBuf, rPosition, 1));
if (chk == 1)
{
int mID = ReadBuf[0];
if (mID > 0) mID--;
ModuleData.CommFail = false;
ModuleData.ShelfCommFail = false;
var rc = csSerialCommFunction.SerialRxProcess(
ReadBuf, RequestRegAddr, (ushort)rPosition, ref ModuleData);
var snapshot1 = ModuleData; // 필요 시 DeepCopy
RaiseOnUpdate(snapshot1);
Thread.Sleep(5);
goto StartSend;
}
else if (chk == 2)
{
rFlag = false;
RaiseOnPrint(ReadBuf[0], csLog.trx_data_print(ReadBuf, rPosition, 1));
goto StartSend;
}
else // -1
{
RecvPacketInit();
Thread.Sleep(50);
goto StartSend;
}
}
}
// timeout
if (rPosition > 0)
{
RaiseOnPrint(ReadBuf[0], csLog.trx_data_print(ReadBuf, rPosition, 1));
}
else
{
WriteRegAddr = 0;
TimeOutCount++;
if (TimeOutCount >= 5)
{
TimeOutCount = 5;
//SystemData[0].CommFail = true;
if (ModuleData.ShelfCommFail == false)
{
ModuleData.Reset();
ModuleData.ShelfCommFail = true;
}
}
Thread.Sleep(100);
}
var snapshot2 = ModuleData; // 필요 시 DeepCopy
RaiseOnUpdate(snapshot2);
}
else
{
Thread.Sleep(100);
} /* if (rFlag == true) */
rPosition = 0;
Thread.Sleep(50);
}
}
#endregion
#region SAFETY RAISE HELPER
private void RaiseOnUpdate(CsDeviceData.DeviceModuleData snapshot)
{
var handler = OnUpdate;
if (handler == null) return;
var args = new ModuleDataEventArgs(snapshot);
if (_ui != null && _ui.InvokeRequired)
{
try { _ui.BeginInvoke(new Action(() => handler(this, args)), null); }
catch { /* 폼 종료 중 등 예외 무시(로그만) */ }
}
else
{
handler(this, args);
}
}
private void RaiseOnDataRecv(byte[] data)
{
var handler = OnDataRecv;
if (handler == null) return;
var args = new DataRecvEventArgs(data);
if (_ui != null && _ui.InvokeRequired)
{
try { _ui.BeginInvoke(new Action(() => handler(this, args)), null); }
catch { }
}
else
{
handler(this, args);
}
}
private void RaiseOnPrint(int id, string msg)
{
var handler = OnPrint;
if (handler == null) return;
var args = new PrintEventArgs(id, msg);
if (_ui != null && _ui.InvokeRequired)
{
try { _ui.BeginInvoke(new Action(() => handler(this, args)), null); }
catch { }
}
else
{
handler(this, args);
}
}
#endregion
}
}