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> </style>
<script src="https://cdn.jsdelivr.net/npm/p5@1.11.3/lib/p5.min.js"></script> <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> <script src="sketch.js"></script>
</head> </head>
<body> <body>
+1 -1
View File
@@ -42,7 +42,7 @@
} }
</style> </style>
<script src="https://cdn.jsdelivr.net/npm/p5@1.11.3/lib/p5.min.js"></script> <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> <script src="sketch.js"></script>
</head> </head>
<body> <body>
+48 -8
View File
@@ -18,7 +18,7 @@ class WallPlotter {
// Static constants // Static constants
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
static VERSION = '2.3.4'; static VERSION = '2.3.5';
static MIN_FEED_MM_MIN = 1; static MIN_FEED_MM_MIN = 1;
static MAX_FEED_MM_MIN = 10000; static MAX_FEED_MM_MIN = 10000;
/** Offline overlay size when not connected (mm) — 150×150 cm centred on origin */ /** 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. */ /** If a USB write does not complete, the ACM device is usually gone. */
static WRITE_TIMEOUT_MS = 3000; static WRITE_TIMEOUT_MS = 3000;
static RESUME_STORAGE_KEY = 'wallplotter.resume.v1'; 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 // Construction
@@ -118,6 +120,8 @@ class WallPlotter {
this._okWaiter = null; this._okWaiter = null;
this._sendChain = Promise.resolve(); this._sendChain = Promise.resolve();
this._lastBusyLogAt = 0; this._lastBusyLogAt = 0;
this._lastSendAt = 0;
this._keepaliveTimer = null;
// --- Keyboard / buttons --- // --- Keyboard / buttons ---
this._keysEnabled = false; this._keysEnabled = false;
@@ -429,6 +433,7 @@ class WallPlotter {
this.writer = this.port.writable.getWriter(); this.writer = this.port.writable.getWriter();
this._startReadLoop(); this._startReadLoop();
this._startKeepalive();
this._link = 'connected'; this._link = 'connected';
this.onStatusChange('connected'); this.onStatusChange('connected');
@@ -493,6 +498,7 @@ class WallPlotter {
if (this._link === 'disconnected' && !this.port) return; if (this._link === 'disconnected' && !this.port) return;
this.readLoopActive = false; this.readLoopActive = false;
this._stopKeepalive();
this._cancelPendingOk(); this._cancelPendingOk();
this._rxBuf = ''; this._rxBuf = '';
@@ -538,6 +544,7 @@ class WallPlotter {
_releaseSerialNow() { _releaseSerialNow() {
if (!this.port && this._link === 'disconnected') return; if (!this.port && this._link === 'disconnected') return;
this.readLoopActive = false; this.readLoopActive = false;
this._stopKeepalive();
this._cancelPendingOk(); this._cancelPendingOk();
this._rxBuf = ''; this._rxBuf = '';
const reader = this.reader; const reader = this.reader;
@@ -569,7 +576,7 @@ class WallPlotter {
} }
} }
_writeLine(command) { _writeLine(command, quiet = false) {
if (!this.writer) { if (!this.writer) {
return Promise.reject(new Error('Not connected to plotter')); return Promise.reject(new Error('Not connected to plotter'));
} }
@@ -588,7 +595,7 @@ class WallPlotter {
if (done) return; if (done) return;
done = true; done = true;
clearTimeout(timer); clearTimeout(timer);
this.onLog('→ ' + command); if (!quiet) this.onLog('→ ' + command);
resolve(); resolve();
}, },
(err) => { (err) => {
@@ -806,15 +813,18 @@ class WallPlotter {
return; return;
} }
this._lastSendAt = performance.now();
const waitOk = options.waitOk !== false; const waitOk = options.waitOk !== false;
const quiet = options.quiet === true || /^M400\b/i.test(command);
const okPromise = waitOk const okPromise = waitOk
? this._waitForOk(options.timeoutMs ?? WallPlotter.OK_TIMEOUT_MS, { ? this._waitForOk(options.timeoutMs ?? WallPlotter.OK_TIMEOUT_MS, {
command, command,
waitLogAfterMs: options.waitLogAfterMs, waitLogAfterMs: options.waitLogAfterMs,
quiet,
}) })
: null; : null;
try { try {
const written = this._writeLine(command); const written = this._writeLine(command, quiet);
if (okPromise) { if (okPromise) {
await Promise.all([ await Promise.all([
written.catch((err) => { written.catch((err) => {
@@ -1268,8 +1278,11 @@ class WallPlotter {
_waitForOk(timeoutMs, options = {}) { _waitForOk(timeoutMs, options = {}) {
const command = options.command || ''; const command = options.command || '';
const waitLogAfterMs = options.waitLogAfterMs ?? WallPlotter.OK_WAIT_LOG_MS; const quiet = options.quiet === true;
const waitLabel = command ? ` (${command})` : ''; 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) => { return new Promise((resolve, reject) => {
if (this._okWaiter) { if (this._okWaiter) {
@@ -1339,6 +1352,32 @@ class WallPlotter {
waiter.reject(err); 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() { _startReadLoop() {
this.readLoopActive = true; this.readLoopActive = true;
const plotter = this; const plotter = this;
@@ -1403,8 +1442,9 @@ class WallPlotter {
} }
return; return;
} }
this.onLog('← ' + line); const isOk = /^(echo:\s*)?ok\b/i.test(line);
if (/^(echo:\s*)?ok\b/i.test(line)) { if (!isOk) this.onLog('← ' + line);
if (isOk) {
const waiter = this._okWaiter; const waiter = this._okWaiter;
if (waiter) waiter.resolve(); if (waiter) waiter.resolve();
} }