farmcontrol-ui/src/components/Dashboard/common/PrinterTemperaturePanel.jsx

308 lines
8.8 KiB
JavaScript

// PrinterTemperaturePanel.js
import { useContext, useState, useEffect } from 'react'
import {
Progress,
Typography,
Spin,
Flex,
Space,
Collapse,
InputNumber,
Button
} from 'antd'
import { LoadingOutlined, CaretRightOutlined } from '@ant-design/icons'
import styled from 'styled-components'
import PropTypes from 'prop-types'
import { ApiServerContext } from '../context/ApiServerContext'
import merge from 'lodash/merge'
const { Text } = Typography
const { Panel } = Collapse
const CustomCollapse = styled(Collapse)`
.ant-collapse-header {
padding: 0 !important;
}
.ant-collapse-content-box {
padding-left: 0 !important;
padding-right: 0 !important;
padding-bottom: 0 !important;
}
`
const PrinterTemperaturePanel = ({
id,
showExtruderControls = true,
showBedControls = true,
showExtruder = true,
showBed = true,
showMoreInfo = true
}) => {
const [temperatureData, setTemperatureData] = useState({
extruder: {
current: 0,
target: 0,
power: 0
},
bed: {
current: 0,
target: 0,
power: 0
},
pinda: 0,
ambiant: 0
})
const { subscribeToObjectEvent, connected, sendObjectAction } =
useContext(ApiServerContext)
// Sync input values with actual temperature targets
useEffect(() => {
if (temperatureData.extruder?.target !== undefined) {
setExtruderTarget(temperatureData.extruder.target)
}
}, [temperatureData.extruder?.target])
useEffect(() => {
if (temperatureData.bed?.target !== undefined) {
setBedTarget(temperatureData.bed.target)
}
}, [temperatureData.bed?.target])
useEffect(() => {
if (id && connected) {
const temperatureEventUnsubscribe = subscribeToObjectEvent(
id,
'printer',
'temperature',
(event) => {
setTemperatureData((prev) => {
const merged = merge({}, prev, event.data)
return merged
})
}
)
return () => {
if (temperatureEventUnsubscribe) temperatureEventUnsubscribe()
}
}
}, [id, connected])
const [extruderTarget, setExtruderTarget] = useState(0)
const [bedTarget, setBedTarget] = useState(0)
const handleSetTemperature = async (data) => {
if (id && connected == true) {
await sendObjectAction(
id,
'printer',
{
type: 'setTemperature',
data
},
(result) => {
console.log('setTemperatureResult', result)
}
)
}
}
const moreInfoItems = [
{
key: '1',
label: 'More Temperature Data',
children: (
<>
<Flex vertical gap={0}>
<Text>
Hot End Power:{' '}
{Math.round((temperatureData.extruder.power || 0) * 100)}%
</Text>
<Progress
percent={(temperatureData.extruder.power || 0) * 100}
showInfo={false}
/>
</Flex>
<Flex vertical gap={0}>
<Text>
Bed Power: {Math.round((temperatureData.bed.power || 0) * 100)}%
</Text>
<Progress
percent={(temperatureData.bed.power || 0) * 100}
showInfo={false}
/>
</Flex>
<Panel>
{typeof temperatureData.pinda !== 'undefined' && (
<Flex vertical gap={0}>
<Text>Pinda Temp: {temperatureData.pindaTemp}°C</Text>
</Flex>
)}
{typeof temperatureData.ambiant !== 'undefined' && (
<Flex vertical gap={0}>
<Text>Ambient Actual: {temperatureData.ambiant}°C</Text>
</Flex>
)}
</Panel>
</>
)
}
]
return (
<div style={{ minWidth: 190 }}>
{temperatureData ? (
<Flex vertical gap='middle'>
{temperatureData.extruder && showExtruder && (
<Flex vertical gap={0}>
<Text>
Hot End: {temperatureData.extruder.current}°C /{' '}
{temperatureData.extruder.target}°C
</Text>
<Progress
percent={(temperatureData.extruder.target / 300) * 100}
strokeColor='#FF392F1D'
success={{
percent: (temperatureData.extruder.current / 300) * 100,
strokeColor: '#FF3B2F'
}}
showInfo={false}
/>
{showExtruderControls && (
<Space direction='horizontal' style={{ marginTop: 5 }}>
<Space.Compact block size='small'>
<InputNumber
value={extruderTarget}
min={0}
max={300}
style={{ width: '120px' }}
addonAfter='°C'
onChange={(value) => setExtruderTarget(value || 0)}
onPressEnter={() =>
handleSetTemperature({
extruder: { target: extruderTarget }
})
}
/>
<Button
type='default'
style={{ width: 40 }}
onClick={() =>
handleSetTemperature({
extruder: { target: extruderTarget }
})
}
>
Set
</Button>
</Space.Compact>
<Button
type='default'
size='small'
style={{ width: 40 }}
onClick={() =>
handleSetTemperature({ extruder: { target: 0 } })
}
>
Off
</Button>
</Space>
)}
</Flex>
)}
{temperatureData.bed && showBed && (
<Flex vertical gap={0}>
<Text>
Heated Bed: {temperatureData.bed.current}°C /{' '}
{temperatureData.bed.target}°C
</Text>
<Progress
percent={(temperatureData.bed.target / 300) * 100}
strokeColor='#FF392F1D'
success={{
percent: (temperatureData.bed.current / 300) * 100,
strokeColor: '#FF3B2F'
}}
showInfo={false}
/>
{showBedControls && (
<Space
direction='horizontal'
style={{ marginTop: 5, height: '21px' }}
>
<Space.Compact block size='small'>
<InputNumber
value={bedTarget}
min={0}
max={300}
style={{ width: '120px' }}
addonAfter='°C'
onChange={(value) => setBedTarget(value || 0)}
onPressEnter={() =>
handleSetTemperature({
bed: { target: bedTarget }
})
}
/>
<Button
type='default'
style={{ width: 40 }}
onClick={() =>
handleSetTemperature({
bed: { target: bedTarget }
})
}
>
Set
</Button>
</Space.Compact>
<Button
type='default'
size='small'
style={{ width: 40 }}
onClick={() =>
handleSetTemperature({
bed: { target: 0 }
})
}
>
Off
</Button>
</Space>
)}
</Flex>
)}
{showMoreInfo === true && (
<CustomCollapse
ghost
size='small'
items={moreInfoItems}
expandIcon={({ isActive }) => (
<CaretRightOutlined rotate={isActive ? 90 : 0} />
)}
/>
)}
</Flex>
) : (
<Flex justify='centre'>
<Spin indicator={<LoadingOutlined spin />} size='large' />
</Flex>
)}
</div>
)
}
PrinterTemperaturePanel.propTypes = {
id: PropTypes.string.isRequired,
showExtruderControls: PropTypes.bool,
showBedControls: PropTypes.bool,
showExtruder: PropTypes.bool,
showBed: PropTypes.bool,
showMoreInfo: PropTypes.bool,
shouldUnsubscribe: PropTypes.bool
}
export default PrinterTemperaturePanel