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.Units.Composite; using InnovEnergy.Lib.Utils; using static InnovEnergy.Lib.Devices.Trumpf.TruConvertDc.DcControlRegisters; namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertDc; [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public class TruConvertDcDevice { private ModbusTcpClient ModbusTcpClient { get; } public TruConvertDcDevice(String hostname, UInt16 port = ModbusTcpClient.DefaultPort, Byte slaveAddress = 0) { var connection = new ModbusTcpConnection(hostname, port); ModbusTcpClient = new ModbusTcpClient(connection, slaveAddress); } public void WriteControl(TruConvertDcControl c) { /* TODO: maybe later ModbusTcpClient.WriteRegisters(Date, new[] { dcControl.Date.ConvertTo() }); ModbusTcpClient.WriteRegisters(Time, new[] { dcControl.Time.ConvertTo() }); ModbusTcpClient.WriteRegisters(IpAddress, dcControl.IpAddress.ConvertTo()); ModbusTcpClient.WriteRegisters(Subnet, dcControl.Subnet.ConvertTo()); ModbusTcpClient.WriteRegisters(Gateway, dcControl.Gateway.ConvertTo()); ModbusTcpClient.WriteMultipleCoils(ResetParamToDefault, dcControl.ResetParamToDefault); ModbusTcpClient.WriteMultipleCoils(RestartFlag, dcControl.RestartFlag); ModbusTcpClient.WriteRegisters(DcControlRegisters.TimeoutCommunication, dcControl.TimeoutForCommunication.TotalSeconds.ConvertTo()); ModbusTcpClient.WriteRegisters(ConnectedSystemConfig, dcControl.ConnectedSystemConfig.ConvertTo()); ModbusTcpClient.WriteRegisters(UpdateSwTrigger, dcControl.UpdateSwTrigger, dcControl.AutomaticSwUpdate, dcControl.CustomerValuesSaveReset); ModbusTcpClient.WriteRegisters(SerialNumberSystemControl, dcControl.SerialNumberSystemControl.ConvertTo()); ModbusTcpClient.WriteRegisters(SerialNumberDcDc, dcControl.SerialNumberDcDc.ConvertTo()); ModbusTcpClient.WriteRegisters(MaterialNumberDcDc, dcControl.MaterialNumberDcDc.ConvertTo()); */ // TODO starting from 4000, evaluate what/if needs updating below 4000 WriteRegs(TimeoutCommunication, c.TimeoutForCommunication.TotalSeconds.ConvertTo()); WriteCoils(PowerStageOperation, c.PowerStageEnable); WriteCoils(ResetsAlarmAndWarning, c.ResetsAlarmAndWarning); WriteRegs (SlaveAddress, c.SlaveAddress, c.SlaveAlarmPolicy); WriteRegs (SubSlaveAddress, c.SubSlaveAddress); WriteCoils(ModbusSlaveId, c.ModbusSlaveId); WriteRegs(MaximumBatteryVoltage, 0.01m, c.MaximumBatteryVoltage, c.MinimumBatteryVoltage); WriteRegs(MaximumBatteryChargingCurrent, 0.1m, c.MaximumBatteryChargingCurrent); WriteRegs(MaximumBatteryDischargingCurrent, 0.1m, c.MaximumBatteryDischargingCurrent); WriteRegs(MaximalPowerAtDc, 1.0m, c.MaximalPowerAtDc); WriteRegs(MaximumVoltageAlarmThreshold, 0.1m, c.MaximumVoltageAlarmThreshold); WriteRegs(MinimumVoltageAlarmThreshold, 0.1m, c.MinimumVoltageAlarmThreshold); WriteRegs(BatteryCurrentSet, 1.0m, c.BatteryCurrentSet); WriteRegs(DynamicCurrentPerMillisecond, 0.01m, c.DynamicCurrentPerMillisecond); WriteRegs(DcLinkControlMode, 1.0m, c.DcLinkControlMode); WriteRegs(ReferenceVoltage, 0.1m, c.ReferenceVoltage, c.UpperVoltageWindow, c.LowerVoltageWindow, c.VoltageDeadBand); } private void WriteRegs (UInt16 a, Decimal res = 1.0m, params Decimal[] regs) => ModbusTcpClient.WriteRegisters(a, regs.ToUInt16(res)); 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 TruConvertDcStatus? ReadStatus() { try { return TryReadStatus(); } catch (Exception) { ModbusTcpClient.CloseConnection(); return null; } } private static IEnumerable GetFlags(UInt16 input) { var ls = (DcCurrentLimitState)input; return Enum .GetValues() .Where(f => ls.HasFlag(f)); } private TruConvertDcStatus TryReadStatus() { // Console.WriteLine("Reading DC Device"); var dcPrValMain = ModbusTcpClient.ReadInputRegisters(5001, 3); var dcBatteryValue = ModbusTcpClient.ReadInputRegisters(5101, 1); var dcBatteryValue2 = ModbusTcpClient.ReadInputRegisters(5111, 1); var dcBatteryValue3 = ModbusTcpClient.ReadInputRegisters(5114, 2); var dcBatteryValue4 = ModbusTcpClient.ReadInputRegisters(5121, 1); var dcPrValDcDc = ModbusTcpClient.ReadInputRegisters(5124, 1); var dcPrValDcDc2 = ModbusTcpClient.ReadInputRegisters(5127, 2); var dcTempValue = ModbusTcpClient.ReadInputRegisters(5511, 1); var dcWarningValues = ModbusTcpClient.ReadInputRegisters(2404, 20); var dcAlarmValues = ModbusTcpClient.ReadInputRegisters(2811, 20); var dcSetValues = ModbusTcpClient.ReadInputRegisters(4001, 1); var warnings = Enumerable .Range(2404, 20) .Select(n => dcWarningValues.GetUInt16((UInt16)n).ConvertTo()) .Where(m => m != WarningMessage.NoWarning) .ToArray(); var alarms = Enumerable .Range(2811, 20) .Select(n => dcAlarmValues.GetUInt16((UInt16)n).ConvertTo()) .Where(m => m != AlarmMessage.NoAlarm) .ToArray(); var dcCurrentLimitState = GetFlags(dcPrValDcDc.GetUInt16(5124)).ToArray(); var dcLinkVoltage = dcPrValDcDc2.GetUInt16(5128); var dcPower = dcBatteryValue4.GetInt16(5121) * 1m; var dcCurrent = dcLinkVoltage != 0m ? dcPower / dcLinkVoltage : 0m; return new TruConvertDcStatus { Left = new DcBus() { Current = dcCurrent, Voltage = dcLinkVoltage }, Right = new DcBus() { Current = dcBatteryValue2.GetInt16(5111), Voltage =dcBatteryValue.GetUInt16(5101) * 0.1m, }, MainState = (MainState)dcPrValMain.GetInt16(5001), NumberOfConnectedSlaves = dcPrValMain.GetUInt16(5002), NumberOfConnectedSubSlaves = dcPrValMain.GetUInt16(5003), TotalDcPower = dcBatteryValue3.GetInt32(5114) * 1m, // Resolution is 0.001 (kW) in Tru convert DC doc, but we want it in W StatusOfCurrentLimiting = dcCurrentLimitState, OverloadCapacity = dcPrValDcDc2.GetUInt16(5127) * 0.1m, DcDcInletTemperature = dcTempValue.GetInt16(5511), Warnings = warnings, Alarms = alarms, PowerOperation = dcSetValues.GetBoolean(4001), }; } }