Release v1.1.1.1: Anti-Theft buttons update, BMS history chg_wait column, and wait for charging status display
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
|
||||
using System.Threading;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO.Ports;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using LFP_Manager.DataStructure;
|
||||
@@ -12,6 +12,7 @@ namespace LFP_Manager.Threads
|
||||
public delegate void UartDataUpdate(object sender, ref DeviceSystemData aSystemData);
|
||||
public delegate void UartDataRecv(byte[] data);
|
||||
public delegate void UartDataPrint(object sender, string msg);
|
||||
public delegate void UartPacketLogEvent(DateTime timestamp, bool isTx, byte[] packet, string description);
|
||||
|
||||
class csUartThread
|
||||
{
|
||||
@@ -28,23 +29,14 @@ namespace LFP_Manager.Threads
|
||||
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 wFlag = 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 TUartTxBuff uartTxBuff = null;
|
||||
// Thread-Safe TX Queue
|
||||
private readonly ConcurrentQueue<TUartTxItem> txQueue = new ConcurrentQueue<TUartTxItem>();
|
||||
|
||||
public event UartDataUpdate OnUpdate = null;
|
||||
public event UartDataRecv OnDataRecv = null;
|
||||
public event UartDataPrint OnPrint = null;
|
||||
public event UartPacketLogEvent OnPacketLog = null;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -56,8 +48,6 @@ namespace LFP_Manager.Threads
|
||||
Config = aConfig;
|
||||
SystemData = aSystemData;
|
||||
|
||||
uartTxBuff = new TUartTxBuff();
|
||||
|
||||
serialComm = new Thread(uartCommThread);
|
||||
}
|
||||
|
||||
@@ -130,13 +120,10 @@ namespace LFP_Manager.Threads
|
||||
|
||||
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)
|
||||
@@ -174,7 +161,7 @@ namespace LFP_Manager.Threads
|
||||
|
||||
#endregion
|
||||
|
||||
#region PUBLIC FUNCTION
|
||||
#region PUBLIC TX FUNCTIONS (QUEUE BASED)
|
||||
|
||||
public void SetPolling(bool flag, int sId, ref DeviceSystemData aSystemData)
|
||||
{
|
||||
@@ -189,52 +176,66 @@ namespace LFP_Manager.Threads
|
||||
AutoUartTx = autoTx;
|
||||
}
|
||||
|
||||
public void SetWriteCoilReg(ushort WriteAddr, short WriteData)
|
||||
/// <summary>
|
||||
/// 공통 TX 큐 삽입 메서드
|
||||
/// </summary>
|
||||
public void EnqueueTx(TUartTxItem item)
|
||||
{
|
||||
wFlag = 2;
|
||||
WriteRegAddr = WriteAddr;
|
||||
WriteCoilRegData = WriteData;
|
||||
|
||||
for (int i = 0; i < 500; i += 10)
|
||||
if (item != null)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
Application.DoEvents();
|
||||
txQueue.Enqueue(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 원시 패킷 전송 (FW 업데이트 등)
|
||||
/// </summary>
|
||||
public void SendRawPacket(byte[] rawData, bool expectReply = true)
|
||||
{
|
||||
if (rawData == null || rawData.Length == 0) return;
|
||||
TUartTxItem item = new TUartTxItem(UartTxType.Raw, SystemId, 0, (ushort)rawData.Length, rawData, expectReply, Config.RecvWaitTime);
|
||||
EnqueueTx(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 코일 레지스터 쓰기 (TX 큐 삽입)
|
||||
/// </summary>
|
||||
public void SetWriteCoilReg(ushort WriteAddr, short WriteData)
|
||||
{
|
||||
byte[] data = csSerialCommFunction.MakeWriteCoilData((ushort)SystemId, WriteAddr, WriteData);
|
||||
TUartTxItem item = new TUartTxItem(UartTxType.WriteCoil, SystemId, WriteAddr, 1, data, true, Config.RecvWaitTime);
|
||||
EnqueueTx(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 레지스터 쓰기 (TX 큐 삽입)
|
||||
/// </summary>
|
||||
public void SetWriteReg(ushort WriteAddr, byte[] WriteData, bool ReplyFlag)
|
||||
{
|
||||
wFlag = 1;
|
||||
|
||||
WriteRegAddr = WriteAddr;
|
||||
|
||||
TUartTRxData uartTRxData = new TUartTRxData();
|
||||
uartTRxData.type = wFlag;
|
||||
//uartTRxData.data = csSerialCommFunction.MakeWriteRegisterData((ushort)SystemId, WriteRegAddr, WriteData);
|
||||
uartTRxData.data = WriteData;
|
||||
uartTRxData.length = uartTRxData.data.Length;
|
||||
|
||||
uartTxBuff?.PutBuff(uartTRxData);
|
||||
if (WriteData == null) return;
|
||||
TUartTxItem item = new TUartTxItem(UartTxType.WriteReg, SystemId, WriteAddr, (ushort)WriteData.Length, WriteData, ReplyFlag, Config.RecvWaitTime);
|
||||
EnqueueTx(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 레지스터 읽기 (TX 큐 삽입)
|
||||
/// </summary>
|
||||
public void SetReadReg(ushort ReadAddr, ushort ReadLen, bool ReplyFlag)
|
||||
{
|
||||
wFlag = 4;
|
||||
ReadRegAddr = ReadAddr;
|
||||
ReadRegLen = ReadLen;
|
||||
byte[] data = csSerialCommFunction.MakeReadRegisterData((ushort)SystemId, csSerialCommFunction.READ_HOLDING_REG, ReadAddr, ReadLen);
|
||||
TUartTxItem item = new TUartTxItem(UartTxType.ReadReg, SystemId, ReadAddr, ReadLen, data, ReplyFlag, Config.RecvWaitTime);
|
||||
EnqueueTx(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 파라미터 레지스터 쓰기 (TX 큐 삽입)
|
||||
/// </summary>
|
||||
public void SetParam(ushort WriteAddr, short[] WriteData)
|
||||
{
|
||||
wFlag = 1;
|
||||
|
||||
WriteRegAddr = WriteAddr;
|
||||
|
||||
TUartTRxData uartTRxData = new TUartTRxData();
|
||||
uartTRxData.type = wFlag;
|
||||
uartTRxData.data = csSerialCommFunction.MakeWriteRegisterData((ushort)SystemId, WriteRegAddr, WriteData);
|
||||
uartTRxData.length = uartTRxData.data.Length;
|
||||
|
||||
uartTxBuff?.PutBuff(uartTRxData);
|
||||
if (WriteData == null) return;
|
||||
byte[] data = csSerialCommFunction.MakeWriteRegisterData((ushort)SystemId, WriteAddr, WriteData);
|
||||
TUartTxItem item = new TUartTxItem(UartTxType.WriteParam, SystemId, WriteAddr, (ushort)WriteData.Length, data, true, Config.RecvWaitTime);
|
||||
EnqueueTx(item);
|
||||
}
|
||||
|
||||
public void SendProcessFromApp(int sId, int mode, int index, int flag, ref DeviceParamData aParam, ref DeviceCalibration aCalib)
|
||||
@@ -315,13 +316,8 @@ namespace LFP_Manager.Threads
|
||||
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;
|
||||
@@ -385,10 +381,6 @@ namespace LFP_Manager.Threads
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
//WaitForm?.Close();
|
||||
}
|
||||
break;
|
||||
case 15: // Capcity change
|
||||
@@ -413,16 +405,11 @@ namespace LFP_Manager.Threads
|
||||
case 18:
|
||||
data = new short[1];
|
||||
i = csConstData.UART_CALIB_ADDR_LIST.ANTI_THEFT;
|
||||
//data[0] = (short)aCalib.AntiTheft.Comm; SetParam((ushort)(i + 0), data);
|
||||
data[0] = (short)aCalib.AntiTheft.GyroScope; SetParam((ushort)(i + 1), data);
|
||||
break;
|
||||
case 19:
|
||||
data = new short[1];
|
||||
i = csConstData.UART_CALIB_ADDR_LIST.ANTI_THEFT;
|
||||
//data[0] = (short)0; SetParam((ushort)(i + 0), data);
|
||||
data[0] = (short)0; SetParam((ushort)(i + 1), data);
|
||||
|
||||
//data[0] = (short)aCalib.AntiTheft.Comm; SetParam((ushort)(i + 0), data);
|
||||
data[0] = (short)aCalib.AntiTheft.GyroScope; SetParam((ushort)(i + 1), data);
|
||||
break;
|
||||
default:
|
||||
@@ -471,176 +458,84 @@ namespace LFP_Manager.Threads
|
||||
|
||||
#endregion
|
||||
|
||||
#region TX BUFFERING
|
||||
#region POLLING GENERATOR
|
||||
|
||||
private byte[] MakeWriteRegData(ushort DevID, ushort WriteAddr, ushort WriteLen, ref ushort[] WriteData)
|
||||
/// <summary>
|
||||
/// 다음 주기 Polling 패킷 아이템 생성
|
||||
/// </summary>
|
||||
private TUartTxItem CreateNextPollingItem()
|
||||
{
|
||||
byte[] wData = null;
|
||||
ushort reqAddr = 0x0000;
|
||||
ushort reqLen = 50;
|
||||
ushort sCmd = csSerialCommFunction.READ_HOLDING_REG;
|
||||
|
||||
if (WriteLen > 0)
|
||||
switch (addr_ch)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
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[] MakeTxDataVision(ref bool wData)
|
||||
{
|
||||
byte[] sData = null;
|
||||
|
||||
if ((uartTxBuff != null) && (uartTxBuff.CheckBuff()))
|
||||
{
|
||||
TUartTRxData sBuff = uartTxBuff.GetBuff();
|
||||
if (sBuff != null)
|
||||
{
|
||||
sData = sBuff.data;
|
||||
wData = true;
|
||||
rFlag = true;
|
||||
}
|
||||
}
|
||||
else if (wFlag == 2)
|
||||
{
|
||||
sData = csSerialCommFunction.MakeWriteCoilData((ushort)SystemId, WriteRegAddr, WriteCoilRegData);
|
||||
if (wFlag != 0) wFlag = 0;
|
||||
rFlag = true;
|
||||
}
|
||||
else if (wFlag == 3)
|
||||
{
|
||||
sData = WriteRegData;
|
||||
if (wFlag != 0) wFlag = 0;
|
||||
rFlag = true;
|
||||
}
|
||||
else if (wFlag == 4)
|
||||
{
|
||||
sData = csSerialCommFunction.MakeReadRegisterData((ushort)SystemId, csSerialCommFunction.READ_HOLDING_REG, ReadRegAddr, ReadRegLen);
|
||||
if (wFlag != 0) wFlag = 0;
|
||||
rFlag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (UartPolling && AutoUartTx)
|
||||
{
|
||||
ushort sCmd;
|
||||
switch (addr_ch)
|
||||
{
|
||||
case 0:
|
||||
addr_ch = 1;
|
||||
RequestRegAddr = 0x0000; //Byul Init 0x0000
|
||||
RequestRegLen = 0x0031;
|
||||
sCmd = csSerialCommFunction.READ_HOLDING_REG;
|
||||
rFlag = true;
|
||||
break;
|
||||
case 1:
|
||||
addr_ch = 4;
|
||||
RequestRegAddr = 58;
|
||||
RequestRegLen = 138-58;
|
||||
sCmd = csSerialCommFunction.READ_HOLDING_REG;
|
||||
rFlag = true;
|
||||
break;
|
||||
case 2:
|
||||
addr_ch = 3;
|
||||
RequestRegAddr = 0x3078;
|
||||
RequestRegLen = 8;
|
||||
sCmd = csSerialCommFunction.READ_COIL_STATUS;
|
||||
rFlag = true;
|
||||
break;
|
||||
case 3:
|
||||
addr_ch = 4;
|
||||
RequestRegAddr = 0x502E;
|
||||
RequestRegLen = 1;
|
||||
sCmd = csSerialCommFunction.READ_COIL_STATUS;
|
||||
rFlag = true;
|
||||
break;
|
||||
case 4:
|
||||
if (Config.ModuleQty > 1)
|
||||
{
|
||||
SystemId++;
|
||||
if (SystemId > Config.ModuleQty)
|
||||
{
|
||||
SystemId = 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)SystemId, sCmd, RequestRegAddr, RequestRegLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
return sData;
|
||||
}
|
||||
|
||||
private byte ReqCmd = 0x42;
|
||||
private byte RequstedCmd;
|
||||
|
||||
private byte[] TxProcess()
|
||||
{
|
||||
byte[] result = null;
|
||||
|
||||
switch (ReqCmd)
|
||||
{
|
||||
case 0x42: // Get the number of PACK
|
||||
csSerialCommFunction.MakeTxData(0x01, ReqCmd, 2);
|
||||
RequstedCmd = ReqCmd;
|
||||
ReqCmd = 0x46;
|
||||
case 0:
|
||||
addr_ch = 1;
|
||||
reqAddr = 0x0000;
|
||||
reqLen = 0x0031; // 49
|
||||
sCmd = csSerialCommFunction.READ_HOLDING_REG;
|
||||
break;
|
||||
case 0x46: // Ger the analog information
|
||||
csSerialCommFunction.MakeTxData(0x01, ReqCmd, 2);
|
||||
RequstedCmd = ReqCmd;
|
||||
ReqCmd = 0x46;
|
||||
case 1:
|
||||
addr_ch = 4;
|
||||
reqAddr = 58;
|
||||
reqLen = 139 - 58; // 81 (Registers 58 ~ 138)
|
||||
sCmd = csSerialCommFunction.READ_HOLDING_REG;
|
||||
break;
|
||||
case 0x90: // Ger warning information
|
||||
csSerialCommFunction.MakeTxData(0x01, ReqCmd, 2);
|
||||
RequstedCmd = ReqCmd;
|
||||
ReqCmd = 0x46;
|
||||
case 2:
|
||||
addr_ch = 3;
|
||||
reqAddr = 0x3078;
|
||||
reqLen = 8;
|
||||
sCmd = csSerialCommFunction.READ_COIL_STATUS;
|
||||
break;
|
||||
case 3:
|
||||
addr_ch = 4;
|
||||
reqAddr = 0x502E;
|
||||
reqLen = 1;
|
||||
sCmd = csSerialCommFunction.READ_COIL_STATUS;
|
||||
break;
|
||||
case 4:
|
||||
if (Config.ModuleQty > 1)
|
||||
{
|
||||
SystemId++;
|
||||
if (SystemId > Config.ModuleQty)
|
||||
{
|
||||
SystemId = 1;
|
||||
}
|
||||
}
|
||||
addr_ch = 0;
|
||||
sCmd = csSerialCommFunction.NO_CMD;
|
||||
break;
|
||||
default:
|
||||
ReqCmd = 0x42;
|
||||
addr_ch = 0;
|
||||
reqAddr = 0x0000;
|
||||
reqLen = 100;
|
||||
sCmd = csSerialCommFunction.READ_HOLDING_REG;
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
if (sCmd == csSerialCommFunction.NO_CMD)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] sData = csSerialCommFunction.MakeReadRegisterData((ushort)SystemId, sCmd, reqAddr, reqLen);
|
||||
if (sData == null || sData.Length == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new TUartTxItem(UartTxType.Polling, SystemId, reqAddr, reqLen, sData, true, Config.RecvWaitTime);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region COMM THREAD
|
||||
#region COMM THREAD (QUEUE BASED PIPELINE)
|
||||
|
||||
private readonly byte[] ReadBuf = new byte[BUFFER_SIZE];
|
||||
ushort rPosition = 0;
|
||||
bool BuffStart = false;
|
||||
private ushort rPosition = 0;
|
||||
private bool BuffStart = false;
|
||||
|
||||
private void RecvPacketInit()
|
||||
{
|
||||
@@ -650,153 +545,180 @@ namespace LFP_Manager.Threads
|
||||
|
||||
private void uartCommThread()
|
||||
{
|
||||
int RecvTimeout = Config.RecvWaitTime;
|
||||
int getData = 0;
|
||||
byte cData = 0;
|
||||
int TimeOutCount = 0;
|
||||
|
||||
StartSend:
|
||||
while (SerialPortThreadEnd == false)
|
||||
{
|
||||
if ((sPort == null) || (sPort.IsOpen == false)) continue;
|
||||
|
||||
//if (UartPolling)
|
||||
if (true)
|
||||
if ((sPort == null) || (sPort.IsOpen == false))
|
||||
{
|
||||
bool wMode = false;
|
||||
byte[] txData = MakeTxDataVision(ref wMode);
|
||||
if (sPort == null) return;
|
||||
if (txData != null)
|
||||
Thread.Sleep(50);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 1. 큐가 비어있고 Polling이 활성화되어 있을 때 다음 Polling 패킷을 TX 큐에 삽입
|
||||
if (txQueue.IsEmpty && UartPolling && AutoUartTx)
|
||||
{
|
||||
TUartTxItem pollItem = CreateNextPollingItem();
|
||||
if (pollItem != null)
|
||||
{
|
||||
FlushBuff();
|
||||
sPort.Write(txData, 0, txData.Length);
|
||||
txQueue.Enqueue(pollItem);
|
||||
}
|
||||
|
||||
if (rFlag == true)
|
||||
else
|
||||
{
|
||||
int rTimeOut = RecvTimeout;
|
||||
RecvPacketInit();
|
||||
Thread.Sleep(10);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
while (rTimeOut > 0)
|
||||
// 2. TX 큐에서 패킷 1개 꺼내기
|
||||
if (!txQueue.TryDequeue(out TUartTxItem currentTx) || currentTx == null || currentTx.Data == null || currentTx.Data.Length == 0)
|
||||
{
|
||||
Thread.Sleep(20);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 3. SerialPort로 패킷 전송
|
||||
try
|
||||
{
|
||||
FlushBuff();
|
||||
sPort.Write(currentTx.Data, 0, currentTx.Data.Length);
|
||||
OnPacketLog?.Invoke(DateTime.Now, true, currentTx.Data, GetTxDescription(currentTx));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Thread.Sleep(50);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 4. 응답 대기 및 수신 처리
|
||||
if (currentTx.ExpectReply)
|
||||
{
|
||||
int rTimeOut = currentTx.TimeoutMs > 0 ? currentTx.TimeoutMs : Config.RecvWaitTime;
|
||||
RecvPacketInit();
|
||||
bool packetHandled = false;
|
||||
|
||||
while (rTimeOut > 0 && SerialPortThreadEnd == false)
|
||||
{
|
||||
if (((getData = GetBuff()) & 0x0100) != 0x0000)
|
||||
{
|
||||
if (((getData = GetBuff()) & 0x0100) != 0x0000)
|
||||
rTimeOut = currentTx.TimeoutMs > 0 ? currentTx.TimeoutMs : Config.RecvWaitTime;
|
||||
cData = (byte)(getData & 0x00FF);
|
||||
|
||||
if (rPosition >= BUFFER_SIZE) RecvPacketInit();
|
||||
|
||||
if (BuffStart == false)
|
||||
{
|
||||
rTimeOut = RecvTimeout;
|
||||
|
||||
cData = (byte)(getData & 0x00FF);
|
||||
|
||||
if (rPosition >= BUFFER_SIZE) RecvPacketInit();
|
||||
|
||||
if (BuffStart == false)
|
||||
{
|
||||
if ((cData == (byte)SystemId) || (cData == (byte)0x7F))
|
||||
{
|
||||
rPosition = 0;
|
||||
ReadBuf[rPosition++] = cData;
|
||||
BuffStart = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
if ((cData == (byte)currentTx.SystemId) || (cData == (byte)0x7F) || (cData == (byte)SystemId))
|
||||
{
|
||||
rPosition = 0;
|
||||
ReadBuf[rPosition++] = cData;
|
||||
|
||||
switch (csSerialCommFunction.ModbusPacketFromSlaveCheck(ReadBuf, rPosition))
|
||||
{
|
||||
case 0: // Need more data
|
||||
break;
|
||||
case 1: // Packet OK, no error
|
||||
TimeOutCount = 0;
|
||||
|
||||
int mID = ReadBuf[0];
|
||||
if (mID > 0) mID--;
|
||||
|
||||
SystemData.CommFail = false;
|
||||
SystemData.ShelfCommFail = false;
|
||||
|
||||
if (wMode == false)
|
||||
{
|
||||
short[] result_code = csSerialCommFunction.SerialRxProcess(ReadBuf, RequestRegAddr, rPosition, ref SystemData);
|
||||
|
||||
OnUpdate?.Invoke(this, ref SystemData);
|
||||
}
|
||||
else
|
||||
{
|
||||
wMode = false;
|
||||
WriteRegAddr = 0;
|
||||
if (OnDataRecv != null)
|
||||
{
|
||||
byte[] adata = new byte[rPosition + 1];
|
||||
for (int j = 0; j < adata.Length; j++) { adata[j] = ReadBuf[j]; }
|
||||
OnDataRecv(adata);
|
||||
}
|
||||
}
|
||||
rFlag = false;
|
||||
Thread.Sleep(5);
|
||||
goto StartSend;
|
||||
case 2: // Fw Update Packet OK
|
||||
TimeOutCount = 0;
|
||||
rFlag = false;
|
||||
if (OnDataRecv != null)
|
||||
{
|
||||
byte[] adata = new byte[rPosition + 1];
|
||||
for (int j = 0; j < adata.Length; j++)
|
||||
{
|
||||
adata[j] = ReadBuf[j];
|
||||
}
|
||||
OnDataRecv(adata);
|
||||
}
|
||||
goto StartSend;
|
||||
case -1: // Packet error
|
||||
RecvPacketInit();
|
||||
Thread.Sleep(100);
|
||||
goto StartSend;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
BuffStart = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.Sleep(1);
|
||||
if (rTimeOut > 0)
|
||||
ReadBuf[rPosition++] = cData;
|
||||
|
||||
int checkResult = csSerialCommFunction.ModbusPacketFromSlaveCheck(ReadBuf, rPosition);
|
||||
if (checkResult == 0)
|
||||
{
|
||||
rTimeOut--;
|
||||
// Need more data
|
||||
}
|
||||
else if (checkResult == 1)
|
||||
{
|
||||
// Packet OK
|
||||
TimeOutCount = 0;
|
||||
SystemData.CommFail = false;
|
||||
SystemData.ShelfCommFail = false;
|
||||
|
||||
byte[] rxPacket = new byte[rPosition];
|
||||
Array.Copy(ReadBuf, rxPacket, rPosition);
|
||||
OnPacketLog?.Invoke(DateTime.Now, false, rxPacket, GetRxDescription(rxPacket, currentTx));
|
||||
|
||||
if (currentTx.TxType == UartTxType.Polling)
|
||||
{
|
||||
csSerialCommFunction.SerialRxProcess(ReadBuf, currentTx.RegAddr, rPosition, ref SystemData);
|
||||
OnUpdate?.Invoke(this, ref SystemData);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (OnDataRecv != null)
|
||||
{
|
||||
byte[] adata = new byte[rPosition + 1];
|
||||
for (int j = 0; j < adata.Length; j++) { adata[j] = ReadBuf[j]; }
|
||||
OnDataRecv(adata);
|
||||
}
|
||||
}
|
||||
|
||||
packetHandled = true;
|
||||
Thread.Sleep(5);
|
||||
break;
|
||||
}
|
||||
else if (checkResult == 2)
|
||||
{
|
||||
// Fw Update Packet OK
|
||||
TimeOutCount = 0;
|
||||
byte[] rxPacket = new byte[rPosition];
|
||||
Array.Copy(ReadBuf, rxPacket, rPosition);
|
||||
OnPacketLog?.Invoke(DateTime.Now, false, rxPacket, "Fw Update Response OK");
|
||||
|
||||
if (OnDataRecv != null)
|
||||
{
|
||||
byte[] adata = new byte[rPosition + 1];
|
||||
for (int j = 0; j < adata.Length; j++) { adata[j] = ReadBuf[j]; }
|
||||
OnDataRecv(adata);
|
||||
}
|
||||
|
||||
packetHandled = true;
|
||||
Thread.Sleep(5);
|
||||
break;
|
||||
}
|
||||
else if (checkResult == -1)
|
||||
{
|
||||
// Packet Error
|
||||
byte[] rxPacket = new byte[rPosition];
|
||||
Array.Copy(ReadBuf, rxPacket, rPosition);
|
||||
OnPacketLog?.Invoke(DateTime.Now, false, rxPacket, "Packet CRC/Format Error");
|
||||
|
||||
RecvPacketInit();
|
||||
Thread.Sleep(20);
|
||||
packetHandled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rPosition > 0)
|
||||
{
|
||||
Thread.Sleep(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteRegAddr = 0;
|
||||
TimeOutCount++;
|
||||
if (TimeOutCount >= 5)
|
||||
Thread.Sleep(1);
|
||||
rTimeOut--;
|
||||
}
|
||||
}
|
||||
|
||||
// 타임아웃 처리
|
||||
if (!packetHandled)
|
||||
{
|
||||
TimeOutCount++;
|
||||
if (TimeOutCount >= 5)
|
||||
{
|
||||
TimeOutCount = 5;
|
||||
if (SystemData.ShelfCommFail == false)
|
||||
{
|
||||
TimeOutCount = 5;
|
||||
//SystemData[0].CommFail = true;
|
||||
if (SystemData.ShelfCommFail == false)
|
||||
{
|
||||
SystemData.ShelfCommFail = true;
|
||||
DataInit();
|
||||
}
|
||||
SystemData.ShelfCommFail = true;
|
||||
DataInit();
|
||||
}
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
OnUpdate?.Invoke(this, ref SystemData);
|
||||
Thread.Sleep(1);
|
||||
Thread.Sleep(50);
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
} /* if (rFlag == true) */
|
||||
|
||||
rPosition = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
// No reply expected
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -850,5 +772,62 @@ namespace LFP_Manager.Threads
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region PACKET LOG HELPERS
|
||||
|
||||
private string GetTxDescription(TUartTxItem item)
|
||||
{
|
||||
if (item == null) return "Unknown TX";
|
||||
switch (item.TxType)
|
||||
{
|
||||
case UartTxType.Polling:
|
||||
return string.Format("Polling (ID:{0}, Addr:0x{1:X4}, Len:{2})", item.SystemId, item.RegAddr, item.RegLen);
|
||||
case UartTxType.WriteParam:
|
||||
return string.Format("Write Param (ID:{0}, Addr:0x{1:X4})", item.SystemId, item.RegAddr);
|
||||
case UartTxType.WriteCoil:
|
||||
return string.Format("Write Coil (ID:{0}, Addr:0x{1:X4})", item.SystemId, item.RegAddr);
|
||||
case UartTxType.WriteReg:
|
||||
return string.Format("Write Reg (ID:{0}, Addr:0x{1:X4}, Len:{2})", item.SystemId, item.RegAddr, item.RegLen);
|
||||
case UartTxType.ReadReg:
|
||||
return string.Format("Read Reg (ID:{0}, Addr:0x{1:X4}, Len:{2})", item.SystemId, item.RegAddr, item.RegLen);
|
||||
case UartTxType.FwUpdate:
|
||||
return string.Format("FW Update (ID:{0}, Len:{1})", item.SystemId, item.Data != null ? item.Data.Length : 0);
|
||||
default:
|
||||
return string.Format("RAW TX (ID:{0}, Len:{1})", item.SystemId, item.Data != null ? item.Data.Length : 0);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetRxDescription(byte[] rxPacket, TUartTxItem item)
|
||||
{
|
||||
if (rxPacket == null || rxPacket.Length < 3) return "Unknown RX";
|
||||
byte devId = rxPacket[0];
|
||||
byte funcCode = rxPacket[1];
|
||||
|
||||
if (funcCode == 0x03)
|
||||
{
|
||||
byte byteCount = rxPacket[2];
|
||||
if (item != null && item.TxType == UartTxType.Polling)
|
||||
{
|
||||
return string.Format("Polling Response (ID:{0}, Bytes:{1})", devId, byteCount);
|
||||
}
|
||||
return string.Format("Read Holding Reg Response (ID:{0}, Bytes:{1})", devId, byteCount);
|
||||
}
|
||||
else if (funcCode == 0x05)
|
||||
{
|
||||
return string.Format("Write Coil Response (ID:{0})", devId);
|
||||
}
|
||||
else if (funcCode == 0x06 || funcCode == 0x10)
|
||||
{
|
||||
return string.Format("Write Reg Response (ID:{0})", devId);
|
||||
}
|
||||
else if (funcCode > 0x80)
|
||||
{
|
||||
byte errCode = rxPacket.Length > 2 ? rxPacket[2] : (byte)0;
|
||||
return string.Format("Modbus Error Response (ID:{0}, Func:0x{1:X2}, ErrCode:0x{2:X2})", devId, funcCode, errCode);
|
||||
}
|
||||
return string.Format("RX Data (ID:{0}, Func:0x{1:X2}, Len:{2})", devId, funcCode, rxPacket.Length);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user