Files
appRobotDriver/robot/GCodeParser.js
2026-06-14 10:32:31 +02:00

91 lines
2.2 KiB
JavaScript

class GCodeParser {
static normalizeInput(raw) {
if (raw === undefined || raw === null) {
return '';
}
if (Buffer.isBuffer(raw)) {
raw = raw.toString('utf8');
}
return String(raw).trim();
}
static splitCommands(input) {
if (!input) {
return [];
}
// Preserve leading G/M on each segment.
return input
.trim()
.split(/ (?=G|M)/i)
.map(segment => segment.trim())
.filter(Boolean);
}
static parseCommand(commandString) {
if (!commandString || commandString.length === 0) {
return null;
}
const tokens = commandString.trim().split(/\s+/);
if (tokens.length === 0) {
return null;
}
const commandToken = tokens[0].toUpperCase();
if (!/^[GM]\d+/i.test(commandToken)) {
return null;
}
const params = {};
for (let i = 1; i < tokens.length; i++) {
const token = tokens[i].trim();
if (token.length === 0) {
continue;
}
if (token.length === 1) {
// Einzelner Buchstabe = Flag ohne Zahlenwert (z. B. 'R' in 'M114 R').
if (/^[A-Za-z]$/.test(token)) {
params[token.toUpperCase()] = true;
}
continue;
}
const key = token.charAt(0).toUpperCase();
const valueString = token.substring(1);
const value = Number(valueString);
if (!Number.isNaN(value)) {
params[key] = value;
}
}
return {
command: commandToken,
params,
raw: commandString.trim()
};
}
static parse(raw) {
const input = this.normalizeInput(raw);
if (!input) {
return [];
}
if (input.startsWith('$J=')) {
return this.parse(input.substring(3).trim());
}
const commands = this.splitCommands(input)
.map(commandString => this.parseCommand(commandString))
.filter(Boolean);
return commands;
}
}
module.exports = GCodeParser;