119 lines
3.3 KiB
C#
119 lines
3.3 KiB
C#
|
using System.Diagnostics.CodeAnalysis;
|
||
|
using InnovEnergy.Lib.Utils;
|
||
|
using InnovEnergy.WireFormat.VictronV1;
|
||
|
|
||
|
namespace InnovEnergy.VenusLogger;
|
||
|
|
||
|
internal static class Devices
|
||
|
{
|
||
|
|
||
|
public static Maybe<Device> Combine(this DeviceType deviceType, params Maybe<Device>[] devices)
|
||
|
{
|
||
|
return devices
|
||
|
.Flatten()
|
||
|
.Combine(deviceType);
|
||
|
}
|
||
|
|
||
|
public static Maybe<Device> Combine(this IEnumerable<Device> devices, DeviceType deviceType)
|
||
|
{
|
||
|
var devs = devices as IReadOnlyCollection<Device> ?? devices.ToList();
|
||
|
|
||
|
return devs.Combine(deviceType);
|
||
|
}
|
||
|
|
||
|
public static Maybe<Device> Combine(this IReadOnlyCollection<Device> devices, DeviceType deviceType)
|
||
|
{
|
||
|
return devices
|
||
|
.EquivalentDevice(deviceType)
|
||
|
.Do(d => d.Devices.Add(devices)); // Maybe;
|
||
|
}
|
||
|
|
||
|
public static Maybe<Device> EquivalentDevice(this DeviceType deviceType, params Maybe<Device>[] devices)
|
||
|
{
|
||
|
return devices
|
||
|
.Flatten()
|
||
|
.EquivalentDevice(deviceType);
|
||
|
}
|
||
|
|
||
|
public static Maybe<Device> EquivalentDevice(this IEnumerable<Device> devices, DeviceType deviceType)
|
||
|
{
|
||
|
var devs = devices as IReadOnlyCollection<Device> ?? devices.ToList();
|
||
|
|
||
|
return devs.EquivalentDevice(deviceType);
|
||
|
}
|
||
|
|
||
|
public static Maybe<Device> EquivalentDevice(this IReadOnlyCollection<Device> devices, DeviceType deviceType)
|
||
|
{
|
||
|
if (devices.Count <= 0)
|
||
|
return null;
|
||
|
|
||
|
if (devices.Count == 1)
|
||
|
return new Device { Type = deviceType, Phases = { devices.First().Phases } };
|
||
|
|
||
|
var voltages = devices.GetPhaseVoltages();
|
||
|
|
||
|
var phases = voltages.Select((v, phase) => new Phase
|
||
|
{
|
||
|
Voltage = v,
|
||
|
Current = devices.Sum(d => d.Phases[phase].Current),
|
||
|
Power = devices.Sum(d => d.Phases[phase].Power),
|
||
|
});
|
||
|
|
||
|
return new Device
|
||
|
{
|
||
|
Type = deviceType,
|
||
|
Phases = { phases }
|
||
|
};
|
||
|
}
|
||
|
|
||
|
public static Device ReversePhases(this Device device)
|
||
|
{
|
||
|
device.Phases.ForEach(p =>
|
||
|
{
|
||
|
p.Current = -p.Current;
|
||
|
p.Power = -p.Power;
|
||
|
});
|
||
|
|
||
|
return device;
|
||
|
}
|
||
|
|
||
|
[SuppressMessage("ReSharper", "PossibleMultipleEnumeration")]
|
||
|
private static IEnumerable<Single> GetPhaseVoltages(this IReadOnlyCollection<Device> devices)
|
||
|
{
|
||
|
// TODO: warning if voltages unequal?
|
||
|
|
||
|
var nPhases = devices.Max(d => d.Phases.Count);
|
||
|
|
||
|
var phases = Enumerable.Range(0, nPhases);
|
||
|
|
||
|
var voltages = phases
|
||
|
.Select(AverageVoltage)
|
||
|
.ToList();
|
||
|
|
||
|
if (nPhases != devices.Min(d => d.Phases.Count))
|
||
|
EqualizeNumberOfPhases();
|
||
|
|
||
|
return voltages;
|
||
|
|
||
|
Single AverageVoltage(Int32 phase)
|
||
|
{
|
||
|
return devices
|
||
|
.Where(d => d.Phases.Count > phase)
|
||
|
.Average(d => d.Phases[phase].Voltage);
|
||
|
}
|
||
|
|
||
|
void EqualizeNumberOfPhases()
|
||
|
{
|
||
|
foreach (var phase in phases)
|
||
|
foreach (var device in devices.Where(d => d.Phases.Count <= phase))
|
||
|
{
|
||
|
device.Phases.Add(new Phase
|
||
|
{
|
||
|
Current = 0,
|
||
|
Voltage = voltages[phase]
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|