send ping

This commit is contained in:
Martin Fuchs
2026-08-16 21:03:11 +02:00
parent 8ae58a63e6
commit d97a0c1b7e
3 changed files with 53 additions and 13 deletions
+1 -1
View File
@@ -42,7 +42,7 @@
}
</style>
<script src="https://cdn.jsdelivr.net/npm/p5@1.11.3/lib/p5.min.js"></script>
<script src="../../lib/WallPlotter.js?v=2.3.4"></script>
<script src="../../lib/WallPlotter.js?v=2.3.5"></script>
<script src="sketch.js"></script>
</head>
<body>
+1 -1
View File
@@ -42,7 +42,7 @@
}
</style>
<script src="https://cdn.jsdelivr.net/npm/p5@1.11.3/lib/p5.min.js"></script>
<script src="../../lib/WallPlotter.js?v=2.3.4"></script>
<script src="../../lib/WallPlotter.js?v=2.3.5"></script>
<script src="sketch.js"></script>
</head>
<body>
+51 -11
View File
@@ -18,7 +18,7 @@ class WallPlotter {
// Static constants
// ---------------------------------------------------------------------------
static VERSION = '2.3.4';
static VERSION = '2.3.5';
static MIN_FEED_MM_MIN = 1;
static MAX_FEED_MM_MIN = 10000;
/** Offline overlay size when not connected (mm) — 150×150 cm centred on origin */
@@ -32,6 +32,8 @@ class WallPlotter {
/** If a USB write does not complete, the ACM device is usually gone. */
static WRITE_TIMEOUT_MS = 3000;
static RESUME_STORAGE_KEY = 'wallplotter.resume.v1';
/** Send a quiet M400 if the line has been silent this long (keeps USB awake). */
static KEEPALIVE_MS = 1200;
// ---------------------------------------------------------------------------
// Construction
@@ -118,6 +120,8 @@ class WallPlotter {
this._okWaiter = null;
this._sendChain = Promise.resolve();
this._lastBusyLogAt = 0;
this._lastSendAt = 0;
this._keepaliveTimer = null;
// --- Keyboard / buttons ---
this._keysEnabled = false;
@@ -429,6 +433,7 @@ class WallPlotter {
this.writer = this.port.writable.getWriter();
this._startReadLoop();
this._startKeepalive();
this._link = 'connected';
this.onStatusChange('connected');
@@ -493,6 +498,7 @@ class WallPlotter {
if (this._link === 'disconnected' && !this.port) return;
this.readLoopActive = false;
this._stopKeepalive();
this._cancelPendingOk();
this._rxBuf = '';
@@ -538,6 +544,7 @@ class WallPlotter {
_releaseSerialNow() {
if (!this.port && this._link === 'disconnected') return;
this.readLoopActive = false;
this._stopKeepalive();
this._cancelPendingOk();
this._rxBuf = '';
const reader = this.reader;
@@ -569,7 +576,7 @@ class WallPlotter {
}
}
_writeLine(command) {
_writeLine(command, quiet = false) {
if (!this.writer) {
return Promise.reject(new Error('Not connected to plotter'));
}
@@ -588,7 +595,7 @@ class WallPlotter {
if (done) return;
done = true;
clearTimeout(timer);
this.onLog('→ ' + command);
if (!quiet) this.onLog('→ ' + command);
resolve();
},
(err) => {
@@ -673,9 +680,9 @@ class WallPlotter {
if (this._unloadBound) return;
this._unloadBound = true;
const release = () => {
this._stashInterruptedPath();
this._persistResumeState(true);
this._releaseSerialNow();
this._stashInterruptedPath();
this._persistResumeState(true);
this._releaseSerialNow();
};
window.addEventListener('pagehide', release);
window.addEventListener('beforeunload', release);
@@ -806,15 +813,18 @@ class WallPlotter {
return;
}
this._lastSendAt = performance.now();
const waitOk = options.waitOk !== false;
const quiet = options.quiet === true || /^M400\b/i.test(command);
const okPromise = waitOk
? this._waitForOk(options.timeoutMs ?? WallPlotter.OK_TIMEOUT_MS, {
command,
waitLogAfterMs: options.waitLogAfterMs,
quiet,
})
: null;
try {
const written = this._writeLine(command);
const written = this._writeLine(command, quiet);
if (okPromise) {
await Promise.all([
written.catch((err) => {
@@ -1268,8 +1278,11 @@ class WallPlotter {
_waitForOk(timeoutMs, options = {}) {
const command = options.command || '';
const waitLogAfterMs = options.waitLogAfterMs ?? WallPlotter.OK_WAIT_LOG_MS;
const waitLabel = command ? ` (${command})` : '';
const quiet = options.quiet === true;
const waitLogAfterMs = quiet
? Math.max(options.waitLogAfterMs ?? WallPlotter.OK_WAIT_LOG_MS, 8000)
: options.waitLogAfterMs ?? WallPlotter.OK_WAIT_LOG_MS;
const waitLabel = command && !quiet ? ` (${command})` : '';
return new Promise((resolve, reject) => {
if (this._okWaiter) {
@@ -1339,6 +1352,32 @@ class WallPlotter {
waiter.reject(err);
}
_startKeepalive() {
this._stopKeepalive();
this._keepaliveTimer = setInterval(() => {
this._keepaliveTick();
}, WallPlotter.KEEPALIVE_MS);
}
_stopKeepalive() {
if (this._keepaliveTimer != null) {
clearInterval(this._keepaliveTimer);
this._keepaliveTimer = null;
}
}
_keepaliveTick() {
if (this._link !== 'connected' || !this.writer) return;
if (this._okWaiter || this._job === 'aborting') return;
if (performance.now() - this._lastSendAt < WallPlotter.KEEPALIVE_MS) return;
this.send('M400', {
quiet: true,
allowWithoutHome: true,
timeoutMs: 4000,
waitLogAfterMs: 10000,
}).catch(() => {});
}
_startReadLoop() {
this.readLoopActive = true;
const plotter = this;
@@ -1403,8 +1442,9 @@ class WallPlotter {
}
return;
}
this.onLog('← ' + line);
if (/^(echo:\s*)?ok\b/i.test(line)) {
const isOk = /^(echo:\s*)?ok\b/i.test(line);
if (!isOk) this.onLog('← ' + line);
if (isOk) {
const waiter = this._okWaiter;
if (waiter) waiter.resolve();
}