Add ControlPvPower function.
This commit is contained in:
parent
85b248dc6f
commit
91da191874
|
@ -1,3 +1,6 @@
|
|||
#undef Amax
|
||||
#undef GridLimit
|
||||
|
||||
using System.Reactive.Linq;
|
||||
using System.Reactive.Threading.Tasks;
|
||||
using Flurl.Http;
|
||||
|
@ -21,6 +24,8 @@ using InnovEnergy.Lib.Units;
|
|||
using InnovEnergy.Lib.Utils;
|
||||
using InnovEnergy.App.SaliMax.AggregationService;
|
||||
using InnovEnergy.App.SaliMax.DataTypes;
|
||||
using static InnovEnergy.App.SaliMax.AggregationService.Aggregator;
|
||||
using static InnovEnergy.App.SaliMax.MiddlewareClasses.MiddlewareAgent;
|
||||
using static InnovEnergy.Lib.Devices.Trumpf.SystemControl.DataTypes.SystemConfig;
|
||||
using DeviceState = InnovEnergy.App.SaliMax.Devices.DeviceState;
|
||||
|
||||
|
@ -45,44 +50,51 @@ internal static class Program
|
|||
private static readonly Channel RelaysChannel;
|
||||
private static readonly Channel BatteriesChannel;
|
||||
|
||||
private const String VpnServerIp = "10.2.0.11";
|
||||
private static Boolean _subscribedToQueue = false;
|
||||
private static Boolean _subscribeToQueueForTheFirstTime = false;
|
||||
private static SalimaxAlarmState _prevSalimaxState = SalimaxAlarmState.Green;
|
||||
private static Int32 _heartBitInterval = 0;
|
||||
|
||||
private const String VpnServerIp = "10.2.0.11";
|
||||
private static Boolean _subscribedToQueue = false;
|
||||
private static Boolean _subscribeToQueueForTheFirstTime = false;
|
||||
private static SalimaxAlarmState _prevSalimaxState = SalimaxAlarmState.Green;
|
||||
private static Int32 _heartBitInterval = 0;
|
||||
|
||||
static Program()
|
||||
{
|
||||
var config = Config.Load();
|
||||
var d = config.Devices;
|
||||
|
||||
Channel CreateChannel(SalimaxDevice device) => device.DeviceState == DeviceState.Disabled
|
||||
? new NullChannel()
|
||||
: new TcpChannel(device);
|
||||
Channel CreateChannel(SalimaxDevice device) => device.DeviceState == DeviceState.Disabled
|
||||
? new NullChannel()
|
||||
: new TcpChannel(device);
|
||||
|
||||
TruConvertAcChannel = CreateChannel(d.TruConvertAcIp);
|
||||
TruConvertDcChannel = CreateChannel(d.TruConvertDcIp);
|
||||
GridMeterChannel = CreateChannel(d.GridMeterIp);
|
||||
TruConvertAcChannel = CreateChannel(d.TruConvertAcIp);
|
||||
TruConvertDcChannel = CreateChannel(d.TruConvertDcIp);
|
||||
GridMeterChannel = CreateChannel(d.GridMeterIp);
|
||||
IslandBusLoadChannel = CreateChannel(d.IslandBusLoadMeterIp);
|
||||
PvOnDc = CreateChannel(d.PvOnDc);
|
||||
PvOnAcGrid = CreateChannel(d.PvOnAcGrid);
|
||||
PvOnAcIsland = CreateChannel(d.PvOnAcIsland);
|
||||
RelaysChannel = CreateChannel(d.RelaysIp);
|
||||
BatteriesChannel = CreateChannel(d.BatteryIp);
|
||||
|
||||
BatteryNodes = config
|
||||
.Devices
|
||||
.BatteryNodes
|
||||
.Select(n => n.ConvertTo<Byte>())
|
||||
.ToArray(config.Devices.BatteryNodes.Length);
|
||||
PvOnDc = CreateChannel(d.PvOnDc);
|
||||
PvOnAcGrid = CreateChannel(d.PvOnAcGrid);
|
||||
PvOnAcIsland = CreateChannel(d.PvOnAcIsland);
|
||||
RelaysChannel = CreateChannel(d.RelaysIp);
|
||||
BatteriesChannel = CreateChannel(d.BatteryIp);
|
||||
|
||||
BatteryNodes = config
|
||||
.Devices
|
||||
.BatteryNodes
|
||||
.Select(n => n.ConvertTo<Byte>())
|
||||
.ToArray(config.Devices.BatteryNodes.Length);
|
||||
}
|
||||
|
||||
public static async Task Main(String[] args)
|
||||
{
|
||||
//Do not await
|
||||
Aggregator.HourlyDataAggregationManager().ContinueWith(t => t.Exception.WriteLine(), TaskContinuationOptions.OnlyOnFaulted).SupressAwaitWarning();
|
||||
Aggregator.DailyDataAggregationManager().ContinueWith(t => t.Exception.WriteLine(), TaskContinuationOptions.OnlyOnFaulted).SupressAwaitWarning();
|
||||
MiddlewareAgent.InitializeCommunicationToMiddleware();
|
||||
HourlyDataAggregationManager()
|
||||
.ContinueWith(t=>t.Exception.WriteLine(), TaskContinuationOptions.OnlyOnFaulted)
|
||||
.SupressAwaitWarning();
|
||||
|
||||
DailyDataAggregationManager()
|
||||
.ContinueWith(t=>t.Exception.WriteLine(), TaskContinuationOptions.OnlyOnFaulted)
|
||||
.SupressAwaitWarning();
|
||||
|
||||
InitializeCommunicationToMiddleware();
|
||||
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
|
@ -92,7 +104,7 @@ internal static class Program
|
|||
catch (Exception e)
|
||||
{
|
||||
e.LogError();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,68 +116,68 @@ internal static class Program
|
|||
Watchdog.NotifyReady();
|
||||
|
||||
var battery48TlDevices = BatteryNodes
|
||||
.Select(n => new Battery48TlDevice(BatteriesChannel, n))
|
||||
.ToList();
|
||||
|
||||
var batteryDevices = new Battery48TlDevices(battery48TlDevices);
|
||||
var acDcDevices = new TruConvertAcDcDevices(TruConvertAcChannel);
|
||||
var dcDcDevices = new TruConvertDcDcDevices(TruConvertDcChannel);
|
||||
var gridMeterDevice = new EmuMeterDevice(GridMeterChannel);
|
||||
var acIslandLoadMeter = new EmuMeterDevice(IslandBusLoadChannel);
|
||||
var pvOnDcDevice = new AmptDevices(PvOnDc);
|
||||
var pvOnAcGridDevice = new AmptDevices(PvOnAcGrid);
|
||||
var pvOnAcIslandDevice = new AmptDevices(PvOnAcIsland);
|
||||
.Select(n => new Battery48TlDevice(BatteriesChannel, n))
|
||||
.ToList();
|
||||
|
||||
var batteryDevices = new Battery48TlDevices(battery48TlDevices);
|
||||
var acDcDevices = new TruConvertAcDcDevices(TruConvertAcChannel);
|
||||
var dcDcDevices = new TruConvertDcDcDevices(TruConvertDcChannel);
|
||||
var gridMeterDevice = new EmuMeterDevice(GridMeterChannel);
|
||||
var acIslandLoadMeter = new EmuMeterDevice(IslandBusLoadChannel);
|
||||
var pvOnDcDevice = new AmptDevices(PvOnDc);
|
||||
var pvOnAcGridDevice = new AmptDevices(PvOnAcGrid);
|
||||
var pvOnAcIslandDevice = new AmptDevices(PvOnAcIsland);
|
||||
var saliMaxRelaysDevice = new RelaysDevice(RelaysChannel);
|
||||
|
||||
StatusRecord ReadStatus()
|
||||
{
|
||||
var config = Config.Load();
|
||||
var devices = config.Devices;
|
||||
var acDc = acDcDevices.Read();
|
||||
var dcDc = dcDcDevices.Read();
|
||||
var relays = saliMaxRelaysDevice.Read();
|
||||
var loadOnAcIsland = acIslandLoadMeter.Read();
|
||||
var gridMeter = gridMeterDevice.Read();
|
||||
var pvOnDc = pvOnDcDevice.Read();
|
||||
var battery = batteryDevices.Read();
|
||||
var config = Config.Load();
|
||||
var devices = config.Devices;
|
||||
var acDc = acDcDevices.Read();
|
||||
var dcDc = dcDcDevices.Read();
|
||||
var relays = saliMaxRelaysDevice.Read();
|
||||
var loadOnAcIsland = acIslandLoadMeter.Read();
|
||||
var gridMeter = gridMeterDevice.Read();
|
||||
var pvOnDc = pvOnDcDevice.Read();
|
||||
var battery = batteryDevices.Read();
|
||||
|
||||
var pvOnAcGrid = pvOnAcGridDevice.Read();
|
||||
var pvOnAcIsland = pvOnAcIslandDevice.Read();
|
||||
var pvOnAcGrid = pvOnAcGridDevice.Read();
|
||||
var pvOnAcIsland = pvOnAcIslandDevice.Read();
|
||||
|
||||
var gridBusToIslandBus = Topology.CalculateGridBusToIslandBusPower(pvOnAcIsland, loadOnAcIsland, acDc);
|
||||
|
||||
var gridBusLoad = devices.LoadOnAcGrid.DeviceState == DeviceState.Disabled
|
||||
? new AcPowerDevice { Power = 0 }
|
||||
: Topology.CalculateGridBusLoad(gridMeter, pvOnAcGrid, gridBusToIslandBus);
|
||||
? new AcPowerDevice { Power = 0 }
|
||||
: Topology.CalculateGridBusLoad(gridMeter, pvOnAcGrid, gridBusToIslandBus);
|
||||
|
||||
var dcLoad = devices.LoadOnDc.DeviceState == DeviceState.Disabled
|
||||
? new DcPowerDevice { Power = 0 }
|
||||
: Topology.CalculateDcLoad(acDc, pvOnDc, dcDc);
|
||||
? new DcPowerDevice { Power = 0 }
|
||||
: Topology.CalculateDcLoad(acDc, pvOnDc, dcDc);
|
||||
|
||||
var acDcToDcLink = devices.LoadOnDc.DeviceState == DeviceState.Disabled
|
||||
? Topology.CalculateAcDcToDcLink(pvOnDc, dcDc, acDc)
|
||||
: new DcPowerDevice { Power = acDc.Dc.Power };
|
||||
var acDcToDcLink = devices.LoadOnDc.DeviceState == DeviceState.Disabled ?
|
||||
Topology.CalculateAcDcToDcLink(pvOnDc, dcDc, acDc)
|
||||
: new DcPowerDevice{ Power = acDc.Dc.Power};
|
||||
|
||||
return new StatusRecord
|
||||
{
|
||||
AcDc = acDc,
|
||||
DcDc = dcDc,
|
||||
Battery = battery,
|
||||
Relays = relays,
|
||||
GridMeter = gridMeter,
|
||||
PvOnAcGrid = pvOnAcGrid,
|
||||
PvOnAcIsland = pvOnAcIsland,
|
||||
PvOnDc = pvOnDc,
|
||||
AcDc = acDc,
|
||||
DcDc = dcDc,
|
||||
Battery = battery,
|
||||
Relays = relays,
|
||||
GridMeter = gridMeter,
|
||||
PvOnAcGrid = pvOnAcGrid,
|
||||
PvOnAcIsland = pvOnAcIsland,
|
||||
PvOnDc = pvOnDc,
|
||||
AcGridToAcIsland = gridBusToIslandBus,
|
||||
AcDcToDcLink = acDcToDcLink,
|
||||
LoadOnAcGrid = gridBusLoad,
|
||||
LoadOnAcIsland = loadOnAcIsland,
|
||||
LoadOnDc = dcLoad,
|
||||
AcDcToDcLink = acDcToDcLink,
|
||||
LoadOnAcGrid = gridBusLoad,
|
||||
LoadOnAcIsland = loadOnAcIsland,
|
||||
LoadOnDc = dcLoad,
|
||||
|
||||
StateMachine = StateMachine.Default,
|
||||
EssControl = EssControl.Default,
|
||||
Log = new SystemLog { SalimaxAlarmState = SalimaxAlarmState.Green, Message = null }, //TODO: Put real stuff
|
||||
Config = config // load from disk every iteration, so config can be changed while running
|
||||
StateMachine = StateMachine.Default,
|
||||
EssControl = EssControl.Default,
|
||||
Log = new SystemLog { SalimaxAlarmState = SalimaxAlarmState.Green, Message = null }, //TODO: Put real stuff
|
||||
Config = config // load from disk every iteration, so config can be changed while running
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -183,11 +195,11 @@ internal static class Program
|
|||
while (true)
|
||||
{
|
||||
await Observable
|
||||
.Interval(UpdateInterval)
|
||||
.Select(_ => RunIteration())
|
||||
.SelectMany(r => UploadCsv(r, DateTime.Now.Round(UpdateInterval)))
|
||||
.SelectError()
|
||||
.ToTask();
|
||||
.Interval(UpdateInterval)
|
||||
.Select(_ => RunIteration())
|
||||
.SelectMany(r => UploadCsv(r, DateTime.Now.Round(UpdateInterval)))
|
||||
.SelectError()
|
||||
.ToTask();
|
||||
}
|
||||
|
||||
|
||||
|
@ -221,7 +233,7 @@ internal static class Program
|
|||
record.CreateTopologyTextBlock().WriteLine();
|
||||
|
||||
(record.Relays is null ? "No relay Data available" : record.Relays.FiWarning ? "Alert: Fi Warning Detected" : "No Fi Warning Detected").WriteLine();
|
||||
(record.Relays is null ? "No relay Data available" : record.Relays.FiError ? "Alert: Fi Error Detected" : "No Fi Error Detected").WriteLine();
|
||||
(record.Relays is null ? "No relay Data available" : record.Relays.FiError ? "Alert: Fi Error Detected" : "No Fi Error Detected") .WriteLine();
|
||||
|
||||
//record.ApplyConfigFile(minSoc:22, gridSetPoint:1);
|
||||
|
||||
|
@ -235,7 +247,7 @@ internal static class Program
|
|||
// ReSharper disable once FunctionNeverReturns
|
||||
}
|
||||
|
||||
public static void SendSalimaxStateAlarm(StatusMessage currentSalimaxState, StatusRecord record)
|
||||
private static void SendSalimaxStateAlarm(StatusMessage currentSalimaxState, StatusRecord record)
|
||||
{
|
||||
var s3Bucket = Config.Load().S3?.Bucket;
|
||||
|
||||
|
@ -268,7 +280,7 @@ internal static class Program
|
|||
}
|
||||
|
||||
//If there is an available message from the RabbitMQ Broker, apply the configuration file
|
||||
Configuration? config = MiddlewareAgent.SetConfigurationFile();
|
||||
Configuration? config = SetConfigurationFile();
|
||||
if (config != null)
|
||||
{
|
||||
record.ApplyConfigFile(config);
|
||||
|
@ -278,10 +290,10 @@ internal static class Program
|
|||
private static StatusMessage GetSalimaxStateAlarm(StatusRecord record)
|
||||
{
|
||||
var alarmCondition = record.DetectAlarmStates();
|
||||
var s3Bucket = Config.Load().S3?.Bucket;
|
||||
var s3Bucket = Config.Load().S3?.Bucket;
|
||||
|
||||
var alarmList = new List<AlarmOrWarning>();
|
||||
var warningList = new List<AlarmOrWarning>();
|
||||
var alarmList = new List<AlarmOrWarning>();
|
||||
var warningList = new List<AlarmOrWarning>();
|
||||
|
||||
if (alarmCondition is not null)
|
||||
{
|
||||
|
@ -295,162 +307,180 @@ internal static class Program
|
|||
Description = alarmCondition
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var alarm in record.AcDc.Alarms)
|
||||
{
|
||||
alarmList.Add(new AlarmOrWarning
|
||||
{
|
||||
Date = DateTime.Now.ToString("yyyy-MM-dd"),
|
||||
Time = DateTime.Now.ToString("HH:mm:ss"),
|
||||
CreatedBy = "AcDc",
|
||||
Description = alarm.ToString()
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var alarm in record.DcDc.Alarms)
|
||||
{
|
||||
alarmList.Add(new AlarmOrWarning
|
||||
{
|
||||
Date = DateTime.Now.ToString("yyyy-MM-dd"),
|
||||
Time = DateTime.Now.ToString("HH:mm:ss"),
|
||||
CreatedBy = "DcDc",
|
||||
Description = alarm.ToString()
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var alarm in record.AcDc.Alarms)
|
||||
{
|
||||
alarmList.Add(new AlarmOrWarning
|
||||
{
|
||||
Date = DateTime.Now.ToString("yyyy-MM-dd"),
|
||||
Time = DateTime.Now.ToString("HH:mm:ss"),
|
||||
CreatedBy = "AcDc",
|
||||
Description = alarm.ToString()
|
||||
});
|
||||
}
|
||||
if (record.Battery != null)
|
||||
{
|
||||
var i = 0;
|
||||
|
||||
foreach (var battery in record.Battery.Devices)
|
||||
{
|
||||
foreach (var alarm in battery.Alarms)
|
||||
{
|
||||
alarmList.Add(new AlarmOrWarning
|
||||
{
|
||||
Date = DateTime.Now.ToString("yyyy-MM-dd"),
|
||||
Time = DateTime.Now.ToString("HH:mm:ss"),
|
||||
CreatedBy = "Battery node" + record.Config.Devices.BatteryNodes[i],
|
||||
Description = alarm
|
||||
});
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
foreach (var warning in record.AcDc.Warnings)
|
||||
{
|
||||
warningList.Add(new AlarmOrWarning
|
||||
{
|
||||
Date = DateTime.Now.ToString("yyyy-MM-dd"),
|
||||
Time = DateTime.Now.ToString("HH:mm:ss"),
|
||||
CreatedBy = "AcDc",
|
||||
Description = warning.ToString()
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var warning in record.DcDc.Warnings)
|
||||
{
|
||||
warningList.Add(new AlarmOrWarning
|
||||
{
|
||||
Date = DateTime.Now.ToString("yyyy-MM-dd"),
|
||||
Time = DateTime.Now.ToString("HH:mm:ss"),
|
||||
CreatedBy = "DcDc",
|
||||
Description = warning.ToString()
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var alarm in record.DcDc.Alarms)
|
||||
{
|
||||
alarmList.Add(new AlarmOrWarning
|
||||
{
|
||||
Date = DateTime.Now.ToString("yyyy-MM-dd"),
|
||||
Time = DateTime.Now.ToString("HH:mm:ss"),
|
||||
CreatedBy = "DcDc",
|
||||
Description = alarm.ToString()
|
||||
});
|
||||
}
|
||||
if (record.Battery != null)
|
||||
{
|
||||
foreach (var warning in record.Battery.Warnings)
|
||||
{
|
||||
warningList.Add(new AlarmOrWarning
|
||||
{
|
||||
Date = DateTime.Now.ToString("yyyy-MM-dd"),
|
||||
Time = DateTime.Now.ToString("HH:mm:ss"),
|
||||
CreatedBy = "Battery",
|
||||
Description = warning
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (record.Battery != null)
|
||||
{
|
||||
var i = 0;
|
||||
var salimaxAlarmsState = (record.Battery is not null && record.Battery.Warnings.Any())
|
||||
| record.AcDc.Warnings.Any()
|
||||
| record.AcDc.SystemControl.Warnings.Any()
|
||||
| record.DcDc.Warnings.Any()
|
||||
? SalimaxAlarmState.Orange
|
||||
: SalimaxAlarmState.Green; // this will be replaced by LedState
|
||||
|
||||
foreach (var battery in record.Battery.Devices)
|
||||
{
|
||||
i++;
|
||||
foreach (var alarm in battery.Alarms)
|
||||
{
|
||||
alarmList.Add(new AlarmOrWarning
|
||||
{
|
||||
Date = DateTime.Now.ToString("yyyy-MM-dd"),
|
||||
Time = DateTime.Now.ToString("HH:mm:ss"),
|
||||
CreatedBy = "Battery" + i,
|
||||
Description = alarm
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
salimaxAlarmsState = (record.Battery is not null && record.Battery.Alarms.Any())
|
||||
| record.AcDc.Alarms.Any()
|
||||
| record.AcDc.SystemControl.Alarms.Any()
|
||||
| record.DcDc.Alarms.Any()
|
||||
| alarmCondition is not null
|
||||
? SalimaxAlarmState.Red
|
||||
: salimaxAlarmsState; // this will be replaced by LedState
|
||||
|
||||
foreach (var warning in record.AcDc.Warnings)
|
||||
{
|
||||
warningList.Add(new AlarmOrWarning
|
||||
{
|
||||
Date = DateTime.Now.ToString("yyyy-MM-dd"),
|
||||
Time = DateTime.Now.ToString("HH:mm:ss"),
|
||||
CreatedBy = "AcDc",
|
||||
Description = warning.ToString()
|
||||
});
|
||||
}
|
||||
int.TryParse(s3Bucket?.Split("-")[0], out var installationId);
|
||||
|
||||
foreach (var warning in record.DcDc.Warnings)
|
||||
{
|
||||
warningList.Add(new AlarmOrWarning
|
||||
{
|
||||
Date = DateTime.Now.ToString("yyyy-MM-dd"),
|
||||
Time = DateTime.Now.ToString("HH:mm:ss"),
|
||||
CreatedBy = "DcDc",
|
||||
Description = warning.ToString()
|
||||
});
|
||||
}
|
||||
var returnedStatus = new StatusMessage
|
||||
{
|
||||
InstallationId = installationId,
|
||||
Status = salimaxAlarmsState,
|
||||
Type = MessageType.AlarmOrWarning,
|
||||
Alarms = alarmList,
|
||||
Warnings = warningList
|
||||
};
|
||||
|
||||
if (record.Battery != null)
|
||||
{
|
||||
foreach (var warning in record.Battery.Warnings)
|
||||
{
|
||||
warningList.Add(new AlarmOrWarning
|
||||
{
|
||||
Date = DateTime.Now.ToString("yyyy-MM-dd"),
|
||||
Time = DateTime.Now.ToString("HH:mm:ss"),
|
||||
CreatedBy = "Battery",
|
||||
Description = warning
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var salimaxAlarmsState = (record.Battery is not null && record.Battery.Warnings.Any())
|
||||
| record.AcDc.Warnings.Any()
|
||||
| record.AcDc.SystemControl.Warnings.Any()
|
||||
| record.DcDc.Warnings.Any()
|
||||
? SalimaxAlarmState.Orange
|
||||
: SalimaxAlarmState.Green; // this will be replaced by LedState
|
||||
|
||||
salimaxAlarmsState = (record.Battery is not null && record.Battery.Alarms.Any())
|
||||
| record.AcDc.Alarms.Any()
|
||||
| record.AcDc.SystemControl.Alarms.Any()
|
||||
| record.DcDc.Alarms.Any()
|
||||
| alarmCondition is not null
|
||||
? SalimaxAlarmState.Red
|
||||
: salimaxAlarmsState; // this will be replaced by LedState
|
||||
|
||||
int.TryParse(s3Bucket?.Split("-")[0], out var installationId);
|
||||
|
||||
var returnedStatus = new StatusMessage
|
||||
{
|
||||
InstallationId = installationId,
|
||||
Status = salimaxAlarmsState,
|
||||
Type = MessageType.AlarmOrWarning,
|
||||
Alarms = alarmList,
|
||||
Warnings = warningList
|
||||
};
|
||||
|
||||
return returnedStatus;
|
||||
return returnedStatus;
|
||||
}
|
||||
|
||||
private static String? DetectAlarmStates(this StatusRecord r) => r.Relays switch
|
||||
{
|
||||
{ K2ConnectIslandBusToGridBus: false, K2IslandBusIsConnectedToGridBus: true } => " Contradiction: R0 is opening the K2 but the K2 is still close ",
|
||||
{ K1GridBusIsConnectedToGrid : false, K2IslandBusIsConnectedToGridBus: true } => " Contradiction: K1 is open but the K2 is still close ",
|
||||
{ FiError: true, K2IslandBusIsConnectedToGridBus: true } => " Contradiction: Fi error occured but the K2 is still close ",
|
||||
_ => null
|
||||
{ FiError: true, K2IslandBusIsConnectedToGridBus: true } => " Contradiction: Fi error occured but the K2 is still close ",
|
||||
_ => null
|
||||
};
|
||||
|
||||
private static void ControlConstants(this StatusRecord r)
|
||||
{
|
||||
var inverters = r.AcDc.Devices;
|
||||
var dcDevices = r.DcDc.Devices;
|
||||
var configFile = r.Config;
|
||||
var inverters = r.AcDc.Devices;
|
||||
var dcDevices = r.DcDc.Devices;
|
||||
var configFile = r.Config;
|
||||
|
||||
var devicesConfig = r.AcDc.Devices.All(d => d.Control.Ac.GridType == GridType.GridTied400V50Hz) ? configFile.GridTie : configFile.IslandMode; // TODO if any of the grid tie mode
|
||||
|
||||
inverters.ForEach(d => d.Control.Dc.MaxVoltage = devicesConfig.AcDc.MaxDcLinkVoltage);
|
||||
inverters.ForEach(d => d.Control.Dc.MinVoltage = devicesConfig.AcDc.MinDcLinkVoltage);
|
||||
inverters.ForEach(d => d.Control.Dc.ReferenceVoltage = devicesConfig.AcDc.ReferenceDcLinkVoltage);
|
||||
|
||||
inverters.ForEach(d => d.Control.Dc.PrechargeConfig = DcPrechargeConfig.PrechargeDcWithInternal);
|
||||
|
||||
dcDevices.ForEach(d => d.Control.DroopControl.UpperVoltage = devicesConfig.DcDc.UpperDcLinkVoltage);
|
||||
dcDevices.ForEach(d => d.Control.DroopControl.LowerVoltage = devicesConfig.DcDc.LowerDcLinkVoltage);
|
||||
dcDevices.ForEach(d => d.Control.DroopControl.ReferenceVoltage = devicesConfig.DcDc.ReferenceDcLinkVoltage);
|
||||
|
||||
dcDevices.ForEach(d => d.Control.CurrentControl.MaxBatteryChargingCurrent = configFile.MaxBatteryChargingCurrent);
|
||||
|
||||
inverters.ForEach(d => d.Control.Dc.MaxVoltage = devicesConfig.AcDc.MaxDcLinkVoltage);
|
||||
inverters.ForEach(d => d.Control.Dc.MinVoltage = devicesConfig.AcDc.MinDcLinkVoltage);
|
||||
inverters.ForEach(d => d.Control.Dc.ReferenceVoltage = devicesConfig.AcDc.ReferenceDcLinkVoltage);
|
||||
|
||||
inverters.ForEach(d => d.Control.Dc.PrechargeConfig = DcPrechargeConfig.PrechargeDcWithInternal);
|
||||
|
||||
dcDevices.ForEach(d => d.Control.DroopControl.UpperVoltage = devicesConfig.DcDc.UpperDcLinkVoltage);
|
||||
dcDevices.ForEach(d => d.Control.DroopControl.LowerVoltage = devicesConfig.DcDc.LowerDcLinkVoltage);
|
||||
dcDevices.ForEach(d => d.Control.DroopControl.ReferenceVoltage = devicesConfig.DcDc.ReferenceDcLinkVoltage);
|
||||
|
||||
dcDevices.ForEach(d => d.Control.CurrentControl.MaxBatteryChargingCurrent = configFile.MaxBatteryChargingCurrent);
|
||||
dcDevices.ForEach(d => d.Control.CurrentControl.MaxBatteryDischargingCurrent = configFile.MaxBatteryDischargingCurrent);
|
||||
dcDevices.ForEach(d => d.Control.MaxDcPower = configFile.MaxDcPower);
|
||||
dcDevices.ForEach(d => d.Control.MaxDcPower = configFile.MaxDcPower);
|
||||
|
||||
dcDevices.ForEach(d => d.Control.VoltageLimits.MaxBatteryVoltage = configFile.MaxChargeBatteryVoltage);
|
||||
dcDevices.ForEach(d => d.Control.VoltageLimits.MinBatteryVoltage = configFile.MinDischargeBatteryVoltage);
|
||||
dcDevices.ForEach(d => d.Control.ControlMode = DcControlMode.VoltageDroop);
|
||||
dcDevices.ForEach(d => d.Control.VoltageLimits.MaxBatteryVoltage = configFile.MaxChargeBatteryVoltage);
|
||||
dcDevices.ForEach(d => d.Control.VoltageLimits.MinBatteryVoltage = configFile.MinDischargeBatteryVoltage);
|
||||
dcDevices.ForEach(d => d.Control.ControlMode = DcControlMode.VoltageDroop);
|
||||
|
||||
r.DcDc.ResetAlarms();
|
||||
r.AcDc.ResetAlarms();
|
||||
}
|
||||
|
||||
// This is will be used for
|
||||
private static void ControlPvPower(this StatusRecord r, Int16 exportLimit = 100)
|
||||
{
|
||||
var inverters = r.AcDc.Devices;
|
||||
var dcDevices = r.DcDc.Devices;
|
||||
var configFile = r.Config;
|
||||
|
||||
var devicesConfig = configFile.GridTie;
|
||||
|
||||
inverters.ForEach(d => d.Control.Dc.MaxVoltage = devicesConfig.AcDc.MaxDcLinkVoltage);
|
||||
inverters.ForEach(d => d.Control.Dc.MinVoltage = devicesConfig.AcDc.MinDcLinkVoltage);
|
||||
inverters.ForEach(d => d.Control.Dc.ReferenceVoltage = devicesConfig.AcDc.ReferenceDcLinkVoltage);
|
||||
|
||||
dcDevices.ForEach(d => d.Control.DroopControl.UpperVoltage = devicesConfig.DcDc.UpperDcLinkVoltage);
|
||||
dcDevices.ForEach(d => d.Control.DroopControl.LowerVoltage = devicesConfig.DcDc.LowerDcLinkVoltage);
|
||||
dcDevices.ForEach(d => d.Control.DroopControl.ReferenceVoltage = devicesConfig.DcDc.ReferenceDcLinkVoltage);
|
||||
}
|
||||
|
||||
// why this is not in Controller?
|
||||
private static void DistributePower(StatusRecord record, EssControl essControl)
|
||||
{
|
||||
var nInverters = record.AcDc.Devices.Count;
|
||||
|
||||
|
||||
var powerPerInverterPhase = nInverters > 0
|
||||
? essControl.PowerSetpoint / nInverters / 3
|
||||
: 0;
|
||||
|
||||
? essControl.PowerSetpoint / nInverters / 3
|
||||
: 0;
|
||||
|
||||
record.AcDc.Devices.ForEach(d =>
|
||||
{
|
||||
d.Control.Ac.PhaseControl = PhaseControl.Asymmetric;
|
||||
|
@ -464,71 +494,74 @@ internal static class Program
|
|||
{
|
||||
if (sc is null)
|
||||
return;
|
||||
|
||||
sc.ReferenceFrame = ReferenceFrame.Consumer;
|
||||
sc.SystemConfig = AcDcAndDcDc;
|
||||
|
||||
sc.ReferenceFrame = ReferenceFrame.Consumer;
|
||||
sc.SystemConfig = AcDcAndDcDc;
|
||||
|
||||
#if DEBUG
|
||||
sc.CommunicationTimeout = TimeSpan.FromMinutes(2);
|
||||
#else
|
||||
sc.CommunicationTimeout = TimeSpan.FromSeconds(20);
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
sc.CommunicationTimeout = TimeSpan.FromMinutes(2);
|
||||
#else
|
||||
sc.CommunicationTimeout = TimeSpan.FromSeconds(20);
|
||||
#endif
|
||||
|
||||
sc.PowerSetPointActivation = PowerSetPointActivation.Immediate;
|
||||
sc.UseSlaveIdForAddressing = true;
|
||||
sc.SlaveErrorHandling = SlaveErrorHandling.Relaxed;
|
||||
sc.SubSlaveErrorHandling = SubSlaveErrorHandling.Off;
|
||||
|
||||
sc.ResetAlarmsAndWarnings = true;
|
||||
sc.SlaveErrorHandling = SlaveErrorHandling.Relaxed;
|
||||
sc.SubSlaveErrorHandling = SubSlaveErrorHandling.Off;
|
||||
|
||||
sc.ResetAlarmsAndWarnings = true;
|
||||
}
|
||||
|
||||
|
||||
private static void ApplyDcDcDefaultSettings(this SystemControlRegisters? sc)
|
||||
{
|
||||
|
||||
if (sc is null)
|
||||
return;
|
||||
|
||||
sc.SystemConfig = DcDcOnly;
|
||||
#if DEBUG
|
||||
sc.CommunicationTimeout = TimeSpan.FromMinutes(2);
|
||||
#else
|
||||
sc.CommunicationTimeout = TimeSpan.FromSeconds(20);
|
||||
#endif
|
||||
|
||||
|
||||
sc.SystemConfig = DcDcOnly;
|
||||
#if DEBUG
|
||||
sc.CommunicationTimeout = TimeSpan.FromMinutes(2);
|
||||
#else
|
||||
sc.CommunicationTimeout = TimeSpan.FromSeconds(20);
|
||||
#endif
|
||||
|
||||
sc.PowerSetPointActivation = PowerSetPointActivation.Immediate;
|
||||
sc.UseSlaveIdForAddressing = true;
|
||||
sc.SlaveErrorHandling = SlaveErrorHandling.Relaxed;
|
||||
sc.SubSlaveErrorHandling = SubSlaveErrorHandling.Off;
|
||||
sc.ResetAlarmsAndWarnings = true;
|
||||
sc.SlaveErrorHandling = SlaveErrorHandling.Relaxed;
|
||||
sc.SubSlaveErrorHandling = SubSlaveErrorHandling.Off;
|
||||
|
||||
sc.ResetAlarmsAndWarnings = true;
|
||||
}
|
||||
|
||||
private static async Task<Boolean> UploadCsv(StatusRecord status, DateTime timeStamp)
|
||||
{
|
||||
var s3Config = status.Config.S3;
|
||||
var csv = status.ToCsv().LogInfo();
|
||||
var csv = status.ToCsv().LogInfo();
|
||||
if (s3Config is null)
|
||||
return false;
|
||||
|
||||
var s3Path = timeStamp.ToUnixTime() + ".csv";
|
||||
var request = s3Config.CreatePutRequest(s3Path);
|
||||
var s3Path = timeStamp.ToUnixTime() + ".csv";
|
||||
var request = s3Config.CreatePutRequest(s3Path);
|
||||
var response = await request.PutAsync(new StringContent(csv));
|
||||
|
||||
// This is temporary for Wittman
|
||||
//await File.WriteAllTextAsync("/var/www/html/status.csv", csv.SplitLines().Where(l => !l.Contains("Secret")).JoinLines());
|
||||
|
||||
|
||||
if (response.StatusCode != 200)
|
||||
{
|
||||
Console.WriteLine("ERROR: PUT");
|
||||
var error = await response.GetStringAsync();
|
||||
Console.WriteLine(error);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void ApplyConfigFile(this StatusRecord status, Configuration? config)
|
||||
{
|
||||
status.Config.MinSoc = config.MinimumSoC;
|
||||
status.Config.GridSetPoint = config.GridSetPoint * 1000; // converted from kW to W
|
||||
status.Config.MinSoc = config.MinimumSoC;
|
||||
status.Config.GridSetPoint = config.GridSetPoint * 1000; // converted from kW to W
|
||||
status.Config.ForceCalibrationCharge = config.ForceCalibrationCharge;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue