Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 22 additions & 6 deletions apps/web/src/routes/Monitor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
usePlannerQueue,
useRxBufferSize,
useFeedrate,
useAvailableAxes,
} from '@/store/hooks'
import { machineStateSync } from '@/services/machineStateSync'
import { Vector3 } from 'three'
Expand Down Expand Up @@ -600,6 +601,7 @@ function ProgressPanel({
const {
machinePosition = { x: 0, y: 0, z: 0 },
workPosition = { x: 0, y: 0, z: 0 },
availableAxes = ['x', 'y', 'z'],
spindleState = 'M5',
spindleSpeed = 0,
senderState,
Expand All @@ -611,12 +613,24 @@ function ProgressPanel({
const isOn = spindleState === 'M3' || spindleState === 'M4'
const direction = spindleState === 'M4' ? 'CCW' : 'CW'

// Axis data
const axes = [
{ axis: 'X' as const, color: 'text-red-500', bgColor: 'bg-red-500/10', borderColor: 'border-red-500/30', mpos: machinePosition.x, wpos: workPosition.x },
{ axis: 'Y' as const, color: 'text-green-500', bgColor: 'bg-green-500/10', borderColor: 'border-green-500/30', mpos: machinePosition.y, wpos: workPosition.y },
{ axis: 'Z' as const, color: 'text-blue-500', bgColor: 'bg-blue-500/10', borderColor: 'border-blue-500/30', mpos: machinePosition.z, wpos: workPosition.z },
]
// Axis color/style configuration
const AXIS_STYLES: Record<string, { color: string; bgColor: string; borderColor: string }> = {
X: { color: 'text-red-500', bgColor: 'bg-red-500/10', borderColor: 'border-red-500/30' },
Y: { color: 'text-green-500', bgColor: 'bg-green-500/10', borderColor: 'border-green-500/30' },
Z: { color: 'text-blue-500', bgColor: 'bg-blue-500/10', borderColor: 'border-blue-500/30' },
A: { color: 'text-orange-500', bgColor: 'bg-orange-500/10', borderColor: 'border-orange-500/30' },
B: { color: 'text-purple-500', bgColor: 'bg-purple-500/10', borderColor: 'border-purple-500/30' },
C: { color: 'text-cyan-500', bgColor: 'bg-cyan-500/10', borderColor: 'border-cyan-500/30' },
}

// Axis data - dynamically built from available axes
const axes = (availableAxes as string[]).map(a => {
const upper = a.toUpperCase()
const style = AXIS_STYLES[upper] || AXIS_STYLES.X
const mpos = (machinePosition as Record<string, number | undefined>)[a] ?? 0
const wpos = (workPosition as Record<string, number | undefined>)[a] ?? 0
return { axis: upper, ...style, mpos, wpos }
})

// Time data from backend (in milliseconds)
const elapsedMs = senderState?.elapsedTime ?? 0
Expand Down Expand Up @@ -1002,6 +1016,7 @@ export default function Monitor() {
const workflowState = useWorkflowState()
const machinePosition = useMachinePosition()
const workPosition = useWorkPosition()
const availableAxes = useAvailableAxes()
const spindleState = useSpindleState()
const spindleSpeed = useSpindleSpeed()
const maxSpindleSpeed = machineState.maxSpindleSpeed
Expand Down Expand Up @@ -1196,6 +1211,7 @@ export default function Monitor() {
onFlashStatus: flashStatus,
machinePosition,
workPosition,
availableAxes,
spindleState,
spindleSpeed,
senderState: jobState, // Use jobState from Redux
Expand Down
59 changes: 33 additions & 26 deletions apps/web/src/routes/Monitor/panels/CurrentStatsPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,59 +1,66 @@
import { useTranslation } from 'react-i18next'
import type { PanelProps } from '../../Setup/types'

// Axis color mapping for distance display
const AXIS_COLORS: Record<string, string> = {
X: 'text-red-500',
Y: 'text-green-500',
Z: 'text-blue-500',
A: 'text-orange-500',
B: 'text-purple-500',
C: 'text-cyan-500',
}

export function CurrentStatsPanel(props: PanelProps) {
const { t } = useTranslation()
const stats = props.senderState?.stats

const availableAxes = props.availableAxes || ['x', 'y', 'z']

// Get distances from stats
const totalDistance = stats?.totalDistance || { x: 0, y: 0, z: 0, total: 0 }
const cuttingDistance = stats?.cuttingDistance || { x: 0, y: 0, z: 0, total: 0 }
const transitionDistance = stats?.transitionDistance || { x: 0, y: 0, z: 0, total: 0 }
const retractDistance = stats?.retractDistance || { x: 0, y: 0, z: 0, total: 0 }


// Calculate operation type breakdown (for pie chart)
const totalDistanceTotal = totalDistance.total || 1 // Avoid division by zero
const cuttingPercent = totalDistanceTotal > 0 ? (cuttingDistance.total / totalDistanceTotal) * 100 : 0
const transitionPercent = totalDistanceTotal > 0 ? (transitionDistance.total / totalDistanceTotal) * 100 : 0
const retractPercent = totalDistanceTotal > 0 ? (retractDistance.total / totalDistanceTotal) * 100 : 0
const retractPercent = 100 - cuttingPercent - transitionPercent

const operationTypes = [
{ type: t('Cutting'), percent: cuttingPercent, color: 'rgb(59 130 246)', bgColor: 'bg-blue-500', distance: cuttingDistance.total },
{ type: t('Transition'), percent: transitionPercent, color: 'rgb(34 197 94)', bgColor: 'bg-green-500', distance: transitionDistance.total },
{ type: t('Retract'), percent: retractPercent, color: 'rgb(249 115 22)', bgColor: 'bg-orange-500', distance: retractDistance.total },
{ type: t('Retract'), percent: retractPercent > 0 ? retractPercent : 0, color: 'rgb(249 115 22)', bgColor: 'bg-orange-500', distance: (totalDistance.total || 0) - cuttingDistance.total - transitionDistance.total },
].filter(op => op.percent > 0) // Only show operations with distance

// Use real travel distances from stats
const totalTravelX = totalDistance.x || 0
const totalTravelY = totalDistance.y || 0
const totalTravelZ = totalDistance.z || 0
const totalDistanceSum = totalTravelX + totalTravelY + totalTravelZ


// Build per-axis distance data dynamically
const axisDistances = availableAxes.map(a => {
const dist = (totalDistance as Record<string, number>)[a] || 0
const upper = a.toUpperCase()
const isRotary = a === 'a' || a === 'b' || a === 'c'
return { axis: upper, distance: dist, unit: isRotary ? t('deg') : t('mm'), color: AXIS_COLORS[upper] || 'text-muted-foreground' }
})
const totalDistanceSum = axisDistances.reduce((sum, a) => sum + a.distance, 0)

return (
<div className="p-4 space-y-4">
{/* Total distance traveled */}
<div className="space-y-2">
<div className="text-xs text-muted-foreground">{t('Total Distance')}</div>
<div className="space-y-1.5">
<div className="flex items-center justify-between gap-2">
<span className="text-xs text-muted-foreground">X:</span>
<span className="text-xs font-mono font-medium">{totalTravelX.toFixed(1)} {t('mm')}</span>
</div>
<div className="flex items-center justify-between gap-2">
<span className="text-xs text-muted-foreground">Y:</span>
<span className="text-xs font-mono font-medium">{totalTravelY.toFixed(1)} {t('mm')}</span>
</div>
<div className="flex items-center justify-between gap-2">
<span className="text-xs text-muted-foreground">Z:</span>
<span className="text-xs font-mono font-medium">{totalTravelZ.toFixed(1)} {t('mm')}</span>
</div>
{axisDistances.map(({ axis, distance, unit, color }) => (
<div key={axis} className="flex items-center justify-between gap-2">
<span className={`text-xs font-medium ${color}`}>{axis}:</span>
<span className="text-xs font-mono font-medium">{distance.toFixed(1)} {unit}</span>
</div>
))}
<div className="flex items-center justify-between gap-2 pt-1 border-t border-border">
<span className="text-xs font-medium">{t('Total:')}</span>
<span className="text-xs font-mono font-semibold">{totalDistanceSum.toFixed(1)} {t('mm')}</span>
</div>
</div>
</div>

{/* Operation type pie chart */}
<div className="space-y-2">
<div className="text-xs text-muted-foreground">{t('Operation Types')}</div>
Expand Down
6 changes: 5 additions & 1 deletion apps/web/src/routes/Setup/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
useWorkPosition,
useSpindleState,
useSpindleSpeed,
useAvailableAxes,
} from '@/store/hooks'
import { machineStateSync } from '@/services/machineStateSync'
import { setConnecting, setFlashing } from '@/store/machineSlice'
Expand Down Expand Up @@ -443,6 +444,7 @@ export default function Setup() {
const workflowState = useWorkflowState()
const machinePosition = useMachinePosition()
const workPosition = useWorkPosition()
const availableAxes = useAvailableAxes()
const spindleState = useSpindleState()
const spindleSpeed = useSpindleSpeed()

Expand Down Expand Up @@ -1069,6 +1071,7 @@ export default function Setup() {
machinePosition,
workPosition,
currentWCS,
availableAxes,
isJobRunning,
spindleState,
spindleSpeed,
Expand Down Expand Up @@ -1096,7 +1099,8 @@ export default function Setup() {
onFlashStatus: flashStatus,
machinePosition,
workPosition,
currentWCS
currentWCS,
availableAxes,
}}
/>
) : null}
Expand Down
63 changes: 40 additions & 23 deletions apps/web/src/routes/Setup/panels/DROPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,25 @@ const DEFAULT_WORKSPACE_NAMES: Record<string, string> = {
'G55': 'Fixture 2',
}

export function DROPanel({
isConnected,
connectedPort,
machineStatus,
onFlashStatus,
machinePosition = { x: 0, y: 0, z: 0 },
workPosition = { x: 0, y: 0, z: 0 },
currentWCS = 'G54'
// Axis color/style configuration
const AXIS_STYLES: Record<string, { color: string; bgColor: string; borderColor: string }> = {
X: { color: 'text-red-500', bgColor: 'bg-red-500/10', borderColor: 'border-red-500/30' },
Y: { color: 'text-green-500', bgColor: 'bg-green-500/10', borderColor: 'border-green-500/30' },
Z: { color: 'text-blue-500', bgColor: 'bg-blue-500/10', borderColor: 'border-blue-500/30' },
A: { color: 'text-orange-500', bgColor: 'bg-orange-500/10', borderColor: 'border-orange-500/30' },
B: { color: 'text-purple-500', bgColor: 'bg-purple-500/10', borderColor: 'border-purple-500/30' },
C: { color: 'text-cyan-500', bgColor: 'bg-cyan-500/10', borderColor: 'border-cyan-500/30' },
}

export function DROPanel({
isConnected,
connectedPort,
machineStatus,
onFlashStatus,
machinePosition = { x: 0, y: 0, z: 0 },
workPosition = { x: 0, y: 0, z: 0 },
currentWCS = 'G54',
availableAxes = ['x', 'y', 'z'],
}: PanelProps) {
const { t } = useTranslation()
const [editDialogOpen, setEditDialogOpen] = useState(false)
Expand Down Expand Up @@ -63,13 +74,13 @@ export function DROPanel({
const { clearBitsetterReference } = useBitsetterReference()

// Handle zero out work offset for a single axis
const handleZeroAxis = useCallback(async (axis: 'X' | 'Y' | 'Z') => {
const handleZeroAxis = useCallback(async (axis: string) => {
// Clear bitsetter reference if Z zero is being set (bitsetter reference becomes invalid)
if (axis === 'Z') {
await clearBitsetterReference(workspace)
}
const axisLower = axis.toLowerCase() as 'x' | 'y' | 'z'

const axisLower = axis.toLowerCase()
const gcode = buildSetZeroCommand(workspace, axisLower)
if (gcode) {
sendGcode(gcode)
Expand All @@ -80,28 +91,30 @@ export function DROPanel({
const handleZeroAll = useCallback(async () => {
// Clear bitsetter reference when zeroing all axes (includes Z)
await clearBitsetterReference(workspace)

const gcode = buildSetZeroCommand(workspace, 'xyz')

const allAxes = availableAxes.join('')
const gcode = buildSetZeroCommand(workspace, allAxes)
if (gcode) {
sendGcode(gcode)
}
}, [workspace, clearBitsetterReference, sendGcode])
}, [workspace, availableAxes, clearBitsetterReference, sendGcode])

// Handle go to work zero for a single axis
const handleGoToZeroAxis = useCallback((axis: 'X' | 'Y' | 'Z') => {
const handleGoToZeroAxis = useCallback((axis: string) => {
const gcode = buildGoToZeroCommand(axis)
if (gcode) {
sendGcode(gcode)
}
}, [sendGcode])

// Handle go to work zero for all axes
const handleGoToZeroAll = useCallback(() => {
const gcode = buildGoToZeroCommand('XYZ')
const allAxes = availableAxes.map(a => a.toUpperCase()).join('')
const gcode = buildGoToZeroCommand(allAxes)
if (gcode) {
sendGcode(gcode)
}
}, [sendGcode])
}, [availableAxes, sendGcode])

const handleEditClick = () => {
setEditDialogOpen(true)
Expand All @@ -126,11 +139,15 @@ export function DROPanel({
}
}, [workspace, savedWorkspaces, setExtensions])

const axes = [
{ axis: 'X' as const, color: 'text-red-500', bgColor: 'bg-red-500/10', borderColor: 'border-red-500/30', mpos: machinePosition.x, wpos: workPosition.x },
{ axis: 'Y' as const, color: 'text-green-500', bgColor: 'bg-green-500/10', borderColor: 'border-green-500/30', mpos: machinePosition.y, wpos: workPosition.y },
{ axis: 'Z' as const, color: 'text-blue-500', bgColor: 'bg-blue-500/10', borderColor: 'border-blue-500/30', mpos: machinePosition.z, wpos: workPosition.z },
]
const axes = useMemo(() => {
return availableAxes.map(a => {
const upper = a.toUpperCase()
const style = AXIS_STYLES[upper] || AXIS_STYLES.X
const mpos = (machinePosition as Record<string, number | undefined>)[a] ?? 0
const wpos = (workPosition as Record<string, number | undefined>)[a] ?? 0
return { axis: upper, ...style, mpos, wpos }
})
}, [availableAxes, machinePosition, workPosition])

return (
<div className="p-3 space-y-2">
Expand Down
Loading
Loading