import { Avatar, Box, Button, CardHeader, Checkbox, FormControlLabel, Grid2, Theme, Tooltip, Typography } from "@mui/material"; import { useMobile, useThemeType } from "hooks"; import VPDDark from "assets/products/Ag/dryingDark.png"; import VPDLight from "assets/products/Ag/dryingLight.png"; import TrendLight from "assets/products/Ag/trendingLight.png"; import TrendDark from "assets/products/Ag/trendingDark.png"; import { useEffect, useState } from "react"; import { makeStyles } from "@mui/styles"; import moment, { Moment } from "moment"; import { blue, orange, teal } from "@mui/material/colors"; import { GrainDryingPoint } from "charts/GrainDryingChart"; import { GrainCable } from "models/GrainCable"; import { Plenum } from "models/Plenum"; import BinGraphsVPD from "bin/graphs/BinGraphsVPD"; import { UnitMeasurement } from "models/UnitMeasurement"; import { Bin } from "models"; import { useBinAPI, useGlobalState } from "providers"; import TimeBar from "common/time/TimeBar"; import { GetDefaultDateRange } from "common/time/DateRange"; import { ZoomOut } from "@mui/icons-material"; import BinGraphsTrending from "bin/graphs/BinGraphsTrending"; import { DataPoint, TrendPoint } from "charts/TrendingChart"; import WaterLight from "assets/products/Ag/waterContentLight.png"; import WaterDark from "assets/products/Ag/waterContentDark.png"; import { Pressure } from "models/Pressure"; import { DataPoint as WaterPoint } from "charts/WaterLevelChart"; import BinWaterLevel from "bin/graphs/BinWaterLevel"; import { Controller } from "models/Controller"; import { pond } from "protobuf-ts/pond"; interface Props { cables: GrainCable[] plenums: Plenum[] componentDevices: Map bin: Bin } const useStyles = makeStyles((theme: Theme) =>{ return ({ root: { display: "flex", flexDirection: "column", height: "100%", overflow: "hidden", }, toolbar: { flexShrink: 0, }, scrollContent: { flex: 1, minHeight: 0, overflowY: "auto", }, card: { position: "relative", display: "flex", height: "100%", flexDirection: "column", overflow: "visible" }, cardHeader: { padding: theme.spacing(1), paddingLeft: theme.spacing(2), marginRight: 10 }, avatarIcon: { width: 33, height: 33 } }) }); export default function BinAnalysisGraphs(props: Props){ const {cables, plenums, componentDevices, bin} = props const themeType = useThemeType() const classes = useStyles() const [{user, as, showErrors}, dispatch] = useGlobalState() const isMobile = useMobile() const [xDomain, setXDomain] = useState(["dataMin", "dataMax"]); const [zoomed, setZoomed] = useState(false); const [recentVPD, setRecentVPD] = useState(); const [loading, setLoading] = useState(false) // map using the component key and the unitmeasurements for that component const [compMeasurements, setCompMeasurements] = useState>( new Map() ); const binAPI = useBinAPI() const defaultDateRange = GetDefaultDateRange() const [startDate, setStartDate] = useState(defaultDateRange.start); const [endDate, setEndDate] = useState(defaultDateRange.end); const [recentPlenumTrend, setRecentPlenumTrend] = useState(); const [recentCableTrend, setRecentCableTrend] = useState(); const [recentWaterContent, setRecentWaterContent] = useState(); useEffect(() => { let measurementMap: Map = new Map(); if (!loading) { setLoading(true); //check if the bin has a fan to use the cfm in the drying graph // if (bin.settings.fan?.type !== pond.FanType.FAN_TYPE_UNKNOWN) { // setIncludeCFM(true); // } binAPI .listBinComponentsMeasurements( bin.key(), startDate.toISOString(), endDate.toISOString(), showErrors, showErrors, as ) .then(resp => { resp.data.measurements.forEach((um: any) => { let unitMeasurement = UnitMeasurement.any(um, user); let entry = measurementMap.get(unitMeasurement.componentId); if (entry) { entry.push(unitMeasurement); } else { measurementMap.set(unitMeasurement.componentId, [unitMeasurement]); } }); setCompMeasurements(measurementMap); setLoading(false); }); } }, [bin, binAPI, startDate, endDate, user, as]); // eslint-disable-line react-hooks/exhaustive-deps const zoomOut = () => { setXDomain(["dataMin", "dataMax"]); setZoomed(false); }; const zoomIn = (domain: string[] | number[]) => { if (!isMobile) { setXDomain(domain); setZoomed(true); } }; const updateDateRange = (newStartDate: any, newEndDate: any) => { let range = GetDefaultDateRange(); range.start = newStartDate; range.end = newEndDate; setStartDate(newStartDate); setEndDate(newEndDate); }; //this uses the components found in the bins status const waterGraph = () => { let moistureCables: pond.GrainCable[] = []; bin.status.grainCables.forEach(cable => { if (cable.relativeHumidity.length > 0) { moistureCables.push(cable); } }); if (bin.status.plenums[0] && moistureCables[0] && bin.status.pressures[0] && bin.supportedGrain()) { return ( 0 ? componentDevices.get(bin.status.fans[0].key) + ":" + bin.status.fans[0].key : undefined } newXDomain={xDomain} multiGraphZoom={zoomIn} multiGraphZoomOut returnLast={lastWater => { setRecentWaterContent(lastWater); }} /> ); } else { return ( Plenum with pressure and moisture cable as well as an initial moisture and supported grain type set in the bin settings required to calculate Water Content ); } }; return ( {zoomed && ( )} { //setShowErrors(!showErrors); dispatch({ key: "showErrors", value: !showErrors }); }} /> } /> } title={ Drying vs. Hydrating } subheader={ recentVPD ? ( 0 ? orange[500] : blue[500] }}> {recentVPD.dryScore > 0 ? "drying" : "hydrating"} {" : "} 0 ? orange[500] : blue[500], fontWeight: 500 }}> {recentVPD.dryScore.toFixed(2)}
{moment(recentVPD.timestamp).fromNow()}
) : ( No Data ) } /> {cables.length > 0 && plenums.length > 0 ? ( { setRecentVPD(lastVPD); }} /> ) : ( Plenum and moisture cable required to calculate VPD )} } title={ Moisture Trending } subheader={ recentPlenumTrend && recentCableTrend ? ( {"Plenum Moisture: "} {recentPlenumTrend.trend.toFixed(2)}
{"Grain Moisture: "} {recentCableTrend.moisture.toString()}
{recentPlenumTrend.timestamp > recentCableTrend.timestamp ? moment(recentPlenumTrend.timestamp).fromNow() : moment(recentCableTrend.timestamp).fromNow()}
) : ( No Data ) } /> {cables.length > 0 && plenums.length > 0 ? ( { setRecentCableTrend(lastData); setRecentPlenumTrend(lastTrend); }} /> ) : ( Plenum and moisture cable required to calculate trending data )} } title={ Grain Water Content } subheader={ recentWaterContent && bin.settings.inventory && bin.settings.inventory.initialMoisture > 0 ? ( {"Water Content: "} {recentWaterContent.liters && !isNaN(recentWaterContent.liters) ? recentWaterContent.liters.toFixed(2) : ""}
{moment(recentWaterContent.timestamp).fromNow()}
) : ( No Data ) } /> {waterGraph()}
) }