385 lines
12 KiB
TypeScript
385 lines
12 KiB
TypeScript
import {
|
|
Box,
|
|
Button,
|
|
Card,
|
|
Grid2 as Grid,
|
|
MenuItem,
|
|
Select,
|
|
ToggleButton,
|
|
ToggleButtonGroup,
|
|
Typography
|
|
} from "@mui/material";
|
|
import { Component, Device } from "models";
|
|
import { Gate } from "models/Gate";
|
|
import { pond } from "protobuf-ts/pond";
|
|
import { useGlobalState, useGateAPI } from "providers";
|
|
import { useEffect, useState } from "react";
|
|
import { useMobile, useSnackbar } from "hooks";
|
|
import { UnitMeasurement } from "models/UnitMeasurement";
|
|
import { quack } from "protobuf-ts/quack";
|
|
import GateDeviceInteraction from "./GateDeviceInteraction";
|
|
import GateSVG from "./GateSVG";
|
|
import GateGraphs from "./GateGraphs";
|
|
//import { ToggleButton, ToggleButtonGroup } from "@material-ui/lab";
|
|
import { getThemeType } from "theme";
|
|
import ButtonGroup from "common/ButtonGroup";
|
|
import { cloneDeep } from "lodash";
|
|
|
|
interface Props {
|
|
gate: Gate;
|
|
comprehensiveDevice: pond.ComprehensiveDevice;
|
|
linkedCompList: Component[];
|
|
drawerView?: boolean;
|
|
}
|
|
|
|
|
|
|
|
export default function GateDevice(props: Props) {
|
|
const { gate, comprehensiveDevice, linkedCompList, drawerView } = props;
|
|
const [{as}] = useGlobalState();
|
|
const [device, setDevice] = useState<Device>(Device.create());
|
|
const [componentOptions, setComponentOptions] = useState<Map<string, Component>>(
|
|
new Map<string, Component>()
|
|
);
|
|
const gateAPI = useGateAPI();
|
|
const [tempKey, setTempKey] = useState("");
|
|
const [pressureKey, setPressureKey] = useState("");
|
|
const [ambientKey, setAmbientKey] = useState("");
|
|
const [greenLightKey, setGreenLightKey] = useState("");
|
|
const [redLightKey, setRedLightKey] = useState("");
|
|
const { openSnack } = useSnackbar();
|
|
const [{ user }] = useGlobalState();
|
|
const [interactionDialog, setInteractionDialog] = useState(false);
|
|
const [densityTemp, setDensityTemp] = useState(0);
|
|
const isMobile = useMobile();
|
|
// const [pcaState, setPCAState] = useState(false);
|
|
// const [pcaFanOn, setPCAFanOn] = useState(false);
|
|
const [detail, setDetail] = useState<"sensors" | "analytics">("analytics");
|
|
const [lastAmbient, setLastAmbient] = useState(0);
|
|
//const [lastTemps, setLastTemps] = useState({ t1: 0, t2: 0 });
|
|
const [ductTemp, setDuctTemp] = useState<number | undefined>()
|
|
//const [lastPressures, setLastPressures] = useState({ p1: 0, p2: 0 });
|
|
const [ductPressure, setDuctPressure] = useState<number | undefined>()
|
|
|
|
|
|
useEffect(() => {
|
|
//addresses of controller LEDs on a V1 device
|
|
let redAddr = "3-1-512";
|
|
let greenAddr = "3-1-1024";
|
|
if (comprehensiveDevice.device) {
|
|
setDevice(Device.any(comprehensiveDevice.device));
|
|
|
|
//check if the device is a MiPCA V2 device since the lEDs will have different addresses
|
|
let dev = Device.create(comprehensiveDevice.device);
|
|
if (dev.settings.product === pond.DeviceProduct.DEVICE_PRODUCT_MIPCA_V2) {
|
|
redAddr = "3-1-256";
|
|
greenAddr = "3-1-512";
|
|
}
|
|
}
|
|
if (comprehensiveDevice.components) {
|
|
let components: Map<string, Component> = new Map<string, Component>();
|
|
setAmbientKey("");
|
|
setTempKey("");
|
|
setPressureKey("");
|
|
comprehensiveDevice.components.forEach(comp => {
|
|
let c = Component.any(comp);
|
|
if (linkedCompList.some(el => el.key() === c.key())) {
|
|
components.set(c.key(), c);
|
|
//determine the positioned components using the gates preferences for it components
|
|
switch (gate.preferences[c.key()]) {
|
|
case pond.GateComponentType.GATE_COMPONENT_TYPE_AMBIENT:
|
|
setAmbientKey(c.key());
|
|
c.status.measurement.forEach(um => {
|
|
let measurement = UnitMeasurement.any(um, user);
|
|
if (measurement.type === quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE) {
|
|
if (measurement.values.length > 1 && measurement.values[0].values.length > 0) {
|
|
setDensityTemp(measurement.values[0].values[0]);
|
|
}
|
|
}
|
|
});
|
|
break;
|
|
case pond.GateComponentType.GATE_COMPONENT_TYPE_TEMP:
|
|
setTempKey(c.key());
|
|
break;
|
|
case pond.GateComponentType.GATE_COMPONENT_TYPE_PRESSURE:
|
|
setPressureKey(c.key());
|
|
// if (
|
|
// c.status.measurement[0] &&
|
|
// c.status.measurement[0].values[0] &&
|
|
// c.status.measurement[0].values[0].values[1]
|
|
// ) {
|
|
// setPCAFanOn(c.status.measurement[0].values[0].values[1] > 996); //apx 4 iwg
|
|
// }
|
|
break;
|
|
default:
|
|
// type is unknown, do nothing
|
|
break;
|
|
}
|
|
}
|
|
if (c.locationString() === redAddr && c.subType() === 1) {
|
|
setRedLightKey(c.key());
|
|
} else if (c.locationString() === greenAddr && c.subType() === 1) {
|
|
setGreenLightKey(c.key());
|
|
}
|
|
});
|
|
setComponentOptions(components);
|
|
}
|
|
}, [comprehensiveDevice, gate, linkedCompList, user]);
|
|
|
|
const gateComponentUpdate = (componentKey: string, gateCompType: pond.GateComponentType) => {
|
|
if (componentKey !== "") {
|
|
gateAPI
|
|
.updatePrefs(
|
|
gate.key,
|
|
"component",
|
|
device.id() + ":" + componentKey,
|
|
gateCompType,
|
|
[gate.key],
|
|
["gate"],
|
|
as
|
|
)
|
|
.then(resp => {
|
|
openSnack("Component Prefence Updated");
|
|
});
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
let tempComponent = componentOptions.get(tempKey);
|
|
if(tempComponent){
|
|
tempComponent.status.measurement.forEach(um => {
|
|
if(um.type === quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE){
|
|
let clone = cloneDeep(um)
|
|
let measurement = UnitMeasurement.any(clone, user)
|
|
if(measurement.values.length > 0){
|
|
let readings = measurement.values[measurement.values.length -1]
|
|
if(readings.values.length > 0){
|
|
setDuctTemp(readings.values[readings.values.length -1])
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}, [componentOptions, tempKey, user]);
|
|
|
|
useEffect(() => {
|
|
let ambientComponent = componentOptions.get(ambientKey);
|
|
let temp = 0;
|
|
if (ambientComponent) {
|
|
ambientComponent.status.measurement.forEach(um => {
|
|
let measurement = UnitMeasurement.any(um, user);
|
|
if (measurement.type === quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE) {
|
|
if (measurement.values.length > 0 && measurement.values[0].values.length > 0) {
|
|
temp = measurement.values[0].values[0];
|
|
}
|
|
}
|
|
});
|
|
}
|
|
setLastAmbient(temp);
|
|
}, [componentOptions, ambientKey, user]);
|
|
|
|
useEffect(() => {
|
|
let pressureComponent = componentOptions.get(pressureKey);
|
|
if(pressureComponent){
|
|
pressureComponent.status.measurement.forEach(um => {
|
|
if(um.type === quack.MeasurementType.MEASUREMENT_TYPE_PRESSURE){
|
|
let clone = cloneDeep(um)
|
|
let measurement = UnitMeasurement.any(clone, user)
|
|
if(measurement.values.length > 0){
|
|
let readings = measurement.values[measurement.values.length -1]
|
|
if(readings.values.length > 0){
|
|
setDuctPressure(readings.values[readings.values.length -1])
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}, [componentOptions, pressureKey, user]);
|
|
|
|
const ambientSelector = () => {
|
|
return (
|
|
<Select
|
|
id="ambientSelect"
|
|
variant="standard"
|
|
value={ambientKey}
|
|
style={{ fontSize: 8 }}
|
|
onChange={e => {
|
|
var key = e.target.value as string;
|
|
gateComponentUpdate(key, pond.GateComponentType.GATE_COMPONENT_TYPE_AMBIENT);
|
|
setAmbientKey(key);
|
|
if (tempKey === key) {
|
|
setTempKey("");
|
|
}
|
|
if (pressureKey === key) {
|
|
setPressureKey("");
|
|
}
|
|
}}
|
|
displayEmpty>
|
|
<MenuItem value="">
|
|
<em>Select Ambient Sensor</em>
|
|
</MenuItem>
|
|
{Array.from(componentOptions.values()).map(c => {
|
|
return (
|
|
<MenuItem key={c.key()} value={c.key()}>
|
|
{c.name()}
|
|
</MenuItem>
|
|
);
|
|
})}
|
|
</Select>
|
|
);
|
|
};
|
|
|
|
const tempSelector = () => {
|
|
return (
|
|
<Select
|
|
id="tempSelect"
|
|
variant="standard"
|
|
value={tempKey}
|
|
style={{ fontSize: 8 }}
|
|
onChange={e => {
|
|
gateComponentUpdate(
|
|
e.target.value as string,
|
|
pond.GateComponentType.GATE_COMPONENT_TYPE_TEMP
|
|
);
|
|
setTempKey(e.target.value as string);
|
|
if (pressureKey === e.target.value) {
|
|
setPressureKey("");
|
|
}
|
|
if (ambientKey === e.target.value) {
|
|
setAmbientKey("");
|
|
}
|
|
}}
|
|
displayEmpty>
|
|
<MenuItem value="">
|
|
<em>Select Temperature Chain</em>
|
|
</MenuItem>
|
|
{Array.from(componentOptions.values()).map(c => {
|
|
return (
|
|
<MenuItem key={c.key()} value={c.key()}>
|
|
{c.name()}
|
|
</MenuItem>
|
|
);
|
|
})}
|
|
</Select>
|
|
);
|
|
};
|
|
|
|
const pressureSelector = () => {
|
|
return (
|
|
<Select
|
|
id="pressureSelect"
|
|
variant="standard"
|
|
value={pressureKey}
|
|
style={{ fontSize: 8 }}
|
|
onChange={e => {
|
|
gateComponentUpdate(
|
|
e.target.value as string,
|
|
pond.GateComponentType.GATE_COMPONENT_TYPE_PRESSURE
|
|
);
|
|
setPressureKey(e.target.value as string);
|
|
if (tempKey === e.target.value) {
|
|
setTempKey("");
|
|
}
|
|
if (ambientKey === e.target.value) {
|
|
setAmbientKey("");
|
|
}
|
|
}}
|
|
displayEmpty>
|
|
<MenuItem value="">
|
|
<em>Select Pressure Chain</em>
|
|
</MenuItem>
|
|
{Array.from(componentOptions.values()).map(c => {
|
|
return (
|
|
<MenuItem key={c.key()} value={c.key()}>
|
|
{c.name()}
|
|
</MenuItem>
|
|
);
|
|
})}
|
|
</Select>
|
|
);
|
|
};
|
|
|
|
return (
|
|
<Grid
|
|
container
|
|
// direction={(isMobile) ? "column" : "row"}
|
|
width="100%"
|
|
//alignItems="center"
|
|
>
|
|
<Grid width={"100%"} size={{ sm: 12, lg: isMobile || drawerView ? 12 : 4}} style={{ padding: 10 }}>
|
|
<Box
|
|
display="flex"
|
|
justifyContent="space-between"
|
|
alignItems="center"
|
|
marginBottom={2}>
|
|
<Typography style={{ fontWeight: 650, fontSize: 20 }}>{device.name()}</Typography>
|
|
<ButtonGroup
|
|
toggle
|
|
buttons={[
|
|
{
|
|
title: "Analysis",
|
|
function: () => setDetail("analytics")
|
|
},
|
|
{
|
|
title: "Sensors",
|
|
function: () => setDetail("sensors")
|
|
}
|
|
]}
|
|
/>
|
|
</Box>
|
|
<Card>
|
|
<GateSVG
|
|
finalTemp={
|
|
gate.gateMutations[device.id().toString()] &&
|
|
!isNaN(gate.gateMutations[device.id().toString()].temp)
|
|
? gate.gateMutations[device.id().toString()].temp
|
|
: 0
|
|
}
|
|
ambientTemp={lastAmbient}
|
|
//innerTemps={lastTemps}
|
|
//innerPressures={lastPressures}
|
|
ductTemp={ductTemp}
|
|
ductPressure={ductPressure}
|
|
ambientSelector={ambientSelector}
|
|
tempChainSelector={tempSelector}
|
|
pressureChainSelector={pressureSelector}
|
|
pcaState={gate.status.pcaState}
|
|
// pcaFanState={pcaFanOn}
|
|
checkInTime={device.status.lastActive}
|
|
/>
|
|
<Button
|
|
variant="contained"
|
|
color="primary"
|
|
fullWidth
|
|
onClick={() => {
|
|
setInteractionDialog(true);
|
|
}}>
|
|
Set Interactions
|
|
</Button>
|
|
</Card>
|
|
<GateDeviceInteraction
|
|
open={interactionDialog}
|
|
gate={gate}
|
|
compDevice={comprehensiveDevice}
|
|
densityTemp={densityTemp}
|
|
close={canceled => {
|
|
setInteractionDialog(false);
|
|
}}
|
|
/>
|
|
</Grid>
|
|
<Grid size={{ sm: 12, lg: isMobile || drawerView ? 12 : 8}} style={{ padding: 10 }}>
|
|
<GateGraphs
|
|
gate={gate}
|
|
display={detail}
|
|
compMap={componentOptions}
|
|
ambient={ambientKey}
|
|
pressure={pressureKey}
|
|
tempChain={tempKey}
|
|
redKey={redLightKey}
|
|
greenKey={greenLightKey}
|
|
device={device.id()}
|
|
/>
|
|
</Grid>
|
|
</Grid>
|
|
);
|
|
}
|