Update StatusApi & Units

This commit is contained in:
ig 2023-04-04 10:23:29 +02:00
parent 904d05c0de
commit a6252895bb
26 changed files with 205 additions and 281 deletions

View File

@ -1,14 +1,13 @@
using InnovEnergy.Lib.StatusApi.Connections; using InnovEnergy.Lib.StatusApi.Connections;
using InnovEnergy.Lib.StatusApi.Generator;
using InnovEnergy.Lib.Units; using InnovEnergy.Lib.Units;
using InnovEnergy.Lib.Units.Composite; using InnovEnergy.Lib.Units.Composite;
namespace InnovEnergy.Lib.StatusApi; namespace InnovEnergy.Lib.StatusApi;
using T = BatteryStatus;
[OpParallel] #pragma warning disable CS8618
public partial record BatteryStatus : DeviceStatus, IDcConnection
public record BatteryStatus : IDcConnection
{ {
public DcBus Dc { get; init; } public DcBus Dc { get; init; }
public Percent Soc { get; init; } public Percent Soc { get; init; }

View File

@ -1,16 +0,0 @@
#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source.
using System.CodeDom.Compiler;
using InnovEnergy.Lib.Units.Composite;
using InnovEnergy.Lib.Utils;
namespace InnovEnergy.Lib.StatusApi;
using T = BatteryStatus;
[GeneratedCode("generate.sh", "1")]
public partial record BatteryStatus
{
private static readonly Func<T, T, T> OpParallel = "|".CreateBinaryOpForProps<T>();
public static T operator |(T left, T right) => OpParallel(left, right);
}

View File

@ -1,10 +1,10 @@
using InnovEnergy.Lib.StatusApi.Generator;
using InnovEnergy.Lib.Units.Composite; using InnovEnergy.Lib.Units.Composite;
namespace InnovEnergy.Lib.StatusApi; namespace InnovEnergy.Lib.StatusApi;
[OpParallel] #pragma warning disable CS8618
public partial record DcDcConverterStatus : DeviceStatus
public record DcDcConverterStatus
{ {
public DcBus Left { get; init; } public DcBus Left { get; init; }
public DcBus Right { get; init; } public DcBus Right { get; init; }

View File

@ -1,16 +0,0 @@
#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source.
using System.CodeDom.Compiler;
using InnovEnergy.Lib.Units.Composite;
using InnovEnergy.Lib.Utils;
namespace InnovEnergy.Lib.StatusApi;
using T = DcDcConverterStatus;
[GeneratedCode("generate.sh", "1")]
public partial record DcDcConverterStatus
{
private static readonly Func<T, T, T> OpParallel = "|".CreateBinaryOpForProps<T>();
public static T operator |(T left, T right) => OpParallel(left, right);
}

View File

@ -1,52 +0,0 @@
using InnovEnergy.Lib.Utils;
namespace InnovEnergy.Lib.StatusApi;
public abstract record DeviceStatus
{
public String DeviceType => GetType()
.Unfold(t => t.BaseType)
.First(t => t.IsAbstract)
.Name
.Replace("Status", "");
}
// public static class Program
// {
// public static void Main(string[] args)
// {
// var x = new ThreePhasePvInverterStatus
// {
// Ac = new()
// {
// Frequency = 50,
// L1 = new()
// {
// Current = 10,
// Voltage = 10,
// Phi = 0,
// },
// L2 = new()
// {
// Current = 52,
// Voltage = 220,
// Phi = Angle.Pi / 2,
// },
// L3 = new()
// {
// Current = 158,
// Voltage = 454,
// Phi = Angle.Pi / 3,
// },
// },
// Strings = new DcBus[]
// {
// new() { Current = 10, Voltage = 22 },
// new() { Current = 12, Voltage = 33 },
// }
// };
//
// var s = x.ToJson();
// }
// }

View File

@ -1,5 +0,0 @@
namespace InnovEnergy.Lib.StatusApi.Generator;
[AttributeUsage(AttributeTargets.Class)]
internal class OpParallelAttribute : Attribute
{}

View File

@ -1,16 +0,0 @@
#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source.
using System.CodeDom.Compiler;
using InnovEnergy.Lib.Units.Composite;
using InnovEnergy.Lib.Utils;
namespace InnovEnergy.Lib.StatusApi;
using T = Template;
[GeneratedCode("generate.sh", "1")]
public partial record Template
{
private static readonly Func<T, T, T> OpParallel = "|".CreateBinaryOpForProps<T>();
public static T operator |(T left, T right) => OpParallel(left, right);
}

View File

@ -1,13 +0,0 @@
#!/usr/bin/env bash
scriptDir=$( dirname -- "$0"; )
cd "$scriptDir/.." || exit
for path in $(grep -e '\[OpParallel\]' -l *.cs)
do
file=$(basename -- "$path")
class="${file%.*}"
echo "generating $file"
sed "s/Template/$class/g" "./Generator/Template.txt" > "./$class.generated.cs"
done

View File

@ -1,11 +1,11 @@
using InnovEnergy.Lib.StatusApi.Connections; using InnovEnergy.Lib.StatusApi.Connections;
using InnovEnergy.Lib.StatusApi.Generator;
using InnovEnergy.Lib.Units.Composite; using InnovEnergy.Lib.Units.Composite;
namespace InnovEnergy.Lib.StatusApi; namespace InnovEnergy.Lib.StatusApi;
[OpParallel] #pragma warning disable CS8618
public partial record MpptStatus : IDcConnection, IPvConnection
public record MpptStatus : IDcConnection, IPvConnection
{ {
public DcBus Dc { get; init; } public DcBus Dc { get; init; }
public IReadOnlyList<DcBus> Strings { get; init; } public IReadOnlyList<DcBus> Strings { get; init; }

View File

@ -1,16 +0,0 @@
#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source.
using System.CodeDom.Compiler;
using InnovEnergy.Lib.Units.Composite;
using InnovEnergy.Lib.Utils;
namespace InnovEnergy.Lib.StatusApi;
using T = MpptStatus;
[GeneratedCode("generate.sh", "1")]
public partial record MpptStatus
{
private static readonly Func<T, T, T> OpParallel = "|".CreateBinaryOpForProps<T>();
public static T operator |(T left, T right) => OpParallel(left, right);
}

View File

@ -1,11 +1,11 @@
using InnovEnergy.Lib.StatusApi.Connections; using InnovEnergy.Lib.StatusApi.Connections;
using InnovEnergy.Lib.StatusApi.Generator;
using InnovEnergy.Lib.Units.Composite; using InnovEnergy.Lib.Units.Composite;
namespace InnovEnergy.Lib.StatusApi; namespace InnovEnergy.Lib.StatusApi;
[OpParallel] #pragma warning disable CS8618
public partial record PowerMeterStatus : DeviceStatus, IAc3Connection
public record PowerMeterStatus : IAc3Connection
{ {
public Ac3Bus Ac { get; init; } public Ac3Bus Ac { get; init; }
} }

View File

@ -1,16 +0,0 @@
#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source.
using System.CodeDom.Compiler;
using InnovEnergy.Lib.Units.Composite;
using InnovEnergy.Lib.Utils;
namespace InnovEnergy.Lib.StatusApi;
using T = PowerMeterStatus;
[GeneratedCode("generate.sh", "1")]
public partial record PowerMeterStatus
{
private static readonly Func<T, T, T> OpParallel = "|".CreateBinaryOpForProps<T>();
public static T operator |(T left, T right) => OpParallel(left, right);
}

View File

@ -1,14 +1,12 @@
using InnovEnergy.Lib.StatusApi.Connections; using InnovEnergy.Lib.StatusApi.Connections;
using InnovEnergy.Lib.StatusApi.Generator;
using InnovEnergy.Lib.Units.Composite; using InnovEnergy.Lib.Units.Composite;
namespace InnovEnergy.Lib.StatusApi; namespace InnovEnergy.Lib.StatusApi;
[OpParallel]
public partial record SinglePhaseInverterStatus : #pragma warning disable CS8618
DeviceStatus,
IAc1Connection, public record SinglePhaseInverterStatus : IAc1Connection, IDcConnection
IDcConnection
{ {
public Ac1Bus Ac { get; init; } public Ac1Bus Ac { get; init; }
public DcBus Dc { get; init; } public DcBus Dc { get; init; }

View File

@ -1,16 +0,0 @@
#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source.
using System.CodeDom.Compiler;
using InnovEnergy.Lib.Units.Composite;
using InnovEnergy.Lib.Utils;
namespace InnovEnergy.Lib.StatusApi;
using T = SinglePhaseInverterStatus;
[GeneratedCode("generate.sh", "1")]
public partial record SinglePhaseInverterStatus
{
private static readonly Func<T, T, T> OpParallel = "|".CreateBinaryOpForProps<T>();
public static T operator |(T left, T right) => OpParallel(left, right);
}

View File

@ -1,14 +1,11 @@
using InnovEnergy.Lib.StatusApi.Connections; using InnovEnergy.Lib.StatusApi.Connections;
using InnovEnergy.Lib.StatusApi.Generator;
using InnovEnergy.Lib.Units.Composite; using InnovEnergy.Lib.Units.Composite;
namespace InnovEnergy.Lib.StatusApi; namespace InnovEnergy.Lib.StatusApi;
[OpParallel] #pragma warning disable CS8618
public partial record SinglePhasePvInverterStatus :
DeviceStatus, public record SinglePhasePvInverterStatus : IAc1Connection, IPvConnection
IAc1Connection,
IPvConnection
{ {
public Ac1Bus Ac { get; init; } public Ac1Bus Ac { get; init; }
public IReadOnlyList<DcBus> Strings { get; init; } public IReadOnlyList<DcBus> Strings { get; init; }

View File

@ -1,16 +0,0 @@
#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source.
using System.CodeDom.Compiler;
using InnovEnergy.Lib.Units.Composite;
using InnovEnergy.Lib.Utils;
namespace InnovEnergy.Lib.StatusApi;
using T = SinglePhasePvInverterStatus;
[GeneratedCode("generate.sh", "1")]
public partial record SinglePhasePvInverterStatus
{
private static readonly Func<T, T, T> OpParallel = "|".CreateBinaryOpForProps<T>();
public static T operator |(T left, T right) => OpParallel(left, right);
}

View File

@ -7,6 +7,22 @@
<ProjectReference Include="../Units/Units.csproj" /> <ProjectReference Include="../Units/Units.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Compile Remove="SinglePhasePvInverterStatus.generated.cs" />
<Compile Remove="PowerMeterStatus.generated.cs" />
<Compile Remove="BatteryStatus.generated.cs" />
<Compile Remove="SinglePhaseInverterStatus.generated.cs" />
<Compile Remove="Generator\OpParallelAttribute.cs" />
<Compile Remove="ThreePhaseInverterStatus.generated.cs" />
<Compile Remove="ThreePhasePvInverterStatus.generated.cs" />
<Compile Remove="MpptStatus.generated.cs" />
<Compile Remove="DcDcConverterStatus.generated.cs" />
</ItemGroup>
<ItemGroup>
<None Remove="Generator\generate.sh" />
</ItemGroup>
<Target Name="PreBuild" BeforeTargets="PreBuildEvent"> <Target Name="PreBuild" BeforeTargets="PreBuildEvent">
<Exec Command="./Generator/generate.sh" /> <Exec Command="./Generator/generate.sh" />
</Target> </Target>

View File

@ -1,14 +1,11 @@
using InnovEnergy.Lib.StatusApi.Connections; using InnovEnergy.Lib.StatusApi.Connections;
using InnovEnergy.Lib.StatusApi.Generator;
using InnovEnergy.Lib.Units.Composite; using InnovEnergy.Lib.Units.Composite;
namespace InnovEnergy.Lib.StatusApi; namespace InnovEnergy.Lib.StatusApi;
[OpParallel] #pragma warning disable CS8618
public partial record ThreePhaseInverterStatus :
DeviceStatus, public record ThreePhaseInverterStatus : IAc3Connection, IDcConnection
IAc3Connection,
IDcConnection
{ {
public Ac3Bus Ac { get; init; } public Ac3Bus Ac { get; init; }
public DcBus Dc { get; init; } public DcBus Dc { get; init; }

View File

@ -1,16 +0,0 @@
#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source.
using System.CodeDom.Compiler;
using InnovEnergy.Lib.Units.Composite;
using InnovEnergy.Lib.Utils;
namespace InnovEnergy.Lib.StatusApi;
using T = ThreePhaseInverterStatus;
[GeneratedCode("generate.sh", "1")]
public partial record ThreePhaseInverterStatus
{
private static readonly Func<T, T, T> OpParallel = "|".CreateBinaryOpForProps<T>();
public static T operator |(T left, T right) => OpParallel(left, right);
}

View File

@ -1,14 +1,11 @@
using InnovEnergy.Lib.StatusApi.Connections; using InnovEnergy.Lib.StatusApi.Connections;
using InnovEnergy.Lib.StatusApi.Generator;
using InnovEnergy.Lib.Units.Composite; using InnovEnergy.Lib.Units.Composite;
namespace InnovEnergy.Lib.StatusApi; namespace InnovEnergy.Lib.StatusApi;
[OpParallel] #pragma warning disable CS8618
public partial record ThreePhasePvInverterStatus :
DeviceStatus, public record ThreePhasePvInverterStatus : IAc3Connection, IPvConnection
IAc3Connection,
IPvConnection
{ {
public Ac3Bus Ac { get; init; } public Ac3Bus Ac { get; init; }
public IReadOnlyList<DcBus> Strings { get; init; } public IReadOnlyList<DcBus> Strings { get; init; }

View File

@ -1,16 +0,0 @@
#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source.
using System.CodeDom.Compiler;
using InnovEnergy.Lib.Units.Composite;
using InnovEnergy.Lib.Utils;
namespace InnovEnergy.Lib.StatusApi;
using T = ThreePhasePvInverterStatus;
[GeneratedCode("generate.sh", "1")]
public partial record ThreePhasePvInverterStatus
{
private static readonly Func<T, T, T> OpParallel = "|".CreateBinaryOpForProps<T>();
public static T operator |(T left, T right) => OpParallel(left, right);
}

View File

@ -1,20 +1,19 @@
using InnovEnergy.Lib.Utils;
using static DecimalMath.DecimalEx; using static DecimalMath.DecimalEx;
namespace InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.Units.Composite;
#pragma warning disable CS8618
public record Ac3Bus public record Ac3Bus
{ {
public AcPhase L1 { get; init; } public AcPhase L1 { get; init; }
public AcPhase L2 { get; init; } public AcPhase L2 { get; init; }
public AcPhase L3 { get; init; } public AcPhase L3 { get; init; }
public Frequency Frequency { get; init; } public Frequency Frequency { get; init; }
public ApparentPower ApparentPower => L1.ApparentPower + L2.ApparentPower + L3.ApparentPower; public ApparentPower ApparentPower => L1.ApparentPower + L2.ApparentPower + L3.ApparentPower;
public ReactivePower ReactivePower => L1.ReactivePower + L2.ReactivePower + L3.ReactivePower; public ReactivePower ReactivePower => L1.ReactivePower + L2.ReactivePower + L3.ReactivePower;
public Power ActivePower => L1.ActivePower + L2.ActivePower + L3.ActivePower; public Power ActivePower => L1.ActivePower + L2.ActivePower + L3.ActivePower;
public Angle Phi => ATan2(ReactivePower, ActivePower); public Angle Phi => ATan2(ReactivePower, ActivePower);
public static Ac3Bus operator |(Ac3Bus left, Ac3Bus right) => OpParallel(left, right);
private static readonly Func<Ac3Bus, Ac3Bus, Ac3Bus> OpParallel = "|".CreateBinaryOpForProps<Ac3Bus>();
} }

View File

@ -19,7 +19,7 @@ public record AcPhase : IBus
init => _Current = value >= 0m ? value : throw new ArgumentException("RMS value cannot be negative"); init => _Current = value >= 0m ? value : throw new ArgumentException("RMS value cannot be negative");
} }
public Angle Phi { get; init; } public Angle Phi { get; init; }
public ApparentPower ApparentPower => Voltage.Value * Current.Value ; public ApparentPower ApparentPower => Voltage.Value * Current.Value ;
public Power ActivePower => ApparentPower.Value * PowerFactor; public Power ActivePower => ApparentPower.Value * PowerFactor;

View File

@ -1,5 +1,3 @@
using InnovEnergy.Lib.Utils;
namespace InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.Units.Composite;
public record DcBus : IBus public record DcBus : IBus
@ -8,7 +6,4 @@ public record DcBus : IBus
public Current Current { get; init; } public Current Current { get; init; }
public Power Power => Current * Voltage; public Power Power => Current * Voltage;
public static DcBus operator |(DcBus left, DcBus right) => OpParallel(left, right);
private static readonly Func<DcBus, DcBus, DcBus> OpParallel = "|".CreateBinaryOpForProps<DcBus>();
} }

View File

@ -0,0 +1,71 @@
#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source.
#define Generate
using static System.Math;
using System.Text.Json;
using System.Text.Json.Serialization;
using InnovEnergy.Lib.Utils;
using System.CodeDom.Compiler;
namespace InnovEnergy.Lib.Units;
using T = Percent;
[GeneratedCode("generate.sh", "1")]
[JsonConverter(typeof(PercentConverter))]
public readonly partial struct Percent
{
public Decimal Value { get; }
public override String ToString() => Value.RoundToSignificantDigits(Units.DisplaySignificantDigits) + Unit;
// scalar multiplication
public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value);
public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value);
public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar);
// addition
public static T operator +(T left, T right) => new T(left.Value + right.Value);
public static T operator -(T left, T right) => new T(left.Value - right.Value);
public static T operator -(T t) => new T(-t.Value);
// compare
public static Boolean operator ==(T left, T right) => left.Value == right.Value;
public static Boolean operator !=(T left, T right) => left.Value != right.Value;
public static Boolean operator > (T left, T right) => left.Value > right.Value;
public static Boolean operator < (T left, T right) => left.Value < right.Value;
public static Boolean operator >=(T left, T right) => left.Value >= right.Value;
public static Boolean operator <=(T left, T right) => left.Value <= right.Value;
// conversion
public static implicit operator T(Decimal d) => new T(d);
public static implicit operator T(Double d) => new T((Decimal)d);
public static implicit operator T(Int32 i) => new T(i);
public static implicit operator Decimal(T t) => t.Value;
// equality
public Boolean Equals(T other) => Value == other.Value;
public override Boolean Equals(Object? obj) => obj is T other && Equals(other);
public override Int32 GetHashCode() => Value.GetHashCode();
}
internal class PercentConverter : JsonConverter<Percent>
{
public override Percent Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return new Percent(reader.GetDecimal());
}
public override void Write(Utf8JsonWriter writer, Percent value, JsonSerializerOptions options)
{
var rounded = value.Value.RoundToSignificantDigits(Units.JsonSignificantDigits);
writer.WriteNumberValue(rounded);
}
}

View File

@ -1,23 +1,7 @@
using System.Text.Json.Serialization;
namespace InnovEnergy.Lib.Units; namespace InnovEnergy.Lib.Units;
public static class Units public static class Units
{ {
static Units()
{
JsonConverters = typeof(Units)
.Assembly
.GetTypes()
.Where(t => t.IsAssignableTo(typeof(JsonConverter)))
.Select(Activator.CreateInstance)
.Cast<JsonConverter>()
.ToArray();
}
public static IReadOnlyList<JsonConverter> JsonConverters { get; }
public static Byte DisplaySignificantDigits { get; set; } = 3; public static Byte DisplaySignificantDigits { get; set; } = 3;
public static Byte JsonSignificantDigits { get; set; } = 3; public static Byte JsonSignificantDigits { get; set; } = 3;
@ -32,3 +16,88 @@ public static class Units
public static Temperature Celsius(this Decimal value) => value; public static Temperature Celsius(this Decimal value) => value;
public static Energy KWh (this Decimal value) => value; public static Energy KWh (this Decimal value) => value;
} }
public static class Prefixes
{
private static readonly IReadOnlyList<String> Big = new[]
{
"",
"k",
"M",
"G",
"T",
"P",
"E",
"Y",
};
private static readonly IReadOnlyList<String> Small = new[]
{
"",
"m",
"µ",
"n",
"p",
"f",
"a",
"z",
"y",
};
public static String TestGetPrefix(Double v, String unit)
{
if (v == 0)
return "";
var log10 = Math.Log10(v / 10);
var l = (Int32)Math.Floor(log10 / 3);
var lookUp = l > 0 ? Big : Small;
var i = Math.Abs(l);
return $"{v / Math.Pow(10.0, l * 3.0)} {lookUp[i]}{unit}";
}
public static String TestGetPrefix(Decimal v, String unit)
{
if (v == 0m)
return "";
var d = (Double)v;
var log10 = Math.Log10(d / 10);
var l = (Int32)Math.Floor(log10 / 3);
var lookUp = l > 0 ? Big : Small;
var i = Math.Abs(l);
return $"{d / Math.Pow(10.0, l * 3.0)} {lookUp[i]}{unit}";
}
public static String TestGetPrefix2(Decimal v, String unit)
{
if (v == 0m)
return "";
var a = Math.Abs(v);
var s = Math.Sign(v);
var i = 0;
while (a >= 10000m)
{
a /= 1000;
i++;
}
while (a < 10m)
{
a *= 1000;
i--;
}
var lookUp = i >= 0 ? Big : Small;
var r = Decimal.Floor(a * 10m) / 10m;
return $"{r*s} {lookUp[Math.Abs(i)]}{unit}";
}
}