fix merge conflict

This commit is contained in:
Noe 2023-06-30 09:00:44 +02:00
commit 9e9a899f8e
33 changed files with 376 additions and 942 deletions

View File

@ -7,9 +7,6 @@ namespace InnovEnergy.App.Backend;
public static class Program public static class Program
{ {
public static void Main(String[] args) public static void Main(String[] args)
{ {
//Db.CreateFakeRelations(); //Db.CreateFakeRelations();

Binary file not shown.

View File

@ -9,8 +9,9 @@ set -e
echo -e "\n============================ Build ============================\n" echo -e "\n============================ Build ============================\n"
dotnet publish \ dotnet publish \
./SaliMax.csproj \ ./SaliMax.csproj \
-p:PublishTrimmed=false \
-c Release \ -c Release \
-r linux-x64 -r linux-x64

View File

@ -28,13 +28,19 @@ public static class Controller
var mode = s.SelectControlMode(); var mode = s.SelectControlMode();
mode.WriteLine(); mode.WriteLine();
if (mode is EssMode.Off or EssMode.NoGridMeter) if (mode is EssMode.Off or EssMode.NoGridMeter)
return new EssControl(mode, EssLimit.NoLimit, PowerCorrection: 0, PowerSetpoint: 0); return EssControl.Default;
var essDelta = s.ComputePowerDelta(mode); var essDelta = s.ComputePowerDelta(mode);
var unlimitedControl = new EssControl(mode, EssLimit.NoLimit, essDelta, 0); var unlimitedControl = new EssControl
{
Mode = mode,
LimitedBy = EssLimit.NoLimit,
PowerCorrection = essDelta,
PowerSetpoint = 0
};
var limitedControl = unlimitedControl var limitedControl = unlimitedControl
.LimitChargePower(s) .LimitChargePower(s)

View File

@ -3,13 +3,21 @@ using InnovEnergy.Lib.Units.Power;
namespace InnovEnergy.App.SaliMax.Ess; namespace InnovEnergy.App.SaliMax.Ess;
public record EssControl public record EssControl
(
EssMode Mode,
EssLimit LimitedBy,
ActivePower PowerCorrection,
ActivePower PowerSetpoint
)
{ {
public required EssMode Mode { get; init; }
public required EssLimit LimitedBy { get; init; }
public required ActivePower PowerCorrection { get; init; }
public required ActivePower PowerSetpoint { get; init; }
public static EssControl Default { get; } = new()
{
Mode = EssMode.Off,
LimitedBy = EssLimit.NoLimit,
PowerCorrection = 0,
PowerSetpoint = 0
};
public EssControl LimitChargePower(Double controlDelta, EssLimit reason) public EssControl LimitChargePower(Double controlDelta, EssLimit reason)
{ {
var overload = PowerCorrection - controlDelta; var overload = PowerCorrection - controlDelta;

View File

@ -12,20 +12,20 @@ namespace InnovEnergy.App.SaliMax.Ess;
public record StatusRecord public record StatusRecord
{ {
public AcDcDevicesRecord AcDc { get; init; } = null!; public required AcDcDevicesRecord AcDc { get; init; }
public DcDcDevicesRecord DcDc { get; init; } = null!; public required DcDcDevicesRecord DcDc { get; init; }
public Battery48TlRecords Battery { get; init; } = null!; public required Battery48TlRecords Battery { get; init; }
public EmuMeterRegisters? GridMeter { get; init; } public required EmuMeterRegisters? GridMeter { get; init; }
public EmuMeterRegisters? LoadOnAcIsland { get; init; } public required EmuMeterRegisters? LoadOnAcIsland { get; init; }
public AcPowerDevice? LoadOnAcGrid { get; init; } = null!; public required AcPowerDevice? LoadOnAcGrid { get; init; }
public AcPowerDevice? PvOnAcGrid { get; init; } = null!; public required AcPowerDevice? PvOnAcGrid { get; init; }
public AcPowerDevice? PvOnAcIsland { get; init; } = null!; public required AcPowerDevice? PvOnAcIsland { get; init; }
public AcPowerDevice? AcGridToAcIsland { get; init; } = null!; public required AcPowerDevice? AcGridToAcIsland { get; init; }
public DcPowerDevice? LoadOnDc { get; init; } = null!; public required DcPowerDevice? LoadOnDc { get; init; }
public RelaysRecord? Relays { get; init; } public required RelaysRecord? Relays { get; init; }
public AmptStatus PvOnDc { get; init; } = null!; public required AmptStatus PvOnDc { get; init; }
public Config Config { get; init; } = null!; public required Config Config { get; init; }
public EssControl EssControl { get; set; } = null!; public required EssControl EssControl { get; set; } // TODO: init only
public StateMachine StateMachine { get; } = new StateMachine(); public required StateMachine StateMachine { get; init; }
} }

View File

@ -14,7 +14,7 @@ public static class Flow
public static TextBlock Horizontal(Unit amount, Int32 width = 10) public static TextBlock Horizontal(Unit amount, Int32 width = 10)
{ {
var label = amount.ToStringRounded(); var label = amount.ToDisplayString();
var arrowChar = amount.Value < 0 ? LeftArrowChar : RightArrowChar; var arrowChar = amount.Value < 0 ? LeftArrowChar : RightArrowChar;
var arrow = Enumerable.Repeat(arrowChar, width).Join(); var arrow = Enumerable.Repeat(arrowChar, width).Join();
@ -26,7 +26,7 @@ public static class Flow
[SuppressMessage("ReSharper", "CoVariantArrayConversion")] [SuppressMessage("ReSharper", "CoVariantArrayConversion")]
public static TextBlock Vertical(Unit amount, Int32 height = 4) public static TextBlock Vertical(Unit amount, Int32 height = 4)
{ {
var label = amount.ToStringRounded(); var label = amount.ToDisplayString();
var arrowChar = amount.Value < 0 ? UpArrowChar : DownArrowChar; var arrowChar = amount.Value < 0 ? UpArrowChar : DownArrowChar;
var halfArrow = Enumerable.Repeat(arrowChar, height/2); var halfArrow = Enumerable.Repeat(arrowChar, height/2);

View File

@ -148,7 +148,9 @@ internal static class Program
LoadOnAcIsland = loadOnAcIsland, LoadOnAcIsland = loadOnAcIsland,
LoadOnDc = loadOnDc, LoadOnDc = loadOnDc,
Config = Config.Load() // load from disk every iteration, so config can be changed while running StateMachine = StateMachine.Default,
EssControl = EssControl.Default,
Config = Config.Load() // load from disk every iteration, so config can be changed while running
}; };
} }
@ -228,17 +230,17 @@ internal static class Program
var islandToGridBusPower = inverterPower + islandLoadPower; var islandToGridBusPower = inverterPower + islandLoadPower;
var gridLoadPower = s.LoadOnAcGrid is null ? 0: s.LoadOnAcGrid.Power.Active; var gridLoadPower = s.LoadOnAcGrid is null ? 0: s.LoadOnAcGrid.Power.Active;
var gridPowerByPhase = TextBlock.AlignLeft(s.GridMeter.Ac.L1.Power.Active.ToStringRounded(), var gridPowerByPhase = TextBlock.AlignLeft(s.GridMeter.Ac.L1.Power.Active.ToDisplayString(),
s.GridMeter.Ac.L2.Power.Active.ToStringRounded(), s.GridMeter.Ac.L2.Power.Active.ToDisplayString(),
s.GridMeter.Ac.L3.Power.Active.ToStringRounded()); s.GridMeter.Ac.L3.Power.Active.ToDisplayString());
var gridVoltageByPhase = TextBlock.AlignLeft(s.GridMeter.Ac.L1.Voltage.ToStringRounded(), var gridVoltageByPhase = TextBlock.AlignLeft(s.GridMeter.Ac.L1.Voltage.ToDisplayString(),
s.GridMeter.Ac.L2.Voltage.ToStringRounded(), s.GridMeter.Ac.L2.Voltage.ToDisplayString(),
s.GridMeter.Ac.L3.Voltage.ToStringRounded()); s.GridMeter.Ac.L3.Voltage.ToDisplayString());
var inverterPowerByPhase = TextBlock.AlignLeft(s.AcDc.Ac.L1.Power.Active.ToStringRounded(), var inverterPowerByPhase = TextBlock.AlignLeft(s.AcDc.Ac.L1.Power.Active.ToDisplayString(),
s.AcDc.Ac.L2.Power.Active.ToStringRounded(), s.AcDc.Ac.L2.Power.Active.ToDisplayString(),
s.AcDc.Ac.L3.Power.Active.ToStringRounded()); s.AcDc.Ac.L3.Power.Active.ToDisplayString());
// ReSharper disable once CoVariantArrayConversion // ReSharper disable once CoVariantArrayConversion
var inverterPowerByAcDc = TextBlock.AlignLeft(s.AcDc.Devices var inverterPowerByAcDc = TextBlock.AlignLeft(s.AcDc.Devices
@ -246,7 +248,7 @@ internal static class Program
.ToArray()); .ToArray());
var dcLinkVoltage = TextBlock.CenterHorizontal("", var dcLinkVoltage = TextBlock.CenterHorizontal("",
s.DcDc.Dc.Link.Voltage.ToStringRounded(), s.DcDc.Dc.Link.Voltage.ToDisplayString(),
""); "");
//var inverterPowerByPhase = new ActivePower[(Int32)s.AcDc.Ac.L1.Power.Active, (Int32)s.AcDc.Ac.L2.Power.Active, (Int32)s.AcDc.Ac.L3.Power.Active]; //var inverterPowerByPhase = new ActivePower[(Int32)s.AcDc.Ac.L1.Power.Active, (Int32)s.AcDc.Ac.L2.Power.Active, (Int32)s.AcDc.Ac.L3.Power.Active];
@ -273,7 +275,7 @@ internal static class Program
var gridBox = TextBlock.AlignLeft(gridPowerByPhase).TitleBox("Grid"); var gridBox = TextBlock.AlignLeft(gridPowerByPhase).TitleBox("Grid");
var inverterBox = TextBlock.AlignLeft(inverterPowerByAcDc).TitleBox("Inverter"); var inverterBox = TextBlock.AlignLeft(inverterPowerByAcDc).TitleBox("Inverter");
var dcDcBox = TextBlock.AlignLeft(dc48Voltage).TitleBox("DC/DC"); var dcDcBox = TextBlock.AlignLeft(dc48Voltage).TitleBox("DC/DC");
var batteryBox = TextBlock.AlignLeft(batteryVoltage.ToStringRounded(), batterySoc.ToStringRounded(), batteryCurrent.ToStringRounded(), batteryTemp.ToStringRounded()).TitleBox("Battery"); var batteryBox = TextBlock.AlignLeft(batteryVoltage.ToDisplayString(), batterySoc.ToDisplayString(), batteryCurrent.ToDisplayString(), batteryTemp.ToDisplayString()).TitleBox("Battery");

View File

@ -9,12 +9,12 @@ namespace InnovEnergy.App.SaliMax;
public record S3Config public record S3Config
{ {
public String Bucket { get; init; } = ""; public required String Bucket { get; init; }
public String Region { get; init; } = ""; public required String Region { get; init; }
public String Provider { get; init; } = ""; public required String Provider { get; init; }
public String Key { get; init; } = ""; public required String Key { get; init; }
public String Secret { get; init; } = ""; public required String Secret { get; init; }
public String ContentType { get; init; } = ""; public required String ContentType { get; init; }
public String Host => $"{Bucket}.{Region}.{Provider}"; public String Host => $"{Bucket}.{Region}.{Provider}";
public String Url => $"https://{Host}"; public String Url => $"https://{Host}";

View File

@ -1,7 +1,9 @@
namespace InnovEnergy.App.SaliMax.System; namespace InnovEnergy.App.SaliMax.System;
public class StateMachine public record StateMachine
{ {
public String Message { get; set; } = "Panic: Unknown State!"; public required String Message { get; set; } // TODO: init only
public Int32 State { get; set; } = 100; public required Int32 State { get; set; } // TODO: init only
public static StateMachine Default { get; } = new StateMachine { State = 100, Message = "Unknown State" };
} }

View File

@ -6,13 +6,15 @@
<LangVersion>preview</LangVersion> <LangVersion>preview</LangVersion>
<IsTrimmable>true</IsTrimmable> <IsTrimmable>true</IsTrimmable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
<InvariantGlobalization>true</InvariantGlobalization> <InvariantGlobalization>true</InvariantGlobalization>
<SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings> <SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>
<RootNamespace>$([System.Text.RegularExpressions.Regex]::Match($(MSBuildProjectExtensionsPath), "[/\\]csharp[/\\].*[/\\]obj").ToString().Replace("/",".").Replace("\\",".").Replace(".csharp", $(Company)).Replace(".obj", ""))</RootNamespace> <RootNamespace>Please.reload.the.project.Rider.is.stupid</RootNamespace>
<Authors>$(Company) Team</Authors> <Authors>$(Company) Team</Authors>
<!-- <ProjectPath>$([System.Text.RegularExpressions.Regex]::Match($(MSBuildProjectExtensionsPath), "[/\\]csharp[/\\].*[/\\]obj").ToString().Replace("/",".").Replace("\\",".").Replace(".csharp", $(Company)).Replace(".obj", ""))</ProjectPath>-->
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(SolutionDir)' != ''">
</Project> <RootNamespace>$(Company).$(MSBuildProjectDirectory.Replace($(SolutionDir), "").Replace("/",".").Replace("\","."))</RootNamespace>
</PropertyGroup>
</Project>

View File

@ -4,8 +4,8 @@ namespace InnovEnergy.Lib.Channels.Stages;
public class Channel<Tx, Rx> public class Channel<Tx, Rx>
{ {
public AsyncAction<Tx> Write { get; init; } = _ => throw new NotImplementedException(nameof(Write)); public required AsyncAction<Tx> Write { get; init; }
public Async<Rx> Read { get; init; } = () => throw new NotImplementedException(nameof(Read)); public required Async<Rx> Read { get; init; }
public Channel<T, R> Map<T, R>(Stage<T, Tx, Rx, R> stage) public Channel<T, R> Map<T, R>(Stage<T, Tx, Rx, R> stage)
{ {

View File

@ -4,9 +4,9 @@ namespace InnovEnergy.Lib.Channels.Stages;
public class ConnectedChannel<Tx, Rx> : Channel<Tx,Rx>, IAsyncDisposable public class ConnectedChannel<Tx, Rx> : Channel<Tx,Rx>, IAsyncDisposable
{ {
public Func<Boolean> IsOpen { get; init; } = () => throw new NotImplementedException(nameof(IsOpen)); public required Func<Boolean> IsOpen { get; init; }
public AsyncAction Open { get; init; } = () => throw new NotImplementedException(nameof(Open)); public required AsyncAction Open { get; init; }
public AsyncAction Close { get; init; } = () => throw new NotImplementedException(nameof(Close)); public required AsyncAction Close { get; init; }
public async ValueTask DisposeAsync() => await Close(); public async ValueTask DisposeAsync() => await Close();
} }

View File

@ -1,16 +1,18 @@
namespace InnovEnergy.Lib.Devices.AMPT; namespace InnovEnergy.Lib.Devices.AMPT;
// not used ATM
public class AmptCommunicationUnitStatus public class AmptCommunicationUnitStatus
{ {
public UInt32 Sid { get; init; } // A well-known value 0x53756e53, uniquely identifies this as a SunSpec Modbus Map public required UInt32 Sid { get; init; } // A well-known value 0x53756e53, uniquely identifies this as a SunSpec Modbus Map
public UInt16 IdSunSpec { get; init; } // A well-known value 1, uniquely identifies this as a SunSpec Common Model public required UInt16 IdSunSpec { get; init; } // A well-known value 1, uniquely identifies this as a SunSpec Common Model
public String Manufacturer { get; init; } = "undefined"; // A well-known value registered with SunSpec for compliance: "Ampt" public required String Manufacturer { get; init; } // A well-known value registered with SunSpec for compliance: "Ampt"
public String Model { get; init; } = "undefined"; // Manufacturer specific value "Communication Unit" public required String Model { get; init; } // Manufacturer specific value "Communication Unit"
public String Version { get; init; } = "undefined"; // Software Version public required String Version { get; init; } // Software Version
public String SerialNumber { get; init; } = "undefined"; // Manufacturer specific value public required String SerialNumber { get; init; } // Manufacturer specific value
public Int16 DeviceAddress { get; init; } // Modbus Device ID public required Int16 DeviceAddress { get; init; } // Modbus Device ID
public UInt16 IdVendor { get; init; } // Ampt SunSpec Vendor Code 64050 public required UInt16 IdVendor { get; init; } // Ampt SunSpec Vendor Code 64050
public IReadOnlyList<AmptStatus> Devices { get; init; } = Array.Empty<AmptStatus>(); public required IReadOnlyList<AmptStatus> Devices { get; init; }
} }

View File

@ -21,13 +21,13 @@ public interface IMatchRule
public record MatchRule : IMatchRule public record MatchRule : IMatchRule
{ {
public MessageType? Type { get; init; } = default; public MessageType? Type { get; init; }
public String? Interface { get; init; } = default; public String? Interface { get; init; }
public String? Member { get; init; } = default; public String? Member { get; init; }
public ObjectPath? Path { get; init; } = default; public ObjectPath? Path { get; init; }
public ObjectPath? PathNamespace { get; init; } = default; public ObjectPath? PathNamespace { get; init; }
public String? Sender { get; init; } = default; public String? Sender { get; init; }
public String? Destination { get; init; } = default; public String? Destination { get; init; }
public Boolean Eavesdrop { get; init; } = false; public Boolean Eavesdrop { get; init; } = false;
public override String ToString() => this.Rule(); public override String ToString() => this.Rule();

View File

@ -5,10 +5,10 @@ public sealed class Ac1Bus
private Ac1Bus() private Ac1Bus()
{} {}
public Voltage Voltage { get; private init; } = null!; public required Voltage Voltage { get; init; }
public Current Current { get; private init; } = null!; public required Current Current { get; init; }
public AcPower Power { get; private init; } = null!; public required AcPower Power { get; init; }
public Frequency Frequency { get; private init; } = null!; public required Frequency Frequency { get; init; }
public static Ac1Bus FromVoltageCurrentFrequencyPhi(Double voltageRms, public static Ac1Bus FromVoltageCurrentFrequencyPhi(Double voltageRms,
Double currentRms, Double currentRms,

View File

@ -6,11 +6,11 @@ public sealed class Ac3Bus
{ {
private Ac3Bus() {} private Ac3Bus() {}
public AcPhase L1 { get; private init; } = null!; public required AcPhase L1 { get; init; }
public AcPhase L2 { get; private init; } = null!; public required AcPhase L2 { get; init; }
public AcPhase L3 { get; private init; } = null!; public required AcPhase L3 { get; init; }
public AcPower Power { get; private init; } = null!; public required AcPower Power { get; init; }
public Frequency Frequency { get; private init; } = null!; public required Frequency Frequency { get; init; }
public static Ac3Bus FromPhasesAndFrequency(AcPhase l1, public static Ac3Bus FromPhasesAndFrequency(AcPhase l1,
AcPhase l2, AcPhase l2,

View File

@ -7,9 +7,9 @@ public sealed class AcPhase
{ {
private AcPhase(){} private AcPhase(){}
public Voltage Voltage { get; private init; } = null!; public required Voltage Voltage { get; init; }
public Current Current { get; private init; } = null!; public required Current Current { get; init; }
public AcPower Power { get; private init; } = null!; public required AcPower Power { get; init; }
public static AcPhase FromVoltageCurrentPhi(Voltage voltageRms, public static AcPhase FromVoltageCurrentPhi(Voltage voltageRms,
Current currentRms, Current currentRms,

View File

@ -8,11 +8,11 @@ public sealed class AcPower
{ {
private AcPower(){} private AcPower(){}
public ApparentPower Apparent { get; private init; } = null!; public required ApparentPower Apparent { get; init; }
public ActivePower Active { get; private init; } = null!; public required ActivePower Active { get; init; }
public ReactivePower Reactive { get; private init; } = null!; public required ReactivePower Reactive { get; init; }
public Angle Phi { get; private init; } = null!; public required Angle Phi { get; init; }
public Double CosPhi { get; private init; } public required Double CosPhi { get; init; }
public static AcPower FromActiveReactiveApparent(ActivePower activePower, ReactivePower reactivePower, ApparentPower apparentPower) public static AcPower FromActiveReactiveApparent(ActivePower activePower, ReactivePower reactivePower, ApparentPower apparentPower)
{ {

View File

@ -6,9 +6,9 @@ public sealed class DcBus
{ {
private DcBus() {} private DcBus() {}
public Voltage Voltage { get; private init; } = null!; public required Voltage Voltage { get; init; }
public Current Current { get; private init; } = null!; public required Current Current { get; init; }
public ActivePower Power { get; private init; } = null!; public required ActivePower Power { get; init; }
public static DcBus FromVoltageCurrent(Voltage voltage, Current current) => new() public static DcBus FromVoltageCurrent(Voltage voltage, Current current) => new()
{ {

View File

@ -2,7 +2,7 @@ namespace InnovEnergy.Lib.Units;
public sealed class Energy : Unit public sealed class Energy : Unit
{ {
public override String Symbol => "kWh"; public override String Symbol => "Wh";
public Energy(Double value) : base(value) public Energy(Double value) : base(value)
{ {

View File

@ -12,7 +12,6 @@ public sealed class ActivePower : AcPower
public static implicit operator ActivePower(Double d) => new ActivePower(d); public static implicit operator ActivePower(Double d) => new ActivePower(d);
public static implicit operator Double(ActivePower d) => d.Value; public static implicit operator Double(ActivePower d) => d.Value;
public static ActivePower operator -(ActivePower d) => -d.Value; public static ActivePower operator -(ActivePower d) => -d.Value;
} }

View File

@ -8,5 +8,35 @@ public abstract class Unit
public Double Value { get; } public Double Value { get; }
public override String ToString() => $"{Value} {Symbol}"; public override String ToString() => $"{Value} {Symbol}";
public String ToStringRounded() => $"{Math.Round(Value,3)} {Symbol}";
} public String ToDisplayString()
{
if (Value == 0)
return $"0 {Symbol}";
var a = Math.Abs(Value);
var s = Math.Sign(Value);
var i = 8;
while (a >= 10000)
{
a /= 1000;
i++;
}
while (a < 10)
{
a *= 1000;
i--;
}
var r = a < 100
? Math.Floor(a * 10) / 10
: Math.Floor(a);
return $"{r * s} {Prefix[i]}{Symbol}";
}
private static readonly IReadOnlyList<String> Prefix = new[] { "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Y" };
}

View File

@ -1,5 +1,4 @@
using System.Collections; using System.Collections;
using System.Reflection;
using InnovEnergy.Lib.Units.Power; using InnovEnergy.Lib.Units.Power;
using InnovEnergy.Lib.Utils; using InnovEnergy.Lib.Utils;
using static System.Reflection.BindingFlags; using static System.Reflection.BindingFlags;
@ -20,7 +19,8 @@ public static class Units
public static Frequency Hz (this Double value) => value; public static Frequency Hz (this Double value) => value;
public static Angle Rad (this Double value) => value; public static Angle Rad (this Double value) => value;
public static Temperature Celsius(this Double value) => value; public static Temperature Celsius(this Double value) => value;
public static Energy KWh (this Double value) => value; public static Energy KWh (this Double value) => value * 1000;
public static Energy Wh (this Double value) => value;
public static String ToCsv(this Object thing) public static String ToCsv(this Object thing)
{ {
@ -88,87 +88,3 @@ public static class Units
} }
} }
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}";
}
}

View File

@ -5,8 +5,8 @@ namespace InnovEnergy.Lib.WebServer;
public static class Default public static class Default
{ {
public static IPEndPoint EndPoint { get; } = new IPEndPoint(0, 0); public static IPEndPoint EndPoint { get; } = new IPEndPoint(0, 0);
public static Url Url { get; } = new Url(""); public static Url Url { get; } = new Url("");
public static HttpResponse HttpNotFound { get; } = new HttpResponse { StatusCode = 404 }; public static HttpResponse HttpNotFound { get; } = new HttpResponse { StatusCode = 404 };
public static HttpResponse HttpForbidden { get; } = new HttpResponse { StatusCode = 403 }; public static HttpResponse HttpForbidden { get; } = new HttpResponse { StatusCode = 403 };

View File

@ -42,7 +42,6 @@
"react-plotly.js": "^2.6.0", "react-plotly.js": "^2.6.0",
"react-router-dom": "^6.8.0", "react-router-dom": "^6.8.0",
"react-scripts": "5.0.1", "react-scripts": "5.0.1",
"react-window": "^1.8.9",
"reactflow": "^11.5.6", "reactflow": "^11.5.6",
"rxjs": "^7.8.0", "rxjs": "^7.8.0",
"sass": "^1.58.3", "sass": "^1.58.3",
@ -17199,11 +17198,6 @@
"node": ">= 4.0.0" "node": ">= 4.0.0"
} }
}, },
"node_modules/memoize-one": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
},
"node_modules/merge-descriptors": { "node_modules/merge-descriptors": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
@ -20585,22 +20579,6 @@
"react-dom": ">=16.13" "react-dom": ">=16.13"
} }
}, },
"node_modules/react-window": {
"version": "1.8.9",
"resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.9.tgz",
"integrity": "sha512-+Eqx/fj1Aa5WnhRfj9dJg4VYATGwIUP2ItwItiJ6zboKWA6EX3lYDAXfGF2hyNqplEprhbtjbipiADEcwQ823Q==",
"dependencies": {
"@babel/runtime": "^7.0.0",
"memoize-one": ">=3.1.1 <6"
},
"engines": {
"node": ">8.0.0"
},
"peerDependencies": {
"react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/reactflow": { "node_modules/reactflow": {
"version": "11.5.6", "version": "11.5.6",
"resolved": "https://registry.npmjs.org/reactflow/-/reactflow-11.5.6.tgz", "resolved": "https://registry.npmjs.org/reactflow/-/reactflow-11.5.6.tgz",
@ -38023,11 +38001,6 @@
"fs-monkey": "^1.0.3" "fs-monkey": "^1.0.3"
} }
}, },
"memoize-one": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
},
"merge-descriptors": { "merge-descriptors": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
@ -40347,15 +40320,6 @@
"debounce": "^1.2.1" "debounce": "^1.2.1"
} }
}, },
"react-window": {
"version": "1.8.9",
"resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.9.tgz",
"integrity": "sha512-+Eqx/fj1Aa5WnhRfj9dJg4VYATGwIUP2ItwItiJ6zboKWA6EX3lYDAXfGF2hyNqplEprhbtjbipiADEcwQ823Q==",
"requires": {
"@babel/runtime": "^7.0.0",
"memoize-one": ">=3.1.1 <6"
}
},
"reactflow": { "reactflow": {
"version": "11.5.6", "version": "11.5.6",
"resolved": "https://registry.npmjs.org/reactflow/-/reactflow-11.5.6.tgz", "resolved": "https://registry.npmjs.org/reactflow/-/reactflow-11.5.6.tgz",

View File

@ -37,7 +37,6 @@
"react-plotly.js": "^2.6.0", "react-plotly.js": "^2.6.0",
"react-router-dom": "^6.8.0", "react-router-dom": "^6.8.0",
"react-scripts": "5.0.1", "react-scripts": "5.0.1",
"react-window": "^1.8.9",
"reactflow": "^11.5.6", "reactflow": "^11.5.6",
"rxjs": "^7.8.0", "rxjs": "^7.8.0",
"sass": "^1.58.3", "sass": "^1.58.3",

View File

@ -1,33 +1,48 @@
import { createContext, ReactNode, SetStateAction, useState } from "react"; import { createContext, ReactNode, useState } from "react";
import { TreeElement, ToggleElement } from "../Installations/Log/CheckboxTree"; import { TreeElement } from "../Installations/Log/CheckboxTree";
import React from "react"; import React from "react";
interface LogContextProviderProps { interface LogContextProviderProps {
toggles: TreeElement[] | null; toggles: TreeElement[] | null;
setToggles: (value: TreeElement[]) => void; setToggles: (value: TreeElement[]) => void;
checkedToggles: ToggleElement | null; checkedToggles: string[];
setCheckedToggles: React.Dispatch<SetStateAction<ToggleElement | null>>; setChecked: (newValue: string) => void;
removeChecked: (value: string) => void;
} }
export const LogContext = createContext<LogContextProviderProps>({ export const LogContext = createContext<LogContextProviderProps>({
toggles: [], toggles: [],
setToggles: () => {}, setToggles: () => {},
checkedToggles: {}, checkedToggles: [],
setCheckedToggles: () => {}, setChecked: () => {},
removeChecked: () => {},
}); });
const LogContextProvider = ({ children }: { children: ReactNode }) => { const LogContextProvider = ({ children }: { children: ReactNode }) => {
const [toggles, setToggles] = useState<TreeElement[] | null>(null); const [toggles, setToggles] = useState<TreeElement[] | null>(null);
const [checkedToggles, setCheckedToggles] = useState<ToggleElement | null>( const [checkedToggles, setCheckedToggles] = useState<string[]>([]);
null
); const setChecked = (newValue: string) => {
if (checkedToggles.length === 5) {
const removedChecked = checkedToggles.slice(1);
setCheckedToggles([...removedChecked, newValue]);
} else {
setCheckedToggles([...checkedToggles, newValue]);
}
};
const removeChecked = (value: string) => {
setCheckedToggles(checkedToggles.filter((toggle) => toggle !== value));
};
return ( return (
<LogContext.Provider <LogContext.Provider
value={{ value={{
toggles, toggles,
setToggles, setToggles,
checkedToggles, checkedToggles,
setCheckedToggles, setChecked,
removeChecked,
}} }}
> >
{children} {children}

View File

@ -21,7 +21,8 @@ export interface TreeElement {
} }
const CheckboxTree = () => { const CheckboxTree = () => {
const { toggles, setCheckedToggles, checkedToggles } = useContext(LogContext); const { toggles, setChecked, checkedToggles, removeChecked } =
useContext(LogContext);
const routeMatch = useRouteMatch([ const routeMatch = useRouteMatch([
routes.installations + routes.list + routes.log + ":id", routes.installations + routes.list + routes.log + ":id",
]); ]);
@ -30,29 +31,17 @@ const CheckboxTree = () => {
return element.children.length > 0 ? renderTree(element.children) : null; return element.children.length > 0 ? renderTree(element.children) : null;
}; };
const handleCheckChildren = (children: TreeElement[], checked?: boolean) => {
if (children.length > 0) {
children.forEach((child) => {
setCheckedToggles((prevState) => {
return {
...prevState,
[child.id]: !checked,
};
});
if (child.children.length > 0) {
handleCheckChildren(child.children, checked);
}
});
}
};
const handleClick = ( const handleClick = (
event: React.MouseEvent<HTMLButtonElement, MouseEvent>, event: React.MouseEvent<HTMLButtonElement, MouseEvent>,
element: TreeElement, element: TreeElement,
checked?: boolean checked?: string
) => { ) => {
event.stopPropagation(); if (checked) {
handleCheckChildren([element], checked); removeChecked(element.id);
} else {
event.stopPropagation();
setChecked(element.id);
}
}; };
const handleExpandClick = ( const handleExpandClick = (
@ -63,7 +52,7 @@ const CheckboxTree = () => {
const renderTree = (data: TreeElement[]): ReactNode => { const renderTree = (data: TreeElement[]): ReactNode => {
return data.map((element) => { return data.map((element) => {
const checked = checkedToggles?.[element.id]; const checked = checkedToggles.find((toggle) => element.id === toggle);
const splitName = element.name.split("/"); const splitName = element.name.split("/");
return ( return (
<TreeItem <TreeItem
@ -73,10 +62,12 @@ const CheckboxTree = () => {
onClick={handleExpandClick} onClick={handleExpandClick}
label={ label={
<> <>
<Checkbox {element.children.length === 0 && (
checked={checked} <Checkbox
onClick={(e) => handleClick(e, element, checked)} checked={!!checked}
/> onClick={(e) => handleClick(e, element, checked)}
/>
)}
{splitName[splitName.length - 1]} {splitName[splitName.length - 1]}
</> </>
} }

View File

@ -3,7 +3,6 @@ import { DataRecord, RecordSeries } from "../../../dataCache/data";
import { import {
GraphData, GraphData,
createTimes, createTimes,
flattenToggles,
getTreeElements, getTreeElements,
isNumeric, isNumeric,
parseCsv, parseCsv,
@ -11,14 +10,13 @@ import {
transformToBarGraphData, transformToBarGraphData,
} from "../../../util/graph.util"; } from "../../../util/graph.util";
import { TimeRange, TimeSpan, UnixTime } from "../../../dataCache/time"; import { TimeRange, TimeSpan, UnixTime } from "../../../dataCache/time";
import { memo, useContext, useEffect, useMemo, useState } from "react"; import { useCallback, useContext, useEffect, useMemo, useState } from "react";
import { BehaviorSubject, startWith, throttleTime, withLatestFrom } from "rxjs"; import { BehaviorSubject, startWith, throttleTime, withLatestFrom } from "rxjs";
import { S3Access } from "../../../dataCache/S3/S3Access"; import { S3Access } from "../../../dataCache/S3/S3Access";
import DataCache, { FetchResult } from "../../../dataCache/dataCache"; import DataCache, { FetchResult } from "../../../dataCache/dataCache";
import { LogContext } from "../../Context/LogContextProvider"; import { LogContext } from "../../Context/LogContextProvider";
import { isDefined } from "../../../dataCache/utils/maybe"; import { isDefined } from "../../../dataCache/utils/maybe";
import { Data, Layout } from "plotly.js"; import { Data, Layout, PlotRelayoutEvent } from "plotly.js";
import { VariableSizeList as List, areEqual } from "react-window";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from "react-intl";
import DateRangePicker from "./DateRangePicker"; import DateRangePicker from "./DateRangePicker";
@ -27,462 +25,6 @@ import { Alert } from "@mui/material";
const NUMBER_OF_NODES = 100; const NUMBER_OF_NODES = 100;
export const testData = `/AcDc/SystemControl/Alarms;;
/AcDc/SystemControl/CommunicationTimeout;00:00:10;
/AcDc/SystemControl/SystemConfig;AcDcAndDcDc;
/AcDc/SystemControl/ResetAlarmsAndWarnings;False;
/AcDc/SystemControl/TargetSlave;0;
/AcDc/SystemControl/UseSlaveIdForAddressing;False;
/AcDc/SystemControl/ReferenceFrame;Producer;
/AcDc/SystemControl/SlaveErrorHandling;Relaxed;
/AcDc/SystemControl/SubSlaveErrorHandling;Strict;
/AcDc/SystemControl/PowerSetPointActivation;Immediate;
/AcDc/SystemControl/PowerSetPointTrigger;Wait;
/AcDc/SystemControl/DeviceState;Operation;
/AcDc/SystemControl/NumberOfConnectedSlaves;2;
/AcDc/SystemControl/NumberOfConnectedSubSlaves;0;
/AcDc/SystemControl/Warnings;;
/AcDc/Devices/1/Status/Ac/L1/Voltage;0;V
/AcDc/Devices/1/Status/Ac/L1/Current;0;A
/AcDc/Devices/1/Status/Ac/L1/Power/Apparent;0;VA
/AcDc/Devices/1/Status/Ac/L1/Power/Active;0;W
/AcDc/Devices/1/Status/Ac/L1/Power/Reactive;0;var
/AcDc/Devices/1/Status/Ac/L1/Power/Phi;0;rad
/AcDc/Devices/1/Status/Ac/L1/Power/CosPhi;1;
/AcDc/Devices/1/Status/Ac/L2/Voltage;0;V
/AcDc/Devices/1/Status/Ac/L2/Current;0;A
/AcDc/Devices/1/Status/Ac/L2/Power/Apparent;0;VA
/AcDc/Devices/1/Status/Ac/L2/Power/Active;0;W
/AcDc/Devices/1/Status/Ac/L2/Power/Reactive;0;var
/AcDc/Devices/1/Status/Ac/L2/Power/Phi;0;rad
/AcDc/Devices/1/Status/Ac/L2/Power/CosPhi;1;
/AcDc/Devices/1/Status/Ac/L3/Voltage;0;V
/AcDc/Devices/1/Status/Ac/L3/Current;0;A
/AcDc/Devices/1/Status/Ac/L3/Power/Apparent;0;VA
/AcDc/Devices/1/Status/Ac/L3/Power/Active;0;W
/AcDc/Devices/1/Status/Ac/L3/Power/Reactive;0;var
/AcDc/Devices/1/Status/Ac/L3/Power/Phi;0;rad
/AcDc/Devices/1/Status/Ac/L3/Power/CosPhi;1;
/AcDc/Devices/1/Status/Ac/Power/Apparent;0;VA
/AcDc/Devices/1/Status/Ac/Power/Active;0;W
/AcDc/Devices/1/Status/Ac/Power/Reactive;0;var
/AcDc/Devices/1/Status/Ac/Power/Phi;0;rad
/AcDc/Devices/1/Status/Ac/Power/CosPhi;1;
/AcDc/Devices/1/Status/Ac/Frequency;0;Hz
/AcDc/Devices/1/Status/Dc/Voltage;0;V
/AcDc/Devices/1/Status/Dc/Current;0;A
/AcDc/Devices/1/Status/Dc/Power;0;W
/AcDc/Devices/1/Status/PowerLimitedBy;Nothing;
/AcDc/Devices/1/Status/InverterState/Current;Idle;
/AcDc/Devices/1/Status/InverterState/OnLastAlarm;Idle;
/AcDc/Devices/1/Status/ActiveGridType;GridTied400V50Hz;
/AcDc/Devices/1/Status/Voltage/Intern/DcUpperHalf;0;V
/AcDc/Devices/1/Status/Voltage/Intern/DcLowerHalf;0;V
/AcDc/Devices/1/Status/Voltage/Intern/NToPe;0;V
/AcDc/Devices/1/Status/Voltage/Extern/DcUpperHalf;0;V
/AcDc/Devices/1/Status/Voltage/Extern/DcLowerHalf;0;V
/AcDc/Devices/1/Status/Voltage/Extern/NToPe;0;V
/AcDc/Devices/1/Status/Temperature/InletAir;0;°C
/AcDc/Devices/1/Status/Temperature/IgbtL1;0;°C
/AcDc/Devices/1/Status/Temperature/IgbtL2;0;°C
/AcDc/Devices/1/Status/Temperature/IgbtL3;0;°C
/AcDc/Devices/1/Status/Temperature/IgbtBalancer;0;°C
/AcDc/Devices/1/Status/OverloadCapacity/L1;0;%
/AcDc/Devices/1/Status/OverloadCapacity/L2;0;%
/AcDc/Devices/1/Status/OverloadCapacity/L3;0;%
/AcDc/Devices/1/Status/Nominal/AcFrequency;50;Hz
/AcDc/Devices/1/Status/Nominal/AcVoltage;400;V
/AcDc/Devices/1/Status/Nominal/Power;25000;W
/AcDc/Devices/1/Status/Alarms;;
/AcDc/Devices/1/Status/Warnings;;
/AcDc/Devices/1/Control/Ac/PhaseControl;Symmetric;
/AcDc/Devices/1/Control/Ac/GridType;GridTied400V50Hz;
/AcDc/Devices/1/Control/Ac/IslandMode/FrequencyOffset;0;Hz
/AcDc/Devices/1/Control/Ac/IslandMode/VoltageAdjustmentFactor;100;%
/AcDc/Devices/1/Control/Dc/ReferenceVoltage;750;V
/AcDc/Devices/1/Control/Dc/MinVoltage;730;V
/AcDc/Devices/1/Control/Dc/MaxVoltage;770;V
/AcDc/Devices/1/Control/Dc/PrechargeConfig;PrechargeDcWithSystemCtl;
/AcDc/Devices/1/Control/PowerStageEnable;True;
/AcDc/Devices/1/Control/ResetAlarmsAndWarnings;False;
/AcDc/Devices/2/Status/Ac/L1/Voltage;0;V
/AcDc/Devices/2/Status/Ac/L1/Current;0;A
/AcDc/Devices/2/Status/Ac/L1/Power/Apparent;0;VA
/AcDc/Devices/2/Status/Ac/L1/Power/Active;0;W
/AcDc/Devices/2/Status/Ac/L1/Power/Reactive;0;var
/AcDc/Devices/2/Status/Ac/L1/Power/Phi;0;rad
/AcDc/Devices/2/Status/Ac/L1/Power/CosPhi;1;
/AcDc/Devices/2/Status/Ac/L2/Voltage;0;V
/AcDc/Devices/2/Status/Ac/L2/Current;0;A
/AcDc/Devices/2/Status/Ac/L2/Power/Apparent;0;VA
/AcDc/Devices/2/Status/Ac/L2/Power/Active;0;W
/AcDc/Devices/2/Status/Ac/L2/Power/Reactive;0;var
/AcDc/Devices/2/Status/Ac/L2/Power/Phi;0;rad
/AcDc/Devices/2/Status/Ac/L2/Power/CosPhi;1;
/AcDc/Devices/2/Status/Ac/L3/Voltage;0;V
/AcDc/Devices/2/Status/Ac/L3/Current;0;A
/AcDc/Devices/2/Status/Ac/L3/Power/Apparent;0;VA
/AcDc/Devices/2/Status/Ac/L3/Power/Active;0;W
/AcDc/Devices/2/Status/Ac/L3/Power/Reactive;0;var
/AcDc/Devices/2/Status/Ac/L3/Power/Phi;0;rad
/AcDc/Devices/2/Status/Ac/L3/Power/CosPhi;1;
/AcDc/Devices/2/Status/Ac/Power/Apparent;0;VA
/AcDc/Devices/2/Status/Ac/Power/Active;0;W
/AcDc/Devices/2/Status/Ac/Power/Reactive;0;var
/AcDc/Devices/2/Status/Ac/Power/Phi;0;rad
/AcDc/Devices/2/Status/Ac/Power/CosPhi;1;
/AcDc/Devices/2/Status/Ac/Frequency;0;Hz
/AcDc/Devices/2/Status/Dc/Voltage;0;V
/AcDc/Devices/2/Status/Dc/Current;0;A
/AcDc/Devices/2/Status/Dc/Power;0;W
/AcDc/Devices/2/Status/PowerLimitedBy;Nothing;
/AcDc/Devices/2/Status/InverterState/Current;Idle;
/AcDc/Devices/2/Status/InverterState/OnLastAlarm;Idle;
/AcDc/Devices/2/Status/ActiveGridType;GridTied400V50Hz;
/AcDc/Devices/2/Status/Voltage/Intern/DcUpperHalf;0;V
/AcDc/Devices/2/Status/Voltage/Intern/DcLowerHalf;0;V
/AcDc/Devices/2/Status/Voltage/Intern/NToPe;0;V
/AcDc/Devices/2/Status/Voltage/Extern/DcUpperHalf;0;V
/AcDc/Devices/2/Status/Voltage/Extern/DcLowerHalf;0;V
/AcDc/Devices/2/Status/Voltage/Extern/NToPe;0;V
/AcDc/Devices/2/Status/Temperature/InletAir;0;°C
/AcDc/Devices/2/Status/Temperature/IgbtL1;0;°C
/AcDc/Devices/2/Status/Temperature/IgbtL2;0;°C
/AcDc/Devices/2/Status/Temperature/IgbtL3;0;°C
/AcDc/Devices/2/Status/Temperature/IgbtBalancer;0;°C
/AcDc/Devices/2/Status/OverloadCapacity/L1;0;%
/AcDc/Devices/2/Status/OverloadCapacity/L2;0;%
/AcDc/Devices/2/Status/OverloadCapacity/L3;0;%
/AcDc/Devices/2/Status/Nominal/AcFrequency;50;Hz
/AcDc/Devices/2/Status/Nominal/AcVoltage;400;V
/AcDc/Devices/2/Status/Nominal/Power;25000;W
/AcDc/Devices/2/Status/Alarms;;
/AcDc/Devices/2/Status/Warnings;;
/AcDc/Devices/2/Control/Ac/PhaseControl;Symmetric;
/AcDc/Devices/2/Control/Ac/GridType;GridTied400V50Hz;
/AcDc/Devices/2/Control/Ac/IslandMode/FrequencyOffset;0;Hz
/AcDc/Devices/2/Control/Ac/IslandMode/VoltageAdjustmentFactor;100;%
/AcDc/Devices/2/Control/Dc/ReferenceVoltage;750;V
/AcDc/Devices/2/Control/Dc/MinVoltage;730;V
/AcDc/Devices/2/Control/Dc/MaxVoltage;770;V
/AcDc/Devices/2/Control/Dc/PrechargeConfig;PrechargeDcWithSystemCtl;
/AcDc/Devices/2/Control/PowerStageEnable;True;
/AcDc/Devices/2/Control/ResetAlarmsAndWarnings;False;
/AcDc/Alarms;;
/AcDc/Warnings;;
/AcDc/Ac/L1/Voltage;0;V
/AcDc/Ac/L1/Current;0;A
/AcDc/Ac/L1/Power/Apparent;0;VA
/AcDc/Ac/L1/Power/Active;0;W
/AcDc/Ac/L1/Power/Reactive;0;var
/AcDc/Ac/L1/Power/Phi;0;rad
/AcDc/Ac/L1/Power/CosPhi;1;
/AcDc/Ac/L2/Voltage;0;V
/AcDc/Ac/L2/Current;0;A
/AcDc/Ac/L2/Power/Apparent;0;VA
/AcDc/Ac/L2/Power/Active;0;W
/AcDc/Ac/L2/Power/Reactive;0;var
/AcDc/Ac/L2/Power/Phi;0;rad
/AcDc/Ac/L2/Power/CosPhi;1;
/AcDc/Ac/L3/Voltage;0;V
/AcDc/Ac/L3/Current;0;A
/AcDc/Ac/L3/Power/Apparent;0;VA
/AcDc/Ac/L3/Power/Active;0;W
/AcDc/Ac/L3/Power/Reactive;0;var
/AcDc/Ac/L3/Power/Phi;0;rad
/AcDc/Ac/L3/Power/CosPhi;1;
/AcDc/Ac/Power/Apparent;0;VA
/AcDc/Ac/Power/Active;0;W
/AcDc/Ac/Power/Reactive;0;var
/AcDc/Ac/Power/Phi;0;rad
/AcDc/Ac/Power/CosPhi;1;
/AcDc/Ac/Frequency;0;Hz
/AcDc/Dc/Voltage;0;V
/AcDc/Dc/Current;0;A
/AcDc/Dc/Power;0;W
/DcDc/Dc/Link/Voltage;0;V
/DcDc/Dc/Link/Current;0;A
/DcDc/Dc/Link/Power;0;W
/DcDc/Dc/Battery/Voltage;0;V
/DcDc/Dc/Battery/Current;0;A
/DcDc/Dc/Battery/Power;0;W
/DcDc/SystemControl/Alarms;;
/DcDc/SystemControl/CommunicationTimeout;00:00:10;
/DcDc/SystemControl/SystemConfig;DcDcOnly;
/DcDc/SystemControl/ResetAlarmsAndWarnings;False;
/DcDc/SystemControl/TargetSlave;0;
/DcDc/SystemControl/UseSlaveIdForAddressing;False;
/DcDc/SystemControl/ReferenceFrame;Producer;
/DcDc/SystemControl/SlaveErrorHandling;Relaxed;
/DcDc/SystemControl/SubSlaveErrorHandling;Strict;
/DcDc/SystemControl/PowerSetPointActivation;Immediate;
/DcDc/SystemControl/PowerSetPointTrigger;Wait;
/DcDc/SystemControl/DeviceState;Operation;
/DcDc/SystemControl/NumberOfConnectedSlaves;2;
/DcDc/SystemControl/NumberOfConnectedSubSlaves;0;
/DcDc/SystemControl/Warnings;;
/DcDc/Devices/1/Status/Dc/Link/Voltage;0;V
/DcDc/Devices/1/Status/Dc/Link/Current;0;A
/DcDc/Devices/1/Status/Dc/Link/Power;0;W
/DcDc/Devices/1/Status/Dc/Battery/Voltage;0;V
/DcDc/Devices/1/Status/Dc/Battery/Current;0;A
/DcDc/Devices/1/Status/Dc/Battery/Power;0;W
/DcDc/Devices/1/Status/OverloadCapacity;0;%
/DcDc/Devices/1/Status/Temperature/InletAir;0;°C
/DcDc/Devices/1/Status/Temperature/HighVoltageModule;0;°C
/DcDc/Devices/1/Status/Temperature/LowVoltageModule;0;°C
/DcDc/Devices/1/Status/PowerLimitedBy;;
/DcDc/Devices/1/Status/Alarms;;
/DcDc/Devices/1/Status/Warnings;;
/DcDc/Devices/1/Control/Vcc/EndPointCurrent;50;A
/DcDc/Devices/1/Control/Vcc/EndPointVoltage;50;V
/DcDc/Devices/1/Control/Vcc/StartPointCurrent;5;A
/DcDc/Devices/1/Control/VoltageLimits/MinBatteryVoltageAlarm;0;V
/DcDc/Devices/1/Control/VoltageLimits/MaxBatteryVoltageAlarm;60;V
/DcDc/Devices/1/Control/VoltageLimits/MinBatteryVoltage;42;V
/DcDc/Devices/1/Control/VoltageLimits/MaxBatteryVoltage;57;V
/DcDc/Devices/1/Control/DroopControl/ReferenceVoltage;750;V
/DcDc/Devices/1/Control/DroopControl/LowerVoltage;55;V
/DcDc/Devices/1/Control/DroopControl/UpperVoltage;55;V
/DcDc/Devices/1/Control/DroopControl/VoltageDeadband;0;V
/DcDc/Devices/1/Control/CurrentControl/CurrentSetpoint;0;A
/DcDc/Devices/1/Control/CurrentControl/MaxCurrentChangePerMs;100;A
/DcDc/Devices/1/Control/MaxDcPower;5;W
/DcDc/Devices/1/Control/ControlMode;VoltageDroop;
/DcDc/Devices/1/Control/ResetAlarmsAndWarnings;False;
/DcDc/Devices/1/Control/PowerStageEnable;True;
/DcDc/Devices/2/Status/Dc/Link/Voltage;0;V
/DcDc/Devices/2/Status/Dc/Link/Current;0;A
/DcDc/Devices/2/Status/Dc/Link/Power;0;W
/DcDc/Devices/2/Status/Dc/Battery/Voltage;0;V
/DcDc/Devices/2/Status/Dc/Battery/Current;0;A
/DcDc/Devices/2/Status/Dc/Battery/Power;0;W
/DcDc/Devices/2/Status/OverloadCapacity;0;%
/DcDc/Devices/2/Status/Temperature/InletAir;0;°C
/DcDc/Devices/2/Status/Temperature/HighVoltageModule;0;°C
/DcDc/Devices/2/Status/Temperature/LowVoltageModule;0;°C
/DcDc/Devices/2/Status/PowerLimitedBy;;
/DcDc/Devices/2/Status/Alarms;;
/DcDc/Devices/2/Status/Warnings;;
/DcDc/Devices/2/Control/Vcc/EndPointCurrent;50;A
/DcDc/Devices/2/Control/Vcc/EndPointVoltage;50;V
/DcDc/Devices/2/Control/Vcc/StartPointCurrent;5;A
/DcDc/Devices/2/Control/VoltageLimits/MinBatteryVoltageAlarm;0;V
/DcDc/Devices/2/Control/VoltageLimits/MaxBatteryVoltageAlarm;60;V
/DcDc/Devices/2/Control/VoltageLimits/MinBatteryVoltage;42;V
/DcDc/Devices/2/Control/VoltageLimits/MaxBatteryVoltage;57;V
/DcDc/Devices/2/Control/DroopControl/ReferenceVoltage;750;V
/DcDc/Devices/2/Control/DroopControl/LowerVoltage;55;V
/DcDc/Devices/2/Control/DroopControl/UpperVoltage;55;V
/DcDc/Devices/2/Control/DroopControl/VoltageDeadband;0;V
/DcDc/Devices/2/Control/CurrentControl/CurrentSetpoint;0;A
/DcDc/Devices/2/Control/CurrentControl/MaxCurrentChangePerMs;100;A
/DcDc/Devices/2/Control/MaxDcPower;5;W
/DcDc/Devices/2/Control/ControlMode;VoltageDroop;
/DcDc/Devices/2/Control/ResetAlarmsAndWarnings;False;
/DcDc/Devices/2/Control/PowerStageEnable;True;
/DcDc/Alarms;;
/DcDc/Warnings;;
/Battery/Dc/Voltage;51.898;V
/Battery/Dc/Current;0.21000000000000002;A
/Battery/Dc/Power;10.898580000000003;W
/Battery/Eoc;True;
/Battery/Warnings;;
/Battery/Alarms;;
/Battery/Soc;99.9;%
/Battery/Devices/1/Dc/Voltage;51.69;V
/Battery/Devices/1/Dc/Current;0.05;A
/Battery/Devices/1/Dc/Power;2.5845000000000002;W
/Battery/Devices/1/Leds/Blue;Off;
/Battery/Devices/1/Leds/Red;Off;
/Battery/Devices/1/Leds/Green;On;
/Battery/Devices/1/Leds/Amber;Off;
/Battery/Devices/1/Temperatures/Heating;True;
/Battery/Devices/1/Temperatures/Board;46.5;°C
/Battery/Devices/1/Temperatures/Cells/Center;249.9;°C
/Battery/Devices/1/Temperatures/Cells/Left;249.5;°C
/Battery/Devices/1/Temperatures/Cells/Right;249.5;°C
/Battery/Devices/1/Temperatures/State;Operation;
/Battery/Devices/1/ConnectedToDcBus;True;
/Battery/Devices/1/Eoc;True;
/Battery/Devices/1/Warnings;;
/Battery/Devices/1/Alarms;;
/Battery/Devices/1/Soc;100;%
/Battery/Devices/1/MaxChargePower;5418.875;W
/Battery/Devices/1/MaxDischargePower;-4668.75;W
/Battery/Devices/2/Dc/Voltage;51.49;V
/Battery/Devices/2/Dc/Current;0.02;A
/Battery/Devices/2/Dc/Power;1.0298;W
/Battery/Devices/2/Leds/Blue;Off;
/Battery/Devices/2/Leds/Red;Off;
/Battery/Devices/2/Leds/Green;On;
/Battery/Devices/2/Leds/Amber;Off;
/Battery/Devices/2/Temperatures/Heating;True;
/Battery/Devices/2/Temperatures/Board;55;°C
/Battery/Devices/2/Temperatures/Cells/Center;251.4;°C
/Battery/Devices/2/Temperatures/Cells/Left;249.8;°C
/Battery/Devices/2/Temperatures/Cells/Right;254.2;°C
/Battery/Devices/2/Temperatures/State;Operation;
/Battery/Devices/2/ConnectedToDcBus;True;
/Battery/Devices/2/Eoc;True;
/Battery/Devices/2/Warnings;;
/Battery/Devices/2/Alarms;;
/Battery/Devices/2/Soc;100;%
/Battery/Devices/2/MaxChargePower;5398.95;W
/Battery/Devices/2/MaxDischargePower;-4648.900000000001;W
/Battery/Devices/3/Dc/Voltage;52.2;V
/Battery/Devices/3/Dc/Current;0.02;A
/Battery/Devices/3/Dc/Power;1.044;W
/Battery/Devices/3/Leds/Blue;Off;
/Battery/Devices/3/Leds/Red;Off;
/Battery/Devices/3/Leds/Green;On;
/Battery/Devices/3/Leds/Amber;Off;
/Battery/Devices/3/Temperatures/Heating;True;
/Battery/Devices/3/Temperatures/Board;47.5;°C
/Battery/Devices/3/Temperatures/Cells/Center;250.5;°C
/Battery/Devices/3/Temperatures/Cells/Left;249.8;°C
/Battery/Devices/3/Temperatures/Cells/Right;251.4;°C
/Battery/Devices/3/Temperatures/State;Operation;
/Battery/Devices/3/ConnectedToDcBus;True;
/Battery/Devices/3/Eoc;True;
/Battery/Devices/3/Warnings;;
/Battery/Devices/3/Alarms;;
/Battery/Devices/3/Soc;100;%
/Battery/Devices/3/MaxChargePower;5469.95;W
/Battery/Devices/3/MaxDischargePower;-4719.900000000001;W
/Battery/Devices/4/Dc/Voltage;51.94;V
/Battery/Devices/4/Dc/Current;0.03;A
/Battery/Devices/4/Dc/Power;1.5581999999999998;W
/Battery/Devices/4/Leds/Blue;Off;
/Battery/Devices/4/Leds/Red;Off;
/Battery/Devices/4/Leds/Green;On;
/Battery/Devices/4/Leds/Amber;Off;
/Battery/Devices/4/Temperatures/Heating;True;
/Battery/Devices/4/Temperatures/Board;47;°C
/Battery/Devices/4/Temperatures/Cells/Center;250;°C
/Battery/Devices/4/Temperatures/Cells/Left;249.8;°C
/Battery/Devices/4/Temperatures/Cells/Right;252.1;°C
/Battery/Devices/4/Temperatures/State;Operation;
/Battery/Devices/4/ConnectedToDcBus;False;
/Battery/Devices/4/Eoc;True;
/Battery/Devices/4/Warnings;;
/Battery/Devices/4/Alarms;;
/Battery/Devices/4/Soc;99.9;%
/Battery/Devices/4/MaxChargePower;5443.925;W
/Battery/Devices/4/MaxDischargePower;-4693.849999999999;W
/Battery/Devices/5/Dc/Voltage;52.17;V
/Battery/Devices/5/Dc/Current;0.09;A
/Battery/Devices/5/Dc/Power;4.6953;W
/Battery/Devices/5/Leds/Blue;Off;
/Battery/Devices/5/Leds/Red;Off;
/Battery/Devices/5/Leds/Green;On;
/Battery/Devices/5/Leds/Amber;Off;
/Battery/Devices/5/Temperatures/Heating;True;
/Battery/Devices/5/Temperatures/Board;48.5;°C
/Battery/Devices/5/Temperatures/Cells/Center;250.6;°C
/Battery/Devices/5/Temperatures/Cells/Left;249.8;°C
/Battery/Devices/5/Temperatures/Cells/Right;250.8;°C
/Battery/Devices/5/Temperatures/State;Operation;
/Battery/Devices/5/ConnectedToDcBus;True;
/Battery/Devices/5/Eoc;True;
/Battery/Devices/5/Warnings;;
/Battery/Devices/5/Alarms;;
/Battery/Devices/5/Soc;100;%
/Battery/Devices/5/MaxChargePower;5466.775;W
/Battery/Devices/5/MaxDischargePower;-4716.55;W
/GridMeter/Ac/L1/Voltage;243;V
/GridMeter/Ac/L1/Current;-12.360750198364258;A
/GridMeter/Ac/L1/Power/Apparent;3009.25;VA
/GridMeter/Ac/L1/Power/Active;-2969;W
/GridMeter/Ac/L1/Power/Reactive;502;var
/GridMeter/Ac/L1/Power/Phi;2.974096306323614;rad
/GridMeter/Ac/L1/Power/CosPhi;-0.9860052513602484;
/GridMeter/Ac/L2/Voltage;243.60000610351562;V
/GridMeter/Ac/L2/Current;-12.548500061035156;A
/GridMeter/Ac/L2/Power/Apparent;3043;VA
/GridMeter/Ac/L2/Power/Active;-3033;W
/GridMeter/Ac/L2/Power/Reactive;351;var
/GridMeter/Ac/L2/Power/Phi;3.026378172298827;rad
/GridMeter/Ac/L2/Power/CosPhi;-0.9933701504473591;
/GridMeter/Ac/L3/Voltage;244.39999389648438;V
/GridMeter/Ac/L3/Current;-13.57349967956543;A
/GridMeter/Ac/L3/Power/Apparent;3317;VA
/GridMeter/Ac/L3/Power/Active;-3313;W
/GridMeter/Ac/L3/Power/Reactive;-73.25;var
/GridMeter/Ac/L3/Power/Phi;-3.1194863851016974;rad
/GridMeter/Ac/L3/Power/CosPhi;-0.9997556663972327;
/GridMeter/Ac/Power/Apparent;9347.579101697936;VA
/GridMeter/Ac/Power/Active;-9315;W
/GridMeter/Ac/Power/Reactive;779.75;var
/GridMeter/Ac/Power/Phi;3.058078286561564;rad
/GridMeter/Ac/Power/CosPhi;-0.9965147016844159;
/GridMeter/Ac/Frequency;50;Hz
/CriticalLoad/Ac/L1/Voltage;244;V
/CriticalLoad/Ac/L1/Current;0;A
/CriticalLoad/Ac/L1/Power/Apparent;0;VA
/CriticalLoad/Ac/L1/Power/Active;0;W
/CriticalLoad/Ac/L1/Power/Reactive;0;var
/CriticalLoad/Ac/L1/Power/Phi;0;rad
/CriticalLoad/Ac/L1/Power/CosPhi;1;
/CriticalLoad/Ac/L2/Voltage;243;V
/CriticalLoad/Ac/L2/Current;0;A
/CriticalLoad/Ac/L2/Power/Apparent;0;VA
/CriticalLoad/Ac/L2/Power/Active;0;W
/CriticalLoad/Ac/L2/Power/Reactive;0;var
/CriticalLoad/Ac/L2/Power/Phi;0;rad
/CriticalLoad/Ac/L2/Power/CosPhi;1;
/CriticalLoad/Ac/L3/Voltage;245.6999969482422;V
/CriticalLoad/Ac/L3/Current;0;A
/CriticalLoad/Ac/L3/Power/Apparent;0;VA
/CriticalLoad/Ac/L3/Power/Active;0;W
/CriticalLoad/Ac/L3/Power/Reactive;0;var
/CriticalLoad/Ac/L3/Power/Phi;0;rad
/CriticalLoad/Ac/L3/Power/CosPhi;1;
/CriticalLoad/Ac/Power/Apparent;0;VA
/CriticalLoad/Ac/Power/Active;0;W
/CriticalLoad/Ac/Power/Reactive;0;var
/CriticalLoad/Ac/Power/Phi;0;rad
/CriticalLoad/Ac/Power/CosPhi;1;
/CriticalLoad/Ac/Frequency;50;Hz
/Relays/K1AcInIsConnectedToGrid;True;
/Relays/K2AcInIsConnectedToAcOut;True;
/Relays/K3Inverter1IsConnectedToAcOut;True;
/Relays/K3Inverter2IsConnectedToAcOut;True;
/Relays/K3Inverter3IsConnectedToAcOut;True;
/Relays/K3Inverter4IsConnectedToAcOut;True;
/Relays/FiWarning;False;
/Relays/FiError;False;
/Relays/K2ConnectAcInToAcOut;True;
/Relays/K3InvertersAreConnectedToAcOut;True;
/Mppt/Dc/Voltage;772.454;V
/Mppt/Dc/Current;10.655000000000001;A
/Mppt/Dc/Power;8230.497370000001;W
/Mppt/Strings/1/Voltage;690.09;V
/Mppt/Strings/1/Current;3.221;A
/Mppt/Strings/1/Power;2222.7798900000003;W
/Mppt/Strings/2/Voltage;599.549;V
/Mppt/Strings/2/Current;3.23;A
/Mppt/Strings/2/Power;1936.54327;W
/Mppt/Strings/3/Voltage;695.46;V
/Mppt/Strings/3/Current;3.371;A
/Mppt/Strings/3/Power;2344.39566;W
/Mppt/Strings/4/Voltage;623.849;V
/Mppt/Strings/4/Current;2.868;A
/Mppt/Strings/4/Power;1789.198932;W
/Config/MinSoc;20;
/Config/LastEoc;0;
/Config/PConstant;0.5;
/Config/ForceChargePower;1000000;
/Config/ForceDischargePower;-1000000;
/Config/MaxInverterPower;32000;
/Config/GridSetPoint;0;
/Config/SelfDischargePower;200;
/Config/HoldSocZone;1;
/Config/ControllerPConstant;0.5;
/SystemState/Message;Panic: Unknown State!;
/SystemState/Id;100;
/LoadOnDc/Power;100;`;
const s3Access = new S3Access( const s3Access = new S3Access(
"saliomameiringen", "saliomameiringen",
"sos-ch-dk-2", "sos-ch-dk-2",
@ -525,11 +67,9 @@ const ScalarGraph = () => {
timeRange[0].toDate(), timeRange[0].toDate(),
timeRange[timeRange.length - 1].toDate(), timeRange[timeRange.length - 1].toDate(),
]); ]);
const [uiRevision, setUiRevision] = useState(Math.random());
const [plotTitles, setPlotTitles] = useState<string[]>([]); const [plotTitles, setPlotTitles] = useState<string[]>([]);
const { toggles, setToggles, setCheckedToggles, checkedToggles } = const { toggles, setToggles, checkedToggles } = useContext(LogContext);
useContext(LogContext);
const times$ = useMemo(() => new BehaviorSubject(timeRange), []); const times$ = useMemo(() => new BehaviorSubject(timeRange), []);
@ -548,7 +88,6 @@ const ScalarGraph = () => {
if (toggles === null && toggleValues && toggleValues.value) { if (toggles === null && toggleValues && toggleValues.value) {
const treeElements = getTreeElements(toggleValues.value); const treeElements = getTreeElements(toggleValues.value);
setToggles(treeElements); setToggles(treeElements);
setCheckedToggles(flattenToggles(treeElements));
} }
}); });
return () => subscription.unsubscribe(); return () => subscription.unsubscribe();
@ -597,143 +136,118 @@ const ScalarGraph = () => {
); );
}; };
const getCacheSeries = (xaxisRange0: Date, xaxisRange1: Date) => { const getCacheSeries = useCallback(
const times = createTimes( (xaxisRange0: Date, xaxisRange1: Date) => {
TimeRange.fromTimes( const times = createTimes(
UnixTime.fromDate(xaxisRange0), TimeRange.fromTimes(
UnixTime.fromDate(xaxisRange1) UnixTime.fromDate(xaxisRange0),
), UnixTime.fromDate(xaxisRange1)
NUMBER_OF_NODES ),
NUMBER_OF_NODES
);
cache.getSeries(times);
times$.next(times);
},
[cache, times$]
);
const handleRelayout = useCallback(
(params: PlotRelayoutEvent) => {
const xaxisRange0 = params["xaxis.range[0]"];
const xaxisRange1 = params["xaxis.range[1]"];
if (xaxisRange0 && xaxisRange1) {
const range0 = new Date(xaxisRange0);
const range1 = new Date(xaxisRange1);
setRange([range0, range1]);
getCacheSeries(range0, range1);
}
},
[getCacheSeries]
);
const renderGraphs = () => {
if (checkedToggles.length > 0) {
const coordinateTimeSeries = transformToGraphData(timeSeries);
const visibleGraphs = Object.keys(coordinateTimeSeries).filter((path) => {
console.log('checkedToggles',coordinateTimeSeries, checkedToggles)
return checkedToggles.find((toggle) => toggle === path)
}
);
console.log('visibleGraphs', visibleGraphs)
if (visibleGraphs.length > 0) {
return (
<div style={{ marginTop: "20px" }}>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DateRangePicker
setRange={setRange}
range={range}
getCacheSeries={getCacheSeries}
/>
</LocalizationProvider>
{visibleGraphs.map((path) => {
const isScalar = isNumeric(coordinateTimeSeries[path].y[0]);
const data = isScalar
? [
{
...coordinateTimeSeries[path],
type: "scatter",
mode: "lines",
fill: "tozeroy",
},
]
: transformToBarGraphData(coordinateTimeSeries[path]);
const barGraphLayout: Partial<Layout> = !isScalar
? {
bargap: 0,
barmode: "stack",
barnorm: "percent",
}
: {};
console.log("graphdata", coordinateTimeSeries);
return (
<Plot
key={path}
data={data as Data[]}
layout={{
width: 1000,
height: 500,
title: path,
xaxis: {
autorange: false,
range: range,
type: "date",
},
yaxis: {
rangemode: "tozero",
},
...barGraphLayout,
}}
config={{
modeBarButtonsToRemove: [
"lasso2d",
"select2d",
"pan2d",
"autoScale2d",
],
}}
onRelayout={handleRelayout}
/>
);
})}
</div>
);
}
}
return (
<Alert sx={{ mt: 2 }} severity="info">
<FormattedMessage
id="makeASelection"
defaultMessage="Please make a selection on the left"
/>
</Alert>
); );
cache.getSeries(times);
times$.next(times);
}; };
const Row = memo((props: any) => { return <>{renderGraphs()}</>;
const { data, index, style } = props;
const visibleGraphs = Object.keys(data).filter((path) => {
return checkedToggles ? checkedToggles[path] : false;
});
if (data[visibleGraphs[index]]) {
const isScalar = isNumeric(data[visibleGraphs[index]].y[0]);
const graphData = isScalar
? [
{
...data[visibleGraphs[index]],
type: "scatter",
mode: "lines+markers",
fill: "tozeroy",
},
]
: transformToBarGraphData(data[visibleGraphs[index]]);
const barGraphLayout: Partial<Layout> = !isScalar
? {
bargap: 0,
barmode: "stack",
barnorm: "percent",
}
: {};
return (
<div style={style}>
<Plot
key={index}
data={graphData as Data[]}
layout={{
width: 1000,
height: 500,
autosize: true,
title: visibleGraphs[index],
uirevision: uiRevision,
xaxis: {
autorange: false,
range: range,
type: "date",
},
yaxis: {
rangemode: "tozero",
},
...barGraphLayout,
}}
config={{
modeBarButtonsToRemove: [
"lasso2d",
"select2d",
"pan2d",
"autoScale2d",
],
}}
onUpdate={(params) => {
console.log("event onupdate", params);
}}
onSliderChange={(params) => {
console.log("event sliderchange", params);
}}
onRestyle={(params) => {
console.log("event restyle", params);
}}
onRelayout={(params) => {
console.log("event relayout", params);
const xaxisRange0 = params["xaxis.range[0]"];
const xaxisRange1 = params["xaxis.range[1]"];
console.log("relayout", xaxisRange0, xaxisRange1);
if (xaxisRange0 && xaxisRange1) {
console.log("relayout", xaxisRange0, xaxisRange1);
const range0 = new Date(xaxisRange0);
const range1 = new Date(xaxisRange1);
setRange([range0, range1]);
setUiRevision(Math.random());
getCacheSeries(range0, range1);
}
}}
/>
</div>
);
}
return null;
}, areEqual);
if (
checkedToggles &&
Object.keys(checkedToggles).find((toggle) => {
return checkedToggles[toggle];
})
) {
const coordinateTimeSeries = transformToGraphData(timeSeries);
return (
<div style={{ marginTop: "20px" }}>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DateRangePicker
setRange={setRange}
range={range}
getCacheSeries={getCacheSeries}
/>
</LocalizationProvider>
<List
height={1000}
itemCount={
Object.keys(checkedToggles).filter(
(toggle) => checkedToggles[toggle]
).length - 1
}
itemSize={() => 500}
width="100%"
itemData={coordinateTimeSeries}
>
{Row}
</List>
</div>
);
}
return (
<Alert sx={{ mt: 2 }} severity="info">
<FormattedMessage
id="makeASelection"
defaultMessage="Please make a selection on the left"
/>
</Alert>
);
}; };
export default ScalarGraph; export default ScalarGraph;

View File

@ -1,79 +1,79 @@
import { Box } from "@mui/material"; import {Box} from "@mui/material";
import { getBoxColor } from "../../../util/graph.util"; import {getBoxColor} from "../../../util/graph.util";
export type BoxData = { export type BoxData = {
label: string; label: string;
values: (string | number)[]; values: (string | number)[];
unit: string; unit: string;
}; };
export type TopologyBoxProps = { export type TopologyBoxProps = {
title?: string; title?: string;
data?: BoxData; data?: BoxData;
}; };
const isInt = (value: number) => { const isInt = (value: number) => {
return value % 1 === 0; return value % 1 === 0;
}; };
export const BOX_SIZE = 85; export const BOX_SIZE = 85;
const TopologyBox = (props: TopologyBoxProps) => { const TopologyBox = (props: TopologyBoxProps) => {
const { titleColor, boxColor } = getBoxColor(props.title); const {titleColor, boxColor} = getBoxColor(props.title);
if (props.title === "Battery") console.log(props.data?.values, "data"); return (
return ( <Box
<Box sx={{
sx={{ visibility: props.title ? "visible" : "hidden",
visibility: props.title ? "visible" : "hidden", height: BOX_SIZE + "px",
height: BOX_SIZE + "px", width: BOX_SIZE + "px",
width: BOX_SIZE + "px", borderRadius: "4px",
borderRadius: "4px", color: "white",
color: "white", }}
}} >
> <p
<p style={{
style={{ marginBlockStart: "0",
marginBlockStart: "0", marginBlockEnd: "0",
marginBlockEnd: "0", backgroundColor: titleColor,
backgroundColor: titleColor, padding: "5px",
padding: "5px", borderTopLeftRadius: "4px",
borderTopLeftRadius: "4px", borderTopRightRadius: "4px",
borderTopRightRadius: "4px", display: "flex",
display: "flex", justifyContent: "center",
justifyContent: "center", }}
}} >
> {props.title}
{props.title} </p>
</p> <div
<div style={{
style={{ backgroundColor: boxColor,
backgroundColor: boxColor, borderBottomLeftRadius: "4px",
borderBottomLeftRadius: "4px", borderBottomRightRadius: "4px",
borderBottomRightRadius: "4px", padding: "5px",
padding: "5px", height: "51px",
height: "51px", }}
}} >
> {props.data && (
{props.data && ( <>
<> {props.data.values.map((value, index) => {
{props.data.values.map((value, index) => { return (
return ( <p
<p key={props.title + '-' + index}
style={{ marginBlockStart: "0", marginBlockEnd: "2px" }} style={{marginBlockStart: "0", marginBlockEnd: "2px"}}
// eslint-disable-next-line formatjs/no-literal-string-in-jsx // eslint-disable-next-line formatjs/no-literal-string-in-jsx
>{`${ >{`${
props.data && props.data.values.length === 3 props.data && props.data.values.length === 3
? "L" + (index + 1) + " " ? "L" + (index + 1) + " "
: "" : ""
}${ }${
!isInt(Number(value)) ? Number(value).toPrecision(4) : value !isInt(Number(value)) ? Number(value).toPrecision(4) : value
}${props.data?.unit}`}</p> }${props.data?.unit}`}</p>
); );
})} })}
</> </>
)} )}
</div> </div>
</Box> </Box>
); );
}; };
export default TopologyBox; export default TopologyBox;

View File

@ -9,7 +9,6 @@ export type TopologyFlowProps = {
hidden?: boolean; hidden?: boolean;
}; };
const TopologyFlow = (props: TopologyFlowProps) => { const TopologyFlow = (props: TopologyFlowProps) => {
console.log("amount", props.amount, props.data?.values);
const length = Math.abs((props.amount ?? 1) * BOX_SIZE); const length = Math.abs((props.amount ?? 1) * BOX_SIZE);
const values = props.data?.values; const values = props.data?.values;
return ( return (

View File

@ -1,7 +1,6 @@
import { Datum, TypedArray } from "plotly.js"; import { Datum, TypedArray } from "plotly.js";
import { import {
TreeElement, TreeElement,
ToggleElement,
} from "../components/Installations/Log/CheckboxTree"; } from "../components/Installations/Log/CheckboxTree";
import { TimeRange, UnixTime } from "../dataCache/time"; import { TimeRange, UnixTime } from "../dataCache/time";
import { DataPoint, DataRecord } from "../dataCache/data"; import { DataPoint, DataRecord } from "../dataCache/data";
@ -143,7 +142,6 @@ export const extractTopologyValues = (
const values = topologyPaths[topologyKey as keyof TopologyValues].map( const values = topologyPaths[topologyKey as keyof TopologyValues].map(
(topologyPath) => timeSeriesValue[topologyPath] (topologyPath) => timeSeriesValue[topologyPath]
); );
console.log("values", values, topologyKey);
switch (topologyKey as keyof TopologyValues) { switch (topologyKey as keyof TopologyValues) {
case "gridToAcInConnection": case "gridToAcInConnection":
topologyValues = [ topologyValues = [
@ -153,7 +151,6 @@ export const extractTopologyValues = (
default: default:
topologyValues = values.map((element) => element.value); topologyValues = values.map((element) => element.value);
} }
console.log("topologyValues", topologyValues);
return { return {
...acc, ...acc,
[topologyKey]: { [topologyKey]: {
@ -198,10 +195,11 @@ export const parseCsv = (text: string): DataRecord => {
.map((l) => { .map((l) => {
return l.split(";"); return l.split(";");
}); });
const x = y const x = y
.map((fields) => { .map((fields) => {
if (isNaN(Number(fields[1]))) { if (fields[0] === "/AcDc/Warnings")
console.log("warnings", fields[1], isNaN(+fields[1]));
if (isNaN(Number(fields[1])) || fields[1] === "") {
return { [fields[0]]: { value: fields[1], unit: fields[2] } }; return { [fields[0]]: { value: fields[1], unit: fields[2] } };
} }
return { [fields[0]]: { value: parseFloat(fields[1]), unit: fields[2] } }; return { [fields[0]]: { value: parseFloat(fields[1]), unit: fields[2] } };
@ -210,17 +208,6 @@ export const parseCsv = (text: string): DataRecord => {
return x; return x;
}; };
export const flattenToggles = (toggles: TreeElement[]): ToggleElement => {
return toggles.reduce((acc, current) => {
if (current.children.length > 0) {
acc[current.id] = false;
return { ...acc, ...flattenToggles(current.children) };
}
acc[current.id] = false;
return acc;
}, {} as ToggleElement);
};
export const insertTreeElements = ( export const insertTreeElements = (
children: TreeElement[] = [], children: TreeElement[] = [],
[head, ...tail]: string[] [head, ...tail]: string[]
@ -291,7 +278,7 @@ export const transformToBarGraphData = (data: GraphCoordinates) => {
marker: { color: stringToColor(split) }, marker: { color: stringToColor(split) },
type: "bar", type: "bar",
name: split, name: split,
showlegend: !foundName, showlegend: split.length > 0 ? !foundName : false,
} as any; } as any;
}); });
} }