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,
Typography
} from '@mui/material';
import { TopologyValues } from '../Log/graph.util';
import {
Link,
Route,
@ -18,17 +19,16 @@ import {
useLocation,
useNavigate
} from 'react-router-dom';
import Button from '@mui/material/Button';
import { FormattedMessage } from 'react-intl';
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 MainStats from './MainStats';
import DetailedBatteryView from './DetailedBatteryView';
import MainStats from './MainStats';
interface BatteryViewProps {
values: JSONRecordData;
values: TopologyValues;
s3Credentials: I_S3Credentials;
installationId: number;
productNum: number;
@ -39,15 +39,12 @@ function BatteryView(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 sortedBatteryView =
props.values != null
? [...props.values.batteryView].sort((a, b) => b.BatteryId - a.BatteryId)
: [];
const [loading, setLoading] = useState(sortedBatteryView.length == 0);
@ -55,13 +52,13 @@ function BatteryView(props: BatteryViewProps) {
navigate(routes.mainstats);
};
// const findBatteryData = (batteryId: number) => {
// for (let i = 0; i < props.values.batteryView.length; i++) {
// if (props.values.batteryView[i].BatteryId == batteryId) {
// return props.values.batteryView[i];
// }
// }
// };
const findBatteryData = (batteryId: number) => {
for (let i = 0; i < props.values.batteryView.length; i++) {
if (props.values.batteryView[i].BatteryId == batteryId) {
return props.values.batteryView[i];
}
}
};
useEffect(() => {
if (sortedBatteryView.length == 0) {
@ -179,23 +176,20 @@ function BatteryView(props: BatteryViewProps) {
></MainStats>
}
/>
{Object.entries(props.values.Battery.Devices).map(
([BatteryId, battery]) => (
{props.values.batteryView.map((battery) => (
<Route
key={routes.detailed_view + BatteryId}
path={routes.detailed_view + BatteryId}
key={routes.detailed_view + battery.BatteryId}
path={routes.detailed_view + battery.BatteryId}
element={
<DetailedBatteryView
batteryId={Number(BatteryId)}
s3Credentials={props.s3Credentials}
batteryData={battery}
batteryData={findBatteryData(battery.BatteryId)}
installationId={props.installationId}
productNum={props.productNum}
></DetailedBatteryView>
}
/>
)
)}
))}
</Routes>
</Grid>
@ -225,9 +219,9 @@ function BatteryView(props: BatteryViewProps) {
</TableRow>
</TableHead>
<TableBody>
{sortedBatteryView.map(({ BatteryId, battery }) => (
{sortedBatteryView.map((battery) => (
<TableRow
key={BatteryId}
key={battery.BatteryId}
style={{
height: '10px'
}}
@ -240,9 +234,9 @@ function BatteryView(props: BatteryViewProps) {
>
<Link
style={{ color: 'black' }}
to={routes.detailed_view + BatteryId}
to={routes.detailed_view + battery.BatteryId.toString()}
>
{'Node ' + BatteryId}
{'Node ' + battery.BatteryId}
</Link>
</TableCell>
<TableCell
@ -259,7 +253,7 @@ function BatteryView(props: BatteryViewProps) {
textAlign: 'center'
}}
>
{battery.Dc.Power.value + ' W'}
{battery.Power.value + ' ' + battery.Power.unit}
</TableCell>
<TableCell
sx={{
@ -267,14 +261,15 @@ function BatteryView(props: BatteryViewProps) {
textAlign: 'center',
backgroundColor:
battery.Dc.Voltage.value < 44 ||
battery.Dc.Voltage.value > 57
battery.Voltage.value < 44 ||
battery.Voltage.value > 57
? '#FF033E'
: '#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
sx={{
@ -286,144 +281,47 @@ function BatteryView(props: BatteryViewProps) {
: battery.Soc.value < 50
? '#ffbf00'
: '#32CD32',
color: battery.Soc.value ? 'inherit' : 'white'
color: battery.Soc.value === '' ? 'white' : 'inherit'
}}
>
{battery.Soc.value + ' %'}
{battery.Soc.value + ' ' + battery.Soc.unit}
</TableCell>
<TableCell
sx={{
width: '10%',
textAlign: 'center',
backgroundColor:
battery.Temperatures.Cells.Average.value > 300
battery.AverageTemperature.value > 300
? '#FF033E'
: battery.Temperatures.Cells.Average.value > 280
: battery.AverageTemperature.value > 280
? '#ffbf00'
: battery.Temperatures.Cells.Average.value < 245
: battery.AverageTemperature.value < 245
? '#008FFB'
: '#32CD32'
}}
>
{battery.Temperatures.Cells.Average.value + ' C'}
{battery.AverageTemperature.value +
' ' +
battery.AverageTemperature.unit}
</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',
battery.Warnings.value !== '' ? 'bold' : 'inherit',
backgroundColor:
Number(battery.Warnings) === 0
? 'inherit'
: '#ff9900',
battery.Warnings.value === '' ? 'inherit' : '#ff9900',
color:
Number(battery.Warnings) != 0
? 'black'
: 'inherit'
battery.Warnings.value != '' ? 'black' : 'inherit'
}}
>
{Number(battery.Warnings) === 0 ? (
{battery.Warnings.value === '' ? (
'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>
) : (
) : battery.Warnings.value.toString().split('-').length >
1 ? (
<Link
style={{ color: 'black' }}
to={
@ -437,6 +335,8 @@ function BatteryView(props: BatteryViewProps) {
>
Multiple Warnings
</Link>
) : (
battery.Warnings.value
)}
</TableCell>
<TableCell
@ -444,32 +344,16 @@ function BatteryView(props: BatteryViewProps) {
width: '20%',
textAlign: 'center',
fontWeight:
Number(battery.Alarms) !== 0 ? 'bold' : 'inherit',
battery.Alarms.value !== '' ? 'bold' : 'inherit',
backgroundColor:
Number(battery.Alarms) === 0
? 'inherit'
: '#FF033E',
color:
Number(battery.Alarms) != 0 ? 'black' : 'inherit'
battery.Alarms.value === '' ? 'inherit' : '#FF033E',
color: battery.Alarms.value != '' ? 'black' : 'inherit'
}}
>
{Number(battery.Alarms) === 0 ? (
{battery.Alarms.value === '' ? (
'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>
) : (
) : battery.Alarms.value.toString().split('-').length >
1 ? (
<Link
style={{ color: 'black' }}
to={
@ -483,10 +367,10 @@ function BatteryView(props: BatteryViewProps) {
>
Multiple Alarms
</Link>
) : (
battery.Alarms.value
)}
</TableCell>
</>
)}
</TableRow>
))}
</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,
Typography
} from '@mui/material';
import { Device } from '../Log/graph.util';
import { Battery } from '../Log/graph.util';
import { useNavigate } from 'react-router-dom';
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import Button from '@mui/material/Button';
@ -25,9 +25,8 @@ import { UserType } from '../../../interfaces/UserTypes';
import { UserContext } from '../../../contexts/userContext';
interface DetailedBatteryViewProps {
batteryId: number;
s3Credentials: I_S3Credentials;
batteryData: Device;
batteryData: Battery;
installationId: number;
productNum: number;
}
@ -36,7 +35,6 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
if (props.batteryData === null) {
return null;
}
const navigate = useNavigate();
const [openModalFirmwareUpdate, setOpenModalFirmwareUpdate] = useState(false);
const [openModalResultFirmwareUpdate, setOpenModalResultFirmwareUpdate] =
@ -67,35 +65,35 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
};
const [GreenisBlinking, setGreenisBlinking] = useState(
props.batteryData.Leds.Green.value === 'Blinking'
props.batteryData.GreenLeds.value === 'Blinking'
);
const [AmberisBlinking, setAmberisBlinking] = useState(
props.batteryData.Leds.Amber.value === 'Blinking'
props.batteryData.AmberLeds.value === 'Blinking'
);
const [RedisBlinking, setRedisBlinking] = useState(
props.batteryData.Leds.Red.value === 'Blinking'
props.batteryData.RedLeds.value === 'Blinking'
);
const [BlueisBlinking, setBlueisBlinking] = useState(
props.batteryData.Leds.Blue.value === 'Blinking'
props.batteryData.BlueLeds.value === 'Blinking'
);
useEffect(() => {
const intervalId = setInterval(() => {
if (props.batteryData.Leds.Amber.value === 'Blinking') {
if (props.batteryData.AmberLeds.value === 'Blinking') {
setAmberisBlinking((prevIsBlinking) => !prevIsBlinking);
}
if (props.batteryData.Leds.Red.value === 'Blinking') {
if (props.batteryData.RedLeds.value === 'Blinking') {
setRedisBlinking((prevIsBlinking) => !prevIsBlinking);
}
if (props.batteryData.Leds.Blue.value === 'Blinking') {
if (props.batteryData.BlueLeds.value === 'Blinking') {
setBlueisBlinking((prevIsBlinking) => !prevIsBlinking);
}
if (props.batteryData.Leds.Green.value === 'Blinking') {
if (props.batteryData.GreenLeds.value === 'Blinking') {
setGreenisBlinking((prevIsBlinking) => !prevIsBlinking);
}
}, 500); // Blink every 500 milliseconds
@ -131,7 +129,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
const res = await axiosConfig
.post(
`/UpdateFirmware?batteryNode=${props.batteryId.toString()}&installationId=${
`/UpdateFirmware?batteryNode=${props.batteryData.BatteryId.toString()}&installationId=${
props.installationId
}&version=${selectedVersion}`
)
@ -171,7 +169,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
try {
// Start the job to generate the battery log
const startRes = await axiosConfig.post(
`/StartDownloadBatteryLog?batteryNode=${props.batteryId.toString()}&installationId=${
`/StartDownloadBatteryLog?batteryNode=${props.batteryData.BatteryId.toString()}&installationId=${
props.installationId
}`
);
@ -637,7 +635,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
fontWeight: 'bold'
}}
>
{'Node ' + props.batteryId}
{'Node ' + props.batteryData.BatteryId}
</Typography>
<div style={batteryStyle}>
@ -645,11 +643,8 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
style={{
...batteryStringStyle,
backgroundColor:
props.batteryData.BatteryStrings.String1Active.value ==
'True' ||
Number(
props.batteryData.BatteryStrings.String1Active.value
) == 0
props.batteryData.String1Active.value == 'True' ||
Number(props.batteryData.String1Active.value) == 0
? '#32CD32'
: '#FF033E'
}}
@ -658,11 +653,8 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
style={{
...batteryStringStyle,
backgroundColor:
props.batteryData.BatteryStrings.String2Active.value ==
'True' ||
Number(
props.batteryData.BatteryStrings.String2Active.value
) == 0
props.batteryData.String2Active.value == 'True' ||
Number(props.batteryData.String2Active.value) == 0
? '#32CD32'
: '#FF033E'
}}
@ -671,11 +663,8 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
style={{
...batteryStringStyle,
backgroundColor:
props.batteryData.BatteryStrings.String3Active.value ==
'True' ||
Number(
props.batteryData.BatteryStrings.String3Active.value
) == 0
props.batteryData.String3Active.value == 'True' ||
Number(props.batteryData.String3Active.value) == 0
? '#32CD32'
: '#FF033E'
}}
@ -684,11 +673,8 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
style={{
...batteryStringStyle,
backgroundColor:
props.batteryData.BatteryStrings.String4Active.value ==
'True' ||
Number(
props.batteryData.BatteryStrings.String4Active.value
) == 0
props.batteryData.String4Active.value == 'True' ||
Number(props.batteryData.String4Active.value) == 0
? '#32CD32'
: '#FF033E'
}}
@ -697,11 +683,8 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
style={{
...batteryStringStyle,
backgroundColor:
props.batteryData.BatteryStrings.String5Active.value ==
'True' ||
Number(
props.batteryData.BatteryStrings.String5Active.value
) == 0
props.batteryData.String5Active.value == 'True' ||
Number(props.batteryData.String5Active.value) == 0
? '#32CD32'
: '#FF033E'
}}
@ -716,7 +699,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
marginTop: '-10px',
borderRadius: '50%',
backgroundColor:
props.batteryData.Leds.Green.value === 'On' ||
props.batteryData.GreenLeds.value === 'On' ||
GreenisBlinking
? 'green'
: 'transparent'
@ -731,7 +714,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
marginTop: '10px',
borderRadius: '50%',
backgroundColor:
props.batteryData.Leds.Amber.value === 'On' ||
props.batteryData.AmberLeds.value === 'On' ||
AmberisBlinking
? 'orange'
: 'transparent'
@ -746,7 +729,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
marginTop: '10px',
borderRadius: '50%',
backgroundColor:
props.batteryData.Leds.Blue.value === 'On' || BlueisBlinking
props.batteryData.BlueLeds.value === 'On' || BlueisBlinking
? '#00ccff'
: 'transparent'
}}
@ -760,7 +743,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
marginTop: '10px',
borderRadius: '50%',
backgroundColor:
props.batteryData.Leds.Red.value === 'On' || RedisBlinking
props.batteryData.RedLeds.value === 'On' || RedisBlinking
? 'red'
: 'transparent'
}}
@ -820,7 +803,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px'
}}
>
{props.batteryData.Dc.Voltage.value + ' V'}
{props.batteryData.Voltage.value +
' ' +
props.batteryData.Voltage.unit}
</TableCell>
</TableRow>
<TableRow>
@ -840,7 +825,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px'
}}
>
{props.batteryData.Dc.Current.value + ' A'}
{props.batteryData.Current.value +
' ' +
props.batteryData.Current.unit}
</TableCell>
</TableRow>
<TableRow>
@ -860,7 +847,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px'
}}
>
{props.batteryData.Dc.Power.value + ' W'}
{props.batteryData.Power.value +
' ' +
props.batteryData.Power.unit}
</TableCell>
</TableRow>
@ -881,7 +870,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px'
}}
>
{props.batteryData.BusCurrent.value + ' A'}
{props.batteryData.BusCurrent.value +
' ' +
props.batteryData.BusCurrent.unit}
</TableCell>
</TableRow>
<TableRow>
@ -901,7 +892,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px'
}}
>
{props.batteryData.CellsCurrent.value + ' A'}
{props.batteryData.CellsCurrent.value +
' ' +
props.batteryData.CellsCurrent.unit}
</TableCell>
</TableRow>
<TableRow>
@ -921,7 +914,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px'
}}
>
{props.batteryData.HeatingCurrent.value + ' A'}
{props.batteryData.HeatingCurrent.value +
' ' +
props.batteryData.HeatingCurrent.unit}
</TableCell>
</TableRow>
@ -942,7 +937,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px'
}}
>
{props.batteryData.Soc.value + ' %'}
{props.batteryData.Soc.value +
' ' +
props.batteryData.Soc.unit}
</TableCell>
</TableRow>
</TableBody>
@ -952,200 +949,200 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
</Grid>
{/*----------------------------------------------------------------------------------------------------------------------------------*/}
{/*{props.productNum === 0 && (*/}
{/* <>*/}
{/* <Grid item md={3} xs={3}>*/}
{/* <Card*/}
{/* sx={{*/}
{/* overflow: 'visible',*/}
{/* marginTop: '30px',*/}
{/* marginLeft: '20px',*/}
{/* display: 'flex',*/}
{/* flexDirection: 'column',*/}
{/* alignItems: 'center',*/}
{/* border: '2px solid #ccc',*/}
{/* borderRadius: '12px'*/}
{/* }}*/}
{/* >*/}
{/* <Typography*/}
{/* variant="h6"*/}
{/* component="div"*/}
{/* sx={{*/}
{/* marginTop: '10px',*/}
{/* borderBottom: '1px solid #ccc',*/}
{/* fontWeight: 'bold'*/}
{/* }}*/}
{/* >*/}
{/* Temperature*/}
{/* </Typography>*/}
{props.productNum === 0 && (
<>
<Grid item md={3} xs={3}>
<Card
sx={{
overflow: 'visible',
marginTop: '30px',
marginLeft: '20px',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
border: '2px solid #ccc',
borderRadius: '12px'
}}
>
<Typography
variant="h6"
component="div"
sx={{
marginTop: '10px',
borderBottom: '1px solid #ccc',
fontWeight: 'bold'
}}
>
Temperature
</Typography>
{/* <TableContainer*/}
{/* component={Paper}*/}
{/* sx={{ marginTop: '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>*/}
{/* </>*/}
{/*)}*/}
<TableContainer
component={Paper}
sx={{ marginTop: '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={3} xs={3}>
@ -1196,9 +1193,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px'
}}
>
{props.batteryData.IoStatus.ConnectedToDcBus.value
? 'True'
: 'False'}
{props.batteryData.ConnectedToDcBus.value +
' ' +
props.batteryData.ConnectedToDcBus.unit}
</TableCell>
</TableRow>
<TableRow>
@ -1218,9 +1215,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px'
}}
>
{props.batteryData.IoStatus.AlarmOutActive.value
? 'True'
: 'False'}
{props.batteryData.AlarmOutActive.value +
' ' +
props.batteryData.AlarmOutActive.unit}
</TableCell>
</TableRow>
<TableRow>
@ -1240,9 +1237,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px'
}}
>
{props.batteryData.IoStatus.InternalFanActive.value
? 'True'
: 'False'}
{props.batteryData.InternalFanActive.value +
' ' +
props.batteryData.InternalFanActive.unit}
</TableCell>
</TableRow>
<TableRow>
@ -1262,9 +1259,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px'
}}
>
{props.batteryData.IoStatus.VoltMeasurementAllowed.value
? 'True'
: 'False'}
{props.batteryData.VoltMeasurementAllowed.value +
' ' +
props.batteryData.VoltMeasurementAllowed.unit}
</TableCell>
</TableRow>
<TableRow>
@ -1284,9 +1281,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px'
}}
>
{props.batteryData.IoStatus.AuxRelayBus.value
? 'True'
: 'False'}
{props.batteryData.AuxRelayBus.value +
' ' +
props.batteryData.AuxRelayBus.unit}
</TableCell>
</TableRow>
<TableRow>
@ -1306,9 +1303,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px'
}}
>
{props.batteryData.IoStatus.RemoteStateActive.value
? 'True'
: 'False'}
{props.batteryData.RemoteStateActive.value +
' ' +
props.batteryData.RemoteStateActive.unit}
</TableCell>
</TableRow>
<TableRow>
@ -1328,9 +1325,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px'
}}
>
{props.batteryData.IoStatus.RiscActive.value
? 'True'
: 'False'}
{props.batteryData.RiscActive.value +
' ' +
props.batteryData.RiscActive.unit}
</TableCell>
</TableRow>
</TableBody>
@ -1388,7 +1385,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px'
}}
>
{props.batteryData.Eoc.value}
{props.batteryData.Eoc.value +
' ' +
props.batteryData.Eoc.unit}
</TableCell>
</TableRow>
@ -1409,7 +1408,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px'
}}
>
{props.batteryData.SerialNumber.value}
{props.batteryData.SerialNumber.value +
' ' +
props.batteryData.SerialNumber.unit}
</TableCell>
</TableRow>
@ -1430,7 +1431,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px'
}}
>
{props.batteryData.FwVersion.value}
{props.batteryData.FwVersion.value +
' ' +
props.batteryData.FwVersion.unit}
</TableCell>
</TableRow>
<TableRow>
@ -1450,33 +1453,35 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px'
}}
>
{props.batteryData.TimeSinceTOC.value}
{props.batteryData.TimeSinceTOC.value +
' ' +
props.batteryData.TimeSinceTOC.unit}
</TableCell>
</TableRow>
{/*{props.productNum === 0 && (*/}
{/* <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>*/}
{/*)}*/}
{props.productNum === 0 && (
<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"
@ -1494,7 +1499,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px'
}}
>
{props.batteryData.MaxChargePower.value + ' W'}
{props.batteryData.MaxChargePower.value +
' ' +
props.batteryData.MaxChargePower.unit}
</TableCell>
</TableRow>
<TableRow>
@ -1514,7 +1521,9 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
paddingRight: '12px'
}}
>
{props.batteryData.MaxDischargePower.value + ' W'}
{props.batteryData.MaxDischargePower.value +
' ' +
props.batteryData.MaxDischargePower.unit}
</TableCell>
</TableRow>
</TableBody>
@ -1522,111 +1531,6 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
</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' }}*/}
{/* >*/}
{/* 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 {
BatteryDataInterface,
BatteryOverviewInterface,
transformInputToBatteryViewDataJson
transformInputToBatteryViewData
} from '../../../interfaces/Chart';
import dayjs, { Dayjs } from 'dayjs';
import { TimeSpan, UnixTime } from '../../../dataCache/time';
@ -96,7 +96,7 @@ function MainStats(props: MainStatsProps) {
const resultPromise: Promise<{
chartData: BatteryDataInterface;
chartOverview: BatteryOverviewInterface;
}> = transformInputToBatteryViewDataJson(
}> = transformInputToBatteryViewData(
props.s3Credentials,
props.id,
product,
@ -192,7 +192,7 @@ function MainStats(props: MainStatsProps) {
const resultPromise: Promise<{
chartData: BatteryDataInterface;
chartOverview: BatteryOverviewInterface;
}> = transformInputToBatteryViewDataJson(
}> = transformInputToBatteryViewData(
props.s3Credentials,
props.id,
product,
@ -254,7 +254,7 @@ function MainStats(props: MainStatsProps) {
const resultPromise: Promise<{
chartData: BatteryDataInterface;
chartOverview: BatteryOverviewInterface;
}> = transformInputToBatteryViewDataJson(
}> = transformInputToBatteryViewData(
props.s3Credentials,
props.id,
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 HistoryOfActions from '../History/History';
import PvView from '../PvView/PvView';
import BatteryView from '../BatteryView/BatteryView';
interface singleInstallationProps {
current_installation?: I_Installation;
@ -421,18 +422,18 @@ function Installation(props: singleInstallationProps) {
}
/>
{/*<Route*/}
{/* path={routes.batteryview + '*'}*/}
{/* element={*/}
{/* <BatteryView*/}
{/* values={values}*/}
{/* s3Credentials={s3Credentials}*/}
{/* installationId={props.current_installation.id}*/}
{/* productNum={props.current_installation.product}*/}
{/* connected={connected}*/}
{/* ></BatteryView>*/}
{/* }*/}
{/*></Route>*/}
<Route
path={routes.batteryview + '*'}
element={
<BatteryView
values={values}
s3Credentials={s3Credentials}
installationId={props.current_installation.id}
productNum={props.current_installation.product}
connected={connected}
></BatteryView>
}
></Route>
<Route
path={routes.pvview + '*'}

