Differentiate between Salimax and Salidomo (csv and json)

so that the frontend supports both
This commit is contained in:
Noe 2025-02-25 10:23:37 +01:00
parent 8b0b49fa30
commit abeac4f49a
13 changed files with 3270 additions and 864 deletions

View File

@ -11,6 +11,7 @@ import {
TableRow, TableRow,
Typography Typography
} from '@mui/material'; } from '@mui/material';
import { TopologyValues } from '../Log/graph.util';
import { import {
Link, Link,
Route, Route,
@ -18,17 +19,16 @@ import {
useLocation, useLocation,
useNavigate useNavigate
} from 'react-router-dom'; } from 'react-router-dom';
import Button from '@mui/material/Button';
import { FormattedMessage } from 'react-intl';
import { I_S3Credentials } from '../../../interfaces/S3Types'; import { I_S3Credentials } from '../../../interfaces/S3Types';
import routes from '../../../Resources/routes.json'; import routes from '../../../Resources/routes.json';
import CircularProgress from '@mui/material/CircularProgress'; import CircularProgress from '@mui/material/CircularProgress';
import { JSONRecordData } from '../Log/graph.util';
import Button from '@mui/material/Button';
import { FormattedMessage } from 'react-intl';
import MainStats from './MainStats';
import DetailedBatteryView from './DetailedBatteryView'; import DetailedBatteryView from './DetailedBatteryView';
import MainStats from './MainStats';
interface BatteryViewProps { interface BatteryViewProps {
values: JSONRecordData; values: TopologyValues;
s3Credentials: I_S3Credentials; s3Credentials: I_S3Credentials;
installationId: number; installationId: number;
productNum: number; productNum: number;
@ -39,15 +39,12 @@ function BatteryView(props: BatteryViewProps) {
if (props.values === null && props.connected == true) { if (props.values === null && props.connected == true) {
return null; return null;
} }
const currentLocation = useLocation(); const currentLocation = useLocation();
const navigate = useNavigate(); const navigate = useNavigate();
const sortedBatteryView =
const sortedBatteryView = Object.entries(props.values.Battery.Devices) props.values != null
.map(([BatteryId, battery]) => { ? [...props.values.batteryView].sort((a, b) => b.BatteryId - a.BatteryId)
return { BatteryId, battery }; // Here we return an object with the id and device : [];
})
.sort((a, b) => parseInt(b.BatteryId) - parseInt(a.BatteryId));
const [loading, setLoading] = useState(sortedBatteryView.length == 0); const [loading, setLoading] = useState(sortedBatteryView.length == 0);
@ -55,13 +52,13 @@ function BatteryView(props: BatteryViewProps) {
navigate(routes.mainstats); navigate(routes.mainstats);
}; };
// const findBatteryData = (batteryId: number) => { const findBatteryData = (batteryId: number) => {
// for (let i = 0; i < props.values.batteryView.length; i++) { for (let i = 0; i < props.values.batteryView.length; i++) {
// if (props.values.batteryView[i].BatteryId == batteryId) { if (props.values.batteryView[i].BatteryId == batteryId) {
// return props.values.batteryView[i]; return props.values.batteryView[i];
// } }
// } }
// }; };
useEffect(() => { useEffect(() => {
if (sortedBatteryView.length == 0) { if (sortedBatteryView.length == 0) {
@ -179,23 +176,20 @@ function BatteryView(props: BatteryViewProps) {
></MainStats> ></MainStats>
} }
/> />
{Object.entries(props.values.Battery.Devices).map( {props.values.batteryView.map((battery) => (
([BatteryId, battery]) => (
<Route <Route
key={routes.detailed_view + BatteryId} key={routes.detailed_view + battery.BatteryId}
path={routes.detailed_view + BatteryId} path={routes.detailed_view + battery.BatteryId}
element={ element={
<DetailedBatteryView <DetailedBatteryView
batteryId={Number(BatteryId)}
s3Credentials={props.s3Credentials} s3Credentials={props.s3Credentials}
batteryData={battery} batteryData={findBatteryData(battery.BatteryId)}
installationId={props.installationId} installationId={props.installationId}
productNum={props.productNum} productNum={props.productNum}
></DetailedBatteryView> ></DetailedBatteryView>
} }
/> />
) ))}
)}
</Routes> </Routes>
</Grid> </Grid>
@ -225,9 +219,9 @@ function BatteryView(props: BatteryViewProps) {
</TableRow> </TableRow>
</TableHead> </TableHead>
<TableBody> <TableBody>
{sortedBatteryView.map(({ BatteryId, battery }) => ( {sortedBatteryView.map((battery) => (
<TableRow <TableRow
key={BatteryId} key={battery.BatteryId}
style={{ style={{
height: '10px' height: '10px'
}} }}
@ -240,9 +234,9 @@ function BatteryView(props: BatteryViewProps) {
> >
<Link <Link
style={{ color: 'black' }} style={{ color: 'black' }}
to={routes.detailed_view + BatteryId} to={routes.detailed_view + battery.BatteryId.toString()}
> >
{'Node ' + BatteryId} {'Node ' + battery.BatteryId}
</Link> </Link>
</TableCell> </TableCell>
<TableCell <TableCell
@ -259,7 +253,7 @@ function BatteryView(props: BatteryViewProps) {
textAlign: 'center' textAlign: 'center'
}} }}
> >
{battery.Dc.Power.value + ' W'} {battery.Power.value + ' ' + battery.Power.unit}
</TableCell> </TableCell>
<TableCell <TableCell
sx={{ sx={{
@ -267,14 +261,15 @@ function BatteryView(props: BatteryViewProps) {
textAlign: 'center', textAlign: 'center',
backgroundColor: backgroundColor:
battery.Dc.Voltage.value < 44 || battery.Voltage.value < 44 ||
battery.Dc.Voltage.value > 57 battery.Voltage.value > 57
? '#FF033E' ? '#FF033E'
: '#32CD32', : '#32CD32',
color: battery.Dc.Voltage.value ? 'inherit' : 'white' color:
battery.Voltage.value === '' ? 'white' : 'inherit'
}} }}
> >
{battery.Dc.Voltage.value + ' V'} {battery.Voltage.value + ' ' + battery.Voltage.unit}
</TableCell> </TableCell>
<TableCell <TableCell
sx={{ sx={{
@ -286,144 +281,47 @@ function BatteryView(props: BatteryViewProps) {
: battery.Soc.value < 50 : battery.Soc.value < 50
? '#ffbf00' ? '#ffbf00'
: '#32CD32', : '#32CD32',
color: battery.Soc.value ? 'inherit' : 'white' color: battery.Soc.value === '' ? 'white' : 'inherit'
}} }}
> >
{battery.Soc.value + ' %'} {battery.Soc.value + ' ' + battery.Soc.unit}
</TableCell> </TableCell>
<TableCell <TableCell
sx={{ sx={{
width: '10%', width: '10%',
textAlign: 'center', textAlign: 'center',
backgroundColor: backgroundColor:
battery.Temperatures.Cells.Average.value > 300 battery.AverageTemperature.value > 300
? '#FF033E' ? '#FF033E'
: battery.Temperatures.Cells.Average.value > 280 : battery.AverageTemperature.value > 280
? '#ffbf00' ? '#ffbf00'
: battery.Temperatures.Cells.Average.value < 245 : battery.AverageTemperature.value < 245
? '#008FFB' ? '#008FFB'
: '#32CD32' : '#32CD32'
}} }}
> >
{battery.Temperatures.Cells.Average.value + ' C'} {battery.AverageTemperature.value +
' ' +
battery.AverageTemperature.unit}
</TableCell> </TableCell>
{/*{props.productNum === 0 && (*/}
{/* <>*/}
{/* <TableCell*/}
{/* style={{*/}
{/* width: '20%',*/}
{/* textAlign: 'center',*/}
{/* padding: '8px',*/}
{/* fontWeight:*/}
{/* battery.Warnings.value !== ''*/}
{/* ? 'bold'*/}
{/* : 'inherit',*/}
{/* backgroundColor:*/}
{/* battery.Warnings.value === ''*/}
{/* ? 'inherit'*/}
{/* : '#ff9900',*/}
{/* color:*/}
{/* battery.Warnings.value != '' ? 'black' : 'inherit'*/}
{/* }}*/}
{/* >*/}
{/* {battery.Warnings.value === '' ? (*/}
{/* 'None'*/}
{/* ) : battery.Warnings.value.toString().split('-')*/}
{/* .length > 1 ? (*/}
{/* <Link*/}
{/* style={{ color: 'black' }}*/}
{/* to={*/}
{/* currentLocation.pathname.substring(*/}
{/* 0,*/}
{/* currentLocation.pathname.lastIndexOf('/') + 1*/}
{/* ) +*/}
{/* routes.log +*/}
{/* '?open=warning'*/}
{/* }*/}
{/* >*/}
{/* Multiple Warnings*/}
{/* </Link>*/}
{/* ) : (*/}
{/* battery.Warnings.value*/}
{/* )}*/}
{/* </TableCell>*/}
{/* <TableCell*/}
{/* sx={{*/}
{/* width: '20%',*/}
{/* textAlign: 'center',*/}
{/* fontWeight:*/}
{/* battery.Alarms.value !== '' ? 'bold' : 'inherit',*/}
{/* backgroundColor:*/}
{/* battery.Alarms.value === ''*/}
{/* ? 'inherit'*/}
{/* : '#FF033E',*/}
{/* color:*/}
{/* battery.Alarms.value != '' ? 'black' : 'inherit'*/}
{/* }}*/}
{/* >*/}
{/* {battery.Alarms.value === '' ? (*/}
{/* 'None'*/}
{/* ) : battery.Alarms.value.toString().split('-')*/}
{/* .length > 1 ? (*/}
{/* <Link*/}
{/* style={{ color: 'black' }}*/}
{/* to={*/}
{/* currentLocation.pathname.substring(*/}
{/* 0,*/}
{/* currentLocation.pathname.lastIndexOf('/') + 1*/}
{/* ) +*/}
{/* routes.log +*/}
{/* '?open=error'*/}
{/* }*/}
{/* >*/}
{/* Multiple Alarms*/}
{/* </Link>*/}
{/* ) : (*/}
{/* battery.Alarms.value*/}
{/* )}*/}
{/* </TableCell>*/}
{/* </>*/}
{/*)}*/}
{props.productNum === 1 && (
<>
<TableCell <TableCell
style={{ style={{
width: '20%', width: '20%',
textAlign: 'center', textAlign: 'center',
padding: '8px', padding: '8px',
fontWeight: fontWeight:
Number(battery.Warnings) !== 0 battery.Warnings.value !== '' ? 'bold' : 'inherit',
? 'bold'
: 'inherit',
backgroundColor: backgroundColor:
Number(battery.Warnings) === 0 battery.Warnings.value === '' ? 'inherit' : '#ff9900',
? 'inherit'
: '#ff9900',
color: color:
Number(battery.Warnings) != 0 battery.Warnings.value != '' ? 'black' : 'inherit'
? 'black'
: 'inherit'
}} }}
> >
{Number(battery.Warnings) === 0 ? ( {battery.Warnings.value === '' ? (
'None' 'None'
) : Number(battery.Warnings) === 1 ? ( ) : battery.Warnings.value.toString().split('-').length >
<Link 1 ? (
style={{ color: 'black' }}
to={
currentLocation.pathname.substring(
0,
currentLocation.pathname.lastIndexOf('/') + 1
) +
routes.log +
'?open=warning'
}
>
New Warning
</Link>
) : (
<Link <Link
style={{ color: 'black' }} style={{ color: 'black' }}
to={ to={
@ -437,6 +335,8 @@ function BatteryView(props: BatteryViewProps) {
> >
Multiple Warnings Multiple Warnings
</Link> </Link>
) : (
battery.Warnings.value
)} )}
</TableCell> </TableCell>
<TableCell <TableCell
@ -444,32 +344,16 @@ function BatteryView(props: BatteryViewProps) {
width: '20%', width: '20%',
textAlign: 'center', textAlign: 'center',
fontWeight: fontWeight:
Number(battery.Alarms) !== 0 ? 'bold' : 'inherit', battery.Alarms.value !== '' ? 'bold' : 'inherit',
backgroundColor: backgroundColor:
Number(battery.Alarms) === 0 battery.Alarms.value === '' ? 'inherit' : '#FF033E',
? 'inherit' color: battery.Alarms.value != '' ? 'black' : 'inherit'
: '#FF033E',
color:
Number(battery.Alarms) != 0 ? 'black' : 'inherit'
}} }}
> >
{Number(battery.Alarms) === 0 ? ( {battery.Alarms.value === '' ? (
'None' 'None'
) : Number(battery.Alarms) === 1 ? ( ) : battery.Alarms.value.toString().split('-').length >
<Link 1 ? (
style={{ color: 'black' }}
to={
currentLocation.pathname.substring(
0,
currentLocation.pathname.lastIndexOf('/') + 1
) +
routes.log +
'?open=error'
}
>
New Alarm
</Link>
) : (
<Link <Link
style={{ color: 'black' }} style={{ color: 'black' }}
to={ to={
@ -483,10 +367,10 @@ function BatteryView(props: BatteryViewProps) {
> >
Multiple Alarms Multiple Alarms
</Link> </Link>
) : (
battery.Alarms.value
)} )}
</TableCell> </TableCell>
</>
)}
</TableRow> </TableRow>
))} ))}
</TableBody> </TableBody>

View File

@ -0,0 +1,493 @@
import React, { useEffect, useState } from 'react';
import {
Container,
Grid,
Paper,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Typography
} from '@mui/material';
import {
Link,
Route,
Routes,
useLocation,
useNavigate
} from 'react-router-dom';
import { I_S3Credentials } from '../../../interfaces/S3Types';
import routes from '../../../Resources/routes.json';
import CircularProgress from '@mui/material/CircularProgress';
import { JSONRecordData } from '../Log/graph.util';
import Button from '@mui/material/Button';
import { FormattedMessage } from 'react-intl';
import MainStatsSalidomo from './MainStatsSalidomo';
import DetailedBatteryViewSalidomo from './DetailedBatteryViewSalidomo';
interface BatteryViewProps {
values: JSONRecordData;
s3Credentials: I_S3Credentials;
installationId: number;
productNum: number;
connected: boolean;
}
function BatteryViewSalidomo(props: BatteryViewProps) {
if (props.values === null && props.connected == true) {
return null;
}
const currentLocation = useLocation();
const navigate = useNavigate();
const sortedBatteryView = Object.entries(props.values.Battery.Devices)
.map(([BatteryId, battery]) => {
return { BatteryId, battery }; // Here we return an object with the id and device
})
.sort((a, b) => parseInt(b.BatteryId) - parseInt(a.BatteryId));
const [loading, setLoading] = useState(sortedBatteryView.length == 0);
const handleMainStatsButton = () => {
navigate(routes.mainstats);
};
useEffect(() => {
if (sortedBatteryView.length == 0) {
setLoading(true);
} else {
setLoading(false);
}
}, [sortedBatteryView]);
return (
<>
{!props.connected && (
<Container
maxWidth="xl"
sx={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
height: '70vh'
}}
>
<CircularProgress size={60} style={{ color: '#ffc04d' }} />
<Typography
variant="body2"
style={{ color: 'black', fontWeight: 'bold' }}
mt={2}
>
Unable to communicate with the installation
</Typography>
<Typography variant="body2" style={{ color: 'black' }}>
Please wait or refresh the page
</Typography>
</Container>
)}
{loading && props.connected && (
<Container
maxWidth="xl"
sx={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
height: '70vh'
}}
>
<CircularProgress size={60} style={{ color: '#ffc04d' }} />
<Typography
variant="body2"
style={{ color: 'black', fontWeight: 'bold' }}
mt={2}
>
Battery service is not available at the moment
</Typography>
<Typography variant="body2" style={{ color: 'black' }}>
Please wait or refresh the page
</Typography>
</Container>
)}
{!loading && props.connected && (
<Container maxWidth="xl">
<Grid container>
<Grid
item
xs={6}
md={6}
sx={{
display:
!currentLocation.pathname.includes('detailed_view') &&
!currentLocation.pathname.includes('mainstats')
? 'block'
: 'none'
}}
>
<Button
variant="contained"
sx={{
marginTop: '20px',
backgroundColor: '#808080',
color: '#000000',
'&:hover': { bgcolor: '#f7b34d' }
}}
>
<FormattedMessage
id="battery_view"
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 container>
<Routes>
<Route
path={routes.mainstats + '*'}
element={
<MainStatsSalidomo
s3Credentials={props.s3Credentials}
id={props.installationId}
></MainStatsSalidomo>
}
/>
{Object.entries(props.values.Battery.Devices).map(
([BatteryId, battery]) => (
<Route
key={routes.detailed_view + BatteryId}
path={routes.detailed_view + BatteryId}
element={
<DetailedBatteryViewSalidomo
batteryId={Number(BatteryId)}
s3Credentials={props.s3Credentials}
batteryData={battery}
installationId={props.installationId}
productNum={props.productNum}
></DetailedBatteryViewSalidomo>
}
/>
)
)}
</Routes>
</Grid>
<TableContainer
component={Paper}
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>
<TableRow>
<TableCell align="center">Battery</TableCell>
<TableCell align="center">Firmware</TableCell>
<TableCell align="center">Power</TableCell>
<TableCell align="center">Voltage</TableCell>
<TableCell align="center">SoC</TableCell>
<TableCell align="center">Temperature</TableCell>
<TableCell align="center">Warnings</TableCell>
<TableCell align="center">Alarms</TableCell>
</TableRow>
</TableHead>
<TableBody>
{sortedBatteryView.map(({ BatteryId, battery }) => (
<TableRow
key={BatteryId}
style={{
height: '10px'
}}
>
<TableCell
component="th"
scope="row"
align="center"
sx={{ fontWeight: 'bold' }}
>
<Link
style={{ color: 'black' }}
to={routes.detailed_view + BatteryId}
>
{'Node ' + BatteryId}
</Link>
</TableCell>
<TableCell
sx={{
width: '10%',
textAlign: 'center'
}}
>
{battery.FwVersion.value}
</TableCell>
<TableCell
sx={{
width: '10%',
textAlign: 'center'
}}
>
{battery.Dc.Power.value + ' W'}
</TableCell>
<TableCell
sx={{
width: '10%',
textAlign: 'center',
backgroundColor:
battery.Dc.Voltage.value < 44 ||
battery.Dc.Voltage.value > 57
? '#FF033E'
: '#32CD32',
color: battery.Dc.Voltage.value ? 'inherit' : 'white'
}}
>
{battery.Dc.Voltage.value + ' V'}
</TableCell>
<TableCell
sx={{
width: '10%',
textAlign: 'center',
backgroundColor:
battery.Soc.value < 20
? '#FF033E'
: battery.Soc.value < 50
? '#ffbf00'
: '#32CD32',
color: battery.Soc.value ? 'inherit' : 'white'
}}
>
{battery.Soc.value + ' %'}
</TableCell>
<TableCell
sx={{
width: '10%',
textAlign: 'center',
backgroundColor:
battery.Temperatures.Cells.Average.value > 300
? '#FF033E'
: battery.Temperatures.Cells.Average.value > 280
? '#ffbf00'
: battery.Temperatures.Cells.Average.value < 245
? '#008FFB'
: '#32CD32'
}}
>
{battery.Temperatures.Cells.Average.value + ' C'}
</TableCell>
{/*{props.productNum === 0 && (*/}
{/* <>*/}
{/* <TableCell*/}
{/* style={{*/}
{/* width: '20%',*/}
{/* textAlign: 'center',*/}
{/* padding: '8px',*/}
{/* fontWeight:*/}
{/* battery.Warnings.value !== ''*/}
{/* ? 'bold'*/}
{/* : 'inherit',*/}
{/* backgroundColor:*/}
{/* battery.Warnings.value === ''*/}
{/* ? 'inherit'*/}
{/* : '#ff9900',*/}
{/* color:*/}
{/* battery.Warnings.value != '' ? 'black' : 'inherit'*/}
{/* }}*/}
{/* >*/}
{/* {battery.Warnings.value === '' ? (*/}
{/* 'None'*/}
{/* ) : battery.Warnings.value.toString().split('-')*/}
{/* .length > 1 ? (*/}
{/* <Link*/}
{/* style={{ color: 'black' }}*/}
{/* to={*/}
{/* currentLocation.pathname.substring(*/}
{/* 0,*/}
{/* currentLocation.pathname.lastIndexOf('/') + 1*/}
{/* ) +*/}
{/* routes.log +*/}
{/* '?open=warning'*/}
{/* }*/}
{/* >*/}
{/* Multiple Warnings*/}
{/* </Link>*/}
{/* ) : (*/}
{/* battery.Warnings.value*/}
{/* )}*/}
{/* </TableCell>*/}
{/* <TableCell*/}
{/* sx={{*/}
{/* width: '20%',*/}
{/* textAlign: 'center',*/}
{/* fontWeight:*/}
{/* battery.Alarms.value !== '' ? 'bold' : 'inherit',*/}
{/* backgroundColor:*/}
{/* battery.Alarms.value === ''*/}
{/* ? 'inherit'*/}
{/* : '#FF033E',*/}
{/* color:*/}
{/* battery.Alarms.value != '' ? 'black' : 'inherit'*/}
{/* }}*/}
{/* >*/}
{/* {battery.Alarms.value === '' ? (*/}
{/* 'None'*/}
{/* ) : battery.Alarms.value.toString().split('-')*/}
{/* .length > 1 ? (*/}
{/* <Link*/}
{/* style={{ color: 'black' }}*/}
{/* to={*/}
{/* currentLocation.pathname.substring(*/}
{/* 0,*/}
{/* currentLocation.pathname.lastIndexOf('/') + 1*/}
{/* ) +*/}
{/* routes.log +*/}
{/* '?open=error'*/}
{/* }*/}
{/* >*/}
{/* Multiple Alarms*/}
{/* </Link>*/}
{/* ) : (*/}
{/* battery.Alarms.value*/}
{/* )}*/}
{/* </TableCell>*/}
{/* </>*/}
{/*)}*/}
{props.productNum === 1 && (
<>
<TableCell
style={{
width: '20%',
textAlign: 'center',
padding: '8px',
fontWeight:
Number(battery.Warnings) !== 0
? 'bold'
: 'inherit',
backgroundColor:
Number(battery.Warnings) === 0
? 'inherit'
: '#ff9900',
color:
Number(battery.Warnings) != 0
? 'black'
: 'inherit'
}}
>
{Number(battery.Warnings) === 0 ? (
'None'
) : Number(battery.Warnings) === 1 ? (
<Link
style={{ color: 'black' }}
to={
currentLocation.pathname.substring(
0,
currentLocation.pathname.lastIndexOf('/') + 1
) +
routes.log +
'?open=warning'
}
>
New Warning
</Link>
) : (
<Link
style={{ color: 'black' }}
to={
currentLocation.pathname.substring(
0,
currentLocation.pathname.lastIndexOf('/') + 1
) +
routes.log +
'?open=warning'
}
>
Multiple Warnings
</Link>
)}
</TableCell>
<TableCell
sx={{
width: '20%',
textAlign: 'center',
fontWeight:
Number(battery.Alarms) !== 0 ? 'bold' : 'inherit',
backgroundColor:
Number(battery.Alarms) === 0
? 'inherit'
: '#FF033E',
color:
Number(battery.Alarms) != 0 ? 'black' : 'inherit'
}}
>
{Number(battery.Alarms) === 0 ? (
'None'
) : Number(battery.Alarms) === 1 ? (
<Link
style={{ color: 'black' }}
to={
currentLocation.pathname.substring(
0,
currentLocation.pathname.lastIndexOf('/') + 1
) +
routes.log +
'?open=error'
}
>
New Alarm
</Link>
) : (
<Link
style={{ color: 'black' }}
to={
currentLocation.pathname.substring(
0,
currentLocation.pathname.lastIndexOf('/') + 1
) +
routes.log +
'?open=error'
}
>
Multiple Alarms
</Link>
)}
</TableCell>
</>
)}
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</Container>
)}
</>
);
}
export default BatteryViewSalidomo;

View File

@ -16,7 +16,7 @@ import {
TableRow, TableRow,
Typography Typography
} from '@mui/material'; } from '@mui/material';
import { Device } from '../Log/graph.util'; import { Battery } from '../Log/graph.util';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import ArrowBackIcon from '@mui/icons-material/ArrowBack'; import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import Button from '@mui/material/Button'; import Button from '@mui/material/Button';
@ -25,9 +25,8 @@ import { UserType } from '../../../interfaces/UserTypes';
import { UserContext } from '../../../contexts/userContext'; import { UserContext } from '../../../contexts/userContext';
interface DetailedBatteryViewProps { interface DetailedBatteryViewProps {
batteryId: number;
s3Credentials: I_S3Credentials; s3Credentials: I_S3Credentials;
batteryData: Device; batteryData: Battery;
installationId: number; installationId: number;
productNum: number; productNum: number;
} }
@ -36,7 +35,6 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
if (props.batteryData === null) { if (props.batteryData === null) {
return null; return null;
} }
const navigate = useNavigate(); const navigate = useNavigate();
const [openModalFirmwareUpdate, setOpenModalFirmwareUpdate] = useState(false); const [openModalFirmwareUpdate, setOpenModalFirmwareUpdate] = useState(false);
const [openModalResultFirmwareUpdate, setOpenModalResultFirmwareUpdate] = const [openModalResultFirmwareUpdate, setOpenModalResultFirmwareUpdate] =
@ -67,35 +65,35 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
}; };
const [GreenisBlinking, setGreenisBlinking] = useState( const [GreenisBlinking, setGreenisBlinking] = useState(
props.batteryData.Leds.Green.value === 'Blinking' props.batteryData.GreenLeds.value === 'Blinking'
); );
const [AmberisBlinking, setAmberisBlinking] = useState( const [AmberisBlinking, setAmberisBlinking] = useState(
props.batteryData.Leds.Amber.value === 'Blinking' props.batteryData.AmberLeds.value === 'Blinking'
); );
const [RedisBlinking, setRedisBlinking] = useState( const [RedisBlinking, setRedisBlinking] = useState(
props.batteryData.Leds.Red.value === 'Blinking' props.batteryData.RedLeds.value === 'Blinking'
); );
const [BlueisBlinking, setBlueisBlinking] = useState( const [BlueisBlinking, setBlueisBlinking] = useState(
props.batteryData.Leds.Blue.value === 'Blinking' props.batteryData.BlueLeds.value === 'Blinking'
); );
useEffect(() => { useEffect(() => {
const intervalId = setInterval(() => { const intervalId = setInterval(() => {
if (props.batteryData.Leds.Amber.value === 'Blinking') { if (props.batteryData.AmberLeds.value === 'Blinking') {
setAmberisBlinking((prevIsBlinking) => !prevIsBlinking); setAmberisBlinking((prevIsBlinking) => !prevIsBlinking);
} }
if (props.batteryData.Leds.Red.value === 'Blinking') { if (props.batteryData.RedLeds.value === 'Blinking') {
setRedisBlinking((prevIsBlinking) => !prevIsBlinking); setRedisBlinking((prevIsBlinking) => !prevIsBlinking);
} }
if (props.batteryData.Leds.Blue.value === 'Blinking') { if (props.batteryData.BlueLeds.value === 'Blinking') {
setBlueisBlinking((prevIsBlinking) => !prevIsBlinking); setBlueisBlinking((prevIsBlinking) => !prevIsBlinking);
} }
if (props.batteryData.Leds.Green.value === 'Blinking') { if (props.batteryData.GreenLeds.value === 'Blinking') {
setGreenisBlinking((prevIsBlinking) => !prevIsBlinking); setGreenisBlinking((prevIsBlinking) => !prevIsBlinking);
} }
}, 500); // Blink every 500 milliseconds }, 500); // Blink every 500 milliseconds
@ -131,7 +129,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
const res = await axiosConfig const res = await axiosConfig
.post( .post(
`/UpdateFirmware?batteryNode=${props.batteryId.toString()}&installationId=${ `/UpdateFirmware?batteryNode=${props.batteryData.BatteryId.toString()}&installationId=${
props.installationId props.installationId
}&version=${selectedVersion}` }&version=${selectedVersion}`
) )
@ -171,7 +169,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
try { try {
// Start the job to generate the battery log // Start the job to generate the battery log
const startRes = await axiosConfig.post( const startRes = await axiosConfig.post(
`/StartDownloadBatteryLog?batteryNode=${props.batteryId.toString()}&installationId=${ `/StartDownloadBatteryLog?batteryNode=${props.batteryData.BatteryId.toString()}&installationId=${
props.installationId props.installationId
}` }`
); );
@ -637,7 +635,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
fontWeight: 'bold' fontWeight: 'bold'
}} }}
> >
{'Node ' + props.batteryId} {'Node ' + props.batteryData.BatteryId}
</Typography> </Typography>
<div style={batteryStyle}> <div style={batteryStyle}>
@ -645,11 +643,8 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
style={{ style={{
...batteryStringStyle, ...batteryStringStyle,
backgroundColor: backgroundColor:
props.batteryData.BatteryStrings.String1Active.value == props.batteryData.String1Active.value == 'True' ||
'True' || Number(props.batteryData.String1Active.value) == 0
Number(
props.batteryData.BatteryStrings.String1Active.value
) == 0
? '#32CD32' ? '#32CD32'
: '#FF033E' : '#FF033E'
}} }}
@ -658,11 +653,8 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
style={{ style={{
...batteryStringStyle, ...batteryStringStyle,
backgroundColor: backgroundColor:
props.batteryData.BatteryStrings.String2Active.value == props.batteryData.String2Active.value == 'True' ||
'True' || Number(props.batteryData.String2Active.value) == 0
Number(
props.batteryData.BatteryStrings.String2Active.value
) == 0
? '#32CD32' ? '#32CD32'
: '#FF033E' : '#FF033E'
}} }}
@ -671,11 +663,8 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
style={{ style={{
...batteryStringStyle, ...batteryStringStyle,
backgroundColor: backgroundColor:
props.batteryData.BatteryStrings.String3Active.value == props.batteryData.String3Active.value == 'True' ||
'True' || Number(props.batteryData.String3Active.value) == 0
Number(
props.batteryData.BatteryStrings.String3Active.value
) == 0
? '#32CD32' ? '#32CD32'
: '#FF033E' : '#FF033E'
}} }}
@ -684,11 +673,8 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
style={{ style={{
...batteryStringStyle, ...batteryStringStyle,
backgroundColor: backgroundColor:
props.batteryData.BatteryStrings.String4Active.value == props.batteryData.String4Active.value == 'True' ||
'True' || Number(props.batteryData.String4Active.value) == 0
Number(
props.batteryData.BatteryStrings.String4Active.value
) == 0
? '#32CD32' ? '#32CD32'
: '#FF033E' : '#FF033E'
}} }}
@ -697,11 +683,8 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
style={{ style={{
...batteryStringStyle, ...batteryStringStyle,
backgroundColor: backgroundColor:
props.batteryData.BatteryStrings.String5Active.value == props.batteryData.String5Active.value == 'True' ||
'True' || Number(props.batteryData.String5Active.value) == 0
Number(
props.batteryData.BatteryStrings.String5Active.value
) == 0
? '#32CD32' ? '#32CD32'
: '#FF033E' : '#FF033E'
}} }}
@ -716,7 +699,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
marginTop: '-10px', marginTop: '-10px',
borderRadius: '50%', borderRadius: '50%',
backgroundColor: backgroundColor:
props.batteryData.Leds.Green.value === 'On' || props.batteryData.GreenLeds.value === 'On' ||
GreenisBlinking GreenisBlinking
? 'green' ? 'green'
: 'transparent' : 'transparent'
@ -731,7 +714,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
marginTop: '10px', marginTop: '10px',
borderRadius: '50%', borderRadius: '50%',
backgroundColor: backgroundColor:
props.batteryData.Leds.Amber.value === 'On' || props.batteryData.AmberLeds.value === 'On' ||
AmberisBlinking AmberisBlinking
? 'orange' ? 'orange'
: 'transparent' : 'transparent'
@ -746,7 +729,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
marginTop: '10px', marginTop: '10px',
borderRadius: '50%', borderRadius: '50%',
backgroundColor: backgroundColor:
props.batteryData.Leds.Blue.value === 'On' || BlueisBlinking props.batteryData.BlueLeds.value === 'On' || BlueisBlinking
? '#00ccff' ? '#00ccff'
: 'transparent' : 'transparent'
}} }}
@ -760,7 +743,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
marginTop: '10px', marginTop: '10px',
borderRadius: '50%', borderRadius: '50%',
backgroundColor: backgroundColor:
props.batteryData.Leds.Red.value === 'On' || RedisBlinking props.batteryData.RedLeds.value === 'On' || RedisBlinking
? 'red' ? 'red'
: 'transparent' : 'transparent'
}} }}
@ -820,7 +803,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.Dc.Voltage.value + ' V'} {props.batteryData.Voltage.value +
' ' +
props.batteryData.Voltage.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
@ -840,7 +825,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.Dc.Current.value + ' A'} {props.batteryData.Current.value +
' ' +
props.batteryData.Current.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
@ -860,7 +847,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.Dc.Power.value + ' W'} {props.batteryData.Power.value +
' ' +
props.batteryData.Power.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
@ -881,7 +870,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.BusCurrent.value + ' A'} {props.batteryData.BusCurrent.value +
' ' +
props.batteryData.BusCurrent.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
@ -901,7 +892,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.CellsCurrent.value + ' A'} {props.batteryData.CellsCurrent.value +
' ' +
props.batteryData.CellsCurrent.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
@ -921,7 +914,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.HeatingCurrent.value + ' A'} {props.batteryData.HeatingCurrent.value +
' ' +
props.batteryData.HeatingCurrent.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
@ -942,7 +937,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.Soc.value + ' %'} {props.batteryData.Soc.value +
' ' +
props.batteryData.Soc.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
</TableBody> </TableBody>
@ -952,200 +949,200 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
</Grid> </Grid>
{/*----------------------------------------------------------------------------------------------------------------------------------*/} {/*----------------------------------------------------------------------------------------------------------------------------------*/}
{/*{props.productNum === 0 && (*/} {props.productNum === 0 && (
{/* <>*/} <>
{/* <Grid item md={3} xs={3}>*/} <Grid item md={3} xs={3}>
{/* <Card*/} <Card
{/* sx={{*/} sx={{
{/* overflow: 'visible',*/} overflow: 'visible',
{/* marginTop: '30px',*/} marginTop: '30px',
{/* marginLeft: '20px',*/} marginLeft: '20px',
{/* display: 'flex',*/} display: 'flex',
{/* flexDirection: 'column',*/} flexDirection: 'column',
{/* alignItems: 'center',*/} alignItems: 'center',
{/* border: '2px solid #ccc',*/} border: '2px solid #ccc',
{/* borderRadius: '12px'*/} borderRadius: '12px'
{/* }}*/} }}
{/* >*/} >
{/* <Typography*/} <Typography
{/* variant="h6"*/} variant="h6"
{/* component="div"*/} component="div"
{/* sx={{*/} sx={{
{/* marginTop: '10px',*/} marginTop: '10px',
{/* borderBottom: '1px solid #ccc',*/} borderBottom: '1px solid #ccc',
{/* fontWeight: 'bold'*/} fontWeight: 'bold'
{/* }}*/} }}
{/* >*/} >
{/* Temperature*/} Temperature
{/* </Typography>*/} </Typography>
{/* <TableContainer*/} <TableContainer
{/* component={Paper}*/} component={Paper}
{/* sx={{ marginTop: '20px', width: '100%' }}*/} sx={{ marginTop: '20px', width: '100%' }}
{/* >*/} >
{/* <Table size="medium" aria-label="a dense table">*/} <Table size="medium" aria-label="a dense table">
{/* <TableBody>*/} <TableBody>
{/* <TableRow>*/} <TableRow>
{/* <TableCell*/} <TableCell
{/* component="th"*/} component="th"
{/* scope="row"*/} scope="row"
{/* align="left"*/} align="left"
{/* sx={{ fontWeight: 'bold' }}*/} sx={{ fontWeight: 'bold' }}
{/* >*/} >
{/* Heating*/} Heating
{/* </TableCell>*/} </TableCell>
{/* <TableCell*/} <TableCell
{/* align="right"*/} align="right"
{/* sx={{*/} sx={{
{/* width: '6ch',*/} width: '6ch',
{/* whiteSpace: 'nowrap',*/} whiteSpace: 'nowrap',
{/* paddingRight: '12px'*/} paddingRight: '12px'
{/* }}*/} }}
{/* >*/} >
{/* {props.batteryData.HeatingTemperature.value +*/} {props.batteryData.HeatingTemperature.value +
{/* ' ' +*/} ' ' +
{/* props.batteryData.HeatingTemperature.unit}*/} props.batteryData.HeatingTemperature.unit}
{/* </TableCell>*/} </TableCell>
{/* </TableRow>*/} </TableRow>
{/* <TableRow>*/} <TableRow>
{/* <TableCell*/} <TableCell
{/* component="th"*/} component="th"
{/* scope="row"*/} scope="row"
{/* align="left"*/} align="left"
{/* sx={{ fontWeight: 'bold' }}*/} sx={{ fontWeight: 'bold' }}
{/* >*/} >
{/* Board Temperature*/} Board Temperature
{/* </TableCell>*/} </TableCell>
{/* <TableCell*/} <TableCell
{/* align="right"*/} align="right"
{/* sx={{*/} sx={{
{/* width: '6ch',*/} width: '6ch',
{/* whiteSpace: 'nowrap',*/} whiteSpace: 'nowrap',
{/* paddingRight: '12px'*/} paddingRight: '12px'
{/* }}*/} }}
{/* >*/} >
{/* {props.batteryData.BoardTemperature.value +*/} {props.batteryData.BoardTemperature.value +
{/* ' ' +*/} ' ' +
{/* props.batteryData.BoardTemperature.unit}*/} props.batteryData.BoardTemperature.unit}
{/* </TableCell>*/} </TableCell>
{/* </TableRow>*/} </TableRow>
{/* <TableRow>*/} <TableRow>
{/* <TableCell*/} <TableCell
{/* component="th"*/} component="th"
{/* scope="row"*/} scope="row"
{/* align="left"*/} align="left"
{/* sx={{ fontWeight: 'bold' }}*/} sx={{ fontWeight: 'bold' }}
{/* >*/} >
{/* Center Cells Temperature*/} Center Cells Temperature
{/* </TableCell>*/} </TableCell>
{/* <TableCell*/} <TableCell
{/* align="right"*/} align="right"
{/* sx={{*/} sx={{
{/* width: '6ch',*/} width: '6ch',
{/* whiteSpace: 'nowrap',*/} whiteSpace: 'nowrap',
{/* paddingRight: '12px'*/} paddingRight: '12px'
{/* }}*/} }}
{/* >*/} >
{/* {props.batteryData.AverageTemperature.value +*/} {props.batteryData.AverageTemperature.value +
{/* ' ' +*/} ' ' +
{/* props.batteryData.AverageTemperature.unit}*/} props.batteryData.AverageTemperature.unit}
{/* </TableCell>*/} </TableCell>
{/* </TableRow>*/} </TableRow>
{/* <TableRow>*/} <TableRow>
{/* <TableCell*/} <TableCell
{/* component="th"*/} component="th"
{/* scope="row"*/} scope="row"
{/* align="left"*/} align="left"
{/* sx={{ fontWeight: 'bold' }}*/} sx={{ fontWeight: 'bold' }}
{/* >*/} >
{/* Left Cells Temperature*/} Left Cells Temperature
{/* </TableCell>*/} </TableCell>
{/* <TableCell*/} <TableCell
{/* align="right"*/} align="right"
{/* sx={{*/} sx={{
{/* width: '6ch',*/} width: '6ch',
{/* whiteSpace: 'nowrap',*/} whiteSpace: 'nowrap',
{/* paddingRight: '12px'*/} paddingRight: '12px'
{/* }}*/} }}
{/* >*/} >
{/* {props.batteryData.LeftCellsTemperature.value +*/} {props.batteryData.LeftCellsTemperature.value +
{/* ' ' +*/} ' ' +
{/* props.batteryData.LeftCellsTemperature.unit}*/} props.batteryData.LeftCellsTemperature.unit}
{/* </TableCell>*/} </TableCell>
{/* </TableRow>*/} </TableRow>
{/* <TableRow>*/} <TableRow>
{/* <TableCell*/} <TableCell
{/* component="th"*/} component="th"
{/* scope="row"*/} scope="row"
{/* align="left"*/} align="left"
{/* sx={{ fontWeight: 'bold' }}*/} sx={{ fontWeight: 'bold' }}
{/* >*/} >
{/* Right Cells Temperature*/} Right Cells Temperature
{/* </TableCell>*/} </TableCell>
{/* <TableCell*/} <TableCell
{/* align="right"*/} align="right"
{/* sx={{*/} sx={{
{/* width: '6ch',*/} width: '6ch',
{/* whiteSpace: 'nowrap',*/} whiteSpace: 'nowrap',
{/* paddingRight: '12px'*/} paddingRight: '12px'
{/* }}*/} }}
{/* >*/} >
{/* {props.batteryData.RightCellsTemperature.value +*/} {props.batteryData.RightCellsTemperature.value +
{/* ' ' +*/} ' ' +
{/* props.batteryData.RightCellsTemperature.unit}*/} props.batteryData.RightCellsTemperature.unit}
{/* </TableCell>*/} </TableCell>
{/* </TableRow>*/} </TableRow>
{/* <TableRow>*/} <TableRow>
{/* <TableCell*/} <TableCell
{/* component="th"*/} component="th"
{/* scope="row"*/} scope="row"
{/* align="left"*/} align="left"
{/* sx={{ fontWeight: 'bold' }}*/} sx={{ fontWeight: 'bold' }}
{/* >*/} >
{/* Average Temperature*/} Average Temperature
{/* </TableCell>*/} </TableCell>
{/* <TableCell*/} <TableCell
{/* align="right"*/} align="right"
{/* sx={{*/} sx={{
{/* width: '6ch',*/} width: '6ch',
{/* whiteSpace: 'nowrap',*/} whiteSpace: 'nowrap',
{/* paddingRight: '12px'*/} paddingRight: '12px'
{/* }}*/} }}
{/* >*/} >
{/* {props.batteryData.AverageTemperature.value +*/} {props.batteryData.AverageTemperature.value +
{/* ' ' +*/} ' ' +
{/* props.batteryData.AverageTemperature.unit}*/} props.batteryData.AverageTemperature.unit}
{/* </TableCell>*/} </TableCell>
{/* </TableRow>*/} </TableRow>
{/* <TableRow>*/} <TableRow>
{/* <TableCell*/} <TableCell
{/* component="th"*/} component="th"
{/* scope="row"*/} scope="row"
{/* align="left"*/} align="left"
{/* sx={{ fontWeight: 'bold' }}*/} sx={{ fontWeight: 'bold' }}
{/* >*/} >
{/* State*/} State
{/* </TableCell>*/} </TableCell>
{/* <TableCell*/} <TableCell
{/* align="right"*/} align="right"
{/* sx={{*/} sx={{
{/* width: '6ch',*/} width: '6ch',
{/* whiteSpace: 'nowrap',*/} whiteSpace: 'nowrap',
{/* paddingRight: '12px'*/} paddingRight: '12px'
{/* }}*/} }}
{/* >*/} >
{/* {props.batteryData.StateTemperature.value +*/} {props.batteryData.StateTemperature.value +
{/* ' ' +*/} ' ' +
{/* props.batteryData.StateTemperature.unit}*/} props.batteryData.StateTemperature.unit}
{/* </TableCell>*/} </TableCell>
{/* </TableRow>*/} </TableRow>
{/* </TableBody>*/} </TableBody>
{/* </Table>*/} </Table>
{/* </TableContainer>*/} </TableContainer>
{/* </Card>*/} </Card>
{/* </Grid>*/} </Grid>
{/* </>*/} </>
{/*)}*/} )}
{/*----------------------------------------------------------------------------------------------------------------------------------*/} {/*----------------------------------------------------------------------------------------------------------------------------------*/}
<Grid item md={3} xs={3}> <Grid item md={3} xs={3}>
@ -1196,9 +1193,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.IoStatus.ConnectedToDcBus.value {props.batteryData.ConnectedToDcBus.value +
? 'True' ' ' +
: 'False'} props.batteryData.ConnectedToDcBus.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
@ -1218,9 +1215,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.IoStatus.AlarmOutActive.value {props.batteryData.AlarmOutActive.value +
? 'True' ' ' +
: 'False'} props.batteryData.AlarmOutActive.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
@ -1240,9 +1237,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.IoStatus.InternalFanActive.value {props.batteryData.InternalFanActive.value +
? 'True' ' ' +
: 'False'} props.batteryData.InternalFanActive.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
@ -1262,9 +1259,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.IoStatus.VoltMeasurementAllowed.value {props.batteryData.VoltMeasurementAllowed.value +
? 'True' ' ' +
: 'False'} props.batteryData.VoltMeasurementAllowed.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
@ -1284,9 +1281,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.IoStatus.AuxRelayBus.value {props.batteryData.AuxRelayBus.value +
? 'True' ' ' +
: 'False'} props.batteryData.AuxRelayBus.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
@ -1306,9 +1303,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.IoStatus.RemoteStateActive.value {props.batteryData.RemoteStateActive.value +
? 'True' ' ' +
: 'False'} props.batteryData.RemoteStateActive.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
@ -1328,9 +1325,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.IoStatus.RiscActive.value {props.batteryData.RiscActive.value +
? 'True' ' ' +
: 'False'} props.batteryData.RiscActive.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
</TableBody> </TableBody>
@ -1388,7 +1385,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.Eoc.value} {props.batteryData.Eoc.value +
' ' +
props.batteryData.Eoc.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
@ -1409,7 +1408,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.SerialNumber.value} {props.batteryData.SerialNumber.value +
' ' +
props.batteryData.SerialNumber.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
@ -1430,7 +1431,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.FwVersion.value} {props.batteryData.FwVersion.value +
' ' +
props.batteryData.FwVersion.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
@ -1450,33 +1453,35 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.TimeSinceTOC.value} {props.batteryData.TimeSinceTOC.value +
' ' +
props.batteryData.TimeSinceTOC.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
{/*{props.productNum === 0 && (*/} {props.productNum === 0 && (
{/* <TableRow>*/} <TableRow>
{/* <TableCell*/} <TableCell
{/* component="th"*/} component="th"
{/* scope="row"*/} scope="row"
{/* align="left"*/} align="left"
{/* sx={{ fontWeight: 'bold' }}*/} sx={{ fontWeight: 'bold' }}
{/* >*/} >
{/* Calibration Charge Requested*/} Calibration Charge Requested
{/* </TableCell>*/} </TableCell>
{/* <TableCell*/} <TableCell
{/* align="right"*/} align="right"
{/* sx={{*/} sx={{
{/* width: '6ch',*/} width: '6ch',
{/* whiteSpace: 'nowrap',*/} whiteSpace: 'nowrap',
{/* paddingRight: '12px'*/} paddingRight: '12px'
{/* }}*/} }}
{/* >*/} >
{/* {props.batteryData.CalibrationChargeRequested.value +*/} {props.batteryData.CalibrationChargeRequested.value +
{/* ' ' +*/} ' ' +
{/* props.batteryData.CalibrationChargeRequested.unit}*/} props.batteryData.CalibrationChargeRequested.unit}
{/* </TableCell>*/} </TableCell>
{/* </TableRow>*/} </TableRow>
{/*)}*/} )}
<TableRow> <TableRow>
<TableCell <TableCell
component="th" component="th"
@ -1494,7 +1499,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.MaxChargePower.value + ' W'} {props.batteryData.MaxChargePower.value +
' ' +
props.batteryData.MaxChargePower.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
@ -1514,7 +1521,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px' paddingRight: '12px'
}} }}
> >
{props.batteryData.MaxDischargePower.value + ' W'} {props.batteryData.MaxDischargePower.value +
' ' +
props.batteryData.MaxDischargePower.unit}
</TableCell> </TableCell>
</TableRow> </TableRow>
</TableBody> </TableBody>
@ -1522,111 +1531,6 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
</TableContainer> </TableContainer>
</Card> </Card>
</Grid> </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' }}*/}
{/* >*/}
{/* Green Led*/}
{/* </TableCell>*/}
{/* <TableCell*/}
{/* align="right"*/}
{/* sx={{*/}
{/* width: '6ch',*/}
{/* whiteSpace: 'nowrap',*/}
{/* paddingRight: '12px'*/}
{/* }}*/}
{/* >*/}
{/* {props.batteryData.GreenLeds.value}*/}
{/* </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'*/}
{/* }}*/}
{/* >*/}
{/* {props.batteryData.AmberLeds.value}*/}
{/* </TableCell>*/}
{/* </TableRow>*/}
{/* <TableRow>*/}
{/* <TableCell*/}
{/* component="th"*/}
{/* scope="row"*/}
{/* align="left"*/}
{/* sx={{ fontWeight: 'bold' }}*/}
{/* >*/}
{/* Blue Led*/}
{/* </TableCell>*/}
{/* <TableCell*/}
{/* align="right"*/}
{/* sx={{*/}
{/* width: '6ch',*/}
{/* whiteSpace: 'nowrap',*/}
{/* paddingRight: '12px'*/}
{/* }}*/}
{/* >*/}
{/* {props.batteryData.BlueLeds.value}*/}
{/* </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'*/}
{/* }}*/}
{/* >*/}
{/* {props.batteryData.RedLeds.value}*/}
{/* </TableCell>*/}
{/* </TableRow>*/}
{/* </TableBody>*/}
{/* </Table>*/}
{/* </TableContainer>*/}
{/* </Card>*/}
{/*</Grid>*/}
</> </>
); );
} }

