2025-08-22 20:28:50 +01:00

231 lines
7.0 KiB
JavaScript

import { useContext, useState, useEffect } from 'react'
import { Typography, Spin, Flex, Space, Slider, Descriptions, Tag } from 'antd'
import { LoadingOutlined } from '@ant-design/icons'
import { PrintServerContext } from '../context/PrintServerContext'
import PropTypes from 'prop-types'
const { Text } = Typography
const PrinterMiscPanel = ({
printerId,
showControls = true,
shouldUnsubscribe = true
}) => {
const [miscData, setMiscData] = useState({
fan: {
speed: 0,
target: 0
},
ledBacklight: {
// eslint-disable-line camelcase
brightness: 0
},
beeper: {
value: 0
},
filamentSensor: {
enabled: false,
filamentDetected: false
},
heaterFan: {
speed: 0
}
})
const [initialized, setInitialized] = useState(false)
const { printServer } = useContext(PrintServerContext)
const [fanSpeed, setFanSpeed] = useState(0)
const [ledBrightness, setLedBrightness] = useState(0)
const [beeperValue, setBeeperValue] = useState(0)
useEffect(() => {
const params = {
printerId,
objects: {
fan: null,
'filament_switch_sensor fsensor': null,
'output_pin BEEPER_pin': null,
'output_pin LCD_backlight_pin': null,
'heater_fan nozzle_cooling_fan': null
}
}
const notifyMiscStatusUpdate = (statusUpdate) => {
if (statusUpdate?.fan) {
setMiscData((prevData) => ({
...prevData,
fan: statusUpdate.fan
}))
setFanSpeed(statusUpdate.fan.speed)
}
if (statusUpdate?.['heater_fan nozzle_cooling_fan']) {
setMiscData((prevData) => ({
...prevData,
heaterFan: statusUpdate['heater_fan nozzle_cooling_fan']
}))
}
if (statusUpdate?.['output_pin LCD_backlight_pin']) {
setMiscData((prevData) => ({
...prevData,
ledBacklight: statusUpdate['output_pin LCD_backlight_pin'].value
}))
setLedBrightness(statusUpdate['output_pin LCD_backlight_pin'].value)
}
if (statusUpdate?.['output_pin BEEPER_pin']) {
setMiscData((prevData) => ({
...prevData,
beeper: statusUpdate['output_pin BEEPER_pin']
}))
setBeeperValue(statusUpdate['output_pin BEEPER_pin'].value)
}
if (statusUpdate?.['filament_switch_sensor fsensor']) {
setMiscData((prevData) => ({
...prevData,
filamentSensor: {
enabled: statusUpdate['filament_switch_sensor fsensor'].enabled,
filamentDetected:
statusUpdate['filament_switch_sensor fsensor'].filament_detected
}
}))
}
}
if (!initialized && printServer.connected) {
setInitialized(true)
printServer.on('connect', () => {
printServer.emit('printer.objects.subscribe', params)
printServer.emit('printer.objects.query', params)
})
printServer.emit('printer.objects.subscribe', params)
printServer.emit('printer.objects.query', params)
printServer.on('notify_status_update', notifyMiscStatusUpdate)
}
return () => {
if (printServer.connected && initialized && shouldUnsubscribe) {
printServer.off('notify_status_update', notifyMiscStatusUpdate)
printServer.emit('printer.objects.unsubscribe', params)
}
}
}, [printServer, initialized, printerId, shouldUnsubscribe])
const handleSetFanSpeed = (value) => {
if (printServer) {
printServer.emit('printer.gcode.script', {
printerId,
script: `M106 S${Math.round(value * 255)}`
})
}
}
const handleSetLedBrightness = (value) => {
if (printServer) {
printServer.emit('printer.gcode.script', {
printerId,
script: `SET_LED LED=led_backlight BRIGHTNESS=${value}`
})
}
}
const handleSetBeeperValue = (value) => {
if (printServer) {
printServer.emit('printer.gcode.script', {
printerId,
script: `M300 S440 P200 V${Math.round(value * 100)}`
})
}
}
return (
<div style={{ minWidth: 190 }}>
{miscData ? (
<Flex vertical gap='middle'>
<Flex vertical gap={'middle'}>
{showControls && (
<>
<Space direction='vertical' style={{ width: '100%' }}>
<Text>Fan Speed: {Math.round(fanSpeed * 100)}%</Text>
<Slider
value={fanSpeed}
min={0}
max={1}
step={0.01}
onChange={setFanSpeed}
onAfterChange={handleSetFanSpeed}
tooltip={{ open: false }}
/>
<Text>LED Backlight: {Math.round(ledBrightness * 100)}%</Text>
<Slider
value={ledBrightness}
min={0}
max={1}
step={0.01}
onChange={setLedBrightness}
onAfterChange={handleSetLedBrightness}
tooltip={{ open: false }}
/>
<Text>Beeper Pitch: {Math.round(beeperValue * 100)}%</Text>
<Slider
value={beeperValue}
min={0}
max={1}
step={0.01}
onChange={setBeeperValue}
onAfterChange={handleSetBeeperValue}
tooltip={{ open: false }}
/>
</Space>
</>
)}
<Descriptions column={1} size='small' bordered>
<Descriptions.Item label='Filament Sensor'>
{miscData.filamentSensor.enabled ? (
miscData.filamentSensor.filamentDetected ? (
<Tag color='green'>Detected</Tag>
) : (
<Tag color='red'>Open</Tag>
)
) : (
<Tag color='default'>Disabled</Tag>
)}
</Descriptions.Item>
<Descriptions.Item label='Part Cooling Fan'>
{miscData.fan.speed > 0 ? (
<Text>Running ({Math.round(miscData.fan.speed * 100)}%)</Text>
) : (
<Text>Off</Text>
)}
</Descriptions.Item>
<Descriptions.Item label='Nozzle Cooling Fan'>
{miscData.heaterFan.speed > 0 ? (
<Text>
Running ({Math.round(miscData.heaterFan.speed * 100)}%)
</Text>
) : (
<Text>Off</Text>
)}
</Descriptions.Item>
</Descriptions>
</Flex>
</Flex>
) : (
<Flex justify='centre'>
<Spin indicator={<LoadingOutlined spin />} size='large' />
</Flex>
)}
</div>
)
}
PrinterMiscPanel.propTypes = {
printerId: PropTypes.string.isRequired,
showControls: PropTypes.bool,
shouldUnsubscribe: PropTypes.bool
}
export default PrinterMiscPanel