Updated backend to provide support for the overview tab
Updated frontend to parse chunks
This commit is contained in:
parent
7f5ea79d16
commit
5d3b3b4cb2
|
@ -11,8 +11,8 @@ public static class WebsocketManager
|
||||||
{
|
{
|
||||||
public static Dictionary<int, InstallationInfo> InstallationConnections = new Dictionary<int, InstallationInfo>();
|
public static Dictionary<int, InstallationInfo> InstallationConnections = new Dictionary<int, InstallationInfo>();
|
||||||
|
|
||||||
//Every 1 minute, check the timestamp of the latest received message for every installation.
|
//Every 2 minutes, check the timestamp of the latest received message for every installation.
|
||||||
//If the difference between the two timestamps is more than one minute, we consider this installation unavailable.
|
//If the difference between the two timestamps is more than two minutes, we consider this installation unavailable.
|
||||||
public static async Task MonitorInstallationTable()
|
public static async Task MonitorInstallationTable()
|
||||||
{
|
{
|
||||||
while (true){
|
while (true){
|
||||||
|
@ -25,7 +25,7 @@ public static class WebsocketManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await Task.Delay(TimeSpan.FromMinutes(1));
|
await Task.Delay(TimeSpan.FromMinutes(2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ dotnet publish \
|
||||||
echo -e "\n============================ Deploy ============================\n"
|
echo -e "\n============================ Deploy ============================\n"
|
||||||
#ip_addresses=("10.2.3.115" "10.2.3.104" "10.2.4.29" "10.2.4.33" "10.2.4.32" "10.2.4.36" "10.2.4.35" "10.2.4.154" "10.2.4.113" "10.2.4.211")
|
#ip_addresses=("10.2.3.115" "10.2.3.104" "10.2.4.29" "10.2.4.33" "10.2.4.32" "10.2.4.36" "10.2.4.35" "10.2.4.154" "10.2.4.113" "10.2.4.211")
|
||||||
#ip_addresses=("10.2.4.154" "10.2.4.29")
|
#ip_addresses=("10.2.4.154" "10.2.4.29")
|
||||||
ip_addresses=("10.2.3.115" "10.2.3.104" "10.2.4.29" "10.2.4.33" "10.2.4.32" "10.2.4.36" "10.2.4.35")
|
ip_addresses=("10.2.3.115" "10.2.3.104" "10.2.4.29" "10.2.4.33" "10.2.4.32" "10.2.4.36" "10.2.4.35" "10.2.4.154" )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ internal static class Program
|
||||||
private static Boolean _subscribeToQueueForTheFirstTime = false;
|
private static Boolean _subscribeToQueueForTheFirstTime = false;
|
||||||
private static SalimaxAlarmState _prevSalimaxState = SalimaxAlarmState.Green;
|
private static SalimaxAlarmState _prevSalimaxState = SalimaxAlarmState.Green;
|
||||||
//private static Int32 _heartBitInterval = 0;
|
//private static Int32 _heartBitInterval = 0;
|
||||||
private const UInt16 NbrOfFileToConcatenate = 15;
|
private const UInt16 NbrOfFileToConcatenate = 30;
|
||||||
private static UInt16 _counterOfFile = 0;
|
private static UInt16 _counterOfFile = 0;
|
||||||
private static SalimaxAlarmState _salimaxAlarmState = SalimaxAlarmState.Green;
|
private static SalimaxAlarmState _salimaxAlarmState = SalimaxAlarmState.Green;
|
||||||
|
|
||||||
|
|
|
@ -269,7 +269,6 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
|
||||||
<IconButton
|
<IconButton
|
||||||
aria-label="go back"
|
aria-label="go back"
|
||||||
sx={{
|
sx={{
|
||||||
marginTop: props.productNum != 0 ? '20px' : '0px',
|
|
||||||
backgroundColor: 'grey',
|
backgroundColor: 'grey',
|
||||||
color: '#000000',
|
color: '#000000',
|
||||||
'&:hover': { bgcolor: '#f7b34d' }
|
'&:hover': { bgcolor: '#f7b34d' }
|
||||||
|
@ -279,40 +278,36 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
|
||||||
<ArrowBackIcon />
|
<ArrowBackIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
|
||||||
{props.productNum === 0 && (
|
<Select
|
||||||
<>
|
value={selectedVersion}
|
||||||
<Select
|
onChange={(event) => setSelectedVersion(event.target.value)}
|
||||||
value={selectedVersion}
|
displayEmpty
|
||||||
onChange={(event) => setSelectedVersion(event.target.value)}
|
variant="outlined"
|
||||||
displayEmpty
|
sx={{
|
||||||
variant="outlined"
|
marginTop: '30px',
|
||||||
sx={{
|
marginLeft: '20px',
|
||||||
marginTop: '30px',
|
height: '40px'
|
||||||
marginLeft: '20px',
|
}}
|
||||||
height: '40px'
|
>
|
||||||
}}
|
<MenuItem disabled value="">
|
||||||
>
|
Select Firmware Version
|
||||||
<MenuItem disabled value="">
|
</MenuItem>
|
||||||
Select Firmware Version
|
<MenuItem value="AF11">AF11</MenuItem>
|
||||||
</MenuItem>
|
<MenuItem value="AF0A">AF0A</MenuItem>
|
||||||
<MenuItem value="AF11">AF11</MenuItem>
|
</Select>
|
||||||
<MenuItem value="AF0A">AF0A</MenuItem>
|
<Button
|
||||||
</Select>
|
variant="contained"
|
||||||
<Button
|
onClick={handleUpdateFirmware}
|
||||||
variant="contained"
|
disabled={!selectedVersion} // Disable button if no version selected
|
||||||
onClick={handleUpdateFirmware}
|
sx={{
|
||||||
disabled={!selectedVersion} // Disable button if no version selected
|
marginLeft: '20px',
|
||||||
sx={{
|
backgroundColor: '#ffc04d',
|
||||||
marginLeft: '20px',
|
color: '#000000',
|
||||||
backgroundColor: '#ffc04d',
|
'&:hover': { bgcolor: '#f7b34d' }
|
||||||
color: '#000000',
|
}}
|
||||||
'&:hover': { bgcolor: '#f7b34d' }
|
>
|
||||||
}}
|
Update Firmware
|
||||||
>
|
</Button>
|
||||||
Update Firmware
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid container>
|
<Grid container>
|
||||||
|
|
|
@ -361,7 +361,7 @@ function InformationSalidomo(props: InformationSalidomoProps) {
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<TextField
|
<TextField
|
||||||
label="S3 Write Key"
|
label="S3 Write Secret Key"
|
||||||
name="s3writesecretkey"
|
name="s3writesecretkey"
|
||||||
value={formValues.s3WriteSecret}
|
value={formValues.s3WriteSecret}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
|
|
|
@ -72,7 +72,7 @@ function Installation(props: singleInstallationProps) {
|
||||||
const continueFetching = useRef(false);
|
const continueFetching = useRef(false);
|
||||||
|
|
||||||
const fetchDataForOneTime = async () => {
|
const fetchDataForOneTime = async () => {
|
||||||
var timeperiodToSearch = 80;
|
var timeperiodToSearch = 70;
|
||||||
let res;
|
let res;
|
||||||
let timestampToFetch;
|
let timestampToFetch;
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ function Installation(props: singleInstallationProps) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchDataPeriodically = async () => {
|
const fetchDataPeriodically = async () => {
|
||||||
var timeperiodToSearch = 80;
|
var timeperiodToSearch = 70;
|
||||||
let res;
|
let res;
|
||||||
let timestampToFetch;
|
let timestampToFetch;
|
||||||
|
|
||||||
|
@ -133,6 +133,7 @@ function Installation(props: singleInstallationProps) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
setConnected(true);
|
setConnected(true);
|
||||||
|
console.log('NUMBER OF FILES=' + Object.keys(res).length);
|
||||||
|
|
||||||
while (continueFetching.current) {
|
while (continueFetching.current) {
|
||||||
for (const timestamp of Object.keys(res)) {
|
for (const timestamp of Object.keys(res)) {
|
||||||
|
@ -154,7 +155,7 @@ function Installation(props: singleInstallationProps) {
|
||||||
await timeout(2000);
|
await timeout(2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
timestampToFetch = timestampToFetch.later(TimeSpan.fromSeconds(30));
|
timestampToFetch = timestampToFetch.later(TimeSpan.fromSeconds(60));
|
||||||
console.log('NEW TIMESTAMP TO FETCH IS ' + timestampToFetch);
|
console.log('NEW TIMESTAMP TO FETCH IS ' + timestampToFetch);
|
||||||
|
|
||||||
for (i = 0; i < 10; i++) {
|
for (i = 0; i < 10; i++) {
|
||||||
|
|
|
@ -0,0 +1,574 @@
|
||||||
|
import { Box, Card, Container, Grid, Modal, Typography } from '@mui/material';
|
||||||
|
import ReactApexChart from 'react-apexcharts';
|
||||||
|
import React, { useContext, useEffect, useState } from 'react';
|
||||||
|
import { I_S3Credentials } from 'src/interfaces/S3Types';
|
||||||
|
import { getChartOptions } from './chartOptions';
|
||||||
|
import {
|
||||||
|
chartAggregatedDataInterface,
|
||||||
|
overviewInterface,
|
||||||
|
transformInputToAggregatedData
|
||||||
|
} from 'src/interfaces/Chart';
|
||||||
|
import Button from '@mui/material/Button';
|
||||||
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
import CircularProgress from '@mui/material/CircularProgress';
|
||||||
|
import { DateTimePicker, LocalizationProvider } from '@mui/x-date-pickers';
|
||||||
|
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import { UserContext } from '../../../contexts/userContext';
|
||||||
|
import { UserType } from '../../../interfaces/UserTypes';
|
||||||
|
|
||||||
|
interface salidomoOverviewProps {
|
||||||
|
s3Credentials: I_S3Credentials;
|
||||||
|
id: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const computeLast7Days = (): string[] => {
|
||||||
|
const currentDate = new Date();
|
||||||
|
const daysOfWeek = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
||||||
|
let currentDayIndex = currentDate.getDay();
|
||||||
|
const last7Days = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < 7; i++) {
|
||||||
|
last7Days.push(daysOfWeek[currentDayIndex]);
|
||||||
|
currentDayIndex++;
|
||||||
|
if (currentDayIndex > 6) {
|
||||||
|
currentDayIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return last7Days;
|
||||||
|
};
|
||||||
|
|
||||||
|
function SalidomoOverview(props: salidomoOverviewProps) {
|
||||||
|
const context = useContext(UserContext);
|
||||||
|
const { currentUser } = context;
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [aggregatedChartState, setAggregatedChartState] = useState(0);
|
||||||
|
const [isDateModalOpen, setIsDateModalOpen] = useState(false);
|
||||||
|
const [isErrorDateModalOpen, setErrorDateModalOpen] = useState(false);
|
||||||
|
const [dateSelectionError, setDateSelectionError] = useState('');
|
||||||
|
const [dateOpen, setDateOpen] = useState(false);
|
||||||
|
|
||||||
|
const [aggregatedDataArray, setAggregatedDataArray] = useState<
|
||||||
|
{
|
||||||
|
chartData: chartAggregatedDataInterface;
|
||||||
|
chartOverview: overviewInterface;
|
||||||
|
datelist: any[];
|
||||||
|
netbalance: any[];
|
||||||
|
}[]
|
||||||
|
>([]);
|
||||||
|
|
||||||
|
const [startDate, setStartDate] = useState(dayjs().add(-1, 'day'));
|
||||||
|
const [endDate, setEndDate] = useState(dayjs());
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
handleWeekData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleWeekData = () => {
|
||||||
|
setAggregatedChartState(0);
|
||||||
|
|
||||||
|
if (
|
||||||
|
aggregatedDataArray[aggregatedChartState] &&
|
||||||
|
aggregatedDataArray[aggregatedChartState].chartData != null
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
|
const resultPromise: Promise<{
|
||||||
|
chartAggregatedData: chartAggregatedDataInterface;
|
||||||
|
chartOverview: overviewInterface;
|
||||||
|
}> = transformInputToAggregatedData(
|
||||||
|
props.s3Credentials,
|
||||||
|
dayjs().subtract(1, 'week'),
|
||||||
|
dayjs()
|
||||||
|
);
|
||||||
|
|
||||||
|
resultPromise
|
||||||
|
.then((result) => {
|
||||||
|
const powerDifference = [];
|
||||||
|
for (
|
||||||
|
let i = 0;
|
||||||
|
i < result.chartAggregatedData.gridImportPower.data.length;
|
||||||
|
i++
|
||||||
|
) {
|
||||||
|
powerDifference.push(
|
||||||
|
result.chartAggregatedData.gridImportPower.data[i] -
|
||||||
|
Math.abs(result.chartAggregatedData.gridExportPower.data[i])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
setAggregatedDataArray((prevData) =>
|
||||||
|
prevData.concat({
|
||||||
|
chartData: result.chartAggregatedData,
|
||||||
|
chartOverview: result.chartOverview,
|
||||||
|
datelist: computeLast7Days(),
|
||||||
|
netbalance: powerDifference
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
setAggregatedChartState(aggregatedDataArray.length);
|
||||||
|
setLoading(false);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSetDate = () => {
|
||||||
|
setDateOpen(true);
|
||||||
|
setIsDateModalOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOkOnErrorDateModal = () => {
|
||||||
|
setErrorDateModalOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
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<{
|
||||||
|
chartAggregatedData: chartAggregatedDataInterface;
|
||||||
|
chartOverview: overviewInterface;
|
||||||
|
dateList: string[];
|
||||||
|
}> = transformInputToAggregatedData(
|
||||||
|
props.s3Credentials,
|
||||||
|
startDate,
|
||||||
|
endDate
|
||||||
|
);
|
||||||
|
|
||||||
|
resultPromise
|
||||||
|
.then((result) => {
|
||||||
|
const powerDifference = [];
|
||||||
|
|
||||||
|
for (
|
||||||
|
let i = 0;
|
||||||
|
i < result.chartAggregatedData.gridImportPower.data.length;
|
||||||
|
i++
|
||||||
|
) {
|
||||||
|
powerDifference.push(
|
||||||
|
result.chartAggregatedData.gridImportPower.data[i] -
|
||||||
|
Math.abs(result.chartAggregatedData.gridExportPower.data[i])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
setAggregatedDataArray((prevData) =>
|
||||||
|
prevData.concat({
|
||||||
|
chartData: result.chartAggregatedData,
|
||||||
|
chartOverview: result.chartOverview,
|
||||||
|
datelist: result.dateList,
|
||||||
|
netbalance: powerDifference
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
setAggregatedChartState(aggregatedDataArray.length);
|
||||||
|
setLoading(false);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleGoBack = () => {
|
||||||
|
if (aggregatedChartState > 0) {
|
||||||
|
setAggregatedChartState(aggregatedChartState - 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleGoForward = () => {
|
||||||
|
if (aggregatedChartState + 1 < aggregatedDataArray.length) {
|
||||||
|
setAggregatedChartState(aggregatedChartState + 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderGraphs = () => {
|
||||||
|
return (
|
||||||
|
<Container maxWidth="xl">
|
||||||
|
{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) => setStartDate(newDate)}
|
||||||
|
sx={{
|
||||||
|
marginTop: 2
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<DateTimePicker
|
||||||
|
label="Select End Date"
|
||||||
|
value={endDate}
|
||||||
|
onChange={(newDate) => setEndDate(newDate)}
|
||||||
|
sx={{
|
||||||
|
marginTop: 2
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<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>
|
||||||
|
)}
|
||||||
|
<Grid container>
|
||||||
|
<Grid item xs={6} md={6}>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
onClick={handleSetDate}
|
||||||
|
disabled={loading}
|
||||||
|
sx={{
|
||||||
|
marginTop: '20px',
|
||||||
|
marginLeft: '10px',
|
||||||
|
backgroundColor: dateOpen ? '#808080' : '#ffc04d',
|
||||||
|
color: '#000000',
|
||||||
|
'&:hover': { bgcolor: '#f7b34d' }
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FormattedMessage id="lastmonth" defaultMessage="Set Date" />
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid
|
||||||
|
container
|
||||||
|
justifyContent="flex-end"
|
||||||
|
alignItems="center"
|
||||||
|
item
|
||||||
|
xs={6}
|
||||||
|
md={6}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
disabled={!(aggregatedChartState > 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={
|
||||||
|
!(aggregatedChartState < aggregatedDataArray.length - 1)
|
||||||
|
}
|
||||||
|
onClick={handleGoForward}
|
||||||
|
sx={{
|
||||||
|
marginTop: '20px',
|
||||||
|
marginLeft: '10px',
|
||||||
|
backgroundColor: '#ffc04d',
|
||||||
|
color: '#000000',
|
||||||
|
'&:hover': { bgcolor: '#f7b34d' }
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FormattedMessage id="goback" defaultMessage="Zoom in" />
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{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>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!loading && (
|
||||||
|
<Grid item xs={12} md={12}>
|
||||||
|
<Grid
|
||||||
|
container
|
||||||
|
direction="row"
|
||||||
|
justifyContent="center"
|
||||||
|
alignItems="stretch"
|
||||||
|
spacing={3}
|
||||||
|
>
|
||||||
|
<Grid item md={6} 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(
|
||||||
|
aggregatedDataArray[aggregatedChartState]
|
||||||
|
.chartOverview.soc,
|
||||||
|
'weekly',
|
||||||
|
aggregatedDataArray[aggregatedChartState].datelist,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
series={[
|
||||||
|
{
|
||||||
|
...aggregatedDataArray[aggregatedChartState].chartData
|
||||||
|
.minsoc,
|
||||||
|
color: '#69d2e7'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...aggregatedDataArray[aggregatedChartState].chartData
|
||||||
|
.maxsoc,
|
||||||
|
color: '#008FFB'
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
type="bar"
|
||||||
|
height={400}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</Grid>
|
||||||
|
<Grid item md={6} 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_power"
|
||||||
|
defaultMessage={'Battery Energy'}
|
||||||
|
/>
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'flex-start',
|
||||||
|
pt: 3
|
||||||
|
}}
|
||||||
|
></Box>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{currentUser.userType == UserType.admin && (
|
||||||
|
<ReactApexChart
|
||||||
|
options={{
|
||||||
|
...getChartOptions(
|
||||||
|
aggregatedDataArray[aggregatedChartState]
|
||||||
|
.chartOverview.dcPower,
|
||||||
|
'weekly',
|
||||||
|
aggregatedDataArray[aggregatedChartState].datelist,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
series={[
|
||||||
|
{
|
||||||
|
...aggregatedDataArray[aggregatedChartState]
|
||||||
|
.chartData.dcChargingPower,
|
||||||
|
color: '#008FFB'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...aggregatedDataArray[aggregatedChartState]
|
||||||
|
.chartData.heatingPower,
|
||||||
|
color: '#ff9900'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...aggregatedDataArray[aggregatedChartState]
|
||||||
|
.chartData.dcDischargingPower,
|
||||||
|
color: '#69d2e7'
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
type="bar"
|
||||||
|
height={400}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{currentUser.userType == UserType.client && (
|
||||||
|
<ReactApexChart
|
||||||
|
options={{
|
||||||
|
...getChartOptions(
|
||||||
|
aggregatedDataArray[aggregatedChartState]
|
||||||
|
.chartOverview.dcPowerWithoutHeating,
|
||||||
|
'weekly',
|
||||||
|
aggregatedDataArray[aggregatedChartState].datelist,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
series={[
|
||||||
|
{
|
||||||
|
...aggregatedDataArray[aggregatedChartState]
|
||||||
|
.chartData.dcChargingPower,
|
||||||
|
color: '#008FFB'
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
...aggregatedDataArray[aggregatedChartState]
|
||||||
|
.chartData.dcDischargingPower,
|
||||||
|
color: '#69d2e7'
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
type="bar"
|
||||||
|
height={400}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Card>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return <>{renderGraphs()}</>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SalidomoOverview;
|
|
@ -17,6 +17,7 @@ import InformationSalidomo from '../Information/InformationSalidomo';
|
||||||
import BatteryView from '../BatteryView/BatteryView';
|
import BatteryView from '../BatteryView/BatteryView';
|
||||||
import Log from '../Log/Log';
|
import Log from '../Log/Log';
|
||||||
import CancelIcon from '@mui/icons-material/Cancel';
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
|
import SalidomoOverview from '../Overview/salidomoOverview';
|
||||||
|
|
||||||
interface singleInstallationProps {
|
interface singleInstallationProps {
|
||||||
current_installation?: I_Installation;
|
current_installation?: I_Installation;
|
||||||
|
@ -66,7 +67,7 @@ function Installation(props: singleInstallationProps) {
|
||||||
const continueFetching = useRef(false);
|
const continueFetching = useRef(false);
|
||||||
|
|
||||||
const fetchDataPeriodically = async () => {
|
const fetchDataPeriodically = async () => {
|
||||||
var timeperiodToSearch = 80;
|
var timeperiodToSearch = 70;
|
||||||
let res;
|
let res;
|
||||||
let timestampToFetch;
|
let timestampToFetch;
|
||||||
|
|
||||||
|
@ -113,7 +114,7 @@ function Installation(props: singleInstallationProps) {
|
||||||
await timeout(2000);
|
await timeout(2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
timestampToFetch = timestampToFetch.later(TimeSpan.fromSeconds(30));
|
timestampToFetch = timestampToFetch.later(TimeSpan.fromSeconds(60));
|
||||||
console.log('NEW TIMESTAMP TO FETCH IS ' + timestampToFetch);
|
console.log('NEW TIMESTAMP TO FETCH IS ' + timestampToFetch);
|
||||||
|
|
||||||
for (i = 0; i < 10; i++) {
|
for (i = 0; i < 10; i++) {
|
||||||
|
@ -296,6 +297,16 @@ function Installation(props: singleInstallationProps) {
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Route
|
||||||
|
path={routes.overview}
|
||||||
|
element={
|
||||||
|
<SalidomoOverview
|
||||||
|
s3Credentials={s3Credentials}
|
||||||
|
id={props.current_installation.id}
|
||||||
|
></SalidomoOverview>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path={routes.batteryview + '*'}
|
path={routes.batteryview + '*'}
|
||||||
element={
|
element={
|
||||||
|
|
|
@ -92,6 +92,10 @@ function SalidomoInstallationTabs() {
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
value: 'overview',
|
||||||
|
label: <FormattedMessage id="overview" defaultMessage="Overview" />
|
||||||
|
},
|
||||||
{
|
{
|
||||||
value: 'log',
|
value: 'log',
|
||||||
label: <FormattedMessage id="log" defaultMessage="Log" />
|
label: <FormattedMessage id="log" defaultMessage="Log" />
|
||||||
|
|
|
@ -403,7 +403,6 @@ export const transformInputToDailyData = async (
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//while (startUnixTime < endTimestamp) {
|
|
||||||
for (var i = 0; i < timestampArray.length; i++) {
|
for (var i = 0; i < timestampArray.length; i++) {
|
||||||
timestampPromises.push(
|
timestampPromises.push(
|
||||||
fetchDataForOneTime(
|
fetchDataForOneTime(
|
||||||
|
|
Loading…
Reference in New Issue