View File

@ -16,7 +16,7 @@ import { getChartOptions } from '../Overview/chartOptions';
import { import {
BatteryDataInterface, BatteryDataInterface,
BatteryOverviewInterface, BatteryOverviewInterface,
transformInputToBatteryViewDataJson transformInputToBatteryViewData
} from '../../../interfaces/Chart'; } from '../../../interfaces/Chart';
import dayjs, { Dayjs } from 'dayjs'; import dayjs, { Dayjs } from 'dayjs';
import { TimeSpan, UnixTime } from '../../../dataCache/time'; import { TimeSpan, UnixTime } from '../../../dataCache/time';
@ -96,7 +96,7 @@ function MainStats(props: MainStatsProps) {
const resultPromise: Promise<{ const resultPromise: Promise<{
chartData: BatteryDataInterface; chartData: BatteryDataInterface;
chartOverview: BatteryOverviewInterface; chartOverview: BatteryOverviewInterface;
}> = transformInputToBatteryViewDataJson( }> = transformInputToBatteryViewData(
props.s3Credentials, props.s3Credentials,
props.id, props.id,
product, product,
@ -192,7 +192,7 @@ function MainStats(props: MainStatsProps) {
const resultPromise: Promise<{ const resultPromise: Promise<{
chartData: BatteryDataInterface; chartData: BatteryDataInterface;
chartOverview: BatteryOverviewInterface; chartOverview: BatteryOverviewInterface;
}> = transformInputToBatteryViewDataJson( }> = transformInputToBatteryViewData(
props.s3Credentials, props.s3Credentials,
props.id, props.id,
product, product,
@ -254,7 +254,7 @@ function MainStats(props: MainStatsProps) {
const resultPromise: Promise<{ const resultPromise: Promise<{
chartData: BatteryDataInterface; chartData: BatteryDataInterface;
chartOverview: BatteryOverviewInterface; chartOverview: BatteryOverviewInterface;
}> = transformInputToBatteryViewDataJson( }> = transformInputToBatteryViewData(
props.s3Credentials, props.s3Credentials,
props.id, props.id,
product, product,

View File

@ -0,0 +1,812 @@
import {
Box,
Card,
Container,
Grid,
IconButton,
Modal,
TextField,
Typography
} from '@mui/material';
import { FormattedMessage } from 'react-intl';
import React, { useContext, useEffect, useState } from 'react';
import { I_S3Credentials } from '../../../interfaces/S3Types';
import ReactApexChart from 'react-apexcharts';
import { getChartOptions } from '../Overview/chartOptions';
import {
BatteryDataInterface,
BatteryOverviewInterface,
transformInputToBatteryViewDataJson
} from '../../../interfaces/Chart';
import dayjs, { Dayjs } from 'dayjs';
import { TimeSpan, UnixTime } from '../../../dataCache/time';
import Button from '@mui/material/Button';
import { DateTimePicker, LocalizationProvider } from '@mui/x-date-pickers';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import CircularProgress from '@mui/material/CircularProgress';
import { useLocation, useNavigate } from 'react-router-dom';
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import { ProductIdContext } from '../../../contexts/ProductIdContextProvider';
interface MainStatsProps {
s3Credentials: I_S3Credentials;
id: number;
}
function MainStatsSalidomo(props: MainStatsProps) {
const [chartState, setChartState] = useState(0);
const [batteryViewDataArray, setBatteryViewDataArray] = useState<
{
chartData: BatteryDataInterface;
chartOverview: BatteryOverviewInterface;
}[]
>([]);
const [isDateModalOpen, setIsDateModalOpen] = useState(false);
const [dateOpen, setDateOpen] = useState(false);
const navigate = useNavigate();
const [startDate, setStartDate] = useState(dayjs().add(-1, 'day'));
const [endDate, setEndDate] = useState(dayjs());
const [isErrorDateModalOpen, setErrorDateModalOpen] = useState(false);
const [dateSelectionError, setDateSelectionError] = useState('');
const [loading, setLoading] = useState(true);
const location = useLocation();
const { product, setProduct } = useContext(ProductIdContext);
const blueColors = [
'#99CCFF',
'#80BFFF',
'#6699CC',
'#4D99FF',
'#2670E6',
'#3366CC',
'#1A4D99',
'#133366',
'#0D274D',
'#081A33'
];
const redColors = [
'#ff9090',
'#ff7070',
'#ff3f3f',
'#ff1e1e',
'#ff0606',
'#fc0000',
'#f40000',
'#d40000',
'#a30000',
'#7a0000'
];
const orangeColors = [
'#ffdb99',
'#ffc968',
'#ffb837',
'#ffac16',
'#ffa706',
'#FF8C00',
'#d48900',
'#CC7A00',
'#a36900',
'#993D00'
];
useEffect(() => {
setLoading(true);
const resultPromise: Promise<{
chartData: BatteryDataInterface;
chartOverview: BatteryOverviewInterface;
}> = transformInputToBatteryViewDataJson(
props.s3Credentials,
props.id,
product,
UnixTime.fromTicks(new Date().getTime() / 1000).earlier(
TimeSpan.fromDays(1)
),
UnixTime.fromTicks(new Date().getTime() / 1000)
);
resultPromise
.then((result) => {
setBatteryViewDataArray((prevData) =>
prevData.concat({
chartData: result.chartData,
chartOverview: result.chartOverview
})
);
setLoading(false);
})
.catch((error) => {
console.error('Error:', error);
});
}, []);
const [isZooming, setIsZooming] = useState(false);
useEffect(() => {
if (isZooming) {
setLoading(true);
} else if (!isZooming && batteryViewDataArray.length > 0) {
setLoading(false);
}
}, [isZooming, batteryViewDataArray]);
function generateSeries(chartData, category, color) {
const series = [];
const pathsToSearch = [
'Node2',
'Node3',
'Node4',
'Node5',
'Node6',
'Node7',
'Node8',
'Node9',
'Node10',
'Node11'
];
let i = 0;
pathsToSearch.forEach((devicePath) => {
if (
Object.hasOwnProperty.call(chartData[category].data, devicePath) &&
chartData[category].data[devicePath].data.length != 0
) {
series.push({
...chartData[category].data[devicePath],
color:
color === 'blue'
? blueColors[i]
: color === 'red'
? redColors[i]
: orangeColors[i]
});
}
i++;
});
return series;
}
const handleCancel = () => {
setIsDateModalOpen(false);
setDateOpen(false);
};
const handleConfirm = () => {
setIsDateModalOpen(false);
setDateOpen(false);
if (endDate.isAfter(dayjs())) {
setDateSelectionError('You cannot ask for future data');
setErrorDateModalOpen(true);
return;
} else if (startDate.isAfter(endDate)) {
setDateSelectionError('Εnd date must precede start date');
setErrorDateModalOpen(true);
return;
}
setLoading(true);
const resultPromise: Promise<{
chartData: BatteryDataInterface;
chartOverview: BatteryOverviewInterface;
}> = transformInputToBatteryViewDataJson(
props.s3Credentials,
props.id,
product,
UnixTime.fromTicks(startDate.unix()),
UnixTime.fromTicks(endDate.unix())
);
resultPromise
.then((result) => {
setBatteryViewDataArray((prevData) =>
prevData.concat({
chartData: result.chartData,
chartOverview: result.chartOverview
})
);
setLoading(false);
setChartState(batteryViewDataArray.length);
})
.catch((error) => {
console.error('Error:', error);
});
};
const handleSetDate = () => {
setDateOpen(true);
setIsDateModalOpen(true);
};
const handleBatteryViewButton = () => {
navigate(
location.pathname.split('/').slice(0, -2).join('/') + '/batteryview'
);
};
const handleGoBack = () => {
if (chartState > 0) {
setChartState(chartState - 1);
}
};
const handleGoForward = () => {
if (chartState + 1 < batteryViewDataArray.length) {
setChartState(chartState + 1);
}
};
const handleOkOnErrorDateModal = () => {
setErrorDateModalOpen(false);
};
const startZoom = () => {
setIsZooming(true);
};
const handleBeforeZoom = (chartContext, { xaxis }) => {
const startX = parseInt(xaxis.min) / 1000;
const endX = parseInt(xaxis.max) / 1000;
const resultPromise: Promise<{
chartData: BatteryDataInterface;
chartOverview: BatteryOverviewInterface;
}> = transformInputToBatteryViewDataJson(
props.s3Credentials,
props.id,
product,
UnixTime.fromTicks(startX).earlier(TimeSpan.fromHours(2)),
UnixTime.fromTicks(endX).earlier(TimeSpan.fromHours(2))
);
resultPromise
.then((result) => {
setBatteryViewDataArray((prevData) =>
prevData.concat({
chartData: result.chartData,
chartOverview: result.chartOverview
})
);
setIsZooming(false);
setChartState(batteryViewDataArray.length);
})
.catch((error) => {
console.error('Error:', error);
});
};
return (
<>
{loading && (
<Container
maxWidth="xl"
sx={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
height: '100vh'
}}
>
<CircularProgress size={60} style={{ color: '#ffc04d' }} />
<Typography variant="body2" style={{ color: 'black' }} mt={2}>
Fetching data...
</Typography>
</Container>
)}
{isErrorDateModalOpen && (
<Modal open={isErrorDateModalOpen} onClose={() => {}}>
<Box
sx={{
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 450,
bgcolor: 'background.paper',
borderRadius: 4,
boxShadow: 24,
p: 4,
display: 'flex',
flexDirection: 'column',
alignItems: 'center'
}}
>
<Typography
variant="body1"
gutterBottom
sx={{ fontWeight: 'bold' }}
>
{dateSelectionError}
</Typography>
<Button
sx={{
marginTop: 2,
textTransform: 'none',
bgcolor: '#ffc04d',
color: '#111111',
'&:hover': { bgcolor: '#f7b34d' }
}}
onClick={handleOkOnErrorDateModal}
>
Ok
</Button>
</Box>
</Modal>
)}
{isDateModalOpen && (
<LocalizationProvider dateAdapter={AdapterDayjs}>
<Modal open={isDateModalOpen} onClose={() => {}}>
<Box
sx={{
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 450,
bgcolor: 'background.paper',
borderRadius: 4,
boxShadow: 24,
p: 4,
display: 'flex',
flexDirection: 'column',
alignItems: 'center'
}}
>
<DateTimePicker
label="Select Start Date"
value={startDate}
onChange={(newDate: Dayjs | null) => {
// Type assertion to Dayjs
if (newDate) {
setStartDate(newDate);
}
}}
renderInput={(props) => <TextField {...props} />}
/>
<DateTimePicker
label="Select End Date"
value={endDate}
onChange={(newDate: Dayjs | null) => {
// Type assertion to Dayjs
if (newDate) {
setEndDate(newDate);
}
}}
renderInput={(props) => <TextField {...props} />}
/>
<div
style={{
display: 'flex',
alignItems: 'center',
marginTop: 10
}}
>
<Button
sx={{
marginTop: 2,
textTransform: 'none',
bgcolor: '#ffc04d',
color: '#111111',
'&:hover': { bgcolor: '#f7b34d' }
}}
onClick={handleConfirm}
>
Confirm
</Button>
<Button
sx={{
marginTop: 2,
marginLeft: 2,
textTransform: 'none',
bgcolor: '#ffc04d',
color: '#111111',
'&:hover': { bgcolor: '#f7b34d' }
}}
onClick={handleCancel}
>
Cancel
</Button>
</div>
</Box>
</Modal>
</LocalizationProvider>
)}
{!loading && (
<>
<Grid item xs={6} md={6}>
<IconButton
aria-label="go back"
sx={{
marginTop: '20px',
backgroundColor: 'grey',
color: '#000000',
'&:hover': { bgcolor: '#f7b34d' }
}}
onClick={handleBatteryViewButton}
>
<ArrowBackIcon />
</IconButton>
<Button
variant="contained"
onClick={handleSetDate}
disabled={loading}
sx={{
marginTop: '20px',
marginLeft: '20px',
backgroundColor: dateOpen ? '#808080' : '#ffc04d',
color: '#000000',
'&:hover': { bgcolor: '#f7b34d' }
}}
>
<FormattedMessage id="set_date" defaultMessage="Set Date" />
</Button>
</Grid>
<Grid
container
justifyContent="flex-end"
alignItems="center"
item
xs={6}
md={6}
>
<Button
variant="contained"
disabled={!(chartState > 0)}
onClick={handleGoBack}
sx={{
marginTop: '20px',
marginLeft: '10px',
backgroundColor: '#ffc04d',
color: '#000000',
'&:hover': { bgcolor: '#f7b34d' }
}}
>
<FormattedMessage id="goback" defaultMessage="Zoom out" />
</Button>
<Button
variant="contained"
disabled={!(chartState < batteryViewDataArray.length - 1)}
onClick={handleGoForward}
sx={{
marginTop: '20px',
marginLeft: '10px',
backgroundColor: '#ffc04d',
color: '#000000',
'&:hover': { bgcolor: '#f7b34d' }
}}
>
<FormattedMessage id="goback" defaultMessage="Zoom in" />
</Button>
</Grid>
<Grid
container
direction="row"
justifyContent="center"
alignItems="stretch"
spacing={3}
>
<Grid item md={12} xs={12}>
<Card
sx={{
overflow: 'visible',
marginTop: '30px',
marginBottom: '30px'
}}
>
<Box
sx={{
marginLeft: '20px'
}}
>
<Box display="flex" alignItems="center">
<Box>
<Typography variant="subtitle1" noWrap>
<FormattedMessage
id="battery_soc"
defaultMessage="Battery SOC (State Of Charge)"
/>
</Typography>
</Box>
</Box>
<Box
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-start',
pt: 3
}}
></Box>
</Box>
<ReactApexChart
options={{
...getChartOptions(
batteryViewDataArray[chartState].chartOverview.Soc,
'daily',
[],
true
),
chart: {
events: {
beforeZoom: (chartContext, options) => {
startZoom();
handleBeforeZoom(chartContext, options);
}
}
}
}}
series={generateSeries(
batteryViewDataArray[chartState].chartData,
'Soc',
'blue'
)}
type="line"
height={420}
/>
</Card>
</Grid>
<Grid item md={12} xs={12}>
<Card
sx={{
overflow: 'visible',
marginTop: '10px',
marginBottom: '30px'
}}
>
<Box
sx={{
marginLeft: '20px'
}}
>
<Box display="flex" alignItems="center">
<Box>
<Typography variant="subtitle1" noWrap>
<FormattedMessage
id="battery_soc"
defaultMessage="Battery Temperature"
/>
</Typography>
</Box>
</Box>
<Box
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-start',
pt: 3
}}
></Box>
</Box>
<ReactApexChart
options={{
...getChartOptions(
batteryViewDataArray[chartState].chartOverview
.Temperature,
'daily',
[],
true
),
chart: {
events: {
beforeZoom: (chartContext, options) => {
startZoom();
handleBeforeZoom(chartContext, options);
}
}
}
}}
series={generateSeries(
batteryViewDataArray[chartState].chartData,
'Temperature',
'blue'
)}
type="line"
height={420}
/>
</Card>
</Grid>
<Grid item md={12} xs={12}>
<Card
sx={{
overflow: 'visible',
marginTop: '10px',
marginBottom: '30px'
}}
>
<Box
sx={{
marginLeft: '20px'
}}
>
<Box display="flex" alignItems="center">
<Box>
<Typography variant="subtitle1" noWrap>
<FormattedMessage
id="battery_power"
defaultMessage="Battery Power"
/>
</Typography>
</Box>
</Box>
<Box
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-start',
pt: 3
}}
></Box>
</Box>
<ReactApexChart
options={{
...getChartOptions(
batteryViewDataArray[chartState].chartOverview.Power,
'daily',
[],
true
),
chart: {
events: {
beforeZoom: (chartContext, options) => {
startZoom();
handleBeforeZoom(chartContext, options);
}
}
}
}}
series={generateSeries(
batteryViewDataArray[chartState].chartData,
'Power',
'red'
)}
type="line"
height={420}
/>
</Card>
</Grid>
<Grid item md={12} xs={12}>
<Card
sx={{
overflow: 'visible',
marginTop: '10px',
marginBottom: '30px'
}}
>
<Box
sx={{
marginLeft: '20px'
}}
>
<Box display="flex" alignItems="center">
<Box>
<Typography variant="subtitle1" noWrap>
<FormattedMessage
id="battery_voltage"
defaultMessage="Battery Voltage"
/>
</Typography>
</Box>
</Box>
<Box
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-start',
pt: 3
}}
></Box>
</Box>
<ReactApexChart
options={{
...getChartOptions(
batteryViewDataArray[chartState].chartOverview.Voltage,
'daily',
[],
true
),
chart: {
events: {
beforeZoom: (chartContext, options) => {
startZoom();
handleBeforeZoom(chartContext, options);
}
}
}
}}
series={generateSeries(
batteryViewDataArray[chartState].chartData,
'Voltage',
'orange'
)}
type="line"
height={420}
/>
</Card>
</Grid>
<Grid item md={12} xs={12}>
<Card
sx={{
overflow: 'visible',
marginTop: '10px',
marginBottom: '30px'
}}
>
<Box
sx={{
marginLeft: '20px'
}}
>
<Box display="flex" alignItems="center">
<Box>
<Typography variant="subtitle1" noWrap>
<FormattedMessage
id="battery_current"
defaultMessage="Battery Current"
/>
</Typography>
</Box>
</Box>
<Box
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-start',
pt: 3
}}
></Box>
</Box>
<ReactApexChart
options={{
...getChartOptions(
batteryViewDataArray[chartState].chartOverview.Current,
'daily',
[],
true
),
chart: {
events: {
beforeZoom: (chartContext, options) => {
startZoom();
handleBeforeZoom(chartContext, options);
}
}
}
}}
series={generateSeries(
batteryViewDataArray[chartState].chartData,
'Current',
'orange'
)}
type="line"
height={420}
/>
</Card>
</Grid>
</Grid>
</>
)}
</>
);
}
export default MainStatsSalidomo;

