diff --git a/public/GamePad.js b/public/GamePad.js
index 997080c..b56ffa7 100755
--- a/public/GamePad.js
+++ b/public/GamePad.js
@@ -24,8 +24,8 @@ function checkGamePad() {
// Dreieck zum Dreieck-Setzen
- if (buttons[3].pressed) {
- socket.send(`G90 G1 X0 Y300 Z0 A${Math.PI/2} B${-1.0*Math.PI/2} C0 F${xyzSpeed}`);
+ if (buttons[3].pressed) {
+ socket.sendCommand(`G90 G1 X0 Y300 Z0 A${Math.PI/2} B${-1.0*Math.PI/2} C0 F${xyzSpeed}`);
}
if (buttons[4].pressed) {
//console.log("x=" + robot.x + " y=" + robot.y + " z=" + robot.z);
@@ -37,47 +37,46 @@ function checkGamePad() {
if(buttons[0].pressed && (Date.now() - lastCheckTime > 500)){
lastCheckTime = Date.now()
console.log('FPoint!');
- socket.send('FPoint');
- socket.send('FShow');
+ socket.sendCommand('FPoint');
+ socket.sendCommand('FShow');
}
// L1 und R1 Button to forward-backward in Point-List
if(gp.buttons[4].pressed && (Date.now() - lastCheckTime > 500)){
lastCheckTime = Date.now()
- socket.send('FMinus');
- socket.send('FShow');
+ socket.sendCommand('FMinus');
+ socket.sendCommand('FShow');
}
if(gp.buttons[5].pressed && (Date.now() - lastCheckTime > 500)){
lastCheckTime = Date.now()
- socket.send('FPlus');
- socket.send('FShow');
+ socket.sendCommand('FPlus');
+ socket.sendCommand('FShow');
}
- if (x < -0.2) { socket.send(`G91 G1 X+${stepSizeXYZ} F${xyzSpeed}`);}
- if (x > 0.2) { socket.send(`G91 G1 X-${stepSizeXYZ} F${xyzSpeed}`);}
+ if (x < -0.2) { socket.sendCommand(`G91 G1 X+${stepSizeXYZ} F${xyzSpeed}`);}
+ if (x > 0.2) { socket.sendCommand(`G91 G1 X-${stepSizeXYZ} F${xyzSpeed}`);}
- if (y < -0.2) { socket.send(`G91 G1 Y${stepSizeXYZ} F${xyzSpeed}`); }
- if (y > 0.2) { socket.send(`G91 G1 Y-${stepSizeXYZ} F${xyzSpeed}`);}
+ if (y < -0.2) { socket.sendCommand(`G91 G1 Y${stepSizeXYZ} F${xyzSpeed}`); }
+ if (y > 0.2) { socket.sendCommand(`G91 G1 Y-${stepSizeXYZ} F${xyzSpeed}`);}
- if (z < -0.2) { socket.send(`G91 G1 Z${stepSizeXYZ} F${xyzSpeed}`); }
- if (z > 0.2) { socket.send(`G91 G1 Z-${stepSizeXYZ} F${xyzSpeed}`); }
+ if (z < -0.2) { socket.sendCommand(`G91 G1 Z${stepSizeXYZ} F${xyzSpeed}`); }
+ if (z > 0.2) { socket.sendCommand(`G91 G1 Z-${stepSizeXYZ} F${xyzSpeed}`); }
// Greif-Richtung
// LeftRight
- if(buttons[14].pressed){ socket.send(`G91 G1 A${stepSize} F${xyzSpeed}`);}
- if(buttons[15].pressed){ socket.send(`G91 G1 A-${stepSize} F${xyzSpeed}`);}
+ if(buttons[14].pressed){ socket.sendCommand(`G91 G1 A${stepSize} F${xyzSpeed}`);}
+ if(buttons[15].pressed){ socket.sendCommand(`G91 G1 A-${stepSize} F${xyzSpeed}`);}
// Up - Down
- if(buttons[12].pressed){ socket.send(`G91 G1 B${stepSize} F${xyzSpeed}`);}
- if(buttons[13].pressed){ socket.send(`G91 G1 B-${stepSize} F${xyzSpeed}`);}
+ if(buttons[12].pressed){ socket.sendCommand(`G91 G1 B${stepSize} F${xyzSpeed}`);}
+ if(buttons[13].pressed){ socket.sendCommand(`G91 G1 B-${stepSize} F${xyzSpeed}`);}
// Drehung
- if (psi < -0.2) { socket.send(`G91 G1 C${stepSize} F${xyzSpeed}`); }
- if (psi > 0.2) { socket.send(`G91 G1 C-${stepSize} F${xyzSpeed}`); }
+ if (psi < -0.2) { socket.sendCommand(`G91 G1 C${stepSize} F${xyzSpeed}`); }
+ if (psi > 0.2) { socket.sendCommand(`G91 G1 C-${stepSize} F${xyzSpeed}`); }
// Trigger-Buttons für Öffnen und Schliessen
- if(buttons[6].pressed){socket.send(`G91 G1 E-${stepSizeE} F${xyzSpeed}`);}
- if(buttons[7].pressed){socket.send(`G91 G1 E${stepSizeE} F${xyzSpeed}`);}
-
+ if(buttons[6].pressed){socket.sendCommand(`G91 G1 E-${stepSizeE} F${xyzSpeed}`);}
+ if(buttons[7].pressed){socket.sendCommand(`G91 G1 E${stepSizeE} F${xyzSpeed}`);}
if (isRunning) { setTimeout(checkGamePad, 15);}
}
diff --git a/public/KeyboardInput.js b/public/KeyboardInput.js
index fdf2838..14605f4 100755
--- a/public/KeyboardInput.js
+++ b/public/KeyboardInput.js
@@ -1,17 +1,16 @@
-document.onkeydown = checkKey;
+document.addEventListener("keydown", (e)=>{
-function checkKey(e) {
+ if(!window.socket){
+ console.warn("socket not ready");
+ return;
+ }
- e = e || window.event;
-
- if(e.key == 'a' || e.key == 'A')
- {
+ if(e.key==="a"||e.key==="A"){
console.log("back to A position");
socket.send(`G90 G1 X0 Y300 Z0 A${Math.PI/2} B-${Math.PI/2} C0 F100`);
}
- // Hand-Winkel (Eulerwinkel)
- else if(e.key == 'i' || e.key == 'I'){
+ else if(e.key==="i"||e.key==="I"){
socket.send('G91 G1 B+0.1 F100');
}
else if(e.key == 'k' || e.key == 'K'){
@@ -63,4 +62,4 @@ function checkKey(e) {
}
-}
\ No newline at end of file
+});
diff --git a/public/WebService.js b/public/WebService.js
index cf5b345..c6580c7 100755
--- a/public/WebService.js
+++ b/public/WebService.js
@@ -1,75 +1,224 @@
-var startTime = Date.now() ;
-console.log("Meine Document-Location: " + document.location);
-var lastPingRequest;
+// WebService.js - robust WebSocket wrapper (drop-in replacement)
+(function () {
+ const startTime = Date.now();
+ console.log("Meine Document-Location:", document.location);
-// Use explicit '/echo' path and a small wrapper to guard sends from other modules
-var socketUrl = (location.protocol === 'https:' ? 'wss://' : 'ws://') + window.location.host + '/echo';
+ const socketUrl =
+ (location.protocol === "https:" ? "wss://" : "ws://") +
+ window.location.host +
+ "/echo";
-console.log("WebSocket URL: " + socketUrl);
+ console.log("WebSocket URL:", socketUrl);
-// socket wrapper keeps the same global identifier but guards sends when underlying ws is not open
-var socket = {
+ // Expose global socket object immediately so other scripts never see "socket is not defined"
+ window.socket = {
+ // internal
_ws: null,
- send: function(msg) {
+ _queue: [],
+ _retry: 0,
+ _pingIntervalId: null,
+ _lastPingRequest: null,
+ _connectedOnce: false,
+
+ // user hooks (can be assigned by UI code)
+ onMessage: null,
+ onOpen: null,
+ onClose: null,
+
+ // ------ API: send / sendCommand (legacy & recommended) ------
+ // raw send (backwards compatible)
+ send(msg) {
+ this._enqueueOrSend(msg);
+ },
+
+ // preferred semantic method for commands
+ sendCommand(cmd) {
+ // you can add validation/normalization here
+ this._enqueueOrSend(cmd);
+ },
+
+ // convenience robot command
+ moveZ(value, feed = 100) {
+ // positive value moves up; negative moves down depending on your G-code semantics
+ this.sendCommand(`G91 G1 Z${value} F${feed}`);
+ },
+
+ // manual control to connect/disconnect
+ connect() {
+ _connect(this);
+ },
+
+ disconnect() {
+ _disconnect(this);
+ },
+
+ isOpen() {
+ return this._ws && this._ws.readyState === WebSocket.OPEN;
+ },
+
+ // internal helper: enqueue if not open, otherwise send immediately
+ _enqueueOrSend(msg) {
+ try {
if (this._ws && this._ws.readyState === WebSocket.OPEN) {
- this._ws.send(msg);
- console.log('Sent message with WebSocket.OPEN:', msg);
+ this._ws.send(msg);
+ console.log("WS SEND:", msg);
} else {
- console.warn('Socket not open, dropping message:', msg);
+ // queue to be flushed on open
+ console.warn("WS not ready → queueing:", msg);
+ this._queue.push(msg);
}
+ } catch (e) {
+ console.error("WS send failed:", e, " (queued )");
+ this._queue.push(msg);
+ }
}
-};
+ };
-let pingIntervalId = null;
-let reconnectDelay = 1000;
-
-function connect() {
- const ws = new WebSocket(socketUrl);
- socket._ws = ws;
-
- ws.onopen = () => {
- console.log('Connected to WS Server');
- reconnectDelay = 1000;
- if (pingIntervalId) clearInterval(pingIntervalId);
- pingIntervalId = setInterval(() => {
- if (socket._ws && socket._ws.readyState === WebSocket.OPEN) {
- lastPingRequest = Date.now();
- socket.send('Ping');
- }
- }, 5000);
- };
-
- ws.onclose = (event) => {
- console.log((event.wasClean) ? 'Disconnected' : 'Connection break: ' + (event.reason || event.code));
- if (pingIntervalId) { clearInterval(pingIntervalId); pingIntervalId = null; }
- setTimeout(() => {
- console.log('Reconnecting...');
- connect();
- }, reconnectDelay);
- reconnectDelay = Math.min(30000, reconnectDelay * 2);
- };
-
- ws.onmessage = (event) => {
- if(event.data == 'Ping'){
- console.log('Ping: ' + (Date.now() - lastPingRequest).toString() + ' ms');
+ // ---------- internal functions ----------
+ function _flushQueue(sock) {
+ while (sock._queue.length) {
+ const m = sock._queue.shift();
+ try {
+ if (sock._ws && sock._ws.readyState === WebSocket.OPEN) {
+ sock._ws.send(m);
+ console.log("Flushed queued msg:", m);
+ } else {
+ // push back and stop flushing
+ sock._queue.unshift(m);
+ break;
}
- else if(event.data.toString().includes('position')){
- console.log('Position: ' + event.data);
+ } catch (e) {
+ console.warn("Failed flushing queued msg, requeueing", e);
+ sock._queue.unshift(m);
+ break;
+ }
+ }
+ }
+
+ function _startPing(sock) {
+ if (sock._pingIntervalId) return;
+ sock._pingIntervalId = setInterval(() => {
+ if (sock._ws && sock._ws.readyState === WebSocket.OPEN) {
+ sock._lastPingRequest = Date.now();
+ sock._enqueueOrSend("Ping");
+ }
+ }, 5000);
+ }
+
+ function _stopPing(sock) {
+ if (sock._pingIntervalId) {
+ clearInterval(sock._pingIntervalId);
+ sock._pingIntervalId = null;
+ }
+ }
+
+ function _connect(sock) {
+ // prevent duplicate connects
+ if (sock._ws && (sock._ws.readyState === WebSocket.CONNECTING || sock._ws.readyState === WebSocket.OPEN)) {
+ console.log("WebSocket already connecting/open - skipping connect()");
+ return;
+ }
+
+ try {
+ console.log("WebSocket: connecting to", socketUrl);
+ const ws = new WebSocket(socketUrl);
+ sock._ws = ws;
+
+ ws.onopen = () => {
+ console.log("Connected to WS Server");
+ sock._connectedOnce = true;
+ sock._retry = 0; // reset retries
+ _flushQueue(sock);
+ _startPing(sock);
+
+ if (typeof sock.onOpen === "function") {
+ try { sock.onOpen(); } catch (e) { console.error("onOpen handler error", e); }
}
- else if(event.data.toString().includes('XYZ__FShow__XYZ')){
- const content = event.data.toString().split('XYZ__FShow__XYZ')[1];
- console.log('File Content: ' + content);
- const el = document.querySelector('textarea#GCodeWindow.editor-look');
- if (el) el.value = content;
+ };
+
+ ws.onmessage = (event) => {
+ const data = event.data ? event.data.toString() : "";
+ // built-in handling (keeps backward compatible behaviour)
+ if (data === "Ping") {
+ if (sock._lastPingRequest) {
+ console.log("Ping:", Date.now() - sock._lastPingRequest, "ms");
+ } else {
+ console.log("Ping (no timestamp)");
+ }
+ } else if (data.includes("position")) {
+ console.log("Position:", data);
+ } else if (data.includes("XYZ__FShow__XYZ")) {
+ const content = data.split("XYZ__FShow__XYZ")[1] || "";
+ console.log("FShow content received, length", content.length);
+ const el = document.querySelector("textarea#GCodeWindow.editor-look");
+ if (el) el.value = content;
+ } else {
+ console.log("DATA:", Date.now() - startTime, data);
}
- else{
- console.log('DATA SinceStartup: ' + (Date.now() - startTime).toString() +': ', event.data);
+
+ // call user onMessage hook if present
+ if (typeof sock.onMessage === "function") {
+ try { sock.onMessage(data); } catch (e) { console.error("onMessage handler error", e); }
}
- };
+ };
- ws.onerror = (err) => console.error('WebSocket error:', err || err.message);
-}
+ ws.onclose = (event) => {
+ const reason = event.reason || event.code || "closed";
+ console.log(event.wasClean ? "Disconnected" : "Connection break: " + reason);
+ _stopPing(sock);
-connect();
+ if (typeof sock.onClose === "function") {
+ try { sock.onClose(event); } catch (e) { console.error("onClose handler error", e); }
+ }
+ // exponential backoff with small jitter
+ sock._retry = (sock._retry || 0) + 1;
+ const base = 1000;
+ const delay = Math.min(30000, base * Math.pow(2, sock._retry - 1)) + Math.floor(Math.random() * 300);
+ console.log("Reconnect in", delay, "ms (attempt", sock._retry, ")");
+ setTimeout(() => _connect(sock), delay);
+ };
+ ws.onerror = (err) => {
+ // some browsers call onerror right before onclose; log only
+ console.error("WebSocket error:", err && (err.message || err));
+ };
+ } catch (e) {
+ console.error("WebSocket create failed", e);
+ // schedule reconnect
+ sock._retry = (sock._retry || 0) + 1;
+ const delay = Math.min(30000, 1000 * Math.pow(2, sock._retry - 1)) + Math.floor(Math.random() * 300);
+ setTimeout(() => _connect(sock), delay);
+ }
+ }
+
+ function _disconnect(sock) {
+ try {
+ _stopPing(sock);
+ if (sock._ws) {
+ try { sock._ws.close(); } catch (e) { /* ignore */ }
+ sock._ws = null;
+ }
+ } catch (e) {
+ console.error("Error during disconnect", e);
+ }
+ }
+
+ // Kick off initial connection
+ window.socket.connect();
+
+ // Expose some helpful debug tools in the console
+ window.__socket_debug = {
+ getQueue: () => window.socket._queue.slice(),
+ getState: () => (window.socket._ws ? window.socket._ws.readyState : null),
+ flush: () => _flushQueue(window.socket),
+ reconnect: () => {
+ _disconnect(window.socket);
+ window.socket._retry = 0;
+ window.socket.connect();
+ }
+ };
+
+ // Optional: if you want a simple rate limiter later, you can add code here.
+ // Keep GamePad traffic in mind — don't flood the queue on reconnect.
+})();
diff --git a/public/index.html b/public/index.html
index 3dc55a7..d5c9a61 100755
--- a/public/index.html
+++ b/public/index.html
@@ -7,8 +7,8 @@