diff --git a/src/bin/BinControllerDisplay.tsx b/src/bin/BinControllerDisplay.tsx new file mode 100644 index 0000000..32cbd94 --- /dev/null +++ b/src/bin/BinControllerDisplay.tsx @@ -0,0 +1,168 @@ +import { Component } from "models" +import React, { useEffect, useState } from "react" +import { makeStyles } from "@mui/styles"; +import { Box, Button, DialogActions, DialogContent, DialogTitle, Typography } from "@mui/material"; +import AerationFanIcon from "products/AgIcons/AerationFanIcon"; +import { quack } from "protobuf-ts/quack"; +import { useComponentAPI, useMobile, useSnackbar } from "hooks"; +import ButtonGroup from "common/ButtonGroup"; +import ObjectHeaterIcon from "products/Construction/ObjectHeaterIcon"; +import ResponsiveDialog from "common/ResponsiveDialog"; + + +interface Props { + deviceID: number + component: Component + currentState?: boolean +} + +const useStyles = makeStyles(() => { + return ({ + controllerDisplay: { + display: "flex", + justifyContent: "space-between", + paddingLeft: 5, + paddingRight: 5 + }, + }) +}) + +export default function BinControllerDisplay(props: Props) { + const {component, deviceID, currentState} = props + const [controllerState, setControllerState] = useState(0) + const [openDialog, setOpenDialog] = useState(false) + const [newOutputState, setNewOutputState] = useState(0) + const {openSnack} = useSnackbar() + const componentAPI = useComponentAPI() + const isMobile = useMobile() + const classes = useStyles() + + useEffect(()=>{ + setControllerState(component.settings.defaultOutputState) + },[component]) + + + const controllerIcon = () => { + if(component.subType() === quack.BooleanOutputSubtype.BOOLEAN_OUTPUT_SUBTYPE_HEATER){ + return + }else{ + return + } + } + + const setController = () => { + let newSettings = component.settings + newSettings.defaultOutputState = newOutputState + componentAPI.update(deviceID, newSettings).then(resp => { + openSnack("Updated controllers output state") + setControllerState(newOutputState) + }).catch(err => { + openSnack("There was a problem updating the controller") + }).finally(() => { + setOpenDialog(false) + }) + } + + const controllerDialog = () => { + return ( + {setOpenDialog(false)}}> + Set Controller State + + This Action will change the output state of the controller + + + + + + + ) + } + + const componentOn = () => { + if(currentState){ + return currentState + }else{ + let state = false + component.status.lastGoodMeasurement.forEach(um => { + if(um.type === quack.MeasurementType.MEASUREMENT_TYPE_BOOLEAN){ + if(um.values.length > 0){ + let readings = um.values + if(readings[readings.length-1].values.length > 0){ + let nodes = readings[readings.length-1].values + if (nodes[nodes.length -1] === 1){ + state = true + } + } + } + } + }) + return state + } + } + + return ( + + {controllerDialog()} + + + + {controllerIcon()} + + + {component.name()} + + + + { + setNewOutputState(0) + setOpenDialog(true) + } + }, + { + title: "On", + function: () => { + setNewOutputState(1) + setOpenDialog(true) + } + }, + { + title: "Off", + function: () => { + setNewOutputState(2) + setOpenDialog(true) + } + } + ]} + toggledButtons={[controllerState]} + toggle + /> + + {componentOn() ? "ON" : "OFF"} + + + + + ) + +} \ No newline at end of file diff --git a/src/bin/BinVisualizerV2.tsx b/src/bin/BinVisualizerV2.tsx index 2e2f987..c51908a 100644 --- a/src/bin/BinVisualizerV2.tsx +++ b/src/bin/BinVisualizerV2.tsx @@ -31,7 +31,7 @@ import { round } from "lodash"; import { Bin, Component, Device } from "models"; import { GetComponentIcon } from "pbHelpers/ComponentType"; import { describeMeasurement } from "pbHelpers/MeasurementDescriber"; -import { useMobile } from "hooks"; +import { useComponentAPI, useMobile } from "hooks"; import { pond } from "protobuf-ts/pond"; import { quack } from "protobuf-ts/quack"; import { useGlobalState, useSnackbar } from "providers"; @@ -71,6 +71,7 @@ import { makeStyles } from "@mui/styles"; import ButtonGroup from "common/ButtonGroup"; import ModeChangeDialog from "./conditioning/modeChangeDialog"; import CustomGrainSelector from "grain/CustomGrainSelector"; +import BinControllerDisplay from "./BinControllerDisplay"; const useStyles = makeStyles((theme: Theme) => { return ({ @@ -180,7 +181,7 @@ interface Props { bin: Bin; loading: boolean; components: Map; - componentDevices?: Map; + componentDevices: Map; devices: Device[]; plenums?: Plenum[]; ambient?: Ambient; @@ -289,6 +290,12 @@ export default function BinVisualizer(props: Props) { const [modeChangeInProgress, setModeChangeInProgress] = useState(false) const [newGrainSettings, setNewGrainSettings] = useState() + const componentAPI = useComponentAPI() + const [openControllerDIalog, setOpenControllerDialog] = useState(false) + const [controllerOutputStates, setControllerOutputStates] = useState>(new Map()) + const [selectedController, setSelectedController] = useState() + const [newOutputState, setNewOutputState] = useState() + useEffect(() => { setModeTime(moment(bin.status.lastModeChange)); }, [bin.status.lastModeChange]); @@ -1544,54 +1551,24 @@ export default function BinVisualizer(props: Props) { Controllers - {bin.status.fans.map(fan => ( - - - - - {fan.name} - - - - {fan.state ? "ON" : "OFF"} - - - ))} - {bin.status.heaters.map(heater => ( - - - - - {heater.name} - - - - {heater.state ? "ON" : "OFF"} - - - ))} + {bin.status.fans.map(fan => { + let fanComp = components.get(fan.key) + let device = componentDevices.get(fan.key) + if(fanComp && device){ + return ( + + ) + } + })} + {bin.status.heaters.map(heater => { + let heaterComp = components.get(heater.key) + let device = componentDevices.get(heater.key) + if(heaterComp && device){ + return ( + + ) + } + })} ); diff --git a/src/common/ButtonGroup.tsx b/src/common/ButtonGroup.tsx index e326d64..ee9e3e4 100644 --- a/src/common/ButtonGroup.tsx +++ b/src/common/ButtonGroup.tsx @@ -48,7 +48,11 @@ interface Props { * * @default undefined */ - toggledButtons?: number[] + toggledButtons?: number[] + /** + * This can be used to set which button starts toggled by default, and from there it will be controlled internally, toggledButtons will override this + */ + defaultToggle?: number /** * Numerical value for the size of the text for buttons that dont use the icon */ @@ -97,7 +101,7 @@ const useStyles = makeStyles((theme: Theme) => { }) export default function ButtonGroup(props: Props){ - const { buttons, toggle, toggledButtons, multiToggle, textSize, disableAll } = props + const { buttons, toggle, toggledButtons, defaultToggle, multiToggle, textSize, disableAll } = props const classes = useStyles() const [currentToggle, setCurrentToggle] = useState([]) @@ -107,6 +111,8 @@ export default function ButtonGroup(props: Props){ let toggled: number [] = [0] if(toggledButtons){ toggled = toggledButtons + } else if(defaultToggle){ + toggled = [defaultToggle] } setCurrentToggle(toggled) }