Files
quibot/backend/src/controllers/text-command.controller.ts
2026-06-18 14:09:54 +02:00

102 lines
3.5 KiB
TypeScript

import { Router } from 'express';
import { raspiService } from '../services/raspi.service.js';
const router = Router();
const commandMap = [
// Catalan forward
{ words: ['endavant', 'avança'], action: 'forward' },
// Catalan backward
{ words: ['atras', 'enrere', 'atras'], action: 'backward' },
// Catalan left
{ words: ['esquerra', 'esquerre', 'stoppa'], action: 'left' },
// Catalan right
{ words: ['dreta', 'destre'], action: 'right' },
// Stop
{ words: ['atura', 'atura', 'pare', 'stop', 'parada', 'aturar'], action: 'stop' },
// Pick up / grab
{ words: ['recull', 'pega', 'pilla', 'agafa'], action: 'pick' },
// Eject / throw
{ words: ['llança', 'tira', 'expulsa', ' llença'], action: 'eject' },
// Spanish forward
{ words: ['adelante'], action: 'forward' },
// Spanish backward
{ words: ['atras', 'atrás', 'reversa', 'al tras'], action: 'backward' },
// Spanish left
{ words: ['izquierda', 'izq'], action: 'left' },
// Spanish right
{ words: ['derecha', 'der'], action: 'right' },
// Spanish stop
{ words: ['para', 'stop', 'pare', 'deten', 'frena', 'alto'], action: 'stop' },
];
function resolveCommand(text: string) {
const lower = text.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
for (const entry of commandMap) {
for (const word of entry.words) {
const normalizedWord = word.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
if (lower.includes(normalizedWord)) {
return entry.action;
}
}
}
return null;
}
router.post('/text', async (req, res) => {
const { text } = req.body;
if (!text || typeof text !== 'string') {
return res.status(400).json({ error: 'Text is required' });
}
const action = resolveCommand(text);
if (!action) {
return res.json({ recognized: text.trim(), action: null, message: 'No motor command matched. Use: endavant, atras, esquerra, dreta, atura, recull, llança' });
}
try {
switch (action) {
case 'forward': {
const result = await raspiService.motorStepForward();
return res.json({ recognized: text.trim(), action: 'forward', result });
}
case 'backward': {
const result = await raspiService.motorStepBackward();
return res.json({ recognized: text.trim(), action: 'backward', result });
}
case 'left': {
await raspiService.motorStepForward();
await new Promise(r => setTimeout(r, 600));
await raspiService.motorStop();
return res.json({ recognized: text.trim(), action: 'turn-left', result: { status: 'turned left' } });
}
case 'right': {
await raspiService.motorStepBackward();
await new Promise(r => setTimeout(r, 600));
await raspiService.motorStop();
return res.json({ recognized: text.trim(), action: 'turn-right', result: { status: 'turned right' } });
}
case 'stop': {
const result = await raspiService.motorStop();
return res.json({ recognized: text.trim(), action: 'stop', result });
}
case 'pick': {
return res.json({ recognized: text.trim(), action: 'pick', message: 'Pick command received' });
}
case 'eject': {
return res.json({ recognized: text.trim(), action: 'eject', message: 'Eject command received' });
}
}
} catch (err: unknown) {
const message = err instanceof Error ? err.message : 'Unknown error';
return res.status(500).json({
recognized: text.trim(),
action,
error: `Command execution failed: ${message}`,
});
}
});
export default router;