255 lines
9.7 KiB
C#
255 lines
9.7 KiB
C#
using InnovEnergy.Lib.Devices.Kaco92L3.DataType;
|
|
|
|
namespace InnovEnergy.Lib.Devices.Kaco92L3;
|
|
|
|
public partial class KacoRecord
|
|
{
|
|
|
|
private static float ScaleSunspec(Int16 value, Int16 sf)
|
|
{
|
|
// -32768 is SunSpec "not implemented"
|
|
if (value == -32768)
|
|
return float.NaN;
|
|
|
|
if (sf == 0)
|
|
return value;
|
|
|
|
return (float)(value * Math.Pow(10, sf));
|
|
}
|
|
|
|
private static float ScaleSunspec(UInt16 value, Int16 sf)
|
|
{
|
|
// interpret unsigned as signed when applying SF; range is the same
|
|
return ScaleSunspec(unchecked((Int16)value), sf);
|
|
}
|
|
|
|
private static Int16 UnscaleSunspecToInt16(float value, Int16 sf)
|
|
{
|
|
if (float.IsNaN(value) || float.IsInfinity(value))
|
|
return -32768; // "not implemented" / invalid
|
|
|
|
if (sf == 0)
|
|
return (Int16)Math.Round(value);
|
|
|
|
var raw = value / (float)Math.Pow(10, sf);
|
|
return (Int16)Math.Round(raw);
|
|
}
|
|
|
|
private static UInt16 UnscaleSunspecToUInt16(float value, Int16 sf)
|
|
{
|
|
var raw = UnscaleSunspecToInt16(value, sf);
|
|
return unchecked((UInt16)raw);
|
|
}
|
|
|
|
/****************************** High-level API for Model 64201 ****************************/
|
|
|
|
// ───────────────────────────────────────────────
|
|
// States & control
|
|
// ───────────────────────────────────────────────
|
|
|
|
// Header
|
|
public UInt16 BattCharId => _battCharId; // ID = 64202
|
|
public UInt16 BattCharLength => _battCharLength; // L = 6 + (RBCount * 8)
|
|
|
|
public ReuqestedState RequestedState
|
|
{
|
|
get => (ReuqestedState)_requestedState;
|
|
set => _requestedState = (UInt16)value;
|
|
}
|
|
|
|
public CurrentState CurrentState => (CurrentState)_currentState;
|
|
|
|
public ControlMode ControlMode
|
|
{
|
|
get => (ControlMode)_controlMode;
|
|
set => _controlMode = (UInt16)value;
|
|
}
|
|
|
|
public bool IsGridConnected => CurrentState == CurrentState.GridConnected;
|
|
public bool IsStandby => CurrentState == CurrentState.Standby;
|
|
public bool IsOff => CurrentState == CurrentState.Off;
|
|
|
|
// Watchdog seconds (no scale factor)
|
|
public UInt16 WatchdogSeconds
|
|
{
|
|
get => _watchdog;
|
|
set => _watchdog = value;
|
|
}
|
|
|
|
|
|
// ───────────────────────────────────────────────
|
|
// Setpoints (scaled)
|
|
// ───────────────────────────────────────────────
|
|
|
|
/// <summary>Active power setpoint in percent of WMax [%].</summary>
|
|
public float ActivePowerSetPercent
|
|
{
|
|
get => ScaleSunspec(_wSetPct, _wSetPctSf);
|
|
set => _wSetPct = UnscaleSunspecToInt16(value, _wSetPctSf);
|
|
}
|
|
|
|
/// <summary>Reactive power setpoint in percent of SMax [%].</summary>
|
|
public float ReactivePowerSetPercent
|
|
{
|
|
get => ScaleSunspec(_varWMaxSetPct, _varSetPctSf);
|
|
set => _varWMaxSetPct = UnscaleSunspecToInt16(value, _varSetPctSf);
|
|
}
|
|
|
|
// ───────────────────────────────────────────────
|
|
// Ramp parameters (scaled)
|
|
// ───────────────────────────────────────────────
|
|
|
|
/// <summary>Active power PT1 ramp time [s].</summary>
|
|
public float ActivePowerRampTimeSeconds
|
|
{
|
|
get => ScaleSunspec(_wParamRmpTms, _rmpTmsSf);
|
|
set => _wParamRmpTms = UnscaleSunspecToUInt16(value, _rmpTmsSf);
|
|
}
|
|
|
|
/// <summary>Active power ramp-down rate [% ref / min].</summary>
|
|
public float ActivePowerRampDownPercentPerMin
|
|
{
|
|
get => ScaleSunspec(_wParamRmpDecTmn, _rmpIncDecSf);
|
|
set => _wParamRmpDecTmn = UnscaleSunspecToUInt16(value, _rmpIncDecSf);
|
|
}
|
|
|
|
/// <summary>Active power ramp-up rate [% ref / min].</summary>
|
|
public float ActivePowerRampUpPercentPerMin
|
|
{
|
|
get => ScaleSunspec(_wParamRmpIncTmn, _rmpIncDecSf);
|
|
set => _wParamRmpIncTmn = UnscaleSunspecToUInt16(value, _rmpIncDecSf);
|
|
}
|
|
|
|
/// <summary>Reactive power PT1 ramp time [s].</summary>
|
|
public float ReactivePowerRampTimeSeconds
|
|
{
|
|
get => ScaleSunspec(_varParamRmpTms, _rmpTmsSf);
|
|
set => _varParamRmpTms = UnscaleSunspecToUInt16(value, _rmpTmsSf);
|
|
}
|
|
|
|
/// <summary>Reactive power ramp-down rate [% ref / min].</summary>
|
|
public float ReactivePowerRampDownPercentPerMin
|
|
{
|
|
get => ScaleSunspec(_varParamRmpDecTmn, _rmpIncDecSf);
|
|
set => _varParamRmpDecTmn = UnscaleSunspecToUInt16(value, _rmpIncDecSf);
|
|
}
|
|
|
|
/// <summary>Reactive power ramp-up rate [% ref / min].</summary>
|
|
public float ReactivePowerRampUpPercentPerMin
|
|
{
|
|
get => ScaleSunspec(_varParamRmpIncTmn, _rmpIncDecSf);
|
|
set => _varParamRmpIncTmn = UnscaleSunspecToUInt16(value, _rmpIncDecSf);
|
|
}
|
|
|
|
// Ramp enable flags
|
|
public EnableDisableEnum ActivePowerRampEnable
|
|
{
|
|
get => (EnableDisableEnum)_wParamEna;
|
|
set => _wParamEna = (UInt16)value;
|
|
}
|
|
|
|
public EnableDisableEnum ReactivePowerRampEnable
|
|
{
|
|
get => (EnableDisableEnum)_varParamEna;
|
|
set => _varParamEna = (UInt16)value;
|
|
}
|
|
|
|
// ───────────────────────────────────────────────
|
|
// Status / error (read-only enum views)
|
|
// ───────────────────────────────────────────────
|
|
|
|
//public VendorStateEnum VendorState => (VendorStateEnum)_stVnd;
|
|
//public PuStateEnum PuState => (PuStateEnum)_stPu;
|
|
public StatePcu PcuState => (StatePcu)_stPcu;
|
|
public ErrorPcu PcuError => (ErrorPcu)_errPcu;
|
|
|
|
public UInt16 BatteryCharVersion => _battCharVersion;
|
|
public UInt16 BatteryCharMinorVersion => _battCharVerMinor;
|
|
|
|
/// <summary>
|
|
/// Scale factor for battery voltages (V_SF).
|
|
/// </summary>
|
|
public Int16 BatteryVoltageScaleFactor => _battCharVSf;
|
|
|
|
/// <summary>
|
|
/// Scale factor for battery currents (A_SF).
|
|
/// </summary>
|
|
public Int16 BatteryCurrentScaleFactor => _battCharASf;
|
|
|
|
// Helper wrappers for scaled values
|
|
private float ScaleBattVoltage(UInt16 raw) => ScaleSunspec(raw, _battCharVSf);
|
|
private float ScaleBattCurrent(UInt16 raw) => ScaleSunspec(raw, _battCharASf);
|
|
private UInt16 UnscaleBattVoltage(float value) => UnscaleSunspecToUInt16(value, _battCharVSf);
|
|
private UInt16 UnscaleBattCurrent(float value) => UnscaleSunspecToUInt16(value, _battCharASf);
|
|
|
|
// ───────────────────────────────────────────────
|
|
// Battery discharge limits (scaled, RW)
|
|
// ───────────────────────────────────────────────
|
|
|
|
/// <summary>Minimum discharge voltage [V].</summary>
|
|
public float MinDischargeVoltage
|
|
{
|
|
get => ScaleBattVoltage(_disMinVRaw);
|
|
set => _disMinVRaw = UnscaleBattVoltage(value);
|
|
}
|
|
|
|
/// <summary>Maximum discharge current [A].</summary>
|
|
public float MaxDischargeCurrent
|
|
{
|
|
get => ScaleBattCurrent(_disMaxARaw);
|
|
set => _disMaxARaw = UnscaleBattCurrent(value);
|
|
}
|
|
|
|
/// <summary>Discharge cutoff current [A]. If discharge current falls below this, it disconnects (optional according to sheet).</summary>
|
|
public float DischargeCutoffCurrent
|
|
{
|
|
get => ScaleBattCurrent(_disCutoffARaw);
|
|
set => _disCutoffARaw = UnscaleBattCurrent(value);
|
|
}
|
|
|
|
// ───────────────────────────────────────────────
|
|
// Battery charge limits (scaled, RW)
|
|
// ───────────────────────────────────────────────
|
|
|
|
/// <summary>Maximum charge voltage [V].</summary>
|
|
public float MaxChargeVoltage
|
|
{
|
|
get => ScaleBattVoltage(_chaMaxVRaw);
|
|
set => _chaMaxVRaw = UnscaleBattVoltage(value);
|
|
}
|
|
|
|
/// <summary>Maximum charge current [A].</summary>
|
|
public float MaxChargeCurrent
|
|
{
|
|
get => ScaleBattCurrent(_chaMaxARaw);
|
|
set => _chaMaxARaw = UnscaleBattCurrent(value);
|
|
}
|
|
|
|
/// <summary>Charge cutoff current [A]. If charge current falls below this, it disconnects.</summary>
|
|
public float ChargeCutoffCurrent
|
|
{
|
|
get => ScaleBattCurrent(_chaCutoffARaw);
|
|
set => _chaCutoffARaw = UnscaleBattCurrent(value);
|
|
}
|
|
|
|
// ───────────────────────────────────────────────
|
|
// Limit enable flag
|
|
// ───────────────────────────────────────────────
|
|
|
|
/// <summary>
|
|
/// When EnLimit = 1, new battery limits are activated.
|
|
/// </summary>
|
|
public EnableDisableEnum BatteryLimitsEnable
|
|
{
|
|
get => (EnableDisableEnum)_enLimitRaw;
|
|
set => _enLimitRaw = (UInt16)value;
|
|
}
|
|
|
|
/// <summary>Convenience bool wrapper for EnLimit.</summary>
|
|
public bool BatteryLimitsEnabled
|
|
{
|
|
get => BatteryLimitsEnable == EnableDisableEnum.Enabled;
|
|
set => BatteryLimitsEnable = value ? EnableDisableEnum.Enabled : EnableDisableEnum.Disabled;
|
|
}
|
|
|
|
} |