470 lines
12 KiB
C#
470 lines
12 KiB
C#
using InnovEnergy.App.SaliMax.Ess;
|
|
using InnovEnergy.App.SaliMax.SaliMaxRelays;
|
|
using InnovEnergy.Lib.Devices.Battery48TL;
|
|
using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc;
|
|
using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc;
|
|
using static InnovEnergy.Lib.Devices.Trumpf.SystemControl.DataTypes.GridType;
|
|
|
|
namespace InnovEnergy.App.SaliMax.System;
|
|
|
|
public static class Controller
|
|
{
|
|
private static Int32 GetSystemState(this StatusRecord r)
|
|
{
|
|
var relays = r.Relays;
|
|
|
|
if (relays is null)
|
|
return 101; // Message = "Panic: relay device is not available!",
|
|
|
|
var acDcs = r.AcDc;
|
|
|
|
if (acDcs.NotAvailable())
|
|
return 102;
|
|
|
|
var k4 = acDcs.AllDisabled() ? 0
|
|
: acDcs.AllGridTied() ? 1
|
|
: acDcs.AllIsland() ? 2
|
|
: 4;
|
|
|
|
if (k4 == 4)
|
|
return 103; //Message = "Panic: ACDCs have unequal grid types",
|
|
|
|
var nInverters = r.AcDc.Devices.Count;
|
|
|
|
var k1 = relays.K1GridBusIsConnectedToGrid ? 1 : 0;
|
|
var k2 = relays.K2IslandBusIsConnectedToGridBus ? 1 : 0;
|
|
var k3 = relays.K3InverterIsConnectedToIslandBus.Take(nInverters).Any(c => c) ? 1 : 0;
|
|
|
|
// states as defined in states excel sheet
|
|
return 1
|
|
+ 1*k1
|
|
+ 2*k2
|
|
+ 4*k3
|
|
+ 8*k4;
|
|
}
|
|
|
|
public static Boolean ControlSystemState(this StatusRecord s)
|
|
{
|
|
s.StateMachine.State = s.GetSystemState();
|
|
|
|
return s.StateMachine.State switch
|
|
{
|
|
1 => State1(s),
|
|
2 => State2(s),
|
|
4 => State4(s),
|
|
6 => State6(s),
|
|
9 => State9(s),
|
|
//10 => State10(s),
|
|
12 => State12(s),
|
|
13 => State13(s),
|
|
15 => State15(s),
|
|
16 => State16(s),
|
|
17 => State17(s),
|
|
18 => State18(s),
|
|
21 => State21(s),
|
|
|
|
101 => State101(s),
|
|
102 => State102(s),
|
|
103 => State103(s),
|
|
_ => UnknownState(s)
|
|
};
|
|
|
|
}
|
|
|
|
private static Boolean NotAvailable(this AcDcDevicesRecord acDcs)
|
|
{
|
|
return acDcs.SystemControl == null || acDcs.Devices.Count == 0;
|
|
}
|
|
|
|
private static Boolean NotAvailable(this DcDcDevicesRecord dcDcs)
|
|
{
|
|
return dcDcs.SystemControl == null || dcDcs.Devices.Count == 0;
|
|
}
|
|
|
|
|
|
private static Boolean NotAvailable(this Battery48TlRecords batteries)
|
|
{
|
|
return batteries.Devices.Count <= 0;
|
|
}
|
|
|
|
private static Boolean State1(StatusRecord s)
|
|
{
|
|
s.StateMachine.Message = "Inverters are off. Switching to Island Mode.";
|
|
|
|
s.DcDc.Enable();
|
|
s.AcDc.Enable();
|
|
s.AcDc.EnableIslandMode();
|
|
s.Relays.DisconnectIslandBusFromGrid();
|
|
|
|
return false;
|
|
|
|
// => 17
|
|
}
|
|
|
|
private static Boolean State2(StatusRecord s)
|
|
{
|
|
s.StateMachine.Message = "Inverters are disconnected from Island Bus. Switching to GridTie Mode. C";
|
|
|
|
s.DcDc.Disable();
|
|
s.AcDc.Disable();
|
|
s.AcDc.EnableGridTieMode();
|
|
s.Relays.ConnectIslandBusToGrid();
|
|
|
|
return false;
|
|
|
|
// => 10
|
|
}
|
|
|
|
private static Boolean State4(StatusRecord s)
|
|
{
|
|
s.StateMachine.Message = "Turning on Inverters";
|
|
|
|
s.DcDc.Enable();
|
|
s.AcDc.Enable();
|
|
s.AcDc.EnableGridTieMode();
|
|
s.Relays.ConnectIslandBusToGrid();
|
|
|
|
return false;
|
|
|
|
// => 12
|
|
}
|
|
|
|
|
|
private static Boolean State6(StatusRecord s)
|
|
{
|
|
s.StateMachine.Message = "Inverters are off. Waiting for them to disconnect from Island Bus.";
|
|
|
|
s.DcDc.Disable();
|
|
s.AcDc.Disable();
|
|
s.AcDc.EnableIslandMode();
|
|
s.Relays.DisconnectIslandBusFromGrid();
|
|
|
|
return true;
|
|
|
|
// => 2
|
|
}
|
|
|
|
|
|
private static Boolean State9(StatusRecord s)
|
|
{
|
|
|
|
s.StateMachine.Message = "Inverters have disconnected from Island Bus. Turning them off.";
|
|
|
|
s.DcDc.Disable(); // TODO: leave enabled?
|
|
s.AcDc.Disable();
|
|
s.AcDc.EnableGridTieMode();
|
|
s.Relays.DisconnectIslandBusFromGrid();
|
|
|
|
return true;
|
|
|
|
// => 1
|
|
}
|
|
|
|
|
|
//
|
|
// private static Boolean State10(StatusRecord s)
|
|
// {
|
|
//
|
|
// s.SystemState.Message = "Inverters have disconnected from AcOut. Turning them off.";
|
|
//
|
|
// s.DcDc.Disable(); // TODO: leave enabled?
|
|
// s.AcDc.Disable();
|
|
// s.AcDc.EnableGridTieMode();
|
|
// s.Relays.DisconnectIslandBusFromGrid();
|
|
//
|
|
// return true;
|
|
//
|
|
// // => 12
|
|
// }
|
|
|
|
private static Boolean State12(StatusRecord s)
|
|
{
|
|
s.StateMachine.Message = "Waiting for Inverters to connect to Island Bus";
|
|
|
|
s.DcDc.Enable();
|
|
s.AcDc.Enable();
|
|
s.AcDc.EnableGridTieMode();
|
|
s.Relays.ConnectIslandBusToGrid();
|
|
|
|
return true;
|
|
|
|
// => 16
|
|
}
|
|
|
|
|
|
|
|
private static Boolean State13(StatusRecord s)
|
|
{
|
|
s.StateMachine.Message = "Disconnected from AcIn (K2), awaiting inverters to disconnect from AcOut (K3)";
|
|
|
|
s.DcDc.Enable();
|
|
s.AcDc.Enable();
|
|
s.AcDc.EnableGridTieMode();
|
|
s.Relays.DisconnectIslandBusFromGrid();
|
|
|
|
return true;
|
|
|
|
// => 9
|
|
}
|
|
|
|
private static Boolean State15(StatusRecord s)
|
|
{
|
|
s.StateMachine.Message = "Grid has been lost, disconnecting AcIn from AcOut (K2)";
|
|
|
|
s.DcDc.Enable();
|
|
s.AcDc.Enable();
|
|
s.AcDc.EnableGridTieMode();
|
|
s.Relays.DisconnectIslandBusFromGrid();
|
|
|
|
return true;
|
|
|
|
// => 13
|
|
}
|
|
|
|
private static Boolean State16(StatusRecord s)
|
|
{
|
|
// return new
|
|
// (
|
|
// " Inverter is in grid-tie\n Waiting for K1AcInIsConnectedToGrid to open to leave it",
|
|
// AcPowerStageEnable: true,
|
|
// DcPowerStageEnable: true,
|
|
// GridType.GridTied400V50Hz,
|
|
// HighActivePinState.Closed
|
|
// );
|
|
|
|
s.StateMachine.Message = "ESS";
|
|
|
|
s.DcDc.Enable();
|
|
s.AcDc.Enable();
|
|
s.AcDc.EnableGridTieMode();
|
|
s.Relays.ConnectIslandBusToGrid();
|
|
|
|
return true;
|
|
|
|
// => 15
|
|
}
|
|
|
|
|
|
private static Boolean State17(StatusRecord s)
|
|
{
|
|
s.StateMachine.Message = "Inverters are in Island Mode. Waiting for them to connect to AcIn.";
|
|
|
|
s.DcDc.Enable();
|
|
s.AcDc.Enable();
|
|
s.AcDc.EnableIslandMode();
|
|
s.Relays.DisconnectIslandBusFromGrid();
|
|
|
|
return true;
|
|
|
|
// => 21
|
|
}
|
|
|
|
|
|
|
|
private static Boolean State18(StatusRecord s)
|
|
{
|
|
// return new
|
|
// (
|
|
// " Didn't succeed to go to Island mode and K1AcInIsConnectedToGrid close\n Turning off power stage of inverter\n Moving to Grid Tie",
|
|
// AcPowerStageEnable: false,
|
|
// DcPowerStageEnable: false,
|
|
// GridType.GridTied400V50Hz,
|
|
// HighActivePinState.Open
|
|
// );
|
|
|
|
s.DcDc.Disable();
|
|
s.AcDc.Disable();
|
|
s.AcDc.EnableIslandMode();
|
|
s.Relays.DisconnectIslandBusFromGrid();
|
|
|
|
return true;
|
|
}
|
|
|
|
private static Boolean State21(StatusRecord s)
|
|
{
|
|
s.StateMachine.Message = "Island Mode";
|
|
|
|
s.DcDc.Enable();
|
|
s.AcDc.Enable();
|
|
s.AcDc.EnableIslandMode();
|
|
s.Relays.DisconnectIslandBusFromGrid();
|
|
|
|
return false;
|
|
|
|
// => 22
|
|
}
|
|
|
|
private static Boolean State22(StatusRecord s)
|
|
{
|
|
s.StateMachine.Message = "Grid became available (K1). Turning off inverters.";
|
|
|
|
s.DcDc.Disable();
|
|
s.AcDc.Disable();
|
|
s.AcDc.EnableIslandMode();
|
|
s.Relays.DisconnectIslandBusFromGrid();
|
|
|
|
return false;
|
|
|
|
// => 6
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static Boolean State101(StatusRecord s)
|
|
{
|
|
s.StateMachine.Message = "Relay device is not available";
|
|
return s.EnableSafeDefaults();
|
|
}
|
|
|
|
private static Boolean State102(StatusRecord s)
|
|
{
|
|
s.StateMachine.Message = "ACDCs not available";
|
|
return s.EnableSafeDefaults();
|
|
}
|
|
|
|
|
|
private static Boolean State103(StatusRecord s)
|
|
{
|
|
s.StateMachine.Message = "Panic: ACDCs have unequal grid types";
|
|
return s.EnableSafeDefaults();
|
|
}
|
|
|
|
private static Boolean State104(StatusRecord s)
|
|
{
|
|
s.StateMachine.Message = "Panic: DCDCs not available";
|
|
return s.EnableSafeDefaults();
|
|
}
|
|
|
|
|
|
private static Boolean UnknownState(StatusRecord s)
|
|
{
|
|
// "Unknown System State"
|
|
|
|
return s.EnableSafeDefaults();
|
|
}
|
|
|
|
|
|
|
|
private static Boolean AllDisabled(this AcDcDevicesRecord acDcs)
|
|
{
|
|
return acDcs.Devices.All(d => !d.Control.PowerStageEnable);
|
|
}
|
|
|
|
private static Boolean AllGridTied(this AcDcDevicesRecord acDcs)
|
|
{
|
|
return acDcs.Devices.All(d => d.Status.ActiveGridType is GridTied380V60Hz)
|
|
|| acDcs.Devices.All(d => d.Status.ActiveGridType is GridTied400V50Hz)
|
|
|| acDcs.Devices.All(d => d.Status.ActiveGridType is GridTied480V60Hz);
|
|
}
|
|
|
|
private static Boolean AllIsland(this AcDcDevicesRecord acDcs)
|
|
{
|
|
return acDcs.Devices.All(d => d.Status.ActiveGridType is Island400V50Hz)
|
|
|| acDcs.Devices.All(d => d.Status.ActiveGridType is Island480V60Hz);
|
|
}
|
|
|
|
private static void ForAll<T>(this IEnumerable<T> ts, Action<T> action)
|
|
{
|
|
foreach (var t in ts)
|
|
action(t);
|
|
}
|
|
|
|
private static void Disable(this AcDcDevicesRecord acDc)
|
|
{
|
|
acDc.Devices
|
|
.Select(d => d.Control)
|
|
.ForAll(c => c.PowerStageEnable = false);
|
|
}
|
|
|
|
|
|
private static void Disable(this DcDcDevicesRecord dcDc)
|
|
{
|
|
dcDc.Devices
|
|
.Select(d => d.Control)
|
|
.ForAll(c => c.PowerStageEnable = false);
|
|
}
|
|
|
|
private static void Enable(this AcDcDevicesRecord acDc)
|
|
{
|
|
acDc.Devices
|
|
.Select(d => d.Control)
|
|
.ForAll(c => c.PowerStageEnable = true);
|
|
}
|
|
|
|
|
|
private static void Enable(this DcDcDevicesRecord dcDc)
|
|
{
|
|
dcDc.Devices
|
|
.Select(d => d.Control)
|
|
.ForAll(c => c.PowerStageEnable = true);
|
|
}
|
|
|
|
|
|
|
|
private static void EnableGridTieMode(this AcDcDevicesRecord acDc)
|
|
{
|
|
acDc.Devices
|
|
.Select(d => d.Control)
|
|
.ForAll(c => c.Ac.GridType = GridTied400V50Hz); // TODO: config grid type
|
|
}
|
|
|
|
|
|
private static void EnableIslandMode(this AcDcDevicesRecord acDc)
|
|
{
|
|
acDc.Devices
|
|
.Select(d => d.Control)
|
|
.ForAll(c => c.Ac.GridType = Island400V50Hz); // TODO: config grid type
|
|
}
|
|
|
|
private static void DisconnectIslandBusFromGrid(this RelaysRecord? relays)
|
|
{
|
|
if (relays is not null)
|
|
relays.K2ConnectIslandBusToGridBus = false;
|
|
}
|
|
|
|
private static void ConnectIslandBusToGrid(this RelaysRecord? relays)
|
|
{
|
|
if (relays is not null)
|
|
relays.K2ConnectIslandBusToGridBus = true;
|
|
}
|
|
|
|
|
|
private static Boolean EnableSafeDefaults(this StatusRecord s)
|
|
{
|
|
s.DcDc.Disable();
|
|
s.AcDc.Disable();
|
|
s.AcDc.EnableGridTieMode();
|
|
s.Relays.DisconnectIslandBusFromGrid();
|
|
|
|
return false;
|
|
}
|
|
|
|
private static DcDcDevicesRecord ResetAlarms(this DcDcDevicesRecord dcDcStatus)
|
|
{
|
|
var sc = dcDcStatus.SystemControl;
|
|
|
|
if (sc is not null)
|
|
sc.ResetAlarmsAndWarnings = sc.Alarms.Any();
|
|
|
|
foreach (var d in dcDcStatus.Devices)
|
|
d.Control.ResetAlarmsAndWarnings = d.Status.Alarms.Any() || d.Status.Warnings.Any();
|
|
|
|
return dcDcStatus;
|
|
}
|
|
|
|
private static AcDcDevicesRecord ResetAlarms(this AcDcDevicesRecord acDcStatus)
|
|
{
|
|
var sc = acDcStatus.SystemControl;
|
|
|
|
if (sc is not null)
|
|
sc.ResetAlarmsAndWarnings = sc.Alarms.Any() || sc.Warnings.Any();
|
|
|
|
foreach (var d in acDcStatus.Devices)
|
|
d.Control.ResetAlarmsAndWarnings = d.Status.Alarms.Any() || d.Status.Warnings.Any();
|
|
|
|
return acDcStatus;
|
|
}
|
|
|
|
} |