[WIP] adjustments to topology
This commit is contained in:
parent
a9d95fd71e
commit
3a4c768074
|
@ -4,7 +4,6 @@ import { UnixTime, TimeSpan } from "../../../dataCache/time";
|
||||||
import { createTimes } from "../../../util/graph.util";
|
import { createTimes } from "../../../util/graph.util";
|
||||||
import {
|
import {
|
||||||
DatePicker,
|
DatePicker,
|
||||||
DateTimePicker,
|
|
||||||
DateTimeValidationError,
|
DateTimeValidationError,
|
||||||
LocalizationProvider,
|
LocalizationProvider,
|
||||||
} from "@mui/x-date-pickers";
|
} from "@mui/x-date-pickers";
|
||||||
|
|
|
@ -1,101 +1,14 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import ScalarGraph, { testData } from "./ScalarGraph";
|
import ScalarGraph from "./ScalarGraph";
|
||||||
import TopologyColumn from "./TopologyColumn";
|
import TopologyView from "./TopologyView";
|
||||||
import { Box } from "@mui/material";
|
|
||||||
import { extractTopologyValues, parseCsv } from "../../../util/graph.util";
|
|
||||||
import { UnixTime } from "../../../dataCache/time";
|
|
||||||
|
|
||||||
const Log = () => {
|
const Log = () => {
|
||||||
const values = extractTopologyValues({
|
return (
|
||||||
time: UnixTime.fromTicks(192384239),
|
<>
|
||||||
value: parseCsv(testData),
|
<TopologyView />
|
||||||
});
|
<ScalarGraph />
|
||||||
|
</>
|
||||||
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;
|
||||||
|
|
|
@ -641,6 +641,7 @@ const ScalarGraph = () => {
|
||||||
layout={{
|
layout={{
|
||||||
width: 1000,
|
width: 1000,
|
||||||
height: 500,
|
height: 500,
|
||||||
|
autosize: true,
|
||||||
title: visibleGraphs[index],
|
title: visibleGraphs[index],
|
||||||
uirevision: uiRevision,
|
uirevision: uiRevision,
|
||||||
xaxis: {
|
xaxis: {
|
||||||
|
@ -781,7 +782,7 @@ const ScalarGraph = () => {
|
||||||
.length
|
.length
|
||||||
}
|
}
|
||||||
itemSize={() => 500}
|
itemSize={() => 500}
|
||||||
width={1000}
|
width="100%"
|
||||||
itemData={coordinateTimeSeries}
|
itemData={coordinateTimeSeries}
|
||||||
>
|
>
|
||||||
{Row}
|
{Row}
|
||||||
|
|
|
@ -9,12 +9,14 @@ export type BoxData = {
|
||||||
export type TopologyBoxProps = {
|
export type TopologyBoxProps = {
|
||||||
title?: string;
|
title?: string;
|
||||||
data?: BoxData[];
|
data?: BoxData[];
|
||||||
connectionData?: BoxData[];
|
};
|
||||||
|
|
||||||
|
const isInt = (value: number) => {
|
||||||
|
return value % 1 === 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const BOX_SIZE = 150;
|
export const BOX_SIZE = 150;
|
||||||
const TopologyBox = (props: TopologyBoxProps) => {
|
const TopologyBox = (props: TopologyBoxProps) => {
|
||||||
console.log("boxdata", props.data);
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
|
@ -26,10 +28,22 @@ const TopologyBox = (props: TopologyBoxProps) => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box sx={{ padding: "5px" }}>
|
<Box sx={{ padding: "5px" }}>
|
||||||
{props.title}
|
<p style={{ marginBlockStart: "2px" }}>{props.title}</p>
|
||||||
{props.data &&
|
{props.data &&
|
||||||
props.data.map((el) => (
|
props.data.map((el) => (
|
||||||
<p>{`${el.label} ${el.values} ${el.unit}`}</p>
|
<div>
|
||||||
|
{el.label}
|
||||||
|
{el.values.map((value) => {
|
||||||
|
return (
|
||||||
|
<p
|
||||||
|
style={{ marginBlockStart: "2px", marginBlockEnd: "2px" }}
|
||||||
|
// eslint-disable-next-line formatjs/no-literal-string-in-jsx
|
||||||
|
>{`${
|
||||||
|
!isInt(Number(value)) ? Number(value).toPrecision(8) : value
|
||||||
|
}${el.unit}`}</p>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
))}
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
import { Box } from "@mui/material";
|
import { Box } from "@mui/material";
|
||||||
import TopologyBox, { TopologyBoxProps } from "./ToplogyBox";
|
import TopologyBox, { TopologyBoxProps } from "./ToplogyBox";
|
||||||
import TopologyFlow from "./TopologyFlow";
|
import TopologyFlow, { TopologyFlowProps } from "./TopologyFlow";
|
||||||
|
|
||||||
type TopologyColumnProps = {
|
type TopologyColumnProps = {
|
||||||
topBox?: TopologyBoxProps;
|
topBox?: TopologyBoxProps;
|
||||||
|
topConnection?: TopologyFlowProps;
|
||||||
centerBox?: TopologyBoxProps;
|
centerBox?: TopologyBoxProps;
|
||||||
|
centerConnection?: TopologyFlowProps;
|
||||||
bottomBox?: TopologyBoxProps;
|
bottomBox?: TopologyBoxProps;
|
||||||
|
bottomConnection?: TopologyFlowProps;
|
||||||
};
|
};
|
||||||
|
|
||||||
const TopologyColumn = (props: TopologyColumnProps) => {
|
const TopologyColumn = (props: TopologyColumnProps) => {
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
|
@ -21,26 +25,23 @@ const TopologyColumn = (props: TopologyColumnProps) => {
|
||||||
<div>
|
<div>
|
||||||
<TopologyBox {...props.topBox} />
|
<TopologyBox {...props.topBox} />
|
||||||
<TopologyFlow
|
<TopologyFlow
|
||||||
|
{...props.topConnection}
|
||||||
orientation="vertical"
|
orientation="vertical"
|
||||||
amount={0.5}
|
|
||||||
hidden={!props.topBox}
|
hidden={!props.topBox}
|
||||||
data={props.topBox?.connectionData}
|
|
||||||
/>
|
/>
|
||||||
<TopologyBox {...props.centerBox} />
|
<TopologyBox {...props.centerBox} />
|
||||||
<TopologyFlow
|
<TopologyFlow
|
||||||
|
{...props.bottomConnection}
|
||||||
orientation="vertical"
|
orientation="vertical"
|
||||||
amount={0.7}
|
|
||||||
hidden={!props.bottomBox}
|
hidden={!props.bottomBox}
|
||||||
data={props.bottomBox?.connectionData}
|
|
||||||
/>
|
/>
|
||||||
<TopologyBox {...props.bottomBox} />
|
<TopologyBox {...props.bottomBox} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<TopologyFlow
|
<TopologyFlow
|
||||||
|
{...props.centerConnection}
|
||||||
orientation="horizontal"
|
orientation="horizontal"
|
||||||
amount={0.1}
|
|
||||||
hidden={!props.centerBox}
|
hidden={!props.centerBox}
|
||||||
data={props.centerBox?.connectionData}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 150px;
|
width: 130px;
|
||||||
height: 150px;
|
height: 130px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,30 +2,35 @@ import { Box } from "@mui/material";
|
||||||
import { BOX_SIZE, BoxData } from "./ToplogyBox";
|
import { BOX_SIZE, BoxData } from "./ToplogyBox";
|
||||||
import "./TopologyFlow.scss";
|
import "./TopologyFlow.scss";
|
||||||
|
|
||||||
type TopologyFlowProps = {
|
export type TopologyFlowProps = {
|
||||||
orientation: "vertical" | "horizontal";
|
orientation?: "vertical" | "horizontal";
|
||||||
amount: number;
|
amount?: number;
|
||||||
|
direction?: "leftToRight" | "rightToLeft";
|
||||||
data?: BoxData[];
|
data?: BoxData[];
|
||||||
hidden?: boolean;
|
hidden?: boolean;
|
||||||
};
|
};
|
||||||
const TopologyFlow = (props: TopologyFlowProps) => {
|
const TopologyFlow = (props: TopologyFlowProps) => {
|
||||||
const length = Math.abs(props.amount * BOX_SIZE);
|
const length = Math.abs((props.amount ?? 1) * (BOX_SIZE - 20));
|
||||||
console.log("props", props.data);
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{props.data?.map((value) => value.values)}
|
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
width: props.orientation === "horizontal" ? BOX_SIZE : length,
|
width: props.orientation === "horizontal" ? BOX_SIZE - 20 : length,
|
||||||
height: props.orientation === "vertical" ? BOX_SIZE : length,
|
height: props.orientation === "vertical" ? BOX_SIZE - 20 : length,
|
||||||
backgroundColor: "grey",
|
backgroundColor: "#f4b3504d",
|
||||||
visibility: props.hidden || !props.data ? "hidden" : "visible",
|
visibility: props.hidden || !props.data ? "hidden" : "visible",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{props.data?.map((value) => value.values)}
|
||||||
<div
|
<div
|
||||||
className="container"
|
className="container"
|
||||||
style={{
|
style={{
|
||||||
transform: props.orientation === "vertical" ? "rotate(90deg)" : "",
|
transform:
|
||||||
|
props.orientation === "vertical"
|
||||||
|
? "rotate(90deg)"
|
||||||
|
: props.direction === "rightToLeft"
|
||||||
|
? "rotate(180deg)"
|
||||||
|
: "",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="data-flow">
|
<div className="data-flow">
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
import { Box } from "@mui/material";
|
||||||
|
import TopologyColumn from "./TopologyColumn";
|
||||||
|
import { UnixTime } from "../../../dataCache/time";
|
||||||
|
import { extractTopologyValues, parseCsv } from "../../../util/graph.util";
|
||||||
|
import { testData } from "./ScalarGraph";
|
||||||
|
|
||||||
|
const TopologyView = () => {
|
||||||
|
const values = extractTopologyValues({
|
||||||
|
time: UnixTime.fromTicks(192384239),
|
||||||
|
value: parseCsv(testData),
|
||||||
|
});
|
||||||
|
console.log("csvValue", parseCsv(testData));
|
||||||
|
if (values) {
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
overflow: "auto",
|
||||||
|
padding: 2,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<TopologyColumn
|
||||||
|
centerBox={{
|
||||||
|
title: "Grid",
|
||||||
|
data: values.acInBus,
|
||||||
|
}}
|
||||||
|
centerConnection={{
|
||||||
|
amount: 0.5,
|
||||||
|
data: values.gridToAcIn,
|
||||||
|
direction: "rightToLeft",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<TopologyColumn
|
||||||
|
centerBox={{
|
||||||
|
title: "AcInBus",
|
||||||
|
data: values.acInBus,
|
||||||
|
}}
|
||||||
|
centerConnection={{
|
||||||
|
amount: 0.5,
|
||||||
|
data: values.gridToAcIn,
|
||||||
|
direction: "leftToRight",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<TopologyColumn
|
||||||
|
centerBox={{
|
||||||
|
title: "AcOutBus",
|
||||||
|
data: values.acOutBus,
|
||||||
|
}}
|
||||||
|
centerConnection={{
|
||||||
|
amount: 0.5,
|
||||||
|
data: values.gridToAcIn,
|
||||||
|
direction: "leftToRight",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<TopologyColumn
|
||||||
|
centerBox={{
|
||||||
|
title: "Inverter",
|
||||||
|
data: values.acOutBus,
|
||||||
|
}}
|
||||||
|
centerConnection={{
|
||||||
|
amount: 0.5,
|
||||||
|
data: values.gridToAcIn,
|
||||||
|
direction: "leftToRight",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<TopologyColumn
|
||||||
|
topBox={{
|
||||||
|
title: "MPPT",
|
||||||
|
data: values.acOutBus,
|
||||||
|
}}
|
||||||
|
topConnection={{
|
||||||
|
amount: 0.5,
|
||||||
|
data: values.gridToAcIn,
|
||||||
|
}}
|
||||||
|
centerBox={{
|
||||||
|
title: "DcBus",
|
||||||
|
data: values.acOutBus,
|
||||||
|
}}
|
||||||
|
centerConnection={{
|
||||||
|
amount: 0.5,
|
||||||
|
data: values.gridToAcIn,
|
||||||
|
direction: "rightToLeft",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<TopologyColumn
|
||||||
|
centerBox={{
|
||||||
|
title: "DcDc",
|
||||||
|
data: values.acOutBus,
|
||||||
|
}}
|
||||||
|
centerConnection={{
|
||||||
|
amount: 0.5,
|
||||||
|
data: values.gridToAcIn,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<TopologyColumn
|
||||||
|
centerBox={{
|
||||||
|
title: "Battery",
|
||||||
|
data: values.acOutBus,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TopologyView;
|
|
@ -1,21 +1,29 @@
|
||||||
import { Maybe } from "yup";
|
import { Maybe } from "yup";
|
||||||
import {Timestamped} from "./types";
|
import { Timestamped } from "./types";
|
||||||
import { isDefined } from "./utils/maybe";
|
import { isDefined } from "./utils/maybe";
|
||||||
|
|
||||||
export type DataRecord = Record<string, number | string>
|
export type DataRecord = Record<string, number | string>;
|
||||||
|
|
||||||
export type DataPoint = Timestamped<Maybe<DataRecord>>
|
export type DataPoint = Timestamped<Maybe<DataRecord>>;
|
||||||
export type RecordSeries = Array<DataPoint>
|
export type RecordSeries = Array<DataPoint>;
|
||||||
export type PointSeries = Array<Timestamped<Maybe<number| string>>>
|
export type PointSeries = Array<Timestamped<Maybe<number | string>>>;
|
||||||
export type DataSeries = Array<Maybe<number| string>>
|
export type DataSeries = Array<Maybe<number | string>>;
|
||||||
|
|
||||||
export function getPoints(recordSeries: RecordSeries, series: keyof DataRecord): PointSeries
|
export function getPoints(
|
||||||
{
|
recordSeries: RecordSeries,
|
||||||
return recordSeries.map(p => ({time: p.time, value: isDefined(p.value) ? p.value[series] : undefined}))
|
series: keyof DataRecord
|
||||||
|
): PointSeries {
|
||||||
|
return recordSeries.map((p) => ({
|
||||||
|
time: p.time,
|
||||||
|
value: isDefined(p.value) ? p.value[series] : undefined,
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getData(recordSeries: RecordSeries, series: keyof DataRecord): DataSeries
|
export function getData(
|
||||||
{
|
recordSeries: RecordSeries,
|
||||||
return recordSeries.map(p => (isDefined(p.value) ? p.value[series] : undefined))
|
series: keyof DataRecord
|
||||||
|
): DataSeries {
|
||||||
|
return recordSeries.map((p) =>
|
||||||
|
isDefined(p.value) ? p.value[series] : undefined
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ export const extractTopologyValues = (
|
||||||
const values = topologyValues[topologyKey].map(
|
const values = topologyValues[topologyKey].map(
|
||||||
(topologyPath) => timeSeriesValue[topologyPath]
|
(topologyPath) => timeSeriesValue[topologyPath]
|
||||||
);
|
);
|
||||||
console.log("values", values);
|
console.log("values", topologyValues);
|
||||||
return {
|
return {
|
||||||
...acc,
|
...acc,
|
||||||
[topologyKey]: [
|
[topologyKey]: [
|
||||||
|
@ -64,7 +64,7 @@ export const extractTopologyValues = (
|
||||||
topologyKey === "gridToAcIn"
|
topologyKey === "gridToAcIn"
|
||||||
? [values.reduce((acc, curr) => Number(acc) + Number(curr))]
|
? [values.reduce((acc, curr) => Number(acc) + Number(curr))]
|
||||||
: values,
|
: values,
|
||||||
label: topologyKey.split("/").pop(),
|
label: topologyValues[topologyKey][0].split("/").pop(),
|
||||||
unit: "V",
|
unit: "V",
|
||||||
} as BoxData,
|
} as BoxData,
|
||||||
],
|
],
|
||||||
|
@ -93,6 +93,14 @@ export const topologyValues: { [key: string]: string[] } = {
|
||||||
battery: ["/Battery/Soc", "/Battery/Dc/Voltage"],
|
battery: ["/Battery/Soc", "/Battery/Dc/Voltage"],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export interface CsvEntry {
|
||||||
|
value: string | number;
|
||||||
|
unit: string;
|
||||||
|
}
|
||||||
|
export interface Csv {
|
||||||
|
[key: string]: CsvEntry;
|
||||||
|
}
|
||||||
|
|
||||||
export const parseCsv = (text: string) => {
|
export const parseCsv = (text: string) => {
|
||||||
console.log("split", text.split(/\r?\n/));
|
console.log("split", text.split(/\r?\n/));
|
||||||
const y = text
|
const y = text
|
||||||
|
|
Loading…
Reference in New Issue