View File

@ -50,7 +50,7 @@ function InstallationTabs() {
} else if (path[path.length - 2] === 'tree') {
setCurrentTab('tree');
} 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)));
}
}, [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 routes from '../../../Resources/routes.json';
import InformationSalidomo from '../Information/InformationSalidomo';
import BatteryView from '../BatteryView/BatteryView';
import BatteryViewSalidomo from '../BatteryView/BatteryViewSalidomo';
import Log from '../Log/Log';
import CancelIcon from '@mui/icons-material/Cancel';
import SalidomoOverview from '../Overview/salidomoOverview';
@ -361,13 +361,13 @@ function SalidomoInstallation(props: singleInstallationProps) {
<Route
path={routes.batteryview + '*'}
element={
<BatteryView
<BatteryViewSalidomo
values={values}
s3Credentials={s3Credentials}
installationId={props.current_installation.id}
productNum={props.current_installation.product}
connected={connected}
></BatteryView>
></BatteryViewSalidomo>
}
></Route>

View File

@ -49,7 +49,7 @@ function SalidomoInstallationTabs() {
} else if (path[path.length - 2] === 'tree') {
setCurrentTab('tree');
} 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)));
}
}, [location]);

View File

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

View File

@ -48,7 +48,7 @@ function SodioHomeInstallationTabs() {
} else if (path[path.length - 2] === 'tree') {
setCurrentTab('tree');
} 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)));
}
}, [location]);

View File

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