using System; using System.Linq; using System.Collections.Generic; using System.Text; using BMS_D1000H.BMSConstData; using BMS_D1000H.DataStructs; using BMS_D1000H.Utils.Functions; namespace BMS_D1000H.Functions { class csModbusDataProcess { #region Recv System Data public static DeviceDataSystem ModBusSystemData_Reg(DeviceDataSystem aMainData, int base_addr, byte[] bdata, int len) { DeviceDataSystem sData = aMainData; if (bdata == null || bdata.Length == 0) return sData; try { int i = 0; for (int j = 0; j < len; j++) { if (i + 1 >= bdata.Length) break; short val = ConvertTo.TwoByteToShort(bdata[i], bdata[i + 1], true); int reg = base_addr + j; ParseSystemRegister(ref sData, reg, val); i += 2; } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine("ModBusSystemData_Reg Parse Error: " + ex.Message); } return sData; } private static bool ParseSystemRegister(ref DeviceDataSystem sData, int reg, short val) { // 기본 상태 및 모듈 통계 데이터 (0 ~ 44) if (reg <= 44) { switch (reg) { case 0: sData.BatVoltage = val; return true; case 1: sData.Current = val; return true; case 2: sData.AverageCurrent = val; return true; case 3: sData.RelativeStateOfCharge = val; return true; case 10: sData.MaxTemp = val; return true; case 11: sData.MinTemp = val; return true; case 12: sData.AvgTemp = val; return true; case 13: sData.MaxCell = val; return true; case 14: sData.MinCell = val; return true; case 15: sData.AvgCell = val; return true; case 16: sData.ModuleQuantity = val; return true; case 17: sData.HistoryDelete = val; return true; case 20: sData.Warning = val; return true; case 21: sData.Protection = val; return true; case 22: sData.TrayCommState = val; return true; case 41: sData.AlarmStatus = val; return true; case 44: sData.OpStatus = val; return true; } } // 파라미터 임계치 정보 (60 ~ 89) else if (reg >= 60 && reg <= 89) { return ParseSystemParams(ref sData, reg, val); } // 네트워크 및 트랩 IP 설정 (120 ~ 147) else if (reg >= 120 && reg <= 147) { return ParseSystemNetConfig(ref sData, reg, val); } return false; } private static bool ParseSystemParams(ref DeviceDataSystem sData, int reg, short val) { switch (reg) { case 60: sData.param.voltage.CUV_Warning = val; return true; case 61: sData.param.voltage.CUV_Threshold = val; return true; case 62: sData.param.voltage.CUV_Recovery = val; return true; case 63: sData.param.voltage.SUV_Warning = val; return true; case 64: sData.param.voltage.SUV_Threshold = val; return true; case 65: sData.param.voltage.SUV_Recovery = val; return true; case 66: sData.param.voltage.COV_Warning = val; return true; case 67: sData.param.voltage.COV_Threshold = val; return true; case 68: sData.param.voltage.COV_Recovery = val; return true; case 69: sData.param.voltage.SOV_Warning = val; return true; case 70: sData.param.voltage.SOV_Threshold = val; return true; case 71: sData.param.voltage.SOV_Recovery = val; return true; case 72: sData.param.current.OC_Chg_Threshold = val; return true; case 73: sData.param.current.OC_Chg_Warning = val; return true; case 74: sData.param.current.OC_Chg_Recovery = val; return true; case 75: sData.param.current.OC_Chg_Time = val; return true; case 76: sData.param.current.OC_Dsg_Threshold = val; return true; case 77: sData.param.current.OC_Dsg_Warning = val; return true; case 78: sData.param.current.OC_Dsg_Recovery = val; return true; case 79: sData.param.current.OC_Dsg_Time = val; return true; case 80: sData.param.temperature.OT_Chg_Threshold = val; return true; case 81: sData.param.temperature.OT_Chg_Warning = val; return true; case 82: sData.param.temperature.OT_Chg_Recovery = val; return true; case 83: sData.param.temperature.OT_Chg_Time = val; return true; case 84: sData.param.temperature.OT_Dsg_Threshold = val; return true; case 85: sData.param.temperature.OT_Dsg_Warning = val; return true; case 86: sData.param.temperature.OT_Dsg_Recovery = val; return true; case 87: sData.param.temperature.OT_Dsg_Time = val; return true; case 88: sData.param.soc.Low_SOC_Warning = val; return true; case 89: sData.param.soc.Low_SOC_Recovery = val; return true; } return false; } private static bool ParseSystemNetConfig(ref DeviceDataSystem sData, int reg, short val) { if (reg >= 120 && reg <= 123) { sData.netconfig.ip_addr.addr[reg - 120] = val; return true; } if (reg >= 124 && reg <= 127) { sData.netconfig.subnet_mask.addr[reg - 124] = val; return true; } if (reg >= 128 && reg <= 131) { sData.netconfig.gateway_addr.addr[reg - 128] = val; return true; } if (reg >= 132 && reg <= 147) { int trapIdx = (reg - 132) / 4; int addrIdx = (reg - 132) % 4; sData.netconfig.trap[trapIdx].addr[addrIdx] = val; return true; } return false; } #endregion #region Recv Tray Data public static DeviceDataTray ModBusData_Reg(int base_addr, byte[] bdata, int len) { DeviceDataTray tData = new DeviceDataTray(); tData.CellVoltage = new short[SystemID.MAX_TRAY_CELL_SIZE]; tData.CellTemperature = new short[SystemID.MAX_TRAY_TEMP_SIZE]; if (bdata == null || bdata.Length == 0) return tData; try { int i = 0; for (int j = 0; j < len; j++) { if (i + 1 >= bdata.Length) break; short val = ConvertTo.TwoByteToShort(bdata[i], bdata[i + 1], true); int reg = base_addr + j; ParseTrayRegister(ref tData, reg, val); i += 2; } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine("ModBusData_Reg Parse Error: " + ex.Message); } return tData; } private static void ParseTrayRegister(ref DeviceDataTray tData, int reg, short val) { // 기본 상태 및 Cell / Temp 데이터 if (reg == 0) tData.BatVoltage = val; else if (reg == 1) tData.Current = val; else if (reg == 2) tData.AverageCurrent = val; else if (reg >= 3 && reg <= 17) { int cellIdx = reg - 3; if (cellIdx < tData.CellVoltage.Length) tData.CellVoltage[cellIdx] = val; } else if (reg >= 18 && reg <= 23) { int tempIdx = reg - 18; if (tempIdx < tData.CellTemperature.Length) tData.CellTemperature[tempIdx] = val; } else if (reg >= 26 && reg <= 29) { switch (reg) { case 26: tData.RelativeStateOfCharge = val; break; case 27: tData.RemainingCapacity = val; break; case 28: tData.StateOfHealth = val; break; case 29: tData.CycleCount = val; break; } } else if (reg == 31) tData.FullChargeCapacity = val; else if (reg == 32) tData.DesignCapacity = val; else if (reg >= 37 && reg <= 40) { switch (reg) { case 37: tData.MaxCellVoltage = val; break; case 38: tData.MinCellVoltage = val; break; case 39: tData.AvgCellVoltage = val; break; case 40: tData.DiffCellVoltage = val; break; } } else if (reg >= 41 && reg <= 45) { switch (reg) { case 41: tData.AlarmStatus = val; break; case 42: tData.Warning = val; break; case 43: tData.Protection = val; break; case 44: tData.OpStatus = val; break; case 45: tData.Commfail = val; break; } } else if (reg >= 46 && reg <= 48) { switch (reg) { case 46: tData.CellBalanceData = val; break; case 47: tData.CellBalanceAvg = val; break; case 48: tData.CellBalanceFlag = val; break; } } else if (reg >= 52 && reg <= 58) { switch (reg) { case 52: tData.MaxCellNo = val; break; case 53: tData.MinCellNo = val; break; case 54: tData.MaxTemp = val; break; case 55: tData.MinTemp = val; break; case 56: tData.MaxTempNo = val; break; case 57: tData.MinTempNo = val; break; case 58: tData.AvgTemp = val; break; } } else if (reg >= 60 && reg <= 89) { ParseTrayParams(ref tData, reg, val); } else if (reg >= 90 && reg <= 101) { ParseTrayProtections(ref tData, reg, val); } } private static void ParseTrayParams(ref DeviceDataTray tData, int reg, short val) { switch (reg) { case 60: tData.param.voltage.CUV_Warning = val; break; case 61: tData.param.voltage.CUV_Threshold = val; break; case 62: tData.param.voltage.CUV_Recovery = val; break; case 63: tData.param.voltage.SUV_Warning = val; break; case 64: tData.param.voltage.SUV_Threshold = val; break; case 65: tData.param.voltage.SUV_Recovery = val; break; case 66: tData.param.voltage.COV_Warning = val; break; case 67: tData.param.voltage.COV_Threshold = val; break; case 68: tData.param.voltage.COV_Recovery = val; break; case 69: tData.param.voltage.SOV_Warning = val; break; case 70: tData.param.voltage.SOV_Threshold = val; break; case 71: tData.param.voltage.SOV_Recovery = val; break; case 72: tData.param.current.OC_Chg_Threshold = val; break; case 73: tData.param.current.OC_Chg_Warning = val; break; case 74: tData.param.current.OC_Chg_Recovery = val; break; case 75: tData.param.current.OC_Chg_Time = val; break; case 76: tData.param.current.OC_Dsg_Threshold = val; break; case 77: tData.param.current.OC_Dsg_Warning = val; break; case 78: tData.param.current.OC_Dsg_Recovery = val; break; case 79: tData.param.current.OC_Dsg_Time = val; break; case 80: tData.param.temperature.OT_Chg_Threshold = val; break; case 81: tData.param.temperature.OT_Chg_Warning = val; break; case 82: tData.param.temperature.OT_Chg_Recovery = val; break; case 83: tData.param.temperature.OT_Chg_Time = val; break; case 84: tData.param.temperature.OT_Dsg_Threshold = val; break; case 85: tData.param.temperature.OT_Dsg_Warning = val; break; case 86: tData.param.temperature.OT_Dsg_Recovery = val; break; case 87: tData.param.temperature.OT_Dsg_Time = val; break; case 88: tData.param.soc.Low_SOC_Warning = val; break; case 89: tData.param.soc.Low_SOC_Recovery = val; break; } } private static void ParseTrayProtections(ref DeviceDataTray tData, int reg, short val) { switch (reg) { case 90: tData.cov_protection_cell = val; break; case 91: tData.cov_warning_cell = val; break; case 92: tData.cuv_protection_cell = val; break; case 93: tData.cuv_warning_cell = val; break; case 94: tData.otd_warning_temp = val; break; case 95: tData.otd_protection_temp = val; break; case 96: tData.otc_warning_temp = val; break; case 97: tData.otc_protection_temp = val; break; case 98: tData.ltd_warning_temp = val; break; case 99: tData.ltd_protection_temp = val; break; case 100: tData.ltc_warning_temp = val; break; case 101: tData.ltc_protection_temp = val; break; } } #endregion } }