View File

@ -30,6 +30,7 @@ import Information from '../Information/Information';
import { UserType } from '../../../interfaces/UserTypes'; import { UserType } from '../../../interfaces/UserTypes';
import HistoryOfActions from '../History/History'; import HistoryOfActions from '../History/History';
import PvView from '../PvView/PvView'; import PvView from '../PvView/PvView';
import BatteryView from '../BatteryView/BatteryView';
interface singleInstallationProps { interface singleInstallationProps {
current_installation?: I_Installation; current_installation?: I_Installation;
@ -421,18 +422,18 @@ function Installation(props: singleInstallationProps) {
} }
/> />
{/*<Route*/} <Route
{/* path={routes.batteryview + '*'}*/} path={routes.batteryview + '*'}
{/* element={*/} element={
{/* <BatteryView*/} <BatteryView
{/* values={values}*/} values={values}
{/* s3Credentials={s3Credentials}*/} s3Credentials={s3Credentials}
{/* installationId={props.current_installation.id}*/} installationId={props.current_installation.id}
{/* productNum={props.current_installation.product}*/} productNum={props.current_installation.product}
{/* connected={connected}*/} connected={connected}
{/* ></BatteryView>*/} ></BatteryView>
{/* }*/} }
{/*></Route>*/} ></Route>
<Route <Route
path={routes.pvview + '*'} path={routes.pvview + '*'}

View File

@ -50,7 +50,7 @@ function InstallationTabs() {
} else if (path[path.length - 2] === 'tree') { } else if (path[path.length - 2] === 'tree') {
setCurrentTab('tree'); setCurrentTab('tree');
} else { } else {
//Even if we are located at path: /batteryview/mainstats, we want the BatteryView tab to be bold //Even if we are located at path: /batteryview/mainstats, we want the BatteryViewSalidomo tab to be bold
setCurrentTab(path.find((pathElement) => tabList.includes(pathElement))); setCurrentTab(path.find((pathElement) => tabList.includes(pathElement)));
} }
}, [location]); }, [location]);

