Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions client/src/components/pdp-monitoring/InstrumentationGraph.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React, { useState, useEffect } from 'react';
import {
LineChart,
Line,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
Legend,
ResponsiveContainer
} from 'recharts';
import { IAprsTelemetryPacket } from '../utils/TelemetryTypes';

interface GraphProps {
dataKeys: string[];
packet?: IAprsTelemetryPacket;
staticData: any[];
realTime: boolean;
}

const InsGraph: React.FC<GraphProps> = (props: GraphProps) => {
const { dataKeys, staticData, realTime, packet } = props;
const [data, setData] = useState<any[]>([]);

useEffect(() => {
if (realTime && packet?.Parsed.altitude > 0) {
setData((prev) => [
...prev,
{
Altitude: packet?.Parsed.altitude
}
]);
}
}, [packet]);

useEffect(() => {
setData(staticData);
}, [])

return (
<ResponsiveContainer width="100%" height={"50%"}>
<LineChart data={data}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="Time" />
<YAxis domain={[]}/>
<Tooltip />
<Legend align='center' />
{dataKeys && dataKeys.map((key, index) => {
if (key !== 'Time') {
return (
<Line
key={index}
type="monotone"
dataKey={key}
stroke={`hsl(${index * 360 / dataKeys.length}, 100%, 50%)`}
strokeWidth={3}
activeDot={{ r: 8 }}
isAnimationActive={!realTime}
/>
);
}
return null;
})}
</LineChart>
</ResponsiveContainer>
);
};

export default InsGraph;
125 changes: 115 additions & 10 deletions client/src/components/pdp-monitoring/InstrumentationModule.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,45 @@
import { MoreVert } from '@mui/icons-material';
import { Box, Button, Card, CardActions, CardContent, CardHeader, IconButton, Paper, Popper, Stack, Tooltip, Typography } from '@mui/material';
import { Menu, MenuItem, } from '@mui/material';
import VisualizationMenu from "./VisualizationMenu"; //In progress to make the menu code a component
import React, { useEffect, useState } from 'react';
import InsGraph from "./InstrumentationGraph";



export enum InstrumentationType_t {
TEMPERATURE = 'Temperature',
PRESSURE = 'Pressure',
LOAD = 'Load'
FORCE = 'Force',
MASS = 'Mass'
}

interface IInstrumentationReadingType {
label: string;
color: string;
med: number; //Threshold to show yellow
hi: number; //Threshold to show red
}

interface IInstrumentationModuleProps {
title: string;
type: InstrumentationType_t;
state: string; //This is the color shown on the reading box
}

export const InstrumentationModule: React.FC<IInstrumentationModuleProps> = (props: IInstrumentationModuleProps) => {
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);

const open = Boolean(anchorEl);

const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};

const handleClose = () => {
setAnchorEl(null);
};

const { title, type } = props;

const [InstrumentationType, setInstrumentationType] = useState<IInstrumentationReadingType>({
Expand All @@ -31,23 +52,58 @@ export const InstrumentationModule: React.FC<IInstrumentationModuleProps> = (pro
case InstrumentationType_t.TEMPERATURE:
setInstrumentationType({
label: "T",
color: "#D65B4F"
color: "#D65B4F",
med: 773, //Kelvin
hi:973
});
break;
case InstrumentationType_t.LOAD:
setInstrumentationType({
label: "L",
color: "#FFC557"
color: "#FFC557",
med: 20,
hi:30
});
break;
case InstrumentationType_t.PRESSURE:
setInstrumentationType({
label: "P",
color: "#005EB8"
color: "#005EB8",
med: 750, //psi
hi:800
});
break;
case InstrumentationType_t.MASS:
setInstrumentationType({
label: "M",
color: "#3FB684",
med: 50, //kg
hi: 25
});
break;
}

}, []);
//Sets the color of the reading depending if its safe or not
// useEffect(() => {
// if (packet?.Parsed.altitude > 0) { //Change to Parsed.pressure to get the measurement
// Altitude: packet?.Parsed.altitude //Change to pressure, temp, load, mass
// switch (Altitude){
// case (Altitude<InstrumentationType.med):
// alert: "#419769" //Green
// break;
// case (Altitude>=InstrumentationType.med && Altitude <InstrumentationType.hi):
// alert: "#D79C00" //Yellow
// break;
// case (Altitude>=InstrumentationType.hi):
// alert: "#D65B4F" //Red
// break;
// }


