[WIP] somehow functional topology view, but with fake data

This commit is contained in:
Sina Blattmann 2023-06-12 13:39:43 +02:00
parent ee40a4d544
commit a9d95fd71e
11 changed files with 992 additions and 20 deletions

View File

@ -42,6 +42,7 @@
"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",
@ -56,6 +57,7 @@
"devDependencies": { "devDependencies": {
"@formatjs/cli": "^6.0.3", "@formatjs/cli": "^6.0.3",
"@types/react-plotly.js": "^2.6.0", "@types/react-plotly.js": "^2.6.0",
"@types/react-window": "^1.8.5",
"eslint-plugin-formatjs": "^4.10.1" "eslint-plugin-formatjs": "^4.10.1"
} }
}, },
@ -6522,6 +6524,15 @@
"@types/react": "*" "@types/react": "*"
} }
}, },
"node_modules/@types/react-window": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@types/react-window/-/react-window-1.8.5.tgz",
"integrity": "sha512-V9q3CvhC9Jk9bWBOysPGaWy/Z0lxYcTXLtLipkt2cnRj1JOSFNF7wqGpkScSXMgBwC+fnVRg/7shwgddBG5ICw==",
"dev": true,
"dependencies": {
"@types/react": "*"
}
},
"node_modules/@types/resolve": { "node_modules/@types/resolve": {
"version": "1.17.1", "version": "1.17.1",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
@ -17188,6 +17199,11 @@
"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",
@ -20569,6 +20585,22 @@
"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",
@ -29830,6 +29862,15 @@
"@types/react": "*" "@types/react": "*"
} }
}, },
"@types/react-window": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@types/react-window/-/react-window-1.8.5.tgz",
"integrity": "sha512-V9q3CvhC9Jk9bWBOysPGaWy/Z0lxYcTXLtLipkt2cnRj1JOSFNF7wqGpkScSXMgBwC+fnVRg/7shwgddBG5ICw==",
"dev": true,
"requires": {
"@types/react": "*"
}
},
"@types/resolve": { "@types/resolve": {
"version": "1.17.1", "version": "1.17.1",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
@ -37982,6 +38023,11 @@
"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",
@ -40301,6 +40347,15 @@
"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,6 +37,7 @@
"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",
@ -84,6 +85,7 @@
"devDependencies": { "devDependencies": {
"@formatjs/cli": "^6.0.3", "@formatjs/cli": "^6.0.3",
"@types/react-plotly.js": "^2.6.0", "@types/react-plotly.js": "^2.6.0",
"@types/react-window": "^1.8.5",
"eslint-plugin-formatjs": "^4.10.1" "eslint-plugin-formatjs": "^4.10.1"
} }
} }

View File

