WS eigene Datei
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,5 +1,6 @@
|
|||||||
# Node
|
# Node
|
||||||
node_modules
|
node_modules
|
||||||
|
logs
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
yarn-debug.log
|
yarn-debug.log
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
|
|||||||
367
package-lock.json
generated
367
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -20,6 +20,7 @@
|
|||||||
"wss": "^0.0.2"
|
"wss": "^0.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"jest-websocket-mock": "^2.5.0"
|
"jest-websocket-mock": "^2.5.0",
|
||||||
|
"jest": "^29.x.x"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
|
|
||||||
module.exports = class PythonSender {
|
|
||||||
|
|
||||||
|
|
||||||
constructor(p = 9875){
|
|
||||||
const WebSocket = require('ws');
|
|
||||||
|
|
||||||
|
|
||||||
this.sockets = [];
|
|
||||||
this.server = new WebSocket.Server({port: p});
|
|
||||||
|
|
||||||
this.server.on('connection', (socket) => this.connectThis(socket));
|
|
||||||
}
|
|
||||||
|
|
||||||
msgThis(msg){
|
|
||||||
console.log("message:" + msg.toString())
|
|
||||||
this.sockets.forEach(s => s.send(msg));
|
|
||||||
}
|
|
||||||
|
|
||||||
closeThis(socket){
|
|
||||||
console.log("Python Receiver is closing the connection");
|
|
||||||
this.sockets = this.sockets.filter(s => s !== socket);
|
|
||||||
}
|
|
||||||
connectThis(socket) {
|
|
||||||
console.log("Python Receiver is connected")
|
|
||||||
this.sockets.push(socket);
|
|
||||||
|
|
||||||
// When you receive a message, send that message to every socket.
|
|
||||||
socket.on('message', (msg) => this.msgThis(msg));
|
|
||||||
|
|
||||||
|
|
||||||
// When a socket closes, or disconnects, remove it from the array.
|
|
||||||
socket.on('close', () => this.closeThis(socket));
|
|
||||||
}
|
|
||||||
|
|
||||||
send(m){
|
|
||||||
if((this.sockets.length) > 0){
|
|
||||||
this.sockets.forEach( s => s.send(m));
|
|
||||||
}
|
|
||||||
else{ console.warn("No sockets connected. Can't send the Message.");}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
if(this.pythonSender != null){
|
|
||||||
var strJSON = CANCreator.cmdMovement(this.motorPositionOld, this.motorPosition);
|
|
||||||
if(strJSON != '{"message":"empty"}'){
|
|
||||||
this.pythonSender.send(strJSON);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -107,8 +107,6 @@ class Robot{
|
|||||||
/** @type {boolean} Relative oder absolute Bewegung (true = relativ) */
|
/** @type {boolean} Relative oder absolute Bewegung (true = relativ) */
|
||||||
this.moveRelative = true;
|
this.moveRelative = true;
|
||||||
|
|
||||||
/** @type {Object|null} Python-Sender-Instanz für GCode-Kommunikation */
|
|
||||||
this.pythonSender = null;
|
|
||||||
/** @type {Object[]} Array von Kommando-Empfängern */
|
/** @type {Object[]} Array von Kommando-Empfängern */
|
||||||
this.cmdReceivers = [];
|
this.cmdReceivers = [];
|
||||||
}
|
}
|
||||||
|
|||||||
63
server/InfoServer.js
Normal file
63
server/InfoServer.js
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
// server/InfoServer.js
|
||||||
|
const fs = require('fs');
|
||||||
|
const https = require('https');
|
||||||
|
|
||||||
|
function createInfoServer(httpsOptions, sharedState, robot, GCode, senders) {
|
||||||
|
return https.createServer(httpsOptions, (req, res) => {
|
||||||
|
|
||||||
|
if (req.url === '/') {
|
||||||
|
return serveFile(res, './public/index.html', 'text/html');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.url === '/app.js') {
|
||||||
|
return serveFile(res, './public/app.js', 'application/javascript');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.url === '/style.css') {
|
||||||
|
return serveFile(res, './public/style.css', 'text/css');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.url === '/allApps.css') {
|
||||||
|
return serveFile(res, './public/allApps.css', 'text/css');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- API ---------- */
|
||||||
|
if (req.url === '/api/status') {
|
||||||
|
const status = {
|
||||||
|
clients: sharedState.connectedClients,
|
||||||
|
senders: senders.map(s => ({
|
||||||
|
name: s.name,
|
||||||
|
status: s.instance?.tSocket ? 'connected' : 'disconnected'
|
||||||
|
})),
|
||||||
|
lastCommands: sharedState.lastCommands,
|
||||||
|
lastPings: sharedState.lastPings
|
||||||
|
};
|
||||||
|
|
||||||
|
res.writeHead(200, {'Content-Type': 'application/json'});
|
||||||
|
return res.end(JSON.stringify(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.url === '/api/position') {
|
||||||
|
res.writeHead(200, {'Content-Type': 'application/json'});
|
||||||
|
return res.end(GCode.getM114(robot));
|
||||||
|
}
|
||||||
|
|
||||||
|
res.writeHead(404);
|
||||||
|
res.end('Not found');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- Helper ---------- */
|
||||||
|
|
||||||
|
function serveFile(res, path, type) {
|
||||||
|
fs.readFile(path, (err, data) => {
|
||||||
|
if (err) {
|
||||||
|
res.writeHead(404);
|
||||||
|
return res.end('Not found');
|
||||||
|
}
|
||||||
|
res.writeHead(200, {'Content-Type': type});
|
||||||
|
res.end(data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = createInfoServer;
|
||||||
83
server/InputWS.js
Normal file
83
server/InputWS.js
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
// server/InputWS.js
|
||||||
|
const fs = require('fs');
|
||||||
|
const WebSocket = require('ws');
|
||||||
|
|
||||||
|
function initInputWS(server, robot, GCode, sharedState) {
|
||||||
|
const wss = new WebSocket.Server({ server });
|
||||||
|
|
||||||
|
wss.on('connection', (ws) => {
|
||||||
|
console.log("WebSocket Input connected");
|
||||||
|
|
||||||
|
const clientIP = ws._socket.remoteAddress || 'unknown';
|
||||||
|
sharedState.connectedClients.push(clientIP);
|
||||||
|
|
||||||
|
ws.on('close', () => {
|
||||||
|
sharedState.connectedClients =
|
||||||
|
sharedState.connectedClients.filter(ip => ip !== clientIP);
|
||||||
|
});
|
||||||
|
|
||||||
|
ws.on('message', (msg) => {
|
||||||
|
const message = msg.toString();
|
||||||
|
|
||||||
|
/* ---------- Ping ---------- */
|
||||||
|
if (message === "Ping") {
|
||||||
|
logPing(sharedState, clientIP);
|
||||||
|
broadcast(wss, message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- GCode ---------- */
|
||||||
|
if (GCode.containsCommand(message)) {
|
||||||
|
logCommand(sharedState, clientIP, message);
|
||||||
|
GCode.receiveGCode(robot, message);
|
||||||
|
broadcast(wss, GCode.getM114(robot));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- File Commands ---------- */
|
||||||
|
if (GCode.ContainsFilesCommand(message)) {
|
||||||
|
logCommand(sharedState, clientIP, message);
|
||||||
|
broadcast(wss, GCode.receiveFC(robot, message));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- Status ---------- */
|
||||||
|
if (message === "M114") {
|
||||||
|
logCommand(sharedState, clientIP, message);
|
||||||
|
broadcast(wss, GCode.getM114(robot));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return wss;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- Helpers ---------- */
|
||||||
|
|
||||||
|
function broadcast(wss, payload) {
|
||||||
|
wss.clients.forEach(client => {
|
||||||
|
if (client.readyState === WebSocket.OPEN) {
|
||||||
|
client.send(payload);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function logCommand(state, ip, message) {
|
||||||
|
fs.appendFileSync(
|
||||||
|
'./logs/gcode_commands.log',
|
||||||
|
`${new Date().toISOString()} ${ip}: ${message}\n`
|
||||||
|
);
|
||||||
|
state.lastCommands.push(`${new Date().toISOString()}: ${message}`);
|
||||||
|
if (state.lastCommands.length > 10) state.lastCommands.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
function logPing(state, ip) {
|
||||||
|
fs.appendFileSync(
|
||||||
|
'./logs/pings.log',
|
||||||
|
`${new Date().toISOString()} ${ip}: Ping\n`
|
||||||
|
);
|
||||||
|
state.lastPings.push(`${new Date().toISOString()}: Ping`);
|
||||||
|
if (state.lastPings.length > 10) state.lastPings.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = initInputWS;
|
||||||
@@ -18,11 +18,18 @@ const GCode = require('./robot/GCode.js')
|
|||||||
// 238 + 1 + 25 = 264
|
// 238 + 1 + 25 = 264
|
||||||
let robot = new Robot(250,264,100); //(300,290,10);
|
let robot = new Robot(250,264,100); //(300,290,10);
|
||||||
|
|
||||||
// Tracking variables for info page
|
|
||||||
|
|
||||||
let connectedClients = [];
|
let connectedClients = [];
|
||||||
let lastCommands = [];
|
let lastCommands = [];
|
||||||
let lastPings = [];
|
let lastPings = [];
|
||||||
|
|
||||||
|
let sharedState = {
|
||||||
|
connectedClients: [],
|
||||||
|
lastCommands: [],
|
||||||
|
lastPings: []
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const httpsOptions = {
|
const httpsOptions = {
|
||||||
"enable": true,
|
"enable": true,
|
||||||
@@ -33,6 +40,7 @@ const httpsOptions = {
|
|||||||
|
|
||||||
server = https.createServer(httpsOptions, (req, res) => {;});
|
server = https.createServer(httpsOptions, (req, res) => {;});
|
||||||
|
|
||||||
|
|
||||||
const wss = new WebSocket.Server({ server });
|
const wss = new WebSocket.Server({ server });
|
||||||
|
|
||||||
// Input Connection for WebService
|
// Input Connection for WebService
|
||||||
@@ -108,6 +116,11 @@ wss.on('connection', function connection(ws)
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
const InputWS = require('./robot/InputWS.js')
|
||||||
|
const wss = InputWS(server, robot, GCode, sharedState);
|
||||||
|
*/
|
||||||
|
|
||||||
var TenetSender = require('./robot/TelnetSenderGRBL.js')
|
var TenetSender = require('./robot/TelnetSenderGRBL.js')
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
70
startRobot_better.js
Normal file
70
startRobot_better.js
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
const https = require('https');
|
||||||
|
|
||||||
|
const Robot = require('./robot/Robot');
|
||||||
|
const GCode = require('./robot/GCode');
|
||||||
|
|
||||||
|
const initInputWS = require('./server/InputWS');
|
||||||
|
const createInfoServer = require('./server/InfoServer');
|
||||||
|
|
||||||
|
const TenetSender = require('./robot/TelnetSenderGRBL');
|
||||||
|
|
||||||
|
/* ---------- Robot ---------- */
|
||||||
|
const robot = new Robot(250, 264, 100);
|
||||||
|
|
||||||
|
/* ---------- Shared State ---------- */
|
||||||
|
const sharedState = {
|
||||||
|
connectedClients: [],
|
||||||
|
lastCommands: [],
|
||||||
|
lastPings: []
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ---------- HTTPS ---------- */
|
||||||
|
const httpsOptions = {
|
||||||
|
enable: true,
|
||||||
|
key: fs.readFileSync('https/localhost.key'),
|
||||||
|
cert: fs.readFileSync('https/localhost.pem'),
|
||||||
|
passphrase: 'abcd'
|
||||||
|
};
|
||||||
|
|
||||||
|
const httpsServer = https.createServer(httpsOptions);
|
||||||
|
|
||||||
|
/* ---------- WebSocket Input ---------- */
|
||||||
|
initInputWS(httpsServer, robot, GCode, sharedState);
|
||||||
|
|
||||||
|
/* ---------- GRBL Sender ---------- */
|
||||||
|
const baseIP = process.env.GRBL_BASE_IP ?? "fluidNcBase.local";
|
||||||
|
const elbowIP= process.env.GRBL_ELLBOW_IP ?? "fluidNcEllbow.local";
|
||||||
|
const handIP = process.env.GRBL_HAND_IP ?? "fluidNcHand.local";
|
||||||
|
|
||||||
|
const telnetSender1 = new TenetSender(baseIP, 2300, "x", "y", "z");
|
||||||
|
const telnetSender2 = new TenetSender(elbowIP, 5000, "a", null, null);
|
||||||
|
const telnetSender3 = new TenetSender(handIP, 5000, "c", "e", "b");
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
[telnetSender1, telnetSender2, telnetSender3].forEach(s => {
|
||||||
|
if (s?.tSocket) robot.cmdReceivers.push(s);
|
||||||
|
});
|
||||||
|
}, 8000);
|
||||||
|
|
||||||
|
/* ---------- Start Input Server ---------- */
|
||||||
|
const port = Number(process.env.PORT) || 2095;
|
||||||
|
httpsServer.listen(port);
|
||||||
|
console.log(`Input HTTPS/WebSocket on https://localhost:${port}`);
|
||||||
|
|
||||||
|
/* ---------- Info Server ---------- */
|
||||||
|
const infoServer = createInfoServer(
|
||||||
|
httpsOptions,
|
||||||
|
sharedState,
|
||||||
|
robot,
|
||||||
|
GCode,
|
||||||
|
[
|
||||||
|
{ name: "Base", instance: telnetSender1 },
|
||||||
|
{ name: "Elbow", instance: telnetSender2 },
|
||||||
|
{ name: "Hand", instance: telnetSender3 }
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
const infoPort = 2098;
|
||||||
|
infoServer.listen(infoPort);
|
||||||
|
console.log(`Info server on https://localhost:${infoPort}`);
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
var PythonSender = require('../robot/PythonSender.js');
|
|
||||||
|
|
||||||
|
|
||||||
test('Initialisiere den WS', () => {
|
|
||||||
var p = new PythonSender();
|
|
||||||
p.server.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Connect to WS', ()=> {
|
|
||||||
var p = new PythonSender(9991);
|
|
||||||
|
|
||||||
const WebSocket = require('ws');
|
|
||||||
|
|
||||||
//w = new WebSocket("ws://localhost:9991")
|
|
||||||
|
|
||||||
//console.log(p.sockets)
|
|
||||||
p.server.close();
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user