Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
d500b500d9
|
|
@ -299,6 +299,7 @@ internal static class Program
|
|||
{
|
||||
subscribedNow = true;
|
||||
_subscribeToQueueForTheFirstTime = true;
|
||||
_prevSalimaxState = currentSalimaxState.Status;
|
||||
_subscribedToQueue = RabbitMqManager.SubscribeToQueue(currentSalimaxState, s3Bucket, VpnServerIp);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -128,8 +128,8 @@ public partial class Battery48TlRecord
|
|||
{
|
||||
Boolean HasBit(Int16 bit) => (_AlarmFlags & 1uL << bit) > 0;
|
||||
|
||||
if (HasBit(0) ) yield return "Tam : BMS temperature too low";
|
||||
if (HasBit(2) ) yield return "TaM2 : BMS temperature too high";
|
||||
if (HasBit(0)) yield return "Tam : BMS temperature too low";
|
||||
if (HasBit(2)) yield return "TaM2 : BMS temperature too high";
|
||||
if (HasBit(3) ) yield return "Tbm : Battery temperature too low";
|
||||
if (HasBit(5) ) yield return "TbM2 : Battery temperature too high";
|
||||
if (HasBit(7) ) yield return "VBm2 : Bus voltage too low";
|
||||
|
|
|
|||
|
|
@ -25,8 +25,7 @@ function App() {
|
|||
const context = useContext(UserContext);
|
||||
const { currentUser, setUser } = context;
|
||||
const tokencontext = useContext(TokenContext);
|
||||
const { token, setNewToken, removeToken } = tokencontext;
|
||||
const [forgotPassword, setForgotPassword] = useState(false);
|
||||
const { token, setNewToken } = tokencontext;
|
||||
const navigate = useNavigate();
|
||||
const searchParams = new URLSearchParams(location.search);
|
||||
const username = searchParams.get('username');
|
||||
|
|
@ -43,14 +42,6 @@ function App() {
|
|||
}
|
||||
};
|
||||
|
||||
const onForgotPassword = () => {
|
||||
setForgotPassword(true);
|
||||
};
|
||||
|
||||
const resetPassword = () => {
|
||||
setForgotPassword(false);
|
||||
};
|
||||
|
||||
const Loader = (Component) => (props) =>
|
||||
(
|
||||
<Suspense fallback={<SuspenseLoader />}>
|
||||
|
|
@ -58,11 +49,6 @@ function App() {
|
|||
</Suspense>
|
||||
);
|
||||
|
||||
// Dashboards
|
||||
const Installations = Loader(
|
||||
lazy(() => import('src/content/dashboards/Installations/'))
|
||||
);
|
||||
|
||||
const ResetPassword = Loader(
|
||||
lazy(() => import('src/components/ResetPassword'))
|
||||
);
|
||||
|
|
@ -84,23 +70,9 @@ function App() {
|
|||
navigate(routes.installations);
|
||||
}
|
||||
})
|
||||
.catch((error) => {});
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
// Status
|
||||
const Status404 = Loader(
|
||||
lazy(() => import('src/content/pages/Status/Status404'))
|
||||
);
|
||||
const Status500 = Loader(
|
||||
lazy(() => import('src/content/pages/Status/Status500'))
|
||||
);
|
||||
const StatusComingSoon = Loader(
|
||||
lazy(() => import('src/content/pages/Status/ComingSoon'))
|
||||
);
|
||||
const StatusMaintenance = Loader(
|
||||
lazy(() => import('src/content/pages/Status/Maintenance'))
|
||||
);
|
||||
|
||||
if (username) {
|
||||
loginToResetPassword();
|
||||
}
|
||||
|
|
@ -174,7 +146,6 @@ function App() {
|
|||
</AccessContextProvider>
|
||||
}
|
||||
/>
|
||||
|
||||
<Route path={routes.users + '*'} element={<Users />} />
|
||||
<Route
|
||||
path={'*'}
|
||||
|
|
|
|||
|
|
@ -18,5 +18,7 @@
|
|||
"information": "information",
|
||||
"configuration": "configuration",
|
||||
"login": "/login/",
|
||||
"forgotPassword": "/forgotPassword/"
|
||||
"forgotPassword": "/forgotPassword/",
|
||||
"mainstats": "mainstats",
|
||||
"general": "general"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,37 +1,47 @@
|
|||
import React from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import {
|
||||
Container,
|
||||
Grid,
|
||||
Paper,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableHead,
|
||||
TableRow,
|
||||
useTheme
|
||||
TableRow
|
||||
} from '@mui/material';
|
||||
import { TopologyValues } from '../Log/graph.util';
|
||||
import { Link } from 'react-router-dom';
|
||||
import {
|
||||
Link,
|
||||
Route,
|
||||
Routes,
|
||||
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 MainStats from './MainStats';
|
||||
|
||||
interface BatteryViewProps {
|
||||
values: TopologyValues;
|
||||
s3Credentials: I_S3Credentials;
|
||||
}
|
||||
|
||||
function BatteryView(props: BatteryViewProps) {
|
||||
if (props.values === null) {
|
||||
return null;
|
||||
}
|
||||
const theme = useTheme();
|
||||
const searchParams = new URLSearchParams(location.search);
|
||||
const installationId = parseInt(searchParams.get('installation'));
|
||||
const currentTab = searchParams.get('tab');
|
||||
|
||||
const currentPath = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const [currentTab, setCurrentTab] = useState<string>(undefined);
|
||||
const numOfBatteries = props.values.batteryView.values[0].value
|
||||
.toString()
|
||||
.split(',').length;
|
||||
|
||||
const batteryData = [];
|
||||
let batteryId = 1;
|
||||
|
||||
// Use a for loop to generate battery data
|
||||
for (let index = 1; index <= numOfBatteries * 7; index += 7) {
|
||||
const battery = {
|
||||
|
|
@ -61,155 +71,225 @@ function BatteryView(props: BatteryViewProps) {
|
|||
batteryData.push(battery);
|
||||
}
|
||||
|
||||
const handleMainStatsButton = () => {
|
||||
navigate(routes.mainstats);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
let path = currentPath.pathname.split('/');
|
||||
|
||||
setCurrentTab(path[path.length - 1]);
|
||||
}, [currentPath]);
|
||||
|
||||
return (
|
||||
<TableContainer component={Paper}>
|
||||
<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>
|
||||
{batteryData.map((battery) => (
|
||||
<TableRow
|
||||
key={battery.BatteryId}
|
||||
style={{
|
||||
height: '10px'
|
||||
}}
|
||||
>
|
||||
<TableCell
|
||||
component="th"
|
||||
scope="row"
|
||||
align="center"
|
||||
sx={{ fontWeight: 'bold' }}
|
||||
>
|
||||
{battery.BatteryId}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
<>
|
||||
<Container maxWidth="xl">
|
||||
<Grid container>
|
||||
<Routes>
|
||||
<Route
|
||||
path={routes.mainstats}
|
||||
element={
|
||||
<MainStats s3Credentials={props.s3Credentials}></MainStats>
|
||||
}
|
||||
/>
|
||||
</Routes>
|
||||
{currentTab === 'batteryview' && (
|
||||
<Grid item xs={6} md={6}>
|
||||
<Button
|
||||
variant="contained"
|
||||
sx={{
|
||||
width: '10%',
|
||||
textAlign: 'center'
|
||||
marginTop: '20px',
|
||||
backgroundColor: '#808080',
|
||||
color: '#000000',
|
||||
'&:hover': { bgcolor: '#f7b34d' }
|
||||
}}
|
||||
>
|
||||
{battery.FwVersion}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
sx={{
|
||||
width: '10%',
|
||||
textAlign: 'center'
|
||||
}}
|
||||
>
|
||||
{battery.Power}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
sx={{
|
||||
width: '10%',
|
||||
textAlign: 'center',
|
||||
<FormattedMessage
|
||||
id="main_stats"
|
||||
defaultMessage="Battery View"
|
||||
/>
|
||||
</Button>
|
||||
|
||||
backgroundColor:
|
||||
battery.Voltage < 44 || battery.Voltage > 57
|
||||
? '#FF033E'
|
||||
: '#32CD32',
|
||||
color: battery.Voltage === '' ? 'white' : 'inherit'
|
||||
}}
|
||||
>
|
||||
{battery.Voltage}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={handleMainStatsButton}
|
||||
sx={{
|
||||
width: '10%',
|
||||
textAlign: 'center',
|
||||
backgroundColor:
|
||||
battery.Soc < 20
|
||||
? '#FF033E'
|
||||
: battery.Soc < 50
|
||||
? '#ffbf00 '
|
||||
: '#32CD32',
|
||||
color: battery.Soc === '' ? 'white' : 'inherit'
|
||||
marginTop: '20px',
|
||||
marginLeft: '20px',
|
||||
// backgroundColor: mainStatsData ? '#808080' : '#ffc04d',
|
||||
backgroundColor: '#ffc04d',
|
||||
color: '#000000',
|
||||
'&:hover': { bgcolor: '#f7b34d' }
|
||||
}}
|
||||
>
|
||||
{battery.Soc}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
sx={{
|
||||
width: '10%',
|
||||
textAlign: 'center',
|
||||
backgroundColor:
|
||||
battery.AverageTemperature > 270 ? '#FF033E' : '#32CD32 '
|
||||
}}
|
||||
>
|
||||
{battery.AverageTemperature}
|
||||
</TableCell>
|
||||
<FormattedMessage id="main_stats" defaultMessage="Main Stats" />
|
||||
</Button>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
|
||||
<TableCell
|
||||
style={{
|
||||
width: '20%',
|
||||
textAlign: 'center',
|
||||
padding: '8px',
|
||||
fontWeight: battery.Warnings !== '' ? 'bold' : 'inherit',
|
||||
backgroundColor:
|
||||
battery.Warnings === '' ? 'inherit' : '#ff9900',
|
||||
color: battery.Warnings != '' ? 'black' : 'inherit'
|
||||
}}
|
||||
>
|
||||
{battery.Warnings === '' ? (
|
||||
'None'
|
||||
) : battery.Warnings.split(';').length > 1 ? (
|
||||
<Link
|
||||
style={{ color: 'black' }}
|
||||
to={
|
||||
'?installation=' +
|
||||
installationId +
|
||||
'&tab=log' +
|
||||
'&open=warning'
|
||||
}
|
||||
{currentTab === 'batteryview' && (
|
||||
<TableContainer
|
||||
component={Paper}
|
||||
sx={{ marginTop: '20px', marginBottom: '20px' }}
|
||||
>
|
||||
<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>
|
||||
{batteryData.map((battery) => (
|
||||
<TableRow
|
||||
key={battery.BatteryId}
|
||||
style={{
|
||||
height: '10px'
|
||||
}}
|
||||
>
|
||||
Multiple Warnings
|
||||
</Link>
|
||||
) : (
|
||||
battery.Warnings
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
sx={{
|
||||
width: '20%',
|
||||
textAlign: 'center',
|
||||
fontWeight: battery.Alarms !== '' ? 'bold' : 'inherit',
|
||||
backgroundColor:
|
||||
battery.Alarms === '' ? 'inherit' : '#FF033E',
|
||||
color: battery.Alarms != '' ? 'black' : 'inherit'
|
||||
}}
|
||||
>
|
||||
{battery.Alarms === '' ? (
|
||||
'None'
|
||||
) : battery.Alarms.split(';').length > 1 ? (
|
||||
<Link
|
||||
style={{ color: 'black' }}
|
||||
to={
|
||||
'?installation=' +
|
||||
installationId +
|
||||
'&tab=log' +
|
||||
'&open=error'
|
||||
}
|
||||
>
|
||||
Multiple Alarms
|
||||
</Link>
|
||||
) : (
|
||||
battery.Alarms
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
<TableCell
|
||||
component="th"
|
||||
scope="row"
|
||||
align="center"
|
||||
sx={{ fontWeight: 'bold' }}
|
||||
>
|
||||
{battery.BatteryId}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
sx={{
|
||||
width: '10%',
|
||||
textAlign: 'center'
|
||||
}}
|
||||
>
|
||||
{battery.FwVersion}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
sx={{
|
||||
width: '10%',
|
||||
textAlign: 'center'
|
||||
}}
|
||||
>
|
||||
{battery.Power}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
sx={{
|
||||
width: '10%',
|
||||
textAlign: 'center',
|
||||
|
||||
backgroundColor:
|
||||
battery.Voltage < 44 || battery.Voltage > 57
|
||||
? '#FF033E'
|
||||
: '#32CD32',
|
||||
color: battery.Voltage === '' ? 'white' : 'inherit'
|
||||
}}
|
||||
>
|
||||
{battery.Voltage}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
sx={{
|
||||
width: '10%',
|
||||
textAlign: 'center',
|
||||
backgroundColor:
|
||||
battery.Soc < 20
|
||||
? '#FF033E'
|
||||
: battery.Soc < 50
|
||||
? '#ffbf00 '
|
||||
: '#32CD32',
|
||||
color: battery.Soc === '' ? 'white' : 'inherit'
|
||||
}}
|
||||
>
|
||||
{battery.Soc}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
sx={{
|
||||
width: '10%',
|
||||
textAlign: 'center',
|
||||
backgroundColor:
|
||||
battery.AverageTemperature > 270
|
||||
? '#FF033E'
|
||||
: '#32CD32 '
|
||||
}}
|
||||
>
|
||||
{battery.AverageTemperature}
|
||||
</TableCell>
|
||||
|
||||
<TableCell
|
||||
style={{
|
||||
width: '20%',
|
||||
textAlign: 'center',
|
||||
padding: '8px',
|
||||
fontWeight:
|
||||
battery.Warnings !== '' ? 'bold' : 'inherit',
|
||||
backgroundColor:
|
||||
battery.Warnings === '' ? 'inherit' : '#ff9900',
|
||||
color: battery.Warnings != '' ? 'black' : 'inherit'
|
||||
}}
|
||||
>
|
||||
{battery.Warnings === '' ? (
|
||||
'None'
|
||||
) : battery.Warnings.split(';').length > 1 ? (
|
||||
<Link
|
||||
style={{ color: 'black' }}
|
||||
to={
|
||||
currentPath.pathname.substring(
|
||||
0,
|
||||
currentPath.pathname.lastIndexOf('/') + 1
|
||||
) +
|
||||
routes.log +
|
||||
'?open=warning'
|
||||
}
|
||||
>
|
||||
Multiple Warnings
|
||||
</Link>
|
||||
) : (
|
||||
battery.Warnings
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell
|
||||
sx={{
|
||||
width: '20%',
|
||||
textAlign: 'center',
|
||||
fontWeight: battery.Alarms !== '' ? 'bold' : 'inherit',
|
||||
backgroundColor:
|
||||
battery.Alarms === '' ? 'inherit' : '#FF033E',
|
||||
color: battery.Alarms != '' ? 'black' : 'inherit'
|
||||
}}
|
||||
>
|
||||
{battery.Alarms === '' ? (
|
||||
'None'
|
||||
) : battery.Alarms.split(';').length > 1 ? (
|
||||
<Link
|
||||
style={{ color: 'black' }}
|
||||
to={
|
||||
currentPath.pathname.substring(
|
||||
0,
|
||||
currentPath.pathname.lastIndexOf('/') + 1
|
||||
) +
|
||||
routes.log +
|
||||
'?open=error'
|
||||
}
|
||||
>
|
||||
Multiple Alarms
|
||||
</Link>
|
||||
) : (
|
||||
battery.Alarms
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
)}
|
||||
</Container>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,772 @@
|
|||
import { Box, Card, Container, Grid, Modal, Typography } from '@mui/material';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { I_S3Credentials } from '../../../interfaces/S3Types';
|
||||
import ReactApexChart from 'react-apexcharts';
|
||||
import { getChartOptions } from '../Overview/chartOptions';
|
||||
import {
|
||||
BatteryDataInterface,
|
||||
BatteryOverviewInterface,
|
||||
transformInputToBatteryViewData
|
||||
} from '../../../interfaces/Chart';
|
||||
import 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';
|
||||
|
||||
interface MainStatsProps {
|
||||
s3Credentials: I_S3Credentials;
|
||||
}
|
||||
|
||||
function MainStats(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 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 | ||||