@ -6,6 +6,7 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
import ChevronRightIcon from "@mui/icons-material/ChevronRight"; import ChevronRightIcon from "@mui/icons-material/ChevronRight";
import useRouteMatch from "../../../hooks/useRouteMatch"; import useRouteMatch from "../../../hooks/useRouteMatch";
import routes from "../../../routes.json"; import routes from "../../../routes.json";
import React from "react";
export interface ToggleElement { export interface ToggleElement {
[key: string]: boolean; [key: string]: boolean;
@ -58,6 +59,7 @@ const CheckboxTree = () => {
) => { ) => {
event.stopPropagation(); event.stopPropagation();
}; };
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?.[element.id];

View File

@ -3,6 +3,7 @@ import { Button } from "@mui/material";
import { UnixTime, TimeSpan } from "../../../dataCache/time"; import { UnixTime, TimeSpan } from "../../../dataCache/time";
import { createTimes } from "../../../util/graph.util"; import { createTimes } from "../../../util/graph.util";
import { import {
DatePicker,
DateTimePicker, DateTimePicker,
DateTimeValidationError, DateTimeValidationError,
LocalizationProvider, LocalizationProvider,
@ -52,9 +53,9 @@ const DateRangePicker = (props: DateRangePickerProps) => {
</Button> </Button>
</div> </div>
<LocalizationProvider dateAdapter={AdapterDayjs}> <LocalizationProvider dateAdapter={AdapterDayjs}>
<DateTimePicker <DatePicker
disableFuture disableFuture
maxDateTime={dayjs(range[1])} maxDate={dayjs(range[1])}
label="From date" label="From date"
value={dayjs(range[0])} value={dayjs(range[0])}
onChange={(newValue) => { onChange={(newValue) => {
@ -73,9 +74,9 @@ const DateRangePicker = (props: DateRangePickerProps) => {
}, },
}} }}
/> />
<DateTimePicker <DatePicker
disableFuture disableFuture
minDateTime={dayjs(range[0])} minDate={dayjs(range[0])}
label="To date" label="To date"
value={dayjs(range[1])} value={dayjs(range[1])}
sx={{ sx={{

View File

@ -1,8 +1,101 @@
import React from "react"; import React from "react";
import ScalarGraph from "./ScalarGraph"; import ScalarGraph, { testData } from "./ScalarGraph";
import TopologyColumn from "./TopologyColumn";
import { Box } from "@mui/material";
import { extractTopologyValues, parseCsv } from "../../../util/graph.util";
import { UnixTime } from "../../../dataCache/time";
const Log = () => { const Log = () => {
return <ScalarGraph />; const values = extractTopologyValues({
time: UnixTime.fromTicks(192384239),
value: parseCsv(testData),
});
if (values) {
return (
<>
<Box
sx={{
display: "flex",
flexDirection: "row",
width: "1000px",
overflow: "auto",
padding: 2,
}}
>
<div>
<TopologyColumn
centerBox={{
title: "Grid",
data: values.acInBus,
connectionData: values.gridToAcIn,
}}
/>
</div>
<div>
<TopologyColumn
centerBox={{
title: "AcInBus",
data: values.acInBus,
connectionData: values.dcBusToDcDc,
}}
/>
</div>
<div>
<TopologyColumn
centerBox={{
title: "AcOutBus",
data: values.acOutBus,
connectionData: values.dcBusToDcDc,
}}
/>
</div>
<div>
<TopologyColumn
centerBox={{
title: "Inverter",
data: values.acOutBus,
connectionData: values.dcBusToDcDc,
}}
/>
</div>
<div>
<TopologyColumn
topBox={{
title: "MPPT",
data: values.acOutBus,
connectionData: values.mpptToDcBus,
}}
centerBox={{
title: "DcBus",
data: values.acOutBus,
connectionData: values.dcBusToDcDc,
}}
/>
</div>
<div>
<TopologyColumn
centerBox={{
title: "DcDc",
data: values.acOutBus,
connectionData: values.dcDCToBattery,
}}
/>
</div>
<div>
<TopologyColumn
centerBox={{
title: "Battery",
data: values.acOutBus,
}}
/>
</div>
</Box>
<ScalarGraph />
</>
);
}
return null;
}; };
export default Log; export default Log;

View File

@ -11,26 +11,476 @@ 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 { useContext, useEffect, useMemo, useState } from "react"; import { memo, 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 } from "plotly.js";
import { Alert } from "@mui/material"; import { VariableSizeList as List, areEqual } from "react-window";
import DateRangePicker from "./DateRangePicker";
import { LocalizationProvider } from "@mui/x-date-pickers";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import { FormattedMessage } from "react-intl";
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;`;
const ScalarGraph = () => { const ScalarGraph = () => {
const timeRange = createTimes( const timeRange = createTimes(
UnixTime.now() /* .fromTicks(1682085650) */ UnixTime.now() /* .fromTicks(1682085650) */
.earlier(TimeSpan.fromDays(14)) .rangeBefore(TimeSpan.fromDays(7)),
.rangeBefore(TimeSpan.fromDays(4)),
NUMBER_OF_NODES NUMBER_OF_NODES
); );
const [timeSeries, setTimeSeries] = useState<RecordSeries>([]); const [timeSeries, setTimeSeries] = useState<RecordSeries>([]);
@ -38,7 +488,6 @@ 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 [uiRevision, setUiRevision] = useState(Math.random());
const [plotTitles, setPlotTitles] = useState<string[]>([]); const [plotTitles, setPlotTitles] = useState<string[]>([]);
@ -66,6 +515,7 @@ const ScalarGraph = () => {
.subscribe(([_, times]) => { .subscribe(([_, times]) => {
const timeSeries = cache.getSeries(times); const timeSeries = cache.getSeries(times);
setTimeSeries(timeSeries); setTimeSeries(timeSeries);
const toggleValues = timeSeries.find((timeStamp) => timeStamp.value); const toggleValues = timeSeries.find((timeStamp) => timeStamp.value);
if (toggles === null && toggleValues && toggleValues.value) { if (toggles === null && toggleValues && toggleValues.value) {
const treeElements = getTreeElements(toggleValues.value); const treeElements = getTreeElements(toggleValues.value);
@ -105,6 +555,7 @@ const ScalarGraph = () => {
const transformToGraphData = (input: RecordSeries): GraphData => { const transformToGraphData = (input: RecordSeries): GraphData => {
const transformedObject: any = {}; const transformedObject: any = {};
input.forEach((item) => { input.forEach((item) => {
if (isDefined(item.value)) { if (isDefined(item.value)) {
Object.keys(item.value).forEach((key) => { Object.keys(item.value).forEach((key) => {
@ -154,7 +605,80 @@ const ScalarGraph = () => {
times$.next(times); times$.next(times);
}; };
const renderGraphs = () => { const Row = memo((props: any) => {
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",
}
: {};
if (!isScalar) {
console.log("graphData", data[visibleGraphs[index]]);
}
return (
<div style={style}>
<Plot
key={index}
data={graphData as Data[]}
layout={{
width: 1000,
height: 500,
title: visibleGraphs[index],
uirevision: uiRevision,
xaxis: {
autorange: false,
range: range,
type: "date",
},
yaxis: {
rangemode: "tozero",
},
...barGraphLayout,
}}
config={{
modeBarButtonsToRemove: [
"lasso2d",
"select2d",
"pan2d",
"autoScale2d",
],
}}
onRelayout={(params) => {
const xaxisRange0 = params["xaxis.range[0]"];
const xaxisRange1 = params["xaxis.range[1]"];
if (xaxisRange0 && xaxisRange1) {
setRange([new Date(xaxisRange0), new Date(xaxisRange1)]);
setUiRevision(Math.random());
getCacheSeries(xaxisRange0, xaxisRange1);
}
}}
/>
</div>
);
}
return null;
}, areEqual);
/* const renderGraphs = () => {
if (checkedToggles) { if (checkedToggles) {
const coordinateTimeSeries = transformToGraphData(timeSeries); const coordinateTimeSeries = transformToGraphData(timeSeries);
const visibleGraphs = Object.keys(coordinateTimeSeries).filter((path) => { const visibleGraphs = Object.keys(coordinateTimeSeries).filter((path) => {
@ -241,7 +765,29 @@ const ScalarGraph = () => {
</Alert> </Alert>
); );
} }
}; }; */
return <>{renderGraphs()}</>; if (checkedToggles) {
const coordinateTimeSeries = transformToGraphData(timeSeries);
console.log(
"length",
Object.keys(checkedToggles).filter((toggle) => checkedToggles[toggle])
.length
);
return (
<List
height={1000}
itemCount={
Object.keys(checkedToggles).filter((toggle) => checkedToggles[toggle])
.length
}
itemSize={() => 500}
width={1000}
itemData={coordinateTimeSeries}
>
{Row}
</List>
);
}
return null;
}; };
export default ScalarGraph; export default ScalarGraph;

View File

@ -0,0 +1,39 @@
import { Box } from "@mui/material";
export type BoxData = {
label: string;
values: (string | number)[];
unit: string;
};
export type TopologyBoxProps = {
title?: string;
data?: BoxData[];
connectionData?: BoxData[];
};
export const BOX_SIZE = 150;
const TopologyBox = (props: TopologyBoxProps) => {
console.log("boxdata", props.data);
return (
<Box
sx={{
border: "1px solid grey",
visibility: props.title ? "visible" : "hidden",
height: BOX_SIZE + "px",
width: BOX_SIZE + "px",
borderRadius: "4px",
}}
>
<Box sx={{ padding: "5px" }}>
{props.title}
{props.data &&
props.data.map((el) => (
<p>{`${el.label} ${el.values} ${el.unit}`}</p>
))}
</Box>
</Box>
);
};
export default TopologyBox;

View File

@ -0,0 +1,50 @@
import { Box } from "@mui/material";
import TopologyBox, { TopologyBoxProps } from "./ToplogyBox";
import TopologyFlow from "./TopologyFlow";
type TopologyColumnProps = {
topBox?: TopologyBoxProps;
centerBox?: TopologyBoxProps;
bottomBox?: TopologyBoxProps;
};
const TopologyColumn = (props: TopologyColumnProps) => {
return (
<Box
sx={{
display: "flex",
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
alignContent: "space-between",
}}
>
<div>
<TopologyBox {...props.topBox} />
<TopologyFlow
orientation="vertical"
amount={0.5}
hidden={!props.topBox}
data={props.topBox?.connectionData}
/>
<TopologyBox {...props.centerBox} />
<TopologyFlow
orientation="vertical"
amount={0.7}
hidden={!props.bottomBox}
data={props.bottomBox?.connectionData}
/>
<TopologyBox {...props.bottomBox} />
</div>
<div>
<TopologyFlow
orientation="horizontal"
amount={0.1}
hidden={!props.centerBox}
data={props.centerBox?.connectionData}
/>
</div>
</Box>
);
};
export default TopologyColumn;

View File

@ -0,0 +1,74 @@
@keyframes flow {
0% {
left: -10px;
}
100% {
left: 110%;
}
}
.container {
position: relative;
width: 150px;
height: 150px;
overflow: hidden;
}
.dot {
position: absolute;
width: 10px;
height: 10px;
border-radius: 50%;
background-color: #ffffff;
box-shadow: 0 0 5px #ffffff;
animation: flow 4s linear infinite;
}
.dot:nth-child(2) {
animation-delay: 0.5s;
top: 75%;
}
.dot:nth-child(3) {
animation-delay: 1s;
top: 25%;
}
.dot:nth-child(4) {
animation-delay: 1.5s;
top: 55%;
}
.dot:nth-child(5) {
animation-delay: 2s;
top: 5%;
}
.dot:nth-child(6) {
animation-delay: 2.5s;
top: 85%;
}
.dot:nth-child(7) {
animation-delay: 0.5s;
top: 10%;
}
.dot:nth-child(8) {
animation-delay: 1s;
top: 20%;
}
.dot:nth-child(9) {
animation-delay: 1.5s;
top: 30%;
}
.dot:nth-child(10) {
animation-delay: 2s;
top: 60%;
}
.dot:nth-child(11) {
animation-delay: 2.5s;
top: 90%;
}

View File

@ -0,0 +1,49 @@
import { Box } from "@mui/material";
import { BOX_SIZE, BoxData } from "./ToplogyBox";
import "./TopologyFlow.scss";
type TopologyFlowProps = {
orientation: "vertical" | "horizontal";
amount: number;
data?: BoxData[];
hidden?: boolean;
};
const TopologyFlow = (props: TopologyFlowProps) => {
const length = Math.abs(props.amount * BOX_SIZE);
console.log("props", props.data);
return (
<>
{props.data?.map((value) => value.values)}
<Box
sx={{
width: props.orientation === "horizontal" ? BOX_SIZE : length,
height: props.orientation === "vertical" ? BOX_SIZE : length,
backgroundColor: "grey",
visibility: props.hidden || !props.data ? "hidden" : "visible",
}}
>
<div
className="container"
style={{
transform: props.orientation === "vertical" ? "rotate(90deg)" : "",
}}
>
<div className="data-flow">
<div className="dot"></div>
<div className="dot"></div>
<div className="dot"></div>
<div className="dot"></div>
<div className="dot"></div>
<div className="dot"></div>
<div className="dot"></div>
<div className="dot"></div>
<div className="dot"></div>
<div className="dot"></div>
</div>
</div>
</Box>
</>
);
};
export default TopologyFlow;

View File

@ -4,7 +4,9 @@ import {
ToggleElement, ToggleElement,
} from "../components/Installations/Log/CheckboxTree"; } from "../components/Installations/Log/CheckboxTree";
import { TimeRange, UnixTime } from "../dataCache/time"; import { TimeRange, UnixTime } from "../dataCache/time";
import { DataRecord } from "../dataCache/data"; import { DataPoint, DataRecord } from "../dataCache/data";
import { isDefined } from "../dataCache/utils/maybe";
import { BoxData } from "../components/Installations/Log/ToplogyBox";
export interface GraphCoordinates { export interface GraphCoordinates {
x: Datum[] | Datum[][] | TypedArray; x: Datum[] | Datum[][] | TypedArray;
@ -33,7 +35,66 @@ export interface GraphData {
[path: string]: GraphCoordinates; [path: string]: GraphCoordinates;
} }
export type TopologyValues = {
gridToAcIn: BoxData[];
acInBus: BoxData[];
acOutBus: BoxData[];
dcBus: BoxData[];
mpptToDcBus: BoxData[];
dcBusToDcDc: BoxData[];
dcDCToBattery: BoxData[];
battery: BoxData[];
};
export const extractTopologyValues = (
timeSeriesData: DataPoint
): TopologyValues | null => {
const timeSeriesValue = timeSeriesData.value;
if (isDefined(timeSeriesValue)) {
return Object.keys(topologyValues).reduce((acc, topologyKey) => {
const values = topologyValues[topologyKey].map(
(topologyPath) => timeSeriesValue[topologyPath]
);
console.log("values", values);
return {
...acc,
[topologyKey]: [
{
values:
topologyKey === "gridToAcIn"
? [values.reduce((acc, curr) => Number(acc) + Number(curr))]
: values,
label: topologyKey.split("/").pop(),
unit: "V",
} as BoxData,
],
};
}, {} as TopologyValues);
}
return null;
};
export const topologyValues: { [key: string]: string[] } = {
gridToAcIn: [
"/GridMeter/Ac/L1/Power/Apparent",
"/GridMeter/Ac/L2/Power/Apparent",
"/GridMeter/Ac/L3/Power/Apparent",
],
acInBus: ["/GridMeter/Ac/L2/Voltage"],
acOutBus: [
"/AcDc/Ac/L1/Voltage",
"/AcDc/Ac/L2/Voltage",
"/AcDc/Ac/L3/Voltage",
],
dcBus: ["/AcDc/Dc/Voltage"],
mpptToDcBus: ["/Mppt/Dc/Power"],
dcBusToDcDc: ["/DcDc/Dc/Link/Power"],
dcDCToBattery: ["/DcDc/Dc/Battery/Power"],
battery: ["/Battery/Soc", "/Battery/Dc/Voltage"],
};
export const parseCsv = (text: string) => { export const parseCsv = (text: string) => {
console.log("split", text.split(/\r?\n/));
const y = text const y = text
.split(/\r?\n/) .split(/\r?\n/)
.filter((split) => split.length > 0) .filter((split) => split.length > 0)
@ -98,7 +159,7 @@ export const flattenBarGraphData = (arr: any): GraphCoordinates[] => {
export const stringToColor = (str: string) => { export const stringToColor = (str: string) => {
if (str.length === 0) { if (str.length === 0) {
return "#FFFFFF"; return "rgba(0,0,0,0)";
} }
let hash = 0; let hash = 0;
for (let i = 0; i < str.length; i++) { for (let i = 0; i < str.length; i++) {