Inserted select button to select firmware version.

This commit is contained in:
Noe 2024-04-30 14:07:50 +02:00
parent cee72bebe6
commit ccec20432b
15 changed files with 468 additions and 372 deletions

View File

@ -533,14 +533,14 @@ public class Controller : ControllerBase
} }
[HttpPost(nameof(UpdateFirmware))] [HttpPost(nameof(UpdateFirmware))]
public async Task<ActionResult> UpdateFirmware(Int64 batteryNode, Int64 installationId,Token authToken) public async Task<ActionResult> UpdateFirmware(Int64 batteryNode, Int64 installationId,String version,Token authToken)
{ {
var session = Db.GetSession(authToken); var session = Db.GetSession(authToken);
var installationToUpdate = Db.GetInstallationById(installationId); var installationToUpdate = Db.GetInstallationById(installationId);
if (installationToUpdate != null) if (installationToUpdate != null)
{ {
_ = session.RunScriptInBackground(installationToUpdate.VpnIp, batteryNode); _ = session.RunScriptInBackground(installationToUpdate.VpnIp, batteryNode,version);
} }
return Ok(); return Ok();

View File

@ -8,6 +8,7 @@ public class Installation : TreeNode
public String Region { get; set; } = ""; public String Region { get; set; } = "";
public String Country { get; set; } = ""; public String Country { get; set; } = "";
public String VpnIp { get; set; } = ""; public String VpnIp { get; set; } = "";
public String InstallationName { get; set; } = "";
public String S3Region { get; set; } = "sos-ch-dk-2"; public String S3Region { get; set; } = "sos-ch-dk-2";
public String S3Provider { get; set; } = "exo.io"; public String S3Provider { get; set; } = "exo.io";
@ -15,6 +16,7 @@ public class Installation : TreeNode
public String S3Key { get; set; } = ""; public String S3Key { get; set; } = "";
public String S3WriteSecret { get; set; } = ""; public String S3WriteSecret { get; set; } = "";
public String S3Secret { get; set; } = ""; public String S3Secret { get; set; } = "";
public int S3BucketId { get; set; } = 0;
public String ReadRoleId { get; set; } = ""; public String ReadRoleId { get; set; } = "";
public String WriteRoleId { get; set; } = ""; public String WriteRoleId { get; set; } = "";

View File

@ -131,7 +131,7 @@ public static class ExoCmd
if (response.StatusCode != HttpStatusCode.OK){ if (response.StatusCode != HttpStatusCode.OK){
Console.WriteLine("Fuck"); Console.WriteLine("Fuck");
} }
//Console.WriteLine($"Created Key for {installation.Name}"); //Console.WriteLine($"Created Key for {installation.InstallationName}");
var responseString = await response.Content.ReadAsStringAsync(); var responseString = await response.Content.ReadAsStringAsync();
var responseJson = JsonNode.Parse(responseString) ; var responseJson = JsonNode.Parse(responseString) ;
@ -143,10 +143,12 @@ public static class ExoCmd
{ {
const String url = "https://api-ch-dk-2.exoscale.com/v2/iam-role"; const String url = "https://api-ch-dk-2.exoscale.com/v2/iam-role";
const String method = "iam-role"; const String method = "iam-role";
String rolename = installation.Product==0?Db.Installations.Count(f => f.Product == 0) + installation.InstallationName:Db.Installations.Count(f => f.Product == 1) + installation.InstallationName;
var contentString = $$""" var contentString = $$"""
{ {
"name" : "{{installation.Id + installation.Name}}", "name" : "{{rolename}}",
"policy" : { "policy" : {
"default-service-strategy": "deny", "default-service-strategy": "deny",
"services": { "services": {
@ -243,10 +245,11 @@ public static class ExoCmd
{ {
const String url = "https://api-ch-dk-2.exoscale.com/v2/iam-role"; const String url = "https://api-ch-dk-2.exoscale.com/v2/iam-role";
const String method = "iam-role"; const String method = "iam-role";
String rolename = installation.Product==0?Db.Installations.Count(f => f.Product == 0) + installation.InstallationName:Db.Installations.Count(f => f.Product == 1) + installation.InstallationName;
var contentString = $$""" var contentString = $$"""
{ {
"name" : "WRITE{{installation.Id + installation.Name}}", "name" : "WRITE{{rolename}}",
"policy" : { "policy" : {
"default-service-strategy": "deny", "default-service-strategy": "deny",
"services": { "services": {

View File

@ -18,10 +18,10 @@ public static class InstallationMethods
{ {
if (installation.Product == 0) if (installation.Product == 0)
{ {
return $"{installation.Id}-{BucketNameSalt}"; return $"{installation.S3BucketId}-{BucketNameSalt}";
} }
return $"{installation.Id}-{SalidomoBucketNameSalt}"; return $"{installation.S3BucketId}-{SalidomoBucketNameSalt}";
} }

View File

@ -68,7 +68,7 @@ public static class SessionMethods
.Apply(Db.Update); .Apply(Db.Update);
} }
public static async Task RunScriptInBackground(this Session? session, String vpnIp, Int64 batteryNode) public static async Task RunScriptInBackground(this Session? session, String vpnIp, Int64 batteryNode,String version)
{ {
Console.WriteLine("-----------------------------------Start updating firmware-----------------------------------"); Console.WriteLine("-----------------------------------Start updating firmware-----------------------------------");
string scriptPath = "/home/ubuntu/backend/uploadBatteryFw/update_firmware.sh"; string scriptPath = "/home/ubuntu/backend/uploadBatteryFw/update_firmware.sh";
@ -77,7 +77,7 @@ public static class SessionMethods
{ {
Process process = new Process(); Process process = new Process();
process.StartInfo.FileName = "/bin/bash"; process.StartInfo.FileName = "/bin/bash";
process.StartInfo.Arguments = $"{scriptPath} {vpnIp} {batteryNode}"; process.StartInfo.Arguments = $"{scriptPath} {vpnIp} {batteryNode} {version}";
process.StartInfo.UseShellExecute = false; process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardOutput = true;
@ -118,6 +118,8 @@ public static class SessionMethods
{ {
var user = session?.User; var user = session?.User;
//Salimax installation //Salimax installation
if (installation.Product==0) if (installation.Product==0)
{ {

View File

@ -16,6 +16,8 @@ public static partial class Db
public static Boolean Create(Installation installation) public static Boolean Create(Installation installation)
{ {
installation.S3BucketId = Installations.Count(f => f.Product == installation.Product)+1;
// SQLite wrapper is smart and *modifies* t's Id to the one generated (autoincrement) by the insertion // SQLite wrapper is smart and *modifies* t's Id to the one generated (autoincrement) by the insertion
return Insert(installation); return Insert(installation);
} }

View File

@ -108,7 +108,7 @@ public static partial class Db
Connection.CreateTable<Warning>(); Connection.CreateTable<Warning>();
}); });
UpdateKeys(); //UpdateKeys();
CleanupSessions().SupressAwaitWarning(); CleanupSessions().SupressAwaitWarning();
} }
@ -148,6 +148,18 @@ public static partial class Db
.Distinct() .Distinct()
.ToList(); .ToList();
Console.WriteLine("VALID READ KEYS");
for (int i = 0; i < validReadKeys.Count; i++)
{
Console.WriteLine(validReadKeys[i]);
}
Console.WriteLine("VALID WRITE KEYS");
for (int i = 0; i < validReadKeys.Count; i++)
{
Console.WriteLine(validWriteKeys[i]);
}
const String provider = "exo.io"; const String provider = "exo.io";
@ -157,7 +169,7 @@ public static partial class Db
{ {
if (keyMetadata["key"].ToString()!="EXOa0b53cf10517307cec1bf00e" && !validReadKeys.Contains(keyMetadata["key"].ToString()) && !validWriteKeys.Contains(keyMetadata["key"].ToString())) if (keyMetadata["key"].ToString()!="EXOa0b53cf10517307cec1bf00e" && !validReadKeys.Contains(keyMetadata["key"].ToString()) && !validWriteKeys.Contains(keyMetadata["key"].ToString()))
{ {
await ExoCmd.RevokeReadKey(keyMetadata["key"].ToString()); //await ExoCmd.RevokeReadKey(keyMetadata["key"].ToString());
Console.WriteLine("Deleted key "+keyMetadata["key"]); Console.WriteLine("Deleted key "+keyMetadata["key"]);
} }

View File

@ -1,3 +1,4 @@
using Flurl.Http;
using Hellang.Middleware.ProblemDetails; using Hellang.Middleware.ProblemDetails;
using InnovEnergy.App.Backend.Database; using InnovEnergy.App.Backend.Database;
using InnovEnergy.App.Backend.Websockets; using InnovEnergy.App.Backend.Websockets;
@ -5,11 +6,13 @@ using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
using InnovEnergy.Lib.Utils; using InnovEnergy.Lib.Utils;
using Org.BouncyCastle.Math.EC;
namespace InnovEnergy.App.Backend; namespace InnovEnergy.App.Backend;
public static class Program public static class Program
{ {
public static void Main(String[] args) public static async Task Main(String[] args)
{ {
Watchdog.NotifyReady(); Watchdog.NotifyReady();
Db.Init(); Db.Init();

View File

@ -58,7 +58,8 @@ public static class RabbitMqManager
{ {
Console.WriteLine("----------------------------------------------"); Console.WriteLine("----------------------------------------------");
Console.WriteLine("Received a message from installation: " + receivedStatusMessage.InstallationId + " and status is: " + receivedStatusMessage.Status); Console.WriteLine("Received a message from installation: " + receivedStatusMessage.InstallationId + " and status is: " + receivedStatusMessage.Status);
var installationId = receivedStatusMessage.InstallationId; int installationId = (int)Db.Installations.Where(f => f.Product == 0 && f.S3BucketId == receivedStatusMessage.InstallationId).Select(f => f.Id).FirstOrDefault();
//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.

View File

@ -32,21 +32,21 @@ interface BatteryViewProps {
s3Credentials: I_S3Credentials; s3Credentials: I_S3Credentials;
installationId: number; installationId: number;
productNum: number; productNum: number;
connected: boolean;
} }
function BatteryView(props: BatteryViewProps) { function BatteryView(props: BatteryViewProps) {
if (props.values === null) { if (props.values === null && props.connected == true) {
return null; return null;
} }
const currentLocation = useLocation(); const currentLocation = useLocation();
const navigate = useNavigate(); const navigate = useNavigate();
const sortedBatteryView = [...props.values.batteryView].sort( const sortedBatteryView =
(a, b) => b.BatteryId - a.BatteryId props.values != null
); ? [...props.values.batteryView].sort((a, b) => b.BatteryId - a.BatteryId)
: [];
const [loading, setLoading] = useState( const [loading, setLoading] = useState(sortedBatteryView.length == 0);
sortedBatteryView.length == 0 ? true : false
);
const handleMainStatsButton = () => { const handleMainStatsButton = () => {
navigate(routes.mainstats); navigate(routes.mainstats);
@ -70,7 +70,31 @@ function BatteryView(props: BatteryViewProps) {
return ( return (
<> <>
{loading && ( {!props.connected && (
<Container
maxWidth="xl"
sx={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
height: '70vh'
}}
>
<CircularProgress size={60} style={{ color: '#ffc04d' }} />
<Typography
variant="body2"
style={{ color: 'black', fontWeight: 'bold' }}
mt={2}
>
Unable to communicate with the installation
</Typography>
<Typography variant="body2" style={{ color: 'black' }}>
Please wait or refresh the page
</Typography>
</Container>
)}
{loading && props.connected && (
<Container <Container
maxWidth="xl" maxWidth="xl"
sx={{ sx={{
@ -95,7 +119,7 @@ function BatteryView(props: BatteryViewProps) {
</Container> </Container>
)} )}
{!loading && ( {!loading && props.connected && (
<Container maxWidth="xl"> <Container maxWidth="xl">
<Grid container> <Grid container>
<Grid <Grid

View File

@ -5,8 +5,10 @@ import {
Card, Card,
Grid, Grid,
IconButton, IconButton,
MenuItem,
Modal, Modal,
Paper, Paper,
Select,
Table, Table,
TableBody, TableBody,
TableCell, TableCell,
@ -18,7 +20,6 @@ import { Battery } from '../Log/graph.util';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import ArrowBackIcon from '@mui/icons-material/ArrowBack'; import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import Button from '@mui/material/Button'; import Button from '@mui/material/Button';
import { FormattedMessage } from 'react-intl';
import axiosConfig from '../../../Resources/axiosConfig'; import axiosConfig from '../../../Resources/axiosConfig';
interface DetailedBatteryViewProps { interface DetailedBatteryViewProps {
@ -37,6 +38,10 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
const [openModalResultFirmwareUpdate, setOpenModalResultFirmwareUpdate] = const [openModalResultFirmwareUpdate, setOpenModalResultFirmwareUpdate] =
useState(false); useState(false);
const [selectedVersion, setSelectedVersion] = useState(
props.batteryData.FwVersion.value
);
const handleBatteryViewButton = () => { const handleBatteryViewButton = () => {
navigate(location.pathname.split('/').slice(0, -2).join('/')); navigate(location.pathname.split('/').slice(0, -2).join('/'));
}; };
@ -113,7 +118,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
.post( .post(
`/UpdateFirmware?batteryNode=${props.batteryData.BatteryId.toString()}&installationId=${ `/UpdateFirmware?batteryNode=${props.batteryData.BatteryId.toString()}&installationId=${
props.installationId props.installationId
}` }&version=${selectedVersion}`
) )
.catch((err) => { .catch((err) => {
if (err.response) { if (err.response) {
@ -264,7 +269,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
<IconButton <IconButton
aria-label="go back" aria-label="go back"
sx={{ sx={{
marginTop: '20px', marginTop: props.productNum != 0 ? '20px' : '0px',
backgroundColor: 'grey', backgroundColor: 'grey',
color: '#000000', color: '#000000',
'&:hover': { bgcolor: '#f7b34d' } '&:hover': { bgcolor: '#f7b34d' }
@ -275,22 +280,38 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
</IconButton> </IconButton>
{props.productNum === 0 && ( {props.productNum === 0 && (
<>
<Select
value={selectedVersion}
onChange={(event) => setSelectedVersion(event.target.value)}
displayEmpty
variant="outlined"
sx={{
marginTop: '30px',
marginLeft: '20px',
height: '40px'
}}
>
<MenuItem disabled value="">
Select Firmware Version
</MenuItem>
<MenuItem value="AF11">AF11</MenuItem>
<MenuItem value="AF0A">AF0A</MenuItem>
</Select>
<Button <Button
variant="contained" variant="contained"
onClick={handleUpdateFirmware} onClick={handleUpdateFirmware}
disabled={!selectedVersion} // Disable button if no version selected
sx={{ sx={{
marginTop: '20px',
marginLeft: '20px', marginLeft: '20px',
backgroundColor: '#ffc04d', backgroundColor: '#ffc04d',
color: '#000000', color: '#000000',
'&:hover': { bgcolor: '#f7b34d' } '&:hover': { bgcolor: '#f7b34d' }
}} }}
> >
<FormattedMessage Update Firmware
id="update_firmware"
defaultMessage="Update Firmware"
/>
</Button> </Button>
</>
)} )}
</Grid> </Grid>
</Grid> </Grid>

View File

@ -1,11 +1,5 @@
import React, { useContext, useEffect, useState } from 'react'; import React, { useContext, useEffect, useState } from 'react';
import { import { Card, CircularProgress, Grid, Typography } from '@mui/material';
Card,
CircularProgress,
Container,
Grid,
Typography
} from '@mui/material';
import { I_Installation } from 'src/interfaces/InstallationTypes'; import { I_Installation } from 'src/interfaces/InstallationTypes';
import { UserContext } from 'src/contexts/userContext'; import { UserContext } from 'src/contexts/userContext';
import AccessContextProvider from 'src/contexts/AccessContextProvider'; import AccessContextProvider from 'src/contexts/AccessContextProvider';
@ -49,10 +43,7 @@ function Installation(props: singleInstallationProps) {
failedToCommunicateWithInstallation, failedToCommunicateWithInstallation,
setFailedToCommunicateWithInstallation setFailedToCommunicateWithInstallation
] = useState(0); ] = useState(0);
const [ const [connected, setConnected] = useState(true);
openModalUnableToCommunicateWIthInstallation,
setOpenModalUnableToCommunicateWIthInstallation
] = useState(false);
if (props.current_installation == undefined) { if (props.current_installation == undefined) {
return null; return null;
@ -83,7 +74,7 @@ function Installation(props: singleInstallationProps) {
if (res != FetchResult.notAvailable && res != FetchResult.tryLater) { if (res != FetchResult.notAvailable && res != FetchResult.tryLater) {
setFailedToCommunicateWithInstallation(0); setFailedToCommunicateWithInstallation(0);
setOpenModalUnableToCommunicateWIthInstallation(false); setConnected(true);
setValues( setValues(
extractValues({ extractValues({
time: now, time: now,
@ -94,7 +85,7 @@ function Installation(props: singleInstallationProps) {
} else { } else {
setFailedToCommunicateWithInstallation((prevCount) => { setFailedToCommunicateWithInstallation((prevCount) => {
if (prevCount + 1 >= 3) { if (prevCount + 1 >= 3) {
setOpenModalUnableToCommunicateWIthInstallation(true); setConnected(false);
} }
return prevCount + 1; return prevCount + 1;
}); });
@ -125,7 +116,7 @@ function Installation(props: singleInstallationProps) {
useEffect(() => { useEffect(() => {
if (status === -1) { if (status === -1) {
setOpenModalUnableToCommunicateWIthInstallation(true); setConnected(false);
} }
}, [status]); }, [status]);
@ -160,10 +151,6 @@ function Installation(props: singleInstallationProps) {
} }
}, [currentTab, location]); }, [currentTab, location]);
const UnableToCommunicateModalHandleOk = () => {
setOpenModalUnableToCommunicateWIthInstallation(false);
};
return ( return (
<> <>
<Grid item xs={12} md={12}> <Grid item xs={12} md={12}>
@ -298,31 +285,6 @@ function Installation(props: singleInstallationProps) {
alignItems="stretch" alignItems="stretch"
spacing={0} spacing={0}
> >
{openModalUnableToCommunicateWIthInstallation && (
<Container
maxWidth="xl"
sx={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
height: '70vh'
}}
>
<CircularProgress size={60} style={{ color: '#ffc04d' }} />
<Typography
variant="body2"
style={{ color: 'black', fontWeight: 'bold' }}
mt={2}
>
Unable to communicate with the installation
</Typography>
<Typography variant="body2" style={{ color: 'black' }}>
Please wait or refresh the page
</Typography>
</Container>
)}
<Routes> <Routes>
<Route <Route
path={routes.information} path={routes.information}
@ -343,6 +305,7 @@ function Installation(props: singleInstallationProps) {
s3Credentials={s3Credentials} s3Credentials={s3Credentials}
installationId={props.current_installation.id} installationId={props.current_installation.id}
productNum={props.current_installation.product} productNum={props.current_installation.product}
connected={connected}
></BatteryView> ></BatteryView>
} }
></Route> ></Route>
@ -353,7 +316,9 @@ function Installation(props: singleInstallationProps) {
<Route <Route
path={routes.live} path={routes.live}
element={<Topology values={values}></Topology>} element={
<Topology values={values} connected={connected}></Topology>
}
/> />
<Route <Route

View File

@ -13,8 +13,8 @@ import { FormattedMessage } from 'react-intl';
import { fetchData } from 'src/content/dashboards/Installations/fetchData'; import { fetchData } from 'src/content/dashboards/Installations/fetchData';
import { Navigate, Route, Routes, useLocation } from 'react-router-dom'; import { Navigate, Route, Routes, useLocation } from 'react-router-dom';
import routes from '../../../Resources/routes.json'; import routes from '../../../Resources/routes.json';
import BatteryView from '../BatteryView/BatteryView';
import InformationSalidomo from '../Information/InformationSalidomo'; import InformationSalidomo from '../Information/InformationSalidomo';
import BatteryView from "../BatteryView/BatteryView";
interface singleInstallationProps { interface singleInstallationProps {
current_installation?: I_Installation; current_installation?: I_Installation;
@ -31,6 +31,11 @@ function Installation(props: singleInstallationProps) {
const [currentTab, setCurrentTab] = useState<string>(undefined); const [currentTab, setCurrentTab] = useState<string>(undefined);
const [values, setValues] = useState<TopologyValues | null>(null); const [values, setValues] = useState<TopologyValues | null>(null);
const status = getStatus(props.current_installation.id); const status = getStatus(props.current_installation.id);
const [
failedToCommunicateWithInstallation,
setFailedToCommunicateWithInstallation
] = useState(0);
const [connected, setConnected] = useState(true);
if (props.current_installation == undefined) { if (props.current_installation == undefined) {
return null; return null;
@ -58,6 +63,8 @@ function Installation(props: singleInstallationProps) {
const res = await fetchData(now, s3Credentials); const res = await fetchData(now, s3Credentials);
if (res != FetchResult.notAvailable && res != FetchResult.tryLater) { if (res != FetchResult.notAvailable && res != FetchResult.tryLater) {
setConnected(true);
setFailedToCommunicateWithInstallation(0);
setValues( setValues(
extractValues({ extractValues({
time: now, time: now,
@ -66,6 +73,14 @@ function Installation(props: singleInstallationProps) {
); );
return true; return true;
} }
else {
setFailedToCommunicateWithInstallation((prevCount) => {
if (prevCount + 1 >= 3) {
setConnected(false);
}
return prevCount + 1;
});
}
} catch (err) { } catch (err) {
return false; return false;
} }
@ -121,6 +136,12 @@ function Installation(props: singleInstallationProps) {
} }
}, [currentTab, location]); }, [currentTab, location]);
useEffect(() => {
if (status === -1) {
setConnected(false);
}
}, [status]);
return ( return (
<> <>
<Grid item xs={12} md={12}> <Grid item xs={12} md={12}>
@ -183,6 +204,7 @@ function Installation(props: singleInstallationProps) {
s3Credentials={s3Credentials} s3Credentials={s3Credentials}
installationId={props.current_installation.id} installationId={props.current_installation.id}
productNum={props.current_installation.product} productNum={props.current_installation.product}
connected={connected}
></BatteryView> ></BatteryView>
} }
></Route> ></Route>

View File

@ -1,5 +1,11 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Container, Grid, Switch, Typography } from '@mui/material'; import {
CircularProgress,
Container,
Grid,
Switch,
Typography
} from '@mui/material';
import TopologyColumn from './topologyColumn'; import TopologyColumn from './topologyColumn';
import { import {
getAmount, getAmount,
@ -9,14 +15,15 @@ import {
interface TopologyProps { interface TopologyProps {
values: TopologyValues; values: TopologyValues;
connected: boolean;
} }
function Topology(props: TopologyProps) { function Topology(props: TopologyProps) {
if (props.values === null) { if (props.values === null && props.connected == true) {
return null; return null;
} }
const highestConnectionValue =
const highestConnectionValue = getHighestConnectionValue(props.values); props.values != null ? getHighestConnectionValue(props.values) : 0;
const [showValues, setShowValues] = useState(false); const [showValues, setShowValues] = useState(false);
const handleSwitch = () => () => { const handleSwitch = () => () => {
@ -28,6 +35,33 @@ function Topology(props: TopologyProps) {
return ( return (
<Container maxWidth="xl" style={{ backgroundColor: 'white' }}> <Container maxWidth="xl" style={{ backgroundColor: 'white' }}>
<Grid container> <Grid container>
{!props.connected && (
<Container
maxWidth="xl"
sx={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
height: '70vh'
}}
>
<CircularProgress size={60} style={{ color: '#ffc04d' }} />
<Typography
variant="body2"
style={{ color: 'black', fontWeight: 'bold' }}
mt={2}
>
Unable to communicate with the installation
</Typography>
<Typography variant="body2" style={{ color: 'black' }}>
Please wait or refresh the page
</Typography>
</Container>
)}
{props.connected && (
<>
<Grid <Grid
item item
xs={12} xs={12}
@ -75,7 +109,8 @@ function Topology(props: TopologyProps) {
centerBox={{ centerBox={{
title: 'Grid', title: 'Grid',
data: props.values.grid, data: props.values.grid,
connected: props.values.gridBox[0].value.toString() != 'Disabled' connected:
props.values.gridBox[0].value.toString() != 'Disabled'
}} }}
centerConnection={{ centerConnection={{
orientation: 'horizontal', orientation: 'horizontal',
@ -131,7 +166,8 @@ function Topology(props: TopologyProps) {
title: 'AC Loads', title: 'AC Loads',
data: props.values.gridBusToLoadOnGridBusConnection, data: props.values.gridBusToLoadOnGridBusConnection,
connected: connected:
props.values.loadOnAcGridBox[0].value.toString() != 'Disabled' props.values.loadOnAcGridBox[0].value.toString() !=
'Disabled'
}} }}
bottomConnection={{ bottomConnection={{
orientation: 'vertical', orientation: 'vertical',
@ -153,7 +189,8 @@ function Topology(props: TopologyProps) {
title: 'Pv Inverter', title: 'Pv Inverter',
data: props.values.pvOnIslandBusToIslandBusConnection, data: props.values.pvOnIslandBusToIslandBusConnection,
connected: connected:
props.values.pvOnIslandBusBox[0].value.toString() != 'Disabled' props.values.pvOnIslandBusBox[0].value.toString() !=
'Disabled'
}} }}
topConnection={{ topConnection={{
orientation: 'vertical', orientation: 'vertical',
@ -312,6 +349,8 @@ function Topology(props: TopologyProps) {
isFirst={false} isFirst={false}
/> />
</Grid> </Grid>
</>
)}
</Grid> </Grid>
</Container> </Container>
); );

View File

@ -86,7 +86,7 @@ export const transformInputToBatteryViewData = async (
const categories = ['Soc', 'Temperature', 'Power', 'Voltage', 'Current']; const categories = ['Soc', 'Temperature', 'Power', 'Voltage', 'Current'];
const pathCategories = [ const pathCategories = [
'Soc', 'Soc',
'Temperatures/Cells/Center', 'Temperatures/Cells/Average',
'Dc/Power', 'Dc/Power',
'Dc/Voltage', 'Dc/Voltage',
'Dc/Current' 'Dc/Current'