using System.Diagnostics.CodeAnalysis; using InnovEnergy.Lib.Devices.Trumpf.TruConvert; using InnovEnergy.Lib.Protocols.Modbus.Clients; using InnovEnergy.Lib.Protocols.Modbus.Connections; using InnovEnergy.Lib.Utils; using static InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.AcControlRegisters; namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc; using UInt16s = IReadOnlyList; [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public class TruConvertAcDevice { private ModbusTcpClient ModbusTcpClient { get; } public TruConvertAcDevice(String hostname, UInt16 port = ModbusTcpClient.DefaultPort, Byte slaveAddress = 0) { var connection = new ModbusTcpConnection(hostname, port); ModbusTcpClient = new ModbusTcpClient(connection, slaveAddress); } public void WriteControl(TruConvertAcControl c) { /* WriteRegs(AcControlRegisters.Date, new List { c.Date.ConvertTo()}); WriteRegs(AcControlRegisters.Time, new List { c.Time.ConvertTo()}); WriteRegs(AcControlRegisters.IpAddress, new List { c.IpAddress.ConvertTo()}); WriteRegs(AcControlRegisters.Subnet, new List { c.Subnet.ConvertTo()}); WriteRegs(AcControlRegisters.Gateway, new List { c.Gateway.ConvertTo()}); WriteCoils(AcControlRegisters.ResetParamToDefault, c.ResetParamToDefault); WriteCoils(AcControlRegisters.FactoryResetParameters, c.FactoryResetParameters); ModbusTcpClient.WriteRegisters(AcControlRegisters.UpdateSwTrigger, c.UpdateSwTrigger, c.AutomaticSwUpdate, c.CustomerValuesSaveReset); */ WriteRegs(CommunicationTimeout, c.CommunicationTimeout.TotalSeconds.ConvertTo()); WriteRegs(ConnectedSystemConfig, c.ConnectedSystemConfig); WriteCoils(PowerStageConfig, c.PowerStageEnable, c.SetValueConfig.ConvertTo(), c.ResetsAlarmAndWarning); WriteRegs(PreChargeDcLinkConfigR, c.PreChargeDcLinkConfig, c.PowerFactorConvention, c.SlaveAddress, c.ErrorHandlingPolicy, c.GridType, c.SubSlaveAddress); WriteCoils(ModbusSlaveId, c.UseModbusSlaveIdForAddressing); WriteRegs(SubSlaveErrorPolicy, c.SubSlaveErrorPolicy); WriteRegs(SignedPowerNominalValue, -1.0m, c.SignedPowerNominalValue);/*, c.SignedPowerSetValueL1, c.SignedPowerSetValueL2, c.SignedPowerSetValueL3, c.PowerSetValue, c.PowerSetValueL1, c.PowerSetValueL2, c.PowerSetValuesL3);*/ WriteRegs(MaximumGridCurrentRmsL1, 0.01m, c.MaximumGridCurrentRmsL1, c.MaximumGridCurrentRmsL2, c.MaximumGridCurrentRmsL3, c.CosPhiSetValueL1, c.CosPhiSetValueL2, c.CosPhiSetValueL3); WriteCoils(PhaseL1IsCapacitive, c.PhaseL1IsCapacitive, c.PhaseL2IsCapacitive, c.PhaseL3IsCapacitive, c.PhasesAreCapacitive); /* WriteRegs(SetPointCosPhi, 0.01m, c.SetPointCosPhi.ConvertTo(), c.SetPointSinPhi.ConvertTo(), c.SetPointSinPhiL1.ConvertTo(), c.SetPointSinPhiL2.ConvertTo(), c.SetPointSinPhiL3.ConvertTo(), c.FrequencyOffsetIm);*/ WriteRegs(VoltageAdjustmentFactorIm, c.VoltageAdjustmentFactorIm); WriteRegs(PreChargeDcLinkVoltage, c.PreChargeDcLinkVoltage); WriteRegs(MaxPeakCurrentVoltageControlL1, 0.01m, c.MaxPeakCurrentVoltageControlL1, c.MaxPeakCurrentVoltageControlL2, c.MaxPeakCurrentVoltageControlL3); WriteRegs(GridFormingMode, c.GridFormingMode, c.DcLinkRefVoltage, c.DcLinkMinVoltage, c.DcLinkMaxVoltage, c.DcVoltageRefUs, c.DcMinVoltageUs, c.DcMaxVoltageUs); WriteRegs(AcDcGcBypassMode, c.AcDcGcBypassMode); WriteRegs(AcDcGcPMaxThresholdPercent, 0.01m, c.AcDcGcPMaxThresholdPercent); WriteRegs(AcDcGcStartupRampEnable, c.AcDcGcStartupRampEnable); WriteRegs(DcConfigModule, c.DcConfigModule); WriteRegs(DcDcPowerDistribution, 0.1m, c.DcDcPowerDistribution); WriteRegs(AcControlRegisters.AcDcDistributionMode, c.AcDcDistributionMode); } private void WriteRegs (UInt16 a, Decimal res = 1.0m, params Decimal[] regs) => ModbusTcpClient.WriteRegisters(a, regs.ToUInt16(res)); private void WriteRegs (UInt16 a, params IConvertible[] regs) => ModbusTcpClient.WriteRegisters(a, regs.Select(v => v.ConvertTo()).ToArray()); private void WriteRegs (UInt16 a, params UInt16[] regs) => ModbusTcpClient.WriteRegisters(a, regs); private void WriteCoils(UInt16 a, params Boolean[] coils) => ModbusTcpClient.WriteMultipleCoils(a, coils); public TruConvertAcStatus? ReadStatus() { try { return TryReadStatus(); } catch (Exception e) { ModbusTcpClient.CloseConnection(); Console.WriteLine("Failed to read inverter status"); e.Message.WriteLine(); return null; } } private TruConvertAcStatus TryReadStatus() { // Console.WriteLine("Reading Ac Device"); var acActualMain = ModbusTcpClient.ReadInputRegisters(5001, 3); var acActualAcDc = ModbusTcpClient.ReadInputRegisters(5021, 9); var acActualAcDc2 = ModbusTcpClient.ReadInputRegisters(5031, 1); var acActualAcDc3 = ModbusTcpClient.ReadInputRegisters(5131, 6); var acActualMeasurement = ModbusTcpClient.ReadInputRegisters(5141, 3); var acActualMeasurement1 = ModbusTcpClient.ReadInputRegisters(5151, 3); var acActualMeasurement2 = ModbusTcpClient.ReadInputRegisters(5161, 3); var acActualMeasurement3 = ModbusTcpClient.ReadInputRegisters(5171, 3); var acActualMeasurement4 = ModbusTcpClient.ReadInputRegisters(5187, 2); var acActualMeasurement5 = ModbusTcpClient.ReadInputRegisters(5189, 2); var acActualMeasurement6 = ModbusTcpClient.ReadInputRegisters(5191, 2); var acActualMeasurement7 = ModbusTcpClient.ReadInputRegisters(5201, 1); var acActualMeasurement8 = ModbusTcpClient.ReadInputRegisters(5211, 4); var acActualMeasurement9 = ModbusTcpClient.ReadInputRegisters(5221, 2); var acActualTemp = ModbusTcpClient.ReadInputRegisters(5501, 1); var acWarningValues = ModbusTcpClient.ReadInputRegisters(2402, 22); var acAlarmValues = ModbusTcpClient.ReadInputRegisters(2809, 22); var acSetValues = ModbusTcpClient.ReadInputRegisters(4196, 1); var warnings = Enumerable .Range(2404, 20) .Select(n => acWarningValues.GetUInt16((UInt16)n).ConvertTo()) .ToArray(); var alarms = Enumerable .Range(2811, 20) .Select(n => acAlarmValues.GetUInt16((UInt16)n).ConvertTo()) .Where(m => m != AlarmMessage.NoAlarm) .ToArray(); return new TruConvertAcStatus { // acActualMainValues MainState = acActualMain.GetInt16(5001).ConvertTo(), NumberOfConnectedSlaves = acActualMain.GetUInt16(5002), NumberOfConnectedSubSlaves = acActualMain.GetUInt16(5003), //acActualAcDc AcDcNominalGridFrequency = acActualAcDc.GetUInt16(5021) * 0.1m, AcDcNominalGridVoltage = acActualAcDc.GetUInt16(5022), AcDcActNominalPower = acActualAcDc.GetUInt16(5023), AcDcActiveGridType = acActualAcDc.GetUInt16(5024).ConvertTo(), AcDcPowerLimitingStatusAct = acActualAcDc.GetUInt16(5025), AcDcDcVoltageReference = acActualAcDc.GetUInt16(5026), // DC link reference AcDcDcLinkVoltageMinAct = acActualAcDc.GetUInt16(5027), // DC link min voltage AcDcDcLinkVoltageMaxAct = acActualAcDc.GetUInt16(5028), // DC link max voltage AcDcDcLinkChargedMinVoltage = acActualAcDc.GetUInt16(5029) * 0.01m, //ac Actual AcDc 2 AcDcStmActCustomer = acActualAcDc2.GetUInt16(5031), //need to check ApparentPowerAcL1 = acActualAcDc3.GetUInt16(5131) * 1m, // in VA ApparentPowerAcL2 = acActualAcDc3.GetUInt16(5132) * 1m, // in VA ApparentPowerAcL3 = acActualAcDc3.GetUInt16(5133) * 1m, // in VA AcDcOverloadIntegratorStatusL1 = acActualAcDc3.GetUInt16(5134) * 0.1m, AcDcOverloadIntegratorStatusL2 = acActualAcDc3.GetUInt16(5135) * 0.1m, AcDcOverloadIntegratorStatusL3 = acActualAcDc3.GetUInt16(5136) * 0.1m, //acActualMeasurement PowerAcL1 = acActualMeasurement.GetInt16(5141) * 1m, // in Watt PowerAcL2 = acActualMeasurement.GetInt16(5142) * 1m, // in Watt PowerAcL3 = acActualMeasurement.GetInt16(5143) * 1m, // in Watt //acActualMeasurement1 PhaseCurrentL1 = acActualMeasurement1.GetUInt16(5151) * 0.01m, PhaseCurrentL2 = acActualMeasurement1.GetUInt16(5152) * 0.01m, PhaseCurrentL3 = acActualMeasurement1.GetUInt16(5153) * 0.01m, //acActualMeasurement2 GridVoltageL1 = acActualMeasurement2.GetUInt16(5161) * 0.1m, GridVoltageL2 = acActualMeasurement2.GetUInt16(5162) * 0.1m, GridVoltageL3 = acActualMeasurement2.GetUInt16(5163) * 0.1m, //acActualMeasurement3 CosPhiL1 = acActualMeasurement3.GetInt16(5171) * 0.01m, CosPhiL2 = acActualMeasurement3.GetInt16(5172) * 0.01m, CosPhiL3 = acActualMeasurement3.GetInt16(5173) * 0.01m, //acActualMeasurement4 SumPowerL1 = acActualMeasurement4.GetUInt32(5187) * 1m, // in Watt //acActualMeasurement5 SumPowerL2 = acActualMeasurement5.GetUInt32(5189) * 1m, // in Watt //acActualMeasurement6 SumPowerL3 = acActualMeasurement6.GetUInt32(5191) * 1m, // in Watt //acActualMeasurement9 GridFrequency = acActualMeasurement7.GetInt16(5201) * 0.01m, //acActualMeasurement10 ActualDcLinkVoltageUpperHalf = acActualMeasurement8.GetUInt16(5211), ActualDcLinkVoltageLowerHalf = acActualMeasurement8.GetUInt16(5212), ActualDcLinkVoltageUpperHalfExt = acActualMeasurement8.GetUInt16(5213), ActualDcLinkVoltageLowerHalfExt = acActualMeasurement8.GetUInt16(5214), //acActualMeasurement11 VoltageIntNtoPE = acActualMeasurement9.GetInt16(5221) * 0.1m, VoltageExtNtoPE = acActualMeasurement9.GetInt16(5222) * 0.1m, //acActualTemp InletAirTemperature = acActualTemp.GetInt16(5501) * 0.1m, Warnings = warnings, Alarms = alarms, // acSetValues AcSignedPowerValue = acSetValues.GetInt16(4196) * -1.0m, // this is also used for control }; } }