Compare commits
3 Commits
3a3f2fe1b8
...
2851e34e47
Author | SHA1 | Date |
---|---|---|
Noe | 2851e34e47 | |
Noe | ce12d6a59a | |
Noe | 2f24f97304 |
|
@ -514,18 +514,16 @@ public class Controller : ControllerBase
|
|||
}
|
||||
|
||||
[HttpPost(nameof(UpdateFirmware))]
|
||||
public ActionResult UpdateFirmware(Int64 batteryNode, Int64 installationId,Token authToken)
|
||||
public async Task<ActionResult> UpdateFirmware(Int64 batteryNode, Int64 installationId,Token authToken)
|
||||
{
|
||||
var session = Db.GetSession(authToken);
|
||||
var installationToUpdate = Db.GetInstallationById(installationId);
|
||||
Console.WriteLine("Inside firmware function controller,batteryNode="+batteryNode+ "and installation is "+installationId);
|
||||
|
||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
if (installationToUpdate != null)
|
||||
{
|
||||
session.RunScriptInBackground(installationToUpdate.VpnIp, batteryNode);
|
||||
_ = session.RunScriptInBackground(installationToUpdate.VpnIp, batteryNode);
|
||||
}
|
||||
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ using System.Diagnostics;
|
|||
using InnovEnergy.App.Backend.Database;
|
||||
using InnovEnergy.App.Backend.Relations;
|
||||
using InnovEnergy.Lib.Utils;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
|
||||
namespace InnovEnergy.App.Backend.DataTypes.Methods;
|
||||
|
||||
|
@ -67,8 +68,9 @@ public static class SessionMethods
|
|||
.Apply(Db.Update);
|
||||
}
|
||||
|
||||
public static async Task<Boolean> RunScriptInBackground(this Session? session, String vpnIp, Int64 batteryNode)
|
||||
public static async Task RunScriptInBackground(this Session? session, String vpnIp, Int64 batteryNode)
|
||||
{
|
||||
Console.WriteLine("11111111111111111111111111111111111111111111111111111111111111");
|
||||
string scriptPath = "/home/ubuntu/backend/uploadBatteryFw/update_firmware.sh";
|
||||
|
||||
await Task.Run(() =>
|
||||
|
@ -80,11 +82,11 @@ public static class SessionMethods
|
|||
process.StartInfo.RedirectStandardOutput = true;
|
||||
|
||||
process.Start();
|
||||
string output = process.StandardOutput.ReadToEnd();
|
||||
process.WaitForExit(); // This can be removed if you don't need to wait for the process to finish
|
||||
Console.WriteLine(output);
|
||||
});
|
||||
|
||||
return true;
|
||||
|
||||
Console.WriteLine("222222222222222222222222222222222222222222222222222222222222222");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import {
|
||||
Container,
|
||||
Grid,
|
||||
|
@ -8,7 +8,8 @@ import {
|
|||
TableCell,
|
||||
TableContainer,
|
||||
TableHead,
|
||||
TableRow
|
||||
TableRow,
|
||||
Typography
|
||||
} from '@mui/material';
|
||||
import { TopologyValues } from '../Log/graph.util';
|
||||
import {
|
||||
|
@ -24,10 +25,12 @@ import { I_S3Credentials } from '../../../interfaces/S3Types';
|
|||
import routes from '../../../Resources/routes.json';
|
||||
import MainStats from './MainStats';
|
||||
import DetailedBatteryView from './DetailedBatteryView';
|
||||
import CircularProgress from '@mui/material/CircularProgress';
|
||||
|
||||
interface BatteryViewProps {
|
||||
values: TopologyValues;
|
||||
s3Credentials: I_S3Credentials;
|
||||
installationId: number;
|
||||
}
|
||||
|
||||
function BatteryView(props: BatteryViewProps) {
|
||||
|
@ -40,6 +43,10 @@ function BatteryView(props: BatteryViewProps) {
|
|||
(a, b) => b.BatteryId - a.BatteryId
|
||||
);
|
||||
|
||||
const [loading, setLoading] = useState(
|
||||
sortedBatteryView.length == 0 ? true : false
|
||||
);
|
||||
|
||||
const handleMainStatsButton = () => {
|
||||
navigate(routes.mainstats);
|
||||
};
|
||||
|
@ -52,15 +59,116 @@ function BatteryView(props: BatteryViewProps) {
|
|||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (sortedBatteryView.length == 0) {
|
||||
setLoading(true);
|
||||
} else {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [sortedBatteryView]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Container maxWidth="xl">
|
||||
<Grid container>
|
||||
<Grid
|
||||
item
|
||||
xs={6}
|
||||
md={6}
|
||||
{loading && (
|
||||
<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 && (
|
||||
<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={
|
||||
<MainStats s3Credentials={props.s3Credentials}></MainStats>
|
||||
}
|
||||
/>
|
||||
{props.values.batteryView.map((battery) => (
|
||||
<Route
|
||||
key={routes.detailed_view + battery.BatteryId}
|
||||
path={routes.detailed_view + battery.BatteryId}
|
||||
element={
|
||||
<DetailedBatteryView
|
||||
s3Credentials={props.s3Credentials}
|
||||
batteryData={findBatteryData(battery.BatteryId)}
|
||||
installationId={props.installationId}
|
||||
></DetailedBatteryView>
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</Routes>
|
||||
</Grid>
|
||||
|
||||
<TableContainer
|
||||
component={Paper}
|
||||
sx={{
|
||||
marginTop: '20px',
|
||||
marginBottom: '20px',
|
||||
display:
|
||||
!currentLocation.pathname.includes('detailed_view') &&
|
||||
!currentLocation.pathname.includes('mainstats')
|
||||
|
@ -68,237 +176,175 @@ function BatteryView(props: BatteryViewProps) {
|
|||
: '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={
|
||||
<MainStats s3Credentials={props.s3Credentials}></MainStats>
|
||||
}
|
||||
/>
|
||||
{props.values.batteryView.map((battery) => (
|
||||
<Route
|
||||
key={routes.detailed_view + battery.BatteryId}
|
||||
path={routes.detailed_view + battery.BatteryId}
|
||||
element={
|
||||
<DetailedBatteryView
|
||||
s3Credentials={props.s3Credentials}
|
||||
batteryData={findBatteryData(battery.BatteryId)}
|
||||
></DetailedBatteryView>
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</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((battery) => (
|
||||
<TableRow
|
||||
key={battery.BatteryId}
|
||||
style={{
|
||||
height: '10px'
|
||||
}}
|
||||
>
|
||||
<TableCell
|
||||
component="th"
|
||||
scope="row"
|
||||
align="center"
|
||||
sx={{ fontWeight: 'bold' }}
|
||||
>
|
||||
<Link
|
||||
style={{ color: 'black' }}
|
||||
to={routes.detailed_view + battery.BatteryId.toString()}
|
||||
>
|
||||
{'Node ' + battery.BatteryId}
|
||||
</Link>
|
||||
</TableCell>
|
||||
<TableCell
|
||||
sx={{
|
||||
width: '10%',
|
||||
textAlign: 'center'
|
||||
}}
|
||||
>
|
||||
{battery.FwVersion.value}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
sx={{
|
||||
width: '10%',
|
||||
textAlign: 'center'
|
||||
}}
|
||||
>
|
||||
{battery.Power.value + ' ' + battery.Power.unit}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
sx={{
|
||||
width: '10%',
|
||||
textAlign: 'center',
|
||||
|
||||
backgroundColor:
|
||||
battery.Voltage.value < 44 || battery.Voltage.value > 57
|
||||
? '#FF033E'
|
||||
: '#32CD32',
|
||||
color: battery.Voltage.value === '' ? 'white' : 'inherit'
|
||||
}}
|
||||
>
|
||||
{battery.Voltage.value + ' ' + battery.Voltage.unit}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
sx={{
|
||||
width: '10%',
|
||||
textAlign: 'center',
|
||||
backgroundColor:
|
||||
battery.Soc.value < 20
|
||||
? '#FF033E'
|
||||
: battery.Soc.value < 50
|
||||
? '#ffbf00'
|
||||
: '#32CD32',
|
||||
color: battery.Soc.value === '' ? 'white' : 'inherit'
|
||||
}}
|
||||
>
|
||||
{battery.Soc.value + ' ' + battery.Soc.unit}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
sx={{
|
||||
width: '10%',
|
||||
textAlign: 'center',
|
||||
backgroundColor:
|
||||
battery.AverageTemperature.value > 270
|
||||
? '#FF033E'
|
||||
: '#32CD32 '
|
||||
}}
|
||||
>
|
||||
{battery.AverageTemperature.value +
|
||||
' ' +
|
||||
battery.AverageTemperature.unit}
|
||||
</TableCell>
|
||||
|
||||
<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>
|
||||
<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>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</Container>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{sortedBatteryView.map((battery) => (
|
||||
<TableRow
|
||||
key={battery.BatteryId}
|
||||
style={{
|
||||
height: '10px'
|
||||
}}
|
||||
>
|
||||
<TableCell
|
||||
component="th"
|
||||
scope="row"
|
||||
align="center"
|
||||
sx={{ fontWeight: 'bold' }}
|
||||
>
|
||||
<Link
|
||||
style={{ color: 'black' }}
|
||||
to={routes.detailed_view + battery.BatteryId.toString()}
|
||||
>
|
||||
{'Node ' + battery.BatteryId}
|
||||
</Link>
|
||||
</TableCell>
|
||||
<TableCell
|
||||
sx={{
|
||||
width: '10%',
|
||||
textAlign: 'center'
|
||||
}}
|
||||
>
|
||||
{battery.FwVersion.value}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
sx={{
|
||||
width: '10%',
|
||||
textAlign: 'center'
|
||||
}}
|
||||
>
|
||||
{battery.Power.value + ' ' + battery.Power.unit}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
sx={{
|
||||
width: '10%',
|
||||
textAlign: 'center',
|
||||
|
||||
backgroundColor:
|
||||
battery.Voltage.value < 44 ||
|
||||
battery.Voltage.value > 57
|
||||
? '#FF033E'
|
||||
: '#32CD32',
|
||||
color:
|
||||
battery.Voltage.value === '' ? 'white' : 'inherit'
|
||||
}}
|
||||
>
|
||||
{battery.Voltage.value + ' ' + battery.Voltage.unit}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
sx={{
|
||||
width: '10%',
|
||||
textAlign: 'center',
|
||||
backgroundColor:
|
||||
battery.Soc.value < 20
|
||||
? '#FF033E'
|
||||
: battery.Soc.value < 50
|
||||
? '#ffbf00'
|
||||
: '#32CD32',
|
||||
color: battery.Soc.value === '' ? 'white' : 'inherit'
|
||||
}}
|
||||
>
|
||||
{battery.Soc.value + ' ' + battery.Soc.unit}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
sx={{
|
||||
width: '10%',
|
||||
textAlign: 'center',
|
||||
backgroundColor:
|
||||
battery.AverageTemperature.value > 270
|
||||
? '#FF033E'
|
||||
: '#32CD32 '
|
||||
}}
|
||||
>
|
||||
{battery.AverageTemperature.value +
|
||||
' ' +
|
||||
battery.AverageTemperature.unit}
|
||||
</TableCell>
|
||||
|
||||
<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>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</Container>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { I_S3Credentials } from '../../../interfaces/S3Types';
|
||||
import {
|
||||
Box,
|
||||
Card,
|
||||
Grid,
|
||||
IconButton,
|
||||
Modal,
|
||||
Paper,
|
||||
Table,
|
||||
TableBody,
|
||||
|
@ -12,14 +15,16 @@ import {
|
|||
Typography
|
||||
} from '@mui/material';
|
||||
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';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import routes from '../../../Resources/routes.json';
|
||||
import axiosConfig from '../../../Resources/axiosConfig';
|
||||
|
||||
interface DetailedBatteryViewProps {
|
||||
s3Credentials: I_S3Credentials;
|
||||
batteryData: Battery;
|
||||
installationId: number;
|
||||
}
|
||||
|
||||
function DetailedBatteryView(props: DetailedBatteryViewProps) {
|
||||
|
@ -27,16 +32,20 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
|
|||
return null;
|
||||
}
|
||||
const navigate = useNavigate();
|
||||
const [openModalFirmwareUpdate, setOpenModalFirmwareUpdate] = useState(false);
|
||||
const [openModalResultFirmwareUpdate, setOpenModalResultFirmwareUpdate] =
|
||||
useState(false);
|
||||
|
||||
const handleBatteryViewButton = () => {
|
||||
navigate(location.pathname.split('/').slice(0, -2).join('/'));
|
||||
};
|
||||
const handleMainStatsButton = () => {
|
||||
navigate(
|
||||
location.pathname.split('/').slice(0, -2).join('/') +
|
||||
'/' +
|
||||
routes.mainstats
|
||||
);
|
||||
|
||||
const handleUpdateFirmware = () => {
|
||||
setOpenModalFirmwareUpdate(true);
|
||||
};
|
||||
|
||||
const firmwareModalResultHandleOk = () => {
|
||||
navigate(location.pathname.split('/').slice(0, -2).join('/'));
|
||||
};
|
||||
|
||||
const [GreenisBlinking, setGreenisBlinking] = useState(
|
||||
|
@ -96,26 +105,177 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
|
|||
backgroundColor: '#bfbfbf'
|
||||
};
|
||||
|
||||
const FirmwareModalHandleProceed = async (e) => {
|
||||
setOpenModalFirmwareUpdate(false);
|
||||
|
||||
const res = await axiosConfig
|
||||
.post(
|
||||
`/UpdateFirmware?batteryNode=${props.batteryData.BatteryId.toString()}&installationId=${
|
||||
props.installationId
|
||||
}`
|
||||
)
|
||||
.catch((err) => {
|
||||
if (err.response) {
|
||||
// setError(true);
|
||||
// setLoading(false);
|
||||
}
|
||||
});
|
||||
|
||||
//if (res) {
|
||||
setOpenModalResultFirmwareUpdate(true);
|
||||
//}
|
||||
};
|
||||
|
||||
const FirmwareModalHandleCancel = () => {
|
||||
setOpenModalFirmwareUpdate(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{openModalResultFirmwareUpdate && (
|
||||
<Modal
|
||||
open={openModalResultFirmwareUpdate}
|
||||
aria-labelledby="error-modal"
|
||||
aria-describedby="error-modal-description"
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: '50%',
|
||||
left: '50%',
|
||||
transform: 'translate(-50%, -50%)',
|
||||
width: 420,
|
||||
bgcolor: 'background.paper',
|
||||
borderRadius: 4,
|
||||
boxShadow: 24,
|
||||
p: 4,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body1"
|
||||
gutterBottom
|
||||
sx={{ fontWeight: 'bold' }}
|
||||
>
|
||||
The firmware is getting updated. Please wait...
|
||||
</Typography>
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
marginTop: 10
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
sx={{
|
||||
marginTop: 2,
|
||||
textTransform: 'none',
|
||||
bgcolor: '#ffc04d',
|
||||
color: '#111111',
|
||||
'&:hover': { bgcolor: '#f7b34d' }
|
||||
}}
|
||||
onClick={firmwareModalResultHandleOk}
|
||||
>
|
||||
Ok
|
||||
</Button>
|
||||
</div>
|
||||
</Box>
|
||||
</Modal>
|
||||
)}
|
||||
|
||||
{openModalFirmwareUpdate && (
|
||||
<Modal
|
||||
open={openModalFirmwareUpdate}
|
||||
onClose={FirmwareModalHandleCancel}
|
||||
aria-labelledby="error-modal"
|
||||
aria-describedby="error-modal-description"
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: '50%',
|
||||
left: '50%',
|
||||
transform: 'translate(-50%, -50%)',
|
||||
width: 420,
|
||||
bgcolor: 'background.paper',
|
||||
borderRadius: 4,
|
||||
boxShadow: 24,
|
||||
p: 4,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body1"
|
||||
gutterBottom
|
||||
sx={{ fontWeight: 'bold' }}
|
||||
>
|
||||
Do you really want to update the firmware?
|
||||
</Typography>
|
||||
|
||||
<Typography variant="body1" gutterBottom>
|
||||
This action requires the battery service to be stopped.
|
||||
</Typography>
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
marginTop: 10
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
sx={{
|
||||
marginTop: 2,
|
||||
textTransform: 'none',
|
||||
bgcolor: '#ffc04d',
|
||||
color: '#111111',
|
||||
'&:hover': { bgcolor: '#f7b34d' }
|
||||
}}
|
||||
onClick={FirmwareModalHandleProceed}
|
||||
>
|
||||
Proceed
|
||||
</Button>
|
||||
<Button
|
||||
sx={{
|
||||
marginTop: 2,
|
||||
marginLeft: 2,
|
||||
textTransform: 'none',
|
||||
bgcolor: '#ffc04d',
|
||||
color: '#111111',
|
||||
'&:hover': { bgcolor: '#f7b34d' }
|
||||
}}
|
||||
onClick={FirmwareModalHandleCancel}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</div>
|
||||
</Box>
|
||||
</Modal>
|
||||
)}
|
||||
|
||||
<Grid container>
|
||||
<Grid item xs={6} md={6}>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={handleBatteryViewButton}
|
||||
<IconButton
|
||||
aria-label="go back"
|
||||
sx={{
|
||||
marginTop: '20px',
|
||||
backgroundColor: '#ffc04d',
|
||||
backgroundColor: 'grey',
|
||||
color: '#000000',
|
||||
'&:hover': { bgcolor: '#f7b34d' }
|
||||
}}
|
||||
onClick={handleBatteryViewButton}
|
||||
>
|
||||
<FormattedMessage id="main_stats" defaultMessage="Battery View" />
|
||||
</Button>
|
||||
<ArrowBackIcon />
|
||||
</IconButton>
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={handleMainStatsButton}
|
||||
onClick={handleUpdateFirmware}
|
||||
sx={{
|
||||
marginTop: '20px',
|
||||
marginLeft: '20px',
|
||||
|
@ -124,7 +284,10 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
|
|||
'&:hover': { bgcolor: '#f7b34d' }
|
||||
}}
|
||||
>
|
||||
<FormattedMessage id="main_stats" defaultMessage="Main Stats" />
|
||||
<FormattedMessage
|
||||
id="update_firmware"
|
||||
defaultMessage="Update Firmware"
|
||||
/>
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
|
|
@ -1,4 +1,12 @@
|
|||
import { Box, Card, Container, Grid, Modal, Typography } from '@mui/material';
|
||||
import {
|
||||
Box,
|
||||
Card,
|
||||
Container,
|
||||
Grid,
|
||||
IconButton,
|
||||
Modal,
|
||||
Typography
|
||||
} from '@mui/material';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { I_S3Credentials } from '../../../interfaces/S3Types';
|
||||
|
@ -16,6 +24,7 @@ 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';
|
||||
|
||||
interface MainStatsProps {
|
||||
s3Credentials: I_S3Credentials;
|
||||
|
@ -384,31 +393,18 @@ function MainStats(props: MainStatsProps) {
|
|||
{!loading && (
|
||||
<>
|
||||
<Grid item xs={6} md={6}>
|
||||
<Button
|
||||
variant="contained"
|
||||
<IconButton
|
||||
aria-label="go back"
|
||||
sx={{
|
||||
marginTop: '20px',
|
||||
backgroundColor: 'grey',
|
||||
color: '#000000',
|
||||
'&:hover': { bgcolor: '#f7b34d' }
|
||||
}}
|
||||
onClick={handleBatteryViewButton}
|
||||
sx={{
|
||||
marginTop: '20px',
|
||||
backgroundColor: '#ffc04d',
|
||||
color: '#000000',
|
||||
'&:hover': { bgcolor: '#f7b34d' }
|
||||
}}
|
||||
>
|
||||
<FormattedMessage id="main_stats" defaultMessage="Battery View" />
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
sx={{
|
||||
marginTop: '20px',
|
||||
marginLeft: '20px',
|
||||
backgroundColor: '#808080',
|
||||
color: '#000000',
|
||||
'&:hover': { bgcolor: '#f7b34d' }
|
||||
}}
|
||||
>
|
||||
<FormattedMessage id="main_stats" defaultMessage="Main Stats" />
|
||||
</Button>
|
||||
<ArrowBackIcon />
|
||||
</IconButton>
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
|
|
|
@ -35,7 +35,13 @@ function Configuration(props: ConfigurationProps) {
|
|||
return null;
|
||||
}
|
||||
|
||||
const forcedCalibrationChargeOptions = [
|
||||
const CalibrationChargeOptions = [
|
||||
'Repetitive Calibration',
|
||||
'Additional Calibration',
|
||||
'Force Calibration Now'
|
||||
];
|
||||
|
||||
const CalibrationChargeOptionsController = [
|
||||
'RepetitivelyEvery',
|
||||
'AdditionallyOnce',
|
||||
'ChargePermanently'
|
||||
|
@ -64,31 +70,55 @@ function Configuration(props: ConfigurationProps) {
|
|||
selectedForcedCalibrationChargeOption,
|
||||
setSelectedForcedCalibrationChargeOption
|
||||
] = useState<string>(
|
||||
props.values.calibrationChargeForced[0].value.toString()
|
||||
CalibrationChargeOptions[
|
||||
CalibrationChargeOptionsController.indexOf(
|
||||
props.values.calibrationChargeState[0].value.toString()
|
||||
)
|
||||
]
|
||||
);
|
||||
const [formValues, setFormValues] = useState<ConfigurationValues>({
|
||||
minimumSoC: props.values.minimumSoC[0].value,
|
||||
gridSetPoint: (props.values.gridSetPoint[0].value as number) / 1000,
|
||||
forceCalibrationCharge: forcedCalibrationChargeOptions.indexOf(
|
||||
props.values.calibrationChargeForced[0].value.toString()
|
||||
CalibrationChargeState: CalibrationChargeOptionsController.indexOf(
|
||||
props.values.calibrationChargeState[0].value.toString()
|
||||
),
|
||||
calibrationChargeDate: null
|
||||
calibrationChargeDate:
|
||||
CalibrationChargeOptionsController.indexOf(
|
||||
props.values.calibrationChargeState[0].value.toString()
|
||||
) == 0
|
||||
? dayjs(props.values.repetitiveCalibrationChargeDate[0].value).toDate()
|
||||
: dayjs(props.values.additionalCalibrationChargeDate[0].value).toDate()
|
||||
});
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
setLoading(true);
|
||||
const res = await axiosConfig
|
||||
.post(`/EditInstallationConfig?installationId=${props.id}`, formValues)
|
||||
.catch((err) => {
|
||||
if (err.response) {
|
||||
setError(true);
|
||||
setLoading(false);
|
||||
}
|
||||
});
|
||||
if (
|
||||
props.values.mode[0].value === 'CalibrationCharge' &&
|
||||
formValues.CalibrationChargeState == 0
|
||||
) {
|
||||
setDateSelectionError(
|
||||
'You cannot change the date while the installation is in Calibration Charge Mode'
|
||||
);
|
||||
setErrorDateModalOpen(true);
|
||||
return;
|
||||
} else if (dayjs(formValues.calibrationChargeDate).isBefore(dayjs())) {
|
||||
setDateSelectionError('You must specify a future date');
|
||||
setErrorDateModalOpen(true);
|
||||
return;
|
||||
} else {
|
||||
setLoading(true);
|
||||
const res = await axiosConfig
|
||||
.post(`/EditInstallationConfig?installationId=${props.id}`, formValues)
|
||||
.catch((err) => {
|
||||
if (err.response) {
|
||||
setError(true);
|
||||
setLoading(false);
|
||||
}
|
||||
});
|
||||
|
||||
if (res) {
|
||||
setUpdated(true);
|
||||
setLoading(false);
|
||||
if (res) {
|
||||
setUpdated(true);
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -97,12 +127,6 @@ function Configuration(props: ConfigurationProps) {
|
|||
};
|
||||
|
||||
const handleConfirm = (newDate) => {
|
||||
if (newDate.isBefore(dayjs())) {
|
||||
setDateSelectionError('You must specify a future date');
|
||||
setErrorDateModalOpen(true);
|
||||
return;
|
||||
}
|
||||
|
||||
setFormValues({
|
||||
...formValues,
|
||||
['calibrationChargeDate']: newDate.toDate()
|
||||
|
@ -114,9 +138,17 @@ function Configuration(props: ConfigurationProps) {
|
|||
|
||||
setFormValues({
|
||||
...formValues,
|
||||
['forceCalibrationCharge']: forcedCalibrationChargeOptions.indexOf(
|
||||
['CalibrationChargeState']: CalibrationChargeOptions.indexOf(
|
||||
event.target.value
|
||||
)
|
||||
),
|
||||
['calibrationChargeDate']:
|
||||
CalibrationChargeOptions.indexOf(event.target.value) == 0
|
||||
? dayjs(
|
||||
props.values.repetitiveCalibrationChargeDate[0].value
|
||||
).toDate()
|
||||
: dayjs(
|
||||
props.values.additionalCalibrationChargeDate[0].value
|
||||
).toDate()
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -258,7 +290,7 @@ function Configuration(props: ConfigurationProps) {
|
|||
>
|
||||
<FormattedMessage
|
||||
id="forced_calibration_charge"
|
||||
defaultMessage="Forced Calibration Charge"
|
||||
defaultMessage="Calibration Charge State"
|
||||
/>
|
||||
</InputLabel>
|
||||
<Select
|
||||
|
@ -268,7 +300,7 @@ function Configuration(props: ConfigurationProps) {
|
|||
onClose={handleCloseForcedCalibrationCharge}
|
||||
onOpen={handleOpenForcedCalibrationCharge}
|
||||
>
|
||||
{forcedCalibrationChargeOptions.map((option) => (
|
||||
{CalibrationChargeOptions.map((option) => (
|
||||
<MenuItem key={option} value={option}>
|
||||
{option}
|
||||
</MenuItem>
|
||||
|
@ -276,22 +308,12 @@ function Configuration(props: ConfigurationProps) {
|
|||
</Select>
|
||||
</FormControl>
|
||||
</div>
|
||||
{formValues.forceCalibrationCharge != 2 && (
|
||||
{formValues.CalibrationChargeState != 2 && (
|
||||
<div>
|
||||
<LocalizationProvider dateAdapter={AdapterDayjs}>
|
||||
<DateTimePicker
|
||||
label="Select Next Calibration Charge Date"
|
||||
value={
|
||||
formValues.forceCalibrationCharge == 0
|
||||
? dayjs(
|
||||
props.values.repetitiveCalibrationChargeDate[0]
|
||||
.value
|
||||
)
|
||||
: dayjs(
|
||||
props.values.additionalCalibrationChargeDate[0]
|
||||
.value
|
||||
)
|
||||
}
|
||||
value={dayjs(formValues.calibrationChargeDate)}
|
||||
onChange={handleConfirm}
|
||||
sx={{
|
||||
marginTop: 2
|
||||
|
|
|
@ -278,6 +278,7 @@ function Installation(props: singleInstallationProps) {
|
|||
<BatteryView
|
||||
values={values}
|
||||
s3Credentials={s3Credentials}
|
||||
installationId={props.current_installation.id}
|
||||
></BatteryView>
|
||||
}
|
||||
></Route>
|
||||
|
|
|
@ -31,7 +31,7 @@ export interface I_BoxDataValue {
|
|||
export type ConfigurationValues = {
|
||||
minimumSoC: string | number;
|
||||
gridSetPoint: number;
|
||||
forceCalibrationCharge: number;
|
||||
CalibrationChargeState: number;
|
||||
calibrationChargeDate: Date | null;
|
||||
};
|
||||
|
||||
|
@ -157,7 +157,7 @@ export type TopologyValues = {
|
|||
gridSetPoint: I_BoxDataValue[];
|
||||
maximumDischargePower: I_BoxDataValue[];
|
||||
DcDcNum: I_BoxDataValue[];
|
||||
calibrationChargeForced: I_BoxDataValue[];
|
||||
calibrationChargeState: I_BoxDataValue[];
|
||||
mode: I_BoxDataValue[];
|
||||
repetitiveCalibrationChargeDate: I_BoxDataValue[];
|
||||
additionalCalibrationChargeDate: I_BoxDataValue[];
|
||||
|
@ -296,7 +296,7 @@ export const topologyPaths: TopologyPaths = {
|
|||
gridSetPoint: ['/Config/GridSetPoint'],
|
||||
maximumDischargePower: ['/Config/MaxBatteryDischargingCurrent'],
|
||||
DcDcNum: ['/DcDc/SystemControl/NumberOfConnectedSlaves'],
|
||||
calibrationChargeForced: ['/Config/ForceCalibrationChargeState'],
|
||||
calibrationChargeState: ['/Config/ForceCalibrationChargeState'],
|
||||
mode: ['/EssControl/Mode'],
|
||||
repetitiveCalibrationChargeDate: [
|
||||
'/Config/DayAndTimeForRepetitiveCalibration'
|
||||
|
|
Loading…
Reference in New Issue