Battery view updated

This commit is contained in:
Noe 2024-03-08 11:19:58 +01:00
parent 39fc4ad331
commit b5f8658300
11 changed files with 1511 additions and 480 deletions

View File

@ -1,24 +1,19 @@
{
"installation": "installation/",
"live": "live",
"users": "/users/",
"log": "log/",
"installations": "/installations/",
"groups": "/groups/",
"group": "group/",
"installation": "installation/",
"login": "/login/",
"forgotPassword": "/forgotPassword/",
"folder": "folder/",
"manageAccess": "manageAccess/",
"user": "user/",
"tree": "tree/",
"list": "list/",
"overview": "overview",
"manage": "manage",
"batteryview": "batteryview",
"log": "log",
"live": "live",
"information": "information",
"configuration": "configuration",
"login": "/login/",
"forgotPassword": "/forgotPassword/",
"mainstats": "mainstats",
"general": "general"
"detailed_view": "detailed_view/"
}

View File

@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react';
import React from 'react';
import {
Container,
Grid,
@ -23,6 +23,7 @@ import { FormattedMessage } from 'react-intl';
import { I_S3Credentials } from '../../../interfaces/S3Types';
import routes from '../../../Resources/routes.json';
import MainStats from './MainStats';
import DetailedBatteryView from './DetailedBatteryView';
interface BatteryViewProps {
values: TopologyValues;
@ -33,68 +34,30 @@ function BatteryView(props: BatteryViewProps) {
if (props.values === null) {
return null;
}
const currentPath = useLocation();
const currentLocation = useLocation();
const navigate = useNavigate();
const [currentTab, setCurrentTab] = useState<string>(undefined);
const numOfBatteries = props.values.batteryView.values[0].value
.toString()
.split(',').length;
const batteryData = [];
let batteryId = 1;
// Use a for loop to generate battery data
for (let index = 1; index <= numOfBatteries * 7; index += 7) {
const battery = {
BatteryId: 'Battery ' + batteryId.toString(),
FwVersion: props.values.batteryView.values[index].value,
Power:
Number(props.values.batteryView.values[index + 1].value).toFixed(2) +
' ' +
props.values.batteryView.values[index + 1].unit,
Voltage:
Number(props.values.batteryView.values[index + 2].value).toFixed(2) +
' ' +
props.values.batteryView.values[index + 2].unit,
Soc:
props.values.batteryView.values[index + 3].value +
' ' +
props.values.batteryView.values[index + 3].unit,
AverageTemperature:
props.values.batteryView.values[index + 4].value +
' ' +
props.values.batteryView.values[index + 4].unit,
Warnings: props.values.batteryView.values[index + 5].value,
Alarms: props.values.batteryView.values[index + 6].value
};
batteryId++;
batteryData.push(battery);
}
const numOfBatteries = props.values.batteryView.length;
const handleMainStatsButton = () => {
navigate(routes.mainstats);
};
useEffect(() => {
let path = currentPath.pathname.split('/');
setCurrentTab(path[path.length - 1]);
}, [currentPath]);
return (
<>
<Container maxWidth="xl">
<Grid container>
<Routes>
<Route
path={routes.mainstats}
element={
<MainStats s3Credentials={props.s3Credentials}></MainStats>
}
/>
</Routes>
{currentTab === 'batteryview' && (
<Grid item xs={6} md={6}>
<Grid
item
xs={6}
md={6}
sx={{
display:
!currentLocation.pathname.includes('detailed_view') &&
!currentLocation.pathname.includes('mainstats')
? 'block'
: 'none'
}}
>
<Button
variant="contained"
sx={{
@ -105,7 +68,7 @@ function BatteryView(props: BatteryViewProps) {
}}
>
<FormattedMessage
id="main_stats"
id="battery_view"
defaultMessage="Battery View"
/>
</Button>
@ -116,7 +79,6 @@ function BatteryView(props: BatteryViewProps) {
sx={{
marginTop: '20px',
marginLeft: '20px',
// backgroundColor: mainStatsData ? '#808080' : '#ffc04d',
backgroundColor: '#ffc04d',
color: '#000000',
'&:hover': { bgcolor: '#f7b34d' }
@ -125,13 +87,42 @@ function BatteryView(props: BatteryViewProps) {
<FormattedMessage id="main_stats" defaultMessage="Main Stats" />
</Button>
</Grid>
)}
</Grid>
{currentTab === 'batteryview' && (
<Grid container>
<Routes>
<Route
path={routes.mainstats + '*'}
element={
<MainStats s3Credentials={props.s3Credentials}></MainStats>
}
/>
{Array.from({ length: numOfBatteries }).map((_, i) => (
<Route
key={routes.detailed_view + i}
path={routes.detailed_view + i}
element={
<DetailedBatteryView
s3Credentials={props.s3Credentials}
batteryData={props.values.batteryView[i]}
></DetailedBatteryView>
}
/>
))}
</Routes>
</Grid>
<TableContainer
component={Paper}
sx={{ marginTop: '20px', marginBottom: '20px' }}
sx={{
marginTop: '20px',
marginBottom: '20px',
display:
!currentLocation.pathname.includes('detailed_view') &&
!currentLocation.pathname.includes('mainstats')
? 'block'
: 'none'
}}
>
<Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead>
@ -147,7 +138,7 @@ function BatteryView(props: BatteryViewProps) {
</TableRow>
</TableHead>
<TableBody>
{batteryData.map((battery) => (
{props.values.batteryView.map((battery) => (
<TableRow
key={battery.BatteryId}
style={{
@ -160,7 +151,15 @@ function BatteryView(props: BatteryViewProps) {
align="center"
sx={{ fontWeight: 'bold' }}
>
{battery.BatteryId}
<Link
style={{ color: 'black' }}
to={
routes.detailed_view +
(battery.BatteryId - 1).toString()
}
>
{'Battery ' + battery.BatteryId}
</Link>
</TableCell>
<TableCell
sx={{
@ -168,7 +167,7 @@ function BatteryView(props: BatteryViewProps) {
textAlign: 'center'
}}
>
{battery.FwVersion}
{battery.FwVersion.value}
</TableCell>
<TableCell
sx={{
@ -176,7 +175,7 @@ function BatteryView(props: BatteryViewProps) {
textAlign: 'center'
}}
>
{battery.Power}
{battery.Power.value + ' ' + battery.Power.unit}
</TableCell>
<TableCell
sx={{
@ -184,40 +183,42 @@ function BatteryView(props: BatteryViewProps) {
textAlign: 'center',
backgroundColor:
battery.Voltage < 44 || battery.Voltage > 57
battery.Voltage.value < 44 || battery.Voltage.value > 57
? '#FF033E'
: '#32CD32',
color: battery.Voltage === '' ? 'white' : 'inherit'
color: battery.Voltage.value === '' ? 'white' : 'inherit'
}}
>
{battery.Voltage}
{battery.Voltage.value + ' ' + battery.Voltage.unit}
</TableCell>
<TableCell
sx={{
width: '10%',
textAlign: 'center',
backgroundColor:
battery.Soc < 20
battery.Soc.value < 20
? '#FF033E'
: battery.Soc < 50
? '#ffbf00 '
: battery.Soc.value < 50
? '#ffbf00'
: '#32CD32',
color: battery.Soc === '' ? 'white' : 'inherit'
color: battery.Soc.value === '' ? 'white' : 'inherit'
}}
>
{battery.Soc}
{battery.Soc.value + ' ' + battery.Soc.unit}
</TableCell>
<TableCell
sx={{
width: '10%',
textAlign: 'center',
backgroundColor:
battery.AverageTemperature > 270
battery.AverageTemperature.value > 270
? '#FF033E'
: '#32CD32 '
}}
>
{battery.AverageTemperature}
{battery.AverageTemperature.value +
' ' +
battery.AverageTemperature.unit}
</TableCell>
<TableCell
@ -226,21 +227,22 @@ function BatteryView(props: BatteryViewProps) {
textAlign: 'center',
padding: '8px',
fontWeight:
battery.Warnings !== '' ? 'bold' : 'inherit',
battery.Warnings.value !== '' ? 'bold' : 'inherit',
backgroundColor:
battery.Warnings === '' ? 'inherit' : '#ff9900',
color: battery.Warnings != '' ? 'black' : 'inherit'
battery.Warnings.value === '' ? 'inherit' : '#ff9900',
color: battery.Warnings.value != '' ? 'black' : 'inherit'
}}
>
{battery.Warnings === '' ? (
{battery.Warnings.value === '' ? (
'None'
) : battery.Warnings.split(';').length > 1 ? (
) : battery.Warnings.value.toString().split(';').length >
1 ? (
<Link
style={{ color: 'black' }}
to={
currentPath.pathname.substring(
currentLocation.pathname.substring(
0,
currentPath.pathname.lastIndexOf('/') + 1
currentLocation.pathname.lastIndexOf('/') + 1
) +
routes.log +
'?open=warning'
@ -249,28 +251,30 @@ function BatteryView(props: BatteryViewProps) {
Multiple Warnings
</Link>
) : (
battery.Warnings
battery.Warnings.value
)}
</TableCell>
<TableCell
sx={{
width: '20%',
textAlign: 'center',
fontWeight: battery.Alarms !== '' ? 'bold' : 'inherit',
fontWeight:
battery.Alarms.value !== '' ? 'bold' : 'inherit',
backgroundColor:
battery.Alarms === '' ? 'inherit' : '#FF033E',
color: battery.Alarms != '' ? 'black' : 'inherit'
battery.Alarms.value === '' ? 'inherit' : '#FF033E',
color: battery.Alarms.value != '' ? 'black' : 'inherit'
}}
>
{battery.Alarms === '' ? (
{battery.Alarms.value === '' ? (
'None'
) : battery.Alarms.split(';').length > 1 ? (
) : battery.Alarms.value.toString().split(';').length >
1 ? (
<Link
style={{ color: 'black' }}
to={
currentPath.pathname.substring(
currentLocation.pathname.substring(
0,
currentPath.pathname.lastIndexOf('/') + 1
currentLocation.pathname.lastIndexOf('/') + 1
) +
routes.log +
'?open=error'
@ -279,7 +283,7 @@ function BatteryView(props: BatteryViewProps) {
Multiple Alarms
</Link>
) : (
battery.Alarms
battery.Alarms.value
)}
</TableCell>
</TableRow>
@ -287,7 +291,6 @@ function BatteryView(props: BatteryViewProps) {
</TableBody>
</Table>
</TableContainer>
)}
</Container>
</>
);

View File

@ -0,0 +1,971 @@
import React from 'react';
import { I_S3Credentials } from '../../../interfaces/S3Types';
import {
Card,
Grid,
Paper,
Table,
TableBody,
TableCell,
TableContainer,
TableRow
} from '@mui/material';
import { Battery } from '../Log/graph.util';
import Button from '@mui/material/Button';
import { FormattedMessage } from 'react-intl';
import { useNavigate } from 'react-router-dom';
import routes from '../../../Resources/routes.json';
interface DetailedBatteryViewProps {
s3Credentials: I_S3Credentials;
batteryData: Battery;
}
function DetailedBatteryView(props: DetailedBatteryViewProps) {
if (props.batteryData === null) {
return null;
}
const navigate = useNavigate();
const handleBatteryViewButton = () => {
navigate(location.pathname.split('/').slice(0, -2).join('/'));
};
const handleMainStatsButton = () => {
navigate(
location.pathname.split('/').slice(0, -2).join('/') +
'/' +
routes.mainstats
);
};
return (
<>
<Grid container>
<Grid item xs={6} md={6}>
<Button
variant="contained"
onClick={handleBatteryViewButton}
sx={{
marginTop: '20px',
backgroundColor: '#ffc04d',
color: '#000000',
'&:hover': { bgcolor: '#f7b34d' }
}}
>
<FormattedMessage id="main_stats" defaultMessage="Battery View" />
</Button>
<Button
variant="contained"
onClick={handleMainStatsButton}
sx={{
marginTop: '20px',
marginLeft: '20px',
backgroundColor: '#ffc04d',
color: '#000000',
'&:hover': { bgcolor: '#f7b34d' }
}}
>
<FormattedMessage id="main_stats" defaultMessage="Main Stats" />
</Button>
</Grid>
</Grid>
<Grid item md={2} xs={2}>
<Card
sx={{
overflow: 'visible',
marginTop: '30px',
marginBottom: '30px',
backgroundColor: 'red'
}}
>
<TableContainer
component={Paper}
sx={{ marginTop: '20px', marginBottom: '20px', width: '100%' }}
>
<Table size="medium" aria-label="a dense table">
<TableBody>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Voltage
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.Voltage.value +
' ' +
props.batteryData.Voltage.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Current
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.Current.value +
' ' +
props.batteryData.Current.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Power
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.Power.value +
' ' +
props.batteryData.Power.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Bus Current
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.BusCurrent.value +
' ' +
props.batteryData.BusCurrent.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Cells Current
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.CellsCurrent.value +
' ' +
props.batteryData.CellsCurrent.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Heating Current
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.HeatingCurrent.value +
' ' +
props.batteryData.HeatingCurrent.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Heating Power
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.HeatingPower.value +
' ' +
props.batteryData.HeatingPower.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Soc
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.Soc.value +
' ' +
props.batteryData.Soc.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
SOCAh
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.SOCAh.value +
' ' +
props.batteryData.SOCAh.unit}
</TableCell>
</TableRow>
</TableBody>
</Table>
</TableContainer>
</Card>
</Grid>
{/*----------------------------------------------------------------------------------------------------------------------------------*/}
<Grid item md={2.9} xs={2.9}>
<Card
sx={{
overflow: 'visible',
marginTop: '30px',
marginLeft: '20px',
marginBottom: '30px',
backgroundColor: 'red'
}}
>
<TableContainer
component={Paper}
sx={{ marginTop: '20px', marginBottom: '20px', width: '100%' }}
>
<Table size="medium" aria-label="a dense table">
<TableBody>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Heating
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.HeatingTemperature.value +
' ' +
props.batteryData.HeatingTemperature.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Board Temperature
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.BoardTemperature.value +
' ' +
props.batteryData.BoardTemperature.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Center Cells Temperature
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.AverageTemperature.value +
' ' +
props.batteryData.AverageTemperature.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Left Cells Temperature
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.LeftCellsTemperature.value +
' ' +
props.batteryData.LeftCellsTemperature.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Right Cells Temperature
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.RightCellsTemperature.value +
' ' +
props.batteryData.RightCellsTemperature.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Average Temperature
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.AverageTemperature.value +
' ' +
props.batteryData.AverageTemperature.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
State
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.StateTemperature.value +
' ' +
props.batteryData.StateTemperature.unit}
</TableCell>
</TableRow>
</TableBody>
</Table>
</TableContainer>
</Card>
</Grid>
{/*----------------------------------------------------------------------------------------------------------------------------------*/}
<Grid item md={2.7} xs={2.7}>
<Card
sx={{
overflow: 'visible',
marginTop: '30px',
marginLeft: '20px',
marginBottom: '30px',
backgroundColor: 'red'
}}
>
<TableContainer
component={Paper}
sx={{ marginTop: '20px', marginBottom: '20px', width: '100%' }}
>
<Table size="medium" aria-label="a dense table">
<TableBody>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Connected To Dc Bus
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.ConnectedToDcBus.value +
' ' +
props.batteryData.ConnectedToDcBus.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Alarm Out Active
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.AlarmOutActive.value +
' ' +
props.batteryData.AlarmOutActive.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Internal Fan Active
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.InternalFanActive.value +
' ' +
props.batteryData.InternalFanActive.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Volt Measurement Allowed
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.VoltMeasurementAllowed.value +
' ' +
props.batteryData.VoltMeasurementAllowed.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Aux Relay Bus
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.AuxRelayBus.value +
' ' +
props.batteryData.AuxRelayBus.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Remote State Active
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.RemoteStateActive.value +
' ' +
props.batteryData.RemoteStateActive.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
RiscActive
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.RiscActive.value +
' ' +
props.batteryData.RiscActive.unit}
</TableCell>
</TableRow>
</TableBody>
</Table>
</TableContainer>
</Card>
</Grid>
{/*----------------------------------------------------------------------------------------------------------------------------------*/}
<Grid item md={2.9} xs={2.9}>
<Card
sx={{
overflow: 'visible',
marginTop: '30px',
marginLeft: '20px',
marginBottom: '30px',
backgroundColor: 'red'
}}
>
<TableContainer
component={Paper}
sx={{ marginTop: '20px', marginBottom: '20px', width: '100%' }}
>
<Table size="medium" aria-label="a dense table">
<TableBody>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Eoc
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.Eoc.value +
' ' +
props.batteryData.Eoc.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Serial Number
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.SerialNumber.value +
' ' +
props.batteryData.SerialNumber.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Firmware Version
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.FwVersion.value +
' ' +
props.batteryData.FwVersion.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Time Since TOC
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.TimeSinceTOC.value +
' ' +
props.batteryData.TimeSinceTOC.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Calibration Charge Requested
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.CalibrationChargeRequested.value +
' ' +
props.batteryData.CalibrationChargeRequested.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Max Charge Power
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.MaxChargePower.value +
' ' +
props.batteryData.MaxChargePower.unit}
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Max Discharge Power
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
{props.batteryData.MaxDischargePower.value +
' ' +
props.batteryData.MaxDischargePower.unit}
</TableCell>
</TableRow>
</TableBody>
</Table>
</TableContainer>
</Card>
</Grid>
{/*----------------------------------------------------------------------------------------------------------------------------------*/}
<Grid item md={1.5} xs={1.5}>
<Card
sx={{
overflow: 'visible',
marginTop: '30px',
marginLeft: '20px',
marginBottom: '30px',
backgroundColor: 'red'
}}
>
<TableContainer
component={Paper}
sx={{ marginTop: '20px', marginBottom: '20px', width: '100%' }}
>
<Table size="medium" aria-label="a dense table">
<TableBody>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Blue Led
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
<div
style={{
width: '20px',
height: '20px',
marginLeft: '2px',
borderRadius: '50%',
backgroundColor:
props.batteryData.BlueLeds.value === 'On'
? '#00ccff'
: 'transparent'
}}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Green Led
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
<div
style={{
width: '20px',
height: '20px',
marginLeft: '2px',
borderRadius: '50%',
backgroundColor:
props.batteryData.GreenLeds.value === 'On'
? 'green'
: 'transparent'
}}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Red Led
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
<div
style={{
width: '20px',
height: '20px',
marginLeft: '2px',
borderRadius: '50%',
backgroundColor:
props.batteryData.RedLeds.value === 'On'
? 'red'
: 'transparent'
}}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell
component="th"
scope="row"
align="left"
sx={{ fontWeight: 'bold' }}
>
Amber Led
</TableCell>
<TableCell
align="right"
sx={{
width: '6ch',
whiteSpace: 'nowrap',
paddingRight: '12px'
}}
>
<div
style={{
width: '20px',
height: '20px',
marginLeft: '2px',
borderRadius: '50%',
backgroundColor:
props.batteryData.AmberLeds.value === 'On'
? 'orange'
: 'transparent'
}}
/>
</TableCell>
</TableRow>
</TableBody>
</Table>
</TableContainer>
</Card>
</Grid>
</>
);
}
export default DetailedBatteryView;

View File

@ -384,7 +384,6 @@ function MainStats(props: MainStatsProps) {
{!loading && (
<>
{' '}
<Grid item xs={6} md={6}>
<Button
variant="contained"

View File

@ -33,10 +33,10 @@ function Configuration(props: ConfigurationProps) {
const forcedCalibrationChargeOptions = ['No', 'UntilEoc', 'Yes'];
const [formValues, setFormValues] = useState<ConfigurationValues>({
minimumSoC: props.values.minimumSoC.values[0].value,
gridSetPoint: (props.values.gridSetPoint.values[0].value as number) / 1000,
minimumSoC: props.values.minimumSoC[0].value,
gridSetPoint: (props.values.gridSetPoint[0].value as number) / 1000,
forceCalibrationCharge: forcedCalibrationChargeOptions.indexOf(
props.values.calibrationChargeForced.values[0].value.toString()
props.values.calibrationChargeForced[0].value.toString()
)
});
@ -78,7 +78,7 @@ function Configuration(props: ConfigurationProps) {
selectedForcedCalibrationChargeOption,
setSelectedForcedCalibrationChargeOption
] = useState<string>(
props.values.calibrationChargeForced.values[0].value.toString()
props.values.calibrationChargeForced[0].value.toString()
);
//const forcedCalibrationChargeOptions = ['No', 'UntilEoc', 'Yes'];
@ -242,8 +242,7 @@ function Configuration(props: ConfigurationProps) {
/>
}
value={
(props.values.installedDcDcPower.values[0]
.value as number) * 10
(props.values.installedDcDcPower[0].value as number) * 10
}
fullWidth
/>
@ -257,10 +256,9 @@ function Configuration(props: ConfigurationProps) {
/>
}
value={
(props.values.maximumDischargePower.values[0]
.value as number) *
(props.values.maximumDischargePower[0].value as number) *
48 *
(props.values.DcDcNum.values[0].value as number)
(props.values.DcDcNum[0].value as number)
}
fullWidth
/>
@ -273,7 +271,7 @@ function Configuration(props: ConfigurationProps) {
defaultMessage="Number of Batteries"
/>
}
value={props.values.battery.values.length - 4}
value={props.values.battery.length - 4}
fullWidth
/>
</div>

View File

@ -18,10 +18,10 @@ import Overview from '../Overview/overview';
import Configuration from '../Configuration/Configuration';
import { fetchData } from 'src/content/dashboards/Installations/fetchData';
import CancelIcon from '@mui/icons-material/Cancel';
import BatteryView from '../BatteryView/BatteryView';
import { Navigate, Route, Routes, useLocation } from 'react-router-dom';
import routes from '../../../Resources/routes.json';
import Information from '../Information/Information';
import BatteryView from '../BatteryView/BatteryView';
interface singleInstallationProps {
current_installation?: I_Installation;
@ -31,7 +31,7 @@ interface singleInstallationProps {
function Installation(props: singleInstallationProps) {
const context = useContext(UserContext);
const { currentUser } = context;
const location = useLocation();
const location = useLocation().pathname;
const [errorLoadingS3Data, setErrorLoadingS3Data] = useState(false);
const webSocketsContext = useContext(WebSocketContext);
const { getStatus } = webSocketsContext;
@ -90,7 +90,7 @@ function Installation(props: singleInstallationProps) {
};
useEffect(() => {
let path = location.pathname.split('/');
let path = location.split('/');
setCurrentTab(path[path.length - 1]);
}, [location]);
@ -99,26 +99,32 @@ function Installation(props: singleInstallationProps) {
if (
currentTab == 'live' ||
currentTab == 'configuration' ||
currentTab == 'batteryview'
location.includes('batteryview')
) {
var interval;
let interval;
if (currentTab == 'live' || currentTab == 'batteryview') {
if (
currentTab == 'live' ||
(location.includes('batteryview') && !location.includes('mainstats'))
) {
fetchDataPeriodically();
interval = setInterval(fetchDataPeriodically, 2000);
}
if (currentTab == 'configuration') {
if (currentTab == 'configuration' || location.includes('mainstats')) {
fetchDataOnlyOneTime();
}
// Cleanup function to cancel interval and update isMounted when unmounted
return () => {
if (currentTab == 'live' || currentTab == 'batteryview') {
if (
currentTab == 'live' ||
(location.includes('batteryview') && !location.includes('mainstats'))
) {
clearInterval(interval);
}
};
}
}, [currentTab, location.pathname]);
}, [currentTab, location]);
return (
<>
@ -178,7 +184,7 @@ function Installation(props: singleInstallationProps) {
fontSize: '14px'
}}
>
{values.mode.values[0].value}
{values.mode[0].value}
</Typography>
</div>
)}
@ -274,8 +280,7 @@ function Installation(props: singleInstallationProps) {
s3Credentials={s3Credentials}
></BatteryView>
}
/>
></Route>
<Route
path={routes.overview}
element={<Overview s3Credentials={s3Credentials}></Overview>}

View File

@ -43,11 +43,8 @@ function InstallationTabs() {
} else if (path[path.length - 2] === 'tree') {
setCurrentTab('tree');
} else {
setCurrentTab(
tabList.includes(path[path.length - 1])
? path[path.length - 1]
: undefined
);
//Even if we are located at path: /batteryview/mainstats, we want the BatteryView tab to be bold
setCurrentTab(path.find((pathElement) => tabList.includes(pathElement)));
}
}, [location]);
@ -140,10 +137,6 @@ function InstallationTabs() {
label: <FormattedMessage id="overview" defaultMessage="Overview" />
},
{
value: 'log',
label: <FormattedMessage id="log" defaultMessage="Log" />
},
{
value: 'information',
label: (
@ -247,10 +240,7 @@ function InstallationTabs() {
/>
)
},
{
value: 'log',
label: <FormattedMessage id="log" defaultMessage="Log" />
},
{
value: 'information',
label: (

View File

@ -28,59 +28,192 @@ export interface I_BoxDataValue {
value: string | number;
}
export type BoxData = {
label: string;
values: I_BoxDataValue[];
};
export type ConfigurationValues = {
minimumSoC: string | number;
gridSetPoint: number;
forceCalibrationCharge: number;
};
export interface Battery {
BatteryId: number;
FwVersion: I_BoxDataValue;
Power: I_BoxDataValue;
Voltage: I_BoxDataValue;
Soc: I_BoxDataValue;
AverageTemperature: I_BoxDataValue;
Warnings: I_BoxDataValue;
Alarms: I_BoxDataValue;
Current: I_BoxDataValue;
BusCurrent: I_BoxDataValue;
CellsCurrent: I_BoxDataValue;
HeatingCurrent: I_BoxDataValue;
HeatingPower: I_BoxDataValue;
SOCAh: I_BoxDataValue;
BlueLeds: I_BoxDataValue;
RedLeds: I_BoxDataValue;
GreenLeds: I_BoxDataValue;
AmberLeds: I_BoxDataValue;
HeatingTemperature: I_BoxDataValue;
BoardTemperature: I_BoxDataValue;
LeftCellsTemperature: I_BoxDataValue;
RightCellsTemperature: I_BoxDataValue;
StateTemperature: I_BoxDataValue;
String1Active: I_BoxDataValue;
String2Active: I_BoxDataValue;
String3Active: I_BoxDataValue;
String4Active: I_BoxDataValue;
String5Active: I_BoxDataValue;
ConnectedToDcBus: I_BoxDataValue;
AlarmOutActive: I_BoxDataValue;
InternalFanActive: I_BoxDataValue;
VoltMeasurementAllowed: I_BoxDataValue;
AuxRelayBus: I_BoxDataValue;
RemoteStateActive: I_BoxDataValue;
RiscActive: I_BoxDataValue;
Eoc: I_BoxDataValue;
SerialNumber: I_BoxDataValue;
TimeSinceTOC: I_BoxDataValue;
CalibrationChargeRequested: I_BoxDataValue;
MaxChargePower: I_BoxDataValue;
MaxDischargePower: I_BoxDataValue;
}
const BatteryKeys = [
'BatteryId',
'FwVersion',
'Power',
'Voltage',
'Soc',
'AverageTemperature',
'Warnings',
'Alarms',
'Current',
'BusCurrent',
'CellsCurrent',
'HeatingCurrent',
'HeatingPower',
'SOCAh',
'BlueLeds',
'RedLeds',
'GreenLeds',
'AmberLeds',
'HeatingTemperature',
'BoardTemperature',
'LeftCellsTemperature',
'RightCellsTemperature',
'StateTemperature',
'String1Active',
'String2Active',
'String3Active',
'String4Active',
'String5Active',
'ConnectedToDcBus',
'AlarmOutActive',
'InternalFanActive',
'VoltMeasurementAllowed',
'AuxRelayBus',
'RemoteStateActive',
'RiscActive',
'Eoc',
'SerialNumber',
'TimeSinceTOC',
'CalibrationChargeRequested',
'MaxChargePower',
'MaxDischargePower'
];
export type TopologyValues = {
gridBox: BoxData;
pvOnAcGridBox: BoxData;
loadOnAcGridBox: BoxData;
pvOnIslandBusBox: BoxData;
loadOnIslandBusBox: BoxData;
pvOnDcBox: BoxData;
loadOnDcBox: BoxData;
batteryBox: BoxData;
gridBox: I_BoxDataValue[];
pvOnAcGridBox: I_BoxDataValue[];
loadOnAcGridBox: I_BoxDataValue[];
pvOnIslandBusBox: I_BoxDataValue[];
loadOnIslandBusBox: I_BoxDataValue[];
pvOnDcBox: I_BoxDataValue[];
loadOnDcBox: I_BoxDataValue[];
batteryBox: I_BoxDataValue[];
grid: BoxData;
gridToAcInConnection: BoxData;
gridBus: BoxData;
islandBus: BoxData;
dcBus: BoxData;
dcBusToDcDcConnection: BoxData;
dcDCToBatteryConnection: BoxData;
battery: BoxData;
dcBusToLoadOnDcConnection: BoxData;
islandBusToLoadOnIslandBusConnection: BoxData;
gridBusToPvOnGridbusConnection: BoxData;
gridBusToLoadOnGridBusConnection: BoxData;
inverter: BoxData;
dcDc: BoxData;
islandBusToInverter: BoxData;
inverterToDcBus: BoxData;
gridBusToIslandBusConnection: BoxData;
pvOnDcBusToDcBusConnection: BoxData;
pvOnIslandBusToIslandBusConnection: BoxData;
minimumSoC: BoxData;
installedDcDcPower: BoxData;
gridSetPoint: BoxData;
maximumDischargePower: BoxData;
DcDcNum: BoxData;
calibrationChargeForced: BoxData;
mode: BoxData;
grid: I_BoxDataValue[];
gridToAcInConnection: I_BoxDataValue[];
gridBus: I_BoxDataValue[];
islandBus: I_BoxDataValue[];
dcBus: I_BoxDataValue[];
dcBusToDcDcConnection: I_BoxDataValue[];
dcDCToBatteryConnection: I_BoxDataValue[];
battery: I_BoxDataValue[];
dcBusToLoadOnDcConnection: I_BoxDataValue[];
islandBusToLoadOnIslandBusConnection: I_BoxDataValue[];
gridBusToPvOnGridbusConnection: I_BoxDataValue[];
gridBusToLoadOnGridBusConnection: I_BoxDataValue[];
inverter: I_BoxDataValue[];
dcDc: I_BoxDataValue[];
islandBusToInverter: I_BoxDataValue[];
inverterToDcBus: I_BoxDataValue[];
gridBusToIslandBusConnection: I_BoxDataValue[];
pvOnDcBusToDcBusConnection: I_BoxDataValue[];
pvOnIslandBusToIslandBusConnection: I_BoxDataValue[];
minimumSoC: I_BoxDataValue[];
installedDcDcPower: I_BoxDataValue[];
gridSetPoint: I_BoxDataValue[];
maximumDischargePower: I_BoxDataValue[];
DcDcNum: I_BoxDataValue[];
calibrationChargeForced: I_BoxDataValue[];
mode: I_BoxDataValue[];
batteryView: BoxData;
batteryView: Battery[];
};
type TopologyPaths = { [key in keyof TopologyValues]: string[] };
const batteryIds = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const batteryPaths = [
'/Battery/Devices/%id%/FwVersion',
'/Battery/Devices/%id%/Dc/Power',
'/Battery/Devices/%id%/Dc/Voltage',
'/Battery/Devices/%id%/Soc',
'/Battery/Devices/%id%/Temperatures/Cells/Average',
'/Battery/Devices/%id%/Warnings',
'/Battery/Devices/%id%/Alarms',
'/Battery/Devices/%id%/Dc/Current',
'/Battery/Devices/%id%/BusCurrent',
'/Battery/Devices/%id%/CellsCurrent',
'/Battery/Devices/%id%/HeatingCurrent',
'/Battery/Devices/%id%/HeatingPower',
'/Battery/Devices/%id%/SOCAh',
'/Battery/Devices/%id%/Leds/Blue',
'/Battery/Devices/%id%/Leds/Red',
'/Battery/Devices/%id%/Leds/Green',
'/Battery/Devices/%id%/Leds/Amber',
'/Battery/Devices/%id%/Temperatures/Heating',
'/Battery/Devices/%id%/Temperatures/Board',
'/Battery/Devices/%id%/Temperatures/Cells/Left',
'/Battery/Devices/%id%/Temperatures/Cells/Right',
'/Battery/Devices/%id%/Temperatures/State',
'/Battery/Devices/%id%/BatteryStrings/String1Active',
'/Battery/Devices/%id%/BatteryStrings/String2Active',
'/Battery/Devices/%id%/BatteryStrings/String3Active',
'/Battery/Devices/%id%/BatteryStrings/String4Active',
'/Battery/Devices/%id%/BatteryStrings/String5Active',
'/Battery/Devices/%id%/IoStatus/ConnectedToDcBus',
'/Battery/Devices/%id%/IoStatus/AlarmOutActive',
'/Battery/Devices/%id%/IoStatus/InternalFanActive',
'/Battery/Devices/%id%/IoStatus/VoltMeasurementAllowed',
'/Battery/Devices/%id%/IoStatus/AuxRelayBus',
'/Battery/Devices/%id%/IoStatus/RemoteStateActive',
'/Battery/Devices/%id%/IoStatus/RiscActive',
'/Battery/Devices/%id%/Eoc',
'/Battery/Devices/%id%/SerialNumber',
'/Battery/Devices/%id%/TimeSinceTOC',
'/Battery/Devices/%id%/CalibrationChargeRequested',
'/Battery/Devices/%id%/MaxChargePower',
'/Battery/Devices/%id%/MaxDischargePower'
];
export const topologyPaths: TopologyPaths = {
gridBox: ['/Config/Devices/GridMeterIp/DeviceState'],
pvOnAcGridBox: ['/Config/Devices/PvOnAcGrid/DeviceState'],
@ -150,88 +283,9 @@ export const topologyPaths: TopologyPaths = {
'/Battery/Devices/10/Dc/Voltage'
],
batteryView: [
'/Config/Devices/BatteryNodes',
'/Battery/Devices/1/FwVersion',
'/Battery/Devices/1/Dc/Power',
'/Battery/Devices/1/Dc/Voltage',
'/Battery/Devices/1/Soc',
'/Battery/Devices/1/Temperatures/Cells/Average',
'/Battery/Devices/1/Warnings',
'/Battery/Devices/1/Alarms',
'/Battery/Devices/2/FwVersion',
'/Battery/Devices/2/Dc/Power',
'/Battery/Devices/2/Dc/Voltage',
'/Battery/Devices/2/Soc',
'/Battery/Devices/2/Temperatures/Cells/Average',
'/Battery/Devices/2/Warnings',
'/Battery/Devices/2/Alarms',
'/Battery/Devices/3/FwVersion',
'/Battery/Devices/3/Dc/Power',
'/Battery/Devices/3/Dc/Voltage',
'/Battery/Devices/3/Soc',
'/Battery/Devices/3/Temperatures/Cells/Average',
'/Battery/Devices/3/Warnings',
'/Battery/Devices/3/Alarms',
'/Battery/Devices/4/FwVersion',
'/Battery/Devices/4/Dc/Power',
'/Battery/Devices/4/Dc/Voltage',
'/Battery/Devices/4/Soc',
'/Battery/Devices/4/Temperatures/Cells/Average',
'/Battery/Devices/4/Warnings',
'/Battery/Devices/4/Alarms',
'/Battery/Devices/5/FwVersion',
'/Battery/Devices/5/Dc/Power',
'/Battery/Devices/5/Dc/Voltage',
'/Battery/Devices/5/Soc',
'/Battery/Devices/5/Temperatures/Cells/Average',
'/Battery/Devices/5/Warnings',
'/Battery/Devices/5/Alarms',
'/Battery/Devices/6/FwVersion',
'/Battery/Devices/6/Dc/Power',
'/Battery/Devices/6/Dc/Voltage',
'/Battery/Devices/6/Soc',
'/Battery/Devices/6/Temperatures/Cells/Average',
'/Battery/Devices/6/Warnings',
'/Battery/Devices/6/Alarms',
'/Battery/Devices/7/FwVersion',
'/Battery/Devices/7/Dc/Power',
'/Battery/Devices/7/Dc/Voltage',
'/Battery/Devices/7/Soc',
'/Battery/Devices/7/Temperatures/Cells/Average',
'/Battery/Devices/7/Warnings',
'/Battery/Devices/7/Alarms',
'/Battery/Devices/8/FwVersion',
'/Battery/Devices/8/Dc/Power',
'/Battery/Devices/8/Dc/Voltage',
'/Battery/Devices/8/Soc',
'/Battery/Devices/8/Temperatures/Cells/Average',
'/Battery/Devices/8/Warnings',
'/Battery/Devices/8/Alarms',
'/Battery/Devices/9/FwVersion',
'/Battery/Devices/9/Dc/Power',
'/Battery/Devices/9/Dc/Voltage',
'/Battery/Devices/9/Soc',
'/Battery/Devices/9/Temperatures/Cells/Average',
'/Battery/Devices/9/Warnings',
'/Battery/Devices/9/Alarms',
'/Battery/Devices/10/FwVersion',
'/Battery/Devices/10/Dc/Power',
'/Battery/Devices/10/Dc/Voltage',
'/Battery/Devices/10/Soc',
'/Battery/Devices/10/Temperatures/Cells/Average',
'/Battery/Devices/10/Warnings',
'/Battery/Devices/10/Alarms'
],
batteryView: batteryIds.flatMap((id) =>
batteryPaths.map((path) => path.replace('%id%', id.toString()))
),
minimumSoC: ['/Config/MinSoc'],
installedDcDcPower: ['/DcDc/SystemControl/NumberOfConnectedSlaves'],
@ -251,6 +305,44 @@ export const extractValues = (
const paths = topologyPaths[topologyKey];
let topologyValues: { unit: string; value: string | number }[] = [];
if (topologyKey === 'batteryView') {
extractedValues[topologyKey] = [];
const numOfBatteries = timeSeriesData.value[
'/Config/Devices/BatteryNodes'
].value
.toString()
.split(',').length;
let battery_id = 1;
let pathIndex = 0;
while (pathIndex < paths.length) {
let battery = {};
let existingKeys = 0;
battery[BatteryKeys[0]] = battery_id;
for (let i = 1; i < BatteryKeys.length; i++) {
const path = paths[pathIndex];
if (timeSeriesData.value.hasOwnProperty(path)) {
existingKeys++;
battery[BatteryKeys[i]] = {
unit: timeSeriesData.value[path].unit.includes('~')
? timeSeriesData.value[path].unit.replace('~', '')
: timeSeriesData.value[path].unit,
value:
typeof timeSeriesData.value[path].value === 'string'
? timeSeriesData.value[path].value
: Number(timeSeriesData.value[path].value).toFixed(1)
};
}
pathIndex++;
}
battery_id++;
if (existingKeys > 0) {
extractedValues[topologyKey].push(battery as Battery);
}
}
} else {
// Check if any of the specified paths exist in the dataRecord
for (const path of paths) {
if (timeSeriesData.value.hasOwnProperty(path)) {
@ -263,27 +355,26 @@ export const extractValues = (
}
}
if (topologyValues.length > 0) {
extractedValues[topologyKey] = {
label: topologyPaths[topologyKey as keyof TopologyValues][0]
.split('/')
.pop(),
values: topologyValues
};
extractedValues[topologyKey] = topologyValues;
}
}
}
return extractedValues;
};
export const getHighestConnectionValue = (values: TopologyValues) =>
Object.keys(values)
export const getHighestConnectionValue = (values: TopologyValues) => {
return Object.keys(values)
.filter((value) => value.includes('Connection'))
.reduce((acc, curr) => {
const value = Math.abs(
values[curr as keyof TopologyValues].values[0].value as number
);
let topologyValue = values[
curr as keyof TopologyValues
][0] as I_BoxDataValue;
const value = Math.abs(topologyValue.value as number);
return value > acc ? value : acc;
}, 0);
};
export const getAmount = (
highestConnectionValue: number,

View File

@ -75,8 +75,7 @@ function Topology(props: TopologyProps) {
centerBox={{
title: 'Grid',
data: props.values.grid,
connected:
props.values.gridBox.values[0].value.toString() != 'Disabled'
connected: props.values.gridBox[0].value.toString() != 'Disabled'
}}
centerConnection={{
orientation: 'horizontal',
@ -84,7 +83,7 @@ function Topology(props: TopologyProps) {
amount: props.values.gridToAcInConnection
? getAmount(
highestConnectionValue,
props.values.gridToAcInConnection.values
props.values.gridToAcInConnection
)
: 0,
showValues: showValues
@ -97,8 +96,7 @@ function Topology(props: TopologyProps) {
title: 'Pv Inverter',
data: props.values.gridBusToPvOnGridbusConnection,
connected:
props.values.pvOnAcGridBox.values[0].value.toString() !=
'Disabled'
props.values.pvOnAcGridBox[0].value.toString() != 'Disabled'
}}
topConnection={{
orientation: 'vertical',
@ -107,7 +105,7 @@ function Topology(props: TopologyProps) {
amount: props.values.gridBusToPvOnGridbusConnection
? getAmount(
highestConnectionValue,
props.values.gridBusToPvOnGridbusConnection.values
props.values.gridBusToPvOnGridbusConnection
)
: 0,
showValues: showValues
@ -123,7 +121,7 @@ function Topology(props: TopologyProps) {
amount: props.values.gridBusToIslandBusConnection
? getAmount(
highestConnectionValue,
props.values.gridBusToIslandBusConnection.values
props.values.gridBusToIslandBusConnection
)
: 0,
data: props.values.gridBusToIslandBusConnection,
@ -133,8 +131,7 @@ function Topology(props: TopologyProps) {
title: 'AC Loads',
data: props.values.gridBusToLoadOnGridBusConnection,
connected:
props.values.loadOnAcGridBox.values[0].value.toString() !=
'Disabled'
props.values.loadOnAcGridBox[0].value.toString() != 'Disabled'
}}
bottomConnection={{
orientation: 'vertical',
@ -143,7 +140,7 @@ function Topology(props: TopologyProps) {
amount: props.values.gridBusToLoadOnGridBusConnection
? getAmount(
highestConnectionValue,
props.values.gridBusToLoadOnGridBusConnection.values
props.values.gridBusToLoadOnGridBusConnection
)
: 0,
showValues: showValues
@ -156,8 +153,7 @@ function Topology(props: TopologyProps) {
title: 'Pv Inverter',
data: props.values.pvOnIslandBusToIslandBusConnection,
connected:
props.values.pvOnIslandBusBox.values[0].value.toString() !=
'Disabled'
props.values.pvOnIslandBusBox[0].value.toString() != 'Disabled'
}}
topConnection={{
orientation: 'vertical',
@ -166,7 +162,7 @@ function Topology(props: TopologyProps) {
amount: props.values.pvOnIslandBusToIslandBusConnection
? getAmount(
highestConnectionValue,
props.values.pvOnIslandBusToIslandBusConnection.values
props.values.pvOnIslandBusToIslandBusConnection
)
: 0,
showValues: showValues
@ -182,7 +178,7 @@ function Topology(props: TopologyProps) {
amount: props.values.islandBusToInverter
? getAmount(
highestConnectionValue,
props.values.islandBusToInverter.values
props.values.islandBusToInverter
)
: 0,
showValues: showValues
@ -191,7 +187,7 @@ function Topology(props: TopologyProps) {
title: 'AC Loads',
data: props.values.islandBusToLoadOnIslandBusConnection,
connected:
props.values.loadOnIslandBusBox.values[0].value.toString() !=
props.values.loadOnIslandBusBox[0].value.toString() !=
'Disabled'
}}
bottomConnection={{
@ -201,7 +197,7 @@ function Topology(props: TopologyProps) {
amount: props.values.islandBusToLoadOnIslandBusConnection
? getAmount(
highestConnectionValue,
props.values.islandBusToLoadOnIslandBusConnection.values
props.values.islandBusToLoadOnIslandBusConnection
)
: 0,
showValues: showValues
@ -221,7 +217,7 @@ function Topology(props: TopologyProps) {
amount: props.values.inverterToDcBus
? getAmount(
highestConnectionValue,
props.values.inverterToDcBus.values
props.values.inverterToDcBus
)
: 0,
showValues: showValues
@ -234,7 +230,7 @@ function Topology(props: TopologyProps) {
title: 'Pv DC-DC',
data: props.values.pvOnDcBusToDcBusConnection,
connected:
props.values.pvOnDcBox.values[0].value.toString() != 'Disabled'
props.values.pvOnDcBox[0].value.toString() != 'Disabled'
}}
topConnection={{
orientation: 'vertical',
@ -243,7 +239,7 @@ function Topology(props: TopologyProps) {
amount: props.values.pvOnDcBusToDcBusConnection
? getAmount(
highestConnectionValue,
props.values.pvOnDcBusToDcBusConnection.values
props.values.pvOnDcBusToDcBusConnection
)
: 0,
showValues: showValues
@ -259,7 +255,7 @@ function Topology(props: TopologyProps) {
amount: props.values.dcBusToDcDcConnection
? getAmount(
highestConnectionValue,
props.values.dcBusToDcDcConnection.values
props.values.dcBusToDcDcConnection
)
: 0,
showValues: showValues
@ -268,8 +264,7 @@ function Topology(props: TopologyProps) {
title: 'DC Loads',
data: props.values.dcBusToLoadOnDcConnection,
connected:
props.values.loadOnDcBox.values[0].value.toString() !=
'Disabled'
props.values.loadOnDcBox[0].value.toString() != 'Disabled'
}}
bottomConnection={{
orientation: 'vertical',
@ -278,7 +273,7 @@ function Topology(props: TopologyProps) {
amount: props.values.dcBusToLoadOnDcConnection
? getAmount(
highestConnectionValue,
props.values.dcBusToLoadOnDcConnection.values
props.values.dcBusToLoadOnDcConnection
)
: 0,
showValues: showValues
@ -298,7 +293,7 @@ function Topology(props: TopologyProps) {
amount: props.values.dcDCToBatteryConnection
? getAmount(
highestConnectionValue,
props.values.dcDCToBatteryConnection.values
props.values.dcDCToBatteryConnection
)
: 0,
showValues: showValues
@ -311,7 +306,7 @@ function Topology(props: TopologyProps) {
title: 'Battery',
data: props.values.battery,
connected:
props.values.batteryBox.values[0].value.toString() != 'Disabled'
props.values.batteryBox[0].value.toString() != 'Disabled'
}}
isLast={true}
isFirst={false}

View File

@ -1,12 +1,5 @@
import React from 'react';
import {
Box,
Card,
CardContent,
Divider,
Typography,
useTheme
} from '@mui/material';
import { Box, Card, CardContent, Divider, Typography } from '@mui/material';
import { AvatarWrapper } from 'src/layouts/TabsContainerWrapper';
import BatteryCharging60Icon from '@mui/icons-material/BatteryCharging60';
import OutletIcon from '@mui/icons-material/Outlet';
@ -14,21 +7,17 @@ import SolarPowerIcon from '@mui/icons-material/SolarPower';
import PowerInputIcon from '@mui/icons-material/PowerInput';
import SignalWifiConnectedNoInternet4Icon from '@mui/icons-material/SignalWifiConnectedNoInternet4';
import BoltIcon from '@mui/icons-material/Bolt';
import { BoxData } from '../Log/graph.util';
import { I_BoxDataValue } from '../Log/graph.util';
import inverterImage from 'src/Resources/images/inverter.png';
import acCurrentImage from 'src/Resources/images/ac-current.png';
import converterImage from 'src/Resources/images/converter.png';
export interface TopologyBoxProps {
title: string;
data?: BoxData;
data?: I_BoxDataValue[];
connected?: boolean;
}
const isInt = (value: number) => {
return value % 1 === 0;
};
function formatPower(value, unit) {
if (isNaN(value)) {
return 'Invalid';
@ -60,7 +49,6 @@ function formatPower(value, unit) {
}
function TopologyBox(props: TopologyBoxProps) {
const theme = useTheme();
const isMobile = window.innerWidth <= 1490;
return (
@ -106,7 +94,7 @@ function TopologyBox(props: TopologyBoxProps) {
>
{props.data && props.title === 'Battery' && (
<Typography variant="h5" noWrap>
{props.title} (x{props.data.values.length - 4})
{props.title} (x{props.data.length - 4})
</Typography>
)}
{props.title != 'Battery' && (
@ -245,7 +233,7 @@ function TopologyBox(props: TopologyBoxProps) {
pt: 1
}}
>
{props.data.values.map((boxData, index) => {
{props.data.map((boxData, index) => {
return (
<Typography key={index}>
{formatPower(boxData.value, boxData.unit) === 0

View File

@ -1,12 +1,12 @@
import React, { useEffect, useState } from 'react';
import './dotsAnimation.css';
import { BoxData } from '../Log/graph.util';
import { Box, Typography } from '@mui/material';
import { I_BoxDataValue } from '../Log/graph.util';
export interface TopologyFlowProps {
orientation: string;
position?: string;
data?: BoxData;
data?: I_BoxDataValue[];
amount?: number;
showValues: boolean;
}
@ -23,10 +23,6 @@ function getRandomStyleVertical() {
return { animationDelay, left };
}
const isInt = (value: number) => {
return value % 1 === 0;
};
function formatPower(value) {
if (isNaN(value)) {
return 'Invalid';
@ -107,7 +103,7 @@ function TopologyFlow(props: TopologyFlowProps) {
zIndex: 1
}}
>
{props.showValues && props.data.values[0].value != 0 && (
{props.showValues && props.data[0].value != 0 && (
<Typography
sx={{
marginTop: '1px',
@ -118,12 +114,12 @@ function TopologyFlow(props: TopologyFlowProps) {
zIndex: 1
}}
>
{formatPower(props.data.values[0].value) === 0
{formatPower(props.data[0].value) === 0
? null
: formatPower(props.data.values[0].value)}
{formatPower(props.data.values[0].value) === 0
: formatPower(props.data[0].value)}
{formatPower(props.data[0].value) === 0
? null
: props.data.values[0].unit}
: props.data[0].unit}
</Typography>
)}
</Box>
@ -158,13 +154,13 @@ function TopologyFlow(props: TopologyFlowProps) {
>
{props.orientation === 'horizontal' &&
props.data &&
props.data.values[0].value != 0 && (
props.data[0].value != 0 && (
<>
<div className="container">
{dotStyles.map((style, index) => (
<div
className={
(props.data.values[0].value as number) >= 0
(props.data[0].value as number) >= 0
? 'dotRight'
: 'dotLeft'
}
@ -181,7 +177,7 @@ function TopologyFlow(props: TopologyFlowProps) {
{props.orientation === 'vertical' &&
props.data &&
props.data.values[0].value != 0 && (
props.data[0].value != 0 && (
<div className="dot-container">
{dotStylesVertical.map((style, index) => (
<div