const WebSocket = require("ws"); /** * Mock FluidNC WebSocket Server für Tests * Ermöglicht es, FluidNCClient in Tests gegen einen echten WS-Server zu testen */ class MockFluidNC { constructor(host = "localhost", port = 9000) { this.host = host; this.port = port; this.server = null; this.clients = []; this.messageHandlers = []; this.receivedCommands = []; } /** * Startet den Mock-Server * @returns {Promise} */ start() { return new Promise((resolve, reject) => { this.server = new WebSocket.Server({ host: this.host, port: this.port }, () => { console.log(`[MockFluidNC] Server started on ws://${this.host}:${this.port}`); resolve(); }); this.server.on("connection", (ws) => { console.log("[MockFluidNC] Client connected"); this.clients.push(ws); ws.on("message", (msg) => { const msgStr = msg.toString().trim(); console.log(`[MockFluidNC] Received: ${msgStr}`); // Befehl zur Historie hinzufügen this.receivedCommands.push(msgStr); // Handler aufrufen, die registriert wurden this.messageHandlers.forEach(handler => handler(msgStr)); // Automatische Responses für spezielle Befehle this._handleCommand(msgStr, ws); }); ws.on("close", () => { console.log("[MockFluidNC] Client disconnected"); this.clients = this.clients.filter(c => c !== ws); }); ws.on("error", (err) => { console.log("[MockFluidNC] Client error:", err.message); }); }); this.server.on("error", reject); }); } /** * Stoppt den Mock-Server * @returns {Promise} */ stop() { return new Promise((resolve) => { if (this.server) { // Alle Clients disconnecten this.clients.forEach(client => { if (client.readyState === WebSocket.OPEN) { client.close(); } }); this.clients = []; this.server.close(() => { console.log("[MockFluidNC] Server stopped"); resolve(); }); } else { resolve(); } }); } /** * Sendet eine Nachricht an alle verbundenen Clients * @param {string} msg */ broadcast(msg) { this.clients.forEach(client => { if (client.readyState === WebSocket.OPEN) { client.send(msg); } }); } /** * Registriert einen Handler, der bei jeder empfangenen Nachricht aufgerufen wird * @param {Function} handler - (msg: string) => void */ onMessage(handler) { this.messageHandlers.push(handler); } /** * Behandelt spezielle G-Code Befehle mit Auto-Responses * @private */ _handleCommand(cmd, ws) { if (cmd === "?") { // Status request - sende eine Status-Antwort ws.send("\n"); } else if (cmd.startsWith("$J=")) { // Jog command - sende OK ws.send("ok\n"); } else if (cmd.includes("G1") || cmd.includes("G0")) { // G-Code command - sende OK ws.send("ok\n"); } } /** * Gibt die Anzahl verbundener Clients zurück */ getConnectedClientCount() { return this.clients.length; } /** * Gibt alle empfangenen Befehle zurück und leert die Liste */ getReceivedCommands() { const commands = [...this.receivedCommands]; this.receivedCommands = []; return commands; } /** * Gibt den letzten empfangenen Befehl zurück */ getLastReceivedCommand() { return this.receivedCommands[this.receivedCommands.length - 1]; } } module.exports = MockFluidNC;