using System; namespace LFP_Manager.DataStructure { public class CsDeviceData : IResettable, IDeepCopy { public DeviceSystemTotalData TotalData; public DeviceModuleData[] ModuleData; public CsDeviceData() { TotalData = new DeviceSystemTotalData(); ModuleData = new DeviceModuleData[csConstData.SystemInfo.MAX_MODULE_SIZE]; for (int i = 0; i < ModuleData.Length; i++) { ModuleData[i] = new DeviceModuleData(); } } public void Reset() { TotalData.Reset(); for (int i = 0; i < ModuleData.Length; i++) { ResetCopyHelpers.ResetOrRecreate(ref ModuleData[i]); } } public CsDeviceData DeepCopy() { var copy = (CsDeviceData)MemberwiseClone(); // 스칼라 복사 copy.TotalData = ResetCopyHelpers.DeepCopyOrNew(TotalData); for (int i = 0; i < ModuleData.Length; i++) { ModuleData[i] = ResetCopyHelpers.DeepCopyOrNew(ModuleData[i]); } return copy; } #region TOTAL DATA public class DeviceSystemTotalData : IResettable, IDeepCopy { public bool CommFail; public DeviceSystemIdent IdentData; public DeviceValueTotalData ValueData; public DeviceStatusTotalData StatusData; public DeviceSystemTotalData() { IdentData = new DeviceSystemIdent(); ValueData = new DeviceValueTotalData(); StatusData = new DeviceStatusTotalData(); } public void Reset() { CommFail = false; IdentData.Reset(); ValueData.Reset(); StatusData.Reset(); } public DeviceSystemTotalData DeepCopy() { var copy = (DeviceSystemTotalData)MemberwiseClone(); // 스칼라 복사 copy.IdentData = IdentData.DeepCopy(); copy.ValueData = ValueData.DeepCopy(); copy.StatusData = StatusData.DeepCopy(); return copy; } public class DeviceSystemIdent : IResettable, IDeepCopy { public byte[] fw_ver; public string FwVerStr; public string Manufacturer; public string DeviceModel; public int AlarmOutputMode; public UInt32 ManufactureDate; public string SerialNumber; public DeviceSystemIdent() { fw_ver = new byte[4]; FwVerStr = ""; Manufacturer = ""; DeviceModel = ""; AlarmOutputMode = 0; ManufactureDate = 0; SerialNumber = ""; } public void Reset() { Manufacturer = ""; DeviceModel = ""; Array.Clear(fw_ver, 0, fw_ver.Length); FwVerStr = ""; AlarmOutputMode = 0; ManufactureDate = 0; SerialNumber = ""; } public DeviceSystemIdent DeepCopy() { var copy = (DeviceSystemIdent)MemberwiseClone(); // 스칼라 복사 copy.fw_ver = (byte[])fw_ver.Clone(); return copy; } } public class DeviceValueTotalData : IResettable, IDeepCopy { public short TotalVoltage; public short TotalCurrent; public short TotalSOC; public short TotalSOH; public short TotalTemp; public DeviceValueTotalData() { TotalVoltage = 0; TotalCurrent = 0; TotalSOC = 0; TotalSOH = 0; TotalTemp = 0; } public void Reset() { TotalVoltage = 0; TotalCurrent = 0; TotalSOC = 0; TotalSOH = 0; TotalTemp = 0; } public DeviceValueTotalData DeepCopy() { return (DeviceValueTotalData)MemberwiseClone(); } } public class DeviceStatusTotalData : IResettable, IDeepCopy { public ushort batteryStatus; public ushort warning; public ushort protection; public ushort status; public DeviceStatusTotalData() { batteryStatus = 0; warning = 0; protection = 0; status = 0; } public void Reset() { batteryStatus = 0; warning = 0; protection = 0; status = 0; } public DeviceStatusTotalData DeepCopy() { return (DeviceStatusTotalData)MemberwiseClone(); } } } #endregion #region MODULE DATA public class DeviceModuleData : IResettable, IDeepCopy { public bool active; public int mNo; public int cellQty; public int tempQty; public int ntcQty; public int ChargeVoltage; public int DOD; public int MaxChaCurrent; public int MaxDchCurrent; public int FloatVoltage; public int BoostVoltage; public int MinChargeTemp; public int MaxChargeTemp; public UInt32 heatbeat; public bool CommFail; public bool ShelfCommFail; public DateTime LastRxTime; public Int32 BmsDateTimeInt; public ushort BmsDateTimeShort1; public ushort BmsDateTimeShort2; public DateTimeStruct BmsDateTime; public DeviceValueData ValueData; public DeviceAvgData AvgData; public DeviceStatusData StatusData; public DeviceParamData ParamData; public DeviceCalibration CalibrationData; public DeviceInforation Information; public DeviceEtcStatus EtcStatus; public DeviceMaxValue MaxValue; public DeviceGyroValue GyroValue; public DeviceModuleData() { active = false; mNo = 0; cellQty = 15; tempQty = 4; ChargeVoltage = 0; DOD = 0; MaxChaCurrent = 0; MaxDchCurrent = 0; heatbeat = 0; CommFail = false; ShelfCommFail = false; LastRxTime = DateTime.MinValue; BmsDateTimeInt = 0; BmsDateTimeShort1 = 0; BmsDateTimeShort2 = 0; BmsDateTime = new DateTimeStruct(); ValueData = new DeviceValueData(); AvgData = new DeviceAvgData(); StatusData = new DeviceStatusData(); ParamData = new DeviceParamData(); CalibrationData = new DeviceCalibration(); Information = new DeviceInforation(); EtcStatus = new DeviceEtcStatus(); MaxValue = new DeviceMaxValue(); GyroValue = new DeviceGyroValue(); } public void Reset() { active = false; mNo = 0; cellQty = 15; tempQty = 4; ChargeVoltage = 0; DOD = 0; MaxChaCurrent = 0; MaxDchCurrent = 0; heatbeat = 0; CommFail = false; ShelfCommFail = false; LastRxTime = DateTime.MinValue; BmsDateTimeInt = 0; BmsDateTimeShort1 = 0; BmsDateTimeShort2 = 0; ResetCopyHelpers.ResetOrRecreate(ref BmsDateTime); ResetCopyHelpers.ResetOrRecreate(ref ValueData); ResetCopyHelpers.ResetOrRecreate(ref AvgData); ResetCopyHelpers.ResetOrRecreate(ref ParamData); ResetCopyHelpers.ResetOrRecreate(ref CalibrationData); ResetCopyHelpers.ResetOrRecreate(ref Information); ResetCopyHelpers.ResetOrRecreate(ref EtcStatus); ResetCopyHelpers.ResetOrRecreate(ref MaxValue); ResetCopyHelpers.ResetOrRecreate(ref GyroValue); } public DeviceModuleData DeepCopy() { var copy = (DeviceModuleData)MemberwiseClone(); // 스칼라 복사 BmsDateTime = ResetCopyHelpers.DeepCopyOrNew(BmsDateTime); ValueData = ResetCopyHelpers.DeepCopyOrNew(ValueData); AvgData = ResetCopyHelpers.DeepCopyOrNew(AvgData); StatusData = ResetCopyHelpers.DeepCopyOrNew(StatusData); ParamData = ResetCopyHelpers.DeepCopyOrNew(ParamData); CalibrationData = ResetCopyHelpers.DeepCopyOrNew(CalibrationData); EtcStatus = ResetCopyHelpers.DeepCopyOrNew(EtcStatus); MaxValue = ResetCopyHelpers.DeepCopyOrNew(MaxValue); GyroValue = ResetCopyHelpers.DeepCopyOrNew(GyroValue); return copy; } public class DateTimeStruct : IResettable, IDeepCopy { public int year; public int month; public int day; public int hour; public int minute; public int second; public string DateTimeStr; public DateTimeStruct() { DateTimeStr = "-"; } public void SetDateTimeStr() { DateTimeStr = String.Format("{0:D4}-{1:D2}-{2:D2} {3:D2}:{4:D2}:{5:D2}", year, month, day, hour, minute, second); } public DateTime ToDateTime() { return new DateTime(year, month, day, hour, minute, second); } public void FromDateTime(DateTime dt) { year = dt.Year; month = dt.Month; day = dt.Day; hour = dt.Hour; minute = dt.Minute; second = dt.Second; SetDateTimeStr(); } public void Reset() { year = 0; month = 0; day = 0; hour = 0; minute = 0; second = 0; DateTimeStr = "-"; } public DateTimeStruct DeepCopy() { return (DateTimeStruct)MemberwiseClone(); } } public class DeviceValueData : IResettable, IDeepCopy { public byte[] fw_ver; public ushort[] CellVoltage; public short[] CellTemperature; public short voltage; public short current; public short cha_current; public short dch_current; public short averageCurrent; public short SOC; public short SOH; public short NumOfCells; public short NumOfTemps; public ushort MaxCellVoltage; // mV public ushort MinCellVoltage; // mV public ushort DiffCellVoltage; // mV public short MosTemperature; public short AmbTemperature; public short MaxTemperature; // 1C public short MinTemperature; // 0.1C public int RecMaxBattChgCurrLmt; public short remainingCapacity; public UInt32 cycleCount; public UInt32 cycleCount_MSB; public UInt32 cycleCount_LSB; public UInt32 fullChgCapacity_mAs; public UInt32 fullChgCapacity_mAs_MSB; public UInt32 fullChgCapacity_mAs_LSB; public UInt32 fullChgCapacity_Ah; public UInt32 TotalBatCapacity_Ah; public int designedCapacity; public UInt32 EstBackupTime; // Minute - Back-up time based on %SoC level and load at // site(In case of Charging Default load at 0.2C) public UInt32 MdCumulativeChgTime; // Hours - Cumulative charge duration public UInt32 MdCumulativeChgTimeMSB; public UInt32 MdCumulativeChgTimeLSB; public UInt32 MdCumulativeDchTime; // Hours - Cumulative discharge duration public UInt32 MdCumulativeDchTimeMSB; public UInt32 MdCumulativeDchTimeLSB; public ushort ChgCrate; public ushort DchCrate; public ushort MdACIR; public ushort RemainEnergyLife; // Remaining capacity in battery pack in life cycle // (13440 - actual cumulative discharge KWH) public ushort RemainCycles; // Remaining cycle in battery pack in life time // (3500 - actual cycle consumed) public ushort ChgCutOffVolt; public ushort DchCutOffVolt; public ushort BatPowerOnDateYear; // YY public ushort BatPowerOnDateMonth; // MM public int TimeLeft; public UInt32 Ah_Charged; public UInt32 Ah_ChargedMSB; public UInt32 Ah_ChargedLSB; public UInt32 Ah_Discharged; public UInt32 Ah_DischargedMSB; public UInt32 Ah_DischargedLSB; public UInt32 Wh_Charged; public UInt32 Wh_ChargedMSB; public UInt32 Wh_ChargedLSB; public UInt32 Wh_Discharged; public UInt32 Wh_DischargedMSB; public UInt32 Wh_DischargedLSB; public int NoOfDischargeCycles; public int NoOfChargeCycles; public int ModuleAlarms; public int ModuleWarnings; public int ModuleStatus; public int ModuleVoltage_int; public int ModBusDocVersion; public int ParametersChanged; public int MaxBattChgCurr; public int MaxBattDchCurr; public int ShortCircuitCurrent; public int ProtectChgCurr; public int ProtectDchCurr; public int BatteryProdDateYear; public int BatteryProdDateMonth; public int BatteryProdDateDay; public int BatteryModelDescription; public int BatteryType; public DeviceValueData() { fw_ver = new byte[6]; CellVoltage = new ushort[csConstData.SystemInfo.MAX_MODULE_CELL_SIZE + 1]; CellTemperature = new short[csConstData.SystemInfo.MAX_MODULE_TEMP_SIZE]; } /// /// 현재 보유한 버퍼 크기를 유지하면서 모든 값을 0으로 초기화 /// public void Reset() { // 배열/버퍼는 전부 0으로 fw_ver.AsSpan().Clear(); CellVoltage.AsSpan().Clear(); CellTemperature.AsSpan().Clear(); // 스칼라 필드 전부 0/기본값 voltage = 0; current = cha_current = dch_current = averageCurrent = 0; SOC = SOH = 0; NumOfCells = 0; NumOfTemps = 0; MaxCellVoltage = MinCellVoltage = DiffCellVoltage = 0; MosTemperature = AmbTemperature = 0; MaxTemperature = MinTemperature = 0; RecMaxBattChgCurrLmt = 0; remainingCapacity = 0; cycleCount = cycleCount_MSB = cycleCount_LSB = 0; fullChgCapacity_mAs = fullChgCapacity_mAs_MSB = fullChgCapacity_mAs_LSB = 0; fullChgCapacity_Ah = TotalBatCapacity_Ah = 0; designedCapacity = 0; EstBackupTime = 0; MdCumulativeChgTime = MdCumulativeChgTimeMSB = MdCumulativeChgTimeLSB = 0; MdCumulativeDchTime = MdCumulativeDchTimeMSB = MdCumulativeDchTimeLSB = 0; ChgCrate = DchCrate = MdACIR = 0; RemainEnergyLife = RemainCycles = 0; ChgCutOffVolt = DchCutOffVolt = 0; BatPowerOnDateYear = BatPowerOnDateMonth = 0; TimeLeft = 0; Ah_Charged = Ah_ChargedMSB = Ah_ChargedLSB = 0; Ah_Discharged = Ah_DischargedMSB = Ah_DischargedLSB = 0; Wh_Charged = Wh_ChargedMSB = Wh_ChargedLSB = 0; Wh_Discharged = Wh_DischargedMSB = Wh_DischargedLSB = 0; NoOfDischargeCycles = NoOfChargeCycles = 0; ModuleAlarms = ModuleWarnings = ModuleStatus = 0; ModuleVoltage_int = ModBusDocVersion = 0; ParametersChanged = 0; MaxBattChgCurr = MaxBattDchCurr = ShortCircuitCurrent = 0; ProtectChgCurr = ProtectDchCurr = 0; BatteryProdDateYear = BatteryProdDateMonth = BatteryProdDateDay = 0; BatteryModelDescription = 0; BatteryType = 0; } public DeviceValueData DeepCopy() { var copy = (DeviceValueData)MemberwiseClone(); // 스칼라 복사 copy.fw_ver = (byte[])fw_ver.Clone(); copy.CellVoltage = (ushort[])CellVoltage.Clone(); copy.CellTemperature = (short[])CellTemperature.Clone(); return copy; } } public class DeviceAvgData : IResettable, IDeepCopy { public short maxCellVoltage; public short minCellVoltage; public short avgCellVoltage; public short diffCellVoltage; public short maxCellNum; public short minCellNum; public short maxTemp; public short minTemp; public short avgTemp; public short diffTemp; public short maxTempNum; public short minTempNum; public DeviceAvgData() { } public void Reset() { maxCellVoltage = 0; minCellVoltage = 0; avgCellVoltage = 0; diffCellVoltage = 0; maxCellNum = 0; minCellNum = 0; maxTemp = 0; minTemp = 0; avgTemp = 0; diffTemp = 0; maxTempNum = 0; minTempNum = 0; } public DeviceAvgData DeepCopy() { return (DeviceAvgData)MemberwiseClone(); } } public class DeviceStatusData : IResettable, IDeepCopy { public ushort batteryStatus; public ushort batteryStatus1; public ushort warning; public ushort protect; public ushort protection1; public ushort status; public ushort faultAndStatus; public ushort relayStatus; public ushort errorCode; public ushort specialAlarm; // 1: Commfail, 2. Gyro, 3, Breaker public ushort faultstatus; // Only for RS-485 public ushort cellBallanceStatus; public ushort cellBalanceValue; public ushort cellBalanceFlag; public DeviceStatusData() { } public void Reset() { batteryStatus = 0; batteryStatus1 = 0; warning = 0; protect = 0; protection1 = 0; status = 0; faultAndStatus = 0; relayStatus = 0; errorCode = 0; specialAlarm = 0; faultstatus = 0; cellBallanceStatus = 0; cellBalanceValue = 0; cellBalanceFlag = 0; } public DeviceStatusData DeepCopy() { return (DeviceStatusData)MemberwiseClone(); } } public class DeviceParamData : IResettable, IDeepCopy { public short CellOverVoltageTrip; public short CellOverVoltageWarning; public short CellOverVoltageRelease; public short CellUnderVoltageTrip; public short CellUnderVoltageWarning; public short CellUnderVoltageRelease; public short SysOverVoltageTrip; public short SysOverVoltageWarning; public short SysOverVoltageRelease; public short SysUnderVoltageTrip; public short SysUnderVoltageWarning; public short SysUnderVoltageRelease; public short ChaHighTempTrip; public short ChaHighTempWarning; public short ChaHighTempRelease; public short ChaLowTempTrip; public short ChaLowTempWarning; public short ChaLowTempRelease; public short DchHighTempTrip; public short DchHighTempWarning; public short DchHighTempRelease; public short DchLowTempTrip; public short DchLowTempWarning; public short DchLowTempRelease; public short ChaOverCurrentTrip1; public short ChaOverCurrentTrip2; public short ChaOverCurrentWarning; public short ChaOverCurrentReleaseTime; public short ChaOverCurrentTimes; public short ChaOverCurrentDelay1; public short ChaOverCurrentDelay2; public short DchOverCurrentTrip1; public short DchOverCurrentTrip2; public short DchOverCurrentWarning; public short DchOverCurrentReleaseTime; public short DchOverCurrentTimes; public short DchOverCurrentDelay1; public short DchOverCurrentDelay2; public short MosHighTempTrip; public short MosHighTempWarning; public short MosHighTempRelease; public short PcbHighTempTrip; public short PcbHighTempWarning; public short PcbHighTempRelease; public short EnvHighTempTrip; public short EnvHighTempWarning; public short EnvHighTempRelease; public short EnvLowTempTrip; public short EnvLowTempWarning; public short EnvLowTempRelease; public short ShortCircuit; public short LowSocTrip; public short LowSocWarning; public short LowSocRelease; public short CellVoltageDifferenceTrip; public short CellVoltageDifferenceWarning; public short CellVoltageDifferenceRelease; public short CellVoltageDifferenceTime; public short DefalutParamOption; public short DefalutParamAll; public ushort ReadParamAll; /// /// 모든 필드를 0(또는 기본값)으로 초기화합니다. /// public void Reset() { CellOverVoltageTrip = CellOverVoltageWarning = CellOverVoltageRelease = 0; CellUnderVoltageTrip = CellUnderVoltageWarning = CellUnderVoltageRelease = 0; SysOverVoltageTrip = SysOverVoltageWarning = SysOverVoltageRelease = 0; SysUnderVoltageTrip = SysUnderVoltageWarning = SysUnderVoltageRelease = 0; ChaHighTempTrip = ChaHighTempWarning = ChaHighTempRelease = 0; ChaLowTempTrip = ChaLowTempWarning = ChaLowTempRelease = 0; DchHighTempTrip = DchHighTempWarning = DchHighTempRelease = 0; DchLowTempTrip = DchLowTempWarning = DchLowTempRelease = 0; ChaOverCurrentTrip1 = ChaOverCurrentTrip2 = ChaOverCurrentWarning = 0; ChaOverCurrentReleaseTime = 0; ChaOverCurrentTimes = 0; ChaOverCurrentDelay1 = ChaOverCurrentDelay2 = 0; DchOverCurrentTrip1 = DchOverCurrentTrip2 = DchOverCurrentWarning = 0; DchOverCurrentReleaseTime = 0; DchOverCurrentTimes = 0; DchOverCurrentDelay1 = DchOverCurrentDelay2 = 0; MosHighTempTrip = MosHighTempWarning = MosHighTempRelease = 0; PcbHighTempTrip = PcbHighTempWarning = PcbHighTempRelease = 0; ShortCircuit = 0; LowSocTrip = LowSocWarning = LowSocRelease = 0; CellVoltageDifferenceTrip = CellVoltageDifferenceWarning = 0; CellVoltageDifferenceRelease = CellVoltageDifferenceTime = 0; DefalutParamOption = 0; DefalutParamAll = 0; ReadParamAll = 0; } public DeviceParamData DeepCopy() { return (DeviceParamData)MemberwiseClone(); } } public class DeviceCalibration : IResettable, IDeepCopy { public BatteryParameter Battery; public CurrentCalib Current; public CapCalibration CapCalib; public FetCalibration FetCalib; public ChargeMode ChaMode; public TAntiTheft AntiTheft; public TBmsDateTime BmsDateTime; public TAntiTheftComm AntiTheftComm; public TAntiTheftGyro AntiTheftGyro; public DeviceCalibration() { Battery = new BatteryParameter(); Current = new CurrentCalib(); CapCalib = new CapCalibration(); FetCalib = new FetCalibration(); ChaMode = new ChargeMode(); AntiTheft = new TAntiTheft(); BmsDateTime = new TBmsDateTime(); AntiTheftComm = new TAntiTheftComm(); AntiTheftGyro = new TAntiTheftGyro(); } /// /// 모든 하위 객체를 기본값으로 리셋합니다. /// - 하위 타입이 IResettable이면 Reset() 호출 /// - 아니면 새 인스턴스로 교체(참조 재바인딩 허용 시) /// public void Reset() { ResetCopyHelpers.ResetOrRecreate(ref Battery); ResetCopyHelpers.ResetOrRecreate(ref Current); ResetCopyHelpers.ResetOrRecreate(ref CapCalib); ResetCopyHelpers.ResetOrRecreate(ref FetCalib); ResetCopyHelpers.ResetOrRecreate(ref ChaMode); ResetCopyHelpers.ResetOrRecreate(ref AntiTheft); ResetCopyHelpers.ResetOrRecreate(ref BmsDateTime); ResetCopyHelpers.ResetOrRecreate(ref AntiTheftComm); ResetCopyHelpers.ResetOrRecreate(ref AntiTheftGyro); } /// /// 깊은 복사. 가능한 경우 하위 객체의 DeepCopy() 사용, 없으면 새 인스턴스 생성(얕은 복사 회피). /// public DeviceCalibration DeepCopy() { return new DeviceCalibration { Battery = ResetCopyHelpers.DeepCopyOrNew(Battery), Current = ResetCopyHelpers.DeepCopyOrNew(Current), // 기존 코드에선 CapCalib/AntiTheft/ChaMode만 깊은 복사를 하고 // 나머지는 얕은 복사를 했습니다. 전부 통일합니다. CapCalib = ResetCopyHelpers.DeepCopyOrNew(CapCalib), FetCalib = ResetCopyHelpers.DeepCopyOrNew(FetCalib), ChaMode = ResetCopyHelpers.DeepCopyOrNew(ChaMode), AntiTheft = ResetCopyHelpers.DeepCopyOrNew(AntiTheft), BmsDateTime = ResetCopyHelpers.DeepCopyOrNew(BmsDateTime), AntiTheftComm = ResetCopyHelpers.DeepCopyOrNew(AntiTheftComm), AntiTheftGyro = ResetCopyHelpers.DeepCopyOrNew(AntiTheftGyro), }; } public class BatteryParameter { public short CellQty; public short TempQty; public UInt32 Capacity; public BatteryParameter() { CellQty = 0; TempQty = 0; Capacity = 0; } } public class CurrentCalib { public short ChargeOption; public CurrentCalib() { ChargeOption = 0; } } public class CapCalibration : IResettable, IDeepCopy { public int DesignCapacity; public int SocValue; public int CycleCount; public CapCalibration() { DesignCapacity = 0; SocValue = 0; CycleCount = 0; } public void Reset() { DesignCapacity = 0; SocValue = 0; CycleCount = 0; } public CapCalibration DeepCopy() { return (CapCalibration)MemberwiseClone(); } } public class FetCalibration { public short FetStatus; public short DchFetOff; // 6010 public short ChaFetOff; // 6011 public short LmtChaFetOff; // 6012 public short PreChaFetOn; // 6013 public short HeaterFetOn; // 6014 public short ChaFetOn; // 6015 public FetCalibration() { FetStatus = 0; DchFetOff = 0; ChaFetOff = 0; LmtChaFetOff = 0; PreChaFetOn = 0; HeaterFetOn = 0; ChaFetOn = 0; } } public class ChargeMode : IResettable, IDeepCopy { public int Mode; public int Value; public ChargeMode() { Mode = 0; Value = 0; } public void Reset() { Mode = 0; Value = 0; } public ChargeMode DeepCopy() { return (ChargeMode)MemberwiseClone(); } } public class TAntiTheft : IResettable, IDeepCopy { public int Comm; public int GyroScope; public TAntiTheft() { Comm = 0; GyroScope = 0; } public void Reset() { Comm = 0; GyroScope = 0; } public TAntiTheft DeepCopy() { return (TAntiTheft)MemberwiseClone(); } } public class TBmsDateTime : IResettable, IDeepCopy { public string Str; public int lValue; public short[] sValue; public TBmsDateTime() { Str = ""; lValue = 0; sValue = new short[2]; } public void Reset() { Str = ""; lValue = 0; sValue[0] = 0; sValue[1] = 0; } public TBmsDateTime DeepCopy() { var copy = (TBmsDateTime)MemberwiseClone(); copy.sValue = (short[])sValue.Clone(); return copy; } } public class TAntiTheftComm : IResettable, IDeepCopy { public int TimeOut; public int FuncSwitch; public int Unlock; public TAntiTheftComm() { TimeOut = 0; FuncSwitch = 0; Unlock = 0; } public void Reset() { TimeOut = 0; FuncSwitch = 0; Unlock = 0; } public TAntiTheftComm DeepCopy() { return (TAntiTheftComm)MemberwiseClone(); } } public class TAntiTheftGyro : IResettable, IDeepCopy { public int XAxis; public int YAxis; public int ZAxis; public int GyroPolicySel; public int GyroFuncSwitch; public int GyroState; public int Unlock; public TAntiTheftGyro() { XAxis = 0; YAxis = 0; ZAxis = 0; GyroPolicySel = 0; GyroFuncSwitch = 0; GyroState = 0; Unlock = 0; } public void Reset() { XAxis = 0; YAxis = 0; ZAxis = 0; GyroPolicySel = 0; GyroFuncSwitch = 0; GyroState = 0; Unlock = 0; } public TAntiTheftGyro DeepCopy() { return (TAntiTheftGyro)MemberwiseClone(); } } } public class DeviceInforation : IResettable, IDeepCopy { public UInt32 ManufactureDate; public byte[] Model_Byte; public byte[] FwVer_Byte; public string Model_Str; public string FwVer_Str; public byte[] BMS_SN; public string BMS_SN_Str; public byte[] Module_SN; public byte[] ManufactureName; public string ManufactureName_Str; public byte[] ManuDate_Byte; public string VendorName; public string ProductCode; public string MajorMinorRev; public string ModelName; public string HwSerialNumber; public string HwProductRev; public string ManufacturingDate; public string SwProductRev; public DeviceInforation() { Model_Byte = new byte[24]; FwVer_Byte = new byte[6]; Model_Str = " "; FwVer_Str = " "; BMS_SN = new byte[32]; BMS_SN_Str = " "; Module_SN = new byte[32]; ManufactureName_Str = " "; ManufactureName = new byte[10]; ManuDate_Byte = new byte[16]; VendorName = "-"; ProductCode = "-"; MajorMinorRev = "-"; ModelName = "-"; HwSerialNumber = "-"; HwProductRev = "-"; ManufacturingDate = "-"; SwProductRev = "-"; } public void Reset() { ManufactureDate = 0; Array.Clear(Model_Byte, 0, Model_Byte.Length); Array.Clear(FwVer_Byte, 0, FwVer_Byte.Length); Model_Str = " "; FwVer_Str = " "; Array.Clear(BMS_SN, 0, BMS_SN.Length); BMS_SN_Str = " "; Array.Clear(Module_SN, 0, Module_SN.Length); Array.Clear(ManufactureName, 0, ManufactureName.Length); ManufactureName_Str = " "; Array.Clear(ManuDate_Byte, 0, ManuDate_Byte.Length); VendorName = "-"; ProductCode = "-"; MajorMinorRev = "-"; ModelName = "-"; HwSerialNumber = "-"; HwProductRev = "-"; ManufacturingDate = "-"; SwProductRev = "-"; } public DeviceInforation DeepCopy() { var copy = (DeviceInforation)MemberwiseClone(); copy.Model_Byte = (byte[])Model_Byte.Clone(); copy.Model_Byte = (byte[])FwVer_Byte.Clone(); copy.Model_Byte = (byte[])BMS_SN.Clone(); copy.Model_Byte = (byte[])Module_SN.Clone(); copy.Model_Byte = (byte[])ManufactureName.Clone(); copy.Model_Byte = (byte[])ManuDate_Byte.Clone(); return copy; } } public class DeviceEtcStatus : IResettable { public short SwitchHW; public short SwitchWarning; public short SwitchProtect; public ushort LogDurationIdle; // min public ushort LogDurationActive; // min public UInt32 DataAndTime; public ushort ChgOCPModel; /* 充电限流 0:不限流保护 1:始终限流充电 2:预充保护 4:充电过流后限流 8:预充+充电过流后限流 */ public short ChgLmtVoltage; // mv public short SOC_StopFloat; // % 暂停浮充Soc public short SOC_RecvFloat; // % 恢复浮充电压 public short DurationFloat; // sec public short DurationIdle; // sec public short VoltageStopFloat; // 0.1V public short VoltageRecvFloat; // 0.1V public short FloatMode; /* 0000: 持续浮充 0001:检测电压 0002:定时浮充 0003:检测SOC */ public short BalanceVoltage; // mV 均衡启动电压 public short BalanceDeltaV; // mV 均衡启动压差 public short WarnLowCapacity; // 低容量告警 public short HistroyDelete; // 删除数据记录 public DeviceEtcStatus() { } public void Reset() { SwitchHW = 0; SwitchWarning = 0; SwitchProtect = 0; LogDurationIdle = 0; LogDurationActive = 0; DataAndTime = 0; ChgOCPModel = 0; ChgLmtVoltage = 0; SOC_StopFloat = 0; SOC_RecvFloat = 0; DurationFloat = 0; DurationIdle = 0; VoltageStopFloat = 0; VoltageRecvFloat = 0; FloatMode = 0; BalanceVoltage = 0; BalanceDeltaV = 0; WarnLowCapacity = 0; HistroyDelete = 0; } } public class DeviceMaxValue : IResettable { public short MaxChgCurrent; public short MaxChgTemperature; public short MinChgTemperature; public short FloatChgVolt; public short BoostChgVolt; public DeviceMaxValue() { } public void Reset() { MaxChgCurrent = 0; MaxChgTemperature = 0; MinChgTemperature = 0; FloatChgVolt = 0; BoostChgVolt = 0; } } public class DeviceGyroValue : IResettable { public short X_axis; public short Y_axis; public short Z_axis; public short Gyro_policy_sel; public short Gyro_func_sw; public short Gyro_state; public DeviceGyroValue() { } public void Reset() { X_axis = 0; Y_axis = 0; Z_axis = 0; Gyro_policy_sel = 0; Gyro_func_sw = 0; Gyro_state = 0; } } } #endregion } public interface IResettable { void Reset(); } public interface IDeepCopy { T DeepCopy(); } public static class ResetCopyHelpers { // IResettable이면 Reset 호출, 아니면 new() public static void ResetOrRecreate(ref T obj) where T : class, new() { if (obj is IResettable r) r.Reset(); else obj = new T(); } // IDeepCopy 우선, ICloneable 차선, 없으면 new() public static T DeepCopyOrNew(T obj) where T : class, new() { if (obj is IDeepCopy dc) return dc.DeepCopy(); if (obj is ICloneable cl) return (T)cl.Clone(); return new T(); } } }