using System; using System.Collections.Generic; using System.Linq; using System.Text; using LFP_Manager.DataStructure; using LFP_Manager.Utils; using LFP_Manager.Controls; using System.Web.Services.Description; using DevExpress.XtraTreeList; using SnmpSharpNet; using DevExpress.XtraGrid.Views.BandedGrid.Handler; using static DevExpress.Xpo.Helpers.AssociatedCollectionCriteriaHelper; namespace LFP_Manager.Function { class CsSerialCommFunctionDelta { public const byte READ_COIL_STATUS = 0x01; public const byte READ_HOLDING_REG = 0x03; public const byte READ_INPUT_REG = 0x04; //Byul 구문 추가 필요 public const byte FORCE_SINGLE_COIL = 0x05; public const byte PRESET_SINGLE_REG = 0x06; public const byte PRESET_MULTI_REG = 0x10; public const byte WRITE_COIL_REG = 0x0F; public const byte ERROR_REG = 0x90; public const byte READ_WRITE_REG = 0x17; public const byte SPECIAL_REG_02 = 0x19; public const byte READ_DEV_ID = 0x2B; public const byte FW_FLASH_ERASE_CMD = 0x43; public const byte FW_FLASH_WRITE_CMD = 0x31; public const byte NO_CMD = 0xFF; public static byte[] GetCRC(byte[] pby, int nSize) { ushort uIndex, i; ushort crc; byte uchCRCHi = 0xff; byte uchCRCLo = 0xff; byte[] result = new byte[2]; for (i = 0; i < nSize; i++) { uIndex = (ushort)((int)uchCRCLo ^ (int)pby[i]); uchCRCLo = (byte)(uchCRCHi ^ csConstData.CRC_Data.auchCRCHi[uIndex]); uchCRCHi = csConstData.CRC_Data.auchCRCLo[uIndex]; } crc = (ushort)((uchCRCHi << 8) | uchCRCLo); result[0] = (byte)(crc >> 8); result[1] = (byte)(crc >> 0); return result; } static public byte[] MakeReadRegisterData(ushort DevID, ushort cmd, ushort ReadAddr, ushort Size) { byte[] result = new byte[8]; byte[] crc; result[0] = (byte)DevID; // Device ID result[1] = (byte)cmd; // Command result[2] = (byte)(ReadAddr >> 8); // Register Address MSB result[3] = (byte)(ReadAddr >> 0); // Register Address LSB result[4] = (byte)(Size >> 8); // Count of Register MSB result[5] = (byte)(Size >> 0); // Count of Register LSB crc = GetCRC(result, 6); result[6] = crc[1]; // CRCH result[7] = crc[0]; // CRCL return result; } static public byte[] MakeWriteCoilData(ushort DevID, ushort WriteAddr, short WriteData) { byte[] result = new byte[7 + (1 * 1) + 2]; byte[] crc; ushort i = 0; result[i++] = (byte)DevID; // Device ID result[i++] = (byte)WRITE_COIL_REG; // Command result[i++] = (byte)(WriteAddr >> 8); // Register Address MSB result[i++] = (byte)(WriteAddr >> 0); // Register Address LSB result[i++] = (byte)(1 >> 8); // Count of Register MSB result[i++] = (byte)(1 >> 0); // Count of Register LSB result[i++] = (byte)(1 * 1); // Byte Count - [2 * (Num of register)] result[i++] = (byte)(WriteData >> 0); crc = GetCRC(result, i); result[i++] = crc[1]; // CRCH result[i++] = crc[0]; // CRCL return result; } static public byte[] MakeWriteRegisterData(ushort devId, ushort writeAddr, short[] writeData) { if (writeData == null || writeData.Length == 0) return Array.Empty(); // 부호 확장 없이 캐스팅 (2’s complement 그대로 0..65535 범위로 들어갑니다) Span regs = writeData.Length <= 16 ? stackalloc ushort[writeData.Length] : new ushort[writeData.Length]; // 길면 힙 사용 for (int k = 0; k < writeData.Length; k++) regs[k] = unchecked((ushort)writeData[k]); return MakeWriteRegisterData(devId, writeAddr, regs); } static private byte[] MakeWriteRegisterData(ushort devId, ushort writeAddr, ReadOnlySpan writeData) { if (writeData.Length <= 0) return Array.Empty(); const byte Func = 0x10; // PRESET_MULTI_REG int regCount = writeData.Length; int payloadLen = 7 + regCount * 2; // CRC 제외 길이 byte[] frame = new byte[payloadLen + 2]; int i = 0; frame[i++] = (byte)devId; // Device ID frame[i++] = Func; // Function Code (0x10) frame[i++] = (byte)(writeAddr >> 8); // Addr Hi frame[i++] = (byte)writeAddr; // Addr Lo frame[i++] = (byte)(regCount >> 8); // Count Hi frame[i++] = (byte)regCount; // Count Lo frame[i++] = (byte)(regCount * 2); // ByteCount // 데이터: 각 레지스터를 Hi → Lo 바이트로 for (int j = 0; j < regCount; j++) { ushort v = writeData[j]; frame[i++] = (byte)(v >> 8); frame[i++] = (byte)v; } // CRC (CRCL → CRCH) 부착 if (!CsCRC16.TryAppendCrcLowHigh(frame, payloadLen, 0)) return Array.Empty(); return frame; } static public byte[] MakeWriteRegisterData(ushort DevID, ushort WriteAddr, short WriteData) { byte[] result = new byte[9 + (1 * 2)]; byte[] crc; ushort i = 0; result[i++] = (byte)DevID; // Device ID result[i++] = (byte)PRESET_MULTI_REG; // Command result[i++] = (byte)(WriteAddr >> 8); // Register Address MSB result[i++] = (byte)(WriteAddr >> 0); // Register Address LSB result[i++] = (byte)(1 >> 8); // Count of Register MSB result[i++] = (byte)(1 >> 0); // Count of Register LSB result[i++] = (byte)(1 * 2); // Byte Count - [2 * (Num of register)] result[i++] = (byte)(WriteData >> 8); result[i++] = (byte)(WriteData >> 0); crc = GetCRC(result, i); result[i++] = crc[1]; // CRCH result[i++] = crc[0]; // CRCL return result; } static public byte[] MakeReadDevIdRegReqData(ushort DevID, ushort cmd, ushort ReadAddr) { byte[] result = new byte[7]; byte[] crc; result[0] = (byte)DevID; // Device ID result[1] = (byte)cmd; // Command result[2] = (byte)0x0E; // MEI Type result[3] = (byte)0x02; // Read Dev Id code result[4] = (byte)ReadAddr; // Object Id crc = GetCRC(result, 5); result[5] = crc[1]; // CRCH result[6] = crc[0]; // CRCL return result; } static short GetRegister(ushort reg_addr, ref DeviceParamData aParam) { short result = 0; switch (reg_addr) { //case 19: result = (short)(0 >> 16); break; // 0021 : UTC TimeStamp MSB //case 20: result = (short)(58 >> 0); break; // 0022 : UTC TimeStamp LSB //case 21: result = (short)0x1000; break; // 0023 : Cell Balancing Flag //case 22: result = (short)0x0000; break; // 0024 : Cell Balancing Voltage //case 23: result = (short)15; break; // 0024 : Cell Balancing Time case 0x4002: result = (short)aParam.CellUnderVoltageWarning; break; // 0061 : Low cell voltage warning data //case 33: result = (short)param.sf1.voltage.CUV_Threshold; break; // 0062 : Low cell voltage protection data //case 34: result = (short)param.sf1.voltage.CUV_Recovery; break; // 0063 : Low cell voltage recovery data //case 35: result = (short)param.sf1.voltage.SUV_Warning; break; // 0064 : Low voltage warning data //case 36: result = (short)param.sf1.voltage.SUV_Threshold; break; // 0065 : Low voltage protection data //case 37: result = (short)param.sf1.voltage.SUV_Recovery; break; // 0066 : Low voltage recovery data //case 38: result = (short)param.sf1.voltage.COV_Warning; break; // 0067 : Over cell voltage warning data //case 39: result = (short)param.sf1.voltage.COV_Threshold; break; // 0068 : Over cell voltage protection data //case 40: result = (short)param.sf1.voltage.COV_Recovery; break; // 0069 : Over cell voltage recovery data //case 41: result = (short)param.sf1.voltage.SOV_Warning; break; // 0070 : Over voltage warning data //case 42: result = (short)param.sf1.voltage.SOV_Threshold; break; // 0071 : Over voltage protection data //case 43: result = (short)param.sf1.voltage.SOV_Recovery; break; // 0072 : Over voltage recovery data //case 44: result = (short)param.sf1.temperature.OT_Chg_Warning; break; // 0044 : Charge over temperature warning data //case 45: result = (short)param.sf1.temperature.OT_Chg_Threshold; break; // 0045 : Charge over temperature protection data //case 46: result = (short)param.sf1.temperature.OT_Chg_Recovery; break; // 0046 : Charge over temperature recovery data //case 47: result = (short)param.sf1.temperature.OT_Chg_Time; break; // 0047 : Charge over temperature time //case 48: result = (short)param.sf1.temperature.OT_Dsg_Warning; break; // 0048 : Discharge over temperature warning data //case 49: result = (short)param.sf1.temperature.OT_Dsg_Threshold; break; // 0049 : Discharge over temperature protection data //case 50: result = (short)param.sf1.temperature.OT_Dsg_Recovery; break; // 0050 : Discharge over temperature recovery data //case 51: result = (short)param.sf1.temperature.OT_Dsg_Time; break; // 0051 : Discharge over temperature time } return result; } static byte[] ModBusGetRegWordToBytes(ushort addr, ref DeviceParamData aParam) { short data; byte[] result = new byte[2]; data = GetRegister(addr, ref aParam); result[0] = (byte)(data >> 8); result[1] = (byte)(data >> 0); return result; } static public byte[] MakeWriteRegisterData(ushort DevID, ushort WriteAddr, ushort reg_len, ref DeviceParamData aParam) { int tlen = (reg_len * 2) + 7 + 2; byte[] result = new byte[tlen]; byte[] tmp; byte[] crc; result[0] = (byte)DevID; // Device ID result[1] = (byte)PRESET_MULTI_REG; // Command result[2] = (byte)(WriteAddr >> 8); // Register Address MSB result[3] = (byte)(WriteAddr >> 0); // Register Address LSB result[4] = (byte)(reg_len >> 8); // Count of Register MSB result[5] = (byte)(reg_len >> 0); // Count of Register LSB result[6] = (byte)(reg_len * 2); ; // Current Value MSB for (int i = 0; i < reg_len; i++) { tmp = ModBusGetRegWordToBytes((ushort)(WriteAddr + i), ref aParam); result[7 + (i * 2) + 0] = tmp[0]; result[7 + (i * 2) + 1] = tmp[1]; } crc = GetCRC(result, 8); result[tlen - 2] = crc[0]; // CRCH result[tlen - 1] = crc[1]; // CRCL return result; } static public byte[] MakeReadWriteRegisterData(ushort DevID, ushort WriteAddr, short WriteData) { byte[] result = new byte[15]; byte[] crc; ushort i = 0; result[i++] = (byte)DevID; // Device ID result[i++] = (byte)READ_WRITE_REG; // Command result[i++] = (byte)(WriteAddr >> 8); // Read Register Address MSB result[i++] = (byte)(WriteAddr >> 0); // Read Register Address LSB result[i++] = (byte)(0 >> 8); // Read Count of Register MSB result[i++] = (byte)(0 >> 0); // Read Count of Register LSB result[i++] = (byte)(WriteAddr >> 8); // Write Register Address MSB result[i++] = (byte)(WriteAddr >> 0); // Write Register Address LSB result[i++] = (byte)(1 >> 8); // Write Count of Register MSB result[i++] = (byte)(1 >> 0); // Write Count of Register LSB result[i++] = (byte)(1 * 2); // Byte Count - [2 * (Num of register)] result[i++] = (byte)(WriteData >> 8); result[i++] = (byte)(WriteData >> 0); crc = GetCRC(result, i); result[i++] = crc[0]; // CRCH result[i++] = crc[1]; // CRCL return result; } public static byte[] MakeCheckSum(byte[] sData, int offset, int len, bool flag) { byte[] result = new byte[2]; int checksum = 0; for (int i = 0; i < len; i++) { checksum += sData[i + offset]; } checksum = ~checksum + 1; result[0] = (byte)(checksum >> 8); result[1] = (byte)checksum; return result; } private static byte[] MakeTxPacket(byte[] sData, int len) { string str = ""; byte[] result; char[] chrArray; int checksum = 0; string checksumStr = ""; char[] checksumChr; str = "~"; for (int i = 0; i < len; i++) { str += sData[i].ToString("X2"); } str += "\r"; chrArray = str.ToCharArray(); for (int i = 0; i < (chrArray.Length - 6); i++) { checksum += chrArray[i + 1]; } checksum = ~checksum + 1; checksumStr = String.Format("{0:X2}{1:X2}", (byte)(checksum >> 8), (byte)checksum); checksumChr = checksumStr.ToCharArray(); for (int i = 0; i < 4; i++) { chrArray[chrArray.Length - 5 + i] = checksumChr[i]; } result = new byte[chrArray.Length]; for (int i = 0; i < chrArray.Length; i++) { result[i] = (byte)chrArray[i]; } return result; } public static byte[] LengthLchk(int sLen) { byte[] result = new byte[2]; int lchksum = 0; lchksum = (~(((sLen >> 8) & 0xF) + ((sLen >> 4) & 0xF) + ((sLen >> 0) & 0xF)) + 1) % 16; lchksum = ((lchksum << 12) | sLen); result[0] = (byte)(lchksum >> 8); result[1] = (byte)(lchksum >> 0); return result; } public static byte[] MakeTxData(byte addr, byte cmd, int sLen) { int buffCh = 0; byte[] sData; byte[] lenId; byte[] checksum; sData = new byte[((sLen > 0) ? 11 : 10)]; sData[buffCh] = 0x7E; buffCh++; // SOI sData[buffCh] = 0x25; buffCh++; // VER sData[buffCh] = addr; buffCh++; // ADDR sData[buffCh] = 0x46; buffCh++; // CID1 sData[buffCh] = cmd; buffCh++; // CID2 (CMD) lenId = LengthLchk(sLen); // LENID sData[buffCh] = lenId[0]; buffCh++; // LENID MSB sData[buffCh] = lenId[1]; buffCh++; // LENID LSB if (sLen > 0) { sData[buffCh] = (byte)(sLen / 2); buffCh++; // INFO } checksum = csSerialCommFunction.MakeCheckSum(sData, 1, sData.Length - 4, false); sData[buffCh] = checksum[1]; buffCh++; sData[buffCh] = checksum[0]; buffCh++; sData[buffCh] = 0x0D; buffCh++; // EOI return MakeTxPacket(sData, sData.Length); } public static int TbPacketCheck(byte[] rdata, int rlen) { int result = 0; byte[] cdata; byte[] checksum; byte[] checksum1; checksum = MakeCheckSum(rdata, 1, rlen - 6, false); checksum1 = new byte[2]; checksum1[0] = csUtils.StrByte2toByte(rdata[rlen - 4], rdata[rlen - 5]); checksum1[1] = csUtils.StrByte2toByte(rdata[rlen - 2], rdata[rlen - 3]); if ((checksum[0] == checksum1[0]) && (checksum[1] == checksum1[1])) { cdata = csUtils.StrToByteArray(rdata, 0, rlen); result = 1; } return result; } static public int ModbusPacketFromSlaveCheck(byte[] rdata, ushort rlen) { int result = 0; byte[] cdata, crc; ushort clen, bytecount; if (rlen > 2) { cdata = rdata; switch (cdata[1]) { case READ_DEV_ID: if (rlen < 10) break; if (rdata[7] == 0) break; int tmp = 0; int cPos = 7; int alen = 0; for (int i = 0; i < cdata[7]; i++) { alen = cdata[cPos + 2]; cPos += alen + 2; if (rlen < (cPos + 3)) { tmp = 1; break; } } if (tmp == 1) break; crc = GetCRC(cdata, (ushort)(rlen - 2)); if ((crc[1] == cdata[rlen - 2]) && (crc[0] == cdata[rlen - 1])) result = 1; else result = -1; break; case READ_COIL_STATUS: case READ_HOLDING_REG: case READ_INPUT_REG: case READ_WRITE_REG: bytecount = cdata[2]; clen = (ushort)(bytecount + 5); // header 3, tail 2 if (rlen >= clen) { crc = GetCRC(cdata, (ushort)(rlen - 2)); if ((crc[1] == cdata[rlen - 2]) && (crc[0] == cdata[rlen - 1])) result = 1; else result = -1; } break; case PRESET_MULTI_REG: case FORCE_SINGLE_COIL: case PRESET_SINGLE_REG: clen = 8; if (rlen >= clen) { crc = GetCRC(cdata, (ushort)(rlen - 2)); if ((crc[0] == cdata[rlen - 1]) && (crc[1] == cdata[rlen - 2])) result = 1; else result = -1; } break; case ERROR_REG: clen = 6; if (rlen >= clen) { crc = GetCRC(cdata, (ushort)(rlen - 2)); if ((crc[0] == cdata[rlen - 1]) && (crc[1] == cdata[rlen - 2])) result = 1; else result = -1; } break; case FW_FLASH_ERASE_CMD: clen = 5; if (rlen >= clen) { crc = GetCRC(cdata, (ushort)(rlen - 2)); if ((crc[0] == cdata[rlen - 1]) && (crc[1] == cdata[rlen - 2])) result = 2; else result = -1; } break; case FW_FLASH_WRITE_CMD: clen = 5; if (rlen >= clen) { crc = GetCRC(cdata, (ushort)(rlen - 2)); if ((crc[0] == cdata[rlen - 1]) && (crc[1] == cdata[rlen - 2])) result = 2; else result = -1; } break; default: result = -1; break; } } return result; } public static short[] SerialRxProcess(byte[] rData, ushort rRegAddr, ushort rLen, ref CsDeviceData.DeviceModuleData aModuleData) { short[] result = new short[2]; switch (rData[1]) { case READ_INPUT_REG: // 0x04 ReadInputRegisterProcess(rData, rRegAddr, rLen, ref aModuleData); break; case READ_WRITE_REG: // 0x17 //ReadSP1RegisterProcess(rData, rRegAddr, rLen, ref rSystemData); break; case SPECIAL_REG_02: // 0x19 //ReadInputRegisterProcess(rData, rRegAddr, rLen, ref rSystemData); break; case READ_DEV_ID: // 0x2B ReadDevIdRegisterProcess(rData, rRegAddr, rLen, ref aModuleData); break; case PRESET_MULTI_REG: // read_holding_reg_process(reverse16(rsp->start_addr, true), reverse16(rsp->qty_reg, true)); //result[0] = 1; //result[1] = 1; break; case ERROR_REG: result[0] = 2; result[1] = (short)((rData[0] << 8) | rData[1]); break; } return result; } private static void ReadCoilRegisterProcess(byte[] rData, ushort rRegAddr, ushort rLen, ref CsDeviceData.DeviceModuleData aModuleData) { int i, j; short reg_count; short reg_value; i = 2; reg_count = rData[i]; i++; for (j = 0; j < reg_count; j++) { reg_value = (short)(rData[i + j]); SetCoilRegister((short)(rRegAddr + j), reg_value, ref aModuleData); i++; } } private static void ReadInputRegisterProcess(byte[] rData, ushort rRegAddr, ushort rLen, ref CsDeviceData.DeviceModuleData aModuleData) { int i, j; short reg_count; short reg_value; i = 2; reg_count = (short)(rData[i] / 2); i += 1; for (j = 0; j < reg_count; j++) { reg_value = (short)(rData[i] << 8 | rData[i + 1]); SetInputRegister((short)(rRegAddr + j), reg_value, ref aModuleData); i += 2; } } private static void ReadDevIdRegisterProcess(byte[] rData, ushort rRegAddr, ushort rLen, ref CsDeviceData.DeviceModuleData aModuleData) { int cPos = 7; int alen = 0; int regCount = rData[7]; int oID = 0; for (int i = 0; i < regCount; i++) { oID = rData[cPos + 1]; alen = rData[cPos + 2]; byte[] tmp = new byte[alen]; for (int j = 0; j < alen; j++) { tmp[j] = rData[cPos + 3 + j]; } switch (oID) { case 0x00: aModuleData.Information.VendorName = Encoding.ASCII.GetString(tmp).Trim('\0'); break; case 0x01: aModuleData.Information.ProductCode = Encoding.ASCII.GetString(tmp).Trim('\0'); break; case 0x02: aModuleData.Information.MajorMinorRev = Encoding.ASCII.GetString(tmp).Trim('\0'); break; case 0x05: aModuleData.Information.ModelName = Encoding.ASCII.GetString(tmp).Trim('\0'); break; case 0x82: aModuleData.Information.HwSerialNumber = Encoding.ASCII.GetString(tmp).Trim('\0'); break; case 0x83: aModuleData.Information.HwProductRev = Encoding.ASCII.GetString(tmp).Trim('\0'); break; case 0x84: aModuleData.Information.ManufacturingDate = Encoding.ASCII.GetString(tmp).Trim('\0'); break; case 0x86: aModuleData.Information.SwProductRev = Encoding.ASCII.GetString(tmp).Trim('\0'); break; } cPos += alen + 2; if (rLen < (cPos + 3)) { break; } } } private static void ReadSP2RegisterProcess(byte[] rData, ushort rRegAddr, ushort rLen, ref DeviceSystemData rSystemData) { int i, j; short reg_count; short reg_value; i = 2; reg_count = (short)(rData[i] / 2); i += 1; for (j = 0; j < reg_count; j++) { reg_value = (short)(rData[i] << 8 | rData[i + 1]); SetSP2Register((short)(rRegAddr + j), reg_value, ref rSystemData); i += 2; } } private static void ReadSP1RegisterProcess(byte[] rData, ushort rRegAddr, ushort rLen, ref DeviceSystemData rSystemData) { int i, j; short reg_count; short reg_value; i = 2; reg_count = (short)(rData[i] / 2); i += 1; for (j = 0; j < reg_count; j++) { reg_value = (short)(rData[i] << 8 | rData[i + 1]); SetSP1Register((short)(rRegAddr + j), reg_value, ref rSystemData); i += 2; } } private static readonly int CURRENT_OFFSET = 10000; private static readonly int TEMP_OFFSET = 400; private static short MakeWarningData_AMG(short reg_value) { byte[] reg_byte = new byte[2]; ushort result = 0; reg_byte[1] = (byte)(reg_value >> 8); reg_byte[0] = (byte)(reg_value >> 0); if (((reg_byte[0] >> 0) & 0x01) == 0x01) result |= (ushort)(1 << 4); // Cell Over Voltage if (((reg_byte[0] >> 1) & 0x01) == 0x01) result |= (ushort)(1 << 5); // Cell Under Voltage if (((reg_byte[0] >> 2) & 0x01) == 0x01) result |= (ushort)(1 << 2); // Pack Over Voltage if (((reg_byte[0] >> 3) & 0x01) == 0x01) result |= (ushort)(1 << 3); // Pack Under Voltage if (((reg_byte[0] >> 4) & 0x01) == 0x01) result |= (ushort)(1 << 6); // Charge Over Current if (((reg_byte[0] >> 5) & 0x01) == 0x01) result |= (ushort)(1 << 7); // Discharge Over Current if (((reg_byte[0] >> 6) & 0x01) == 0x01) result |= (ushort)(1 << 14); // ENV Over Temperature if (((reg_byte[0] >> 7) & 0x01) == 0x01) result |= (ushort)(1 << 15); // ENV Under Temperature if (((reg_byte[1] >> 0) & 0x01) == 0x01) result |= (ushort)(1 << 0); // Chg Over Temperature if (((reg_byte[1] >> 1) & 0x01) == 0x01) result |= (ushort)(1 << 1); // Chg Under Temperature if (((reg_byte[1] >> 2) & 0x01) == 0x01) result |= (ushort)(1 << 0); // Dch Over Temperature if (((reg_byte[1] >> 3) & 0x01) == 0x01) result |= (ushort)(1 << 1); // Dch Under Temperature if (((reg_byte[1] >> 4) & 0x01) == 0x01) result |= (ushort)(1 << 11); // SOC Low Alarm if (((reg_byte[1] >> 5) & 0x01) == 0x01) result |= (ushort)(1 << 9); // Diff Voltage Alarm if (((reg_byte[1] >> 6) & 0x01) == 0x01) result |= (ushort)(1 << 13); // CB On/OFF (1: OFF, 0: ON) if (((reg_byte[1] >> 7) & 0x01) == 0x01) result |= (ushort)(1 << 12); // reserved return (short)result; } private static short MakeProtectData_AMG(short reg_value) { byte[] reg_byte = new byte[2]; ushort result = 0; reg_byte[1] = (byte)(reg_value >> 8); reg_byte[0] = (byte)(reg_value >> 0); if (((reg_byte[0] >> 0) & 0x01) == 0x01) result |= (ushort)(1 << 4); // Cell Over Voltage if (((reg_byte[0] >> 1) & 0x01) == 0x01) result |= (ushort)(1 << 2); // Pack Over Voltage if (((reg_byte[0] >> 2) & 0x01) == 0x01) result |= (ushort)(1 << 5); // Cell Under Voltage if (((reg_byte[0] >> 3) & 0x01) == 0x01) result |= (ushort)(1 << 3); // Pack Under Voltage if (((reg_byte[0] >> 4) & 0x01) == 0x01) result |= (ushort)(1 << 6); // Cha Over Current 1 if (((reg_byte[0] >> 5) & 0x01) == 0x01) result |= (ushort)(1 << 6); // Cha Over Current 2 if (((reg_byte[0] >> 6) & 0x01) == 0x01) result |= (ushort)(1 << 7); // Dch Over Current 1 if (((reg_byte[0] >> 7) & 0x01) == 0x01) result |= (ushort)(1 << 7); // Dch Over Current 2 if (((reg_byte[1] >> 0) & 0x01) == 0x01) result |= (ushort)(1 << 8); // SC Protect / CB off if (((reg_byte[1] >> 1) & 0x01) == 0x01) result |= (ushort)(1 << 0); // Chg Over Temperature if (((reg_byte[1] >> 2) & 0x01) == 0x01) result |= (ushort)(1 << 1); // Chg Under Temperature if (((reg_byte[1] >> 3) & 0x01) == 0x01) result |= (ushort)(1 << 0); // Dch Over Temperature if (((reg_byte[1] >> 4) & 0x01) == 0x01) result |= (ushort)(1 << 1); // Dch Under Temperature return (short)result; } private static void MakeAlarm(ref CsDeviceData.DeviceModuleData mData) { if (((mData.StatusData.faultstatus >> 14) & 0x0001) == 0x0001) { mData.StatusData.batteryStatus = 4; // Anti-theft Gyroscope } else if (((mData.StatusData.faultstatus >> 15) & 0x0001) == 0x0001) { mData.StatusData.batteryStatus = 5; // Anti-theft Comm. } else if (mData.StatusData.protect != 0x0000) { mData.StatusData.batteryStatus = 2; } else if (mData.StatusData.warning != 0x0000) { mData.StatusData.batteryStatus = 1; } else { mData.StatusData.batteryStatus = 0; } } private static void SetInputRegister(short reg_addr, short reg_value, ref CsDeviceData.DeviceModuleData aModuleData) { switch (reg_addr) { case 0x0FFF: aModuleData.ValueData.voltage = (short)(reg_value / 10); aModuleData.active = true; break; // 48.00V = 4800 case 0x1000: aModuleData.ValueData.current = (short)(reg_value - CURRENT_OFFSET); break; // 100.0A = 1000 -10000 = 0; case 0x1001: aModuleData.ValueData.remainingCapacity = (short)(reg_value / 1); break; // 100.0Ah = 1000 case 0x1002: aModuleData.ValueData.MosTemperature = (short)(reg_value - TEMP_OFFSET); break; // 10.0C = 100 case 0x1003: aModuleData.ValueData.AmbTemperature = (short)(reg_value - TEMP_OFFSET); break; // 10.0C = 100 case 0x1004: aModuleData.StatusData.warning = (ushort)CsAlarmDefine.DevWarningToGui(reg_value); break; // Warning Status case 0x1005: aModuleData.StatusData.protect = (ushort)CsAlarmDefine.DevProtectToGui(reg_value); break; // Protection Status case 0x1006: // Fault Status aModuleData.StatusData.faultstatus = (ushort)(reg_value / 1); aModuleData.StatusData.status = (ushort)((reg_value >> 8) & 0x00FF); MakeAlarm(ref aModuleData); break; // Fault Status case 0x1007: aModuleData.ValueData.SOC = (short)(reg_value / 10); break; // 100.00% = 10000 case 0x1008: aModuleData.ValueData.SOH = (short)(reg_value / 10); break; // 100.00% = 10000 case 0x1009: aModuleData.ValueData.fullChgCapacity_Ah = (ushort)(reg_value / 1); break; // 100.0Ah = 1000 case 0x100A: aModuleData.ValueData.cycleCount = (ushort)(reg_value / 1); break; // 100 cycles = 100 case 0x100B: aModuleData.ValueData.NumOfCells = (short)(reg_value / 1); break; // 15 cells = 15 case 0x100C: case 0x100D: case 0x100E: case 0x100F: case 0x1010: case 0x1011: case 0x1012: case 0x1013: case 0x1014: case 0x1015: case 0x1016: case 0x1017: case 0x1018: case 0x1019: case 0x101A: case 0x101B: // 3.256V = 3256 int cNo = reg_addr - 0x100C; if (cNo < 15) { aModuleData.ValueData.CellVoltage[cNo] = (ushort)(reg_value / 1); } MakeMaxAvgMinCellVoltage(ref aModuleData); break; // 100.00% = 10000 case 0x101C: aModuleData.ValueData.NumOfTemps = (short)(reg_value / 1); break; // 5 temps = 5 case 0x101D: case 0x101E: case 0x101F: case 0x1020: // 25.3C = 253 - 400 = -147 (Offset -400) int tNo = reg_addr - 0x101D; aModuleData.ValueData.CellTemperature[tNo] = (short)(reg_value - TEMP_OFFSET); MakeMaxAvgMinTemperature(ref aModuleData); break; // 100.00% = 10000 case 0x1021: aModuleData.MaxValue.MaxChgCurrent = (short)(reg_value); break; // Max. Charge Current case 0x1022: aModuleData.MaxValue.MaxChgTemperature = (short)(reg_value - TEMP_OFFSET); break; // Max. Charge Temperature case 0x1023: aModuleData.MaxValue.MinChgTemperature = (short)(reg_value - TEMP_OFFSET); break; // Min. Charge Temperature case 0x1024: aModuleData.MaxValue.FloatChgVolt = (short)(reg_value / 10); break; // Float Charge Current case 0x1025: aModuleData.MaxValue.BoostChgVolt = (short)(reg_value / 10); break; // Boost Charge Current case 0x3000: aModuleData.CalibrationData.AntiTheftComm.TimeOut = (short)(reg_value / 1); break; case 0x3002: aModuleData.CalibrationData.AntiTheftComm.FuncSwitch = (short)(reg_value / 1); break; case 0x4000: aModuleData.CalibrationData.AntiTheftGyro.XAxis = (short)(reg_value / 1); break; case 0x4001: aModuleData.CalibrationData.AntiTheftGyro.YAxis = (short)(reg_value / 1); break; case 0x4002: aModuleData.CalibrationData.AntiTheftGyro.ZAxis = (short)(reg_value / 1); break; case 0x4003: aModuleData.CalibrationData.AntiTheftGyro.GyroPolicySel = (short)(reg_value / 1); break; case 0x4004: aModuleData.CalibrationData.AntiTheftGyro.GyroFuncSwitch = (short)(reg_value / 1); break; case 0x4006: aModuleData.CalibrationData.AntiTheftGyro.GyroState = (short)(reg_value / 1); break; default: break; } } private static void SetSP1Register(short reg_addr, short reg_value, ref DeviceSystemData rSystemData) { switch (reg_addr) { case 0x4000: rSystemData.GyroValue.X_axis = (short)(reg_value); break; // case 0x4001: rSystemData.GyroValue.Y_axis = (short)(reg_value); break; // case 0x4002: rSystemData.GyroValue.Z_axis = (short)(reg_value); break; // case 0x4003: rSystemData.GyroValue.Gyro_policy_sel = (short)(reg_value); break; // case 0x4004: rSystemData.GyroValue.Gyro_func_sw = (short)(reg_value); break; // case 0x4006: rSystemData.GyroValue.Gyro_state = (short)(reg_value); break; // default: break; } } private static void SetSP2Register(short reg_addr, short reg_value, ref DeviceSystemData rSystemData) { switch (reg_addr) { case 0x3000: rSystemData.GyroValue.X_axis = (short)(reg_value); break; // case 0x3002: rSystemData.GyroValue.Y_axis = (short)(reg_value); break; // default: break; } } private static void SetReadIdRegister(short reg_addr, short reg_value, ref DeviceSystemData rSystemData) { switch (reg_addr) { case 0x4000: rSystemData.GyroValue.X_axis = (short)(reg_value); break; // case 0x4001: rSystemData.GyroValue.Y_axis = (short)(reg_value); break; // case 0x4002: rSystemData.GyroValue.Z_axis = (short)(reg_value); break; // case 0x4003: rSystemData.GyroValue.Gyro_policy_sel = (short)(reg_value); break; // case 0x4004: rSystemData.GyroValue.Gyro_func_sw = (short)(reg_value); break; // case 0x4006: rSystemData.GyroValue.Gyro_state = (short)(reg_value); break; // default: break; } } private static void SetCoilRegister(short reg_addr, short reg_value, ref CsDeviceData.DeviceModuleData mData) { switch (reg_addr) { case 0x3078: mData.StatusData.relayStatus = (ushort)reg_value; mData.CalibrationData.FetCalib.FetStatus = reg_value; break; case 0x502E: mData.CalibrationData.Current.ChargeOption = reg_value; break; } } private static void MakeMaxAvgMinCellVoltage(ref CsDeviceData.DeviceModuleData mData) { int Max, Avg, Min, Sum; int MaxNo, MinNo; Max = Avg = Min = Sum = 0; MaxNo = MinNo = 0; for (int i = 0; i < mData.cellQty; i++) { if (i == 0) { Max = Min = mData.ValueData.CellVoltage[i]; } Sum += mData.ValueData.CellVoltage[i]; if (Max < mData.ValueData.CellVoltage[i]) { Max = mData.ValueData.CellVoltage[i]; MaxNo = i; } if (Min > mData.ValueData.CellVoltage[i]) { Min = mData.ValueData.CellVoltage[i]; MinNo = i; } } Avg = Sum / mData.cellQty; mData.AvgData.avgCellVoltage = (short)Avg; mData.AvgData.maxCellVoltage = (short)Max; mData.AvgData.maxCellNum = (short)(MaxNo + 1); mData.AvgData.minCellVoltage = (short)Min; mData.AvgData.minCellNum = (short)(MinNo + 1); mData.AvgData.diffCellVoltage = (short)(Max - Min); } private static void MakeMaxAvgMinTemperature(ref CsDeviceData.DeviceModuleData mData) { int Max, Avg, Min, Sum; int MaxNo, MinNo; Max = Avg = Min = Sum = 0; MaxNo = MinNo = 0; for (int i = 0; i < mData.tempQty; i++) { if (i == 0) { Max = Min = mData.ValueData.CellTemperature[i]; } Sum += mData.ValueData.CellTemperature[i]; if (Max < mData.ValueData.CellTemperature[i]) { Max = mData.ValueData.CellTemperature[i]; MaxNo = i; } if (Min > mData.ValueData.CellTemperature[i]) { Min = mData.ValueData.CellTemperature[i]; MinNo = i; } } Avg = Sum / mData.tempQty; mData.AvgData.avgTemp = (short)Avg; mData.AvgData.maxTemp = (short)Max; mData.AvgData.maxTempNum = (short)(MaxNo + 1); mData.AvgData.minTemp = (short)Min; mData.AvgData.minTempNum = (short)(MinNo + 1); mData.AvgData.diffTemp = (short)(Max - Min); } private static short MakeUartWarningData(short rdata) { short result = 0; bool[] bAlarm = csUtils.Int16ToBitArray(rdata); if (bAlarm[0] == true) result |= (short)(1 << 2); // 0x0001:Pack OV if (bAlarm[1] == true) result |= (short)(1 << 4); // 0x0002:Cell OV if (bAlarm[2] == true) result |= (short)(1 << 3); // 0x0004:Pack UV if (bAlarm[3] == true) result |= (short)(1 << 5); // 0x0008:Cell UV if (bAlarm[4] == true) result |= (short)(1 << 6); // 0x0010:Charging OC if (bAlarm[5] == true) result |= (short)(1 << 7); // 0x0020:Discharging OC if (bAlarm[8] == true) result |= (short)(1 << 0); // 0x0080: Charging Over Tempratuer if (bAlarm[9] == true) result |= (short)(1 << 0); // 0x0080: Discharging Over Tempratuer if (bAlarm[10] == true) result |= (short)(1 << 1); // 0x0040: Charging Under Tempratuer if (bAlarm[11] == true) result |= (short)(1 << 1); // 0x0040: Discharging Under Tempratuer if (bAlarm[12] == true) result |= (short)(1 << 11); // 0x0200:SOC Low return result; } private static short MakeUartTripData(short rdata) { short result = 0; bool[] bAlarm = csUtils.Int16ToBitArray(rdata); if (bAlarm[0] == true) result |= (short)(1 << 2); // 0x0001:Pack OV if (bAlarm[1] == true) result |= (short)(1 << 4); // 0x0002:Cell OV if (bAlarm[2] == true) result |= (short)(1 << 3); // 0x0004:Pack UV if (bAlarm[3] == true) result |= (short)(1 << 5); // 0x0008:Cell UV if (bAlarm[4] == true) result |= (short)(1 << 6); // 0x0010:Charging OC if (bAlarm[5] == true) result |= (short)(1 << 7); // 0x0020:Discharging OC if (bAlarm[8] == true) result |= (short)(1 << 0); // 0x0080: Charging Over Temprature if (bAlarm[9] == true) result |= (short)(1 << 0); // 0x0080: Discharging Over Temprature if (bAlarm[10] == true) result |= (short)(1 << 1); // 0x0040: Charging Under Temprature if (bAlarm[11] == true) result |= (short)(1 << 1); // 0x0040: Discharging Under Temprature if (bAlarm[13] == true) result |= (short)(1 << 9); // 0x0200:Short Circuit Protection return result; } private static short MakeUartErrorData(short rdata, short cdata) { short result = cdata; bool[] bAlarm = csUtils.Int16ToBitArray(rdata); if (bAlarm[0] == true) result |= (short)(1 << 9); // 0x0001:Voltage error if (bAlarm[1] == true) result |= (short)(1 << 9); // 0x0002:Temperature error if (bAlarm[2] == true) result |= (short)(1 << 9); // 0x0004: 电流检测Error if (bAlarm[3] == true) result |= (short)(1 << 9); // 0x0010:Cell unbalance return result; } } }