This commit is contained in:
chk
2026-03-09 19:29:46 +01:00
commit 0cd5c16ae2
583 changed files with 72518 additions and 0 deletions

13
server/config/config.js Normal file
View File

@@ -0,0 +1,13 @@
module.exports = {
fluidnc: {
host: "fluidncsilver.local",
port: 81,
reconnectDelay: 30000
},
server: {
port: 3000
}
};

View File

@@ -0,0 +1,105 @@
const config = require("../config/config");
const net = require("net");
const { resolve } = require("path");
const TelnetSocket = require("telnet-stream");
class FluidNCClient {
constructor() {
console.log("[FluidNCClient] Initializing...");
this.url = config.fluidnc.host;
this.port = config.fluidnc.port || 23;
this.tSocket = null;
this.connected = false;
this.state = { x:0, z:0, state:"unknown" };
this.listeners = [];
this._connect();
}
_connect() {
console.log(`[FluidNCClient] Connecting to FluidNC: ${this.url}`);
let socket = null;
new Promise((resolve, reject) => {
socket = net.createConnection({host:this.url, port:this.port}, () => {
resolve(socket);
}).on("error", reject);
}).then(connection => {
console.log("[FluidNCClient] Telnet socket connected");
this.connected = true;
connection.on("data", data => {
const msg = data.toString().replace(/\r/g,"").trim();
if(!msg) return;
console.log("[FluidNCClient] Received:", msg);
if(msg.startsWith("<") && msg.includes("MPos:")){
const match = msg.match(/MPos:([\d\.\-]+),[\d\.\-]+,([\d\.\-]+)/);
if(match){
this.state.x = parseFloat(match[1]);
this.state.z = parseFloat(match[2]);
this.state.state = msg.split(",")[0].replace("<","");
this._broadcast(this.state);
}
}
});
if(socket != null){
this.tSocket = TelnetSocket(socket);
this.tSocket.on("close", () => {
console.log("[FluidNCClient] Telnet Closed");
this.tSocket = null;
this.connected = false;
setTimeout(()=>this._connect(), 30000);
});
}
}, error => {
console.log("[FluidNCClient] Telnet Connection Error:", error.toString());
this.tSocket = null;
this.connected = false;
setTimeout(()=>this._connect(), 30000);
});
}
_broadcast(msg){
this.listeners.forEach(fn => fn(msg));
}
onMessage(fn){
this.listeners.push(fn);
}
send(cmd){
if(this.tSocket){
console.log("[FluidNCClient] Sending:", cmd);
this.tSocket.write(cmd + "\r\n");
}
}
jog(axis, value){
if(!this.connected) return;
this.send("G91");
this.send(`G0 ${axis.toUpperCase()}${value}`);
this.send("G90");
}
sendGcode(cmd){
if(!this.connected) return;
this.send("G90");
this.send(cmd);
}
setZero(){
if(!this.connected) return;
this.send("G10 L20 P1 X0 Z0");
}
}
module.exports = FluidNCClient;

View File

@@ -0,0 +1,26 @@
class StatusParser {
static parse(line){
if(!line.startsWith("<")) return null;
const stateMatch = line.match(/^<([^|]+)/);
const posMatch = line.match(/MPos:([^|]+)/);
if(!posMatch) return null;
const parts = posMatch[1].split(",");
return {
type: "status",
state: stateMatch ? stateMatch[1] : "unknown",
x: parseFloat(parts[0]),
y: parseFloat(parts[1]),
z: parseFloat(parts[2])
};
}
}
module.exports = StatusParser;

96
server/server.js Normal file
View File

@@ -0,0 +1,96 @@
const fs = require("fs");
const path = require("path");
const https = require("https");
const express = require("express");
const WebSocket = require("ws");
const config = require("./config/config");
const FluidNCClient = require("./fluidnc/FluidNCClient");
const app = express();
app.use(express.static(path.join(__dirname,"../web")));
const server = https.createServer({
key: fs.readFileSync(path.join(__dirname,"../cert/key.pem")),
cert: fs.readFileSync(path.join(__dirname,"../cert/cert.pem"))
},app);
const wss = new WebSocket.Server({server});
const fluid = new FluidNCClient();
let clients = [];
wss.on("connection",(ws)=>{
console.log("[WS] Client connected");
clients.push(ws);
ws.on("message",(msg)=>{
try{
const data = JSON.parse(msg);
console.log("[WS] Received message:", data);
if(data.type==="jog"){
fluid.jog(data.axis,data.value);
}
if(data.type==="gcode"){
fluid.sendGcode(data.cmd);
}
if(data.type==="zero"){
fluid.setZero();
}
}catch(e){
console.log("[WS] Error parsing message:", e);
}
});
ws.on("close",()=>{
clients = clients.filter(c=>c!==ws);
console.log("[WS] Client disconnected");
});
});
fluid.onMessage((msg)=>{
const json = JSON.stringify(msg);
clients.forEach(c=>{
if(c.readyState===WebSocket.OPEN){
c.send(json);
}
});
});
server.listen(config.server.port,()=>{
console.log("[Server] Running at:");
console.log(`https://localhost:${config.server.port}`);
});