scan after scan after scan

This commit is contained in:
legop3
2026-05-01 17:34:48 -04:00
parent c01456409d
commit c37a7965ff
@@ -1,8 +1,7 @@
const { spawn } = require('child_process'); const { spawn } = require('child_process');
const EventEmitter = require('events'); const EventEmitter = require('events');
const POLL_INTERVAL_MS = 3500; const SCAN_TIMEOUT_MS = 4000;
const SCAN_TIMEOUT_MS = 2000;
const RECONNECT_DELAY_MS = 5000; const RECONNECT_DELAY_MS = 5000;
function parsePayloadLine(line) { function parsePayloadLine(line) {
@@ -48,7 +47,8 @@ function createLidarRuntime({ logger, host, port = 6053, key, shouldPoll, reques
connected: false, connected: false,
process: null, process: null,
reconnectTimer: null, reconnectTimer: null,
pollTimer: null, pollSoonTimer: null,
requestTimeoutTimer: null,
stdoutBuffer: '', stdoutBuffer: '',
currentScan: null, currentScan: null,
requestInFlight: false, requestInFlight: false,
@@ -65,6 +65,26 @@ function createLidarRuntime({ logger, host, port = 6053, key, shouldPoll, reques
state.reconnectTimer = null; state.reconnectTimer = null;
} }
function clearPollSoonTimer() {
if (!state.pollSoonTimer) return;
clearTimeout(state.pollSoonTimer);
state.pollSoonTimer = null;
}
function clearRequestTimeoutTimer() {
if (!state.requestTimeoutTimer) return;
clearTimeout(state.requestTimeoutTimer);
state.requestTimeoutTimer = null;
}
function triggerPollSoon() {
if (state.pollSoonTimer) return;
state.pollSoonTimer = setTimeout(() => {
state.pollSoonTimer = null;
tickPoll();
}, 0);
}
function scheduleReconnect() { function scheduleReconnect() {
if (state.reconnectTimer) return; if (state.reconnectTimer) return;
state.reconnectTimer = setTimeout(() => { state.reconnectTimer = setTimeout(() => {
@@ -74,6 +94,7 @@ function createLidarRuntime({ logger, host, port = 6053, key, shouldPoll, reques
} }
function resetScanState() { function resetScanState() {
clearRequestTimeoutTimer();
state.currentScan = null; state.currentScan = null;
state.requestInFlight = false; state.requestInFlight = false;
state.requestStartedAt = 0; state.requestStartedAt = 0;
@@ -92,6 +113,7 @@ function createLidarRuntime({ logger, host, port = 6053, key, shouldPoll, reques
logger.info('Neato lidar scan parsed', { points: points.length, rotationSpeed: payload.rotationSpeed }); logger.info('Neato lidar scan parsed', { points: points.length, rotationSpeed: payload.rotationSpeed });
resetScanState(); resetScanState();
events.emit('scan', payload); events.emit('scan', payload);
triggerPollSoon();
} }
function handlePayload(payload) { function handlePayload(payload) {
@@ -168,6 +190,7 @@ function createLidarRuntime({ logger, host, port = 6053, key, shouldPoll, reques
if (!state.connected) { if (!state.connected) {
state.connected = true; state.connected = true;
emitStatus(); emitStatus();
triggerPollSoon();
} }
handleStdoutChunk(chunk); handleStdoutChunk(chunk);
}); });
@@ -193,38 +216,33 @@ function createLidarRuntime({ logger, host, port = 6053, key, shouldPoll, reques
async function tickPoll() { async function tickPoll() {
if (!state.connected) return; if (!state.connected) return;
if (!shouldPoll?.()) return; if (!shouldPoll?.()) return;
if (state.requestInFlight) { if (state.requestInFlight) return;
if (Date.now() - state.requestStartedAt >= SCAN_TIMEOUT_MS) {
logger.warn('Neato lidar scan timed out; resetting parser state');
resetScanState();
}
return;
}
state.requestInFlight = true; state.requestInFlight = true;
state.requestStartedAt = Date.now(); state.requestStartedAt = Date.now();
clearRequestTimeoutTimer();
state.requestTimeoutTimer = setTimeout(() => {
logger.warn('Neato lidar scan timed out; resetting parser state');
resetScanState();
triggerPollSoon();
}, SCAN_TIMEOUT_MS);
try { try {
await requestScan?.(); await requestScan?.();
} catch (err) { } catch (err) {
logger.warn('Failed to request Neato lidar scan', err.message); logger.warn('Failed to request Neato lidar scan', err.message);
resetScanState(); resetScanState();
triggerPollSoon();
} }
} }
function start() { function start() {
startLogStream(); startLogStream();
if (!state.pollTimer) { triggerPollSoon();
state.pollTimer = setInterval(() => {
tickPoll();
}, POLL_INTERVAL_MS);
}
} }
function stop() { function stop() {
clearReconnectTimer(); clearReconnectTimer();
if (state.pollTimer) { clearPollSoonTimer();
clearInterval(state.pollTimer); clearRequestTimeoutTimer();
state.pollTimer = null;
}
teardownProcess(); teardownProcess();
} }