View File

@ -16,7 +16,7 @@ import { fetchDataJson } from 'src/content/dashboards/Installations/fetchData';
import { Navigate, Route, Routes, useLocation } from 'react-router-dom'; import { Navigate, Route, Routes, useLocation } from 'react-router-dom';
import routes from '../../../Resources/routes.json'; import routes from '../../../Resources/routes.json';
import InformationSalidomo from '../Information/InformationSalidomo'; import InformationSalidomo from '../Information/InformationSalidomo';
import BatteryView from '../BatteryView/BatteryView'; import BatteryViewSalidomo from '../BatteryView/BatteryViewSalidomo';
import Log from '../Log/Log'; import Log from '../Log/Log';
import CancelIcon from '@mui/icons-material/Cancel'; import CancelIcon from '@mui/icons-material/Cancel';
import SalidomoOverview from '../Overview/salidomoOverview'; import SalidomoOverview from '../Overview/salidomoOverview';
@ -361,13 +361,13 @@ function SalidomoInstallation(props: singleInstallationProps) {
<Route <Route
path={routes.batteryview + '*'} path={routes.batteryview + '*'}
element={ element={
<BatteryView <BatteryViewSalidomo
values={values} values={values}
s3Credentials={s3Credentials} s3Credentials={s3Credentials}
installationId={props.current_installation.id} installationId={props.current_installation.id}
productNum={props.current_installation.product} productNum={props.current_installation.product}
connected={connected} connected={connected}
></BatteryView> ></BatteryViewSalidomo>
} }
></Route> ></Route>

View File

@ -49,7 +49,7 @@ function SalidomoInstallationTabs() {
} else if (path[path.length - 2] === 'tree') { } else if (path[path.length - 2] === 'tree') {
setCurrentTab('tree'); setCurrentTab('tree');
} else { } else {
//Even if we are located at path: /batteryview/mainstats, we want the BatteryView tab to be bold //Even if we are located at path: /batteryview/mainstats, we want the BatteryViewSalidomo tab to be bold
setCurrentTab(path.find((pathElement) => tabList.includes(pathElement))); setCurrentTab(path.find((pathElement) => tabList.includes(pathElement)));
} }
}, [location]); }, [location]);

