using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Runtime.InteropServices; using System.Threading; using System.Windows.Forms; using LFP_Manager.DataStructure; using LFP_Manager.Function; using LFP_Manager.Utils; using static DevExpress.Utils.Drawing.Helpers.NativeMethods; namespace LFP_Manager.Threads { class csValueCanThread { #region DLL FUNCTION #endregion #region VARIABLES int TxThreadPeriod = 10; int RxThreadPeriod = 1; public delegate void invokeDelegate(); CommConfig Config; DeviceSystemData SystemData; int SystemId = 0; int DCP = 0; Thread canCommTx = null; Thread canCommRx = null; //string Msg = ""; // ValueCAN Variables IntPtr m_hObject; // handle for device NeoDevice ndNeoToOpen; byte[] bNetwork = new byte[255]; // List of hardware IDs int iOpenDeviceType; // Storage for the device type that is open //////////////////////////////////////// bool can_bOpen = false; bool CanTxThreadEnd = true; bool CanRxThreadEnd = true; bool CanPolling = false; bool AutoCanTx = true; // Message Queue icsSpyMessage[] stMessages = new icsSpyMessage[20000]; // TempSpace for messages const int RX_QUEUE_MAX = 512; icsSpyMessage[] RxMsgQueue = new icsSpyMessage[RX_QUEUE_MAX]; // RX Message Queue int RxQueueFront = 0; int RxQueueEnd = 0; void RxQueuePut(ref icsSpyMessage rxMsg) { RxMsgQueue[RxQueueFront++] = rxMsg; RxQueueFront %= RX_QUEUE_MAX; } bool RxQueueGet(ref icsSpyMessage rxMsg) { if (RxQueueFront != RxQueueEnd) { rxMsg = RxMsgQueue[RxQueueEnd++]; RxQueueEnd %= RX_QUEUE_MAX; return true; } return false; } public event CanDataUpdate OnUpdate = null; public event CanDataPrint OnPrint = null; public event CanDataRecv OnDataRecv = null; private object lockObject = new object(); #endregion #region CONSTRUCTORS public csValueCanThread(int sId, CommConfig aConfig, ref DeviceSystemData aSystemData) { SystemId = sId; Config = aConfig; SystemData = aSystemData; canCommTx = new Thread(canTxThread); canCommRx = new Thread(canRxThread); } public void disposeThread() { CanTxThreadEnd = true; if (canCommTx != null) { if (canCommTx.IsAlive) { canCommTx.Abort(); } canCommTx = null; } CanRxThreadEnd = true; if (canCommRx != null) { if (canCommRx.IsAlive) { canCommRx.Abort(); } canCommRx = null; } //close the port int iNumberOfErrors = 0; int iResult = icsNeoDll.icsneoClosePort(m_hObject, ref iNumberOfErrors); if (iResult == 1) { //MessageBox.Show("Port Closed OK!"); } else { throw new Exception(String.Format("ValueCAN - Problem ClosingPort")); } //Clear device type and open flag iOpenDeviceType = 0; can_bOpen = false; } public int CloseValueCAN() { int iNumberOfErrors = 0; int iResult = icsNeoDll.icsneoClosePort(m_hObject, ref iNumberOfErrors); if (iResult == 1) { //MessageBox.Show("Port Closed OK!"); } else { throw new Exception(String.Format("ValueCAN - Problem ClosingPort")); } return iResult; } public int ReOpenValueCAN() { int iNumberOfErrors = 0; int iResult = icsNeoDll.icsneoClosePort(m_hObject, ref iNumberOfErrors); if (iResult != 1) throw new Exception(String.Format("ValueCAN - Problem ClosingPort")); iResult = icsNeoDll.icsneoOpenNeoDevice(ref ndNeoToOpen, ref m_hObject, ref bNetwork[0], 1, 0); if (iResult != 1) throw new Exception(String.Format("ValueCAN - Problem Opening Port")); return iResult; } public int OpenValueCan() { int iResult; NeoDeviceEx[] ndNeoToOpenex = new NeoDeviceEx[16]; //Struct holding detected hardware information int iNumberOfDevices; //Number of hardware devices to look for OptionsNeoEx neoDeviceOption = new OptionsNeoEx(); //Set the number of devices to find, for this example look for 16. This example will only work with the first. iNumberOfDevices = 15; iResult = icsNeoDll.icsneoFindDevices(ref ndNeoToOpenex[0], ref iNumberOfDevices, 0, 0, ref neoDeviceOption, 0); if (iResult == 0) { throw new Exception(String.Format("ValueCAN - Problem finding devices")); } if (iNumberOfDevices < 1) { throw new Exception(String.Format("ValueCAN - No devices found")); } ndNeoToOpen = ndNeoToOpenex[0].neoDevice; //Open the first found device iResult = icsNeoDll.icsneoOpenNeoDevice(ref ndNeoToOpen, ref m_hObject, ref bNetwork[0], 1, 0); if (iResult == 1) { //MessageBox.Show("Port Opened OK!"); } else { throw new Exception(String.Format("ValueCAN - Problem Opening Port")); } //Set the device type for later use iOpenDeviceType = ndNeoToOpen.DeviceType; return 1; } private void ConfigBitRate(CommConfig aConfig) { //Get the network name index to set the baud rate of int iNetworkID = (int)eNETWORK_ID.NETID_HSCAN; int iBitRateToUse = csCanConstData.BaudRate.BaudRateInts[aConfig.CanBaudrate]; //Set the bit rate int iResult = icsNeoDll.icsneoSetBitRate(m_hObject, iBitRateToUse, iNetworkID); if (iResult != 1) { throw new Exception(String.Format("ValueCAN - Problem setting bit rate")); } else { //MessageBox.Show("Bit Rate Set"); } } private void ConfigFDRate(CommConfig aConfig) { //Get the network name index to set the baud rate of int iNetworkID = (int)eNETWORK_ID.NETID_HSCAN; int iBitRateToUse = 10000000; //Set the bit rate int iResult = icsNeoDll.icsneoSetFDBitRate(m_hObject, iBitRateToUse, iNetworkID); if (iResult != 1) { throw new Exception(String.Format("ValueCAN - Problem setting FD bit rate")); } else { //MessageBox.Show("FD Bit Rate Set"); } } private void GetSetting(CommConfig aConfig) { SVCAN3Settings VcanReadSettings = new SVCAN3Settings(); SFireSettings FireReadSettings = new SFireSettings(); SFire2Settings Fire2ReadSettings = new SFire2Settings(); SRADGalaxySettings RadGalaxyReadSettings = new SRADGalaxySettings(); SVCANRFSettings VcanRFReadSettings = new SVCANRFSettings(); SVCAN412Settings Vcan412ReadSettings = new SVCAN412Settings(); SRADPlutoSettingsPack RADPlutoSettings = new SRADPlutoSettingsPack(); CAN_SETTINGS HSCanSettings = new CAN_SETTINGS(); int iNumberOfBytes = 0; int iResult; //Get the settigns of the connected hardware switch (iOpenDeviceType) { case (int)eHardwareTypes.NEODEVICE_FIRE: //FIRE //Get the settings iNumberOfBytes = System.Runtime.InteropServices.Marshal.SizeOf(FireReadSettings); iResult = icsNeoDll.icsneoGetFireSettings(m_hObject, ref FireReadSettings, iNumberOfBytes); if (iResult == 0) { MessageBox.Show("Problem reading FIRE configuration"); return; } //Copy the HS CAN settings from the structure to sub struct HSCanSettings = FireReadSettings.can1; break; case (int)eHardwareTypes.NEODEVICE_VCAN3: //Vcan3 //Get the setting iNumberOfBytes = System.Runtime.InteropServices.Marshal.SizeOf(VcanReadSettings); iResult = icsNeoDll.icsneoGetVCAN3Settings(m_hObject, ref VcanReadSettings, iNumberOfBytes); if (iResult == 0) { MessageBox.Show("Problem reading VCAN3 configuration"); return; } //Copy the HS CAN settings from the structure to sub struct HSCanSettings = VcanReadSettings.Can1; break; case (int)eHardwareTypes.NEODEVICE_FIRE2: //FIRE2 //Get the setting iNumberOfBytes = System.Runtime.InteropServices.Marshal.SizeOf(Fire2ReadSettings); iResult = icsNeoDll.icsneoGetFire2Settings(m_hObject, ref Fire2ReadSettings, iNumberOfBytes); if (iResult == 0) { MessageBox.Show("Problem reading FIRE2 configuration"); return; } //Copy the HS CAN settings from the structure to sub struct HSCanSettings = Fire2ReadSettings.can1; break; case (int)eHardwareTypes.NEODEVICE_RADGALAXY: //RadGalaxy //Get the setting iNumberOfBytes = System.Runtime.InteropServices.Marshal.SizeOf(RadGalaxyReadSettings); iResult = icsNeoDll.icsneoGetRADGalaxySettings(m_hObject, ref RadGalaxyReadSettings, iNumberOfBytes); if (iResult == 0) { MessageBox.Show("Problem reading RADGalaxy configuration"); return; } //Copy the HS CAN settings from the structure to sub struct HSCanSettings = RadGalaxyReadSettings.Can1; break; case (int)eHardwareTypes.NEODEVICE_VCANRF: //VcanRF //Get the setting iNumberOfBytes = System.Runtime.InteropServices.Marshal.SizeOf(VcanRFReadSettings); iResult = icsNeoDll.icsneoGetVCANRFSettings(m_hObject, ref VcanRFReadSettings, iNumberOfBytes); if (iResult == 0) { MessageBox.Show("Problem reading VCANRF configuration"); return; } //Copy the HS CAN settings from the structure to sub struct HSCanSettings = VcanRFReadSettings.can1; break; case (int)eHardwareTypes.NEODEVICE_VCAN42: //Vcan4-2 case (int)eHardwareTypes.NEODEVICE_VCAN41: //Vcan4-1 (Same steps for both) //Get the setting iNumberOfBytes = System.Runtime.InteropServices.Marshal.SizeOf(Vcan412ReadSettings); iResult = icsNeoDll.icsneoGetVCAN412Settings(m_hObject, ref Vcan412ReadSettings, iNumberOfBytes); if (iResult == 0) { MessageBox.Show("Problem reading VCAN412 configuration"); return; } //Copy the HS CAN settings from the structure to sub struct HSCanSettings = Vcan412ReadSettings.can1; break; case (int)eHardwareTypes.NEODEVICE_RADPLUTO: //RAD Pluto //Get the setting RADPlutoSettings.uiDevice = (UInt32)EDeviceSettingsType.DeviceRADPlutoSettingsType; iNumberOfBytes = System.Runtime.InteropServices.Marshal.SizeOf(RADPlutoSettings); iResult = icsNeoDll.icsneoGetDeviceSettings(m_hObject, ref RADPlutoSettings, iNumberOfBytes, 0); if (iResult == 0) { MessageBox.Show("Problem reading RAD Pluto configuration"); return; } //Copy the HS CAN settings from the structure to sub struct HSCanSettings = RADPlutoSettings.PlutoSettings.can1; break; default: //Connected hardware does not support this command MessageBox.Show("Problem reading configuration, unsupported device"); return; } //fill text boxes with data from sub struct //txt3GPSeg1.Text = Convert.ToString(HSCanSettings.TqSeg1); //txt3GPSeg2.Text = Convert.ToString(HSCanSettings.TqSeg2); //txt3GPropDelay.Text = Convert.ToString(HSCanSettings.TqProp); //txt3GSJumpW.Text = Convert.ToString(HSCanSettings.TqSync); //txt3GBRP.Text = Convert.ToString(HSCanSettings.BRP); } public unsafe bool Start(CommConfig aConfig, int sId, bool aPolling) { bool result = false; SystemId = sId; CanPolling = aPolling; try { if (OpenValueCan() == 0) throw new System.InvalidOperationException("Failed to open the device, please check if the device type and device index number are correct."); // Baudrate Config ConfigBitRate(aConfig); // FD Rate Config ConfigFDRate(aConfig); // Get Setting Value GetSetting(aConfig); can_bOpen = true; CanTxThreadEnd = false; CanRxThreadEnd = false; canCommTx.Start(); canCommRx.Start(); result = true; } catch (Exception ex) { System.Exception Ex = new System.Exception(ex.Message, ex); throw Ex; } return result; } #endregion #region TX FUNCTION private int GetErrorValueCAN() { int result = 0; int[] iErrors = new int[600]; //Array for Error Numbers int iNumberOfErrors = 0; // Storage for number of errors // Read Out the errors int iResult = icsNeoDll.icsneoGetErrorMessages(m_hObject, ref iErrors[0], ref iNumberOfErrors); // Test the returned result if (iResult == 0) { MessageBox.Show("Problem Reading Errors"); } else { if (iNumberOfErrors != 0) { ReOpenValueCAN(); for (int iCount = 0; iCount < iNumberOfErrors; iCount++) { if (iErrors[iCount] == 44) result++; } } } return result; } private void SendPacketByValueCAN(UInt32 ExID, byte[] Data) { Monitor.Enter(lockObject); try { //OnPrint?.Invoke(this, csCanCommFunction.PacketToMsg(sendobj, 1)); long lResult; icsSpyMessage stMessagesTx = new icsSpyMessage(); long lNetworkID; string sTempString; // Read the Network we will transmit on (indicated by lstNetwork ListBox) sTempString = "HSCAN"; lNetworkID = icsNeoDll.GetNetworkIDfromString(ref sTempString); // Is this a CAN network or a J1850/ISO one? // load the message structure //Make id Extended stMessagesTx.StatusBitField = Convert.ToInt16(eDATA_STATUS_BITFIELD_1.SPY_STATUS_XTD_FRAME); stMessagesTx.ArbIDOrHeader = (int)ExID; // The ArbID stMessagesTx.NumberBytesData = (byte)Data.Length; // The number of Data Bytes if (stMessagesTx.NumberBytesData > 8) stMessagesTx.NumberBytesData = 8; // You can only have 8 databytes with CAN // Load all of the data bytes in the structure stMessagesTx.Data1 = Data[0]; stMessagesTx.Data2 = Data[1]; stMessagesTx.Data3 = Data[2]; stMessagesTx.Data4 = Data[3]; stMessagesTx.Data5 = Data[4]; stMessagesTx.Data6 = Data[5]; stMessagesTx.Data7 = Data[6]; stMessagesTx.Data8 = Data[7]; // Transmit the assembled message for (int i = 0; i < 5; i++) { lResult = icsNeoDll.icsneoTxMessages(m_hObject, ref stMessagesTx, Convert.ToInt32(lNetworkID), 1); if (lResult == 1) break; else { if (GetErrorValueCAN() == 0) break; //ReOpenValueCAN(); } } //GetErrorValueCAN(); } catch (Exception) { //throw new Exception(String.Format("CAN Transmit Exception", ex.Message)); } finally { Monitor.Exit(lockObject); } } private unsafe void SendPacketByValueCAN(ref VCI_CAN_OBJ senObj) { long lResult; icsSpyMessage stMessagesTx = new icsSpyMessage(); long lNetworkID; string sTempString; // Read the Network we will transmit on (indicated by lstNetwork ListBox) sTempString = "HSCAN"; lNetworkID = icsNeoDll.GetNetworkIDfromString(ref sTempString); // Is this a CAN network or a J1850/ISO one? // load the message structure //Make id Extended stMessagesTx.StatusBitField = Convert.ToInt16(eDATA_STATUS_BITFIELD_1.SPY_STATUS_XTD_FRAME); stMessagesTx.ArbIDOrHeader = (int)senObj.ID; // The ArbID stMessagesTx.NumberBytesData = (byte)senObj.DataLen; // The number of Data Bytes if (stMessagesTx.NumberBytesData > 8) stMessagesTx.NumberBytesData = 8; // You can only have 8 databytes with CAN // Load all of the data bytes in the structure stMessagesTx.Data1 = senObj.Data[0]; stMessagesTx.Data2 = senObj.Data[1]; stMessagesTx.Data3 = senObj.Data[2]; stMessagesTx.Data4 = senObj.Data[3]; stMessagesTx.Data5 = senObj.Data[4]; stMessagesTx.Data6 = senObj.Data[5]; stMessagesTx.Data7 = senObj.Data[6]; stMessagesTx.Data8 = senObj.Data[7]; // Transmit the assembled message lResult = icsNeoDll.icsneoTxMessages(m_hObject, ref stMessagesTx, Convert.ToInt32(lNetworkID), 1); // Test the returned result if (lResult != 1) { MessageBox.Show(String.Format("Problem Transmitting Message - ({0})", lResult)); } } public void SetAutoTx(bool autoTx) { AutoCanTx = autoTx; } unsafe public void SendDataFromApp(UInt32 header, byte[] data) { if (can_bOpen == false) return; VCI_CAN_OBJ sendobj = new VCI_CAN_OBJ(); sendobj.SendType = csCanConstData.SendType.Normal; sendobj.ExternFlag = csCanConstData.FrameType.Extended; sendobj.RemoteFlag = csCanConstData.FrameFormat.Data_Frame; sendobj.ID = header; // 0x1815c9c8 int len = 8; sendobj.DataLen = System.Convert.ToByte(len); for (int i = 0; i < len; i++) sendobj.Data[i] = data[i]; SendPacketByValueCAN(sendobj.ID, data); OnPrint?.Invoke(this, csCanCommFunction.PacketToMsg(sendobj, 1)); } public void SetPolling(bool flag, int sId, ref DeviceSystemData aSystemData) { SystemId = sId; CanPolling = flag; SystemData = aSystemData; SystemData.mNo = SystemId; } public void SetDCP(int aDCP) { DCP = aDCP; } public void SendProcessFromApp(int sId, int mode, int flag, int dcp, ref DeviceParamData aParam, ref DeviceCalibration aCalib) { switch (mode) { case 5: // Cell Volatge Parameter SendData(sId, 5, flag, dcp, ref aParam, ref aCalib); SendData(sId, 23, flag, dcp, ref aParam, ref aCalib); break; case 7: SendData(sId, 7, flag, dcp, ref aParam, ref aCalib); SendData(sId, 23, flag, dcp, ref aParam, ref aCalib); break; case 6: SendData(sId, 6, flag, dcp, ref aParam, ref aCalib); SendData(sId, 24, flag, dcp, ref aParam, ref aCalib); break; case 22: SendData(sId, 22, flag, dcp, ref aParam, ref aCalib); SendData(sId, 24, flag, dcp, ref aParam, ref aCalib); break; case 14: SendData(sId, 14, flag, dcp, ref aParam, ref aCalib); break; case 99: // All param read SendData(sId, 5, flag, dcp, ref aParam, ref aCalib); SendData(sId, 6, flag, dcp, ref aParam, ref aCalib); SendData(sId, 7, flag, dcp, ref aParam, ref aCalib); SendData(sId, 14, flag, dcp, ref aParam, ref aCalib); SendData(sId, 22, flag, dcp, ref aParam, ref aCalib); SendData(sId, 23, flag, dcp, ref aParam, ref aCalib); SendData(sId, 24, flag, dcp, ref aParam, ref aCalib); SendData(sId, 2, flag, dcp, ref aParam, ref aCalib); break; case 9: // Cell Voltage Calibration SendData(sId, 9, flag, dcp, ref aParam, ref aCalib); break; case 1: // Cell Voltage Calibration SendData(sId, 1, flag, dcp, ref aParam, ref aCalib); break; case 12: // Cell Voltage Calibration SendData(sId, 12, flag, dcp, ref aParam, ref aCalib); break; case 8: // Battery Parameter Setting SendData(sId, 8, flag, dcp, ref aParam, ref aCalib); break; case 17: // Cell Balancing Parameter - 240531 SendData(sId, 17, flag, dcp, ref aParam, ref aCalib); break; case 21: // System Information (Device Address) SendData(sId, 21, flag, dcp, ref aParam, ref aCalib); break; case 13: // Soc Calibration SendData(sId, 13, flag, dcp, ref aParam, ref aCalib); break; case 15: // Default Parameter SendData(sId, 15, flag, dcp, ref aParam, ref aCalib); break; case 16: // Default Parameter if (aParam.DefalutParamAll == 1) SendData(0xFF, 16, flag, dcp, ref aParam, ref aCalib); else SendData(sId, 16, flag, dcp, ref aParam, ref aCalib); break; case 2: // Cell Voltage Difference Parameter SendData(sId, 2, flag, dcp, ref aParam, ref aCalib); break; case 25: SendData(sId, 25, flag, dcp, ref aParam, ref aCalib); break; // Inventory Data Control case 900: // Manufacturer Cmd SendData(sId, 900, flag, dcp, ref aParam, ref aCalib); break; case 901: // Serial Number #1 Cmd SendData(sId, 901, flag, dcp, ref aParam, ref aCalib); break; case 902: // Serial Number #2 Cmd SendData(sId, 902, flag, dcp, ref aParam, ref aCalib); break; } } unsafe void SendData(int sId, int mode, int flag, int dcp, ref DeviceParamData aParam, ref DeviceCalibration aCalib) { if (can_bOpen == false) return; VCI_CAN_OBJ sendobj = MakeTxData(sId, mode, flag, dcp, ref aParam, ref aCalib); byte[] data = new byte[8]; for (int i = 0; i < 8; i++) data[i] = sendobj.Data[i]; SendPacketByValueCAN(sendobj.ID, data); } private UInt32 MakeID(int sId, int mode) { UInt32 result = 0; PACKET_HEADER hdr = new PACKET_HEADER(); hdr.Index = 6; // Fixed 6 hdr.R = 0; // Fixed 0 hdr.DP = 0; // Fixed 0 hdr.PF = (byte)mode; // Command if (sId == 0xFF) hdr.PS = (byte)(sId); // PDU SPECIFIC else hdr.PS = (byte)(sId + 200); // PDU SPECIFIC hdr.SA = 200; // SOURCE ADDRESS result = csCanCommFunction.CovertHtoP(hdr); return result; } private UInt32 MakeInvID(int sId, int mode) { UInt32 result = 0; PACKET_HEADER hdr = new PACKET_HEADER(); hdr.Index = 1; // Fixed 1 for Inventory Data hdr.R = 0; // Fixed 0 hdr.DP = 0; // Fixed 0 hdr.PF = (byte)((mode % 900) + 1); // Command if (sId == 0xFF) hdr.PS = (byte)(sId); // PDU SPECIFIC else hdr.PS = (byte)(sId + 200); // PDU SPECIFIC hdr.SA = 200; // SOURCE ADDRESS result = csCanCommFunction.CovertHtoP(hdr); return result; } unsafe private VCI_CAN_OBJ MakeTxData(int sId, int mode, int flag, int dcp, ref DeviceParamData aParam, ref DeviceCalibration aCalib) { VCI_CAN_OBJ sendobj = new VCI_CAN_OBJ(); sendobj.SendType = csCanConstData.SendType.Normal; sendobj.RemoteFlag = csCanConstData.FrameFormat.Data_Frame; sendobj.ExternFlag = csCanConstData.FrameType.Extended; if (mode < 900) sendobj.ID = MakeID(sId, mode); else sendobj.ID = MakeInvID(sId, mode); sendobj.DataLen = (byte)(8); byte[] aData = csCanCommFunction.MakeCanData(mode, flag, dcp, ref aParam, ref aCalib); for (int i = 0; i < 8; i++) { sendobj.Data[i] = aData[i]; } return sendobj; } #endregion #region COMM TX THREAD int current_cmd = 0; int RxSystemId = 0; public int GetCommSystemId() { return RxSystemId; } unsafe private void canTxThread() { int txTick = 0; while (CanTxThreadEnd == false) { txTick++; if (txTick >= TxThreadPeriod) { if (CanPolling && AutoCanTx) { int flag = 0; TxProcess(ref flag); RxSystemId = SystemId; SendData(SystemId, current_cmd, flag, DCP, ref SystemData.ParamData, ref SystemData.CalibriationData); //Thread.Sleep(1); } txTick %= TxThreadPeriod; } GetMessageBuff(); Thread.Sleep(1); } } void TxProcess(ref int aflag) { switch (current_cmd) { case 20: current_cmd = 900; break; case 900: current_cmd = 901; break; case 901: current_cmd = 902; break; case 902: current_cmd = 1; break; case 1: current_cmd = 19; break; case 19: current_cmd = 3; break; case 3: current_cmd = 4; break; case 4: current_cmd = 11; break; case 11: current_cmd = 16; break; case 16: current_cmd = 20; break; default: current_cmd = 20; break; } } #endregion #region COMM RX THREAD unsafe private void canRxThread() { while (CanRxThreadEnd == false) { DateTime aTime = DateTime.Now; if (GetMessageProcess()) { // Received data SystemData.ShelfCommFail = false; SystemData.LastRxTime = DateTime.Now; } else { TimeSpan dTime = DateTime.Now - SystemData.LastRxTime; if (SystemData.ShelfCommFail == false) { if (dTime.TotalSeconds > 10) { SystemData.ShelfCommFail = true; DataInit(); OnUpdate?.Invoke(this, ref SystemData); } } } Thread.Sleep(RxThreadPeriod); } } unsafe private int GetMessageBuff() { int result = 0; int lNumberOfMessages = 1; int lNumberOfErrors = 0; //double dTime = 0; // read the messages from the driver int lResult = icsNeoDll.icsneoGetMessages(m_hObject, ref stMessages[0], ref lNumberOfMessages, ref lNumberOfErrors); // was the read successful? if (lResult == 1) { for (int i = 0; i < lNumberOfMessages; i++) { // Calculate the messages timestamp //lResult = icsNeoDll.icsneoGetTimeStampForMsg(m_hObject, ref stMessages[i], ref dTime); if ((stMessages[i].StatusBitField & Convert.ToInt32(eDATA_STATUS_BITFIELD_1.SPY_STATUS_TX_MSG)) == 0) { // Rx Data if (stMessages[i].ArbIDOrHeader != 0) RxQueuePut(ref stMessages[i]); } } } return result; } private bool GetMessageProcess() { bool result = false; icsSpyMessage rxMsg = new icsSpyMessage(); if (RxQueueGet(ref rxMsg)) { switch (rxMsg.Protocol) { case (int)ePROTOCOL.SPY_PROTOCOL_CAN: { UInt32 exID = (UInt32)rxMsg.ArbIDOrHeader; byte[] rData = new byte[8]; rData[0] = rxMsg.Data1; rData[1] = rxMsg.Data2; rData[2] = rxMsg.Data3; rData[3] = rxMsg.Data4; rData[4] = rxMsg.Data5; rData[5] = rxMsg.Data6; rData[6] = rxMsg.Data7; rData[7] = rxMsg.Data8; OnPrint?.Invoke(this, csCanCommFunction.PacketToMsg(exID, rData, 0)); PACKET_HEADER pHeader = csCanCommFunction.CovertPtoH(exID); switch (pHeader.Index) { case 0x01: // Inventory Data Packet if ((pHeader.SA == (200 + SystemId))) { result = true; RxSystemId = pHeader.SA - 200; csCanCommFunction.CanInvRxProcess(RxSystemId, exID, rData, ref SystemData, DateTime.Now); OnUpdate?.Invoke(this, ref SystemData); } break; case 0x04: // Firmware Update Packet OnDataRecv?.Invoke(exID, rData); break; case 0x06: // Normal Packet if (pHeader.SA == (200 + SystemId)) { result = true; RxSystemId = pHeader.SA - 200; csCanCommFunction.CanRxProcess(ref Config, RxSystemId, exID, rData, ref SystemData, DateTime.Now); OnUpdate?.Invoke(this, ref SystemData); } break; } } break; } } return result; } #endregion #region DATA INIT private void DataInit() { SystemData.ShelfCommFail = true; for (int j = 0; j < csConstData.SystemInfo.MAX_MODULE_CELL_SIZE; j++) { SystemData.ValueData.CellVoltage[j] = 0; } for (int j = 0; j < csConstData.SystemInfo.MAX_MODULE_TEMP_SIZE; j++) { SystemData.ValueData.CellTemperature[j] = 0; } SystemData.ValueData.voltageOfPack = 0; SystemData.ValueData.current = 0; SystemData.ValueData.rSOC = 0; SystemData.AvgData.maxCellVoltage = 0; SystemData.AvgData.minCellVoltage = 0; SystemData.AvgData.avgCellVoltage = 0; SystemData.AvgData.maxTemp = 0; SystemData.AvgData.minTemp = 0; SystemData.AvgData.avgTemp = 0; SystemData.heatbeat = 0; SystemData.StatusData.warning = 0; SystemData.StatusData.protect = 0; for (int j = 0; j < SystemData.Information.pcb_sn.Length; j++) { SystemData.Information.pcb_sn[j] = 0; } for (int j = 0; j < SystemData.Information.module_sn.Length; j++) { SystemData.Information.module_sn[j] = 0; } SystemData.CalibriationData.Battery.Capacity = 0; SystemData.CalibriationData.Current.ChaAndDchSelect = 0; } #endregion } }