261 lines
7.9 KiB
JavaScript
261 lines
7.9 KiB
JavaScript
import { useState, useContext, useEffect } from 'react'
|
|
import { Form, Button, Typography, Flex, Steps, Divider, Alert } from 'antd'
|
|
import { useMediaQuery } from 'react-responsive'
|
|
import PropTypes from 'prop-types'
|
|
import { PrintServerContext } from '../../context/PrintServerContext'
|
|
|
|
import PrinterSelect from '../../common/PrinterSelect'
|
|
import PrinterTemperaturePanel from '../../common/PrinterTemperaturePanel'
|
|
|
|
import { LoadingOutlined } from '@ant-design/icons'
|
|
|
|
const { Title } = Typography
|
|
|
|
const UnloadFilamentStock = ({ onOk, reset, printer = null }) => {
|
|
UnloadFilamentStock.propTypes = {
|
|
onOk: PropTypes.func.isRequired,
|
|
reset: PropTypes.bool.isRequired,
|
|
printer: PropTypes.object
|
|
}
|
|
|
|
const { printServer } = useContext(PrintServerContext)
|
|
const isMobile = useMediaQuery({ maxWidth: 768 })
|
|
|
|
const initialUnloadFilamentStockForm = {
|
|
printer: printer
|
|
}
|
|
|
|
const [unloadFilamentStockLoading, setUnloadFilamentStockLoading] =
|
|
useState(false)
|
|
const [currentStep, setCurrentStep] = useState(0)
|
|
const [nextEnabled, setNextEnabled] = useState(false)
|
|
const [currentTemperature, setCurrentTemperature] = useState(-1)
|
|
const [targetTemperature, setTargetTemperature] = useState(0)
|
|
const [filamentSensorDetected, setFilamentSensorDetected] = useState(true)
|
|
const [unloadFilamentStockForm] = Form.useForm()
|
|
const [unloadFilamentStockFormValues, setUnloadFilamentStockFormValues] =
|
|
useState(initialUnloadFilamentStockForm)
|
|
|
|
// Add websocket temperature monitoring
|
|
useEffect(() => {
|
|
if (unloadFilamentStockFormValues.printer) {
|
|
const params = {
|
|
printerId: unloadFilamentStockFormValues.printer._id,
|
|
objects: {
|
|
extruder: null,
|
|
'filament_switch_sensor fsensor': null
|
|
}
|
|
}
|
|
|
|
const notifyStatusUpdate = (statusUpdate) => {
|
|
if (statusUpdate?.extruder?.temperature !== undefined) {
|
|
setCurrentTemperature(statusUpdate.extruder.temperature)
|
|
}
|
|
if (statusUpdate?.extruder?.target !== undefined) {
|
|
setTargetTemperature(statusUpdate.extruder.target)
|
|
}
|
|
if (
|
|
statusUpdate?.['filament_switch_sensor fsensor']
|
|
?.filament_detected !== undefined
|
|
) {
|
|
setFilamentSensorDetected(
|
|
Boolean(
|
|
statusUpdate['filament_switch_sensor fsensor'].filament_detected
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
printServer.emit('printer.objects.subscribe', params)
|
|
printServer.emit('printer.objects.query', params)
|
|
printServer.on('notify_status_update', notifyStatusUpdate)
|
|
|
|
return () => {
|
|
printServer.off('notify_status_update', notifyStatusUpdate)
|
|
printServer.emit('printer.objects.unsubscribe', params)
|
|
}
|
|
}
|
|
}, [printServer, unloadFilamentStockFormValues.printer])
|
|
|
|
useEffect(() => {
|
|
if (reset) {
|
|
unloadFilamentStockForm.resetFields()
|
|
}
|
|
}, [reset, unloadFilamentStockForm])
|
|
|
|
useEffect(() => {
|
|
unloadFilamentStockForm
|
|
.validateFields({
|
|
validateOnly: true
|
|
})
|
|
.then(() => {
|
|
// Only enable next if we have a printer selected, we're not loading, and we've reached target temperature
|
|
setNextEnabled(
|
|
Boolean(unloadFilamentStockFormValues.printer) &&
|
|
!unloadFilamentStockLoading &&
|
|
currentTemperature + 1 > targetTemperature &&
|
|
targetTemperature != 0
|
|
)
|
|
})
|
|
.catch(() => setNextEnabled(false))
|
|
}, [
|
|
unloadFilamentStockForm,
|
|
unloadFilamentStockFormValues,
|
|
unloadFilamentStockLoading,
|
|
currentTemperature,
|
|
targetTemperature
|
|
])
|
|
|
|
const handleUnloadFilamentStock = async () => {
|
|
setUnloadFilamentStockLoading(true)
|
|
// Send G-code to retract the filament
|
|
await printServer.emit('printer.gcode.script', {
|
|
printerId: unloadFilamentStockFormValues.printer._id,
|
|
script: `_CLIENT_LINEAR_MOVE E=-200 F=1000`
|
|
})
|
|
//setUnloadFilamentStockLoading(false)
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (unloadFilamentStockLoading == true && filamentSensorDetected == false) {
|
|
setUnloadFilamentStockLoading(false)
|
|
onOk()
|
|
}
|
|
}, [unloadFilamentStockLoading, filamentSensorDetected, onOk])
|
|
|
|
const steps = [
|
|
{
|
|
title: 'Preheat',
|
|
key: 'preHeat',
|
|
content: (
|
|
<Flex vertical gap={'middle'} style={{ paddingBottom: 16 }}>
|
|
<Form.Item
|
|
label='Printer'
|
|
name='printer'
|
|
style={{ margin: 0 }}
|
|
rules={[
|
|
{
|
|
required: true,
|
|
message: 'Please select a printer'
|
|
}
|
|
]}
|
|
>
|
|
<PrinterSelect checkable={false} />
|
|
</Form.Item>
|
|
|
|
{unloadFilamentStockLoading == false ? (
|
|
<>
|
|
{targetTemperature == 0 ? (
|
|
<Alert
|
|
message={'Heat the extruder to start unloading filament.'}
|
|
type='info'
|
|
showIcon
|
|
/>
|
|
) : null}
|
|
|
|
{targetTemperature > 0 &&
|
|
currentTemperature < targetTemperature ? (
|
|
<Alert
|
|
message={'Heating extruder...'}
|
|
type='error'
|
|
showIcon
|
|
icon={<LoadingOutlined />}
|
|
/>
|
|
) : null}
|
|
|
|
{targetTemperature > 0 &&
|
|
currentTemperature + 1 > targetTemperature &&
|
|
filamentSensorDetected ? (
|
|
<Alert
|
|
message={'Ready to unload filament stock.'}
|
|
type='success'
|
|
showIcon
|
|
/>
|
|
) : null}
|
|
</>
|
|
) : (
|
|
<Alert
|
|
message={'Unloading filament stock...'}
|
|
type='info'
|
|
showIcon
|
|
icon={<LoadingOutlined />}
|
|
/>
|
|
)}
|
|
|
|
{unloadFilamentStockFormValues.printer ? (
|
|
<PrinterTemperaturePanel
|
|
showHeatedBed={false}
|
|
showMoreInfo={false}
|
|
printerId={unloadFilamentStockFormValues.printer._id}
|
|
/>
|
|
) : null}
|
|
</Flex>
|
|
)
|
|
}
|
|
]
|
|
|
|
return (
|
|
<Flex gap={'middle'}>
|
|
{!isMobile && (
|
|
<div style={{ minWidth: '160px' }}>
|
|
<Steps
|
|
current={currentStep}
|
|
items={steps}
|
|
direction='vertical'
|
|
style={{ width: 'fit-content' }}
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
{!isMobile && <Divider type={'vertical'} style={{ height: 'unset' }} />}
|
|
|
|
<Flex vertical={'true'} style={{ flexGrow: 1 }} gap='middle'>
|
|
<Title level={2} style={{ marginTop: 0, marginBottom: 4 }}>
|
|
Unload Filament Stock
|
|
</Title>
|
|
<Form
|
|
name='unloadFilamentStock'
|
|
autoComplete='off'
|
|
form={unloadFilamentStockForm}
|
|
onFinish={handleUnloadFilamentStock}
|
|
onValuesChange={(changedValues) =>
|
|
setUnloadFilamentStockFormValues((prevValues) => ({
|
|
...prevValues,
|
|
...changedValues
|
|
}))
|
|
}
|
|
initialValues={initialUnloadFilamentStockForm}
|
|
>
|
|
<div style={{ minHeight: '260px' }}>{steps[currentStep].content}</div>
|
|
|
|
<Flex justify={'end'}>
|
|
<Button
|
|
style={{
|
|
margin: '0 8px'
|
|
}}
|
|
onClick={() => setCurrentStep(currentStep - 1)}
|
|
disabled={!(currentStep > 0)}
|
|
>
|
|
Previous
|
|
</Button>
|
|
{currentStep === steps.length - 1 && (
|
|
<Button
|
|
type='primary'
|
|
loading={unloadFilamentStockLoading}
|
|
disabled={!nextEnabled}
|
|
onClick={() => {
|
|
unloadFilamentStockForm.submit()
|
|
}}
|
|
>
|
|
{unloadFilamentStockLoading ? 'Unloading...' : 'Unload'}
|
|
</Button>
|
|
)}
|
|
</Flex>
|
|
</Form>
|
|
</Flex>
|
|
</Flex>
|
|
)
|
|
}
|
|
|
|
export default UnloadFilamentStock
|