Merge branch 'dev_environment' into staging_environment
This commit is contained in:
commit
1c41157281
11 changed files with 486 additions and 364 deletions
|
|
@ -419,16 +419,12 @@ export default function BinCard(props: Props) {
|
||||||
Math.round(current * 35.239).toLocaleString() +
|
Math.round(current * 35.239).toLocaleString() +
|
||||||
"/" +
|
"/" +
|
||||||
Math.round(capacity * 35.239).toLocaleString() +
|
Math.round(capacity * 35.239).toLocaleString() +
|
||||||
(lidarBushels ? "(" + Math.round(lidarBushels * 35.239).toLocaleString() + " est)" : "") +
|
|
||||||
" L"
|
" L"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT && bin.bushelsPerTonne() > 1) {
|
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT && bin.bushelsPerTonne() > 1) {
|
||||||
return (
|
return (
|
||||||
bin.grainTonnes().toLocaleString() +
|
bin.grainTonnes().toLocaleString() +
|
||||||
(lidarBushels
|
|
||||||
? "(" + Math.round(lidarBushels / bin.bushelsPerTonne()).toLocaleString() + " est)"
|
|
||||||
: "") +
|
|
||||||
" mT " +
|
" mT " +
|
||||||
bin.fillPercent() +
|
bin.fillPercent() +
|
||||||
"%"
|
"%"
|
||||||
|
|
@ -438,7 +434,6 @@ export default function BinCard(props: Props) {
|
||||||
current.toLocaleString() +
|
current.toLocaleString() +
|
||||||
"/" +
|
"/" +
|
||||||
capacity.toLocaleString() +
|
capacity.toLocaleString() +
|
||||||
(lidarBushels ? "(" + lidarBushels.toLocaleString() + " est)" : "") +
|
|
||||||
" bu"
|
" bu"
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
@ -469,10 +464,10 @@ export default function BinCard(props: Props) {
|
||||||
|
|
||||||
const info = () => {
|
const info = () => {
|
||||||
const inv = bin.settings.inventory;
|
const inv = bin.settings.inventory;
|
||||||
let bushelAmount = inv?.grainBushels;
|
let bushelAmount = bin.bushels();
|
||||||
let bushelCapacity = bin.settings.specs?.bushelCapacity;
|
let bushelCapacity = bin.settings.specs?.bushelCapacity;
|
||||||
const empty =
|
const empty =
|
||||||
!inv || inv.empty || !bushelCapacity || bushelCapacity <= 0 || inv.grainBushels <= 0;
|
!inv || inv.empty || !bushelCapacity || bushelCapacity <= 0 || bushelAmount <= 0;
|
||||||
return (
|
return (
|
||||||
<Box width={1} marginTop={0}>
|
<Box width={1} marginTop={0}>
|
||||||
<Typography align="center" color="textSecondary" noWrap style={{ fontSize: "0.65rem" }}>
|
<Typography align="center" color="textSecondary" noWrap style={{ fontSize: "0.65rem" }}>
|
||||||
|
|
|
||||||
|
|
@ -362,95 +362,95 @@ export default function BinVisualizer(props: Props) {
|
||||||
let trendCables = cables;
|
let trendCables = cables;
|
||||||
if (bin.key() !== "" && !loadingTrend) {
|
if (bin.key() !== "" && !loadingTrend) {
|
||||||
setLoadingTrend(true);
|
setLoadingTrend(true);
|
||||||
// binAPI
|
binAPI
|
||||||
// .getBinsTrendData([bin.key()], 7)
|
.getBinsTrendData([bin.key()], 7)
|
||||||
// .then(resp => {
|
.then(resp => {
|
||||||
// let binTrend = resp.data.trendData[bin.key()];
|
let binTrend = resp.data.trendData[bin.key()];
|
||||||
// //the variables to use to build the average conditions
|
//the variables to use to build the average conditions
|
||||||
// let temps: number[] = [];
|
let temps: number[] = [];
|
||||||
// let humids: number[] = [];
|
let humids: number[] = [];
|
||||||
// let emcs: number[] = [];
|
let emcs: number[] = [];
|
||||||
// let tempTrends: number[] = [];
|
let tempTrends: number[] = [];
|
||||||
// let humidTrends: number[] = [];
|
let humidTrends: number[] = [];
|
||||||
// let emcTrends: number[] = [];
|
let emcTrends: number[] = [];
|
||||||
|
|
||||||
// let lowNodeConditions: GrainConditions | undefined = undefined;
|
let lowNodeConditions: GrainConditions | undefined = undefined;
|
||||||
// let highNodeConditions: GrainConditions | undefined = undefined;
|
let highNodeConditions: GrainConditions | undefined = undefined;
|
||||||
// let avgConditions: GrainConditions | undefined = undefined;
|
let avgConditions: GrainConditions | undefined = undefined;
|
||||||
// trendCables.forEach(cable => {
|
trendCables.forEach(cable => {
|
||||||
// //only use the values below the top node
|
//only use the values below the top node
|
||||||
// //because splice mutates the original array make a clone in the cables so the svg still has all of them for display
|
//because splice mutates the original array make a clone in the cables so the svg still has all of them for display
|
||||||
// //also reverse it so that the node 1 (end of the cable) is in the first position
|
//also reverse it so that the node 1 (end of the cable) is in the first position
|
||||||
// let tempClone = cloneDeep(cable.temperatures).reverse();
|
let tempClone = cloneDeep(cable.temperatures).reverse();
|
||||||
// let humClone = cloneDeep(cable.humidities).reverse();
|
let humClone = cloneDeep(cable.humidities).reverse();
|
||||||
// let emcClone = cloneDeep(cable.grainMoistures).reverse();
|
let emcClone = cloneDeep(cable.grainMoistures).reverse();
|
||||||
// //add the cable data to the proper arrays
|
//add the cable data to the proper arrays
|
||||||
// if (cable.topNode > 0) {
|
if (cable.topNode > 0) {
|
||||||
// temps.push(...tempClone.splice(0, cable.topNode));
|
temps.push(...tempClone.splice(0, cable.topNode));
|
||||||
// humids.push(...humClone.splice(0, cable.topNode));
|
humids.push(...humClone.splice(0, cable.topNode));
|
||||||
// emcs.push(...emcClone.splice(0, cable.topNode));
|
emcs.push(...emcClone.splice(0, cable.topNode));
|
||||||
// } else {
|
} else {
|
||||||
// //if the cable has no fill set (top node) then use all of the nodes
|
//if the cable has no fill set (top node) then use all of the nodes
|
||||||
// temps = tempClone;
|
temps = tempClone;
|
||||||
// humids = humClone;
|
humids = humClone;
|
||||||
// emcs = emcClone;
|
emcs = emcClone;
|
||||||
// }
|
}
|
||||||
// //add the trend data to the proper arrays if the top node is set
|
//add the trend data to the proper arrays if the top node is set
|
||||||
// let cableTrendData = binTrend.cableTrend[cable.key()];
|
let cableTrendData = binTrend.cableTrend[cable.key()];
|
||||||
// tempTrends.push(cableTrendData.grainCelciusTrend);
|
tempTrends.push(cableTrendData.grainCelciusTrend);
|
||||||
// humidTrends.push(cableTrendData.grainHumidityTrend);
|
humidTrends.push(cableTrendData.grainHumidityTrend);
|
||||||
// emcTrends.push(cableTrendData.grainEmcTrend);
|
emcTrends.push(cableTrendData.grainEmcTrend);
|
||||||
|
|
||||||
// //if the lowest temp for this cable is less than the temp in the low node conditions or the low node conditions are not set
|
//if the lowest temp for this cable is less than the temp in the low node conditions or the low node conditions are not set
|
||||||
// //use this cables lowest node and trend data in the condition
|
//use this cables lowest node and trend data in the condition
|
||||||
// if (!lowNodeConditions || Math.min(...temps) < lowNodeConditions.tempC) {
|
if (!lowNodeConditions || Math.min(...temps) < lowNodeConditions.tempC) {
|
||||||
// //determine which node is the coldest so that the data displayed is for the same node
|
//determine which node is the coldest so that the data displayed is for the same node
|
||||||
// let lowTempIndex =
|
let lowTempIndex =
|
||||||
// temps.indexOf(Math.min(...temps)) === -1 ? 0 : temps.indexOf(Math.min(...temps));
|
temps.indexOf(Math.min(...temps)) === -1 ? 0 : temps.indexOf(Math.min(...temps));
|
||||||
// lowNodeConditions = {
|
lowNodeConditions = {
|
||||||
// tempC: temps[lowTempIndex],
|
tempC: temps[lowTempIndex],
|
||||||
// humidity: humids[lowTempIndex],
|
humidity: humids[lowTempIndex],
|
||||||
// emc: emcs[lowTempIndex],
|
emc: emcs[lowTempIndex],
|
||||||
// tempCTrend: cableTrendData.coldNodeTrend?.tempTrend ?? 0,
|
tempCTrend: cableTrendData.coldNodeTrend?.tempTrend ?? 0,
|
||||||
// humidityTrend: cableTrendData.coldNodeTrend?.humidityTrend ?? 0,
|
humidityTrend: cableTrendData.coldNodeTrend?.humidityTrend ?? 0,
|
||||||
// emcTrend: cableTrendData.coldNodeTrend?.emcTrend ?? 0
|
emcTrend: cableTrendData.coldNodeTrend?.emcTrend ?? 0
|
||||||
// };
|
};
|
||||||
// }
|
}
|
||||||
|
|
||||||
// //do the same for the high node
|
//do the same for the high node
|
||||||
// if (!highNodeConditions || cable.maxTemp() > highNodeConditions.tempC) {
|
if (!highNodeConditions || cable.maxTemp() > highNodeConditions.tempC) {
|
||||||
// let highTempIndex =
|
let highTempIndex =
|
||||||
// temps.indexOf(Math.max(...temps)) === -1 ? 0 : temps.indexOf(Math.max(...temps));
|
temps.indexOf(Math.max(...temps)) === -1 ? 0 : temps.indexOf(Math.max(...temps));
|
||||||
// highNodeConditions = {
|
highNodeConditions = {
|
||||||
// tempC: temps[highTempIndex],
|
tempC: temps[highTempIndex],
|
||||||
// humidity: humids[highTempIndex],
|
humidity: humids[highTempIndex],
|
||||||
// emc: emcs[highTempIndex],
|
emc: emcs[highTempIndex],
|
||||||
// tempCTrend: cableTrendData.hotNodeTrend?.tempTrend ?? 0,
|
tempCTrend: cableTrendData.hotNodeTrend?.tempTrend ?? 0,
|
||||||
// humidityTrend: cableTrendData.hotNodeTrend?.humidityTrend ?? 0,
|
humidityTrend: cableTrendData.hotNodeTrend?.humidityTrend ?? 0,
|
||||||
// emcTrend: cableTrendData.hotNodeTrend?.emcTrend ?? 0
|
emcTrend: cableTrendData.hotNodeTrend?.emcTrend ?? 0
|
||||||
// };
|
};
|
||||||
// }
|
}
|
||||||
// });
|
});
|
||||||
// //set the average conditions
|
//set the average conditions
|
||||||
// avgConditions = {
|
avgConditions = {
|
||||||
// tempC: average(temps),
|
tempC: average(temps),
|
||||||
// humidity: average(humids),
|
humidity: average(humids),
|
||||||
// emc: average(emcs),
|
emc: average(emcs),
|
||||||
// tempCTrend: average(tempTrends),
|
tempCTrend: average(tempTrends),
|
||||||
// humidityTrend: average(humidTrends),
|
humidityTrend: average(humidTrends),
|
||||||
// emcTrend: average(emcTrends)
|
emcTrend: average(emcTrends)
|
||||||
// };
|
};
|
||||||
// setAverageConditions(avgConditions);
|
setAverageConditions(avgConditions);
|
||||||
// setLowNodeConditions(lowNodeConditions);
|
setLowNodeConditions(lowNodeConditions);
|
||||||
// setHighNodeConditions(highNodeConditions);
|
setHighNodeConditions(highNodeConditions);
|
||||||
// })
|
})
|
||||||
// .catch(err => {
|
.catch(err => {
|
||||||
// console.log(err);
|
console.log(err);
|
||||||
// openSnack("Failed to retrieve trend data");
|
openSnack("Failed to retrieve trend data");
|
||||||
// })
|
})
|
||||||
// .finally(() => {
|
.finally(() => {
|
||||||
// setLoadingTrend(false);
|
setLoadingTrend(false);
|
||||||
// });
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [binAPI, bin, cables, openSnack]); //eslint-disable-line react-hooks/exhaustive-deps
|
}, [binAPI, bin, cables, openSnack]); //eslint-disable-line react-hooks/exhaustive-deps
|
||||||
|
|
@ -485,7 +485,7 @@ export default function BinVisualizer(props: Props) {
|
||||||
if (bin.settings.inventory && bin.settings.specs) {
|
if (bin.settings.inventory && bin.settings.specs) {
|
||||||
const isEmpty = bin.settings.inventory?.empty === true;
|
const isEmpty = bin.settings.inventory?.empty === true;
|
||||||
const capacity = bin.settings.specs.bushelCapacity;
|
const capacity = bin.settings.specs.bushelCapacity;
|
||||||
const grainBushels = bin.settings.inventory.grainBushels;
|
const grainBushels = bin.bushels();
|
||||||
setSliderCoulour("gold");
|
setSliderCoulour("gold");
|
||||||
if (!capacity) {
|
if (!capacity) {
|
||||||
setFillPercentage(null);
|
setFillPercentage(null);
|
||||||
|
|
@ -535,7 +535,7 @@ export default function BinVisualizer(props: Props) {
|
||||||
|
|
||||||
const inventoryOverview = () => {
|
const inventoryOverview = () => {
|
||||||
const capacity = bin.settings.specs?.bushelCapacity ?? 0;
|
const capacity = bin.settings.specs?.bushelCapacity ?? 0;
|
||||||
const grainBushels = bin.settings.inventory?.grainBushels ?? 0;
|
const grainBushels = bin.bushels();
|
||||||
const isEmpty = bin.settings.inventory?.empty === true || !grainBushels || grainBushels <= 0;
|
const isEmpty = bin.settings.inventory?.empty === true || !grainBushels || grainBushels <= 0;
|
||||||
const grainType = bin.settings.inventory?.grainType;
|
const grainType = bin.settings.inventory?.grainType;
|
||||||
const grainTypeName = isEmpty || !grainType ? "" : GrainDescriber(grainType).name;
|
const grainTypeName = isEmpty || !grainType ? "" : GrainDescriber(grainType).name;
|
||||||
|
|
@ -1481,9 +1481,7 @@ export default function BinVisualizer(props: Props) {
|
||||||
onChange={(_, value) => {
|
onChange={(_, value) => {
|
||||||
setFillPercentage(value as number);
|
setFillPercentage(value as number);
|
||||||
const capacity = bin.settings.specs ? bin.settings.specs.bushelCapacity : 0;
|
const capacity = bin.settings.specs ? bin.settings.specs.bushelCapacity : 0;
|
||||||
const current = bin.settings.inventory
|
const current = bin.bushels()
|
||||||
? bin.settings.inventory.grainBushels
|
|
||||||
: 0;
|
|
||||||
let grainAmount = ((value as number) / 100) * capacity;
|
let grainAmount = ((value as number) / 100) * capacity;
|
||||||
|
|
||||||
if (grainAmount < current) {
|
if (grainAmount < current) {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import {
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
Divider,
|
Divider,
|
||||||
Grid2,
|
Grid2,
|
||||||
|
IconButton,
|
||||||
lighten,
|
lighten,
|
||||||
List,
|
List,
|
||||||
ListItem,
|
ListItem,
|
||||||
|
|
@ -36,12 +37,23 @@ import { useGlobalState } from "providers";
|
||||||
import React, { useCallback, useEffect, useState } from "react";
|
import React, { useCallback, useEffect, useState } from "react";
|
||||||
import RemoveGroup from "./RemoveGroup";
|
import RemoveGroup from "./RemoveGroup";
|
||||||
import { pond } from "protobuf-ts/pond";
|
import { pond } from "protobuf-ts/pond";
|
||||||
|
import { Add, Remove } from "@mui/icons-material";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) => {
|
const useStyles = makeStyles((theme: Theme) => {
|
||||||
return ({
|
return ({
|
||||||
deviceListContainer: {
|
deviceListContainer: {
|
||||||
marginBottom: theme.spacing(1)
|
marginBottom: theme.spacing(1)
|
||||||
},
|
},
|
||||||
|
listTitle: {
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: 650
|
||||||
|
},
|
||||||
|
listButton: {
|
||||||
|
cursor: "pointer",
|
||||||
|
"&:hover": {
|
||||||
|
backgroundColor: lighten(theme.palette.background.default, 0.25)
|
||||||
|
}
|
||||||
|
},
|
||||||
devicesList: {
|
devicesList: {
|
||||||
overflow: "auto",
|
overflow: "auto",
|
||||||
minHeight: "25vh",
|
minHeight: "25vh",
|
||||||
|
|
@ -87,6 +99,7 @@ export default function GroupSettings(props: Props) {
|
||||||
const deviceAPI = useDeviceAPI();
|
const deviceAPI = useDeviceAPI();
|
||||||
const snackbar = useSnackbar()
|
const snackbar = useSnackbar()
|
||||||
const [devices, setDevices] = useState<Device[]>([]);
|
const [devices, setDevices] = useState<Device[]>([]);
|
||||||
|
const [nonGroupDevices, setNonGroupDevices] = useState<Device[]>([]);
|
||||||
const [group, setGroup] = useState<Group>(initialGroup ? Group.clone(initialGroup) : new Group());
|
const [group, setGroup] = useState<Group>(initialGroup ? Group.clone(initialGroup) : new Group());
|
||||||
const [isRemoveGroupOpen, setIsRemoveGroupOpen] = useState<boolean>(
|
const [isRemoveGroupOpen, setIsRemoveGroupOpen] = useState<boolean>(
|
||||||
mode === "remove" ? true : false
|
mode === "remove" ? true : false
|
||||||
|
|
@ -109,13 +122,14 @@ export default function GroupSettings(props: Props) {
|
||||||
|
|
||||||
const loadDevices = useCallback(() => {
|
const loadDevices = useCallback(() => {
|
||||||
setLoadingDevices(true);
|
setLoadingDevices(true);
|
||||||
|
//this lists the devices for the user/team viewing
|
||||||
deviceAPI
|
deviceAPI
|
||||||
.list(1000000, 0, "asc")
|
.list(1000000, 0, "asc")
|
||||||
.then((response: any) => {
|
.then((response: any) => {
|
||||||
let rDevices: Device[] = response.data.devices
|
let rDevices: Device[] = response.data.devices
|
||||||
? response.data.devices.map((device: any) => Device.any(device))
|
? response.data.devices.map((device: any) => Device.any(device))
|
||||||
: [];
|
: [];
|
||||||
|
//remove duplicates from the options
|
||||||
setDevices(rDevices);
|
setDevices(rDevices);
|
||||||
})
|
})
|
||||||
.catch((_error: any) => {
|
.catch((_error: any) => {
|
||||||
|
|
@ -124,6 +138,16 @@ export default function GroupSettings(props: Props) {
|
||||||
.finally(() => setLoadingDevices(false));
|
.finally(() => setLoadingDevices(false));
|
||||||
}, [deviceAPI, as]);
|
}, [deviceAPI, as]);
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
let ungrouped: Device[] = []
|
||||||
|
devices.forEach(device => {
|
||||||
|
if(!groupDeviceNumbers.includes(device.id())){
|
||||||
|
ungrouped.push(device)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
setNonGroupDevices(ungrouped)
|
||||||
|
},[groupDeviceNumbers, devices])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (prevInitialGroup !== initialGroup) {
|
if (prevInitialGroup !== initialGroup) {
|
||||||
setGroup(initialGroup ? Group.clone(initialGroup) : new Group());
|
setGroup(initialGroup ? Group.clone(initialGroup) : new Group());
|
||||||
|
|
@ -317,27 +341,58 @@ export default function GroupSettings(props: Props) {
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</List>
|
</List>
|
||||||
) : (
|
) : (
|
||||||
<List dense className={classes.devicesList}>
|
<React.Fragment>
|
||||||
{filterDevices(deviceSearch, devices, [])
|
{groupDevices &&
|
||||||
.sort((a, b: Device) => a.name().localeCompare(b.name()))
|
<List dense className={classes.devicesList}>
|
||||||
.map(device => {
|
{filterDevices(deviceSearch, groupDevices, [])
|
||||||
const label = `checkbox-list-secondary-label-${device.id()}`;
|
.sort((a, b: Device) => a.name().localeCompare(b.name()))
|
||||||
return (
|
.map(device => {
|
||||||
<ListItem key={device.id()} onClick={() => changeDevices(device.id())}>
|
const label = `checkbox-list-secondary-label-${device.id()}`;
|
||||||
<ListItemText id={label} primary={device.name()} />
|
return (
|
||||||
<ListItemSecondaryAction>
|
<ListItem className={classes.listButton} key={device.id()} onClick={() => {
|
||||||
<Checkbox
|
removeDevice(device.id())
|
||||||
edge="end"
|
}}>
|
||||||
onChange={() => changeDevices(device.id())}
|
<ListItemText id={label} primary={device.name()} />
|
||||||
checked={group.settings.devices.includes(device.id())}
|
<ListItemSecondaryAction>
|
||||||
inputProps={{ "aria-labelledby": label }}
|
{/* <Checkbox
|
||||||
disabled={!canEdit}
|
edge="end"
|
||||||
/>
|
onChange={() => changeDevices(device.id())}
|
||||||
</ListItemSecondaryAction>
|
checked={group.settings.devices.includes(device.id())}
|
||||||
</ListItem>
|
inputProps={{ "aria-labelledby": label }}
|
||||||
);
|
disabled={!canEdit}
|
||||||
})}
|
/> */}
|
||||||
</List>
|
-
|
||||||
|
</ListItemSecondaryAction>
|
||||||
|
</ListItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</List>
|
||||||
|
}
|
||||||
|
<List dense className={classes.devicesList}>
|
||||||
|
{filterDevices(deviceSearch, nonGroupDevices, [])
|
||||||
|
.sort((a, b: Device) => a.name().localeCompare(b.name()))
|
||||||
|
.map(device => {
|
||||||
|
const label = `checkbox-list-secondary-label-${device.id()}`;
|
||||||
|
return (
|
||||||
|
<ListItem className={classes.listButton} key={device.id()} onClick={() => {
|
||||||
|
addDevice(device.id())
|
||||||
|
}}>
|
||||||
|
<ListItemText id={label} primary={device.name()} />
|
||||||
|
<ListItemSecondaryAction>
|
||||||
|
{/* <Checkbox
|
||||||
|
edge="end"
|
||||||
|
onChange={() => changeDevices(device.id())}
|
||||||
|
checked={group.settings.devices.includes(device.id())}
|
||||||
|
inputProps={{ "aria-labelledby": label }}
|
||||||
|
disabled={!canEdit}
|
||||||
|
/> */}
|
||||||
|
+
|
||||||
|
</ListItemSecondaryAction>
|
||||||
|
</ListItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</List>
|
||||||
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
</Paper>
|
</Paper>
|
||||||
);
|
);
|
||||||
|
|
@ -383,16 +438,49 @@ export default function GroupSettings(props: Props) {
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</List>
|
</List>
|
||||||
) : (
|
) : (
|
||||||
|
<React.Fragment>
|
||||||
|
{groupDevices &&
|
||||||
|
<React.Fragment>
|
||||||
|
<Typography className={classes.listTitle}>Grouped Devices</Typography>
|
||||||
|
<List dense className={classes.devicesList}>
|
||||||
|
{filterDevices(deviceSearch, groupDevices, [])
|
||||||
|
.sort((a, b: Device) => a.name().localeCompare(b.name()))
|
||||||
|
.map(device => {
|
||||||
|
const label = `checkbox-list-secondary-label-${device.id()}`;
|
||||||
|
return (
|
||||||
|
<ListItem className={classes.listButton} key={device.id()} onClick={() => {
|
||||||
|
removeDevice(device.id())
|
||||||
|
}}>
|
||||||
|
<ListItemText id={label} primary={device.name()} />
|
||||||
|
<ListItemSecondaryAction>
|
||||||
|
{/* <Checkbox
|
||||||
|
edge="end"
|
||||||
|
onChange={() => changeDevices(device.id())}
|
||||||
|
checked={group.settings.devices.includes(device.id())}
|
||||||
|
inputProps={{ "aria-labelledby": label }}
|
||||||
|
disabled={!canEdit}
|
||||||
|
/> */}
|
||||||
|
<Remove />
|
||||||
|
</ListItemSecondaryAction>
|
||||||
|
</ListItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</List>
|
||||||
|
</React.Fragment>
|
||||||
|
}
|
||||||
|
<Typography className={classes.listTitle}>Devices You Can Add</Typography>
|
||||||
<List dense className={classes.devicesList}>
|
<List dense className={classes.devicesList}>
|
||||||
{filterDevices(deviceSearch, devices, [])
|
{filterDevices(deviceSearch, nonGroupDevices, [])
|
||||||
.sort((a, b: Device) => a.name().localeCompare(b.name()))
|
.sort((a, b: Device) => a.name().localeCompare(b.name()))
|
||||||
.map(device => {
|
.map(device => {
|
||||||
const label = `checkbox-list-secondary-label-${device.id()}`;
|
const label = `checkbox-list-secondary-label-${device.id()}`;
|
||||||
return (
|
return (
|
||||||
<ListItem key={device.id()} onClick={() => changeDevices(device.id())}>
|
<ListItem className={classes.listButton} key={device.id()} onClick={() => {
|
||||||
|
addDevice(device.id())
|
||||||
|
}}>
|
||||||
<ListItemText id={label} primary={device.name()} />
|
<ListItemText id={label} primary={device.name()} />
|
||||||
<ListItemSecondaryAction>
|
<ListItemSecondaryAction>
|
||||||
<Checkbox
|
{/* <Checkbox
|
||||||
edge="end"
|
edge="end"
|
||||||
onChange={(_, checked) => {
|
onChange={(_, checked) => {
|
||||||
if (checked) addDevice(device.id());
|
if (checked) addDevice(device.id());
|
||||||
|
|
@ -402,12 +490,14 @@ export default function GroupSettings(props: Props) {
|
||||||
checked={groupDeviceNumbers.includes(device.id())}
|
checked={groupDeviceNumbers.includes(device.id())}
|
||||||
inputProps={{ "aria-labelledby": label }}
|
inputProps={{ "aria-labelledby": label }}
|
||||||
disabled={!canEdit}
|
disabled={!canEdit}
|
||||||
/>
|
/> */}
|
||||||
|
<Add />
|
||||||
</ListItemSecondaryAction>
|
</ListItemSecondaryAction>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</List>
|
</List>
|
||||||
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
</Paper>
|
</Paper>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -185,6 +185,8 @@ import { Result } from "@mapbox/mapbox-gl-geocoder";
|
||||||
const [measurement, setMeasurement] = useState(false);
|
const [measurement, setMeasurement] = useState(false);
|
||||||
const [measurementData, setMeasurementData] = useState<Map<string, MeasurementData>>(new Map());
|
const [measurementData, setMeasurementData] = useState<Map<string, MeasurementData>>(new Map());
|
||||||
const measurementRef = useRef(measurementData);
|
const measurementRef = useRef(measurementData);
|
||||||
|
const zoomRef = useRef(15)
|
||||||
|
const fieldMarkerZoom = 15
|
||||||
|
|
||||||
//watches for changes to the viewing as and sets the load boolean to trigger a load
|
//watches for changes to the viewing as and sets the load boolean to trigger a load
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -591,12 +593,13 @@ import { Result } from "@mapbox/mapbox-gl-geocoder";
|
||||||
}
|
}
|
||||||
let newFM = fieldMarkers.get(newKey);
|
let newFM = fieldMarkers.get(newKey);
|
||||||
if (newFM) {
|
if (newFM) {
|
||||||
setCurrentView({
|
let view = {
|
||||||
latitude: newFM.lat(),
|
latitude: newFM.lat(),
|
||||||
longitude: newFM.long(),
|
longitude: newFM.long(),
|
||||||
zoom: 12,
|
zoom: currentView.zoom,
|
||||||
transitionDuration: 1000
|
transitionDuration: 1000
|
||||||
});
|
}
|
||||||
|
setCurrentView(view);
|
||||||
}
|
}
|
||||||
setObjectKey(newKey);
|
setObjectKey(newKey);
|
||||||
setFMIndexKey(newID);
|
setFMIndexKey(newID);
|
||||||
|
|
@ -621,12 +624,13 @@ import { Result } from "@mapbox/mapbox-gl-geocoder";
|
||||||
}
|
}
|
||||||
let newFM = fieldMarkers.get(newKey);
|
let newFM = fieldMarkers.get(newKey);
|
||||||
if (newFM) {
|
if (newFM) {
|
||||||
setCurrentView({
|
let view = {
|
||||||
latitude: newFM.lat(),
|
latitude: newFM.lat(),
|
||||||
longitude: newFM.long(),
|
longitude: newFM.long(),
|
||||||
zoom: 12,
|
zoom: currentView.zoom,
|
||||||
transitionDuration: 1000
|
transitionDuration: 1000
|
||||||
});
|
}
|
||||||
|
setCurrentView(view);
|
||||||
}
|
}
|
||||||
setObjectKey(newKey);
|
setObjectKey(newKey);
|
||||||
setFMIndexKey(newID);
|
setFMIndexKey(newID);
|
||||||
|
|
@ -728,13 +732,14 @@ import { Result } from "@mapbox/mapbox-gl-geocoder";
|
||||||
subtype: fm.type(),
|
subtype: fm.type(),
|
||||||
mini: true,
|
mini: true,
|
||||||
clickFunc: (event, index) => {
|
clickFunc: (event, index) => {
|
||||||
|
console.log(zoomRef)
|
||||||
clickDelay();
|
clickDelay();
|
||||||
closeDrawers();
|
closeDrawers();
|
||||||
setIgnoreFeatures(true);
|
setIgnoreFeatures(true);
|
||||||
setCurrentView({
|
setCurrentView({
|
||||||
latitude: fm.lat(),
|
latitude: fm.lat(),
|
||||||
longitude: fm.long(),
|
longitude: fm.long(),
|
||||||
zoom: 12,
|
zoom: zoomRef.current,
|
||||||
transitionDuration: 0
|
transitionDuration: 0
|
||||||
//transitionInterpolator: new FlyToInterpolator()
|
//transitionInterpolator: new FlyToInterpolator()
|
||||||
});
|
});
|
||||||
|
|
@ -1115,14 +1120,16 @@ import { Result } from "@mapbox/mapbox-gl-geocoder";
|
||||||
let xOff = !mobileOffset ? -250 : undefined;
|
let xOff = !mobileOffset ? -250 : undefined;
|
||||||
let yOff = mobileOffset ? -150 : undefined;
|
let yOff = mobileOffset ? -150 : undefined;
|
||||||
|
|
||||||
setCurrentView({
|
let view = {
|
||||||
latitude: lat,
|
latitude: lat,
|
||||||
longitude: long,
|
longitude: long,
|
||||||
zoom: zoom,
|
zoom: zoom,
|
||||||
transitionDuration: transDuration,
|
transitionDuration: transDuration,
|
||||||
xOffset: center ? 0 : xOff,
|
xOffset: center ? 0 : xOff,
|
||||||
yOffset: center ? 0 : yOff
|
yOffset: center ? 0 : yOff
|
||||||
});
|
}
|
||||||
|
setCurrentView(view);
|
||||||
|
zoomRef.current = zoom
|
||||||
};
|
};
|
||||||
|
|
||||||
const markerDialog = () => {
|
const markerDialog = () => {
|
||||||
|
|
|
||||||
|
|
@ -125,11 +125,23 @@ export class Bin {
|
||||||
return colour;
|
return colour;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bushels(): number {
|
||||||
|
let bushels = this.settings.inventory?.grainBushels || 0
|
||||||
|
if (this.settings.inventory?.inventoryControl === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_AUTOMATIC_LIDAR){
|
||||||
|
bushels = this.status.grainBushels
|
||||||
|
}
|
||||||
|
return bushels
|
||||||
|
}
|
||||||
|
|
||||||
public fillPercent(): number {
|
public fillPercent(): number {
|
||||||
let fill = 0;
|
let fill = 0;
|
||||||
if (this.settings.inventory && this.settings.specs) {
|
if (this.settings.inventory && this.settings.specs) {
|
||||||
|
let bushels = this.settings.inventory.grainBushels
|
||||||
|
if (this.settings.inventory.inventoryControl === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_AUTOMATIC_LIDAR){
|
||||||
|
bushels = this.status.grainBushels
|
||||||
|
}
|
||||||
fill = Math.round(
|
fill = Math.round(
|
||||||
(this.settings.inventory.grainBushels / this.settings.specs.bushelCapacity) * 100
|
(bushels / this.settings.specs.bushelCapacity) * 100
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return fill;
|
return fill;
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,7 @@ export default function DevicePage() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
setDiagnosticComponents(diagComponents)
|
||||||
setComponents(rComponents)
|
setComponents(rComponents)
|
||||||
let interactions: Interaction[] = [];
|
let interactions: Interaction[] = [];
|
||||||
resp.data.interactions.forEach((interaction: pond.Interaction) => {
|
resp.data.interactions.forEach((interaction: pond.Interaction) => {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import {
|
import {
|
||||||
GraphComponent,
|
// GraphComponent,
|
||||||
GraphOrientation,
|
// GraphOrientation,
|
||||||
GraphPoint,
|
// GraphPoint,
|
||||||
GraphType,
|
GraphType,
|
||||||
InteractionLine
|
InteractionLine
|
||||||
} from "common/Graph";
|
} from "common/Graph";
|
||||||
|
|
@ -41,15 +41,15 @@ import {
|
||||||
Weight,
|
Weight,
|
||||||
CapacitorCable
|
CapacitorCable
|
||||||
} from "pbHelpers/ComponentTypes";
|
} from "pbHelpers/ComponentTypes";
|
||||||
import { multilineGrainCableData } from "pbHelpers/ComponentTypes/GrainCable";
|
//import { multilineGrainCableData } from "pbHelpers/ComponentTypes/GrainCable";
|
||||||
import { multilineCapCableData } from "./ComponentTypes/CapacitorCable";
|
//import { multilineCapCableData } from "./ComponentTypes/CapacitorCable";
|
||||||
import { findInteractionsAsSource } from "pbHelpers/Interaction";
|
import { findInteractionsAsSource } from "pbHelpers/Interaction";
|
||||||
import { pond } from "protobuf-ts/pond";
|
import { pond } from "protobuf-ts/pond";
|
||||||
import { quack } from "protobuf-ts/quack";
|
import { quack } from "protobuf-ts/quack";
|
||||||
|
|
||||||
import { notNull, or } from "utils/types";
|
import { notNull, or } from "utils/types";
|
||||||
import { emptyComponentId } from "./Component";
|
//import { emptyComponentId } from "./Component";
|
||||||
import { multilinePressureCableData } from "./ComponentTypes/PressureCable";
|
//import { multilinePressureCableData } from "./ComponentTypes/PressureCable";
|
||||||
import { describeMeasurement, MeasurementDescriber } from "./MeasurementDescriber";
|
import { describeMeasurement, MeasurementDescriber } from "./MeasurementDescriber";
|
||||||
import { convertedUnitMeasurement, MeasurementsFor, UnitMeasurement } from "models/UnitMeasurement";
|
import { convertedUnitMeasurement, MeasurementsFor, UnitMeasurement } from "models/UnitMeasurement";
|
||||||
import { Sen5x } from "./ComponentTypes/Sen5x";
|
import { Sen5x } from "./ComponentTypes/Sen5x";
|
||||||
|
|
@ -622,194 +622,194 @@ export function GetComponentIcon(
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: deprecated function, new graphs are handled in measurementChart (using reCharts instead of victory)
|
//TODO: deprecated function, new graphs are handled in measurementChart (using reCharts instead of victory)
|
||||||
export function getGraphProps(
|
// export function getGraphProps(
|
||||||
componentType: quack.ComponentType,
|
// componentType: quack.ComponentType,
|
||||||
subtype: number,
|
// subtype: number,
|
||||||
measurements: pond.Measurement[],
|
// measurements: pond.Measurement[],
|
||||||
interactions: Interaction[],
|
// interactions: Interaction[],
|
||||||
overlays: pond.ComponentOverlays[],
|
// overlays: pond.ComponentOverlays[],
|
||||||
orientation: GraphOrientation,
|
// orientation: GraphOrientation,
|
||||||
filters?: GraphFilters
|
// filters?: GraphFilters
|
||||||
): any {
|
// ): any {
|
||||||
const componentID: quack.IComponentID = quack.ComponentID.fromObject(
|
// const componentID: quack.IComponentID = quack.ComponentID.fromObject(
|
||||||
or(measurements[0].measurement, {
|
// or(measurements[0].measurement, {
|
||||||
id: emptyComponentId()
|
// id: emptyComponentId()
|
||||||
}).id as any
|
// }).id as any
|
||||||
);
|
// );
|
||||||
let graphProps = {
|
// let graphProps = {
|
||||||
orientation: orientation
|
// orientation: orientation
|
||||||
} as any;
|
// } as any;
|
||||||
let ext = extension(componentType, subtype);
|
// let ext = extension(componentType, subtype);
|
||||||
ext.measurements.forEach((componentMeasurement: ComponentMeasurement, index: number) => {
|
// ext.measurements.forEach((componentMeasurement: ComponentMeasurement, index: number) => {
|
||||||
let describer = describeMeasurement(
|
// let describer = describeMeasurement(
|
||||||
componentMeasurement.measurementType,
|
// componentMeasurement.measurementType,
|
||||||
componentType,
|
// componentType,
|
||||||
subtype
|
// subtype
|
||||||
);
|
// );
|
||||||
let range =
|
// let range =
|
||||||
filters && filters.ranges && filters.ranges[index] ? filters.ranges[index] : undefined;
|
// filters && filters.ranges && filters.ranges[index] ? filters.ranges[index] : undefined;
|
||||||
let selectedInteractions =
|
// let selectedInteractions =
|
||||||
filters && filters.selectedInteractions ? filters.selectedInteractions : [];
|
// filters && filters.selectedInteractions ? filters.selectedInteractions : [];
|
||||||
let interactionLines = getInteractionLines(
|
// let interactionLines = getInteractionLines(
|
||||||
componentType,
|
// componentType,
|
||||||
subtype,
|
// subtype,
|
||||||
componentMeasurement.measurementType,
|
// componentMeasurement.measurementType,
|
||||||
componentID,
|
// componentID,
|
||||||
interactions,
|
// interactions,
|
||||||
selectedInteractions
|
// selectedInteractions
|
||||||
);
|
// );
|
||||||
let selectedOverlays = filters?.selectedOverlays ?? [];
|
// let selectedOverlays = filters?.selectedOverlays ?? [];
|
||||||
let overlayAreas = getOverlayAreas(
|
// let overlayAreas = getOverlayAreas(
|
||||||
componentMeasurement.measurementType,
|
// componentMeasurement.measurementType,
|
||||||
overlays,
|
// overlays,
|
||||||
selectedOverlays
|
// selectedOverlays
|
||||||
);
|
// );
|
||||||
graphProps["graphComponent" + (index + 1).toString()] = {
|
// graphProps["graphComponent" + (index + 1).toString()] = {
|
||||||
label: componentMeasurement.label,
|
// label: componentMeasurement.label,
|
||||||
data: [],
|
// data: [],
|
||||||
tick: describer.unit(),
|
// tick: describer.unit(),
|
||||||
colour: componentMeasurement.colour,
|
// colour: componentMeasurement.colour,
|
||||||
type: componentMeasurement.graphType,
|
// type: componentMeasurement.graphType,
|
||||||
range: range,
|
// range: range,
|
||||||
isBoolean:
|
// isBoolean:
|
||||||
componentMeasurement.measurementType === quack.MeasurementType.MEASUREMENT_TYPE_BOOLEAN,
|
// componentMeasurement.measurementType === quack.MeasurementType.MEASUREMENT_TYPE_BOOLEAN,
|
||||||
isPercent:
|
// isPercent:
|
||||||
componentMeasurement.measurementType === quack.MeasurementType.MEASUREMENT_TYPE_PERCENT ||
|
// componentMeasurement.measurementType === quack.MeasurementType.MEASUREMENT_TYPE_PERCENT ||
|
||||||
(componentMeasurement.measurementType === quack.MeasurementType.MEASUREMENT_TYPE_ANALOG &&
|
// (componentMeasurement.measurementType === quack.MeasurementType.MEASUREMENT_TYPE_ANALOG &&
|
||||||
subtype === quack.AnalogInputSubtype.ANALOG_INPUT_SUBTYPE_FUEL),
|
// subtype === quack.AnalogInputSubtype.ANALOG_INPUT_SUBTYPE_FUEL),
|
||||||
interactionLines: interactionLines,
|
// interactionLines: interactionLines,
|
||||||
states: ext.states,
|
// states: ext.states,
|
||||||
decimals: describer.decimals(),
|
// decimals: describer.decimals(),
|
||||||
overlays: overlayAreas
|
// overlays: overlayAreas
|
||||||
} as GraphComponent;
|
// } as GraphComponent;
|
||||||
});
|
// });
|
||||||
|
|
||||||
//for new cables add here to get the data for multiline
|
// //for new cables add here to get the data for multiline
|
||||||
if (showMultilineCable(componentType, filters)) {
|
// if (showMultilineCable(componentType, filters)) {
|
||||||
let cableData: any = {};
|
// let cableData: any = {};
|
||||||
if (componentType === quack.ComponentType.COMPONENT_TYPE_GRAIN_CABLE) {
|
// if (componentType === quack.ComponentType.COMPONENT_TYPE_GRAIN_CABLE) {
|
||||||
cableData = multilineGrainCableData(measurements, filters);
|
// cableData = multilineGrainCableData(measurements, filters);
|
||||||
} else if (componentType === quack.ComponentType.COMPONENT_TYPE_PRESSURE_CABLE) {
|
// } else if (componentType === quack.ComponentType.COMPONENT_TYPE_PRESSURE_CABLE) {
|
||||||
cableData = multilinePressureCableData(measurements, filters);
|
// cableData = multilinePressureCableData(measurements, filters);
|
||||||
} else if (componentType === quack.ComponentType.COMPONENT_TYPE_CAPACITOR_CABLE) {
|
// } else if (componentType === quack.ComponentType.COMPONENT_TYPE_CAPACITOR_CABLE) {
|
||||||
cableData = multilineCapCableData(measurements, filters);
|
// cableData = multilineCapCableData(measurements, filters);
|
||||||
}
|
// }
|
||||||
//will loop through the keys in cableData
|
// //will loop through the keys in cableData
|
||||||
//IMPORTANT keys must be data1, data2, etc in the multiline function in the component
|
// //IMPORTANT keys must be data1, data2, etc in the multiline function in the component
|
||||||
for (let i = 1; i <= Object.keys(cableData).length; i++) {
|
// for (let i = 1; i <= Object.keys(cableData).length; i++) {
|
||||||
let gc = "graphComponent" + i;
|
// let gc = "graphComponent" + i;
|
||||||
if (graphProps[gc]) {
|
// if (graphProps[gc]) {
|
||||||
graphProps[gc].data = cableData["data" + i];
|
// graphProps[gc].data = cableData["data" + i];
|
||||||
graphProps[gc].type = GraphType.MULTILINE;
|
// graphProps[gc].type = GraphType.MULTILINE;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
measurements.forEach((reading: pond.Measurement, readIndex) => {
|
// measurements.forEach((reading: pond.Measurement, readIndex) => {
|
||||||
if (notNull(reading) && notNull(reading.timestamp) && notNull(reading.measurement)) {
|
// if (notNull(reading) && notNull(reading.timestamp) && notNull(reading.measurement)) {
|
||||||
let date = new Date(Date.parse(reading.timestamp));
|
// let date = new Date(Date.parse(reading.timestamp));
|
||||||
for (let index = 0; index < ext.measurements.length; index++) {
|
// for (let index = 0; index < ext.measurements.length; index++) {
|
||||||
let componentMeasurement: ComponentMeasurement = ext.measurements[index];
|
// let componentMeasurement: ComponentMeasurement = ext.measurements[index];
|
||||||
if (componentMeasurement.isErrorMeasurement(reading.measurement)) {
|
// if (componentMeasurement.isErrorMeasurement(reading.measurement)) {
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
let dataPoint = null;
|
// let dataPoint = null;
|
||||||
switch (componentMeasurement.graphType) {
|
// switch (componentMeasurement.graphType) {
|
||||||
case GraphType.AREA:
|
// case GraphType.AREA:
|
||||||
let avg = componentMeasurement.extract(
|
// let avg = componentMeasurement.extract(
|
||||||
or(reading.measurement, {} as quack.Measurement),
|
// or(reading.measurement, {} as quack.Measurement),
|
||||||
filters
|
// filters
|
||||||
);
|
// );
|
||||||
if (avg && avg.low !== null && avg.high !== null) {
|
// if (avg && avg.low !== null && avg.high !== null) {
|
||||||
dataPoint = {
|
// dataPoint = {
|
||||||
x: date,
|
// x: date,
|
||||||
y: avg.low,
|
// y: avg.low,
|
||||||
y0: avg.high
|
// y0: avg.high
|
||||||
} as GraphPoint;
|
// } as GraphPoint;
|
||||||
}
|
// }
|
||||||
break;
|
// break;
|
||||||
case GraphType.SCATTER:
|
// case GraphType.SCATTER:
|
||||||
let scatter = componentMeasurement.extract(
|
// let scatter = componentMeasurement.extract(
|
||||||
or(reading.measurement, {} as quack.Measurement),
|
// or(reading.measurement, {} as quack.Measurement),
|
||||||
filters
|
// filters
|
||||||
);
|
// );
|
||||||
if (scatter && scatter.value !== undefined && scatter.value !== null) {
|
// if (scatter && scatter.value !== undefined && scatter.value !== null) {
|
||||||
dataPoint = {
|
// dataPoint = {
|
||||||
x: date,
|
// x: date,
|
||||||
y: Number(scatter.value),
|
// y: Number(scatter.value),
|
||||||
bubble: or(scatter.bubble, 0)
|
// bubble: or(scatter.bubble, 0)
|
||||||
} as GraphPoint;
|
// } as GraphPoint;
|
||||||
}
|
// }
|
||||||
break;
|
// break;
|
||||||
case GraphType.RADAR:
|
// case GraphType.RADAR:
|
||||||
if (subtype === quack.AnalogInputSubtype.ANALOG_INPUT_SUBTYPE_WIND_DIRECTION) {
|
// if (subtype === quack.AnalogInputSubtype.ANALOG_INPUT_SUBTYPE_WIND_DIRECTION) {
|
||||||
let value = componentMeasurement.extract(
|
// let value = componentMeasurement.extract(
|
||||||
or(reading.measurement, {} as quack.Measurement),
|
// or(reading.measurement, {} as quack.Measurement),
|
||||||
filters
|
// filters
|
||||||
);
|
// );
|
||||||
|
|
||||||
dataPoint = {
|
// dataPoint = {
|
||||||
x: getWindDirection(value).dString,
|
// x: getWindDirection(value).dString,
|
||||||
y: getWindDirection(value).direction
|
// y: getWindDirection(value).direction
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
break;
|
// break;
|
||||||
default:
|
// default:
|
||||||
//linear and bar
|
// //linear and bar
|
||||||
let value = componentMeasurement.extract(
|
// let value = componentMeasurement.extract(
|
||||||
or(reading.measurement, {} as quack.Measurement),
|
// or(reading.measurement, {} as quack.Measurement),
|
||||||
filters
|
// filters
|
||||||
);
|
// );
|
||||||
|
|
||||||
if (value !== undefined && value !== null) {
|
// if (value !== undefined && value !== null) {
|
||||||
if (componentType === quack.ComponentType.COMPONENT_TYPE_ANALOG_INPUT) {
|
// if (componentType === quack.ComponentType.COMPONENT_TYPE_ANALOG_INPUT) {
|
||||||
if (subtype === quack.AnalogInputSubtype.ANALOG_INPUT_SUBTYPE_FUEL) {
|
// if (subtype === quack.AnalogInputSubtype.ANALOG_INPUT_SUBTYPE_FUEL) {
|
||||||
if (value > 100) {
|
// if (value > 100) {
|
||||||
value = 0;
|
// value = 0;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if (componentType === quack.ComponentType.COMPONENT_TYPE_EDGE_TRIGGERED) {
|
// if (componentType === quack.ComponentType.COMPONENT_TYPE_EDGE_TRIGGERED) {
|
||||||
if (subtype === quack.EdgeTriggeredSubtype.EDGE_TRIGGERED_SUBTYPE_WIND_SPEED) {
|
// if (subtype === quack.EdgeTriggeredSubtype.EDGE_TRIGGERED_SUBTYPE_WIND_SPEED) {
|
||||||
if (readIndex < measurements.length - 1) {
|
// if (readIndex < measurements.length - 1) {
|
||||||
//do math
|
// //do math
|
||||||
//get the time of both the current reading and the reading before it
|
// //get the time of both the current reading and the reading before it
|
||||||
let currentTime = new Date(
|
// let currentTime = new Date(
|
||||||
Date.parse(measurements[readIndex].timestamp)
|
// Date.parse(measurements[readIndex].timestamp)
|
||||||
).valueOf();
|
// ).valueOf();
|
||||||
let prevTime = new Date(
|
// let prevTime = new Date(
|
||||||
Date.parse(measurements[readIndex + 1].timestamp)
|
// Date.parse(measurements[readIndex + 1].timestamp)
|
||||||
).valueOf();
|
// ).valueOf();
|
||||||
|
|
||||||
//get the difference in seconds between the two
|
// //get the difference in seconds between the two
|
||||||
let deltaTime = (currentTime - prevTime) / 1000;
|
// let deltaTime = (currentTime - prevTime) / 1000;
|
||||||
|
|
||||||
//divide the ticks by the time between intervals for the average ticks per second and multiply
|
// //divide the ticks by the time between intervals for the average ticks per second and multiply
|
||||||
//by 2.4 to convert to km/h
|
// //by 2.4 to convert to km/h
|
||||||
value = (Number(value) / deltaTime) * 2.4;
|
// value = (Number(value) / deltaTime) * 2.4;
|
||||||
} else {
|
// } else {
|
||||||
value = 0;
|
// value = 0;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if (subtype === quack.EdgeTriggeredSubtype.EDGE_TRIGGERED_SUBTYPE_RAIN) {
|
// if (subtype === quack.EdgeTriggeredSubtype.EDGE_TRIGGERED_SUBTYPE_RAIN) {
|
||||||
value = Math.round(value * 0.2794);
|
// value = Math.round(value * 0.2794);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
dataPoint = {
|
// dataPoint = {
|
||||||
x: date,
|
// x: date,
|
||||||
y: Number(value)
|
// y: Number(value)
|
||||||
} as GraphPoint;
|
// } as GraphPoint;
|
||||||
}
|
// }
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
if (dataPoint !== null) {
|
// if (dataPoint !== null) {
|
||||||
graphProps["graphComponent" + (index + 1).toString()].data.push(dataPoint);
|
// graphProps["graphComponent" + (index + 1).toString()].data.push(dataPoint);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
return graphProps;
|
// return graphProps;
|
||||||
}
|
// }
|
||||||
|
|
||||||
function getWindDirection(value: number) {
|
function getWindDirection(value: number) {
|
||||||
//determine the general direction based on the value
|
//determine the general direction based on the value
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ import GrainCableLightIcon from "assets/components/grainCableLight.png";
|
||||||
import TemperatureHumidityDarkIcon from "assets/components/temperatureHumidityDark.png";
|
import TemperatureHumidityDarkIcon from "assets/components/temperatureHumidityDark.png";
|
||||||
import TemperatureHumidityLightIcon from "assets/components/temperatureHumidityLight.png";
|
import TemperatureHumidityLightIcon from "assets/components/temperatureHumidityLight.png";
|
||||||
import { ExtractMoisture, grainName } from "grain";
|
import { ExtractMoisture, grainName } from "grain";
|
||||||
import { GraphPoint } from "common/Graph";
|
//import { GraphPoint } from "common/Graph";
|
||||||
import moment from "moment";
|
//import moment from "moment";
|
||||||
import {
|
import {
|
||||||
AreaChartData,
|
AreaChartData,
|
||||||
ComponentMeasurement,
|
ComponentMeasurement,
|
||||||
|
|
@ -418,38 +418,38 @@ export function binSplitAt(filters?: GraphFilters): number {
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: deprecated function with new measurements
|
//TODO: deprecated function with new measurements
|
||||||
export function multilineGrainCableData(
|
// export function multilineGrainCableData(
|
||||||
measurements: Array<pond.Measurement>,
|
// measurements: Array<pond.Measurement>,
|
||||||
filters?: GraphFilters
|
// filters?: GraphFilters
|
||||||
) {
|
// ) {
|
||||||
let temperature: Array<Array<GraphPoint>> = [];
|
// let temperature: Array<Array<GraphPoint>> = [];
|
||||||
let humidity: Array<Array<GraphPoint>> = []; //humidity is not being used by the graphs
|
// let humidity: Array<Array<GraphPoint>> = []; //humidity is not being used by the graphs
|
||||||
let moisture: Array<Array<GraphPoint>> = [];
|
// let moisture: Array<Array<GraphPoint>> = [];
|
||||||
measurements.forEach((measurement: pond.Measurement, i) => {
|
// measurements.forEach((measurement: pond.Measurement, i) => {
|
||||||
let nodes = extractNodes(measurement.measurement);
|
// let nodes = extractNodes(measurement.measurement);
|
||||||
let selectedNodes = filters ? or(filters.selectedNodes, []) : [];
|
// let selectedNodes = filters ? or(filters.selectedNodes, []) : [];
|
||||||
for (let j = 0; j < selectedNodes.length; j++) {
|
// for (let j = 0; j < selectedNodes.length; j++) {
|
||||||
if (i === 0) {
|
// if (i === 0) {
|
||||||
temperature[j] = [];
|
// temperature[j] = [];
|
||||||
humidity[j] = [];
|
// humidity[j] = [];
|
||||||
moisture[j] = [];
|
// moisture[j] = [];
|
||||||
}
|
// }
|
||||||
let nodeIndex = selectedNodes[j];
|
// let nodeIndex = selectedNodes[j];
|
||||||
if (nodeIndex < nodes.length) {
|
// if (nodeIndex < nodes.length) {
|
||||||
let node = nodes[nodeIndex];
|
// let node = nodes[nodeIndex];
|
||||||
let ts = moment(measurement.timestamp);
|
// let ts = moment(measurement.timestamp);
|
||||||
temperature[j].push({ x: ts, y: node.temperature });
|
// temperature[j].push({ x: ts, y: node.temperature });
|
||||||
humidity[j].push({ x: ts, y: node.humidity });
|
// humidity[j].push({ x: ts, y: node.humidity });
|
||||||
let grain =
|
// let grain =
|
||||||
isBinSplit(filters) && nodeIndex >= binSplitAt(filters)
|
// isBinSplit(filters) && nodeIndex >= binSplitAt(filters)
|
||||||
? pond.Grain.GRAIN_NONE
|
// ? pond.Grain.GRAIN_NONE
|
||||||
: or(filters, { grainType: pond.Grain.GRAIN_NONE }).grainType;
|
// : or(filters, { grainType: pond.Grain.GRAIN_NONE }).grainType;
|
||||||
moisture[j].push({
|
// moisture[j].push({
|
||||||
x: ts,
|
// x: ts,
|
||||||
y: ExtractMoisture(grain, node.temperature, node.humidity)
|
// y: ExtractMoisture(grain, node.temperature, node.humidity)
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
return { data1: temperature, data2: moisture, data3: humidity };
|
// return { data1: temperature, data2: moisture, data3: humidity };
|
||||||
}
|
// }
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,10 @@ export class MeasurementDescriber {
|
||||||
}
|
}
|
||||||
if (componentType === quack.ComponentType.COMPONENT_TYPE_GRAIN_CABLE) {
|
if (componentType === quack.ComponentType.COMPONENT_TYPE_GRAIN_CABLE) {
|
||||||
this.details.graph = GraphType.AREA;
|
this.details.graph = GraphType.AREA;
|
||||||
|
if(componentSubtype === quack.GrainCableSubtype.GRAIN_CABLE_SUBTYPE_OPI_DIAG){
|
||||||
|
this.details.label = "Cable ID"
|
||||||
|
this.details.unit = ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (componentType === quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT) {
|
if (componentType === quack.ComponentType.COMPONENT_TYPE_VAPOUR_PRESSURE_DEFICIT) {
|
||||||
this.details.path = "vpd.celciusTimes10";
|
this.details.path = "vpd.celciusTimes10";
|
||||||
|
|
@ -194,6 +198,10 @@ export class MeasurementDescriber {
|
||||||
if (componentType === quack.ComponentType.COMPONENT_TYPE_GRAIN_CABLE) {
|
if (componentType === quack.ComponentType.COMPONENT_TYPE_GRAIN_CABLE) {
|
||||||
this.details.label = "Humidity";
|
this.details.label = "Humidity";
|
||||||
this.details.graph = GraphType.AREA;
|
this.details.graph = GraphType.AREA;
|
||||||
|
if(componentSubtype === quack.GrainCableSubtype.GRAIN_CABLE_SUBTYPE_OPI_DIAG){
|
||||||
|
this.details.label = "Cable Type"
|
||||||
|
this.details.unit = ""
|
||||||
|
}
|
||||||
// can be used for testing node splitting on a cable if you dont have a component that uses it
|
// can be used for testing node splitting on a cable if you dont have a component that uses it
|
||||||
// this.details.nodeDetails = {
|
// this.details.nodeDetails = {
|
||||||
// colours: ["white", "black"],
|
// colours: ["white", "black"],
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,10 @@ export interface IBinAPIContext {
|
||||||
showErrors?: boolean,
|
showErrors?: boolean,
|
||||||
otherTeam?: string
|
otherTeam?: string
|
||||||
) => Promise<AxiosResponse<pond.ListObjectMeasurementsResponse>>;
|
) => Promise<AxiosResponse<pond.ListObjectMeasurementsResponse>>;
|
||||||
|
getBinsTrendData: (
|
||||||
|
bins: string[],
|
||||||
|
days: number
|
||||||
|
) => Promise<AxiosResponse<pond.GetBinsTrendDataResponse>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BinAPIContext = createContext<IBinAPIContext>({} as IBinAPIContext);
|
export const BinAPIContext = createContext<IBinAPIContext>({} as IBinAPIContext);
|
||||||
|
|
@ -629,6 +633,12 @@ export default function BinProvider(props: PropsWithChildren<Props>) {
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getBinsTrendData = (bins: string[], days: number) => {
|
||||||
|
return get<pond.GetBinsTrendDataResponse>(
|
||||||
|
pondURL("/binTrends?bins=" + bins.toString() + "&days=" + days + (as ? "&as=" + as : ""))
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BinAPIContext.Provider
|
<BinAPIContext.Provider
|
||||||
value={{
|
value={{
|
||||||
|
|
@ -655,7 +665,8 @@ export default function BinProvider(props: PropsWithChildren<Props>) {
|
||||||
listHistoryBetween,
|
listHistoryBetween,
|
||||||
listBinPrefs,
|
listBinPrefs,
|
||||||
updateTopNodes,
|
updateTopNodes,
|
||||||
listBinMeasurements
|
listBinMeasurements,
|
||||||
|
getBinsTrendData
|
||||||
}}>
|
}}>
|
||||||
{children}
|
{children}
|
||||||
</BinAPIContext.Provider>
|
</BinAPIContext.Provider>
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ export default function GroupProvider(props: PropsWithChildren<Props>) {
|
||||||
|
|
||||||
const addDevice = (group: number, device: number) => {
|
const addDevice = (group: number, device: number) => {
|
||||||
let url = "/groups/" + group + "/devices/" + device + "/add";
|
let url = "/groups/" + group + "/devices/" + device + "/add";
|
||||||
if (as) url = pondURL(url + as)
|
if (as) url = url + "?as=" + as
|
||||||
return new Promise<AxiosResponse>((resolve, reject) => {
|
return new Promise<AxiosResponse>((resolve, reject) => {
|
||||||
post(pondURL(url), group).then(resp => {
|
post(pondURL(url), group).then(resp => {
|
||||||
return resolve(resp)
|
return resolve(resp)
|
||||||
|
|
@ -100,7 +100,7 @@ export default function GroupProvider(props: PropsWithChildren<Props>) {
|
||||||
|
|
||||||
const removeDevice = (group: number, device: number) => {
|
const removeDevice = (group: number, device: number) => {
|
||||||
let url = "/groups/" + group + "/devices/" + device + "/remove";
|
let url = "/groups/" + group + "/devices/" + device + "/remove";
|
||||||
if (as) url = pondURL(url + as)
|
if (as) url = url + "?as=" + as
|
||||||
return new Promise<AxiosResponse>((resolve, reject) => {
|
return new Promise<AxiosResponse>((resolve, reject) => {
|
||||||
post(pondURL(url), group).then(resp => {
|
post(pondURL(url), group).then(resp => {
|
||||||
return resolve(resp)
|
return resolve(resp)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue