namespace InnovEnergy.App.SaliMax.Controller; public static class Control { public static Decimal ControlGridPower(this StatusRecord status, Decimal targetPower) { return ControlPower(status.GridMeterStatus!.Ac.ActivePower, targetPower, status.SalimaxConfig!.PConstant); } public static Decimal ControlInverterPower(this StatusRecord status, Decimal targetInverterPower) { var s = status.InverterStatus!; var totalInverterAcPower = s.Ac.ActivePower; return ControlPower(totalInverterAcPower, targetInverterPower,status.SalimaxConfig!.PConstant); } public static Decimal ControlBatteryPower(this StatusRecord status, Decimal targetBatteryPower, UInt16 i = 0) //this will use the avg batteries { return ControlPower(status.BatteriesStatus!.Combined.Dc.Power, targetBatteryPower, status.SalimaxConfig!.PConstant); } public static Decimal ControlLowBatterySoc(this StatusRecord status) { return ControlBatteryPower(status, HoldMinSocCurve(status)); } public static Decimal LowerLimit(params Decimal[] deltas) => deltas.Max(); public static Decimal UpperLimit(params Decimal[] deltas) => deltas.Min(); private static Decimal HoldMinSocCurve(StatusRecord s) { // TODO: explain LowSOC curve var a = -2 * s.SalimaxConfig!.SelfDischargePower / s.SalimaxConfig.HoldSocZone; var b = -a * (s.SalimaxConfig.MinSoc + s.SalimaxConfig.HoldSocZone); return s.BatteriesStatus!.Combined.Soc * a + b; //this will use the avg batteries } private static Decimal ControlPower(Decimal measurement, Decimal target, Decimal p) { var error = target - measurement; return error * p; } }