View File

@ -364,13 +364,13 @@ function SodioHomeInstallation(props: singleInstallationProps) {
{/*<Route*/} {/*<Route*/}
{/* path={routes.batteryview + '*'}*/} {/* path={routes.batteryview + '*'}*/}
{/* element={*/} {/* element={*/}
{/* <BatteryView*/} {/* <BatteryViewSalidomo*/}
{/* values={values}*/} {/* values={values}*/}
{/* s3Credentials={s3Credentials}*/} {/* s3Credentials={s3Credentials}*/}
{/* installationId={props.current_installation.id}*/} {/* installationId={props.current_installation.id}*/}
{/* productNum={props.current_installation.product}*/} {/* productNum={props.current_installation.product}*/}
{/* connected={connected}*/} {/* connected={connected}*/}
{/* ></BatteryView>*/} {/* ></BatteryViewSalidomo>*/}
{/* }*/} {/* }*/}
{/*></Route>*/} {/*></Route>*/}

View File

@ -48,7 +48,7 @@ function SodioHomeInstallationTabs() {
} else if (path[path.length - 2] === 'tree') { } else if (path[path.length - 2] === 'tree') {
setCurrentTab('tree'); setCurrentTab('tree');
} else { } else {
//Even if we are located at path: /batteryview/mainstats, we want the BatteryView tab to be bold //Even if we are located at path: /batteryview/mainstats, we want the BatteryViewSalidomo tab to be bold
setCurrentTab(path.find((pathElement) => tabList.includes(pathElement))); setCurrentTab(path.find((pathElement) => tabList.includes(pathElement)));
} }
}, [location]); }, [location]);

