Inserted select button to select firmware version.
This commit is contained in:
parent
cee72bebe6
commit
ccec20432b
|
@ -533,14 +533,14 @@ public class Controller : ControllerBase
|
|||
}
|
||||
|
||||
[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 installationToUpdate = Db.GetInstallationById(installationId);
|
||||
|
||||
if (installationToUpdate != null)
|
||||
{
|
||||
_ = session.RunScriptInBackground(installationToUpdate.VpnIp, batteryNode);
|
||||
_ = session.RunScriptInBackground(installationToUpdate.VpnIp, batteryNode,version);
|
||||
}
|
||||
|
||||
return Ok();
|
||||
|
|
|
@ -8,6 +8,7 @@ public class Installation : TreeNode
|
|||
public String Region { get; set; } = "";
|
||||
public String Country { get; set; } = "";
|
||||
public String VpnIp { get; set; } = "";
|
||||
public String InstallationName { get; set; } = "";
|
||||
|
||||
public String S3Region { get; set; } = "sos-ch-dk-2";
|
||||
public String S3Provider { get; set; } = "exo.io";
|
||||
|
@ -15,6 +16,7 @@ public class Installation : TreeNode
|
|||
public String S3Key { get; set; } = "";
|
||||
public String S3WriteSecret { get; set; } = "";
|
||||
public String S3Secret { get; set; } = "";
|
||||
public int S3BucketId { get; set; } = 0;
|
||||
public String ReadRoleId { get; set; } = "";
|
||||
public String WriteRoleId { get; set; } = "";
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ public static class ExoCmd
|
|||
if (response.StatusCode != HttpStatusCode.OK){
|
||||
Console.WriteLine("Fuck");
|
||||
}
|
||||
//Console.WriteLine($"Created Key for {installation.Name}");
|
||||
//Console.WriteLine($"Created Key for {installation.InstallationName}");
|
||||
var responseString = await response.Content.ReadAsStringAsync();
|
||||
|
||||
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 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 = $$"""
|
||||
{
|
||||
"name" : "{{installation.Id + installation.Name}}",
|
||||
"name" : "{{rolename}}",
|
||||
"policy" : {
|
||||
"default-service-strategy": "deny",
|
||||
"services": {
|
||||
|
@ -243,10 +245,11 @@ public static class ExoCmd
|
|||
{
|
||||
const String url = "https://api-ch-dk-2.exoscale.com/v2/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 = $$"""
|
||||
{
|
||||
"name" : "WRITE{{installation.Id + installation.Name}}",
|
||||
"name" : "WRITE{{rolename}}",
|
||||
"policy" : {
|
||||
"default-service-strategy": "deny",
|
||||
"services": {
|
||||
|
|
|
@ -18,10 +18,10 @@ public static class InstallationMethods
|
|||
{
|
||||
if (installation.Product == 0)
|
||||
{
|
||||
return $"{installation.Id}-{BucketNameSalt}";
|
||||
return $"{installation.S3BucketId}-{BucketNameSalt}";
|
||||
}
|
||||
|
||||
return $"{installation.Id}-{SalidomoBucketNameSalt}";
|
||||
return $"{installation.S3BucketId}-{SalidomoBucketNameSalt}";
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ public static class SessionMethods
|
|||
.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-----------------------------------");
|
||||
string scriptPath = "/home/ubuntu/backend/uploadBatteryFw/update_firmware.sh";
|
||||
|
@ -77,7 +77,7 @@ public static class SessionMethods
|
|||
{
|
||||
Process process = new Process();
|
||||
process.StartInfo.FileName = "/bin/bash";
|
||||
process.StartInfo.Arguments = $"{scriptPath} {vpnIp} {batteryNode}";
|
||||
process.StartInfo.Arguments = $"{scriptPath} {vpnIp} {batteryNode} {version}";
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
process.StartInfo.RedirectStandardOutput = true;
|
||||
|
||||
|
@ -118,6 +118,8 @@ public static class SessionMethods
|
|||
{
|
||||
var user = session?.User;
|
||||
|
||||
|
||||
|
||||
//Salimax installation
|
||||
if (installation.Product==0)
|
||||
{
|
||||
|
|
|
@ -16,6 +16,8 @@ public static partial class Db
|
|||
|
||||
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
|
||||
return Insert(installation);
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ public static partial class Db
|
|||
Connection.CreateTable<Warning>();
|
||||
});
|
||||
|
||||
UpdateKeys();
|
||||
//UpdateKeys();
|
||||
CleanupSessions().SupressAwaitWarning();
|
||||
|
||||
}
|
||||
|
@ -147,7 +147,19 @@ public static partial class Db
|
|||
.Select(i => i.S3WriteKey)
|
||||
.Distinct()
|
||||
.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";
|
||||
|
@ -157,7 +169,7 @@ public static partial class Db
|
|||
{
|
||||
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"]);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
using Flurl.Http;
|
||||
using Hellang.Middleware.ProblemDetails;
|
||||
using InnovEnergy.App.Backend.Database;
|
||||
using InnovEnergy.App.Backend.Websockets;
|
||||
|
@ -5,11 +6,13 @@ using Microsoft.AspNetCore.HttpOverrides;
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using InnovEnergy.Lib.Utils;
|
||||
using Org.BouncyCastle.Math.EC;
|
||||
|
||||
namespace InnovEnergy.App.Backend;
|
||||
|
||||
public static class Program
|
||||
{
|
||||
public static void Main(String[] args)
|
||||
public static async Task Main(String[] args)
|
||||
{
|
||||
Watchdog.NotifyReady();
|
||||
Db.Init();
|
||||
|
@ -18,7 +21,7 @@ public static class Program
|
|||
RabbitMqManager.InitializeEnvironment();
|
||||
RabbitMqManager.StartRabbitMqConsumer();
|
||||
WebsocketManager.MonitorInstallationTable();
|
||||
|
||||
|
||||
builder.Services.AddControllers();
|
||||
builder.Services.AddProblemDetails(setup =>
|
||||
{
|
||||
|
|
|
@ -58,7 +58,8 @@ public static class RabbitMqManager
|
|||
{
|
||||
Console.WriteLine("----------------------------------------------");
|
||||
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.
|
||||
//There is no need to notify the corresponding front-ends.
|
||||
|
|
|
@ -32,21 +32,21 @@ interface BatteryViewProps {
|
|||
s3Credentials: I_S3Credentials;
|
||||
installationId: number;
|
||||
productNum: number;
|
||||
connected: boolean;
|
||||
}
|
||||
|
||||
function BatteryView(props: BatteryViewProps) {
|
||||
if (props.values === null) {
|
||||
if (props.values === null && props.connected == true) {
|
||||
return null;
|
||||
}
|
||||
const currentLocation = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const sortedBatteryView = [...props.values.batteryView].sort(
|
||||
(a, b) => b.BatteryId - a.BatteryId
|
||||
);
|
||||
const sortedBatteryView =
|
||||
props.values != null
|
||||
? [...props.values.batteryView].sort((a, b) => b.BatteryId - a.BatteryId)
|
||||
: [];
|
||||
|
||||
const [loading, setLoading] = useState(
|
||||
sortedBatteryView.length == 0 ? true : false
|
||||
);
|
||||
const [loading, setLoading] = useState(sortedBatteryView.length == 0);
|
||||
|
||||
const handleMainStatsButton = () => {
|
||||
navigate(routes.mainstats);
|
||||
|
@ -70,7 +70,31 @@ function BatteryView(props: BatteryViewProps) {
|
|||
|
||||
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
|
||||
maxWidth="xl"
|
||||
sx={{
|
||||
|
@ -95,7 +119,7 @@ function BatteryView(props: BatteryViewProps) {
|
|||
</Container>
|
||||
)}
|
||||
|
||||
{!loading && (
|
||||
{!loading && props.connected && (
|
||||
<Container maxWidth="xl">
|
||||
<Grid container>
|
||||
<Grid
|
||||
|
|
|
@ -5,8 +5,10 @@ import {
|
|||
Card,
|
||||
Grid,
|
||||
IconButton,
|
||||
MenuItem,
|
||||
Modal,
|
||||
Paper,
|
||||
Select,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
|
@ -18,7 +20,6 @@ import { Battery } from '../Log/graph.util';
|
|||
import { useNavigate } from 'react-router-dom';
|
||||
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
||||
import Button from '@mui/material/Button';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import axiosConfig from '../../../Resources/axiosConfig';
|
||||
|
||||
interface DetailedBatteryViewProps {
|
||||
|
@ -37,6 +38,10 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
|
|||
const [openModalResultFirmwareUpdate, setOpenModalResultFirmwareUpdate] =
|
||||
useState(false);
|
||||
|
||||
const [selectedVersion, setSelectedVersion] = useState(
|
||||
props.batteryData.FwVersion.value
|
||||
);
|
||||
|
||||
const handleBatteryViewButton = () => {
|
||||
navigate(location.pathname.split('/').slice(0, -2).join('/'));
|
||||
};
|
||||
|
@ -113,7 +118,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
|
|||
.post(
|
||||
`/UpdateFirmware?batteryNode=${props.batteryData.BatteryId.toString()}&installationId=${
|
||||
props.installationId
|
||||
}`
|
||||
}&version=${selectedVersion}`
|
||||
)
|
||||
.catch((err) => {
|
||||
if (err.response) {
|
||||
|
@ -264,7 +269,7 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
|
|||
<IconButton
|
||||
aria-label="go back"
|
||||
sx={{
|
||||
marginTop: '20px',
|
||||
marginTop: props.productNum != 0 ? '20px' : '0px',
|
||||
backgroundColor: 'grey',
|
||||
color: '#000000',
|
||||
'&:hover': { bgcolor: '#f7b34d' }
|
||||
|
@ -275,22 +280,38 @@ function DetailedBatteryView(props: DetailedBatteryViewProps) {
|
|||
</IconButton>
|
||||
|
||||
{props.productNum === 0 && (
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={handleUpdateFirmware}
|
||||
sx={{
|
||||
marginTop: '20px',
|
||||
marginLeft: '20px',
|
||||
backgroundColor: '#ffc04d',
|
||||
color: '#000000',
|
||||
'&:hover': { bgcolor: '#f7b34d' }
|
||||
}}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="update_firmware"
|
||||
defaultMessage="Update Firmware"
|
||||
/>
|
||||
</Button>
|
||||
<>
|
||||
<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
|
||||
variant="contained"
|
||||
onClick={handleUpdateFirmware}
|
||||
disabled={!selectedVersion} // Disable button if no version selected
|
||||
sx={{
|
||||
marginLeft: '20px',
|
||||
backgroundColor: '#ffc04d',
|
||||
color: '#000000',
|
||||
'&:hover': { bgcolor: '#f7b34d' }
|
||||
}}
|
||||
>
|
||||
Update Firmware
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import {
|
||||
Card,
|
||||
CircularProgress,
|
||||
Container,
|
||||
Grid,
|
||||
Typography
|
||||
} from '@mui/material';
|
||||
import { Card, CircularProgress, Grid, Typography } from '@mui/material';
|
||||
import { I_Installation } from 'src/interfaces/InstallationTypes';
|
||||
import { UserContext } from 'src/contexts/userContext';
|
||||
import AccessContextProvider from 'src/contexts/AccessContextProvider';
|
||||
|
@ -49,10 +43,7 @@ function Installation(props: singleInstallationProps) {
|
|||
failedToCommunicateWithInstallation,
|
||||
setFailedToCommunicateWithInstallation
|
||||
] = useState(0);
|
||||
const [
|
||||
openModalUnableToCommunicateWIthInstallation,
|
||||
setOpenModalUnableToCommunicateWIthInstallation
|
||||
] = useState(false);
|
||||
const [connected, setConnected] = useState(true);
|
||||
|
||||
if (props.current_installation == undefined) {
|
||||
return null;
|
||||
|
@ -83,7 +74,7 @@ function Installation(props: singleInstallationProps) {
|
|||
|
||||
if (res != FetchResult.notAvailable && res != FetchResult.tryLater) {
|
||||
setFailedToCommunicateWithInstallation(0);
|
||||
setOpenModalUnableToCommunicateWIthInstallation(false);
|
||||
setConnected(true);
|
||||
setValues(
|
||||
extractValues({
|
||||
time: now,
|
||||
|
@ -94,7 +85,7 @@ function Installation(props: singleInstallationProps) {
|
|||
} else {
|
||||
setFailedToCommunicateWithInstallation((prevCount) => {
|
||||
if (prevCount + 1 >= 3) {
|
||||
setOpenModalUnableToCommunicateWIthInstallation(true);
|
||||
setConnected(false);
|
||||
}
|
||||
return prevCount + 1;
|
||||
});
|
||||
|
@ -125,7 +116,7 @@ function Installation(props: singleInstallationProps) {
|
|||
|
||||
useEffect(() => {
|
||||
if (status === -1) {
|
||||
setOpenModalUnableToCommunicateWIthInstallation(true);
|
||||
setConnected(false);
|
||||
}
|
||||
}, [status]);
|
||||
|
||||
|
@ -160,10 +151,6 @@ function Installation(props: singleInstallationProps) {
|
|||
}
|
||||
}, [currentTab, location]);
|
||||
|
||||
const UnableToCommunicateModalHandleOk = () => {
|
||||
setOpenModalUnableToCommunicateWIthInstallation(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Grid item xs={12} md={12}>
|
||||
|
@ -298,31 +285,6 @@ function Installation(props: singleInstallationProps) {
|
|||
alignItems="stretch"
|
||||
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>
|
||||
<Route
|
||||
path={routes.information}
|
||||
|
@ -343,6 +305,7 @@ function Installation(props: singleInstallationProps) {
|
|||
s3Credentials={s3Credentials}
|
||||
installationId={props.current_installation.id}
|
||||
productNum={props.current_installation.product}
|
||||
connected={connected}
|
||||
></BatteryView>
|
||||
}
|
||||
></Route>
|
||||
|
@ -353,7 +316,9 @@ function Installation(props: singleInstallationProps) {
|
|||
|
||||
<Route
|
||||
path={routes.live}
|
||||
element={<Topology values={values}></Topology>}
|
||||
element={
|
||||
<Topology values={values} connected={connected}></Topology>
|
||||
}
|
||||
/>
|
||||
|
||||
<Route
|
||||
|
|
|
@ -13,8 +13,8 @@ import { FormattedMessage } from 'react-intl';
|
|||
import { fetchData } from 'src/content/dashboards/Installations/fetchData';
|
||||
import { Navigate, Route, Routes, useLocation } from 'react-router-dom';
|
||||
import routes from '../../../Resources/routes.json';
|
||||
import BatteryView from '../BatteryView/BatteryView';
|
||||
import InformationSalidomo from '../Information/InformationSalidomo';
|
||||
import BatteryView from "../BatteryView/BatteryView";
|
||||
|
||||
interface singleInstallationProps {
|
||||
current_installation?: I_Installation;
|
||||
|
@ -31,6 +31,11 @@ function Installation(props: singleInstallationProps) {
|
|||
const [currentTab, setCurrentTab] = useState<string>(undefined);
|
||||
const [values, setValues] = useState<TopologyValues | null>(null);
|
||||
const status = getStatus(props.current_installation.id);
|
||||
const [
|
||||
failedToCommunicateWithInstallation,
|
||||
setFailedToCommunicateWithInstallation
|
||||
] = useState(0);
|
||||
const [connected, setConnected] = useState(true);
|
||||
|
||||
if (props.current_installation == undefined) {
|
||||
return null;
|
||||
|
@ -58,6 +63,8 @@ function Installation(props: singleInstallationProps) {
|
|||
const res = await fetchData(now, s3Credentials);
|
||||
|
||||
if (res != FetchResult.notAvailable && res != FetchResult.tryLater) {
|
||||
setConnected(true);
|
||||
setFailedToCommunicateWithInstallation(0);
|
||||
setValues(
|
||||
extractValues({
|
||||
time: now,
|
||||
|
@ -66,6 +73,14 @@ function Installation(props: singleInstallationProps) {
|
|||
);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
setFailedToCommunicateWithInstallation((prevCount) => {
|
||||
if (prevCount + 1 >= 3) {
|
||||
setConnected(false);
|
||||
}
|
||||
return prevCount + 1;
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
|
@ -120,6 +135,12 @@ function Installation(props: singleInstallationProps) {
|
|||
};
|
||||
}
|
||||
}, [currentTab, location]);
|
||||
|
||||
useEffect(() => {
|
||||
if (status === -1) {
|
||||
setConnected(false);
|
||||
}
|
||||
}, [status]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -183,6 +204,7 @@ function Installation(props: singleInstallationProps) {
|
|||
s3Credentials={s3Credentials}
|
||||
installationId={props.current_installation.id}
|
||||
productNum={props.current_installation.product}
|
||||
connected={connected}
|
||||
></BatteryView>
|
||||
}
|
||||
></Route>
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
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 {
|
||||
getAmount,
|
||||
|
@ -9,14 +15,15 @@ import {
|
|||
|
||||
interface TopologyProps {
|
||||
values: TopologyValues;
|
||||
connected: boolean;
|
||||
}
|
||||
|
||||
function Topology(props: TopologyProps) {
|
||||
if (props.values === null) {
|
||||
if (props.values === null && props.connected == true) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const highestConnectionValue = getHighestConnectionValue(props.values);
|
||||
const highestConnectionValue =
|
||||
props.values != null ? getHighestConnectionValue(props.values) : 0;
|
||||
const [showValues, setShowValues] = useState(false);
|
||||
|
||||
const handleSwitch = () => () => {
|
||||
|
@ -28,290 +35,322 @@ function Topology(props: TopologyProps) {
|
|||
return (
|
||||
<Container maxWidth="xl" style={{ backgroundColor: 'white' }}>
|
||||
<Grid container>
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
md={12}
|
||||
style={{
|
||||
marginTop: '10px',
|
||||
height: '20px',
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'right',
|
||||
justifyContent: 'right'
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<Typography sx={{ marginTop: '5px', marginRight: '20px' }}>
|
||||
Display Values
|
||||
{!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>
|
||||
<Switch
|
||||
edge="start"
|
||||
color="secondary"
|
||||
onChange={handleSwitch()}
|
||||
sx={{
|
||||
'& .MuiSwitch-thumb': {
|
||||
backgroundColor: 'orange'
|
||||
},
|
||||
marginLeft: '20px'
|
||||
<Typography variant="body2" style={{ color: 'black' }}>
|
||||
Please wait or refresh the page
|
||||
</Typography>
|
||||
</Container>
|
||||
)}
|
||||
|
||||
{props.connected && (
|
||||
<>
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
md={12}
|
||||
style={{
|
||||
marginTop: '10px',
|
||||
height: '20px',
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'right',
|
||||
justifyContent: 'right'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Grid>
|
||||
>
|
||||
<div>
|
||||
<Typography sx={{ marginTop: '5px', marginRight: '20px' }}>
|
||||
Display Values
|
||||
</Typography>
|
||||
<Switch
|
||||
edge="start"
|
||||
color="secondary"
|
||||
onChange={handleSwitch()}
|
||||
sx={{
|
||||
'& .MuiSwitch-thumb': {
|
||||
backgroundColor: 'orange'
|
||||
},
|
||||
marginLeft: '20px'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Grid>
|
||||
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
md={12}
|
||||
style={{
|
||||
height: isMobile ? '550px' : '600px',
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<TopologyColumn
|
||||
centerBox={{
|
||||
title: 'Grid',
|
||||
data: props.values.grid,
|
||||
connected: props.values.gridBox[0].value.toString() != 'Disabled'
|
||||
}}
|
||||
centerConnection={{
|
||||
orientation: 'horizontal',
|
||||
data: props.values.gridToAcInConnection,
|
||||
amount: props.values.gridToAcInConnection
|
||||
? getAmount(
|
||||
highestConnectionValue,
|
||||
props.values.gridToAcInConnection
|
||||
)
|
||||
: 0,
|
||||
showValues: showValues
|
||||
}}
|
||||
isLast={false}
|
||||
isFirst={true}
|
||||
/>
|
||||
<TopologyColumn
|
||||
topBox={{
|
||||
title: 'Pv Inverter',
|
||||
data: props.values.gridBusToPvOnGridbusConnection,
|
||||
connected:
|
||||
props.values.pvOnAcGridBox[0].value.toString() != 'Disabled'
|
||||
}}
|
||||
topConnection={{
|
||||
orientation: 'vertical',
|
||||
position: 'top',
|
||||
data: props.values.gridBusToPvOnGridbusConnection,
|
||||
amount: props.values.gridBusToPvOnGridbusConnection
|
||||
? getAmount(
|
||||
highestConnectionValue,
|
||||
props.values.gridBusToPvOnGridbusConnection
|
||||
)
|
||||
: 0,
|
||||
showValues: showValues
|
||||
}}
|
||||
centerBox={{
|
||||
title: 'Grid Bus',
|
||||
data: props.values.gridBus,
|
||||
connected: true
|
||||
}}
|
||||
centerConnection={{
|
||||
orientation: 'horizontal',
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
md={12}
|
||||
style={{
|
||||
height: isMobile ? '550px' : '600px',
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<TopologyColumn
|
||||
centerBox={{
|
||||
title: 'Grid',
|
||||
data: props.values.grid,
|
||||
connected:
|
||||
props.values.gridBox[0].value.toString() != 'Disabled'
|
||||
}}
|
||||
centerConnection={{
|
||||
orientation: 'horizontal',
|
||||
data: props.values.gridToAcInConnection,
|
||||
amount: props.values.gridToAcInConnection
|
||||
? getAmount(
|
||||
highestConnectionValue,
|
||||
props.values.gridToAcInConnection
|
||||
)
|
||||
: 0,
|
||||
showValues: showValues
|
||||
}}
|
||||
isLast={false}
|
||||
isFirst={true}
|
||||
/>
|
||||
<TopologyColumn
|
||||
topBox={{
|
||||
title: 'Pv Inverter',
|
||||
data: props.values.gridBusToPvOnGridbusConnection,
|
||||
connected:
|
||||
props.values.pvOnAcGridBox[0].value.toString() != 'Disabled'
|
||||
}}
|
||||
topConnection={{
|
||||
orientation: 'vertical',
|
||||
position: 'top',
|
||||
data: props.values.gridBusToPvOnGridbusConnection,
|
||||
amount: props.values.gridBusToPvOnGridbusConnection
|
||||
? getAmount(
|
||||
highestConnectionValue,
|
||||
props.values.gridBusToPvOnGridbusConnection
|
||||
)
|
||||
: 0,
|
||||
showValues: showValues
|
||||
}}
|
||||
centerBox={{
|
||||
title: 'Grid Bus',
|
||||
data: props.values.gridBus,
|
||||
connected: true
|
||||
}}
|
||||
centerConnection={{
|
||||
orientation: 'horizontal',
|
||||
|
||||
amount: props.values.gridBusToIslandBusConnection
|
||||
? getAmount(
|
||||
highestConnectionValue,
|
||||
props.values.gridBusToIslandBusConnection
|
||||
)
|
||||
: 0,
|
||||
data: props.values.gridBusToIslandBusConnection,
|
||||
showValues: showValues
|
||||
}}
|
||||
bottomBox={{
|
||||
title: 'AC Loads',
|
||||
data: props.values.gridBusToLoadOnGridBusConnection,
|
||||
connected:
|
||||
props.values.loadOnAcGridBox[0].value.toString() != 'Disabled'
|
||||
}}
|
||||
bottomConnection={{
|
||||
orientation: 'vertical',
|
||||
position: 'bottom',
|
||||
data: props.values.gridBusToLoadOnGridBusConnection,
|
||||
amount: props.values.gridBusToLoadOnGridBusConnection
|
||||
? getAmount(
|
||||
highestConnectionValue,
|
||||
props.values.gridBusToLoadOnGridBusConnection
|
||||
)
|
||||
: 0,
|
||||
showValues: showValues
|
||||
}}
|
||||
isLast={false}
|
||||
isFirst={false}
|
||||
/>
|
||||
<TopologyColumn
|
||||
topBox={{
|
||||
title: 'Pv Inverter',
|
||||
data: props.values.pvOnIslandBusToIslandBusConnection,
|
||||
connected:
|
||||
props.values.pvOnIslandBusBox[0].value.toString() != 'Disabled'
|
||||
}}
|
||||
topConnection={{
|
||||
orientation: 'vertical',
|
||||
position: 'top',
|
||||
data: props.values.pvOnIslandBusToIslandBusConnection,
|
||||
amount: props.values.pvOnIslandBusToIslandBusConnection
|
||||
? getAmount(
|
||||
highestConnectionValue,
|
||||
props.values.pvOnIslandBusToIslandBusConnection
|
||||
)
|
||||
: 0,
|
||||
showValues: showValues
|
||||
}}
|
||||
centerBox={{
|
||||
title: 'Island Bus',
|
||||
data: props.values.islandBus,
|
||||
connected: true
|
||||
}}
|
||||
centerConnection={{
|
||||
orientation: 'horizontal',
|
||||
data: props.values.islandBusToInverter,
|
||||
amount: props.values.islandBusToInverter
|
||||
? getAmount(
|
||||
highestConnectionValue,
|
||||
props.values.islandBusToInverter
|
||||
)
|
||||
: 0,
|
||||
showValues: showValues
|
||||
}}
|
||||
bottomBox={{
|
||||
title: 'AC Loads',
|
||||
data: props.values.islandBusToLoadOnIslandBusConnection,
|
||||
connected:
|
||||
props.values.loadOnIslandBusBox[0].value.toString() !=
|
||||
'Disabled'
|
||||
}}
|
||||
bottomConnection={{
|
||||
orientation: 'vertical',
|
||||
position: 'bottom',
|
||||
data: props.values.islandBusToLoadOnIslandBusConnection,
|
||||
amount: props.values.islandBusToLoadOnIslandBusConnection
|
||||
? getAmount(
|
||||
highestConnectionValue,
|
||||
props.values.islandBusToLoadOnIslandBusConnection
|
||||
)
|
||||
: 0,
|
||||
showValues: showValues
|
||||
}}
|
||||
isLast={false}
|
||||
isFirst={false}
|
||||
/>
|
||||
<TopologyColumn
|
||||
centerBox={{
|
||||
title: 'AC-DC',
|
||||
data: props.values.inverter,
|
||||
connected: true
|
||||
}}
|
||||
centerConnection={{
|
||||
orientation: 'horizontal',
|
||||
data: props.values.inverterToDcBus,
|
||||
amount: props.values.inverterToDcBus
|
||||
? getAmount(
|
||||
highestConnectionValue,
|
||||
props.values.inverterToDcBus
|
||||
)
|
||||
: 0,
|
||||
showValues: showValues
|
||||
}}
|
||||
isLast={false}
|
||||
isFirst={false}
|
||||
/>
|
||||
<TopologyColumn
|
||||
topBox={{
|
||||
title: 'Pv DC-DC',
|
||||
data: props.values.pvOnDcBusToDcBusConnection,
|
||||
connected:
|
||||
props.values.pvOnDcBox[0].value.toString() != 'Disabled'
|
||||
}}
|
||||
topConnection={{
|
||||
orientation: 'vertical',
|
||||
position: 'top',
|
||||
data: props.values.pvOnDcBusToDcBusConnection,
|
||||
amount: props.values.pvOnDcBusToDcBusConnection
|
||||
? getAmount(
|
||||
highestConnectionValue,
|
||||
props.values.pvOnDcBusToDcBusConnection
|
||||
)
|
||||
: 0,
|
||||
showValues: showValues
|
||||
}}
|
||||
centerBox={{
|
||||
title: 'DC Link',
|
||||
data: props.values.dcBus,
|
||||
connected: true
|
||||
}}
|
||||
centerConnection={{
|
||||
orientation: 'horizontal',
|
||||
data: props.values.dcBusToDcDcConnection,
|
||||
amount: props.values.dcBusToDcDcConnection
|
||||
? getAmount(
|
||||
highestConnectionValue,
|
||||
props.values.dcBusToDcDcConnection
|
||||
)
|
||||
: 0,
|
||||
showValues: showValues
|
||||
}}
|
||||
bottomBox={{
|
||||
title: 'DC Loads',
|
||||
data: props.values.dcBusToLoadOnDcConnection,
|
||||
connected:
|
||||
props.values.loadOnDcBox[0].value.toString() != 'Disabled'
|
||||
}}
|
||||
bottomConnection={{
|
||||
orientation: 'vertical',
|
||||
position: 'bottom',
|
||||
data: props.values.dcBusToLoadOnDcConnection,
|
||||
amount: props.values.dcBusToLoadOnDcConnection
|
||||
? getAmount(
|
||||
highestConnectionValue,
|
||||
props.values.dcBusToLoadOnDcConnection
|
||||
)
|
||||
: 0,
|
||||
showValues: showValues
|
||||
}}
|
||||
isLast={false}
|
||||
isFirst={false}
|
||||
/>
|
||||
<TopologyColumn
|
||||
centerBox={{
|
||||
title: 'DC-DC',
|
||||
data: props.values.dcDc,
|
||||
connected: true
|
||||
}}
|
||||
centerConnection={{
|
||||
orientation: 'horizontal',
|
||||
data: props.values.dcDCToBatteryConnection,
|
||||
amount: props.values.dcDCToBatteryConnection
|
||||
? getAmount(
|
||||
highestConnectionValue,
|
||||
props.values.dcDCToBatteryConnection
|
||||
)
|
||||
: 0,
|
||||
showValues: showValues
|
||||
}}
|
||||
isLast={false}
|
||||
isFirst={false}
|
||||
/>
|
||||
<TopologyColumn
|
||||
centerBox={{
|
||||
title: 'Battery',
|
||||
data: props.values.battery,
|
||||
connected:
|
||||
props.values.batteryBox[0].value.toString() != 'Disabled'
|
||||
}}
|
||||
isLast={true}
|
||||
isFirst={false}
|
||||
/>
|
||||
</Grid>
|
||||
amount: props.values.gridBusToIslandBusConnection
|
||||
? getAmount(
|
||||
highestConnectionValue,
|
||||
props.values.gridBusToIslandBusConnection
|
||||
)
|
||||
: 0,
|
||||
data: props.values.gridBusToIslandBusConnection,
|
||||
showValues: showValues
|
||||
}}
|
||||
bottomBox={{
|
||||
title: 'AC Loads',
|
||||
data: props.values.gridBusToLoadOnGridBusConnection,
|
||||
connected:
|
||||
props.values.loadOnAcGridBox[0].value.toString() !=
|
||||
'Disabled'
|
||||
}}
|
||||
bottomConnection={{
|
||||
orientation: 'vertical',
|
||||
position: 'bottom',
|
||||
data: props.values.gridBusToLoadOnGridBusConnection,
|
||||
amount: props.values.gridBusToLoadOnGridBusConnection
|
||||
? getAmount(
|
||||
highestConnectionValue,
|
||||
props.values.gridBusToLoadOnGridBusConnection
|
||||
)
|
||||
: 0,
|
||||
showValues: showValues
|
||||
}}
|
||||
isLast={false}
|
||||
isFirst={false}
|
||||
/>
|
||||
<TopologyColumn
|
||||
topBox={{
|
||||
title: 'Pv Inverter',
|
||||
data: props.values.pvOnIslandBusToIslandBusConnection,
|
||||
connected:
|
||||
props.values.pvOnIslandBusBox[0].value.toString() !=
|
||||
'Disabled'
|
||||
}}
|
||||
topConnection={{
|
||||
orientation: 'vertical',
|
||||
position: 'top',
|
||||
data: props.values.pvOnIslandBusToIslandBusConnection,
|
||||
amount: props.values.pvOnIslandBusToIslandBusConnection
|
||||
? getAmount(
|
||||
highestConnectionValue,
|
||||
props.values.pvOnIslandBusToIslandBusConnection
|
||||
)
|
||||
: 0,
|
||||
showValues: showValues
|
||||
}}
|
||||
centerBox={{
|
||||
title: 'Island Bus',
|
||||
data: props.values.islandBus,
|
||||
connected: true
|
||||
}}
|
||||
centerConnection={{
|
||||
orientation: 'horizontal',
|
||||
data: props.values.islandBusToInverter,
|
||||
amount: props.values.islandBusToInverter
|
||||
? getAmount(
|
||||
highestConnectionValue,
|
||||
props.values.islandBusToInverter
|
||||
)
|
||||
: 0,
|
||||
showValues: showValues
|
||||
}}
|
||||
bottomBox={{
|
||||
title: 'AC Loads',
|
||||
data: props.values.islandBusToLoadOnIslandBusConnection,
|
||||
connected:
|
||||
props.values.loadOnIslandBusBox[0].value.toString() !=
|
||||
'Disabled'
|
||||
}}
|
||||
bottomConnection={{
|
||||
orientation: 'vertical',
|
||||
position: 'bottom',
|
||||
data: props.values.islandBusToLoadOnIslandBusConnection,
|
||||
amount: props.values.islandBusToLoadOnIslandBusConnection
|
||||
? getAmount(
|
||||
highestConnectionValue,
|
||||
props.values.islandBusToLoadOnIslandBusConnection
|
||||
)
|
||||
: 0,
|
||||
showValues: showValues
|
||||
}}
|
||||
isLast={false}
|
||||
isFirst={false}
|
||||
/>
|
||||
<TopologyColumn
|
||||
centerBox={{
|
||||
title: 'AC-DC',
|
||||
data: props.values.inverter,
|
||||
connected: true
|
||||
}}
|
||||
centerConnection={{
|
||||
orientation: 'horizontal',
|
||||
data: props.values.inverterToDcBus,
|
||||
amount: props.values.inverterToDcBus
|
||||
? getAmount(
|
||||
highestConnectionValue,
|
||||
props.values.inverterToDcBus
|
||||
)
|
||||
: 0,
|
||||
showValues: showValues
|
||||
}}
|
||||
isLast={false}
|
||||
isFirst={false}
|
||||
/>
|
||||
<TopologyColumn
|
||||
topBox={{
|
||||
title: 'Pv DC-DC',
|
||||
data: props.values.pvOnDcBusToDcBusConnection,
|
||||
connected:
|
||||
props.values.pvOnDcBox[0].value.toString() != 'Disabled'
|
||||
}}
|
||||
topConnection={{
|
||||
orientation: 'vertical',
|
||||
position: 'top',
|
||||
data: props.values.pvOnDcBusToDcBusConnection,
|
||||
amount: props.values.pvOnDcBusToDcBusConnection
|
||||
? getAmount(
|
||||
highestConnectionValue,
|
||||
props.values.pvOnDcBusToDcBusConnection
|
||||
)
|
||||
: 0,
|
||||
showValues: showValues
|
||||
}}
|
||||
centerBox={{
|
||||
title: 'DC Link',
|
||||
data: props.values.dcBus,
|
||||
connected: true
|
||||
}}
|
||||
centerConnection={{
|
||||
orientation: 'horizontal',
|
||||
data: props.values.dcBusToDcDcConnection,
|
||||
amount: props.values.dcBusToDcDcConnection
|
||||
? getAmount(
|
||||
highestConnectionValue,
|
||||
props.values.dcBusToDcDcConnection
|
||||
)
|
||||
: 0,
|
||||
showValues: showValues
|
||||
}}
|
||||
bottomBox={{
|
||||
title: 'DC Loads',
|
||||
data: props.values.dcBusToLoadOnDcConnection,
|
||||
connected:
|
||||
props.values.loadOnDcBox[0].value.toString() != 'Disabled'
|
||||
}}
|
||||
bottomConnection={{
|
||||
orientation: 'vertical',
|
||||
position: 'bottom',
|
||||
data: props.values.dcBusToLoadOnDcConnection,
|
||||
amount: props.values.dcBusToLoadOnDcConnection
|
||||
? getAmount(
|
||||
highestConnectionValue,
|
||||
props.values.dcBusToLoadOnDcConnection
|
||||
)
|
||||
: 0,
|
||||
showValues: showValues
|
||||
}}
|
||||
isLast={false}
|
||||
isFirst={false}
|
||||
/>
|
||||
<TopologyColumn
|
||||
centerBox={{
|
||||
title: 'DC-DC',
|
||||
data: props.values.dcDc,
|
||||
connected: true
|
||||
}}
|
||||
centerConnection={{
|
||||
orientation: 'horizontal',
|
||||
data: props.values.dcDCToBatteryConnection,
|
||||
amount: props.values.dcDCToBatteryConnection
|
||||
? getAmount(
|
||||
highestConnectionValue,
|
||||
props.values.dcDCToBatteryConnection
|
||||
)
|
||||
: 0,
|
||||
showValues: showValues
|
||||
}}
|
||||
isLast={false}
|
||||
isFirst={false}
|
||||
/>
|
||||
<TopologyColumn
|
||||
centerBox={{
|
||||
title: 'Battery',
|
||||
data: props.values.battery,
|
||||
connected:
|
||||
props.values.batteryBox[0].value.toString() != 'Disabled'
|
||||
}}
|
||||
isLast={true}
|
||||
isFirst={false}
|
||||
/>
|
||||
</Grid>
|
||||
</>
|
||||
)}
|
||||
</Grid>
|
||||
</Container>
|
||||
);
|
||||
|
|
|
@ -86,7 +86,7 @@ export const transformInputToBatteryViewData = async (
|
|||
const categories = ['Soc', 'Temperature', 'Power', 'Voltage', 'Current'];
|
||||
const pathCategories = [
|
||||
'Soc',
|
||||
'Temperatures/Cells/Center',
|
||||
'Temperatures/Cells/Average',
|
||||
'Dc/Power',
|
||||
'Dc/Voltage',
|
||||
'Dc/Current'
|
||||
|
|
Loading…
Reference in New Issue