diff --git a/web/app.js b/web/app.js index e6d056e..f9cb1c6 100644 --- a/web/app.js +++ b/web/app.js @@ -37,7 +37,10 @@ let _gattDepth = 0; function _withTimeout(promise, ms) { return new Promise((resolve, reject) => { - const t = setTimeout(() => reject(new Error(`GATT timeout (${ms}ms)`)), ms); + const t = setTimeout(() => { + console.warn(`[GATT] operation timed out after ${ms}ms`); + reject(new Error(`GATT timeout (${ms}ms)`)); + }, ms); promise.then(v => { clearTimeout(t); resolve(v); }, e => { clearTimeout(t); reject(e); }); }); @@ -45,6 +48,7 @@ function _withTimeout(promise, ms) { function _enqueue(fn) { if (_gattDepth >= GATT_MAX_DEPTH) { + console.warn(`[GATT] write dropped - queue depth ${_gattDepth} >= max ${GATT_MAX_DEPTH}`); return Promise.reject(new Error('GATT queue full - device unreachable?')); } _gattDepth++; @@ -57,6 +61,7 @@ function gattWrite(char, value) { return _enqueue(() => char.writeValueWithRespo function gattCmd (char, value) { return _enqueue(() => char.writeValueWithoutResponse(value)); } function gattQueueReset() { + console.log('[GATT] queue reset'); // Drain the chain so a reconnect starts with a fresh resolved promise _gattQueue = Promise.resolve(); _gattDepth = 0; @@ -133,7 +138,9 @@ async function discoverServices() { // Telemetry notify (1 Hz) - also carries chargeStatus chars.telemetry.addEventListener('characteristicvaluechanged', e => parseTelemetry(e.target.value)); + console.log('[TELEM] subscribing to notifications'); await chars.telemetry.startNotifications(); + console.log('[TELEM] subscribed, reading initial value'); // Initial read so values show immediately. Also force updateChargeUI() here // because parseTelemetry() only calls it on a *change*, and currentChargeStatus // starts at 0 (discharging) - so a discharging device would never trigger the @@ -487,6 +494,7 @@ function parseTelemetry(dv) { // chargeStatus is now delivered via telemetry (no separate characteristic) if (chargeStatus !== currentChargeStatus) { currentChargeStatus = chargeStatus; + console.log('[TELEM] charge status:', ['discharging','charging','full'][chargeStatus] ?? chargeStatus); updateChargeUI(); } @@ -547,6 +555,7 @@ let debugLiveRing = []; let debugT0 = 0; function openDebugModal() { + console.log('[DEBUG] modal opened (imuSubscribed=' + imuSubscribed + ')'); debugModalOpen = true; debugT0 = Date.now(); debugLiveRing = []; @@ -555,6 +564,7 @@ function openDebugModal() { if (!imuSubscribed && chars.imuStream) vizSetPaused(false); } function closeDebugModal() { + console.log('[DEBUG] modal closed'); debugModalOpen = false; document.getElementById('debugOverlay').classList.remove('show'); } @@ -706,6 +716,7 @@ const TRAIL_LEN = 120; let cursorX = canvas.width/2, cursorY = canvas.height/2, trail = []; let vizPaused = true; let imuSubscribed = false; +let _prevIdle = false; // Stream diagnostics let streamPktCount = 0; // packets received this second @@ -715,7 +726,9 @@ let streamLastRateT = 0; // timestamp of last rate log let streamFreezeTimer = null; // fires if no packet for >1s while subscribed function streamDiagReset() { + console.log('[STREAM] diagnostics reset'); streamPktCount = streamPktTotal = streamLastPktT = streamLastRateT = 0; + _prevIdle = false; if (streamFreezeTimer) { clearTimeout(streamFreezeTimer); streamFreezeTimer = null; } } @@ -771,6 +784,7 @@ function vizUpdateIndicator() { async function vizSetPaused(paused) { vizPaused = paused; if (!paused && chars.imuStream && !imuSubscribed) { + console.log('[STREAM] requesting subscribe'); try { await chars.imuStream.startNotifications(); imuSubscribed = true; @@ -778,12 +792,15 @@ async function vizSetPaused(paused) { log('IMU stream subscribed','ok'); } catch(e) { log(`IMU stream start failed: ${e.message}`,'err'); vizPaused = true; } } else if (paused && imuSubscribed) { + console.log(`[STREAM] requesting unsubscribe (total rx: ${streamPktTotal})`); try { await chars.imuStream.stopNotifications(); imuSubscribed = false; streamDiagReset(); document.getElementById('orientLabel').textContent = '- not streaming -'; } catch(e) { log(`IMU stream stop failed: ${e.message}`,'err'); } + } else { + console.log(`[STREAM] vizSetPaused(${paused}) - no action (imuSubscribed=${imuSubscribed})`); } vizUpdateIndicator(); } @@ -817,6 +834,7 @@ function parseImuStream(dv) { feedDebugRow(gyroX, gyroZ, accelX, accelY, accelZ, moveX, moveY, flags); if (vizPaused) return; + const idle = !!(flags & 0x01); const single = !!(flags & 0x02); const dbl = !!(flags & 0x04); @@ -835,6 +853,13 @@ function parseImuStream(dv) { streamDiagPkt(); + if (idle !== _prevIdle) { + console.log(`[STREAM] idle → ${idle ? 'idle' : 'active'} (pkt #${streamPktTotal})`); + _prevIdle = idle; + } + if (single) console.log(`[STREAM] single tap (pkt #${streamPktTotal})`); + if (dbl) console.log(`[STREAM] double tap (pkt #${streamPktTotal})`); + if (single) flashTap('Left'); if (dbl) flashTap('Right'); drawViz(idle);