View File

@ -401,6 +401,7 @@ export const transformInputToAggregatedDataJson = async (
) { ) {
// Handle not available or try later case // Handle not available or try later case
} else { } else {
console.log(result);
dateList.push(currentDay.format('DD-MM')); dateList.push(currentDay.format('DD-MM'));
pathsToSearch.forEach((path) => { pathsToSearch.forEach((path) => {
const value = path const value = path
@ -410,7 +411,6 @@ export const transformInputToAggregatedDataJson = async (
if (value !== undefined) { if (value !== undefined) {
if (path === '.GridExportPower') { if (path === '.GridExportPower') {
result.GridExportPower = -value; result.GridExportPower = -value;
// result[path].value = -result[path].value;
} }
if (value < overviewData[path].min) { if (value < overviewData[path].min) {
overviewData[path].min = value; overviewData[path].min = value;
@ -549,214 +549,214 @@ export const transformInputToAggregatedDataJson = async (
// 'Node2': {name:'Node2', data: [[timestamp,value],[timestamp,value]]}, // 'Node2': {name:'Node2', data: [[timestamp,value],[timestamp,value]]},
// ]} // ]}
// export const transformInputToBatteryViewData = async ( export const transformInputToBatteryViewData = async (
// s3Credentials: I_S3Credentials, s3Credentials: I_S3Credentials,
// id: number, id: number,
// product: number, product: number,
// start_time?: UnixTime, start_time?: UnixTime,
// end_time?: UnixTime end_time?: UnixTime
// ): Promise<{ ): Promise<{
// chartData: BatteryDataInterface; chartData: BatteryDataInterface;
// chartOverview: BatteryOverviewInterface; chartOverview: BatteryOverviewInterface;
// }> => { }> => {
// const prefixes = ['', 'k', 'M', 'G', 'T']; const prefixes = ['', 'k', 'M', 'G', 'T'];
// const MAX_NUMBER = 9999999; const MAX_NUMBER = 9999999;
// const categories = ['Soc', 'Temperature', 'Power', 'Voltage', 'Current']; const categories = ['Soc', 'Temperature', 'Power', 'Voltage', 'Current'];
// const pathCategories = [ const pathCategories = [
// 'Soc', 'Soc',
// 'Temperatures/Cells/Average', 'Temperatures/Cells/Average',
// 'Dc/Power', 'Dc/Power',
// 'Dc/Voltage', 'Dc/Voltage',
// 'Dc/Current' 'Dc/Current'
// ]; ];
//
// const pathsToSearch = [ const pathsToSearch = [
// '/Battery/Devices/1/', '/Battery/Devices/1/',
// '/Battery/Devices/2/', '/Battery/Devices/2/',
// '/Battery/Devices/3/', '/Battery/Devices/3/',
// '/Battery/Devices/4/', '/Battery/Devices/4/',
// '/Battery/Devices/5/', '/Battery/Devices/5/',
// '/Battery/Devices/6/', '/Battery/Devices/6/',
// '/Battery/Devices/7/', '/Battery/Devices/7/',
// '/Battery/Devices/8/', '/Battery/Devices/8/',
// '/Battery/Devices/9/', '/Battery/Devices/9/',
// '/Battery/Devices/10/' '/Battery/Devices/10/'
// ]; ];
//
// const pathsToSave = []; const pathsToSave = [];
//
// const chartData: BatteryDataInterface = { const chartData: BatteryDataInterface = {
// Soc: { name: 'State Of Charge', data: [] }, Soc: { name: 'State Of Charge', data: [] },
// Temperature: { name: 'Temperature', data: [] }, Temperature: { name: 'Temperature', data: [] },
// Power: { name: 'Power', data: [] }, Power: { name: 'Power', data: [] },
// Voltage: { name: 'Voltage', data: [] }, Voltage: { name: 'Voltage', data: [] },
// Current: { name: 'Voltage', data: [] } Current: { name: 'Voltage', data: [] }
// }; };
//
// const chartOverview: BatteryOverviewInterface = { const chartOverview: BatteryOverviewInterface = {
// Soc: { magnitude: 0, unit: '', min: 0, max: 0 }, Soc: { magnitude: 0, unit: '', min: 0, max: 0 },
// Temperature: { magnitude: 0, unit: '', min: 0, max: 0 }, Temperature: { magnitude: 0, unit: '', min: 0, max: 0 },
// Power: { magnitude: 0, unit: '', min: 0, max: 0 }, Power: { magnitude: 0, unit: '', min: 0, max: 0 },
// Voltage: { magnitude: 0, unit: '', min: 0, max: 0 }, Voltage: { magnitude: 0, unit: '', min: 0, max: 0 },
// Current: { magnitude: 0, unit: '', min: 0, max: 0 } Current: { magnitude: 0, unit: '', min: 0, max: 0 }
// }; };
//
// let initialiation = true; let initialiation = true;
//
// let timestampArray: number[] = []; let timestampArray: number[] = [];
// let adjustedTimestampArray = []; let adjustedTimestampArray = [];
// const timestampPromises = []; const timestampPromises = [];
//
// await axiosConfig await axiosConfig
// .get( .get(
// `/GetCsvTimestampsForInstallation?id=${id}&start=${start_time.ticks}&end=${end_time.ticks}` `/GetCsvTimestampsForInstallation?id=${id}&start=${start_time.ticks}&end=${end_time.ticks}`
// ) )
// .then((res: AxiosResponse<number[]>) => { .then((res: AxiosResponse<number[]>) => {
// timestampArray = res.data; timestampArray = res.data;
// }) })
// .catch((err: AxiosError) => { .catch((err: AxiosError) => {
// if (err.response && err.response.status == 401) { if (err.response && err.response.status == 401) {
// //removeToken(); //removeToken();
// //navigate(routes.login); //navigate(routes.login);
// } }
// }); });
//
// for (var i = 0; i < timestampArray.length; i++) { for (var i = 0; i < timestampArray.length; i++) {
// timestampPromises.push( timestampPromises.push(
// fetchDataForOneTime( fetchDataForOneTime(
// UnixTime.fromTicks(timestampArray[i], true), UnixTime.fromTicks(timestampArray[i], true),
// s3Credentials s3Credentials
// ) )
// ); );
//
// const adjustedTimestamp = const adjustedTimestamp =
// product == 0 product == 0
// ? new Date(timestampArray[i] * 1000) ? new Date(timestampArray[i] * 1000)
// : new Date(timestampArray[i] * 100000); : new Date(timestampArray[i] * 100000);
// //Timezone offset is negative, so we convert the timestamp to the current zone by subtracting the corresponding offset //Timezone offset is negative, so we convert the timestamp to the current zone by subtracting the corresponding offset
// adjustedTimestamp.setHours( adjustedTimestamp.setHours(
// adjustedTimestamp.getHours() - adjustedTimestamp.getTimezoneOffset() / 60 adjustedTimestamp.getHours() - adjustedTimestamp.getTimezoneOffset() / 60
// ); );
// adjustedTimestampArray.push(adjustedTimestamp); adjustedTimestampArray.push(adjustedTimestamp);
// } }
//
// const results: Promise<FetchResult<Record<string, DataRecord>>>[] = const results: Promise<FetchResult<Record<string, DataRecord>>>[] =
// await Promise.all(timestampPromises); await Promise.all(timestampPromises);
//
// for (let i = 0; i < results.length; i++) { for (let i = 0; i < results.length; i++) {
// if (results[i] == null) { if (results[i] == null) {
// // Handle not available or try later case // Handle not available or try later case
// } else { } else {
// const timestamp = Object.keys(results[i])[ const timestamp = Object.keys(results[i])[
// Object.keys(results[i]).length - 1 Object.keys(results[i]).length - 1
// ]; ];
// const result = results[i][timestamp]; const result = results[i][timestamp];
// const battery_nodes = result['/Config/Devices/BatteryNodes'].value const battery_nodes = result['/Config/Devices/BatteryNodes'].value
// .toString() .toString()
// .split(','); .split(',');
//
// //Initialize the chartData structure based on the node names extracted from the first result //Initialize the chartData structure based on the node names extracted from the first result
// let old_length = pathsToSave.length; let old_length = pathsToSave.length;
//
// if (battery_nodes.length > old_length) { if (battery_nodes.length > old_length) {
// battery_nodes.forEach((node) => { battery_nodes.forEach((node) => {
// if (!pathsToSave.includes('Node' + node)) { if (!pathsToSave.includes('Node' + node)) {
// pathsToSave.push('Node' + node); pathsToSave.push('Node' + node);
// } }
// }); });
// } }
//
// if (initialiation) { if (initialiation) {
// initialiation = false; initialiation = false;
// categories.forEach((category) => { categories.forEach((category) => {
// chartData[category].data = []; chartData[category].data = [];
// chartOverview[category] = { chartOverview[category] = {
// magnitude: 0, magnitude: 0,
// unit: '', unit: '',
// min: MAX_NUMBER, min: MAX_NUMBER,
// max: -MAX_NUMBER max: -MAX_NUMBER
// }; };
// }); });
// } }
//
// if (battery_nodes.length > old_length) { if (battery_nodes.length > old_length) {
// categories.forEach((category) => { categories.forEach((category) => {
// pathsToSave.forEach((path) => { pathsToSave.forEach((path) => {
// if (pathsToSave.indexOf(path) >= old_length) { if (pathsToSave.indexOf(path) >= old_length) {
// chartData[category].data[path] = { name: path, data: [] }; chartData[category].data[path] = { name: path, data: [] };
// } }
// }); });
// }); });
// } }
//
// for ( for (
// let category_index = 0; let category_index = 0;
// category_index < pathCategories.length; category_index < pathCategories.length;
// category_index++ category_index++
// ) { ) {
// let category = categories[category_index]; let category = categories[category_index];
//
// for (let j = 0; j < pathsToSave.length; j++) { for (let j = 0; j < pathsToSave.length; j++) {
// let path = pathsToSearch[j] + pathCategories[category_index]; let path = pathsToSearch[j] + pathCategories[category_index];
//
// if (result[path]) { if (result[path]) {
// const value = result[path]; const value = result[path];
//
// if (value.value < chartOverview[category].min) { if (value.value < chartOverview[category].min) {
// chartOverview[category].min = value.value; chartOverview[category].min = value.value;
// } }
//
// if (value.value > chartOverview[category].max) { if (value.value > chartOverview[category].max) {
// chartOverview[category].max = value.value; chartOverview[category].max = value.value;
// } }
chartData[category].data[pathsToSave[j]].data.push([
adjustedTimestampArray[i],
value.value
]);
} else {
// chartData[category].data[pathsToSave[j]].data.push([ // chartData[category].data[pathsToSave[j]].data.push([
// adjustedTimestampArray[i], // adjustedTimestampArray[i],
// value.value // null
// ]); // ]);
// } else { }
// // chartData[category].data[pathsToSave[j]].data.push([ }
// // adjustedTimestampArray[i], }
// // null }
// // ]); }
// } categories.forEach((category) => {
// } let value = Math.max(
// } Math.abs(chartOverview[category].max),
// } Math.abs(chartOverview[category].min)
// } );
// categories.forEach((category) => { let magnitude = 0;
// let value = Math.max(
// Math.abs(chartOverview[category].max), if (value < 0) {
// Math.abs(chartOverview[category].min) value = -value;
// ); }
// let magnitude = 0; while (value >= 1000) {
// value /= 1000;
// if (value < 0) { magnitude++;
// value = -value; }
// } chartOverview[category].magnitude = magnitude;
// while (value >= 1000) { });
// value /= 1000;
// magnitude++; chartOverview.Soc.unit = '(%)';
// } chartOverview.Soc.min = 0;
// chartOverview[category].magnitude = magnitude; chartOverview.Soc.max = 100;
// }); chartOverview.Temperature.unit = '(°C)';
// chartOverview.Power.unit =
// chartOverview.Soc.unit = '(%)'; '(' + prefixes[chartOverview['Power'].magnitude] + 'W' + ')';
// chartOverview.Soc.min = 0; chartOverview.Voltage.unit =
// chartOverview.Soc.max = 100; '(' + prefixes[chartOverview['Voltage'].magnitude] + 'V' + ')';
// chartOverview.Temperature.unit = '(°C)';
// chartOverview.Power.unit = chartOverview.Current.unit =
// '(' + prefixes[chartOverview['Power'].magnitude] + 'W' + ')'; '(' + prefixes[chartOverview['Current'].magnitude] + 'A' + ')';
// chartOverview.Voltage.unit =
// '(' + prefixes[chartOverview['Voltage'].magnitude] + 'V' + ')'; return {
// chartData: chartData,
// chartOverview.Current.unit = chartOverview: chartOverview
// '(' + prefixes[chartOverview['Current'].magnitude] + 'A' + ')'; };
// };
// return {
// chartData: chartData,
// chartOverview: chartOverview
// };
// };
// We use this function in order to retrieve data for main stats. // We use this function in order to retrieve data for main stats.
// The data is of the following form: // The data is of the following form: