diff --git a/src/components/Dashboard/Production/Printers/ControlPrinter.jsx b/src/components/Dashboard/Production/Printers/ControlPrinter.jsx index de59103..25078bf 100644 --- a/src/components/Dashboard/Production/Printers/ControlPrinter.jsx +++ b/src/components/Dashboard/Production/Printers/ControlPrinter.jsx @@ -19,7 +19,7 @@ import PrinterIcon from '../../../Icons/PrinterIcon.jsx' import PrinterTemperaturePanel from '../../common/PrinterTemperaturePanel.jsx' import PrinterPositionPanel from '../../common/PrinterPositionPanel.jsx' import PrinterMovementPanel from '../../common/PrinterMovementPanel.jsx' - +import PrinterMiscPanel from '../../common/PrinterMiscPanel.jsx' import JobIcon from '../../../Icons/JobIcon.jsx' import SubJobIcon from '../../../Icons/SubJobIcon.jsx' import FilamentStockIcon from '../../../Icons/FilamentStockIcon.jsx' @@ -50,7 +50,8 @@ const ControlPrinter = () => { filamentStock: true, temperature: true, position: true, - movement: true + movement: true, + misc: true } ) @@ -58,7 +59,8 @@ const ControlPrinter = () => { const [sideBarVisible, setSideBarVisible] = useState( collapseState.temperature || collapseState.position || - collapseState.movement + collapseState.movement || + collapseState.misc ) const [loadFilamentStockOpen, setLoadFilamentStockOpen] = useState(false) @@ -68,7 +70,8 @@ const ControlPrinter = () => { setSideBarVisible( collapseState.temperature || collapseState.position || - collapseState.movement + collapseState.movement || + collapseState.misc ) }, [collapseState]) @@ -168,18 +171,23 @@ const ControlPrinter = () => { const sideBarItems = ( {collapseState.temperature && ( - + )} {collapseState.position && ( - - + + )} {collapseState.movement && ( - - + + + + )} + {collapseState.misc && ( + + )} @@ -236,6 +244,10 @@ const ControlPrinter = () => { key: 'movement', label: 'Movement' }, + { + key: 'misc', + label: 'Misc' + }, { key: 'notes', label: 'Notes' } ]} visibleState={collapseState} diff --git a/src/components/Dashboard/common/PrinterMiscPanel.jsx b/src/components/Dashboard/common/PrinterMiscPanel.jsx index cacbd4f..967749e 100644 --- a/src/components/Dashboard/common/PrinterMiscPanel.jsx +++ b/src/components/Dashboard/common/PrinterMiscPanel.jsx @@ -1,22 +1,21 @@ 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 { ApiServerContext } from '../context/ApiServerContext' import PropTypes from 'prop-types' +import merge from 'lodash/merge' const { Text } = Typography -const PrinterMiscPanel = ({ - printerId, - showControls = true, - shouldUnsubscribe = true -}) => { +const PrinterMiscPanel = ({ id, showControls = true }) => { + const { subscribeToObjectEvent, connected, sendObjectAction } = + useContext(ApiServerContext) const [miscData, setMiscData] = useState({ fan: { speed: 0, target: 0 }, - ledBacklight: { + lcdBacklight: { // eslint-disable-line camelcase brightness: 0 }, @@ -27,112 +26,81 @@ const PrinterMiscPanel = ({ enabled: false, filamentDetected: false }, - heaterFan: { + coolingFan: { speed: 0 } }) - const [initialized, setInitialized] = useState(false) - const { printServer } = useContext(PrintServerContext) const [fanSpeed, setFanSpeed] = useState(0) - const [ledBrightness, setLedBrightness] = useState(0) + const [lcdBrightness, setLcdBrightness] = 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 + if (id && connected == true) { + console.log('subscribing to misc event') + const miscEventUnsubscribe = subscribeToObjectEvent( + id, + 'printer', + 'misc', + (event) => { + console.log('misc event', event) + setMiscData((prev) => { + const merged = merge({}, prev, event.data) + return merged + }) + } + ) + return () => { + if (miscEventUnsubscribe) miscEventUnsubscribe() } } + }, [id, connected, subscribeToObjectEvent]) - 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 - } - })) - } + useEffect(() => { + if (miscData.fan?.speed !== undefined) { + setFanSpeed(miscData.fan.speed) } - - 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) + if (miscData.lcdBacklight?.brightness !== undefined) { + setLcdBrightness(miscData.lcdBacklight.brightness) } - - return () => { - if (printServer.connected && initialized && shouldUnsubscribe) { - printServer.off('notify_status_update', notifyMiscStatusUpdate) - printServer.emit('printer.objects.unsubscribe', params) - } + if (miscData.beeper?.value !== undefined) { + setBeeperValue(miscData.beeper.value) } - }, [printServer, initialized, printerId, shouldUnsubscribe]) + }, [ + miscData.fan?.speed, + miscData.lcdBacklight?.brightness, + miscData.beeper?.value + ]) const handleSetFanSpeed = (value) => { - if (printServer) { - printServer.emit('printer.gcode.script', { - printerId, - script: `M106 S${Math.round(value * 255)}` + if (id && connected == true) { + sendObjectAction(id, 'printer', { + type: 'gcodeScript', + data: { + 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 handleSetLcdBrightness = (value) => { + if (id && connected == true) { + sendObjectAction(id, 'printer', { + type: 'gcodeScript', + data: { + script: `SET_LCD LCD=lcd_backlight BRIGHTNESS=${value}` + } }) } } const handleSetBeeperValue = (value) => { - if (printServer) { - printServer.emit('printer.gcode.script', { - printerId, - script: `M300 S440 P200 V${Math.round(value * 100)}` + if (id && connected == true) { + sendObjectAction(id, 'printer', { + type: 'gcodeScript', + data: { + script: `M300 S440 P200 V${Math.round(value * 100)}` + } }) } } @@ -156,14 +124,14 @@ const PrinterMiscPanel = ({ tooltip={{ open: false }} /> - LED Backlight: {Math.round(ledBrightness * 100)}% + LCD Backlight: {Math.round(lcdBrightness * 100)}% @@ -201,9 +169,9 @@ const PrinterMiscPanel = ({ )} - {miscData.heaterFan.speed > 0 ? ( + {miscData.coolingFan.speed > 0 ? ( - Running ({Math.round(miscData.heaterFan.speed * 100)}%) + Running ({Math.round(miscData.coolingFan.speed * 100)}%) ) : ( Off @@ -222,9 +190,8 @@ const PrinterMiscPanel = ({ } PrinterMiscPanel.propTypes = { - printerId: PropTypes.string.isRequired, - showControls: PropTypes.bool, - shouldUnsubscribe: PropTypes.bool + id: PropTypes.string.isRequired, + showControls: PropTypes.bool } export default PrinterMiscPanel diff --git a/src/components/Dashboard/common/PrinterMovementPanel.jsx b/src/components/Dashboard/common/PrinterMovementPanel.jsx index d22cbb0..de6e10c 100644 --- a/src/components/Dashboard/common/PrinterMovementPanel.jsx +++ b/src/components/Dashboard/common/PrinterMovementPanel.jsx @@ -10,7 +10,6 @@ import { Card, message // eslint-disable-line } from 'antd' -import { PrintServerContext } from '../context/PrintServerContext' import PropTypes from 'prop-types' import LevelBedIcon from '../../Icons/LevelBedIcon' import ArrowLeftIcon from '../../Icons/ArrowLeftIcon' @@ -18,14 +17,12 @@ import ArrowRightIcon from '../../Icons/ArrowRightIcon' import ArrowUpIcon from '../../Icons/ArrowUpIcon' import ArrowDownIcon from '../../Icons/ArrowDownIcon' import HomeIcon from '../../Icons/HomeIcon' +import { ApiServerContext } from '../context/ApiServerContext' -const PrinterMovementPanel = ({ printerId }) => { +const PrinterMovementPanel = ({ id }) => { + const { connected, sendObjectAction } = useContext(ApiServerContext) const [posValue, setPosValue] = useState(10) const [rateValue, setRateValue] = useState(1000) - const { printServer } = useContext(PrintServerContext) - - //const messageApi = message.useMessage() - const handlePosRadioChange = (e) => { const value = e.target.value setPosValue(value) // Update posValue state when radio button changes @@ -40,20 +37,26 @@ const PrinterMovementPanel = ({ printerId }) => { } const handleHomeAxisClick = (axis) => { - if (printServer) { - printServer.emit('printer.gcode.script', { - printerId, - script: `G28 ${axis}` + if (id && connected == true) { + sendObjectAction(id, 'printer', { + type: 'homeAxis', + data: { + axis: axis + } }) } } const handleMoveAxisClick = (axis, minus) => { const distanceValue = !minus ? posValue * -1 : posValue - if (printServer) { - printServer.emit('printer.gcode.script', { - printerId, - script: `_CLIENT_LINEAR_MOVE ${axis}=${distanceValue} F=${rateValue}` + if (id && connected == true) { + sendObjectAction(id, 'printer', { + type: 'moveAxis', + data: { + axis: axis, + distance: distanceValue, + rate: rateValue + } }) } //sendCommand('moveAxis', { axis, pos, rate }) @@ -93,7 +96,7 @@ const PrinterMovementPanel = ({ printerId }) => { return (
- + { min={0.1} max={100} value={posValue} - formatter={(value) => `${value} mm`} - parser={(value) => value?.replace(' mm', '')} + suffix='mm' onChange={handlePosInputChange} placeholder='10 mm' name='posInput' - style={{ flexGrow: 1 }} + style={{ flexGrow: 1, minWidth: '125px' }} /> `${value} mm/s`} - parser={(value) => value?.replace(' mm/s', '')} + suffix='mm/s' onChange={handleRateInputChange} placeholder='100 mm/s' name='rateInput' - style={{ flexGrow: 1 }} + style={{ flexGrow: 1, minWidth: '125px' }} /> @@ -237,7 +238,7 @@ const PrinterMovementPanel = ({ printerId }) => { } PrinterMovementPanel.propTypes = { - printerId: PropTypes.string.isRequired + id: PropTypes.string.isRequired } export default PrinterMovementPanel diff --git a/src/components/Dashboard/common/PrinterPositionPanel.jsx b/src/components/Dashboard/common/PrinterPositionPanel.jsx index 570ead4..8995e6c 100644 --- a/src/components/Dashboard/common/PrinterPositionPanel.jsx +++ b/src/components/Dashboard/common/PrinterPositionPanel.jsx @@ -7,14 +7,16 @@ import { Collapse, InputNumber, Descriptions, - Button + Button, + Divider } from 'antd' -import { LoadingOutlined, CaretLeftOutlined } from '@ant-design/icons' -import { PrintServerContext } from '../context/PrintServerContext' +import { LoadingOutlined, CaretRightOutlined } from '@ant-design/icons' +import { ApiServerContext } from '../context/ApiServerContext' import styled from 'styled-components' import PropTypes from 'prop-types' import BoolDisplay from './BoolDisplay' - +import merge from 'lodash/merge' +import { round } from '../utils/Utils' const { Text } = Typography const CustomCollapse = styled(Collapse)` @@ -29,91 +31,151 @@ const CustomCollapse = styled(Collapse)` ` const PrinterPositionPanel = ({ - printerId, + id, showControls = true, - showMoreInfo = true, - shouldUnsubscribe = true + showMoreInfo = true }) => { + const { subscribeToObjectEvent, connected, sendObjectAction } = + useContext(ApiServerContext) const [positionData, setPositionData] = useState({ - speed_factor: 1.0, // eslint-disable-line + speedFactor: 1.0, // eslint-disable-line speed: 100, - extrude_factor: 1.0, // eslint-disable-line - absolute_foordinates: true, // eslint-disable-line - absolute_extrude: false, // eslint-disable-line - homing_origin: [0.0, 0.0, 0.0, 0.0], // eslint-disable-line - position: [0.0, 0.0, 0.0, 0.0], - gcode_position: [0.0, 0.0, 0.0, 0.0] // eslint-disable-line + extrudeFactor: 1.0, // eslint-disable-line + absoluteCoordinates: true, // eslint-disable-line + absoluteExtrude: false, // eslint-disable-line + homingOrigin: [0.0, 0.0, 0.0, 0.0], // eslint-disable-line + toolheadPosition: [0.0, 0.0, 0.0, 0.0], + gcodePosition: [0.0, 0.0, 0.0, 0.0], // eslint-disable-line + livePosition: [0.0, 0.0, 0.0, 0.0], + maxVelocity: 1000, + maxAcceleration: 1000, + squareCornerVelocity: 100, + minCruiseRatio: 0 }) - const [initialized, setInitialized] = useState(false) - const { printServer } = useContext(PrintServerContext) - const [speedFactor, setSpeedFactor] = useState(positionData.speed_factor) - const [extrudeFactor, setExtrudeFactor] = useState( - positionData.extrude_factor + useEffect(() => { + if (id && connected == true) { + console.log('subscribing to motion event') + const motionEventUnsubscribe = subscribeToObjectEvent( + id, + 'printer', + 'motion', + (event) => { + console.log('motion event', event) + setPositionData((prev) => { + const merged = merge({}, prev, event.data) + return merged + }) + } + ) + return () => { + if (motionEventUnsubscribe) motionEventUnsubscribe() + } + } + }, [id, connected]) + const [speedFactor, setSpeedFactor] = useState(positionData.speedFactor) + const [extrudeFactor, setExtrudeFactor] = useState(positionData.extrudeFactor) + const [maxVelocity, setMaxVelocity] = useState(positionData.maxVelocity) + const [maxAcceleration, setMaxAcceleration] = useState( + positionData.maxAcceleration + ) + const [squareCornerVelocity, setSquareCornerVelocity] = useState( + positionData.squareCornerVelocity + ) + const [minCruiseRatio, setMinCruiseRatio] = useState( + positionData.minCruiseRatio ) useEffect(() => { - const params = { - printerId, - objects: { - toolhead: null, - gcode_move: null // eslint-disable-line - } + if (positionData.speedFactor !== undefined) { + setSpeedFactor(positionData.speedFactor) } - - const notifyPositionStatusUpdate = (statusUpdate) => { - if (statusUpdate?.toolhead) { - setPositionData((prevData) => ({ - ...prevData, - ...statusUpdate.toolhead - })) - } - if (statusUpdate?.gcode_move) { - setPositionData((prevData) => ({ - ...prevData, - ...statusUpdate.gcode_move - })) - } + if (positionData.extrudeFactor !== undefined) { + setExtrudeFactor(positionData.extrudeFactor) } - - 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', notifyPositionStatusUpdate) + if (positionData.maxVelocity !== undefined) { + setMaxVelocity(positionData.maxVelocity) } - - setSpeedFactor(positionData.speed_factor) - setExtrudeFactor(positionData.extrude_factor) - - return () => { - if (printServer?.connected && initialized && shouldUnsubscribe) { - printServer.off('notify_status_update', notifyPositionStatusUpdate) - printServer.emit('printer.objects.unsubscribe', params) - } + if (positionData.maxAcceleration !== undefined) { + setMaxAcceleration(positionData.maxAcceleration) } - }, [printServer, initialized, printerId, shouldUnsubscribe]) + if (positionData.squareCornerVelocity !== undefined) { + setSquareCornerVelocity(positionData.squareCornerVelocity) + } + if (positionData.minCruiseRatio !== undefined) { + setMinCruiseRatio(positionData.minCruiseRatio) + } + }, [ + positionData.speedFactor, + positionData.extrudeFactor, + positionData.maxVelocity, + positionData.maxAcceleration, + positionData.squareCornerVelocity, + positionData.minCruiseRatio + ]) const handleSetSpeedFactor = () => { - if (printServer) { - printServer.emit('printer.gcode.script', { - printerId, - script: `M220 S${speedFactor * 100}` + if (id && connected == true) { + sendObjectAction(id, 'printer', { + type: 'setSpeedFactor', + data: { + speedFactor: speedFactor * 100 + } }) } } const handleSetExtrudeFactor = () => { - if (printServer) { - printServer.emit('printer.gcode.script', { - printerId, - script: `M221 S${extrudeFactor * 100}` + if (id && connected == true) { + sendObjectAction(id, 'printer', { + type: 'setExtrudeFactor', + data: { + extrudeFactor: extrudeFactor * 100 + } + }) + } + } + + const handleSetMaxVelocity = () => { + if (id && connected == true) { + sendObjectAction(id, 'printer', { + type: 'setMaxVelocity', + data: { + maxVelocity: maxVelocity + } + }) + } + } + + const handleSetMaxAcceleration = () => { + if (id && connected == true) { + sendObjectAction(id, 'printer', { + type: 'setMaxAcceleration', + data: { + maxAcceleration: maxAcceleration + } + }) + } + } + + const handleSetSquareCornerVelocity = () => { + if (id && connected == true) { + sendObjectAction(id, 'printer', { + type: 'setSquareCornerVelocity', + data: { + squareCornerVelocity: squareCornerVelocity + } + }) + } + } + + const handleSetMinCruiseRatio = () => { + if (id && connected == true) { + sendObjectAction(id, 'printer', { + type: 'setMinCruiseRatio', + data: { + minCruiseRatio: minCruiseRatio + } }) } } @@ -124,22 +186,132 @@ const PrinterPositionPanel = ({ label: 'More Position Data', children: ( <> + GCode Position: - {positionData.gcode_position[0].toFixed(2)}mm + {' '} + {round(positionData.gcodePosition[0], 2)}mm + - {positionData.gcode_position[1].toFixed(2)}mm + {round(positionData.gcodePosition[1], 2)}mm - {positionData.gcode_position[2].toFixed(2)}mm + {round(positionData.gcodePosition[2], 2)}mm - {positionData.gcode_position[3].toFixed(2)}mm + {round(positionData.gcodePosition[3], 2)}mm + {showControls && ( + <> + + + Max Velocity: + + setMaxVelocity(value)} + onPressEnter={handleSetMaxVelocity} + size='small' + /> + + + + + + + Max Acceleration: + + setMaxAcceleration(value)} + onPressEnter={handleSetMaxAcceleration} + size='small' + /> + + + + + + + + Sqr Corner Vel: + + setSquareCornerVelocity(value)} + onPressEnter={handleSetSquareCornerVelocity} + size='small' + /> + + + + + + + + Min Cruise Ratio: + + setMinCruiseRatio(value / 100)} + onPressEnter={handleSetMinCruiseRatio} + size='small' + /> + + + + + + + )} Homing Origin: - {positionData.homing_origin[0].toFixed(2)}mm + {round(positionData.homingOrigin[0], 2)}mm - {positionData.homing_origin[1].toFixed(2)}mm + {round(positionData.homingOrigin[1], 2)}mm - {positionData.homing_origin[2].toFixed(2)}mm + {round(positionData.homingOrigin[2], 2)}mm - {positionData.homing_origin[3].toFixed(2)}mm + {round(positionData.homingOrigin[3], 2)}mm @@ -173,16 +345,36 @@ const PrinterPositionPanel = ({ - {positionData.position[0].toFixed(2)}mm + + {round(positionData.livePosition[0], 2)}mm + + {round(positionData.toolheadPosition[0], 2)}mm + + - {positionData.position[1].toFixed(2)}mm + + {round(positionData.livePosition[1], 2)}mm + + {round(positionData.toolheadPosition[1], 2)}mm + + - {positionData.position[2].toFixed(2)}mm + + {round(positionData.livePosition[2], 2)}mm + + {round(positionData.toolheadPosition[2], 2)}mm + + - {positionData.position[3].toFixed(2)}mm + + {round(positionData.livePosition[3], 2)}mm + + {round(positionData.toolheadPosition[3], 2)}mm + + {showControls && ( @@ -192,11 +384,12 @@ const PrinterPositionPanel = ({ Speed Factor: setSpeedFactor(value)} onPressEnter={handleSetSpeedFactor} size='small' @@ -215,11 +408,12 @@ const PrinterPositionPanel = ({ Extrude Factor: setExtrudeFactor(value)} onPressEnter={handleSetExtrudeFactor} size='small' @@ -237,13 +431,23 @@ const PrinterPositionPanel = ({ )} - - {positionData.speed.toFixed(2)}mm/s + + {round(positionData.speed, 2)}mm/s - + {positionData ? ( + ) : ( + n/a + )} + + + {positionData ? ( + ) : ( @@ -259,7 +463,7 @@ const PrinterPositionPanel = ({ size='small' items={moreInfoItems} expandIcon={({ isActive }) => ( - + )} /> )} @@ -274,10 +478,9 @@ const PrinterPositionPanel = ({ } PrinterPositionPanel.propTypes = { - printerId: PropTypes.string.isRequired, + id: PropTypes.string.isRequired, showControls: PropTypes.bool, - showMoreInfo: PropTypes.bool, - shouldUnsubscribe: PropTypes.bool + showMoreInfo: PropTypes.bool } export default PrinterPositionPanel diff --git a/src/components/Dashboard/common/PrinterTemperaturePanel.jsx b/src/components/Dashboard/common/PrinterTemperaturePanel.jsx index 48ce07d..1d1f865 100644 --- a/src/components/Dashboard/common/PrinterTemperaturePanel.jsx +++ b/src/components/Dashboard/common/PrinterTemperaturePanel.jsx @@ -8,7 +8,8 @@ import { Space, Collapse, InputNumber, - Button + Button, + Divider } from 'antd' import { LoadingOutlined, CaretRightOutlined } from '@ant-design/icons' import styled from 'styled-components' @@ -113,6 +114,7 @@ const PrinterTemperaturePanel = ({ label: 'More Temperature Data', children: ( <> + Hot End Power:{' '} diff --git a/src/components/Dashboard/utils/Utils.js b/src/components/Dashboard/utils/Utils.js index 52e2e2f..36ec864 100644 --- a/src/components/Dashboard/utils/Utils.js +++ b/src/components/Dashboard/utils/Utils.js @@ -30,5 +30,9 @@ export function timeStringToMinutes(timeString) { return Math.floor(totalMinutes) } +export function round(num, decimals) { + return Math.round(num * 10 ** decimals) / 10 ** decimals +} + // Re-export the functions for backward compatibility export {}