Merge remote-tracking branch 'origin/main'

This commit is contained in:
atef 2024-05-21 11:19:26 +02:00
commit bde392e35d
10 changed files with 443 additions and 425 deletions

View File

@ -57,9 +57,9 @@ public static class RabbitMqManager
if (receivedStatusMessage != null) if (receivedStatusMessage != null)
{ {
Console.WriteLine("----------------------------------------------"); Console.WriteLine("----------------------------------------------");
Console.WriteLine("Received a message from installation: " + receivedStatusMessage.InstallationId + " and status is: " + receivedStatusMessage.Status);
int installationId = (int)Db.Installations.Where(f => f.Product == 0 && f.S3BucketId == receivedStatusMessage.InstallationId).Select(f => f.Id).FirstOrDefault();
int installationId = (int)Db.Installations.Where(f => f.Product == receivedStatusMessage.Product && f.S3BucketId == receivedStatusMessage.InstallationId).Select(f => f.Id).FirstOrDefault();
Console.WriteLine("Received a message from installation: " + installationId + " , product is: "+receivedStatusMessage.Product+ " and status is: " + receivedStatusMessage.Status);
//This is a heartbit message, just update the timestamp for this installation. //This is a heartbit message, just update the timestamp for this installation.
//There is no need to notify the corresponding front-ends. //There is no need to notify the corresponding front-ends.
@ -77,7 +77,7 @@ public static class RabbitMqManager
{ {
Warning newWarning = new Warning Warning newWarning = new Warning
{ {
InstallationId = receivedStatusMessage.InstallationId, InstallationId = installationId,
Description = warning.Description, Description = warning.Description,
Date = warning.Date, Date = warning.Date,
Time = warning.Time, Time = warning.Time,
@ -85,7 +85,7 @@ public static class RabbitMqManager
Seen = false Seen = false
}; };
//Create a new warning and add it to the database //Create a new warning and add it to the database
Db.HandleWarning(newWarning, receivedStatusMessage.InstallationId); Db.HandleWarning(newWarning, installationId);
} }
} }
@ -93,12 +93,12 @@ public static class RabbitMqManager
//Traverse the Alarm list, and store each of them to the database //Traverse the Alarm list, and store each of them to the database
if (receivedStatusMessage.Alarms != null) if (receivedStatusMessage.Alarms != null)
{ {
Console.WriteLine("Add an alarm for installation "+receivedStatusMessage.InstallationId); Console.WriteLine("Add an alarm for installation "+installationId);
foreach (var alarm in receivedStatusMessage.Alarms) foreach (var alarm in receivedStatusMessage.Alarms)
{ {
Error newError = new Error Error newError = new Error
{ {
InstallationId = receivedStatusMessage.InstallationId, InstallationId = installationId,
Description = alarm.Description, Description = alarm.Description,
Date = alarm.Date, Date = alarm.Date,
Time = alarm.Time, Time = alarm.Time,
@ -106,7 +106,7 @@ public static class RabbitMqManager
Seen = false Seen = false
}; };
//Create a new error and add it to the database //Create a new error and add it to the database
Db.HandleError(newError, receivedStatusMessage.InstallationId); Db.HandleError(newError, installationId);
} }
} }
} }

View File

@ -16,7 +16,11 @@ dotnet publish \
-r linux-x64 -r linux-x64
echo -e "\n============================ Deploy ============================\n" echo -e "\n============================ Deploy ============================\n"
ip_addresses=("10.2.3.115" "10.2.3.104" "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.29") #ip_addresses=("10.2.3.115" "10.2.3.104" "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.29")
#ip_addresses=("10.2.4.154" "10.2.4.29")
ip_addresses=("10.2.3.115" "10.2.3.104" "10.2.4.33" "10.2.4.32" "10.2.4.36" "10.2.4.35" "10.2.4.154" "10.2.4.29")
for ip_address in "${ip_addresses[@]}"; do for ip_address in "${ip_addresses[@]}"; do
rsync -v \ rsync -v \

View File

