import BLE from './ble.js'; import UI from './ui.js'; import IK from './kinematics.js'; import Settings from './settings.js'; let isRunning = false; function delayMs(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } export default { get isRunning() { return isRunning; }, stop() { isRunning = false; }, async run(sequence, spotsData, currentSteps1, currentSteps2, onStepComplete) { if (isRunning) { UI.log('A sequence is already running.', 'warn'); return false; } isRunning = true; UI.log(`Running sequence: ${sequence.name}`, 'info'); let steps1 = currentSteps1; let steps2 = currentSteps2; for (let i = 0; i < sequence.steps.length; i++) { if (!isRunning) { UI.log('Sequence stopped.', 'info'); break; } const step = sequence.steps[i]; let targetX, targetY, label; if (step.type === 'spot') { const spot = spotsData.find(s => s.id === step.id); if (!spot) { UI.log(`Sequence error: Spot '${step.id}' not found. Skipping.`, 'error'); continue; } targetX = spot.x; targetY = spot.y; label = spot.label || spot.id; } else if (step.type === 'xy') { targetX = step.x; targetY = step.y; label = `(${targetX}, ${targetY})`; } else { UI.log(`Unknown step type: ${step.type}`, 'error'); continue; } const wsCheck = IK.checkWorkspace(targetX, targetY); if (!wsCheck.ok) { UI.log(`⛔ ${wsCheck.reason} [${label}]`, 'error'); continue; // or break? let's continue } const res = IK.solve(targetX, targetY); if (!res.reachable || IK.armsCrossed(res.theta1, res.theta2)) { UI.log(`Target ${label} is unreachable or crosses arms.`, 'error'); continue; } const newSteps1 = IK.radToSteps(res.theta1); const newSteps2 = IK.radToSteps(res.theta2); const delta1 = newSteps1 - steps1; const delta2 = newSteps2 - steps2; steps1 = newSteps1; steps2 = newSteps2; if (onStepComplete) { onStepComplete(steps1, steps2); } const cmd1 = `S1${delta1 >= 0 ? '+' : ''}${delta1}`; const cmd2 = `S2${delta2 >= 0 ? '+' : ''}${delta2}`; UI.log(`Seq step: ${label}`, 'info'); if (BLE.isConnected()) { try { await BLE.write(cmd1); await BLE.write(cmd2); } catch (e) { UI.log(`BLE error: ${e.message}`, 'error'); isRunning = false; return false; } } else { console.log(`[sim] ${cmd1} ${cmd2}`); } // Wait for delay const waitTime = typeof step.delay === 'number' ? step.delay : Settings.delay; await delayMs(waitTime); } isRunning = false; UI.log(`Sequence completed.`, 'success'); return true; } };