Innovenergy_trunk/csharp/app/VenusLogger/Devices.cs

119 lines
3.3 KiB
C#
Raw Normal View History

2023-02-16 12:57:06 +00:00
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]
});
}
}
}
}