@ -1,3 +1,5 @@
using System.IO.Compression;
using System.Text;
using System.Text.Json; using System.Text.Json;
using Flurl.Http; using Flurl.Http;
using InnovEnergy.App.SaliMax.Devices; using InnovEnergy.App.SaliMax.Devices;
@ -68,7 +70,37 @@ public class AggregatedData
var s3Path = DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd") + ".csv"; var s3Path = DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd") + ".csv";
var request = _S3Config.CreatePutRequest(s3Path); var request = _S3Config.CreatePutRequest(s3Path);
var response = await request.PutAsync(new StringContent(csv));
// Compress CSV data to a byte array
byte[] compressedBytes;
using (var memoryStream = new MemoryStream())
{
//Create a zip directory and put the compressed file inside
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
var entry = archive.CreateEntry("data.csv", CompressionLevel.SmallestSize); // Add CSV data to the ZIP archive
using (var entryStream = entry.Open())
using (var writer = new StreamWriter(entryStream))
{
writer.Write(csv);
}
}
compressedBytes = memoryStream.ToArray();
}
// Encode the compressed byte array as a Base64 string
string base64String = Convert.ToBase64String(compressedBytes);
// Create StringContent from Base64 string
var stringContent = new StringContent(base64String, Encoding.UTF8, "application/base64");
// Upload the compressed data (ZIP archive) to S3
var response = await request.PutAsync(stringContent);
//
// var request = _S3Config.CreatePutRequest(s3Path);
// var response = await request.PutAsync(new StringContent(csv));
if (response.StatusCode != 200) if (response.StatusCode != 200)
{ {

View File

@ -1,4 +1,4 @@
#define Amax #undef Amax
#undef GridLimit #undef GridLimit
using System.IO.Compression; using System.IO.Compression;
@ -486,6 +486,7 @@ internal static class Program
var returnedStatus = new StatusMessage var returnedStatus = new StatusMessage
{ {
InstallationId = installationId, InstallationId = installationId,
Product = 0,
Status = salimaxAlarmsState, Status = salimaxAlarmsState,
Type = MessageType.AlarmOrWarning, Type = MessageType.AlarmOrWarning,
Alarms = alarmList, Alarms = alarmList,

View File

@ -31,6 +31,21 @@ const FlatInstallationView = (props: FlatInstallationViewProps) => {
const [selectedInstallation, setSelectedInstallation] = useState<number>(-1); const [selectedInstallation, setSelectedInstallation] = useState<number>(-1);
const currentLocation = useLocation(); const currentLocation = useLocation();
const sortedInstallations = [...props.installations].sort((a, b) => {
// Compare the status field of each installation and sort them based on the status.
//Installations with alarms go first
let a_status = getStatus(a.id);
let b_status = getStatus(b.id);
if (a_status > b_status) {
return -1;
}
if (a_status < b_status) {
return 1;
}
return 0;
});
const handleSelectOneInstallation = (installationID: number): void => { const handleSelectOneInstallation = (installationID: number): void => {
if (selectedInstallation != installationID) { if (selectedInstallation != installationID) {
setSelectedInstallation(installationID); setSelectedInstallation(installationID);
@ -100,7 +115,7 @@ const FlatInstallationView = (props: FlatInstallationViewProps) => {
</TableRow> </TableRow>
</TableHead> </TableHead>
<TableBody> <TableBody>
{props.installations.map((installation) => { {sortedInstallations.map((installation) => {
const isInstallationSelected = const isInstallationSelected =
installation.s3BucketId === selectedInstallation; installation.s3BucketId === selectedInstallation;

View File

@ -25,9 +25,29 @@ export const fetchDailyData = (
if (r.status === 404) { if (r.status === 404) {
return Promise.resolve(FetchResult.notAvailable); return Promise.resolve(FetchResult.notAvailable);
} else if (r.status === 200) { } else if (r.status === 200) {
const text = await r.text(); // const text = await r.text();
const csvtext = await r.text(); // Assuming the server returns the Base64 encoded ZIP file as text
//const response = await fetch(url); // Fetch the resource from the server
const contentEncoding = r.headers.get('content-type');
if (contentEncoding != 'application/base64; charset=utf-8') {
return parseCsv(csvtext);
}
const byteArray = Uint8Array.from(atob(csvtext), (c) =>
c.charCodeAt(0)
);
//Decompress the byte array using JSZip
const zip = await JSZip.loadAsync(byteArray);
// Assuming the CSV file is named "data.csv" inside the ZIP archive
const csvContent = await zip.file('data.csv').async('text');
return parseCsv(csvContent);
//console.log(parseCsv(text)); //console.log(parseCsv(text));
return parseCsv(text); //return parseCsv(text);
} else { } else {
return Promise.resolve(FetchResult.notAvailable); return Promise.resolve(FetchResult.notAvailable);
} }
@ -58,15 +78,24 @@ export const fetchData = (
if (r.status === 404) { if (r.status === 404) {
return Promise.resolve(FetchResult.notAvailable); return Promise.resolve(FetchResult.notAvailable);
} else if (r.status === 200) { } else if (r.status === 200) {
const base64String = await r.text(); // Assuming the server returns the Base64 encoded ZIP file as text const csvtext = await r.text(); // Assuming the server returns the Base64 encoded ZIP file as text
const byteArray = Uint8Array.from(atob(base64String), (c) =>
//const response = await fetch(url); // Fetch the resource from the server
const contentEncoding = r.headers.get('content-type');
if (contentEncoding != 'application/base64; charset=utf-8') {
return parseCsv(csvtext);
}
const byteArray = Uint8Array.from(atob(csvtext), (c) =>
c.charCodeAt(0) c.charCodeAt(0)
); );
// Decompress the byte array using JSZip //Decompress the byte array using JSZip
const zip = await JSZip.loadAsync(byteArray); const zip = await JSZip.loadAsync(byteArray);
// Assuming the CSV file is named "data.csv" inside the ZIP archive // Assuming the CSV file is named "data.csv" inside the ZIP archive
const csvContent = await zip.file('data.csv').async('text'); const csvContent = await zip.file('data.csv').async('text');
return parseCsv(csvContent); return parseCsv(csvContent);
} else { } else {
return Promise.resolve(FetchResult.notAvailable); return Promise.resolve(FetchResult.notAvailable);

View File

@ -135,6 +135,33 @@ function InstallationTabs() {
) )
} }
] ]
: currentUser.userType == UserType.partner
? [
{
value: 'live',
label: <FormattedMessage id="live" defaultMessage="Live" />
},
{
value: 'overview',
label: <FormattedMessage id="overview" defaultMessage="Overview" />
},
{
value: 'batteryview',
label: (
<FormattedMessage
id="batteryview"
defaultMessage="Battery View"
/>
)
},
{
value: 'information',
label: (
<FormattedMessage id="information" defaultMessage="Information" />
)
}
]
: [ : [
{ {
value: 'live', value: 'live',
@ -219,7 +246,8 @@ function InstallationTabs() {
) )
} }
] ]
: [ : currentUser.userType == UserType.partner
? [
{ {
value: 'list', value: 'list',
icon: <ListIcon id="mode-toggle-button-list-icon" /> icon: <ListIcon id="mode-toggle-button-list-icon" />
@ -260,6 +288,37 @@ function InstallationTabs() {
} }
] ]
: [ : [
{
value: 'list',
icon: <ListIcon id="mode-toggle-button-list-icon" />
},
{
value: 'tree',
icon: <AccountTreeIcon id="mode-toggle-button-tree-icon" />
},
{
value: 'live',
label: <FormattedMessage id="live" defaultMessage="Live" />
},
{
value: 'overview',
label: (
<FormattedMessage id="overview" defaultMessage="Overview" />
)
},
{
value: 'information',
label: (
<FormattedMessage
id="information"
defaultMessage="Information"
/>
)
}
]
: [
{ {
value: 'list', value: 'list',
icon: <ListIcon id="mode-toggle-button-list-icon" /> icon: <ListIcon id="mode-toggle-button-list-icon" />

View File

@ -45,14 +45,10 @@ function Overview(props: OverviewProps) {
const { currentUser } = context; const { currentUser } = context;
const [dailyData, setDailyData] = useState(true); const [dailyData, setDailyData] = useState(true);
const [weeklyData, setWeeklyData] = useState(false); const [aggregatedData, setAggregatedData] = useState(false);
const [weeklybalance, setWeeklyBalance] = useState([]);
const [monthlybalance, setMonthlyBalance] = useState([]);
const [monthlyData, setMonthlyData] = useState(false);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [chartState, setChartState] = useState(0); const [chartState, setChartState] = useState(0);
const [monthlyDateList, setMonthlyDateList] = useState([]); const [aggregatedChartState, setAggregatedChartState] = useState(0);
const [weeklyDateList, setWeeklyDateList] = useState([]);
const [isDateModalOpen, setIsDateModalOpen] = useState(false); const [isDateModalOpen, setIsDateModalOpen] = useState(false);
const [isErrorDateModalOpen, setErrorDateModalOpen] = useState(false); const [isErrorDateModalOpen, setErrorDateModalOpen] = useState(false);
const [dateSelectionError, setDateSelectionError] = useState(''); const [dateSelectionError, setDateSelectionError] = useState('');
@ -64,19 +60,18 @@ function Overview(props: OverviewProps) {
}[] }[]
>([]); >([]);
const [aggregatedDataArray, setAggregatedDataArray] = useState<
{
chartData: chartAggregatedDataInterface;
chartOverview: overviewInterface;
datelist: any[];
netbalance: any[];
}[]
>([]);
const [startDate, setStartDate] = useState(dayjs().add(-1, 'day')); const [startDate, setStartDate] = useState(dayjs().add(-1, 'day'));
const [endDate, setEndDate] = useState(dayjs()); const [endDate, setEndDate] = useState(dayjs());
const [weeklyDataArray, setWeeklyDataArray] = useState<{
chartData: chartAggregatedDataInterface;
chartOverview: overviewInterface;
}>({ chartData: null, chartOverview: null });
const [monthlyDataArray, setMonthlyDataArray] = useState<{
chartData: chartAggregatedDataInterface;
chartOverview: overviewInterface;
}>({ chartData: null, chartOverview: null });
useEffect(() => { useEffect(() => {
const resultPromise: Promise<{ const resultPromise: Promise<{
chartData: chartDataInterface; chartData: chartDataInterface;
@ -135,17 +130,19 @@ function Overview(props: OverviewProps) {
const handle24HourData = () => { const handle24HourData = () => {
setDailyData(true); setDailyData(true);
setWeeklyData(false); setAggregatedData(false);
setMonthlyData(false);
setChartState(0); setChartState(0);
}; };
const handleWeekData = () => { const handleWeekData = () => {
setDailyData(false); setDailyData(false);
setWeeklyData(true); setAggregatedData(true);
setMonthlyData(false); setAggregatedChartState(0);
if (weeklyDataArray.chartData != null) { if (
aggregatedDataArray[aggregatedChartState] &&
aggregatedDataArray[aggregatedChartState].chartData != null
) {
return; return;
} }
setLoading(true); setLoading(true);
@ -153,15 +150,15 @@ function Overview(props: OverviewProps) {
const resultPromise: Promise<{ const resultPromise: Promise<{
chartAggregatedData: chartAggregatedDataInterface; chartAggregatedData: chartAggregatedDataInterface;
chartOverview: overviewInterface; chartOverview: overviewInterface;
}> = transformInputToAggregatedData(props.s3Credentials, 'weekly'); }> = transformInputToAggregatedData(
props.s3Credentials,
dayjs().subtract(1, 'week'),
dayjs()
);
resultPromise resultPromise
.then((result) => { .then((result) => {
setWeeklyDataArray({
chartData: result.chartAggregatedData,
chartOverview: result.chartOverview
});
const powerDifference = []; const powerDifference = [];
for ( for (
let i = 0; let i = 0;
@ -174,8 +171,16 @@ function Overview(props: OverviewProps) {
); );
} }
setWeeklyBalance(powerDifference); setAggregatedDataArray((prevData) =>
setWeeklyDateList(computeLast7Days()); prevData.concat({
chartData: result.chartAggregatedData,
chartOverview: result.chartOverview,
datelist: computeLast7Days(),
netbalance: powerDifference
})
);
setAggregatedChartState(aggregatedDataArray.length);
setLoading(false); setLoading(false);
}) })
.catch((error) => { .catch((error) => {
@ -212,6 +217,8 @@ function Overview(props: OverviewProps) {
} }
setLoading(true); setLoading(true);
if (dailyData) {
const resultPromise: Promise<{ const resultPromise: Promise<{
chartData: chartDataInterface; chartData: chartDataInterface;
chartOverview: overviewInterface; chartOverview: overviewInterface;
@ -236,43 +243,24 @@ function Overview(props: OverviewProps) {
.catch((error) => { .catch((error) => {
console.error('Error:', error); console.error('Error:', error);
}); });
}; } else {
const handleGoBack = () => {
if (chartState > 0) {
setChartState(chartState - 1);
}
};
const handleGoForward = () => {
if (chartState + 1 < dailyDataArray.length) {
setChartState(chartState + 1);
}
};
const handleMonthData = () => {
setDailyData(false); setDailyData(false);
setWeeklyData(false); setAggregatedData(true);
setMonthlyData(true);
if (monthlyDataArray.chartData != null) {
return;
}
setLoading(true); setLoading(true);
const resultPromise: Promise<{ const resultPromise: Promise<{
chartAggregatedData: chartAggregatedDataInterface; chartAggregatedData: chartAggregatedDataInterface;
chartOverview: overviewInterface; chartOverview: overviewInterface;
dateList: string[]; dateList: string[];
}> = transformInputToAggregatedData(props.s3Credentials, 'monthly'); }> = transformInputToAggregatedData(
props.s3Credentials,
startDate,
endDate
);
resultPromise resultPromise
.then((result) => { .then((result) => {
setMonthlyDataArray({
chartData: result.chartAggregatedData,
chartOverview: result.chartOverview
});
const powerDifference = []; const powerDifference = [];
for ( for (
@ -286,14 +274,43 @@ function Overview(props: OverviewProps) {
); );
} }
setMonthlyBalance(powerDifference); setAggregatedDataArray((prevData) =>
prevData.concat({
chartData: result.chartAggregatedData,
chartOverview: result.chartOverview,
datelist: result.dateList,
netbalance: powerDifference
})
);
setMonthlyDateList(result.dateList); setAggregatedChartState(aggregatedDataArray.length);
setLoading(false); setLoading(false);
}) })
.catch((error) => { .catch((error) => {
console.error('Error:', error); console.error('Error:', error);
}); });
}
};
const handleGoBack = () => {
if (dailyData && chartState > 0) {
setChartState(chartState - 1);
}
if (aggregatedData && aggregatedChartState > 0) {
setAggregatedChartState(aggregatedChartState - 1);
}
};
const handleGoForward = () => {
if (dailyData && chartState + 1 < dailyDataArray.length) {
setChartState(chartState + 1);
}
if (
aggregatedData &&
aggregatedChartState + 1 < aggregatedDataArray.length
) {
setAggregatedChartState(aggregatedChartState + 1);
}
}; };
const renderGraphs = () => { const renderGraphs = () => {
@ -438,29 +455,14 @@ function Overview(props: OverviewProps) {
sx={{ sx={{
marginTop: '20px', marginTop: '20px',
marginLeft: '10px', marginLeft: '10px',
backgroundColor: weeklyData ? '#808080' : '#ffc04d', backgroundColor: aggregatedData ? '#808080' : '#ffc04d',
color: '#000000', color: '#000000',
'&:hover': { bgcolor: '#f7b34d' } '&:hover': { bgcolor: '#f7b34d' }
}} }}
> >
<FormattedMessage id="lastweek" defaultMessage="Last week" /> <FormattedMessage id="lastweek" defaultMessage="Last week" />
</Button> </Button>
{/*<Button*/}
{/* variant="contained"*/}
{/* onClick={handleMonthData}*/}
{/* disabled={loading}*/}
{/* sx={{*/}
{/* marginTop: '20px',*/}
{/* marginLeft: '10px',*/}
{/* backgroundColor: monthlyData ? '#808080' : '#ffc04d',*/}
{/* color: '#000000',*/}
{/* '&:hover': { bgcolor: '#f7b34d' }*/}
{/* }}*/}
{/*>*/}
{/* <FormattedMessage id="lastmonth" defaultMessage="Last Month" />*/}
{/*</Button>*/}
{dailyData && (
<>
<Button <Button
variant="contained" variant="contained"
onClick={handleSetDate} onClick={handleSetDate}
@ -475,10 +477,8 @@ function Overview(props: OverviewProps) {
> >
<FormattedMessage id="lastmonth" defaultMessage="Set Date" /> <FormattedMessage id="lastmonth" defaultMessage="Set Date" />
</Button> </Button>
</>
)}
</Grid> </Grid>
{dailyData && (
<Grid <Grid
container container
justifyContent="flex-end" justifyContent="flex-end"
@ -489,7 +489,9 @@ function Overview(props: OverviewProps) {
> >
<Button <Button
variant="contained" variant="contained"
disabled={!(chartState > 0)} disabled={
dailyData ? !(chartState > 0) : !(aggregatedChartState > 0)
}
onClick={handleGoBack} onClick={handleGoBack}
sx={{ sx={{
marginTop: '20px', marginTop: '20px',
@ -504,7 +506,11 @@ function Overview(props: OverviewProps) {
<Button <Button
variant="contained" variant="contained"
disabled={!(chartState < dailyDataArray.length - 1)} disabled={
dailyData
? !(chartState < dailyDataArray.length - 1)
: !(aggregatedChartState < aggregatedDataArray.length - 1)
}
onClick={handleGoForward} onClick={handleGoForward}
sx={{ sx={{
marginTop: '20px', marginTop: '20px',
@ -517,7 +523,6 @@ function Overview(props: OverviewProps) {
<FormattedMessage id="goback" defaultMessage="Zoom in" /> <FormattedMessage id="goback" defaultMessage="Zoom in" />
</Button> </Button>
</Grid> </Grid>
)}
{loading && ( {loading && (
<Container <Container
@ -619,7 +624,7 @@ function Overview(props: OverviewProps) {
</Grid> </Grid>
)} )}
{(weeklyData || monthlyData) && ( {aggregatedData && (
<Grid <Grid
container container
direction="row" direction="row"
@ -660,29 +665,32 @@ function Overview(props: OverviewProps) {
></Box> ></Box>
</Box> </Box>
{weeklyData && (
<ReactApexChart <ReactApexChart
options={{ options={{
...getChartOptions( ...getChartOptions(
weeklyDataArray.chartOverview.overview, aggregatedDataArray[aggregatedChartState]
.chartOverview.overview,
'overview', 'overview',
weeklyDateList, aggregatedDataArray[aggregatedChartState].datelist,
true true
) )
}} }}
series={[ series={[
{ {
...weeklyDataArray.chartData.gridImportPower, ...aggregatedDataArray[aggregatedChartState]
.chartData.gridImportPower,
color: '#b30000', color: '#b30000',
type: 'bar' type: 'bar'
}, },
{ {
...weeklyDataArray.chartData.gridExportPower, ...aggregatedDataArray[aggregatedChartState]
.chartData.gridExportPower,
color: '#ff3333', color: '#ff3333',
type: 'bar' type: 'bar'
}, },
{ {
...weeklyDataArray.chartData.pvProduction, ...aggregatedDataArray[aggregatedChartState]
.chartData.pvProduction,
type: 'bar', type: 'bar',
color: '#ff9900' color: '#ff9900'
}, },
@ -690,51 +698,13 @@ function Overview(props: OverviewProps) {
name: 'Net Energy', name: 'Net Energy',
color: '#ff3333', color: '#ff3333',
type: 'line', type: 'line',
data: weeklybalance data: aggregatedDataArray[aggregatedChartState]
.netbalance
} }
]} ]}
height={400} height={400}
type={'bar'} type={'bar'}
/> />
)}
{monthlyData && (
<ReactApexChart
options={{
...getChartOptions(
monthlyDataArray.chartOverview.overview,
'overview',
monthlyDateList,
true
)
}}
series={[
{
...monthlyDataArray.chartData.gridImportPower,
color: '#b30000',
type: 'bar'
},
{
...monthlyDataArray.chartData.gridExportPower,
color: '#ff3333',
type: 'bar'
},
{
...monthlyDataArray.chartData.pvProduction,
color: '#ff9900',
type: 'bar'
},
{
name: 'Net Energy',
type: 'line',
data: monthlybalance,
color: '#666666'
}
]}
height={400}
type={'bar'}
/>
)}
</Card> </Card>
</Grid> </Grid>
</Grid> </Grid>
@ -806,48 +776,26 @@ function Overview(props: OverviewProps) {
/> />
)} )}
{weeklyData && ( {aggregatedData && (
<ReactApexChart <ReactApexChart
options={{ options={{
...getChartOptions( ...getChartOptions(
weeklyDataArray.chartOverview.soc, aggregatedDataArray[aggregatedChartState]
.chartOverview.soc,
'weekly', 'weekly',
weeklyDateList, aggregatedDataArray[aggregatedChartState].datelist,
true true
) )
}} }}
series={[ series={[
{ {
...weeklyDataArray.chartData.minsoc, ...aggregatedDataArray[aggregatedChartState]
.chartData.minsoc,
color: '#69d2e7' color: '#69d2e7'
}, },
{ {
...weeklyDataArray.chartData.maxsoc, ...aggregatedDataArray[aggregatedChartState]
color: '#008FFB' .chartData.maxsoc,
}
]}
type="bar"
height={400}
/>
)}
{monthlyData && (
<ReactApexChart
options={{
...getChartOptions(
monthlyDataArray.chartOverview.soc,
'monthly',
monthlyDateList,
true
)
}}
series={[
{
...monthlyDataArray.chartData.minsoc,
color: '#69d2e7'
},
{
...monthlyDataArray.chartData.maxsoc,
color: '#008FFB' color: '#008FFB'
} }
]} ]}
@ -918,27 +866,31 @@ function Overview(props: OverviewProps) {
/> />
)} )}
{weeklyData && currentUser.userType == UserType.admin && ( {aggregatedData && currentUser.userType == UserType.admin && (
<ReactApexChart <ReactApexChart
options={{ options={{
...getChartOptions( ...getChartOptions(
weeklyDataArray.chartOverview.dcPower, aggregatedDataArray[aggregatedChartState]
.chartOverview.dcPower,
'weekly', 'weekly',
weeklyDateList, aggregatedDataArray[aggregatedChartState].datelist,
false false
) )
}} }}
series={[ series={[
{ {
...weeklyDataArray.chartData.dcChargingPower, ...aggregatedDataArray[aggregatedChartState]
.chartData.dcChargingPower,
color: '#008FFB' color: '#008FFB'
}, },
{ {
...weeklyDataArray.chartData.heatingPower, ...aggregatedDataArray[aggregatedChartState]
.chartData.heatingPower,
color: '#ff9900' color: '#ff9900'
}, },
{ {
...weeklyDataArray.chartData.dcDischargingPower, ...aggregatedDataArray[aggregatedChartState]
.chartData.dcDischargingPower,
color: '#69d2e7' color: '#69d2e7'
} }
]} ]}
@ -947,80 +899,27 @@ function Overview(props: OverviewProps) {
/> />
)} )}
{weeklyData && currentUser.userType == UserType.client && ( {aggregatedData && currentUser.userType == UserType.client && (
<ReactApexChart <ReactApexChart
options={{ options={{
...getChartOptions( ...getChartOptions(
weeklyDataArray.chartOverview.dcPowerWithoutHeating, aggregatedDataArray[aggregatedChartState]
.chartOverview.dcPowerWithoutHeating,
'weekly', 'weekly',
weeklyDateList, aggregatedDataArray[aggregatedChartState].datelist,
true true
) )
}} }}
series={[ series={[
{ {
...weeklyDataArray.chartData.dcChargingPower, ...aggregatedDataArray[aggregatedChartState]
.chartData.dcChargingPower,
color: '#008FFB' color: '#008FFB'
}, },
{ {
...weeklyDataArray.chartData.dcDischargingPower, ...aggregatedDataArray[aggregatedChartState]
color: '#69d2e7' .chartData.dcDischargingPower,
}
]}
type="bar"
height={400}
/>
)}
{monthlyData && currentUser.userType == UserType.admin && (
<ReactApexChart
options={{
...getChartOptions(
monthlyDataArray.chartOverview.dcPower,
'monthly',
monthlyDateList,
false
)
}}
series={[
{
...monthlyDataArray.chartData.dcChargingPower,
color: '#008FFB'
},
{
...weeklyDataArray.chartData.heatingPower,
color: '#ff9900'
},
{
...monthlyDataArray.chartData.dcDischargingPower,
color: '#69d2e7'
}
]}
type="bar"
height={400}
/>
)}
{monthlyData && currentUser.userType == UserType.client && (
<ReactApexChart
options={{
...getChartOptions(
monthlyDataArray.chartOverview
.dcPowerWithoutHeating,
'monthly',
monthlyDateList,
true
)
}}
series={[
{
...monthlyDataArray.chartData.dcChargingPower,
color: '#008FFB'
},
{
...monthlyDataArray.chartData.dcDischargingPower,
color: '#69d2e7' color: '#69d2e7'
} }
]} ]}
@ -1228,40 +1127,21 @@ function Overview(props: OverviewProps) {
/> />
)} )}
{weeklyData && ( {aggregatedData && (
<ReactApexChart <ReactApexChart
options={{ options={{
...getChartOptions( ...getChartOptions(
weeklyDataArray.chartOverview.pvProduction, aggregatedDataArray[aggregatedChartState]
.chartOverview.pvProduction,
'weekly', 'weekly',
weeklyDateList, aggregatedDataArray[aggregatedChartState].datelist,
true true
) )
}} }}
series={[ series={[
{ {
...weeklyDataArray.chartData.pvProduction, ...aggregatedDataArray[aggregatedChartState]
color: '#ff9900' .chartData.pvProduction,
}
]}
type="bar"
height={400}
/>
)}
{monthlyData && (
<ReactApexChart
options={{
...getChartOptions(
monthlyDataArray.chartOverview.pvProduction,
'monthly',
monthlyDateList,
true
)
}}
series={[
{
...monthlyDataArray.chartData.pvProduction,
color: '#ff9900' color: '#ff9900'
} }
]} ]}
@ -1330,49 +1210,27 @@ function Overview(props: OverviewProps) {
height={400} height={400}
/> />
)} )}
{weeklyData && ( {aggregatedData && (
<ReactApexChart <ReactApexChart
options={{ options={{
...getChartOptions( ...getChartOptions(
weeklyDataArray.chartOverview.gridPower, aggregatedDataArray[aggregatedChartState]
.chartOverview.gridPower,
'weekly', 'weekly',
weeklyDateList, aggregatedDataArray[aggregatedChartState].datelist,
true true
) )
}} }}
series={[ series={[
{ {
...weeklyDataArray.chartData.gridImportPower, ...aggregatedDataArray[aggregatedChartState]
.chartData.gridImportPower,
color: '#b30000' color: '#b30000'
}, },
{ {
...weeklyDataArray.chartData.gridExportPower, ...aggregatedDataArray[aggregatedChartState]
color: '#ff3333' .chartData.gridExportPower,
}
]}
type="bar"
height={400}
/>
)}
{monthlyData && (
<ReactApexChart
options={{
...getChartOptions(
monthlyDataArray.chartOverview.gridPower,
'monthly',
monthlyDateList,
true
)
}}
series={[
{
...monthlyDataArray.chartData.gridImportPower,
color: '#b30000'
},
{
...monthlyDataArray.chartData.gridExportPower,
color: '#ff3333' color: '#ff3333'
} }
]} ]}

View File

@ -9,11 +9,30 @@ import { InstallationsContext } from 'src/contexts/InstallationsContextProvider'
import { Route, Routes } from 'react-router-dom'; import { Route, Routes } from 'react-router-dom';
import routes from '../../../Resources/routes.json'; import routes from '../../../Resources/routes.json';
import Folder from './Folder'; import Folder from './Folder';
import { WebSocketContext } from '../../../contexts/WebSocketContextProvider';
function InstallationTree() { function InstallationTree() {
const { foldersAndInstallations, fetchAllFoldersAndInstallations } = const { foldersAndInstallations, fetchAllFoldersAndInstallations } =
useContext(InstallationsContext); useContext(InstallationsContext);
const webSocketContext = useContext(WebSocketContext);
const { getStatus } = webSocketContext;
const sortedInstallations = [...foldersAndInstallations].sort((a, b) => {
// Compare the status field of each installation and sort them based on the status.
//Installations with alarms go first
let a_status = getStatus(a.id);
let b_status = getStatus(b.id);
if (a_status > b_status) {
return -1;
}
if (a_status < b_status) {
return 1;
}
return 0;
});
useEffect(() => { useEffect(() => {
fetchAllFoldersAndInstallations(); fetchAllFoldersAndInstallations();
}, []); }, []);
@ -23,7 +42,7 @@ function InstallationTree() {
return ( return (
node.parentId == parent_id && ( node.parentId == parent_id && (
<CustomTreeItem node={node} parent_id={parent_id}> <CustomTreeItem node={node} parent_id={parent_id}>
{foldersAndInstallations.map((subnode) => { {sortedInstallations.map((subnode) => {
return ( return (
subnode != node && subnode != node &&
subnode.parentId == node.id && ( subnode.parentId == node.id && (

View File

@ -424,7 +424,8 @@ export const transformInputToDailyData = async (
export const transformInputToAggregatedData = async ( export const transformInputToAggregatedData = async (
s3Credentials: I_S3Credentials, s3Credentials: I_S3Credentials,
type: string start_date: dayjs.Dayjs,
end_date: dayjs.Dayjs
): Promise<{ ): Promise<{
chartAggregatedData: chartAggregatedDataInterface; chartAggregatedData: chartAggregatedDataInterface;
chartOverview: overviewInterface; chartOverview: overviewInterface;
@ -435,11 +436,11 @@ export const transformInputToAggregatedData = async (
const MAX_NUMBER = 9999999; const MAX_NUMBER = 9999999;
const dateList = []; const dateList = [];
let currentDate = dayjs(); //let currentDate = dayjs();
let currentDay = let currentDay = start_date;
type === 'weekly' // type === 'weekly'
? currentDate.subtract(1, 'week') // ? currentDate.subtract(1, 'week')
: currentDate.subtract(1, 'month'); // : currentDate.subtract(1, 'month');
const pathsToSearch = [ const pathsToSearch = [
'/MinSoc', '/MinSoc',
@ -497,7 +498,7 @@ export const transformInputToAggregatedData = async (
const timestampPromises = []; const timestampPromises = [];
while (currentDay.isBefore(currentDate)) { while (currentDay.isBefore(end_date)) {
timestampPromises.push( timestampPromises.push(
fetchDailyData(currentDay.format('YYYY-MM-DD'), s3Credentials) fetchDailyData(currentDay.format('YYYY-MM-DD'), s3Credentials)
); );
@ -505,7 +506,7 @@ export const transformInputToAggregatedData = async (
} }
const results = await Promise.all(timestampPromises); const results = await Promise.all(timestampPromises);
currentDay = currentDate.subtract(1, 'month'); currentDay = start_date;
for (let i = 0; i < results.length; i++) { for (let i = 0; i < results.length; i++) {
const result = results[i]; const result = results[i];