// }
// }, [packet]);


return (
<Card sx={{ maxWidth: 250, maxHeight: 250 }}>
Expand Down Expand Up @@ -95,11 +151,31 @@ export const InstrumentationModule: React.FC<IInstrumentationModuleProps> = (pro
</Paper>
</Popper>

<Tooltip title="Visualization Type">
<IconButton>
<div>
<IconButton
id="basic-button"
aria-controls={open ? 'basic-menu' : undefined}
aria-haspopup="true"
aria-expanded={open ? 'true' : undefined}
onClick={handleClick}
>
<MoreVert/>
</IconButton>
</Tooltip>
<Menu
id="basic-menu"
anchorEl={anchorEl}
open={open}
onClose={handleClose}
MenuListProps={{
'aria-labelledby': 'basic-button',
}}
>
<MenuItem onClick={handleClose}>Graph</MenuItem>
<MenuItem onClick={handleClose}>Value</MenuItem>
<MenuItem onClick={handleClose}>Graph and Value</MenuItem>
</Menu>
</div>

<Tooltip
title={`${type} Reading`}
>
Expand All @@ -111,8 +187,11 @@ export const InstrumentationModule: React.FC<IInstrumentationModuleProps> = (pro
padding: 1,
width: 35,
height: 35

}}
textAlign={'center'}


>
<Typography margin={0} sx={{ fontWeight: "bold" }}>{InstrumentationType.label}</Typography>
</Box>
Expand All @@ -122,10 +201,36 @@ export const InstrumentationModule: React.FC<IInstrumentationModuleProps> = (pro
/>
<CardContent>
<div>
<p>Temperature: 0</p>
<p>Pressure: 0</p>
<p>Altitude: 0</p>

<div><Box height="120px" ml="-60px">
<InsGraph IInstrumentationModuleProps={true}
staticData={["0","25","50","100"]}
realTime={false}
/>
</Box>
</div>

<Tooltip
title={`Current ${type}`}>
<center>
<Box
sx={{
backgroundColor: "#419769",
color: 'white',
borderRadius: 1,
padding: 1,
width: 90,
height: 35
}}
textAlign={'center'}

>
<Typography margin={0} sx={{ fontWeight: "bold" }}>{InstrumentationType.label}</Typography>
</Box>
</center>
</Tooltip>
</div>

</CardContent>
<CardActions>
<div>
Expand Down
10 changes: 9 additions & 1 deletion client/src/components/pdp-monitoring/InstrumentationPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Chip, Grid, Paper, Stack, Switch, Tooltip, Typography, styled } from '@mui/material';
import { Chip, Grid, Paper, Stack, Switch, Tooltip, Typography, styled, } from '@mui/material';
import React, { useEffect, useState } from 'react';

import SensorsIcon from '@mui/icons-material/Sensors';
Expand Down Expand Up @@ -31,8 +31,16 @@ const InstrumentationPanel: React.FC<IProps> = (props: IProps) => {
gap={2}
>
<InstrumentationModule title={"Run Tank"} type={InstrumentationType_t.PRESSURE}/>
<InstrumentationModule title={"N2O Flow"} type={InstrumentationType_t.PRESSURE}/>
<InstrumentationModule title={"N2 Flow"} type={InstrumentationType_t.PRESSURE}/>
<InstrumentationModule title={"Injector"} type={InstrumentationType_t.PRESSURE}/>
<InstrumentationModule title={"Run Tank"} type={InstrumentationType_t.TEMPERATURE}/>
<InstrumentationModule title={"Run Tank"} type={InstrumentationType_t.MASS}/>
<InstrumentationModule title={"ShuntCurrent"} type={InstrumentationType_t.LOAD}/>

</Grid>
</Stack>

);
};

Expand Down
26 changes: 26 additions & 0 deletions client/src/components/pdp-monitoring/VisualizationMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React, {useCallback, useEffect, useState} from "react";
import { Button, List, ListItemButton, ListItemText, MenuItem, Menu, MoreVertIcon } from "@mui/material";

export default function BasicMenu() {
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const open = Boolean(anchorEl);
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};

}
export default function BasicMenu() {
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const open = Boolean(anchorEl);
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};

}