Merge branch 'main' of https://git.innov.energy/Innovenergy/git_trunk
This commit is contained in:
commit
19978dd211
|
@ -89,19 +89,23 @@ public partial class Db : IDisposable
|
|||
|
||||
public IEnumerable<Installation> GetAllAccessibleInstallations(User user)
|
||||
{
|
||||
var direct = GetDirectlyAccessibleInstallations(user).ToList();
|
||||
var direct = GetDirectlyAccessibleInstallations(user);
|
||||
var fromFolders = GetAllAccessibleFolders(user)
|
||||
.SelectMany(GetChildInstallations)
|
||||
.Except(direct);
|
||||
.SelectMany(GetChildInstallations);
|
||||
|
||||
return direct.Concat(fromFolders);
|
||||
return direct
|
||||
.Concat(fromFolders)
|
||||
.Distinct();
|
||||
}
|
||||
|
||||
|
||||
public IEnumerable<Folder> GetAllAccessibleFolders(User user)
|
||||
{
|
||||
return GetDirectlyAccessibleFolders(user)
|
||||
.SelectMany(GetDescendantFolders);
|
||||
.SelectMany(GetDescendantFolders)
|
||||
.Distinct();
|
||||
|
||||
// Distinct because the user might have direct access
|
||||
// to a child folder of a folder he has already access to
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
using DecimalMath;
|
||||
using InnovEnergy.Lib.Protocols.Modbus.Clients;
|
||||
using InnovEnergy.Lib.Protocols.Modbus.Connections;
|
||||
using InnovEnergy.Lib.StatusApi.Connections;
|
||||
using InnovEnergy.Lib.Units.Composite;
|
||||
using InnovEnergy.Lib.Utils;
|
||||
using static DecimalMath.DecimalEx;
|
||||
|
||||
namespace InnovEnergy.Lib.Devices.EmuMeter;
|
||||
|
@ -37,108 +34,61 @@ public class EmuMeterDevice
|
|||
private EmuMeterStatus TryReadStatus()
|
||||
{
|
||||
// Console.WriteLine("Reading Emu Meter Data");
|
||||
|
||||
|
||||
// TODO: get SerialNb, depends on Little/Big Endian support in Modbus Lib
|
||||
// var registers = Modbus.ReadHoldingRegisters(5001, 4);
|
||||
// var id = registers.GetInt32(5001);
|
||||
|
||||
var powerCurrent = Modbus.ReadHoldingRegisters(9000, 108).ToDecimals(); // TODO "ModbusRegisters"
|
||||
var voltageFreq = Modbus.ReadHoldingRegisters(9200, 112).ToDecimals(); // To check with Ivo
|
||||
var energyTotal = Modbus.ReadHoldingRegisters(6000, 24) .ToUInt64s();
|
||||
var energyPhases = Modbus.ReadHoldingRegisters(6100, 104).ToUInt64s();
|
||||
|
||||
// var energyPhases = Modbus.ReadHoldingRegisters(6100, 104).ToUInt64s();
|
||||
|
||||
var activePowerL123 = powerCurrent[0];
|
||||
var activePowerL1 = powerCurrent[1];
|
||||
var activePowerL2 = powerCurrent[2];
|
||||
var activePowerL3 = powerCurrent[3];
|
||||
var reactivePowerL123 = powerCurrent[5];
|
||||
var reactivePowerL1 = powerCurrent[6];
|
||||
var reactivePowerL2 = powerCurrent[7];
|
||||
var reactivePowerL3 = powerCurrent[8];
|
||||
var apparentPowerL123 = powerCurrent[10];
|
||||
var apparentPowerL1 = powerCurrent[11];
|
||||
var apparentPowerL2 = powerCurrent[12];
|
||||
var apparentPowerL3 = powerCurrent[13];
|
||||
var currentL123 = powerCurrent[50];
|
||||
|
||||
var currentL1 = powerCurrent[51];
|
||||
var currentL2 = powerCurrent[52];
|
||||
var currentL3 = powerCurrent[53];
|
||||
|
||||
var voltageL1N = voltageFreq[0];
|
||||
var voltageL2N = voltageFreq[1];
|
||||
var voltageL3N = voltageFreq[2];
|
||||
var voltageL1L2 = voltageFreq[3];
|
||||
var voltageL2L3 = voltageFreq[4];
|
||||
var voltageL3L1 = voltageFreq[5];
|
||||
var powerFactorL1 = voltageFreq[50];
|
||||
var powerFactorL2 = voltageFreq[51];
|
||||
var powerFactorL3 = voltageFreq[52];
|
||||
var frequency = voltageFreq[55];
|
||||
var energyImportL123 = energyTotal[0 / 4] / 1000.0m;
|
||||
var energyExportL123 = energyTotal[20 / 4] / 1000.0m;
|
||||
var energyImportL1 = energyPhases[0 / 4] / 1000.0m;
|
||||
var energyExportL1 = energyPhases[20 / 4] / 1000.0m;
|
||||
var energyImportL2 = energyPhases[40 / 4] / 1000.0m;
|
||||
var energyExportL2 = energyPhases[60 / 4] / 1000.0m;
|
||||
var energyImportL3 = energyPhases[80 / 4] / 1000.0m;
|
||||
var energyExportL3 = energyPhases[100 / 4] / 1000.0m;
|
||||
|
||||
// Ac: new Ac3Bus
|
||||
// (
|
||||
// new AcPhase(
|
||||
// voltageL1N,
|
||||
// currentL1,
|
||||
// GetPhi(powerFactorL1)
|
||||
// ),
|
||||
//
|
||||
// new AcPhase(
|
||||
// voltageL2N,
|
||||
// currentL2,
|
||||
// GetPhi(powerFactorL2)
|
||||
// ),
|
||||
//
|
||||
// new AcPhase(
|
||||
// voltageL3N,
|
||||
// currentL3,
|
||||
// GetPhi(powerFactorL3)
|
||||
// ),
|
||||
// frequency
|
||||
// ),
|
||||
// activePowerL123,
|
||||
// reactivePowerL123,
|
||||
// apparentPowerL123,
|
||||
// currentL123,
|
||||
// voltageL1L2,
|
||||
// voltageL2L3,
|
||||
// voltageL3L1,
|
||||
// energyImportL123,
|
||||
// energyImportL1,
|
||||
// energyImportL2,
|
||||
// energyImportL3,
|
||||
// energyExportL123,
|
||||
// energyExportL1,
|
||||
// energyExportL2,
|
||||
// energyExportL3
|
||||
// );
|
||||
|
||||
|
||||
var l1 = new AcPhase
|
||||
{
|
||||
Current = currentL1,
|
||||
Voltage = voltageL1N,
|
||||
Phi = ATan2(reactivePowerL1, activePowerL1) // TODO: check that this works
|
||||
};
|
||||
var l2 = new AcPhase
|
||||
{
|
||||
Current = currentL2,
|
||||
Voltage = voltageL2N,
|
||||
Phi = ATan2(reactivePowerL2, activePowerL2)
|
||||
};
|
||||
var l3 = new AcPhase
|
||||
{
|
||||
Current = currentL3,
|
||||
Voltage = voltageL3N,
|
||||
Phi = ATan2(reactivePowerL3, activePowerL3)
|
||||
};
|
||||
|
||||
return new EmuMeterStatus
|
||||
{
|
||||
Ac = new Ac3Bus
|
||||
{
|
||||
Frequency = frequency,
|
||||
L1 = new AcPhase
|
||||
{
|
||||
Current = currentL1,
|
||||
Voltage = voltageL1N,
|
||||
Phi = ATan2(reactivePowerL1, activePowerL1) // TODO: check that this works
|
||||
},
|
||||
L2 = new AcPhase
|
||||
{
|
||||
Current = currentL2,
|
||||
Voltage = voltageL2N,
|
||||
Phi = ATan2(reactivePowerL2, activePowerL2)
|
||||
},
|
||||
L3 = new AcPhase
|
||||
{
|
||||
Current = currentL3,
|
||||
Voltage = voltageL3N,
|
||||
Phi = ATan2(reactivePowerL3, activePowerL3)
|
||||
}
|
||||
L1 = l1,
|
||||
L2 = l2,
|
||||
L3 = l3
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ namespace InnovEnergy.Lib.Devices.EmuMeter;
|
|||
|
||||
public record EmuMeterStatus : PowerMeterStatus
|
||||
{
|
||||
// TODO add serial nb, (and other?)
|
||||
// TODO: additional Measurements, device id
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ public readonly partial struct UnixTimeSpan
|
|||
|
||||
public static UnixTimeSpan operator /(UnixTimeSpan a, UInt32 b) => new UnixTimeSpan(a.Ticks / b);
|
||||
public static UnixTimeSpan operator /(UnixTimeSpan a, Int32 b) => new UnixTimeSpan(a.Ticks / (UInt32)b);
|
||||
public static UInt32 operator /(UnixTimeSpan a, UnixTimeSpan b) => a.Ticks / b.Ticks;
|
||||
public static UInt32 operator /(UnixTimeSpan a, UnixTimeSpan b) => a.Ticks / b.Ticks;
|
||||
|
||||
public static UnixTimeSpan operator %(UnixTimeSpan a, UInt32 b) => new UnixTimeSpan(a.Ticks % b);
|
||||
public static UnixTimeSpan operator %(UnixTimeSpan a, Int32 b) => new UnixTimeSpan(a.Ticks % (UInt32)b);
|
|
@ -0,0 +1,17 @@
|
|||
using InnovEnergy.Lib.Time.Unix;
|
||||
using InnovEnergy.Lib.Units.Generator;
|
||||
|
||||
|
||||
namespace InnovEnergy.Lib.Units;
|
||||
|
||||
[Sum]
|
||||
public readonly partial struct Energy
|
||||
{
|
||||
public static String Unit => "kWh";
|
||||
public static String Symbol => "E";
|
||||
|
||||
public Energy(Decimal value) => Value = value;
|
||||
|
||||
public static Power operator /(Energy energy, TimeSpan timeSpan) => energy.Value * 1000m / (Decimal) timeSpan.TotalHours ;
|
||||
public static Power operator /(Energy energy, UnixTimeSpan timeSpan) => energy.Value * 3_600_000m / timeSpan.Ticks;
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source.
|
||||
#define Sum
|
||||
|
||||
using static System.Math;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using InnovEnergy.Lib.Utils;
|
||||
|
||||
namespace InnovEnergy.Lib.Units;
|
||||
|
||||
using T = Energy;
|
||||
|
||||
[JsonConverter(typeof(EnergyConverter))]
|
||||
public readonly partial struct Energy
|
||||
{
|
||||
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);
|
||||
|
||||
// parallel
|
||||
|
||||
#if Sum
|
||||
|
||||
public static T operator |(T left, T right) => new T(left.Value + right.Value);
|
||||
public static T operator -(T t) => new T(-t.Value);
|
||||
|
||||
#elif Mean
|
||||
|
||||
public static T operator |(T left, T right) => new T((left.Value + right.Value)/2m);
|
||||
|
||||
#elif Equal
|
||||
|
||||
public static T operator |(T left, T right)
|
||||
{
|
||||
var d = Max(Abs(left.Value), Abs(right.Value));
|
||||
|
||||
if (d == 0m)
|
||||
return new T(0m);
|
||||
|
||||
var relativeError = Abs(left.Value - right.Value) / d;
|
||||
|
||||
const Decimal maxRelativeError = 0.05m;
|
||||
|
||||
if (relativeError > maxRelativeError)
|
||||
throw new Exception($"{nameof(left)} and {nameof(right)} must be approximately equal.\n" +
|
||||
$"Difference > {maxRelativeError * 100}% detected\n" +
|
||||
$"{nameof(left)} : {left}\n" +
|
||||
$"{nameof(right)}: {right}");
|
||||
|
||||
return new T((left.Value + right.Value) / 2m);
|
||||
}
|
||||
#endif
|
||||
|
||||
// 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 EnergyConverter : JsonConverter<Energy>
|
||||
{
|
||||
public override Energy Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
return new Energy(reader.GetDecimal());
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, Energy value, JsonSerializerOptions options)
|
||||
{
|
||||
var rounded = value.Value.RoundToSignificantDigits(Units.JsonSignificantDigits);
|
||||
|
||||
writer.WriteNumberValue(rounded);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
using InnovEnergy.Lib.Time.Unix;
|
||||
using InnovEnergy.Lib.Units.Generator;
|
||||
|
||||
namespace InnovEnergy.Lib.Units;
|
||||
|
@ -14,5 +15,10 @@ public readonly partial struct Power
|
|||
// P=UI
|
||||
public static Voltage operator /(Power power, Current current) => new Voltage(power.Value / current.Value);
|
||||
public static Current operator /(Power power, Voltage voltage) => new Current(power.Value / voltage.Value);
|
||||
|
||||
public static Energy operator *(Power power, TimeSpan timeSpan) => power.Value / 1000m * (Decimal) timeSpan.TotalHours;
|
||||
public static Energy operator *(TimeSpan timeSpan, Power power) => power.Value / 1000m * (Decimal) timeSpan.TotalHours;
|
||||
|
||||
public static Energy operator *(Power power, UnixTimeSpan timeSpan) => power.Value * timeSpan.Ticks / 3_600_000;
|
||||
public static Energy operator *(UnixTimeSpan timeSpan, Power power) => power.Value * timeSpan.Ticks / 3_600_000;
|
||||
}
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../Utils/Utils.csproj" />
|
||||
<ProjectReference Include="../Time/Time.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
|
||||
|
|
Loading…
Reference in New Issue