diff --git a/typescript/Frontend/src/components/Installations/Alarms.tsx b/typescript/Frontend/src/components/Installations/Alarms.tsx deleted file mode 100644 index fce927204..000000000 --- a/typescript/Frontend/src/components/Installations/Alarms.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { FormattedMessage } from "react-intl"; - -const Alarms = () => { - return ( -
- -
- ); -}; - -export default Alarms; diff --git a/typescript/Frontend/src/components/Installations/InstallationList.tsx b/typescript/Frontend/src/components/Installations/InstallationList.tsx index 79679e51e..77673bbab 100644 --- a/typescript/Frontend/src/components/Installations/InstallationList.tsx +++ b/typescript/Frontend/src/components/Installations/InstallationList.tsx @@ -42,7 +42,7 @@ const InstallationList = (props: InstallationListProps) => { const routeMatch = useRouteMatch([ routes.installations + routes.list + routes.installation + ":id", - routes.installations + routes.list + routes.alarms + ":id", + routes.installations + routes.list + routes.liveView + ":id", routes.installations + routes.list + routes.log + ":id", ]); diff --git a/typescript/Frontend/src/components/Installations/InstallationTabs.tsx b/typescript/Frontend/src/components/Installations/InstallationTabs.tsx index ea7db5818..0d20be0b5 100644 --- a/typescript/Frontend/src/components/Installations/InstallationTabs.tsx +++ b/typescript/Frontend/src/components/Installations/InstallationTabs.tsx @@ -9,7 +9,7 @@ import { AntTabs, StyledTab } from "../../util/installation.util"; const InstallationTabs = () => { const routeMatch = useRouteMatch([ routes.installations + routes.list + routes.installation + ":id", - routes.installations + routes.list + routes.alarms + ":id", + routes.installations + routes.list + routes.liveView + ":id", routes.installations + routes.list + routes.log + ":id", ]); @@ -40,14 +40,16 @@ const InstallationTabs = () => { to={routes.installation + id} /> { element={} index /> - } /> + } /> } /> diff --git a/typescript/Frontend/src/components/Installations/LiveView.tsx b/typescript/Frontend/src/components/Installations/LiveView.tsx new file mode 100644 index 000000000..7d01b20e7 --- /dev/null +++ b/typescript/Frontend/src/components/Installations/LiveView.tsx @@ -0,0 +1,7 @@ +import TopologyView from "./Log/TopologyView"; + +const LiveView = () => { + return ; +}; + +export default LiveView; diff --git a/typescript/Frontend/src/components/Installations/Log/DateRangePicker.tsx b/typescript/Frontend/src/components/Installations/Log/DateRangePicker.tsx index 329457d3c..8c6971914 100644 --- a/typescript/Frontend/src/components/Installations/Log/DateRangePicker.tsx +++ b/typescript/Frontend/src/components/Installations/Log/DateRangePicker.tsx @@ -10,7 +10,7 @@ import { TimeRange, UnixTime } from "../../../dataCache/time"; interface DateRangePickerProps { setRange: (value: Date[]) => void; range: Date[]; - getCacheSeries: (xaxisRange0: number, xaxisRange1: number) => void; + getCacheSeries: (xaxisRange0: Date, xaxisRange1: Date) => void; } const DateRangePicker = (props: DateRangePickerProps) => { const { setRange, range, getCacheSeries } = props; @@ -23,8 +23,11 @@ const DateRangePicker = (props: DateRangePickerProps) => { ), 100 ); - setRange([timeRange[0].toDate(), timeRange[timeRange.length - 1].toDate()]); - getCacheSeries(timeRange[0].ticks, timeRange[timeRange.length - 1].ticks); + const timeRange0 = timeRange[0].toDate(); + const timeRange1 = timeRange[timeRange.length - 1].toDate(); + + setRange([timeRange0, timeRange1]); + getCacheSeries(timeRange0, timeRange1); }; return ( diff --git a/typescript/Frontend/src/components/Installations/Log/Log.tsx b/typescript/Frontend/src/components/Installations/Log/Log.tsx index 93517caab..d1156f14e 100644 --- a/typescript/Frontend/src/components/Installations/Log/Log.tsx +++ b/typescript/Frontend/src/components/Installations/Log/Log.tsx @@ -1,11 +1,9 @@ import React from "react"; import ScalarGraph from "./ScalarGraph"; -import TopologyView from "./TopologyView"; const Log = () => { return ( <> - ); diff --git a/typescript/Frontend/src/components/Installations/Log/ScalarGraph.tsx b/typescript/Frontend/src/components/Installations/Log/ScalarGraph.tsx index d43f46f72..156227f3e 100644 --- a/typescript/Frontend/src/components/Installations/Log/ScalarGraph.tsx +++ b/typescript/Frontend/src/components/Installations/Log/ScalarGraph.tsx @@ -491,6 +491,7 @@ const s3Access = new S3Access( "f2KtCWN4EHFqtvH2kotdyI0w5SjjdHVPAADdcD3ik8g", "" ); + export const fetchData = ( timestamp: UnixTime ): Promise> => { @@ -516,7 +517,7 @@ export const fetchData = ( const ScalarGraph = () => { const timeRange = createTimes( UnixTime.now() /* .fromTicks(1682085650) */ - .rangeBefore(TimeSpan.fromHours(5)), + .rangeBefore(TimeSpan.fromDays(1)), NUMBER_OF_NODES ); const [timeSeries, setTimeSeries] = useState([]); @@ -596,11 +597,11 @@ const ScalarGraph = () => { ); }; - const getCacheSeries = (xaxisRange0: number, xaxisRange1: number) => { + const getCacheSeries = (xaxisRange0: Date, xaxisRange1: Date) => { const times = createTimes( TimeRange.fromTimes( - UnixTime.fromTicks(xaxisRange0), - UnixTime.fromTicks(xaxisRange1) + UnixTime.fromDate(xaxisRange0), + UnixTime.fromDate(xaxisRange1) ), NUMBER_OF_NODES ); @@ -661,14 +662,29 @@ const ScalarGraph = () => { "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) { - setRange([new Date(xaxisRange0), new Date(xaxisRange1)]); + console.log("relayout", xaxisRange0, xaxisRange1); + const range0 = new Date(xaxisRange0); + const range1 = new Date(xaxisRange1); + + setRange([range0, range1]); setUiRevision(Math.random()); - getCacheSeries(xaxisRange0, xaxisRange1); + getCacheSeries(range0, range1); } }} /> @@ -680,13 +696,13 @@ const ScalarGraph = () => { if ( checkedToggles && - Object.keys(checkedToggles).find((toggle) => checkedToggles[toggle]) + Object.keys(checkedToggles).find((toggle) => { + return checkedToggles[toggle]; + }) ) { - console.log("timeseries", timeSeries); const coordinateTimeSeries = transformToGraphData(timeSeries); - console.log("timeSeries", timeSeries); return ( - <> +
{ itemCount={ Object.keys(checkedToggles).filter( (toggle) => checkedToggles[toggle] - ).length + ).length - 1 } itemSize={() => 500} width="100%" @@ -707,9 +723,10 @@ const ScalarGraph = () => { > {Row} - +
); } + return ( void; - getCacheSeries: (xaxisRange0: number, xaxisRange1: number) => void; + getCacheSeries: (xaxisRange0: Date, xaxisRange1: Date) => void; dayRange: number; children?: React.ReactNode; } @@ -13,19 +13,15 @@ const ShortcutButton = (props: ShortcutButtonProps) => { return ( { - const weekRange = createTimes( + const range = createTimes( UnixTime.now().rangeBefore(TimeSpan.fromDays(props.dayRange)), 100 ); - console.log("weekrange", weekRange[0].ticks); - props.setRange([ - weekRange[0].toDate(), - weekRange[weekRange.length - 1].toDate(), - ]); - props.getCacheSeries( - weekRange[0].ticks, - weekRange[weekRange.length - 1].ticks - ); + const range0 = range[0].toDate(); + const range1 = range[range.length - 1].toDate(); + + props.setRange([range0, range1]); + props.getCacheSeries(range0, range1); }} sx={{ mt: 2, mb: 2, mr: 2 }} > diff --git a/typescript/Frontend/src/components/Installations/Log/TopologyBox.tsx b/typescript/Frontend/src/components/Installations/Log/TopologyBox.tsx index 541a5a0e4..c73b9e3ea 100644 --- a/typescript/Frontend/src/components/Installations/Log/TopologyBox.tsx +++ b/typescript/Frontend/src/components/Installations/Log/TopologyBox.tsx @@ -1,4 +1,5 @@ import { Box } from "@mui/material"; +import { getBoxColor } from "../../../util/graph.util"; export type BoxData = { label: string; @@ -17,6 +18,8 @@ const isInt = (value: number) => { export const BOX_SIZE = 85; const TopologyBox = (props: TopologyBoxProps) => { + const { titleColor, boxColor } = getBoxColor(props.title); + if (props.title === "Battery") console.log(props.data?.values, "data"); return ( { style={{ marginBlockStart: "0", marginBlockEnd: "0", - backgroundColor: "#e74c3c", + backgroundColor: titleColor, padding: "5px", borderTopLeftRadius: "4px", borderTopRightRadius: "4px", + display: "flex", + justifyContent: "center", }} > {props.title}

{props.data && ( <> - {props.data.values.map((value) => { + {props.data.values.map((value, index) => { return (

{`${ + props.data && props.data.values.length === 3 + ? "L" + (index + 1) + " " + : "" + }${ !isInt(Number(value)) ? Number(value).toPrecision(4) : value }${props.data?.unit}`}

); diff --git a/typescript/Frontend/src/components/Installations/Log/TopologyFlow.tsx b/typescript/Frontend/src/components/Installations/Log/TopologyFlow.tsx index 7de1442c6..d3def8fb3 100644 --- a/typescript/Frontend/src/components/Installations/Log/TopologyFlow.tsx +++ b/typescript/Frontend/src/components/Installations/Log/TopologyFlow.tsx @@ -9,6 +9,7 @@ export type TopologyFlowProps = { hidden?: boolean; }; const TopologyFlow = (props: TopologyFlowProps) => { + console.log("amount", props.amount, props.data?.values); const length = Math.abs((props.amount ?? 1) * BOX_SIZE); const values = props.data?.values; return ( @@ -25,7 +26,7 @@ const TopologyFlow = (props: TopologyFlowProps) => { sx={{ width: props.orientation === "horizontal" ? BOX_SIZE : length, height: props.orientation === "vertical" ? BOX_SIZE : length, - backgroundColor: "#f4b3504d", + backgroundColor: "#FFEBCD", visibility: props.hidden || !props.data ? "hidden" : "visible", display: "flex", alignItems: "center", @@ -37,11 +38,16 @@ const TopologyFlow = (props: TopologyFlowProps) => { style={{ position: "absolute", zIndex: 1, + width: BOX_SIZE, + display: "flex", + justifyContent: "center", }} > - {values?.map( - (value) => `${Math.round(value as number)} ${props.data?.unit}` - )} + {values + ?.filter((value) => (value as number) !== 0) + .map( + (value) => `${Math.round(value as number)} ${props.data?.unit}` + )}

{ const [values, setValues] = useState(null); @@ -31,7 +32,7 @@ const TopologyView = () => { ); } }) - .catch((err) => console.log(err)); + .catch((err) => console.error(err)); }, 2000); return () => clearInterval(interval); @@ -66,12 +67,15 @@ const TopologyView = () => {
{ data: values.gridBusToPvOnGridbusConnection, }} topBox={{ - title: "PvOnGridBus", + title: "Pv", }} bottomConnection={{ amount: getAmount( @@ -91,22 +95,35 @@ const TopologyView = () => { data: values.gridBusToLoadOnGridBusConnection, }} bottomBox={{ - title: "LoadOnGridBus", + title: "Load", }} />
{
{ data: values.dcBusToDcDcConnection, }} bottomConnection={{ - amount: 0.2, + amount: getAmount( + highestConnectionValue, + values.dcBusToLoadOnDcConnection.values + ), data: values.dcBusToLoadOnDcConnection, }} bottomBox={{ - title: "LoadOnDc", + title: "Load", }} />
@@ -162,7 +188,7 @@ const TopologyView = () => { { ); } - return null; + return ( + + + + ); }; export default TopologyView; diff --git a/typescript/Frontend/src/lang/de.json b/typescript/Frontend/src/lang/de.json index 037eeab43..295b87a34 100644 --- a/typescript/Frontend/src/lang/de.json +++ b/typescript/Frontend/src/lang/de.json @@ -1,5 +1,5 @@ { - "alarms": "Alarme", + "liveView": "Live Ansicht", "allInstallations": "Alle Installationen", "applyChanges": "Änderungen übernehmen", "country": "Land", diff --git a/typescript/Frontend/src/lang/en.json b/typescript/Frontend/src/lang/en.json index aabb7b8fe..3cbbc6634 100644 --- a/typescript/Frontend/src/lang/en.json +++ b/typescript/Frontend/src/lang/en.json @@ -1,5 +1,5 @@ { - "alarms": "Alarms", + "liveView": "Live view", "allInstallations": "All installations", "applyChanges": "Apply changes", "country": "Country", diff --git a/typescript/Frontend/src/routes.json b/typescript/Frontend/src/routes.json index 27947ff1b..f2ec5fff1 100644 --- a/typescript/Frontend/src/routes.json +++ b/typescript/Frontend/src/routes.json @@ -1,6 +1,6 @@ { "installation": "installation/", - "alarms": "alarms/", + "liveView": "liveView/", "users": "/users/", "log": "log/", "installations": "/installations/", diff --git a/typescript/Frontend/src/util/graph.util.tsx b/typescript/Frontend/src/util/graph.util.tsx index a2e52162c..1693e21c7 100644 --- a/typescript/Frontend/src/util/graph.util.tsx +++ b/typescript/Frontend/src/util/graph.util.tsx @@ -48,17 +48,28 @@ export type TopologyValues = { islandBusToLoadOnIslandBusConnection: BoxData; gridBusToPvOnGridbusConnection: BoxData; gridBusToLoadOnGridBusConnection: BoxData; + inverter: BoxData; + dcDc: BoxData; + islandBusToInverter: BoxData; + inverterToDcBus: BoxData; + gridBusToIslandBusConnection: BoxData; + pvOnDcBusToDcBusConnection: BoxData; + pvOnIslandBusToIslandBusConnection: BoxData; }; type TopologyPaths = { [key in keyof TopologyValues]: string[] }; export const topologyPaths: TopologyPaths = { gridToAcInConnection: [ - "/GridMeter/Ac/L1/Power/Apparent", - "/GridMeter/Ac/L2/Power/Apparent", - "/GridMeter/Ac/L3/Power/Apparent", + "/GridMeter/Ac/L1/Power/Active", + "/GridMeter/Ac/L2/Power/Active", + "/GridMeter/Ac/L3/Power/Active", + ], + gridBus: [ + "/GridMeter/Ac/L1/Voltage", + "/GridMeter/Ac/L2/Voltage", + "/GridMeter/Ac/L3/Voltage", ], - gridBus: ["/GridMeter/Ac/L2/Voltage"], islandBus: [ "/AcDc/Ac/L1/Voltage", "/AcDc/Ac/L2/Voltage", @@ -69,12 +80,58 @@ export const topologyPaths: TopologyPaths = { dcDCToBatteryConnection: ["/DcDc/Dc/Battery/Power"], battery: ["/Battery/Soc", "/Battery/Dc/Voltage"], dcBusToLoadOnDcConnection: ["/LoadOnDc/Power"], - islandBusToLoadOnIslandBusConnection: ["/LoadOnAcIsland/Ac/Power/Apparent"], - gridBusToPvOnGridbusConnection: ["/PvOnAcGrid/Power/Apparent"], - gridBusToLoadOnGridBusConnection: ["/LoadOnAcGrid/Power/Apparent"], + islandBusToLoadOnIslandBusConnection: ["/LoadOnAcIsland/Ac/Power/Active"], + gridBusToPvOnGridbusConnection: ["/PvOnAcGrid/Power/Active"], + gridBusToLoadOnGridBusConnection: ["/LoadOnAcGrid/Power/Active"], + inverter: ["/AcDc/Devices/1/Status/Ac/Power/Active"], + dcDc: ["/DcDc/Devices/1/Status/Dc/Battery/Voltage"], + islandBusToInverter: ["/AcDc/Ac/Power/Active"], + inverterToDcBus: ["/AcDc/Dc/Power"], + gridBusToIslandBusConnection: ["/AcGridToAcIsland/Power/Active"], + pvOnDcBusToDcBusConnection: ["/PvOnDc/Dc/Power"], + pvOnIslandBusToIslandBusConnection: ["/PvOnAcIsland/Power/Active"], }; -const getBoxColor = () => {}; +interface BoxColor { + titleColor: string; + boxColor: string; +} +export const getBoxColor = (boxTitle?: string): BoxColor => { + switch (boxTitle) { + case "Grid": + return { + titleColor: "#e74c3c", + boxColor: "#c0392b", + }; + case "Island Bus": + case "Grid Bus": + return { + titleColor: "#adadad", + boxColor: "#8e8e8e", + }; + case "Inverter": + return { + titleColor: "#4789d0", + boxColor: "#4789d0", + }; + case "Pv": + return { + titleColor: "#f4b350", + boxColor: "#f39c12", + }; + + case "Load": + return { + titleColor: "#2ecc71", + boxColor: "#27ae60", + }; + default: + return { + titleColor: "#e74c3c", + boxColor: "#c0392b", + }; + } +}; export const extractTopologyValues = ( timeSeriesData: DataPoint @@ -86,7 +143,7 @@ export const extractTopologyValues = ( const values = topologyPaths[topologyKey as keyof TopologyValues].map( (topologyPath) => timeSeriesValue[topologyPath] ); - console.log("AAA", topologyKey); + console.log("values", values, topologyKey); switch (topologyKey as keyof TopologyValues) { case "gridToAcInConnection": topologyValues = [ @@ -94,7 +151,7 @@ export const extractTopologyValues = ( ]; break; default: - topologyValues = values.map(({ value }) => value); + topologyValues = values.map((element) => element.value); } console.log("topologyValues", topologyValues); return { @@ -116,8 +173,9 @@ export const getHighestConnectionValue = (values: TopologyValues) => Object.keys(values) .filter((value) => value.includes("Connection")) .reduce((acc, curr) => { - const value = values[curr as keyof TopologyValues].values[0] as number; - console.log("reduce", value, acc); + const value = Math.abs( + values[curr as keyof TopologyValues].values[0] as number + ); return value > acc ? value : acc; }, 0); @@ -125,8 +183,7 @@ export const getAmount = ( highestConnectionValue: number, values: (string | number)[] ) => { - console.log("amount", values[0] as number, highestConnectionValue); - return (values[0] as number) / highestConnectionValue; + return Math.abs(values[0] as number) / highestConnectionValue; }; export interface CsvEntry {