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 System.Data.Entity.Core.Common.CommandTrees; using DevExpress.XtraRichEdit.Fields.Expression; using DevExpress.XtraRichEdit.Layout; using DevExpress.XtraPrinting.Native.LayoutAdjustment; namespace LFP_Manager.Function { class csSerialCommFunction { static readonly byte[] auchCRCHi = { 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,0x40 }; static readonly byte[] auchCRCLo = { 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,0x40 }; 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 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 ^ auchCRCHi[uIndex]); uchCRCHi = 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) { byte[] result = new byte[9 + (WriteData.Length * 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)(WriteData.Length >> 8); // Count of Register MSB result[i++] = (byte)(WriteData.Length >> 0); // Count of Register LSB result[i++] = (byte)(WriteData.Length * 2); // Byte Count - [2 * (Num of register)] for (int j = 0; j < WriteData.Length; j++) { result[i++] = (byte)(WriteData[j] >> 8); result[i++] = (byte)(WriteData[j] >> 0); } crc = GetCRC(result, i); result[i++] = crc[1]; // CRCH result[i++] = 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; } 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_COIL_STATUS: case READ_HOLDING_REG: case READ_INPUT_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 DeviceSystemData rSystemData) { short[] result = new short[2]; switch (rData[1]) { case READ_COIL_STATUS: ReadCoilRegisterProcess(rData, rRegAddr, rLen, ref rSystemData); break; case READ_HOLDING_REG: ReadHoldRegisterProcess(rData, rRegAddr, rLen, ref rSystemData); break; case READ_INPUT_REG: //ReadInputRegisterProcess(rData, rRegAddr, rLen, ref rSystemData); break; //case READ_INPUT_REG: // ReadRegister(rData, rRegAddr, rLen, ref rSystemData); // 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 DeviceSystemData rSystemData) { 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 rSystemData); i++; } } private static void ReadHoldRegisterProcess(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]); SetHoldRegister((short)(rRegAddr + j), reg_value, ref rSystemData); i += 2; } } private static void SetCoilRegister(short reg_addr, short reg_value, ref DeviceSystemData rSystemData) { switch (reg_addr) { case 0x3078: rSystemData.StatusData.relayStatus = reg_value; rSystemData.CalibrationData.FetCalib.FetStatus = reg_value; break; case 0x502E: rSystemData.CalibrationData.Current.ChargeOption = reg_value; break; } } private static void SetHoldRegister(short reg_addr, short reg_value, ref DeviceSystemData rSystemData) { int temp = 0; switch (reg_addr) { case 0: rSystemData.ValueData.voltageOfPack = (short)(reg_value / 10); break; //Total Voltage case 1: rSystemData.ValueData.current = (short)((reg_value) / 10); break; //Total Current case 2: // Cell Voltage #1 case 3: // Cell Voltage #2 case 4: // Cell Voltage #3 case 5: // Cell Voltage #4 case 6: // Cell Voltage #5 case 7: // Cell Voltage #6 case 8: // Cell Voltage #7 case 9: // Cell Voltage #8' case 10: // Cell Voltage #9 case 11: // Cell Voltage #10 case 12: // Cell Voltage #11 case 13: // Cell Voltage #12 case 14: // Cell Voltage #13 case 15: // Cell Voltage #14 case 16: // Cell Voltage #15 rSystemData.ValueData.CellVoltage[reg_addr - 2] = (ushort)(reg_value / 1); csUtils.MakeMaxAvgMinCellVoltage(ref rSystemData, 15); break; // 15 CellVoltage 1mV case 17: break; // Cell Voltage #16 - Reserved case 18: rSystemData.ValueData.Ext1Temperature = (short)((reg_value) * 10); break; //Ext1 Temperature (Temp of MOS-FET) case 19: rSystemData.ValueData.Ext2Temperature = (short)((reg_value) * 10); break; //Ext2 Amb. PCB Temperature 1C case 20: break; // Temp Max. case 21: rSystemData.ValueData.remainingCapacity = (short)(reg_value / 1); break; // Remaining Capacity case 22: rSystemData.ValueData.MaxBattChargeCurr = reg_value / 1; break; case 23: rSystemData.ValueData.stateOfHealth = (short)(reg_value * 10); break; case 24: rSystemData.ValueData.rSOC = (short)(reg_value * 10); break; //SOC case 25: rSystemData.StatusData.status = reg_value; break; //Operating Status case 26: rSystemData.StatusData.warning = MakeUartWarningData(reg_value); break; //Warning Status case 27: rSystemData.StatusData.protection = MakeUartTripData(reg_value); break; //Protection Status case 28: // Error Code // 0x0001:Voltage error // 0x0002:Temperature error // 0x0004: Current Check Error // 0x0010:Cell unbalance break; case 29: // Cycle count MSB temp = rSystemData.ValueData.cycleCount; rSystemData.ValueData.cycleCount = (temp & (0x0000FFFF)) | (reg_value << 16); break; case 30: // Cycle count LSB temp = rSystemData.ValueData.cycleCount; rSystemData.ValueData.cycleCount = (int)(temp & (0xFFFF0000)) | (reg_value << 0); break; case 31: // fullChargeCapacity MSB temp = rSystemData.ValueData.fullChargeCapacity; rSystemData.ValueData.fullChargeCapacity = (temp & (0x0000FFFF)) | (reg_value << 16); break; case 32: // fullChargeCapacity LSB temp = rSystemData.ValueData.fullChargeCapacity; rSystemData.ValueData.fullChargeCapacity = (int)(temp & (0xFFFF0000)) | (reg_value << 0); break; case 33: case 34: rSystemData.ValueData.CellTemperature[((reg_addr - 33) * 2) + 0] = (short)(((reg_value >> 8) & 0xFF) * 10); rSystemData.ValueData.CellTemperature[((reg_addr - 33) * 2) + 1] = (short)(((reg_value >> 0) & 0xFF) * 10); csUtils.MakeMaxAvgMinTemperature(ref rSystemData, 4); break; case 35: break; // Reserved case 36: rSystemData.cellQty = reg_value; break; // Cell Qty case 37: rSystemData.ValueData.designedCapacity = reg_value; break; case 38: rSystemData.StatusData.cellBallanceStatus = reg_value; break; case 39: rSystemData.StatusData.specialAlarm = (short)(reg_value); break; // Special Alarm //case 61: rSystemData.StatusData.cellBallanceStatus = reg_value; break; //45 ~ 99 : Reserved case 45: rSystemData.BmsDateTimeShort1 = (ushort)reg_value; break; // DateTime case 46: rSystemData.BmsDateTimeShort2 = (ushort)reg_value; int yy, MM, dd, HH, mm, ss; rSystemData.BmsDateTimeInt = (rSystemData.BmsDateTimeShort1 << 16) | (rSystemData.BmsDateTimeShort2); yy = (rSystemData.BmsDateTimeInt >> 26) & 0x003F; MM = ((rSystemData.BmsDateTimeInt >> 22) & 0x000F) % 13; dd = ((rSystemData.BmsDateTimeInt >> 17) & 0x001F) % 32; HH = ((rSystemData.BmsDateTimeInt >> 12) & 0x001F) % 24; mm = ((rSystemData.BmsDateTimeInt >> 6) & 0x003F) % 60; ss = ((rSystemData.BmsDateTimeInt >> 0) & 0x003F) % 60; yy += 2000; rSystemData.BmsDateTime.DateTimeStr = string.Format("{0:0000}-{1:00}-{2:00} {3:00}:{4:00}:{5:00}" , yy , MM , dd , HH , mm , ss ); break; // DateTime case 47: rSystemData.CalibrationData.ChaMode.Mode = reg_value; break; // 0x2F case 48: rSystemData.CalibrationData.ChaMode.Value = reg_value; break; // 0x2F case 56: rSystemData.CalibrationData.BalCalib.Volt = reg_value; break; // Cell Balance Voltage case 57: rSystemData.CalibrationData.BalCalib.Diff = reg_value; break; // Cell Balance Diff case 58: rSystemData.ParamData.LowSocWarning = reg_value; break; case 61: rSystemData.ParamData.CellUnderVoltageWarning = reg_value; break; case 62: rSystemData.ParamData.CellUnderVoltageTrip = reg_value; break; case 63: rSystemData.ParamData.CellUnderVoltageRelease = reg_value; break; case 64: rSystemData.ParamData.SysUnderVoltageWarning = (short)(reg_value / 10); break; case 65: rSystemData.ParamData.SysUnderVoltageTrip = (short)(reg_value / 10); break; case 66: rSystemData.ParamData.SysUnderVoltageRelease = (short)(reg_value / 10); break; case 67: rSystemData.ParamData.CellOverVoltageWarning = reg_value; break; case 68: rSystemData.ParamData.CellOverVoltageTrip = reg_value; break; case 69: rSystemData.ParamData.CellOverVoltageRelease = reg_value; break; case 70: rSystemData.ParamData.SysOverVoltageWarning = (short)(reg_value / 10); break; case 71: rSystemData.ParamData.SysOverVoltageTrip = (short)(reg_value / 10); break; case 72: rSystemData.ParamData.SysOverVoltageRelease = (short)(reg_value / 10); break; case 76: rSystemData.ParamData.ChaOverCurrentTimes = (short)(reg_value / 1); break; case 77: rSystemData.ParamData.DchOverCurrentTimes = (short)(reg_value / 1); break; case 78: rSystemData.ParamData.ChaOverCurrentReleaseTime = (short)(reg_value * 1); break; case 79: rSystemData.ParamData.DchOverCurrentReleaseTime = (short)(reg_value * 1); break; case 80: rSystemData.ParamData.ChaOverCurrentTrip1 = (short)(reg_value / 10); break; case 81: rSystemData.ParamData.DchOverCurrentTrip1 = (short)(reg_value / 10); break; case 82: rSystemData.ParamData.ShortCircuit = (short)(reg_value / 10); break; // Short Circuit Current = 300A case 83: rSystemData.ParamData.ChaOverCurrentTrip2 = (short)(reg_value / 10); break; case 84: rSystemData.ParamData.DchOverCurrentTrip2 = (short)(reg_value / 10); break; case 85: rSystemData.ParamData.ChaOverCurrentDelay1 = (short)(reg_value / 1); break; case 86: rSystemData.ParamData.ChaOverCurrentDelay2 = (short)(reg_value / 1); break; case 87: rSystemData.ParamData.DchOverCurrentDelay1 = (short)(reg_value / 1); break; case 88: rSystemData.ParamData.DchOverCurrentDelay2 = (short)(reg_value / 1); break; case 90: rSystemData.ParamData.ChaLowTempWarning = (short)(reg_value - 50); break; case 91: rSystemData.ParamData.ChaLowTempTrip = (short)(reg_value - 50); break; case 92: rSystemData.ParamData.ChaLowTempRelease = (short)(reg_value - 50); break; case 93: rSystemData.ParamData.ChaHighTempWarning = (short)(reg_value - 50); break; case 94: rSystemData.ParamData.ChaHighTempTrip = (short)(reg_value - 50); break; case 95: rSystemData.ParamData.ChaHighTempRelease = (short)(reg_value - 50); break; case 96: rSystemData.ParamData.DchLowTempWarning = (short)(reg_value - 50); break; case 97: rSystemData.ParamData.DchLowTempTrip = (short)(reg_value - 50); break; case 98: rSystemData.ParamData.DchLowTempRelease = (short)(reg_value - 50); break; case 99: rSystemData.ParamData.DchHighTempWarning = (short)(reg_value - 50); break; case 100: rSystemData.ParamData.DchHighTempTrip = (short)(reg_value - 50); break; case 101: rSystemData.ParamData.DchHighTempRelease = (short)(reg_value - 50); break; case 102: break; // PCB High Temp Warning case 103: break; // PCB High Temp Trip case 104: break; // PCB High Temp Release //100 ~111 : Model_Product Name case 105: case 106: case 107: case 108: case 109: case 110: case 111: case 112: case 113: case 114: case 115: case 116: int mReg = reg_addr - 105; rSystemData.Information.Model_Byte[(mReg * 2) + 0] = (byte)(reg_value >> 8); rSystemData.Information.Model_Byte[(mReg * 2) + 1] = (byte)(reg_value >> 0); if (reg_addr == 116) { rSystemData.Information.ModelName = Encoding.Default.GetString(rSystemData.Information.Model_Byte).Trim('\0'); } break; //112 ~114 : FW Version case 117: case 118: case 119: int fReg = reg_addr - 117; rSystemData.Information.FwVer_Byte[(fReg * 2) + 0] = (byte)(reg_value >> 8); rSystemData.Information.FwVer_Byte[(fReg * 2) + 1] = (byte)(reg_value >> 0); if (reg_addr == 119) { rSystemData.Information.SwProductRev = Encoding.Default.GetString(rSystemData.Information.FwVer_Byte).Trim('\0'); } break; //115 ~ 122 : BMS Serial number case 120: case 121: case 122: case 123: case 124: case 125: case 126: case 127: int snReg = reg_addr - 120; rSystemData.Information.BMS_SN[(snReg * 2) + 0] = (byte)(reg_value >> 8); rSystemData.Information.BMS_SN[(snReg * 2) + 1] = (byte)(reg_value >> 0); if (reg_addr == 127) { rSystemData.Information.HwSerialNumber = Encoding.Default.GetString(rSystemData.Information.BMS_SN).Trim('\0'); } break; case 130: rSystemData.ParamData.EnvLowTempWarning = (short)(reg_value - 50); break; case 131: rSystemData.ParamData.EnvLowTempTrip = (short)(reg_value - 50); break; case 132: rSystemData.ParamData.EnvLowTempRelease = (short)(reg_value - 50); break; case 133: rSystemData.ParamData.EnvHighTempWarning = (short)(reg_value - 50); break; case 134: rSystemData.ParamData.EnvHighTempTrip = (short)(reg_value - 50); break; case 135: rSystemData.ParamData.EnvHighTempRelease = (short)(reg_value - 50); break; case 136: // Anti-Theft Communication rSystemData.CalibrationData.AntiTheft.Comm = reg_value; break; case 137: // Anti-Theft Gyro-Scope rSystemData.CalibrationData.AntiTheft.GyroScope = reg_value; break; case 163: // 0xA3 case 164: // 0xA4 case 165: // 0xA5 case 166: // 0xA6 int ManuDateReg = reg_addr - 163; rSystemData.Information.ManuDate_Byte[(ManuDateReg * 2) + 0] = (byte)(reg_value >> 8); rSystemData.Information.ManuDate_Byte[(ManuDateReg * 2) + 1] = (byte)(reg_value >> 0); if (reg_addr == 166) { rSystemData.Information.ManufacturingDate = Encoding.Default.GetString(rSystemData.Information.ManuDate_Byte).Trim('\0'); } break; } csMakeDataFunction.MakeAlarm(ref rSystemData); } public 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; } public 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 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[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; } } }