ros-mobile-bridge 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/LICENSE +201 -0
- package/README.md +174 -0
- package/ROADMAP.md +85 -0
- package/SECURITY.md +46 -0
- package/dist/index.cjs +2288 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +737 -0
- package/dist/index.d.ts +737 -0
- package/dist/index.mjs +2275 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +94 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/CircuitBreaker.ts","../src/EventLoopMonitor.ts","../src/SubscriptionBandwidth.ts","../src/schemaToTemplate.ts","../src/jsonSchemaToTemplate.ts","../src/FoxgloveClient.ts","../src/RosbridgeClient.ts","../src/constants.ts","../src/ProtocolManager.ts"],"names":["parseRosMsgDef","NOOP_LOGGER","TEXT_DECODER","MAX_RECONNECT_ATTEMPTS","BASE_RECONNECT_DELAY_MS","CONNECTION_TIMEOUT_MS","ZERO_TWIST","CMD_VEL_SCHEMA"],"mappings":"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","file":"index.mjs","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * CircuitBreaker — per-subscription state machine that gracefully suspends\n * a topic when the adaptive throttle has done all it can but the JS thread\n * is still saturated.\n *\n * Design rationale: at the deepest throttle bucket (e.g. 0.5 Hz cap), each\n * 1080p q95 frame parse still takes ~200 ms on a modern phone — even one\n * frame every two seconds produces a perceptible 200 ms gesture freeze. No\n * amount of further throttle tuning fixes this; the workload is\n * fundamentally too heavy for the transport on this device. The breaker\n * detects sustained overload at the deepest bucket and unsubscribes from\n * the bridge, freeing the JS thread, network, and memory entirely for that\n * topic until the user (or auto-retry) decides to try again.\n *\n * The state machine has four states:\n * - `closed`: normal, throttle handles the rest\n * - `tripped_auto`: paused, auto-retry timer running (exponential backoff)\n * - `tripped_manual`: paused, NO auto-retry — user opted out\n * - `half_open`: re-subscribed, watching lag for `recoveryDwellMs`; if lag\n * stays low, close; if it spikes, re-trip with longer cooldown.\n *\n * The breaker is a pure state machine — it doesn't send WebSocket ops\n * itself. The protocol client's `onStateChange` callback is responsible for\n * the side effects (send unsubscribe on enter `tripped_auto`, send\n * subscribe on enter `half_open`, etc).\n */\n\nimport type { CircuitBreakerState } from './types';\n\nexport interface CircuitBreakerConfig {\n /**\n * Lag threshold (ms) above which the breaker considers the subscription\n * \"still saturated\" while at the deepest throttle bucket. Suggest 250 ms —\n * well above normal lag, well below a total freeze.\n */\n lagThresholdMs: number;\n\n /**\n * Sustained ms of over-threshold lag before tripping. Suggest 5000 ms —\n * long enough that transient spikes (one heavy frame, a GC pause) don't\n * trigger; short enough that a genuinely too-heavy workload trips before\n * the user gets frustrated.\n */\n tripDwellMs: number;\n\n /**\n * ms of healthy operation in `half_open` before closing the breaker.\n * Suggest 10000 ms.\n */\n recoveryDwellMs: number;\n\n /**\n * Cooldown durations per consecutive trip within this connection. Index\n * `tripCount - 1` is read; the last value is reused for further trips.\n * Suggest `[30000, 60000, 120000, 300000]`.\n */\n cooldownsMs: number[];\n\n /**\n * Side-effect handler. Called on every state transition. The protocol\n * client uses it to send the actual `subscribe` / `unsubscribe` ops to\n * the bridge.\n */\n onStateChange: (newState: CircuitBreakerState, oldState: CircuitBreakerState) => void;\n}\n\n/**\n * ms of sustained healthy observations before we reset the saturation\n * timer. Without this debounce, lag oscillating around the trip threshold\n * resets the timer every other sample and the breaker never accumulates\n * enough dwell to trip even when the workload is plainly saturating things.\n */\nconst HEALTHY_DEBOUNCE_MS = 4000;\n\n/**\n * Grace period after a (re)subscription before the breaker can register\n * any observations. The first 1-2 s after subscribe always have transient\n * spikes (initial frame burst, schema parse, first JIT pass through the\n * decode path) that don't reflect sustained workload. Without warmup these\n * can trip the breaker on lightweight workloads before the JIT settles in.\n */\nconst WARMUP_MS = 2000;\n\nexport class CircuitBreaker {\n private state: CircuitBreakerState = 'closed';\n private tripCount = 0;\n private saturationObservedAt = 0;\n private healthyObservedAt = 0;\n private cooldownTimer: ReturnType<typeof setTimeout> | null = null;\n private subscriptionStartedAt: number = Date.now();\n private nextRetryAt: number | null = null;\n\n constructor(private readonly config: CircuitBreakerConfig) {}\n\n getState(): CircuitBreakerState {\n return this.state;\n }\n\n /**\n * `Date.now()` when auto-retry is scheduled to fire, or `null` if no\n * cooldown is running (closed / half_open / tripped_manual).\n */\n getNextRetryAt(): number | null {\n return this.nextRetryAt;\n }\n\n /**\n * Single entry point for \"I saw a message; here's the current bandwidth\n * and JS-thread lag.\" Internally gates by `HEAVY_BANDWIDTH_THRESHOLD_BYTES_PER_SEC`\n * and the breaker's `lagThresholdMs` so the trip policy lives in one place\n * instead of being replicated at every call site.\n */\n recordObservation(now: number, bytesPerSec: number, lagMs: number): void {\n if (bytesPerSec > HEAVY_BANDWIDTH_THRESHOLD_BYTES_PER_SEC && lagMs > this.config.lagThresholdMs) {\n this.recordOverloaded(now);\n } else {\n this.recordHealthy(now);\n }\n }\n\n /**\n * Called from the protocol client's `recordBytes` when the tracker is in\n * the heavily-throttled range (top buckets) and lag exceeds the threshold.\n */\n recordOverloaded(now: number): void {\n if (now - this.subscriptionStartedAt < WARMUP_MS) return;\n if (this.state === 'closed' || this.state === 'half_open') {\n if (this.saturationObservedAt === 0) {\n this.saturationObservedAt = now;\n } else if (now - this.saturationObservedAt >= this.config.tripDwellMs) {\n this.trip();\n }\n this.healthyObservedAt = 0;\n }\n }\n\n /**\n * Called from `recordBytes` when lag is below threshold or the tracker is\n * below the heavily-throttled range.\n */\n recordHealthy(now: number): void {\n if (now - this.subscriptionStartedAt < WARMUP_MS) return;\n if (this.state !== 'closed' && this.state !== 'half_open') return;\n\n if (this.healthyObservedAt === 0) {\n this.healthyObservedAt = now;\n }\n const healthyDwell = now - this.healthyObservedAt;\n\n if (this.saturationObservedAt > 0 && healthyDwell >= HEALTHY_DEBOUNCE_MS) {\n this.saturationObservedAt = 0;\n }\n\n if (this.state === 'half_open' && healthyDwell >= this.config.recoveryDwellMs) {\n this.close();\n }\n }\n\n /**\n * User pressed \"try again now\" — bypasses the cooldown timer and jumps\n * straight to `half_open`. Works from any tripped state.\n */\n retry(): void {\n if (this.state === 'tripped_auto' || this.state === 'tripped_manual') {\n this.clearCooldown();\n this.openHalf();\n }\n }\n\n /**\n * User pressed \"stop trying\" — switches `tripped_auto` to `tripped_manual`\n * and cancels the auto-retry timer. The subscription remains paused until\n * the user manually retries.\n */\n disable(): void {\n if (this.state === 'tripped_auto') {\n this.clearCooldown();\n this.transition('tripped_manual');\n }\n }\n\n /**\n * Called by the protocol client on disconnect or unsubscribe so the\n * cooldown timer doesn't outlive the connection.\n */\n destroy(): void {\n this.clearCooldown();\n }\n\n // ── Internal transitions ─────────────────────────────────────────────\n\n private trip(): void {\n this.tripCount++;\n this.saturationObservedAt = 0;\n const cooldownIdx = Math.min(this.tripCount - 1, this.config.cooldownsMs.length - 1);\n const cooldownMs = this.config.cooldownsMs[cooldownIdx] ?? 30_000;\n this.nextRetryAt = Date.now() + cooldownMs;\n this.transition('tripped_auto');\n this.cooldownTimer = setTimeout(() => {\n this.cooldownTimer = null;\n this.nextRetryAt = null;\n if (this.state === 'tripped_auto') {\n this.openHalf();\n }\n }, cooldownMs);\n }\n\n private openHalf(): void {\n const now = Date.now();\n this.saturationObservedAt = 0;\n this.healthyObservedAt = 0;\n this.subscriptionStartedAt = now;\n this.transition('half_open');\n }\n\n private close(): void {\n this.saturationObservedAt = 0;\n this.transition('closed');\n }\n\n private transition(next: CircuitBreakerState): void {\n const prev = this.state;\n if (prev === next) return;\n this.state = next;\n try {\n this.config.onStateChange(next, prev);\n } catch {\n // The side-effect callback shouldn't throw; if it does we don't want\n // to leave the breaker in a half-applied state — `this.state` is\n // already updated above.\n }\n }\n\n private clearCooldown(): void {\n if (this.cooldownTimer !== null) {\n clearTimeout(this.cooldownTimer);\n this.cooldownTimer = null;\n }\n this.nextRetryAt = null;\n }\n}\n\n/**\n * Default config tuned for the camera-on-modern-phone workload that\n * motivated the breaker. Protocol clients can override per subscription.\n */\nexport const DEFAULT_BREAKER_CONFIG: Omit<CircuitBreakerConfig, 'onStateChange'> = {\n lagThresholdMs: 250,\n tripDwellMs: 5_000,\n recoveryDwellMs: 10_000,\n cooldownsMs: [30_000, 60_000, 120_000, 300_000],\n};\n\n/**\n * Bytes/sec floor a subscription must exceed before the breaker considers\n * tripping it. Without this gate, when one heavy publisher saturates the\n * thread, every subscription sees the same high lag and trips in lockstep\n * — killing innocent low-rate topics. With the gate, only the actual heavy\n * contributor qualifies.\n */\nexport const HEAVY_BANDWIDTH_THRESHOLD_BYTES_PER_SEC = 500_000;\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * EventLoopMonitor — direct measurement of JS-thread saturation.\n *\n * Hardcoded byte/sec bucket thresholds were a proxy for \"is the JS thread\n * saturated?\" calibrated to one device class and one message size; on\n * different devices or with bigger frames they under- or over-throttled.\n * This monitor measures the actual symptom.\n *\n * Mechanism: a `setInterval` fires every PROBE_INTERVAL_MS. Each tick\n * records how late it ran vs. when it was scheduled. Under saturation the\n * JS thread is busy with parse / reconcile work and the timer fires late —\n * that delta IS the lag. Under idle, lag is ~0-5 ms (normal scheduler\n * jitter).\n *\n * Smoothing: a 1 s rolling window keeps (timestamp, lag) pairs. The\n * reported value is the MAX over that window, not an EMA — bursty\n * saturation should be detected on the spike, not blurred away.\n *\n * The monitor starts on first `getMaxLagMs()` call (lazy) and runs forever.\n * Cost: one `setInterval` at 5 Hz reading `Date.now()`.\n *\n * Public surface: `getMaxLagMs`, `getLagStats`, `getLagHistoryCsv`, and\n * `clearLagHistory` are exported from the package and let consumers build\n * \"currently throttled\" diagnostics. `setModeGetter` is module-internal —\n * protocol clients call it from their constructors so the lag history is\n * tagged with the active throttle mode for bug-report exports, and\n * consumers never need to wire it themselves.\n */\n\nconst PROBE_INTERVAL_MS = 200;\nconst WINDOW_MS = 1000;\nconst HISTORY_MAX = 600;\n\ninterface LagSample {\n t: number;\n lag: number;\n}\n\ninterface HistorySample {\n t: number;\n lag: number;\n mode: string;\n}\n\nlet started = false;\nlet lastTickAt = 0;\nconst samples: LagSample[] = [];\nconst history: HistorySample[] = [];\n\nlet modeGetter: () => string = () => 'auto';\n\n/**\n * Internal. Protocol clients invoke this from their constructors with the\n * value they received from `ProtocolClientOptions.getThrottleMode`. The\n * monitor uses the result to tag history samples with the active throttle\n * mode for the diagnostics CSV. Not re-exported from the package entry\n * point — consumers configure throttle mode through `getThrottleMode`.\n */\nexport function setModeGetter(fn: () => string): void {\n modeGetter = fn;\n}\n\nfunction startMonitor(): void {\n if (started) return;\n started = true;\n lastTickAt = Date.now();\n const handle: unknown = setInterval(() => {\n const now = Date.now();\n const elapsed = now - lastTickAt;\n const lag = Math.max(0, elapsed - PROBE_INTERVAL_MS);\n lastTickAt = now;\n\n samples.push({ t: now, lag });\n const cutoff = now - WINDOW_MS;\n while (samples.length > 0) {\n const head = samples[0];\n if (!head || head.t >= cutoff) break;\n samples.shift();\n }\n\n let mode = 'auto';\n try {\n mode = modeGetter();\n } catch {\n // mode tagging is best-effort; never break the monitor on a bad getter.\n }\n history.push({ t: now, lag, mode });\n if (history.length > HISTORY_MAX) {\n history.shift();\n }\n }, PROBE_INTERVAL_MS);\n\n // The monitor is a passive diagnostic; it must not keep a Node process\n // alive on its own. Once a consumer's real work (an active WebSocket,\n // an HTTP server) finishes, the process should exit even if the monitor\n // is still ticking. `unref` exists on Node's Timeout object; browsers,\n // React Native, and Electron's renderer don't have or need it.\n const unref = (handle as { unref?: () => void } | null)?.unref;\n if (typeof unref === 'function') {\n unref.call(handle);\n }\n}\n\n/**\n * Max observed JS-thread lag (ms) over the last `WINDOW_MS`. Auto-starts\n * the monitor on first call. Returns `0` if no samples have been collected\n * yet.\n */\nexport function getMaxLagMs(): number {\n if (!started) startMonitor();\n let max = 0;\n for (const s of samples) {\n if (s.lag > max) max = s.lag;\n }\n return max;\n}\n\n/**\n * Percentile statistics over the long-term history buffer (roughly the last\n * 2 minutes). Returns `null` when no samples have been collected yet.\n */\nexport function getLagStats(): {\n count: number;\n durationSec: number;\n p50: number;\n p90: number;\n p99: number;\n max: number;\n} | null {\n if (history.length === 0) return null;\n const sorted = history.map((s) => s.lag).sort((a, b) => a - b);\n const pick = (q: number): number => {\n const idx = Math.min(sorted.length - 1, Math.floor(sorted.length * q));\n return sorted[idx] ?? 0;\n };\n const first = history[0];\n const last = history[history.length - 1];\n const span = first && last ? (last.t - first.t) / 1000 : 0;\n return {\n count: history.length,\n durationSec: Math.round(span),\n p50: pick(0.5),\n p90: pick(0.9),\n p99: pick(0.99),\n max: sorted[sorted.length - 1] ?? 0,\n };\n}\n\n/**\n * CSV dump of the history buffer. One row per sample, mode-tagged so a\n * recording that spans a throttle-mode change still tells you which lag\n * values belong to which mode. Useful for attaching to bug reports.\n */\nexport function getLagHistoryCsv(): string {\n const header = 'timestamp_ms,lag_ms,mode';\n const rows = history.map((s) => `${s.t},${s.lag},${s.mode}`);\n return [header, ...rows].join('\\n');\n}\n\n/**\n * Clear the long-term history buffer. The rolling 1 s window used by the\n * throttle keeps running, so live throttle decisions stay correct. Useful\n * when starting a new test session.\n */\nexport function clearLagHistory(): void {\n history.length = 0;\n}\n\n/**\n * Test helper. Resets the monitor's internal state so unit tests get a\n * clean slate. Not exported from the package entry point.\n *\n * @internal\n */\nexport function __resetEventLoopMonitor(): void {\n samples.length = 0;\n history.length = 0;\n lastTickAt = Date.now();\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * SubscriptionBandwidth — adaptive throttle driven by JS-thread saturation.\n *\n * Bucket selection reads `EventLoopMonitor.getMaxLagMs()` rather than a\n * per-subscription bytes/sec rate. The symptom the throttle is protecting\n * against (gesture and control starvation) is a property of the JS thread,\n * not of any single message stream, so the right signal is thread saturation\n * directly. A bytes/sec ladder would have to be calibrated per device class\n * and per message size — fragile in a library targeting four runtimes — and\n * would miss the case where several medium-rate subscriptions (lidar + odom\n * + imu) sum to thread saturation while none individually crosses a byte\n * threshold.\n *\n * Bytes/sec is still tracked per subscription for metrics and UI (\"currently\n * throttled because /camera is at 5 MB/s\") via `getSubscriptionStats`; it is\n * not the throttle decision input.\n *\n * Hysteresis: tighten immediately on the spike (saturation costs gesture\n * authority — pay the cost up front), relax slowly (3 s below threshold) so\n * the throttle doesn't oscillate around a boundary.\n *\n * The curves themselves (`DEFAULT_PRESETS` below) were tuned on one device\n * class. Consumers can override per mode via `ProtocolClientOptions.presetOverrides`;\n * each tracker carries its own effective preset map so two clients with\n * different overrides don't share state.\n */\n\nimport { getMaxLagMs } from './EventLoopMonitor';\nimport type { BucketDef, ProtocolLogger, ThrottleMode } from './types';\n\nconst BANDWIDTH_WINDOW_MS = 1000;\nconst TIGHTEN_DWELL_MS = 0;\nconst RELAX_DWELL_MS = 3000;\n\n/**\n * Library-tuned throttle curves. Override via\n * `ProtocolClientOptions.presetOverrides` to ship a per-device-class curve.\n * Exported for use by consumers building their own preset variants on top\n * of the defaults (e.g. `{ ...DEFAULT_PRESETS, auto: [...customAuto] }`).\n *\n * @experimental The override *shape* (`BucketDef`, `ThrottleMode`,\n * `presetOverrides`) is semver-stable, but the default *values* in this map\n * may be rebalanced in any patch release as device-tuning data accrues. Do\n * not snapshot these numbers and assume they're frozen; reference the export\n * if you want to track the current defaults.\n */\nexport const DEFAULT_PRESETS: Record<ThrottleMode, BucketDef[]> = {\n performance: [{ threshold: 0, minIntervalMs: 0, label: 'none' }],\n\n auto: [\n { threshold: 0, minIntervalMs: 0, label: 'none' },\n { threshold: 100, minIntervalMs: 100, label: '10 Hz' },\n { threshold: 150, minIntervalMs: 200, label: '5 Hz' },\n { threshold: 200, minIntervalMs: 1000, label: '1 Hz' },\n { threshold: 350, minIntervalMs: 2000, label: '0.5 Hz' },\n ],\n\n efficient: [\n { threshold: 0, minIntervalMs: 0, label: 'none' },\n { threshold: 80, minIntervalMs: 100, label: '10 Hz' },\n { threshold: 130, minIntervalMs: 200, label: '5 Hz' },\n { threshold: 200, minIntervalMs: 1000, label: '1 Hz' },\n { threshold: 350, minIntervalMs: 2000, label: '0.5 Hz' },\n ],\n};\n\nconst THROTTLE_MODES: readonly ThrottleMode[] = ['performance', 'auto', 'efficient'];\n\n/**\n * Pessimistic-start initial bucket per mode. Without this, every new\n * subscription floods → spike → tighten, costing the first ~1 s of\n * usability while the throttle catches up. Each tracker boots at a\n * moderate cap and only relaxes if observed lag stays below the\n * next-lower bucket's threshold long enough.\n */\nconst INITIAL_BUCKET_PER_MODE: Record<ThrottleMode, number> = {\n performance: 0,\n auto: 2,\n efficient: 3,\n};\n\n/**\n * Validate a single mode's bucket array. Returns `true` if usable as an\n * override; logs a warning and returns `false` otherwise so the caller can\n * fall back to the default for that mode.\n *\n * Only enforces correctness-essential rules:\n * - The array is non-empty.\n * - The first bucket has `threshold === 0`.\n *\n * Consumer-hygiene rules (thresholds sorted ascending, unique labels) are\n * intentionally not enforced — `recordBytes` and `bucketLabelForLag`\n * terminate with sensible-enough results in their absence, and listing every\n * possible quality rule is not the library's job.\n */\nfunction validatePreset(\n buckets: BucketDef[] | undefined,\n mode: ThrottleMode,\n logger: ProtocolLogger,\n): boolean {\n if (!buckets || buckets.length === 0) {\n logger.warn(\n `[ros-mobile-bridge] presetOverrides.${mode}: empty bucket array; using default preset for this mode`,\n );\n return false;\n }\n const first = buckets[0];\n if (!first || first.threshold !== 0) {\n logger.warn(\n `[ros-mobile-bridge] presetOverrides.${mode}: first bucket must have threshold === 0 (the \"no throttle\" base case); using default preset for this mode`,\n );\n return false;\n }\n return true;\n}\n\n/**\n * Merge consumer-supplied overrides on top of `DEFAULT_PRESETS`. Invalid\n * per-mode overrides are skipped (with a `logger.warn`); valid ones replace\n * the default for their mode. Returns a fresh object so two clients with\n * different overrides never share mutable state through this map.\n */\nexport function buildEffectivePresets(\n overrides: Partial<Record<ThrottleMode, BucketDef[]>> | undefined,\n logger: ProtocolLogger,\n): Record<ThrottleMode, BucketDef[]> {\n const merged: Record<ThrottleMode, BucketDef[]> = {\n performance: DEFAULT_PRESETS.performance,\n auto: DEFAULT_PRESETS.auto,\n efficient: DEFAULT_PRESETS.efficient,\n };\n if (!overrides) return merged;\n\n for (const mode of THROTTLE_MODES) {\n const override = overrides[mode];\n if (override === undefined) continue;\n if (validatePreset(override, mode, logger)) {\n merged[mode] = override;\n }\n }\n return merged;\n}\n\nexport interface BandwidthTracker {\n /** Ring buffer of (timestamp, byteSize) over the rolling window. */\n window: Array<{ t: number; b: number }>;\n /** Cached bytes/sec, updated on each `recordBytes`. */\n bytesPerSec: number;\n /** Bucket index currently applied (drives `adaptiveMinIntervalMs`). */\n currentBucket: number;\n /**\n * Most recently observed target bucket (may differ from `currentBucket`\n * while we're inside the hysteresis dwell window).\n */\n targetBucket: number;\n /** ms timestamp when `targetBucket` was first observed. */\n targetObservedAt: number;\n /** Effective adaptive throttle interval. `0` means no throttle. */\n adaptiveMinIntervalMs: number;\n /**\n * Effective preset map for this tracker. Shared by reference across every\n * tracker created by the same client; never mutated after construction.\n */\n presets: Record<ThrottleMode, BucketDef[]>;\n}\n\nexport function createBandwidthTracker(\n mode: ThrottleMode = 'auto',\n presets: Record<ThrottleMode, BucketDef[]> = DEFAULT_PRESETS,\n): BandwidthTracker {\n const initialBucket = INITIAL_BUCKET_PER_MODE[mode] ?? 0;\n const preset = presets[mode];\n const safeInitial = Math.min(initialBucket, Math.max(0, preset.length - 1));\n const initialIntervalMs = preset[safeInitial]?.minIntervalMs ?? 0;\n return {\n window: [],\n bytesPerSec: 0,\n currentBucket: safeInitial,\n targetBucket: safeInitial,\n targetObservedAt: 0,\n adaptiveMinIntervalMs: initialIntervalMs,\n presets,\n };\n}\n\n/**\n * Record an incoming message of `byteSize` bytes at time `now`. Updates the\n * rolling byte window and applies the bucket policy for the active mode\n * based on JS-thread lag. Mutates `tracker` in place.\n *\n * Bucket selection reads from `EventLoopMonitor.getMaxLagMs()` — a global\n * signal, not per-subscription. If every subscription is a small\n * contributor but they sum to JS-thread saturation, the throttle still\n * fires. That's correct: the symptom we're protecting against (gesture and\n * control starvation) is a property of the thread, not a single stream.\n */\nexport function recordBytes(\n tracker: BandwidthTracker,\n now: number,\n byteSize: number,\n mode: ThrottleMode = 'auto',\n): void {\n tracker.window.push({ t: now, b: byteSize });\n const cutoff = now - BANDWIDTH_WINDOW_MS;\n while (tracker.window.length > 0) {\n const head = tracker.window[0];\n if (!head || head.t >= cutoff) break;\n tracker.window.shift();\n }\n let total = 0;\n for (const e of tracker.window) total += e.b;\n tracker.bytesPerSec = total / (BANDWIDTH_WINDOW_MS / 1000);\n\n const buckets = tracker.presets[mode];\n const lagMs = getMaxLagMs();\n\n let targetBucket = 0;\n for (let i = buckets.length - 1; i >= 1; i--) {\n const bucket = buckets[i];\n if (bucket && lagMs >= bucket.threshold) {\n targetBucket = i;\n break;\n }\n }\n\n if (targetBucket !== tracker.targetBucket) {\n tracker.targetBucket = targetBucket;\n tracker.targetObservedAt = now;\n return;\n }\n if (targetBucket === tracker.currentBucket) {\n return;\n }\n\n const dwell = now - tracker.targetObservedAt;\n const tighten = targetBucket > tracker.currentBucket;\n const requiredDwell = tighten ? TIGHTEN_DWELL_MS : RELAX_DWELL_MS;\n if (dwell < requiredDwell) return;\n\n if (tighten) {\n tracker.currentBucket = targetBucket;\n } else {\n tracker.currentBucket = Math.max(targetBucket, tracker.currentBucket - 1);\n tracker.targetObservedAt = now;\n }\n tracker.adaptiveMinIntervalMs = buckets[tracker.currentBucket]?.minIntervalMs ?? 0;\n}\n\n/**\n * Effective min-interval (ms) for a callback, combining the user's request\n * with the adaptive throttle. The user's `userMinIntervalMs` is a floor —\n * adaptive can only make the interval longer, never shorter.\n */\nexport function effectiveMinInterval(\n userMinIntervalMs: number | undefined,\n disableAdaptive: boolean,\n tracker: BandwidthTracker,\n): number {\n const user = userMinIntervalMs ?? 0;\n if (disableAdaptive) return user;\n return Math.max(user, tracker.adaptiveMinIntervalMs);\n}\n\n/**\n * Reset the tracker to the deepest bucket so half-open recovery starts\n * conservative. The throttle's existing step-relax logic walks the bucket\n * back up if observed lag stays below the next-lower bucket's threshold.\n * Avoids a flood-then-tighten cycle on every breaker recovery.\n */\nexport function setTrackerToDeepest(tracker: BandwidthTracker, mode: ThrottleMode): void {\n const buckets = tracker.presets[mode];\n const lastIdx = Math.max(0, buckets.length - 1);\n tracker.currentBucket = lastIdx;\n tracker.targetBucket = lastIdx;\n tracker.targetObservedAt = 0;\n tracker.adaptiveMinIntervalMs = buckets[lastIdx]?.minIntervalMs ?? 0;\n}\n\n/**\n * Label of the bucket the tracker is currently sitting at. Used by UI to\n * tell the user what cap their subscription is throttled to right now.\n * Returns `\"none\"` for the no-cap bucket (or when the tracker's bucket\n * index is somehow out of range, which shouldn't happen in practice).\n */\nexport function getTrackerBucketLabel(tracker: BandwidthTracker, mode: ThrottleMode): string {\n const buckets = tracker.presets[mode];\n return buckets[tracker.currentBucket]?.label ?? 'none';\n}\n\n/**\n * Resolve which bucket a given lag value would land in for the active mode\n * under the library's **default** presets. Independent of any tracker —\n * pass a raw lag measurement (typically from `getMaxLagMs()`) and the\n * active throttle mode, and get back the bucket label the default-tuned\n * throttle would apply at that lag.\n *\n * Useful for diagnostics overlays that want to show \"JS lag is N ms →\n * bucket X\" so observers can correlate measured lag with the throttle\n * policy.\n *\n * **Note on `presetOverrides`:** this function is a stateless module-level\n * helper and has no awareness of per-client overrides. If a consumer\n * supplies `presetOverrides.auto`, calling `bucketLabelForLag('auto', lag)`\n * still returns the **default** bucket label for that lag value, not the\n * override's. For override-aware bucket labels, read\n * `getSubscriptionStats(topic).bucketLabel` off a live subscription.\n */\nexport function bucketLabelForLag(mode: ThrottleMode, lagMs: number): string {\n const buckets = DEFAULT_PRESETS[mode];\n let idx = 0;\n for (let i = buckets.length - 1; i >= 1; i--) {\n const bucket = buckets[i];\n if (bucket && lagMs >= bucket.threshold) {\n idx = i;\n break;\n }\n }\n return buckets[idx]?.label ?? 'none';\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * schemaToTemplate — derive a default JSON payload from a parsed ROS message\n * definition.\n *\n * Takes the array returned by `@foxglove/rosmsg` (for `.msg` and ros2msg) or\n * `@foxglove/ros2idl-parser` (for ros2idl). The first element is the root\n * message; subsequent elements are referenced types. Returns a plain object\n * with every field set to its zero / empty default, ready to use as a\n * starting point for a publish payload editor.\n */\n\nimport type { MessageDefinition } from '@foxglove/message-definition';\n\nconst PRIMITIVE_DEFAULTS: Record<string, unknown> = {\n bool: false,\n int8: 0,\n uint8: 0,\n int16: 0,\n uint16: 0,\n int32: 0,\n uint32: 0,\n int64: 0,\n uint64: 0,\n float32: 0.0,\n float64: 0.0,\n string: '',\n wstring: '',\n time: { sec: 0, nsec: 0 },\n duration: { sec: 0, nsec: 0 },\n 'builtin_interfaces/Time': { sec: 0, nanosec: 0 },\n 'builtin_interfaces/Duration': { sec: 0, nanosec: 0 },\n 'builtin_interfaces/msg/Time': { sec: 0, nanosec: 0 },\n 'builtin_interfaces/msg/Duration': { sec: 0, nanosec: 0 },\n};\n\n/**\n * Build a default JSON template from a parsed message definition. Used by\n * `IProtocolClient.getSchemaTemplate` to surface ready-to-edit payloads for\n * publish UIs.\n */\nexport function schemaToTemplate(\n definitions: MessageDefinition[],\n): Record<string, unknown> {\n if (!definitions.length) return {};\n\n const typeMap = new Map<string, MessageDefinition>();\n for (const def of definitions) {\n if (def.name) {\n typeMap.set(def.name, def);\n }\n }\n\n const root = definitions[0];\n if (!root) return {};\n return buildObject(root, typeMap, 0);\n}\n\nfunction buildObject(\n def: MessageDefinition,\n typeMap: Map<string, MessageDefinition>,\n depth: number,\n): Record<string, unknown> {\n // Guard against self-referencing types.\n if (depth > 10) return {};\n\n const result: Record<string, unknown> = {};\n\n for (const field of def.definitions) {\n if (field.isConstant) continue;\n\n const defaultVal = getFieldDefault(field.type, field.isComplex, typeMap, depth);\n\n if (field.isArray) {\n result[field.name] = [];\n } else {\n result[field.name] = defaultVal;\n }\n }\n\n return result;\n}\n\nfunction getFieldDefault(\n typeName: string,\n isComplex: boolean | undefined,\n typeMap: Map<string, MessageDefinition>,\n depth: number,\n): unknown {\n if (PRIMITIVE_DEFAULTS[typeName] !== undefined) {\n const val = PRIMITIVE_DEFAULTS[typeName];\n return typeof val === 'object' ? JSON.parse(JSON.stringify(val)) : val;\n }\n\n if (isComplex) {\n const subDef = typeMap.get(typeName);\n if (subDef) {\n return buildObject(subDef, typeMap, depth + 1);\n }\n for (const [key, def] of typeMap) {\n if (key.endsWith(`/${typeName}`) || typeName.endsWith(`/${key}`)) {\n return buildObject(def, typeMap, depth + 1);\n }\n }\n }\n\n return '';\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * jsonSchemaToTemplate — derive a zero-valued JSON payload from a JSON Schema.\n *\n * Used by the Foxglove WebSocket path to turn bridges that ship JSON Schema\n * into Topic-Publisher / field-path templates. The reference foxglove_bridge\n * ships ros2idl instead, which `schemaToTemplate` handles; this parser\n * covers the remaining gap so consumers don't need a hard-coded table of\n * well-known ROS 2 types.\n *\n * Scope: draft-07-compatible JSON Schema, restricted to the subset a bridge\n * typically emits for ROS message shapes (object / array / primitive).\n * Does not resolve `$ref`, `allOf` / `oneOf` / `anyOf`, or enum defaults.\n */\n\nexport function jsonSchemaToTemplate(schema: unknown): unknown {\n if (!schema || typeof schema !== 'object' || Array.isArray(schema)) return null;\n const s = schema as Record<string, unknown>;\n\n // Explicit `default` wins over type-derived zero value.\n if ('default' in s) return s.default;\n\n const type = s.type;\n if (type === 'object') {\n const props = s.properties;\n if (!props || typeof props !== 'object' || Array.isArray(props)) return {};\n const result: Record<string, unknown> = {};\n for (const [key, sub] of Object.entries(props as Record<string, unknown>)) {\n result[key] = jsonSchemaToTemplate(sub);\n }\n return result;\n }\n\n if (type === 'array') {\n // Zero-length array matches the ROS shape for variable-length fields\n // (JointState.name, LaserScan.ranges, etc.).\n return [];\n }\n\n if (type === 'string') return '';\n if (type === 'number' || type === 'integer') return 0;\n if (type === 'boolean') return false;\n if (type === 'null') return null;\n\n // Union type (e.g. ['number', 'null']) — pick the first non-null entry.\n if (Array.isArray(type)) {\n const first = type.find((t) => t !== 'null') ?? type[0];\n return jsonSchemaToTemplate({ ...s, type: first });\n }\n\n return null;\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * FoxgloveClient — Foxglove WebSocket Protocol v1 implementation.\n *\n * Implements `IProtocolClient` against raw `WebSocket` using the Foxglove WS\n * v1 spec: https://github.com/foxglove/ws-protocol/blob/main/docs/spec.md\n *\n * Key design decisions:\n *\n * - Uses the runtime's global `WebSocket` (no `@foxglove/ws-protocol` SDK),\n * so the same compiled output runs in React Native, browsers, Node 22+\n * natively, and Node 18-21 with a `ws` polyfill.\n * - Supports JSON and CDR (binary) encoding via `@foxglove/rosmsg2-serialization`,\n * with ros2idl and ros2msg schemas.\n * - Exponential backoff reconnection (1 s → 2 s → 4 s → 8 s → 16 s, max 5\n * attempts).\n * - Keep-alive ping every 5 s, reconnect if no pong in 10 s.\n * - Dead-man's switch: publishes zero Twist on unexpected disconnect when\n * the client has been publishing on `/cmd_vel`.\n * - Control-priority outbox: gesture, E-Stop, and action-cancel publishes\n * drain at the top of every incoming WS message handler so they ride out\n * before the JS thread is consumed by the next parse macrotask.\n */\n\nimport { parse as parseRosMsgDef } from '@foxglove/rosmsg';\nimport { parseRos2idl } from '@foxglove/ros2idl-parser';\nimport { MessageReader } from '@foxglove/rosmsg2-serialization';\nimport {\n type BucketDef,\n type CircuitBreakerState,\n type ConnectionStatus,\n type IProtocolClient,\n type ProtocolClientOptions,\n type ProtocolLogger,\n type PublishOptions,\n type RosMessage,\n type ServiceInfo,\n type SubscribeOptions,\n type ThrottleMode,\n type TopicInfo,\n} from './types';\nimport { CircuitBreaker, DEFAULT_BREAKER_CONFIG } from './CircuitBreaker';\nimport { getMaxLagMs, setModeGetter } from './EventLoopMonitor';\nimport {\n type BandwidthTracker,\n buildEffectivePresets,\n createBandwidthTracker,\n effectiveMinInterval,\n getTrackerBucketLabel,\n recordBytes,\n setTrackerToDeepest,\n} from './SubscriptionBandwidth';\nimport { schemaToTemplate } from './schemaToTemplate';\nimport { jsonSchemaToTemplate } from './jsonSchemaToTemplate';\n\nconst NOOP_LOGGER: ProtocolLogger = { log() {}, warn() {}, error() {} };\n\n// Module-level singletons. `new TextEncoder()` / `new TextDecoder()` are\n// cheap but not free, and the per-message hot path constructs one per call\n// in the original code. Reusing matches what Node and browsers do\n// internally for encoders without options.\nconst TEXT_ENCODER = new TextEncoder();\nconst TEXT_DECODER = new TextDecoder();\n\n// ─── Foxglove WS v1 Protocol Types ──────────────────────────────────────────\n\ninterface FoxgloveChannel {\n id: number;\n topic: string;\n encoding: string;\n schemaName: string;\n schema: string;\n schemaEncoding?: string;\n}\n\ninterface FoxgloveServerInfo {\n op: 'serverInfo';\n name: string;\n capabilities: string[];\n supportedEncodings?: string[];\n metadata?: Record<string, string>;\n sessionId?: string;\n}\n\ninterface FoxgloveAdvertise {\n op: 'advertise';\n channels: FoxgloveChannel[];\n}\n\ninterface FoxgloveUnadvertise {\n op: 'unadvertise';\n channelIds: number[];\n}\n\ninterface FoxgloveServiceResponse {\n op: 'serviceCallResponse';\n serviceId: number;\n callId: number;\n encoding: string;\n data: string;\n}\n\ninterface FoxgloveService {\n id: number;\n name: string;\n type: string;\n requestSchema?: string;\n responseSchema?: string;\n}\n\ninterface FoxgloveAdvertiseServices {\n op: 'advertiseServices';\n services: FoxgloveService[];\n}\n\ntype FoxgloveServerMessage =\n | FoxgloveServerInfo\n | FoxgloveAdvertise\n | FoxgloveUnadvertise\n | FoxgloveAdvertiseServices\n | FoxgloveServiceResponse\n | { op: string; [key: string]: unknown };\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\n// Subprotocol negotiation: send both, server picks the one it supports.\n// - foxglove.sdk.v1: Foxglove Bridge 3.x+ (ROS 2 Jazzy+), adds CDR services + schemas op\n// - foxglove.websocket.v1: Foxglove Bridge 1.x-2.x (Humble/Iron), standard ws-protocol\n// Wire format (opcodes, binary layout, JSON ops) is identical for subscribe/publish/ping/pong.\nconst SUBPROTOCOLS = ['foxglove.sdk.v1', 'foxglove.websocket.v1'];\nconst PING_INTERVAL_MS = 5_000;\nconst PONG_TIMEOUT_MS = 10_000;\nconst MAX_RECONNECT_ATTEMPTS = 5;\nconst BASE_RECONNECT_DELAY_MS = 1_000;\nconst CONNECTION_TIMEOUT_MS = 10_000;\n\nconst ZERO_TWIST = {\n linear: { x: 0, y: 0, z: 0 },\n angular: { x: 0, y: 0, z: 0 },\n};\n\nconst CMD_VEL_SCHEMA = 'geometry_msgs/msg/Twist';\n\n// Binary op-codes (Foxglove WS v1). Binary frames start with a single byte\n// opcode; 0x01 = messageData is used in both directions.\nenum BinaryOpcode {\n MESSAGE_DATA = 0x01,\n}\n\n// ─── Implementation ──────────────────────────────────────────────────────────\n\nexport class FoxgloveClient implements IProtocolClient {\n private readonly onLatency: ((rttMs: number) => void) | undefined;\n private readonly logger: ProtocolLogger;\n private readonly getThrottleMode: () => ThrottleMode;\n private readonly presets: Record<ThrottleMode, BucketDef[]>;\n\n private ws: WebSocket | null = null;\n private url = '';\n private status: ConnectionStatus = 'disconnected';\n private statusListeners = new Set<(s: ConnectionStatus) => void>();\n private logListeners = new Set<(log: string) => void>();\n private topicsListeners = new Set<(topics: TopicInfo[]) => void>();\n private servicesListeners = new Set<(services: ServiceInfo[]) => void>();\n\n constructor(options?: ProtocolClientOptions) {\n this.onLatency = options?.onLatency;\n this.logger = options?.logger ?? NOOP_LOGGER;\n this.getThrottleMode = options?.getThrottleMode ?? (() => 'auto');\n this.presets = buildEffectivePresets(options?.presetOverrides, this.logger);\n // Wire the EventLoopMonitor's mode getter from our own throttle-mode\n // option so consumers never need to know that setter exists.\n setModeGetter(this.getThrottleMode);\n }\n\n // Channel state\n private channels = new Map<number, FoxgloveChannel>();\n private topicToChannelId = new Map<string, number>();\n\n // Per-subscription state. Each callback keeps its own throttle clock so\n // multi-subscriber topics with different `maxFrequency` settings stay\n // isolated. Bandwidth tracking is per-subscription and feeds the adaptive\n // throttle layered on top of per-callback `maxFrequency`.\n private nextSubscriptionId = 1;\n private subscriptions = new Map<\n number,\n {\n topic: string;\n channelId: number;\n callbacks: Map<\n (msg: RosMessage) => void,\n {\n userMinIntervalMs: number | undefined;\n disableAdaptive: boolean;\n lastDeliveredAt: number;\n }\n >;\n bandwidth: BandwidthTracker;\n breaker: CircuitBreaker;\n isPaused: boolean;\n }\n >();\n private topicToSubscriptionId = new Map<string, number>();\n private breakerListeners = new Map<string, Set<(state: CircuitBreakerState) => void>>();\n\n // CDR message readers — keyed by subscriptionId, created from channel schema.\n private messageReaders = new Map<number, MessageReader>();\n\n // Publish state — maps topic → client-advertised channelId.\n private nextClientChannelId = 1;\n private advertisedTopics = new Map<string, number>();\n private hasPublishedTwist = false;\n\n // Control-priority outbox. Twist / E-Stop publishes route through here\n // and get flushed at the top of every incoming WS message handler.\n private static readonly CONTROL_FLUSH_BATCH = 3;\n private controlOutbox: Array<{ channelId: number; data: Record<string, unknown> }> = [];\n private controlFlushScheduled = false;\n\n // Service calls\n private nextServiceCallId = 1;\n private pendingServiceCalls = new Map<\n number,\n {\n resolve: (v: Record<string, unknown>) => void;\n reject: (e: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n }\n >();\n private availableServices = new Map<string, FoxgloveService>();\n\n // Keep-alive\n private pingTimer: ReturnType<typeof setInterval> | null = null;\n private pongTimer: ReturnType<typeof setTimeout> | null = null;\n private lastPingSentTime = 0;\n\n // Reconnection\n private reconnectAttempts = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private connectionTimeoutTimer: ReturnType<typeof setTimeout> | null = null;\n private intentionalDisconnect = false;\n\n // Connection handshake\n private connectResolve: (() => void) | null = null;\n private connectReject: ((e: Error) => void) | null = null;\n private serverInfoReceived = false;\n\n get isConnected(): boolean {\n return this.status === 'connected';\n }\n\n get reconnectAttempt(): number {\n return this.reconnectAttempts;\n }\n\n get maxReconnectAttempts(): number {\n return MAX_RECONNECT_ATTEMPTS;\n }\n\n async connect(url: string): Promise<void> {\n if (this.status === 'connecting' || this.status === 'connected') {\n return;\n }\n\n this.url = url.trim();\n this.intentionalDisconnect = false;\n this.reconnectAttempts = 0;\n\n this.log(`Opening WebSocket to ${this.url}...`);\n return this.performConnect();\n }\n\n async disconnect(): Promise<void> {\n this.intentionalDisconnect = true;\n\n this.safePublishZeroTwist();\n\n // Drain pending control-priority publishes BEFORE closing the socket.\n // Without this, an Action Client cancel-goal queued via the outbox +\n // setTimeout(0) gets dropped when cleanup() closes the websocket — the\n // macrotask scheduler hadn't fired yet, so the E-Stop's cancel never\n // reaches the robot.\n this.flushControlOutbox();\n\n this.cleanup();\n this.setStatus('disconnected');\n }\n\n async getAvailableTopics(): Promise<TopicInfo[]> {\n const appTopics = new Set(this.advertisedTopics.keys());\n\n return Array.from(this.channels.values()).map((ch) => ({\n topic: ch.topic,\n schemaName: ch.schemaName,\n encoding: ch.encoding,\n source: appTopics.has(ch.topic) ? ('app' as const) : ('robot' as const),\n }));\n }\n\n getSchemaTemplate(schemaName: string): Record<string, unknown> | null {\n // Find a channel advertising this schema, then pick the parser that\n // matches the schema format. Foxglove WS lets a server advertise\n // channels with ros2idl (reference foxglove_bridge), ros2msg (legacy),\n // or JSON Schema (some bridges). Try the declared `schemaEncoding`\n // first, then heuristic-detect; the older foxglove-websocket Python\n // library doesn't set the field.\n for (const ch of this.channels.values()) {\n if (ch.schemaName !== schemaName || !ch.schema) continue;\n const encoding = (ch.schemaEncoding ?? '').toLowerCase();\n const schemaStr = ch.schema;\n const looksLikeJsonSchema = schemaStr.trimStart().startsWith('{');\n\n const tryRos2idl = (): Record<string, unknown> | null => {\n try {\n return schemaToTemplate(parseRos2idl(schemaStr));\n } catch {\n return null;\n }\n };\n const tryRos2msg = (): Record<string, unknown> | null => {\n try {\n return schemaToTemplate(parseRosMsgDef(schemaStr, { ros2: true }));\n } catch {\n return null;\n }\n };\n const tryJsonSchema = (): Record<string, unknown> | null => {\n try {\n const parsed = JSON.parse(schemaStr);\n const t = jsonSchemaToTemplate(parsed);\n return t && typeof t === 'object' && !Array.isArray(t)\n ? (t as Record<string, unknown>)\n : null;\n } catch {\n return null;\n }\n };\n\n let order: Array<() => Record<string, unknown> | null>;\n if (encoding === 'ros2idl') {\n order = [tryRos2idl, tryJsonSchema, tryRos2msg];\n } else if (encoding === 'jsonschema' || looksLikeJsonSchema) {\n order = [tryJsonSchema, tryRos2idl, tryRos2msg];\n } else {\n order = [tryRos2msg, tryRos2idl, tryJsonSchema];\n }\n\n for (const attempt of order) {\n const t = attempt();\n if (t) return t;\n }\n this.log(\n `Schema template parse failed for \"${schemaName}\" — all parsers rejected the schema.`,\n );\n break;\n }\n return null;\n }\n\n subscribe(\n topic: string,\n onMessage: (msg: RosMessage) => void,\n options?: SubscribeOptions,\n ): () => void {\n const userMinIntervalMs =\n options?.maxFrequency && options.maxFrequency > 0\n ? 1000 / options.maxFrequency\n : undefined;\n const disableAdaptive = options?.disableAdaptive ?? false;\n\n const existingSubId = this.topicToSubscriptionId.get(topic);\n if (existingSubId !== undefined) {\n const sub = this.subscriptions.get(existingSubId);\n if (sub) {\n sub.callbacks.set(onMessage, {\n userMinIntervalMs,\n disableAdaptive,\n lastDeliveredAt: 0,\n });\n return () => {\n sub.callbacks.delete(onMessage);\n if (sub.callbacks.size === 0) {\n this.unsubscribeTopic(topic, existingSubId);\n }\n };\n }\n }\n\n const channelId = this.topicToChannelId.get(topic);\n if (channelId === undefined) {\n this.logger.warn(\n `[FoxgloveClient] Topic \"${topic}\" not available. Available: ${Array.from(this.topicToChannelId.keys()).join(', ')}`,\n );\n return () => {};\n }\n\n const subscriptionId = this.nextSubscriptionId++;\n const callbacks = new Map<\n (msg: RosMessage) => void,\n {\n userMinIntervalMs: number | undefined;\n disableAdaptive: boolean;\n lastDeliveredAt: number;\n }\n >();\n callbacks.set(onMessage, {\n userMinIntervalMs,\n disableAdaptive,\n lastDeliveredAt: 0,\n });\n\n const breaker = new CircuitBreaker({\n ...DEFAULT_BREAKER_CONFIG,\n onStateChange: (newState) => {\n const sub = this.subscriptions.get(subscriptionId);\n if (!sub) return;\n sub.isPaused = newState === 'tripped_auto' || newState === 'tripped_manual';\n if (newState === 'tripped_auto') {\n if (this.ws && this.status === 'connected') {\n this.sendJson({ op: 'unsubscribe', subscriptionIds: [subscriptionId] });\n }\n this.log(`[breaker] ${topic} → tripped_auto (sustained overload)`);\n } else if (newState === 'half_open') {\n setTrackerToDeepest(sub.bandwidth, this.getThrottleMode());\n if (this.ws && this.status === 'connected') {\n this.sendJson({\n op: 'subscribe',\n subscriptions: [{ id: subscriptionId, channelId: sub.channelId }],\n });\n }\n this.log(`[breaker] ${topic} → half_open (re-subscribed)`);\n } else if (newState === 'closed') {\n this.log(`[breaker] ${topic} → closed (recovered)`);\n } else if (newState === 'tripped_manual') {\n this.log(`[breaker] ${topic} → tripped_manual (user disabled auto-retry)`);\n }\n const listeners = this.breakerListeners.get(topic);\n if (listeners) {\n for (const cb of listeners) {\n try {\n cb(newState);\n } catch (err) {\n this.logger.error('[FoxgloveClient] Breaker listener error:', err);\n }\n }\n }\n },\n });\n\n this.subscriptions.set(subscriptionId, {\n topic,\n channelId,\n callbacks,\n bandwidth: createBandwidthTracker(this.getThrottleMode(), this.presets),\n breaker,\n isPaused: false,\n });\n this.topicToSubscriptionId.set(topic, subscriptionId);\n\n const channel = this.channels.get(channelId);\n if (channel && channel.schema && channel.encoding !== 'json') {\n const schemaEncoding = channel.schemaEncoding ?? '';\n this.log(\n `Creating CDR reader for \"${topic}\" (encoding=${channel.encoding}, schemaEncoding=${schemaEncoding})`,\n );\n try {\n let msgDefs;\n if (schemaEncoding === 'ros2idl') {\n msgDefs = parseRos2idl(channel.schema);\n } else {\n msgDefs = parseRosMsgDef(channel.schema, { ros2: true });\n }\n this.messageReaders.set(subscriptionId, new MessageReader(msgDefs));\n this.log(` CDR reader created successfully for \"${topic}\"`);\n } catch (err) {\n this.log(` CDR reader FAILED for \"${topic}\": ${String(err)}`);\n this.log(` Schema preview: ${channel.schema.substring(0, 200)}`);\n }\n }\n\n this.sendJson({\n op: 'subscribe',\n subscriptions: [{ id: subscriptionId, channelId }],\n });\n\n return () => {\n callbacks.delete(onMessage);\n if (callbacks.size === 0) {\n this.unsubscribeTopic(topic, subscriptionId);\n }\n };\n }\n\n publish(\n topic: string,\n schemaName: string,\n data: Record<string, unknown>,\n options?: PublishOptions,\n ): void {\n if (!this.ws || this.status !== 'connected') {\n return;\n }\n\n if (schemaName === CMD_VEL_SCHEMA) {\n this.hasPublishedTwist = true;\n }\n\n let clientChannelId = this.advertisedTopics.get(topic);\n if (clientChannelId === undefined) {\n clientChannelId = this.nextClientChannelId++;\n this.advertisedTopics.set(topic, clientChannelId);\n\n this.sendJson({\n op: 'advertise',\n channels: [\n {\n id: clientChannelId,\n topic,\n encoding: 'json',\n schemaName,\n },\n ],\n });\n\n // Delay first message so the bridge has time to create the ROS\n // publisher. Without this, the message arrives before the publisher\n // is ready and gets dropped.\n const chId = clientChannelId;\n setTimeout(() => {\n this.sendBinaryMessage(chId, data);\n }, 150);\n return;\n }\n\n if (options?.priority === 'control') {\n this.controlOutbox.push({ channelId: clientChannelId, data });\n this.scheduleControlFlush();\n return;\n }\n\n this.sendBinaryMessage(clientChannelId, data);\n }\n\n private scheduleControlFlush(): void {\n if (this.controlFlushScheduled) return;\n this.controlFlushScheduled = true;\n setTimeout(() => {\n this.controlFlushScheduled = false;\n this.flushControlOutbox();\n }, 0);\n }\n\n private flushControlOutbox(): void {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n this.controlOutbox.length = 0;\n return;\n }\n let drained = 0;\n while (\n this.controlOutbox.length > 0 &&\n drained < FoxgloveClient.CONTROL_FLUSH_BATCH\n ) {\n const entry = this.controlOutbox.shift();\n if (!entry) break;\n this.sendBinaryMessage(entry.channelId, entry.data);\n drained++;\n }\n if (this.controlOutbox.length > 0) {\n this.scheduleControlFlush();\n }\n }\n\n ensureAdvertised(topic: string, schemaName: string): void {\n if (!this.ws || this.status !== 'connected') return;\n if (this.advertisedTopics.has(topic)) return;\n\n const clientChannelId = this.nextClientChannelId++;\n this.advertisedTopics.set(topic, clientChannelId);\n\n this.sendJson({\n op: 'advertise',\n channels: [\n {\n id: clientChannelId,\n topic,\n encoding: 'json',\n schemaName,\n },\n ],\n });\n }\n\n unadvertise(topic: string): void {\n const clientChannelId = this.advertisedTopics.get(topic);\n if (clientChannelId === undefined) return;\n\n this.advertisedTopics.delete(topic);\n\n if (this.ws && this.status === 'connected') {\n this.sendJson({\n op: 'unadvertise',\n channelIds: [clientChannelId],\n });\n }\n }\n\n private sendBinaryMessage(channelId: number, data: Record<string, unknown>): void {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;\n\n const jsonPayload = JSON.stringify(data);\n const payloadBytes = TEXT_ENCODER.encode(jsonPayload);\n\n const buffer = new ArrayBuffer(1 + 4 + payloadBytes.byteLength);\n const view = new DataView(buffer);\n view.setUint8(0, BinaryOpcode.MESSAGE_DATA);\n view.setUint32(1, channelId, true);\n new Uint8Array(buffer, 5).set(payloadBytes);\n\n this.ws.send(buffer);\n }\n\n async callService(\n service: string,\n request: Record<string, unknown>,\n ): Promise<Record<string, unknown>> {\n if (!this.ws || this.status !== 'connected') {\n throw new Error('Not connected');\n }\n\n const serviceInfo = this.availableServices.get(service);\n if (!serviceInfo) {\n throw new Error(`Service \"${service}\" not available`);\n }\n\n const callId = this.nextServiceCallId++;\n\n return new Promise<Record<string, unknown>>((resolve, reject) => {\n const timer = setTimeout(() => {\n this.pendingServiceCalls.delete(callId);\n reject(new Error(`Service call \"${service}\" timed out after 30s`));\n }, 30_000);\n\n this.pendingServiceCalls.set(callId, { resolve, reject, timer });\n\n const jsonData = JSON.stringify(request);\n const encoded = btoa(jsonData);\n\n this.sendJson({\n op: 'serviceCallRequest',\n serviceId: serviceInfo.id,\n callId,\n encoding: 'json',\n data: encoded,\n });\n });\n }\n\n onStatusChange(cb: (status: ConnectionStatus) => void): () => void {\n this.statusListeners.add(cb);\n cb(this.status);\n return () => {\n this.statusListeners.delete(cb);\n };\n }\n\n onTopicsChange(cb: (topics: TopicInfo[]) => void): () => void {\n this.topicsListeners.add(cb);\n return () => {\n this.topicsListeners.delete(cb);\n };\n }\n\n getAvailableServices(): ServiceInfo[] {\n return Array.from(this.availableServices.values()).map((s) => ({\n name: s.name,\n type: s.type,\n }));\n }\n\n onServicesChange(cb: (services: ServiceInfo[]) => void): () => void {\n this.servicesListeners.add(cb);\n cb(this.getAvailableServices());\n return () => {\n this.servicesListeners.delete(cb);\n };\n }\n\n onLog(cb: (log: string) => void): () => void {\n this.logListeners.add(cb);\n return () => {\n this.logListeners.delete(cb);\n };\n }\n\n publishZeroTwist(): void {\n this.safePublishZeroTwist();\n }\n\n // ── Private: connection lifecycle ────────────────────────────────────────\n\n private performConnect(): Promise<void> {\n this.cleanup();\n this.setStatus('connecting');\n\n return new Promise<void>((resolve, reject) => {\n this.connectResolve = resolve;\n this.connectReject = reject;\n\n try {\n this.ws = new WebSocket(this.url, SUBPROTOCOLS);\n this.ws.binaryType = 'arraybuffer';\n\n this.ws.onopen = () => {\n const negotiated = this.ws?.protocol ?? 'unknown';\n this.log(\n `WebSocket handshake successful (protocol: ${negotiated}), waiting for serverInfo...`,\n );\n this.clearConnectionTimeout();\n };\n\n this.ws.onmessage = (event: MessageEvent) => {\n this.handleWsMessage(event);\n };\n\n this.ws.onerror = (event: Event) => {\n const detail =\n (event as Event & { message?: string }).message ??\n 'Handshake failed or connection rejected by server';\n this.log(`WebSocket error: ${detail}`);\n this.logger.error('[FoxgloveClient] WebSocket error:', event);\n this.handleConnectionError(new Error(`WebSocket error: ${detail}`));\n };\n\n this.ws.onclose = (event: CloseEvent) => {\n this.log(`WebSocket closed: code=${event.code}, reason=${event.reason || 'none'}`);\n this.handleClose(event.code ?? 1000, event.reason ?? '');\n };\n\n this.connectionTimeoutTimer = setTimeout(() => {\n this.handleConnectionError(\n new Error(`Connection timeout after ${CONNECTION_TIMEOUT_MS}ms`),\n );\n }, CONNECTION_TIMEOUT_MS);\n } catch (err) {\n this.handleConnectionError(err instanceof Error ? err : new Error(String(err)));\n }\n });\n }\n\n // ── Private: WebSocket message handling ──────────────────────────────────\n\n private handleWsMessage(event: MessageEvent): void {\n // Drain the control outbox BEFORE we spend the JS thread parsing this\n // incoming message. Under heavy load, control publishes that landed in\n // the outbox while the previous parse held the thread now ride out\n // before this one starts. Cheap when outbox is empty.\n if (this.controlOutbox.length > 0) {\n this.flushControlOutbox();\n }\n\n if (typeof event.data === 'string') {\n this.handleJsonMessage(event.data);\n } else if (event.data instanceof ArrayBuffer) {\n this.handleBinaryMessage(event.data);\n }\n }\n\n private handleJsonMessage(raw: string): void {\n let msg: FoxgloveServerMessage;\n try {\n msg = JSON.parse(raw) as FoxgloveServerMessage;\n } catch {\n this.logger.warn('[FoxgloveClient] Failed to parse JSON message');\n return;\n }\n\n switch (msg.op) {\n case 'serverInfo':\n this.handleServerInfo(msg as FoxgloveServerInfo);\n break;\n case 'advertise':\n this.handleAdvertise(msg as FoxgloveAdvertise);\n break;\n case 'unadvertise':\n this.handleUnadvertise(msg as FoxgloveUnadvertise);\n break;\n case 'advertiseServices':\n this.handleAdvertiseServices(msg as FoxgloveAdvertiseServices);\n break;\n case 'serviceCallResponse':\n this.handleServiceCallResponse(msg as FoxgloveServiceResponse);\n break;\n case 'pong':\n this.handlePong();\n break;\n case 'schemas':\n // sdk.v1 sends schemas metadata; not currently needed.\n break;\n case 'status':\n if ((msg as { level?: number }).level === 2) {\n this.logger.error(\n '[FoxgloveClient] Server error:',\n (msg as { message?: string }).message,\n );\n }\n break;\n }\n }\n\n private handleBinaryMessage(buffer: ArrayBuffer): void {\n if (buffer.byteLength < 5) return;\n\n const view = new DataView(buffer);\n const opcode = view.getUint8(0);\n\n if (opcode !== BinaryOpcode.MESSAGE_DATA) return;\n\n // messageData binary format (server → client):\n // [uint8 op=0x01] [uint32LE subscriptionId] [uint64LE timestamp] [payload]\n const subscriptionId = view.getUint32(1, true);\n\n const timestampLow = view.getUint32(5, true);\n const timestampHigh = view.getUint32(9, true);\n const timestampNs = timestampHigh * 0x100000000 + timestampLow;\n const sec = Math.floor(timestampNs / 1_000_000_000);\n const nsec = timestampNs % 1_000_000_000;\n\n const payloadOffset = 13;\n const payload = buffer.slice(payloadOffset);\n\n const sub = this.subscriptions.get(subscriptionId);\n if (!sub) return;\n if (sub.isPaused) return;\n\n const now = Date.now();\n const mode = this.getThrottleMode();\n recordBytes(sub.bandwidth, now, buffer.byteLength, mode);\n sub.breaker.recordObservation(now, sub.bandwidth.bytesPerSec, getMaxLagMs());\n\n // Single pass over callbacks: collect those whose throttle window allows\n // delivery. Avoids recomputing `effectiveMinInterval` in a second pass.\n const deliverTo: Array<[(msg: RosMessage) => void, { lastDeliveredAt: number }]> = [];\n for (const [cb, entry] of sub.callbacks) {\n const interval = effectiveMinInterval(\n entry.userMinIntervalMs,\n entry.disableAdaptive,\n sub.bandwidth,\n );\n if (interval <= 0 || now - entry.lastDeliveredAt >= interval) {\n deliverTo.push([cb, entry]);\n }\n }\n if (deliverTo.length === 0) return;\n\n const channelInfo = this.channels.get(sub.channelId);\n const schemaName = channelInfo?.schemaName ?? '';\n const encoding = channelInfo?.encoding ?? 'json';\n\n let data: Record<string, unknown> | Uint8Array;\n\n if (encoding === 'json') {\n try {\n const text = TEXT_DECODER.decode(payload);\n data = JSON.parse(text) as Record<string, unknown>;\n } catch {\n data = new Uint8Array(payload);\n }\n } else {\n const reader = this.messageReaders.get(subscriptionId);\n if (reader) {\n try {\n data = reader.readMessage(new Uint8Array(payload)) as Record<string, unknown>;\n } catch {\n data = new Uint8Array(payload);\n }\n } else {\n data = new Uint8Array(payload);\n }\n }\n\n const rosMsg: RosMessage = {\n topic: sub.topic,\n schemaName,\n encoding: encoding === 'json' ? 'json' : 'cdr',\n data,\n receiveTime: { sec, nsec },\n byteSize: payload.byteLength,\n };\n\n for (const [cb, entry] of deliverTo) {\n entry.lastDeliveredAt = now;\n try {\n cb(rosMsg);\n } catch (err) {\n this.logger.error('[FoxgloveClient] Subscriber callback error:', err);\n }\n }\n }\n\n private handleServerInfo(info: FoxgloveServerInfo): void {\n this.log(`Received serverInfo: ${info.name} (sessionId: ${info.sessionId ?? 'none'})`);\n this.serverInfoReceived = true;\n }\n\n private handleAdvertise(msg: FoxgloveAdvertise): void {\n for (const ch of msg.channels) {\n this.channels.set(ch.id, ch);\n this.topicToChannelId.set(ch.topic, ch.id);\n this.log(\n ` Channel: ${ch.topic} [${ch.schemaName}] encoding=${ch.encoding} schemaEncoding=${ch.schemaEncoding ?? 'none'}`,\n );\n }\n\n if (this.connectResolve && this.serverInfoReceived) {\n this.log(`Connection established with ${msg.channels.length} initial topics.`);\n this.clearConnectionTimeout();\n this.reconnectAttempts = 0;\n this.setStatus('connected');\n this.startPingLoop();\n\n this.connectResolve();\n this.connectResolve = null;\n this.connectReject = null;\n } else {\n this.notifyTopicsChanged();\n }\n }\n\n private handleUnadvertise(msg: FoxgloveUnadvertise): void {\n for (const id of msg.channelIds) {\n const ch = this.channels.get(id);\n if (ch) {\n this.topicToChannelId.delete(ch.topic);\n }\n this.channels.delete(id);\n }\n this.notifyTopicsChanged();\n }\n\n private handleAdvertiseServices(msg: FoxgloveAdvertiseServices): void {\n for (const svc of msg.services) {\n this.availableServices.set(svc.name, svc);\n }\n this.notifyServicesChanged();\n }\n\n private notifyServicesChanged(): void {\n const snapshot = this.getAvailableServices();\n for (const cb of this.servicesListeners) {\n try {\n cb(snapshot);\n } catch (err) {\n this.logger.error('[FoxgloveClient] Services listener error:', err);\n }\n }\n }\n\n private handleServiceCallResponse(msg: FoxgloveServiceResponse): void {\n const pending = this.pendingServiceCalls.get(msg.callId);\n if (!pending) return;\n\n clearTimeout(pending.timer);\n this.pendingServiceCalls.delete(msg.callId);\n\n try {\n if (msg.encoding === 'json' && msg.data) {\n const decoded = atob(msg.data);\n const parsed = JSON.parse(decoded) as Record<string, unknown>;\n pending.resolve(parsed);\n } else {\n pending.resolve({ success: true });\n }\n } catch (err) {\n pending.reject(\n new Error(\n `Failed to parse service response: ${err instanceof Error ? err.message : String(err)}`,\n ),\n );\n }\n }\n\n // ── Private: keep-alive ──────────────────────────────────────────────────\n\n private startPingLoop(): void {\n this.stopPingLoop();\n\n this.pingTimer = setInterval(() => {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n if (this.pongTimer) {\n clearTimeout(this.pongTimer);\n this.pongTimer = null;\n }\n\n this.lastPingSentTime = Date.now();\n this.sendJson({ op: 'ping' });\n\n this.pongTimer = setTimeout(() => {\n this.logger.warn('[FoxgloveClient] Pong timeout — reconnecting');\n this.handleClose(4000, 'Pong timeout');\n }, PONG_TIMEOUT_MS);\n }\n }, PING_INTERVAL_MS);\n }\n\n private stopPingLoop(): void {\n if (this.pingTimer) {\n clearInterval(this.pingTimer);\n this.pingTimer = null;\n }\n if (this.pongTimer) {\n clearTimeout(this.pongTimer);\n this.pongTimer = null;\n }\n }\n\n private handlePong(): void {\n if (this.pongTimer) {\n clearTimeout(this.pongTimer);\n this.pongTimer = null;\n }\n if (this.onLatency && this.lastPingSentTime > 0) {\n try {\n this.onLatency(Date.now() - this.lastPingSentTime);\n } catch {\n // metrics must never affect protocol operation\n }\n }\n }\n\n // ── Private: reconnection ────────────────────────────────────────────────\n\n private handleConnectionError(error: Error): void {\n this.clearConnectionTimeout();\n\n if (this.connectReject) {\n this.connectReject(error);\n this.connectResolve = null;\n this.connectReject = null;\n }\n\n this.setStatus('error');\n this.cleanup();\n this.scheduleReconnect();\n }\n\n private handleClose(_code: number, _reason: string): void {\n const wasConnected = this.status === 'connected';\n\n if (wasConnected && this.hasPublishedTwist && !this.intentionalDisconnect) {\n this.safePublishZeroTwist();\n }\n\n this.cleanup();\n this.setStatus('disconnected');\n\n if (wasConnected && !this.intentionalDisconnect) {\n this.scheduleReconnect();\n }\n }\n\n private scheduleReconnect(): void {\n if (\n this.intentionalDisconnect ||\n this.reconnectTimer !== null ||\n this.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS\n ) {\n if (this.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {\n this.logger.warn(\n `[FoxgloveClient] Max reconnect attempts (${MAX_RECONNECT_ATTEMPTS}) reached`,\n );\n this.setStatus('error');\n }\n return;\n }\n\n const delay = Math.min(\n BASE_RECONNECT_DELAY_MS * Math.pow(2, this.reconnectAttempts),\n 16_000,\n );\n this.log(\n `Scheduling reconnect attempt ${this.reconnectAttempts + 1}/${MAX_RECONNECT_ATTEMPTS} in ${delay}ms...`,\n );\n this.reconnectAttempts++;\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.performConnect().catch((err) => {\n this.logger.error('[FoxgloveClient] Reconnect failed:', err);\n });\n }, delay);\n }\n\n // ── Private: unsubscribe ─────────────────────────────────────────────────\n\n private unsubscribeTopic(topic: string, subscriptionId: number): void {\n const sub = this.subscriptions.get(subscriptionId);\n sub?.breaker.destroy();\n // `breakerListeners` are owned by the caller of `onBreakerStateChange`,\n // not by the subscription. Their cleanup happens through the unsubscribe\n // function that `onBreakerStateChange` returns. Tearing them down here\n // would nuke listeners belonging to other consumers watching the same\n // topic.\n\n this.subscriptions.delete(subscriptionId);\n this.topicToSubscriptionId.delete(topic);\n this.messageReaders.delete(subscriptionId);\n\n if (this.ws && this.status === 'connected' && !sub?.isPaused) {\n this.sendJson({\n op: 'unsubscribe',\n subscriptionIds: [subscriptionId],\n });\n }\n }\n\n // ── IProtocolClient: circuit breaker controls ─────────────────────────────\n\n getBreakerState(topic: string): CircuitBreakerState {\n const subId = this.topicToSubscriptionId.get(topic);\n if (subId === undefined) return 'closed';\n const sub = this.subscriptions.get(subId);\n return sub?.breaker.getState() ?? 'closed';\n }\n\n getBreakerNextRetryAt(topic: string): number | null {\n const subId = this.topicToSubscriptionId.get(topic);\n if (subId === undefined) return null;\n return this.subscriptions.get(subId)?.breaker.getNextRetryAt() ?? null;\n }\n\n getSubscriptionStats(topic: string) {\n const subId = this.topicToSubscriptionId.get(topic);\n if (subId === undefined) return null;\n const sub = this.subscriptions.get(subId);\n if (!sub) return null;\n const mode = this.getThrottleMode();\n return {\n adaptiveMinIntervalMs: sub.bandwidth.adaptiveMinIntervalMs,\n bucketLabel: getTrackerBucketLabel(sub.bandwidth, mode),\n bytesPerSec: sub.bandwidth.bytesPerSec,\n };\n }\n\n breakerRetry(topic: string): void {\n const subId = this.topicToSubscriptionId.get(topic);\n if (subId === undefined) return;\n this.subscriptions.get(subId)?.breaker.retry();\n }\n\n breakerDisable(topic: string): void {\n const subId = this.topicToSubscriptionId.get(topic);\n if (subId === undefined) return;\n this.subscriptions.get(subId)?.breaker.disable();\n }\n\n onBreakerStateChange(\n topic: string,\n cb: (state: CircuitBreakerState) => void,\n ): () => void {\n let listeners = this.breakerListeners.get(topic);\n if (!listeners) {\n listeners = new Set();\n this.breakerListeners.set(topic, listeners);\n }\n listeners.add(cb);\n return () => {\n const set = this.breakerListeners.get(topic);\n if (set) {\n set.delete(cb);\n if (set.size === 0) this.breakerListeners.delete(topic);\n }\n };\n }\n\n // ── Private: dead-man's switch ───────────────────────────────────────────\n\n private safePublishZeroTwist(): void {\n if (!this.hasPublishedTwist) return;\n\n try {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.publish('/cmd_vel', CMD_VEL_SCHEMA, ZERO_TWIST, { priority: 'control' });\n }\n } catch {\n // best effort\n }\n\n this.hasPublishedTwist = false;\n }\n\n // ── Private: cleanup ─────────────────────────────────────────────────────\n\n private cleanup(): void {\n this.clearConnectionTimeout();\n this.stopPingLoop();\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n for (const [, pending] of this.pendingServiceCalls) {\n clearTimeout(pending.timer);\n pending.reject(new Error('Connection closed'));\n }\n this.pendingServiceCalls.clear();\n\n if (this.ws) {\n if (this.ws.readyState === WebSocket.OPEN && this.advertisedTopics.size > 0) {\n const channelIds = Array.from(this.advertisedTopics.values());\n try {\n this.sendJson({ op: 'unadvertise', channelIds });\n } catch {\n // best effort\n }\n }\n\n this.ws.onopen = null;\n this.ws.onmessage = null;\n this.ws.onerror = null;\n this.ws.onclose = null;\n\n if (\n this.ws.readyState === WebSocket.OPEN ||\n this.ws.readyState === WebSocket.CONNECTING\n ) {\n this.ws.close();\n }\n this.ws = null;\n }\n\n this.channels.clear();\n this.topicToChannelId.clear();\n this.subscriptions.clear();\n this.topicToSubscriptionId.clear();\n this.messageReaders.clear();\n this.advertisedTopics.clear();\n this.availableServices.clear();\n this.notifyServicesChanged();\n this.serverInfoReceived = false;\n this.nextSubscriptionId = 1;\n this.nextClientChannelId = 1;\n this.nextServiceCallId = 1;\n }\n\n private clearConnectionTimeout(): void {\n if (this.connectionTimeoutTimer) {\n clearTimeout(this.connectionTimeoutTimer);\n this.connectionTimeoutTimer = null;\n }\n }\n\n // ── Private: helpers ─────────────────────────────────────────────────────\n\n private setStatus(status: ConnectionStatus): void {\n if (this.status === status) return;\n this.status = status;\n for (const cb of this.statusListeners) {\n try {\n cb(status);\n } catch (err) {\n this.logger.error('[FoxgloveClient] Status listener error:', err);\n }\n }\n }\n\n private sendJson(msg: Record<string, unknown>): void {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify(msg));\n }\n }\n\n private notifyTopicsChanged(): void {\n const appTopics = new Set(this.advertisedTopics.keys());\n const topics: TopicInfo[] = Array.from(this.channels.values()).map((ch) => ({\n topic: ch.topic,\n schemaName: ch.schemaName,\n encoding: ch.encoding,\n source: appTopics.has(ch.topic) ? ('app' as const) : ('robot' as const),\n }));\n for (const cb of this.topicsListeners) {\n try {\n cb(topics);\n } catch (err) {\n this.logger.error('[FoxgloveClient] Topics listener error:', err);\n }\n }\n }\n\n private log(message: string): void {\n const timestamp = new Date().toISOString().substring(11, 23);\n const formatted = `[${timestamp}] ${message}`;\n this.logger.log(`[FoxgloveClient] ${formatted}`);\n for (const cb of this.logListeners) {\n try {\n cb(formatted);\n } catch (err) {\n this.logger.error('[FoxgloveClient] Log listener error:', err);\n }\n }\n }\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * RosbridgeClient — rosbridge v2 protocol implementation.\n *\n * Implements the rosbridge v2 JSON protocol directly over the runtime's\n * `WebSocket`. No `roslib` dependency: that library pulls in Node-only\n * modules (`bson`, `ws`) that break in React Native and that we don't need\n * because the protocol is a small JSON envelope.\n *\n * Protocol spec: https://github.com/RobotWebTools/rosbridge_suite/blob/ros2/ROSBRIDGE_PROTOCOL.md\n * Default port: 9090.\n *\n * Features:\n *\n * - Topic discovery via the `/rosapi/topics` service.\n * - Subscribe with `throttle_rate` and `queue_length=1` (drop old, keep\n * latest) for sane defaults on high-rate topics.\n * - Publish with auto-advertise on first send.\n * - Service calls with a 30 s timeout.\n * - Dead-man's switch: zero Twist on unexpected disconnect.\n * - Exponential backoff reconnection (1 s → 2 s → 4 s → 8 s → 16 s, max 5\n * attempts).\n * - `tryDropPublishBeforeParse` fast-path: bounded substring scan extracts\n * `op` and `topic` from a `publish` envelope so we can drop messages no\n * callback wants without paying `JSON.parse` cost on the full payload.\n * Matters for high-bandwidth topics where parse dominates per-message\n * work.\n */\n\nimport {\n type BucketDef,\n type CircuitBreakerState,\n type ConnectionStatus,\n type IProtocolClient,\n type ProtocolClientOptions,\n type ProtocolLogger,\n type PublishOptions,\n type RosMessage,\n type ServiceInfo,\n type SubscribeOptions,\n type ThrottleMode,\n type TopicInfo,\n} from './types';\nimport { CircuitBreaker, DEFAULT_BREAKER_CONFIG } from './CircuitBreaker';\nimport { getMaxLagMs, setModeGetter } from './EventLoopMonitor';\nimport {\n type BandwidthTracker,\n buildEffectivePresets,\n createBandwidthTracker,\n effectiveMinInterval,\n getTrackerBucketLabel,\n recordBytes,\n setTrackerToDeepest,\n} from './SubscriptionBandwidth';\n\nconst NOOP_LOGGER: ProtocolLogger = { log() {}, warn() {}, error() {} };\n\n// Module-level decoder singleton — see the FoxgloveClient comment for the\n// rationale; same reasoning for the rosbridge binary-frame path.\nconst TEXT_DECODER = new TextDecoder();\n\nconst MAX_RECONNECT_ATTEMPTS = 5;\nconst BASE_RECONNECT_DELAY_MS = 1_000;\nconst CONNECTION_TIMEOUT_MS = 10_000;\nconst DEFAULT_THROTTLE_RATE_MS = 100;\nconst SERVICE_CALL_TIMEOUT_MS = 30_000;\n\nconst ZERO_TWIST = {\n linear: { x: 0, y: 0, z: 0 },\n angular: { x: 0, y: 0, z: 0 },\n};\n\nconst CMD_VEL_SCHEMA = 'geometry_msgs/msg/Twist';\n\nexport class RosbridgeClient implements IProtocolClient {\n private readonly onLatency: ((rttMs: number) => void) | undefined;\n private readonly logger: ProtocolLogger;\n private readonly getThrottleMode: () => ThrottleMode;\n private readonly presets: Record<ThrottleMode, BucketDef[]>;\n\n private ws: WebSocket | null = null;\n private url = '';\n private status: ConnectionStatus = 'disconnected';\n private statusListeners = new Set<(s: ConnectionStatus) => void>();\n private logListeners = new Set<(log: string) => void>();\n private topicsListeners = new Set<(topics: TopicInfo[]) => void>();\n private servicesListeners = new Set<(services: ServiceInfo[]) => void>();\n private availableServices: ServiceInfo[] = [];\n private servicesPollTimer: ReturnType<typeof setInterval> | null = null;\n\n constructor(options?: ProtocolClientOptions) {\n this.onLatency = options?.onLatency;\n this.logger = options?.logger ?? NOOP_LOGGER;\n this.getThrottleMode = options?.getThrottleMode ?? (() => 'auto');\n this.presets = buildEffectivePresets(options?.presetOverrides, this.logger);\n // Wire the EventLoopMonitor's mode getter from our own throttle-mode\n // option so consumers never need to know that setter exists.\n setModeGetter(this.getThrottleMode);\n }\n\n private activeSubscriptions = new Map<\n string,\n {\n schemaName: string;\n callbacks: Map<\n (msg: RosMessage) => void,\n {\n userMinIntervalMs: number | undefined;\n disableAdaptive: boolean;\n lastDeliveredAt: number;\n }\n >;\n bandwidth: BandwidthTracker;\n breaker: CircuitBreaker;\n isPaused: boolean;\n }\n >();\n private breakerListeners = new Map<string, Set<(state: CircuitBreakerState) => void>>();\n\n private advertisedTopics = new Set<string>();\n private hasPublishedTwist = false;\n\n private static readonly CONTROL_FLUSH_BATCH = 3;\n private controlOutbox: Array<Record<string, unknown>> = [];\n private controlFlushScheduled = false;\n\n private discoveredTopics: TopicInfo[] = [];\n\n private pendingServiceCalls = new Map<\n string,\n {\n resolve: (result: Record<string, unknown>) => void;\n reject: (error: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n }\n >();\n private serviceCallCounter = 0;\n\n private latencyProbeTimer: ReturnType<typeof setInterval> | null = null;\n\n private reconnectAttempts = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private connectionTimeoutTimer: ReturnType<typeof setTimeout> | null = null;\n private intentionalDisconnect = false;\n\n get isConnected(): boolean {\n return this.status === 'connected';\n }\n\n get reconnectAttempt(): number {\n return this.reconnectAttempts;\n }\n\n get maxReconnectAttempts(): number {\n return MAX_RECONNECT_ATTEMPTS;\n }\n\n async connect(url: string): Promise<void> {\n if (this.status === 'connecting' || this.status === 'connected') {\n return;\n }\n\n this.url = url.trim();\n this.intentionalDisconnect = false;\n this.reconnectAttempts = 0;\n\n this.log(`Connecting to rosbridge at ${this.url}...`);\n return this.performConnect();\n }\n\n async disconnect(): Promise<void> {\n this.intentionalDisconnect = true;\n\n this.safePublishZeroTwist();\n this.flushControlOutbox();\n\n this.cleanup();\n this.setStatus('disconnected');\n }\n\n async getAvailableTopics(): Promise<TopicInfo[]> {\n if (!this.ws || !this.isConnected) {\n return this.discoveredTopics;\n }\n\n try {\n const result = await this.callService('/rosapi/topics', {});\n const names: string[] = (result.topics as string[]) ?? [];\n const types: string[] = (result.types as string[]) ?? [];\n\n const topics: TopicInfo[] = [];\n for (let i = 0; i < names.length; i++) {\n const name = names[i];\n if (!name) continue;\n topics.push({\n topic: name,\n schemaName: types[i] ?? '',\n encoding: 'json',\n source: this.advertisedTopics.has(name) ? 'app' : 'robot',\n });\n }\n\n this.discoveredTopics = topics;\n this.log(`Discovered ${topics.length} topics.`);\n this.notifyTopicsChanged();\n return topics;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n this.log(`Failed to get topics via rosapi: ${msg}`);\n return this.discoveredTopics;\n }\n }\n\n getSchemaTemplate(_schemaName: string): Record<string, unknown> | null {\n // rosbridge's /rosapi/message_details is async and not surfaced through\n // the current IProtocolClient contract. Consumers that need a template\n // for a rosbridge connection should compose one client-side. Foxglove WS\n // does the heavy lifting via inline schemas.\n return null;\n }\n\n subscribe(\n topic: string,\n onMessage: (msg: RosMessage) => void,\n options?: SubscribeOptions,\n ): () => void {\n if (!this.ws || this.status !== 'connected') {\n return () => {};\n }\n\n const userMinIntervalMs =\n options?.maxFrequency && options.maxFrequency > 0\n ? 1000 / options.maxFrequency\n : undefined;\n const disableAdaptive = options?.disableAdaptive ?? false;\n\n const existing = this.activeSubscriptions.get(topic);\n if (existing) {\n existing.callbacks.set(onMessage, {\n userMinIntervalMs,\n disableAdaptive,\n lastDeliveredAt: 0,\n });\n return () => {\n existing.callbacks.delete(onMessage);\n if (existing.callbacks.size === 0) {\n this.unsubscribeTopic(topic);\n }\n };\n }\n\n const topicInfo = this.discoveredTopics.find((t) => t.topic === topic);\n const messageType = topicInfo?.schemaName ?? '';\n\n if (!messageType) {\n this.log(`Warning: subscribing to \"${topic}\" without known message type`);\n }\n\n const callbacks = new Map<\n (msg: RosMessage) => void,\n {\n userMinIntervalMs: number | undefined;\n disableAdaptive: boolean;\n lastDeliveredAt: number;\n }\n >();\n callbacks.set(onMessage, {\n userMinIntervalMs,\n disableAdaptive,\n lastDeliveredAt: 0,\n });\n\n const breaker = new CircuitBreaker({\n ...DEFAULT_BREAKER_CONFIG,\n onStateChange: (newState) => {\n const sub = this.activeSubscriptions.get(topic);\n if (!sub) return;\n sub.isPaused = newState === 'tripped_auto' || newState === 'tripped_manual';\n if (newState === 'tripped_auto') {\n if (this.ws && this.status === 'connected') {\n this.send({ op: 'unsubscribe', topic });\n }\n this.log(`[breaker] ${topic} → tripped_auto (sustained overload)`);\n } else if (newState === 'half_open') {\n setTrackerToDeepest(sub.bandwidth, this.getThrottleMode());\n if (this.ws && this.status === 'connected') {\n this.send({\n op: 'subscribe',\n topic,\n type: sub.schemaName,\n throttle_rate: DEFAULT_THROTTLE_RATE_MS,\n queue_length: 1,\n });\n }\n this.log(`[breaker] ${topic} → half_open (re-subscribed)`);\n } else if (newState === 'closed') {\n this.log(`[breaker] ${topic} → closed (recovered)`);\n } else if (newState === 'tripped_manual') {\n this.log(`[breaker] ${topic} → tripped_manual (user disabled auto-retry)`);\n }\n const listeners = this.breakerListeners.get(topic);\n if (listeners) {\n for (const cb of listeners) {\n try {\n cb(newState);\n } catch (err) {\n this.logger.error('[RosbridgeClient] Breaker listener error:', err);\n }\n }\n }\n },\n });\n\n this.activeSubscriptions.set(topic, {\n schemaName: messageType,\n callbacks,\n bandwidth: createBandwidthTracker(this.getThrottleMode(), this.presets),\n breaker,\n isPaused: false,\n });\n\n this.send({\n op: 'subscribe',\n topic,\n type: messageType,\n throttle_rate: DEFAULT_THROTTLE_RATE_MS,\n queue_length: 1,\n });\n\n return () => {\n callbacks.delete(onMessage);\n if (callbacks.size === 0) {\n this.unsubscribeTopic(topic);\n }\n };\n }\n\n publish(\n topic: string,\n schemaName: string,\n data: Record<string, unknown>,\n options?: PublishOptions,\n ): void {\n if (!this.ws || this.status !== 'connected') {\n return;\n }\n\n if (schemaName === CMD_VEL_SCHEMA) {\n this.hasPublishedTwist = true;\n }\n\n if (!this.advertisedTopics.has(topic)) {\n this.send({\n op: 'advertise',\n topic,\n type: schemaName,\n });\n this.advertisedTopics.add(topic);\n }\n\n const payload = { op: 'publish', topic, msg: data };\n\n if (options?.priority === 'control') {\n this.controlOutbox.push(payload);\n this.scheduleControlFlush();\n return;\n }\n\n this.send(payload);\n }\n\n private scheduleControlFlush(): void {\n if (this.controlFlushScheduled) return;\n this.controlFlushScheduled = true;\n setTimeout(() => {\n this.controlFlushScheduled = false;\n this.flushControlOutbox();\n }, 0);\n }\n\n private flushControlOutbox(): void {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n this.controlOutbox.length = 0;\n return;\n }\n let drained = 0;\n while (\n this.controlOutbox.length > 0 &&\n drained < RosbridgeClient.CONTROL_FLUSH_BATCH\n ) {\n const entry = this.controlOutbox.shift();\n if (!entry) break;\n this.send(entry);\n drained++;\n }\n if (this.controlOutbox.length > 0) {\n this.scheduleControlFlush();\n }\n }\n\n ensureAdvertised(topic: string, schemaName: string): void {\n if (!this.ws || this.status !== 'connected') return;\n if (this.advertisedTopics.has(topic)) return;\n\n this.send({\n op: 'advertise',\n topic,\n type: schemaName,\n });\n this.advertisedTopics.add(topic);\n }\n\n unadvertise(topic: string): void {\n if (!this.advertisedTopics.has(topic)) return;\n\n this.advertisedTopics.delete(topic);\n\n if (this.ws && this.status === 'connected') {\n this.send({\n op: 'unadvertise',\n topic,\n });\n }\n }\n\n async callService(\n service: string,\n request: Record<string, unknown>,\n ): Promise<Record<string, unknown>> {\n if (!this.ws || this.status !== 'connected') {\n throw new Error('Not connected');\n }\n\n const id = `service_call:${service}:${++this.serviceCallCounter}`;\n\n return new Promise<Record<string, unknown>>((resolve, reject) => {\n const timer = setTimeout(() => {\n this.pendingServiceCalls.delete(id);\n reject(\n new Error(`Service call \"${service}\" timed out after ${SERVICE_CALL_TIMEOUT_MS}ms`),\n );\n }, SERVICE_CALL_TIMEOUT_MS);\n\n this.pendingServiceCalls.set(id, { resolve, reject, timer });\n\n this.send({\n op: 'call_service',\n id,\n service,\n args: request,\n });\n });\n }\n\n onStatusChange(cb: (status: ConnectionStatus) => void): () => void {\n this.statusListeners.add(cb);\n cb(this.status);\n return () => {\n this.statusListeners.delete(cb);\n };\n }\n\n onTopicsChange(cb: (topics: TopicInfo[]) => void): () => void {\n this.topicsListeners.add(cb);\n return () => {\n this.topicsListeners.delete(cb);\n };\n }\n\n getAvailableServices(): ServiceInfo[] {\n return [...this.availableServices];\n }\n\n onServicesChange(cb: (services: ServiceInfo[]) => void): () => void {\n this.servicesListeners.add(cb);\n cb(this.getAvailableServices());\n return () => {\n this.servicesListeners.delete(cb);\n };\n }\n\n private async discoverServices(): Promise<void> {\n if (!this.isConnected) return;\n try {\n const result = await this.callService('/rosapi/services', {});\n const names: string[] = (result.services as string[]) ?? [];\n const next: ServiceInfo[] = names.map((n) => ({ name: n, type: '' }));\n const prevKey = this.availableServices\n .map((s) => s.name)\n .sort()\n .join('|');\n const nextKey = next.map((s) => s.name).sort().join('|');\n if (prevKey === nextKey) return;\n this.availableServices = next;\n this.notifyServicesChanged();\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n this.log(`Service discovery via /rosapi/services failed: ${msg}`);\n this.stopServicesPoll();\n }\n }\n\n private startServicesPoll(): void {\n if (this.servicesPollTimer) return;\n void this.discoverServices();\n this.servicesPollTimer = setInterval(() => {\n void this.discoverServices();\n }, 30_000);\n }\n\n private stopServicesPoll(): void {\n if (this.servicesPollTimer) {\n clearInterval(this.servicesPollTimer);\n this.servicesPollTimer = null;\n }\n }\n\n private notifyServicesChanged(): void {\n const snapshot = this.getAvailableServices();\n for (const cb of this.servicesListeners) {\n try {\n cb(snapshot);\n } catch (err) {\n this.logger.error('[RosbridgeClient] Services listener error:', err);\n }\n }\n }\n\n onLog(cb: (log: string) => void): () => void {\n this.logListeners.add(cb);\n return () => {\n this.logListeners.delete(cb);\n };\n }\n\n publishZeroTwist(): void {\n this.safePublishZeroTwist();\n }\n\n // ── Private: connection lifecycle ──────────────────────────────────────\n\n private performConnect(): Promise<void> {\n this.cleanupConnection();\n this.setStatus('connecting');\n\n return new Promise<void>((resolve, reject) => {\n try {\n this.ws = new WebSocket(this.url);\n\n this.connectionTimeoutTimer = setTimeout(() => {\n this.log(`Connection timeout after ${CONNECTION_TIMEOUT_MS}ms`);\n reject(new Error(`Connection timeout after ${CONNECTION_TIMEOUT_MS}ms`));\n this.cleanup();\n this.setStatus('error');\n this.scheduleReconnect();\n }, CONNECTION_TIMEOUT_MS);\n\n this.ws.onopen = () => {\n this.clearConnectionTimeout();\n this.reconnectAttempts = 0;\n this.log('Connected to rosbridge server.');\n this.setStatus('connected');\n this.startLatencyProbe();\n this.startServicesPoll();\n resolve();\n };\n\n this.ws.onerror = (event: Event) => {\n const detail =\n (event as Event & { message?: string }).message ?? 'Connection error';\n this.log(`Rosbridge error: ${detail}`);\n this.logger.error('[RosbridgeClient] Error:', event);\n\n if (this.status === 'connecting') {\n this.clearConnectionTimeout();\n reject(new Error(`Rosbridge error: ${detail}`));\n this.cleanup();\n this.setStatus('error');\n this.scheduleReconnect();\n }\n };\n\n this.ws.onclose = () => {\n const wasConnected = this.status === 'connected';\n this.log('Rosbridge connection closed.');\n\n if (wasConnected && this.hasPublishedTwist && !this.intentionalDisconnect) {\n this.safePublishZeroTwist();\n }\n\n this.cleanupConnection();\n this.setStatus('disconnected');\n\n if (wasConnected && !this.intentionalDisconnect) {\n this.scheduleReconnect();\n }\n };\n\n this.ws.onmessage = (event: MessageEvent) => {\n this.handleMessage(event.data as string | ArrayBuffer);\n };\n } catch (err) {\n this.clearConnectionTimeout();\n const error = err instanceof Error ? err : new Error(String(err));\n reject(error);\n this.cleanup();\n this.setStatus('error');\n }\n });\n }\n\n // ── Private: message handling ──────────────────────────────────────────\n\n private handleMessage(raw: string | ArrayBuffer): void {\n if (this.controlOutbox.length > 0) {\n this.flushControlOutbox();\n }\n\n try {\n const data = typeof raw === 'string' ? raw : TEXT_DECODER.decode(raw);\n const byteSize = typeof raw === 'string' ? data.length : raw.byteLength;\n // Compute mode once per incoming message and forward to the inner\n // handlers so we don't call the host's `getThrottleMode` twice on the\n // fast-path → dispatch flow.\n const mode = this.getThrottleMode();\n\n if (this.tryDropPublishBeforeParse(data, byteSize, mode)) {\n return;\n }\n\n const msg = JSON.parse(data) as Record<string, unknown>;\n const op = msg.op as string;\n\n switch (op) {\n case 'publish':\n this.handlePublish(msg, byteSize, mode);\n break;\n case 'service_response':\n this.handleServiceResponse(msg);\n break;\n case 'status': {\n const level = msg.level as string | undefined;\n const statusMsg = msg.msg as string | undefined;\n if (level === 'error' || level === 'warning') {\n this.log(`rosbridge ${level}: ${statusMsg ?? 'unknown'}`);\n }\n break;\n }\n }\n } catch (err) {\n this.logger.error('[RosbridgeClient] Failed to parse message:', err);\n }\n }\n\n /**\n * Drop a publish message before paying full `JSON.parse` cost.\n *\n * Rosbridge frames look like `{\"op\":\"publish\",\"topic\":\"…\",\"msg\":{…}}`.\n * For fat payloads (base64-encoded camera frames, large arrays)\n * `JSON.parse` on the whole envelope dominates per-message cost. We do a\n * cheap substring search to extract `op` and `topic`, run the same\n * throttle/breaker accounting `handlePublish` would do, and return `true`\n * to skip the parse when no callback wants the message right now.\n *\n * Handles both compact (`{\"op\":\"publish\"`) and pretty (`{\"op\": \"publish\"`)\n * JSON forms.\n */\n private tryDropPublishBeforeParse(data: string, byteSize: number, mode: ThrottleMode): boolean {\n if (\n !data.startsWith('{\"op\":\"publish\"') &&\n !data.startsWith('{\"op\": \"publish\"')\n ) {\n return false;\n }\n\n const topicKeyIdx = data.indexOf('\"topic\"');\n if (topicKeyIdx < 0 || topicKeyIdx > 200) return false;\n\n let i = topicKeyIdx + 7;\n if (data[i] !== ':') return false;\n i++;\n if (data[i] === ' ') i++;\n if (data[i] !== '\"') return false;\n i++;\n const topicEnd = data.indexOf('\"', i);\n if (topicEnd < 0) return false;\n const topic = data.slice(i, topicEnd);\n\n const sub = this.activeSubscriptions.get(topic);\n if (!sub) return true; // not subscribed → drop\n\n const now = Date.now();\n\n if (sub.isPaused) {\n recordBytes(sub.bandwidth, now, byteSize, mode);\n return true;\n }\n\n let anyCallbackWantsThis = false;\n for (const entry of sub.callbacks.values()) {\n const interval = effectiveMinInterval(\n entry.userMinIntervalMs,\n entry.disableAdaptive,\n sub.bandwidth,\n );\n if (interval <= 0 || now - entry.lastDeliveredAt >= interval) {\n anyCallbackWantsThis = true;\n break;\n }\n }\n\n if (anyCallbackWantsThis) return false;\n\n recordBytes(sub.bandwidth, now, byteSize, mode);\n sub.breaker.recordObservation(now, sub.bandwidth.bytesPerSec, getMaxLagMs());\n\n return true;\n }\n\n private handlePublish(msg: Record<string, unknown>, byteSize: number, mode: ThrottleMode): void {\n const topic = msg.topic as string;\n const msgData = (msg.msg ?? {}) as Record<string, unknown>;\n\n const sub = this.activeSubscriptions.get(topic);\n if (!sub) return;\n if (sub.isPaused) return;\n\n const now = Date.now();\n recordBytes(sub.bandwidth, now, byteSize, mode);\n sub.breaker.recordObservation(now, sub.bandwidth.bytesPerSec, getMaxLagMs());\n\n // Single pass over callbacks: collect those whose throttle window allows\n // delivery. Avoids recomputing `effectiveMinInterval` in a second loop.\n const deliverTo: Array<[(msg: RosMessage) => void, { lastDeliveredAt: number }]> = [];\n for (const [cb, entry] of sub.callbacks) {\n const interval = effectiveMinInterval(\n entry.userMinIntervalMs,\n entry.disableAdaptive,\n sub.bandwidth,\n );\n if (interval <= 0 || now - entry.lastDeliveredAt >= interval) {\n deliverTo.push([cb, entry]);\n }\n }\n if (deliverTo.length === 0) return;\n\n const rosMsg: RosMessage = {\n topic,\n schemaName: sub.schemaName,\n encoding: 'json',\n data: msgData,\n receiveTime: {\n sec: Math.floor(now / 1000),\n nsec: (now % 1000) * 1_000_000,\n },\n byteSize,\n };\n\n for (const [cb, entry] of deliverTo) {\n entry.lastDeliveredAt = now;\n try {\n cb(rosMsg);\n } catch (err) {\n this.logger.error('[RosbridgeClient] Subscriber callback error:', err);\n }\n }\n }\n\n private handleServiceResponse(msg: Record<string, unknown>): void {\n const id = msg.id as string;\n const pending = this.pendingServiceCalls.get(id);\n if (!pending) return;\n\n clearTimeout(pending.timer);\n this.pendingServiceCalls.delete(id);\n\n const success = msg.result === true || msg.result === 'true';\n if (success) {\n const values = (msg.values ?? {}) as Record<string, unknown>;\n pending.resolve(values);\n } else {\n const errorMsg =\n typeof msg.values === 'string' ? msg.values : 'Service call failed';\n pending.reject(new Error(errorMsg));\n }\n }\n\n // ── Private: topic management ──────────────────────────────────────────\n\n private unsubscribeTopic(topic: string): void {\n const sub = this.activeSubscriptions.get(topic);\n sub?.breaker.destroy();\n // `breakerListeners` are owned by the caller of `onBreakerStateChange`,\n // not by the subscription. Their cleanup happens through the unsubscribe\n // function that `onBreakerStateChange` returns.\n\n this.activeSubscriptions.delete(topic);\n if (this.ws && this.status === 'connected' && !sub?.isPaused) {\n this.send({ op: 'unsubscribe', topic });\n }\n }\n\n // ── IProtocolClient: circuit breaker controls ─────────────────────────────\n\n getBreakerState(topic: string): CircuitBreakerState {\n return this.activeSubscriptions.get(topic)?.breaker.getState() ?? 'closed';\n }\n\n getBreakerNextRetryAt(topic: string): number | null {\n return this.activeSubscriptions.get(topic)?.breaker.getNextRetryAt() ?? null;\n }\n\n getSubscriptionStats(topic: string) {\n const sub = this.activeSubscriptions.get(topic);\n if (!sub) return null;\n const mode = this.getThrottleMode();\n return {\n adaptiveMinIntervalMs: sub.bandwidth.adaptiveMinIntervalMs,\n bucketLabel: getTrackerBucketLabel(sub.bandwidth, mode),\n bytesPerSec: sub.bandwidth.bytesPerSec,\n };\n }\n\n breakerRetry(topic: string): void {\n this.activeSubscriptions.get(topic)?.breaker.retry();\n }\n\n breakerDisable(topic: string): void {\n this.activeSubscriptions.get(topic)?.breaker.disable();\n }\n\n onBreakerStateChange(\n topic: string,\n cb: (state: CircuitBreakerState) => void,\n ): () => void {\n let listeners = this.breakerListeners.get(topic);\n if (!listeners) {\n listeners = new Set();\n this.breakerListeners.set(topic, listeners);\n }\n listeners.add(cb);\n return () => {\n const set = this.breakerListeners.get(topic);\n if (set) {\n set.delete(cb);\n if (set.size === 0) this.breakerListeners.delete(topic);\n }\n };\n }\n\n // ── Private: dead-man's switch ─────────────────────────────────────────\n\n private safePublishZeroTwist(): void {\n if (!this.hasPublishedTwist) return;\n\n try {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.publish('/cmd_vel', CMD_VEL_SCHEMA, ZERO_TWIST, { priority: 'control' });\n }\n } catch {\n // best effort\n }\n\n this.hasPublishedTwist = false;\n }\n\n // ── Private: latency probe ──────────────────────────────────────────────\n\n private startLatencyProbe(): void {\n this.stopLatencyProbe();\n this.latencyProbeTimer = setInterval(() => {\n if (!this.ws || this.status !== 'connected') return;\n const start = Date.now();\n const id = `latency_probe:${++this.serviceCallCounter}`;\n\n const timer = setTimeout(() => {\n this.pendingServiceCalls.delete(id);\n }, 5_000);\n\n this.pendingServiceCalls.set(id, {\n resolve: () => {\n clearTimeout(timer);\n if (this.onLatency) {\n try {\n this.onLatency(Date.now() - start);\n } catch {\n // metrics must never affect protocol operation\n }\n }\n },\n reject: () => {\n clearTimeout(timer);\n },\n timer,\n });\n\n this.send({\n op: 'call_service',\n id,\n service: '/rosapi/topics',\n args: {},\n });\n }, 5_000);\n }\n\n private stopLatencyProbe(): void {\n if (this.latencyProbeTimer) {\n clearInterval(this.latencyProbeTimer);\n this.latencyProbeTimer = null;\n }\n }\n\n // ── Private: reconnection ──────────────────────────────────────────────\n\n private scheduleReconnect(): void {\n if (\n this.intentionalDisconnect ||\n this.reconnectTimer !== null ||\n this.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS\n ) {\n if (this.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {\n this.log(`Max reconnect attempts (${MAX_RECONNECT_ATTEMPTS}) reached.`);\n this.setStatus('error');\n }\n return;\n }\n\n const delay = Math.min(\n BASE_RECONNECT_DELAY_MS * Math.pow(2, this.reconnectAttempts),\n 16_000,\n );\n this.log(\n `Scheduling reconnect attempt ${this.reconnectAttempts + 1}/${MAX_RECONNECT_ATTEMPTS} in ${delay}ms...`,\n );\n this.reconnectAttempts++;\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.performConnect().catch((err) => {\n this.logger.error('[RosbridgeClient] Reconnect failed:', err);\n });\n }, delay);\n }\n\n // ── Private: cleanup ───────────────────────────────────────────────────\n\n private cleanupConnection(): void {\n this.clearConnectionTimeout();\n this.stopServicesPoll();\n this.activeSubscriptions.clear();\n\n for (const [, pending] of this.pendingServiceCalls) {\n clearTimeout(pending.timer);\n pending.reject(new Error('Connection closed'));\n }\n this.pendingServiceCalls.clear();\n\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n for (const topic of this.advertisedTopics) {\n try {\n this.send({ op: 'unadvertise', topic });\n } catch {\n // best effort\n }\n }\n }\n\n this.advertisedTopics.clear();\n }\n\n private cleanup(): void {\n this.cleanupConnection();\n this.stopLatencyProbe();\n this.stopServicesPoll();\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n if (this.ws) {\n try {\n this.ws.close();\n } catch {\n // ignore\n }\n this.ws = null;\n }\n\n this.discoveredTopics = [];\n if (this.availableServices.length > 0) {\n this.availableServices = [];\n this.notifyServicesChanged();\n }\n }\n\n private clearConnectionTimeout(): void {\n if (this.connectionTimeoutTimer) {\n clearTimeout(this.connectionTimeoutTimer);\n this.connectionTimeoutTimer = null;\n }\n }\n\n // ── Private: helpers ───────────────────────────────────────────────────\n\n private send(msg: Record<string, unknown>): void {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify(msg));\n }\n }\n\n private setStatus(status: ConnectionStatus): void {\n if (this.status === status) return;\n this.status = status;\n for (const cb of this.statusListeners) {\n try {\n cb(status);\n } catch (err) {\n this.logger.error('[RosbridgeClient] Status listener error:', err);\n }\n }\n }\n\n private notifyTopicsChanged(): void {\n for (const cb of this.topicsListeners) {\n try {\n cb(this.discoveredTopics);\n } catch (err) {\n this.logger.error('[RosbridgeClient] Topics listener error:', err);\n }\n }\n }\n\n private log(message: string): void {\n const timestamp = new Date().toISOString().substring(11, 23);\n const formatted = `[${timestamp}] ${message}`;\n this.logger.log(`[RosbridgeClient] ${formatted}`);\n for (const cb of this.logListeners) {\n try {\n cb(formatted);\n } catch (err) {\n this.logger.error('[RosbridgeClient] Log listener error:', err);\n }\n }\n }\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\nimport type { ProtocolType } from './types';\n\n/**\n * Default TCP port for each supported protocol. Useful for consumers\n * building connection-configuration UIs that want a sensible starting\n * value when the user changes protocol.\n */\nexport const DEFAULT_PORTS: Record<ProtocolType, number> = {\n 'foxglove-ws': 8765,\n rosbridge: 9090,\n zenoh: 7447,\n};\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 Benjamín Arratia\n\n/**\n * ProtocolManager — factory plus active-connection lifecycle manager.\n *\n * Builds the appropriate `IProtocolClient` for `options.protocol`, sanitizes\n * the user-entered host, validates the URL with `new URL()`, and forwards\n * the connection. Holds the active client so callers don't have to.\n *\n * `setClientOptions` is the injection point for the host's `onLatency`\n * callback, `logger`, and `getThrottleMode` selector. Options are stored\n * and forwarded into every client the manager constructs.\n */\n\nimport { FoxgloveClient } from './FoxgloveClient';\nimport { RosbridgeClient } from './RosbridgeClient';\nimport type {\n ConnectionOptions,\n IProtocolClient,\n ProtocolClientOptions,\n} from './types';\nimport { DEFAULT_PORTS } from './constants';\n\n/**\n * Normalize a user-entered host string into something safe to drop into\n * `${scheme}://${host}:${port}`. Strips `ws://`, `wss://`, `http://`,\n * `https://` prefixes (paste from a browser address bar or a Foxglove URL),\n * drops a trailing `:port` (so a `host:8766` paste doesn't poison the URL\n * with two ports — the dedicated `port` field always wins), and trims\n * trailing path / query / fragment plus whitespace.\n */\nfunction sanitizeHost(raw: string): string {\n let host = (raw ?? '').trim();\n host = host.replace(/^(wss?|https?):\\/\\//i, '');\n // Drop trailing path/query/fragment.\n host = host.split('/')[0] ?? host;\n host = host.split('?')[0] ?? host;\n host = host.split('#')[0] ?? host;\n // Strip trailing :port. IPv6 literals are bracketed (`[::1]:8765`), so\n // only strip when the colon isn't inside brackets.\n if (!host.startsWith('[')) {\n const colonIx = host.indexOf(':');\n if (colonIx !== -1) host = host.slice(0, colonIx);\n }\n return host;\n}\n\nexport class ProtocolManager {\n private activeClient: IProtocolClient | null = null;\n private activeOptions: ConnectionOptions | null = null;\n private clientOptions: ProtocolClientOptions | undefined;\n\n /**\n * Set options forwarded to every client constructed by this manager.\n * Host applications typically call this once at startup.\n */\n setClientOptions(options: ProtocolClientOptions): void {\n this.clientOptions = options;\n }\n\n /**\n * Create and connect a protocol client for the given options.\n *\n * For `protocol: 'zenoh'`, throws a clear \"planned for v0.2.0\" error —\n * the v0.1.0 release does not ship a Zenoh implementation.\n */\n async connect(options: ConnectionOptions): Promise<IProtocolClient> {\n if (this.activeClient) {\n await this.activeClient.disconnect();\n }\n\n const client = this.createClient(options);\n const scheme = options.secure ? 'wss' : 'ws';\n const port = options.port || DEFAULT_PORTS[options.protocol];\n const host = sanitizeHost(options.host);\n const url = `${scheme}://${host}:${port}`;\n\n // Validate before handing to the runtime's WebSocket implementation.\n // Some platforms (React Native on Android via okhttp3) throw on the\n // native message-queue thread for malformed ports/hosts — there's no\n // JS-side handler for that, so the process dies. Catching here keeps\n // the failure inside the connection flow where the host can surface\n // it as a regular connection error.\n try {\n // eslint-disable-next-line no-new\n new URL(url);\n } catch {\n throw new Error(\n `Invalid connection URL \"${url}\" — check host and port. Hosts should not include \"ws://\" or \":port\"; use the port field instead.`,\n );\n }\n\n await client.connect(url);\n\n this.activeClient = client;\n this.activeOptions = options;\n\n return client;\n }\n\n /**\n * Disconnect the active client and forget it.\n */\n async disconnect(): Promise<void> {\n if (this.activeClient) {\n await this.activeClient.disconnect();\n this.activeClient = null;\n this.activeOptions = null;\n }\n }\n\n /**\n * Currently active client, or `null` if not connected.\n */\n getClient(): IProtocolClient | null {\n return this.activeClient;\n }\n\n /**\n * Currently active connection options, or `null` if not connected.\n */\n getOptions(): ConnectionOptions | null {\n return this.activeOptions;\n }\n\n private createClient(options: ConnectionOptions): IProtocolClient {\n switch (options.protocol) {\n case 'foxglove-ws':\n return new FoxgloveClient(this.clientOptions);\n case 'rosbridge':\n return new RosbridgeClient(this.clientOptions);\n case 'zenoh':\n throw new Error('Zenoh support is planned for v0.2.0');\n default: {\n const exhaustive: never = options.protocol;\n throw new Error(`Unknown protocol: ${String(exhaustive)}`);\n }\n }\n }\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ros-mobile-bridge",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Protocol adapters for connecting JavaScript and TypeScript runtimes to ROS 2 robots. Foxglove WebSocket and rosbridge over a single IProtocolClient interface; runs in React Native, browsers, Node.js, and Electron from the same build.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ros",
|
|
7
|
+
"ros2",
|
|
8
|
+
"robotics",
|
|
9
|
+
"foxglove",
|
|
10
|
+
"rosbridge",
|
|
11
|
+
"websocket",
|
|
12
|
+
"react-native",
|
|
13
|
+
"mobile",
|
|
14
|
+
"cdr"
|
|
15
|
+
],
|
|
16
|
+
"license": "Apache-2.0",
|
|
17
|
+
"author": {
|
|
18
|
+
"name": "Benjamín Arratia",
|
|
19
|
+
"url": "https://aurilabs.tech"
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://github.com/AuriLabsTech/ros-mobile-bridge#readme",
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/AuriLabsTech/ros-mobile-bridge.git"
|
|
25
|
+
},
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/AuriLabsTech/ros-mobile-bridge/issues"
|
|
28
|
+
},
|
|
29
|
+
"type": "module",
|
|
30
|
+
"main": "./dist/index.cjs",
|
|
31
|
+
"module": "./dist/index.mjs",
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"exports": {
|
|
34
|
+
".": {
|
|
35
|
+
"import": {
|
|
36
|
+
"types": "./dist/index.d.ts",
|
|
37
|
+
"default": "./dist/index.mjs"
|
|
38
|
+
},
|
|
39
|
+
"require": {
|
|
40
|
+
"types": "./dist/index.d.cts",
|
|
41
|
+
"default": "./dist/index.cjs"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"./package.json": "./package.json"
|
|
45
|
+
},
|
|
46
|
+
"files": [
|
|
47
|
+
"dist",
|
|
48
|
+
"LICENSE",
|
|
49
|
+
"README.md",
|
|
50
|
+
"CHANGELOG.md",
|
|
51
|
+
"ROADMAP.md",
|
|
52
|
+
"SECURITY.md"
|
|
53
|
+
],
|
|
54
|
+
"sideEffects": false,
|
|
55
|
+
"engines": {
|
|
56
|
+
"node": ">=18"
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build": "tsup",
|
|
60
|
+
"clean": "rimraf dist",
|
|
61
|
+
"lint": "eslint .",
|
|
62
|
+
"lint:fix": "eslint . --fix",
|
|
63
|
+
"format": "prettier --write .",
|
|
64
|
+
"format:check": "prettier --check .",
|
|
65
|
+
"typecheck": "tsc --noEmit",
|
|
66
|
+
"test": "vitest run",
|
|
67
|
+
"test:watch": "vitest",
|
|
68
|
+
"test:coverage": "vitest run --coverage",
|
|
69
|
+
"docs": "typedoc",
|
|
70
|
+
"check-licenses": "license-checker --production --onlyAllow 'Apache-2.0;MIT;BSD-2-Clause;BSD-3-Clause;ISC;0BSD;CC0-1.0;Python-2.0' --excludePrivatePackages",
|
|
71
|
+
"prepublishOnly": "npm run clean && npm run lint && npm run typecheck && npm test && npm run build"
|
|
72
|
+
},
|
|
73
|
+
"dependencies": {
|
|
74
|
+
"@foxglove/ros2idl-parser": "^0.3.6",
|
|
75
|
+
"@foxglove/rosmsg": "^5.0.5",
|
|
76
|
+
"@foxglove/rosmsg2-serialization": "^3.0.3"
|
|
77
|
+
},
|
|
78
|
+
"devDependencies": {
|
|
79
|
+
"@types/node": "^20.11.0",
|
|
80
|
+
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
|
81
|
+
"@typescript-eslint/parser": "^7.0.0",
|
|
82
|
+
"@vitest/coverage-v8": "^1.4.0",
|
|
83
|
+
"eslint": "^8.57.0",
|
|
84
|
+
"eslint-import-resolver-typescript": "^3.10.1",
|
|
85
|
+
"eslint-plugin-import": "^2.29.1",
|
|
86
|
+
"license-checker": "^25.0.1",
|
|
87
|
+
"prettier": "^3.2.5",
|
|
88
|
+
"rimraf": "^5.0.5",
|
|
89
|
+
"tsup": "^8.0.2",
|
|
90
|
+
"typedoc": "^0.25.13",
|
|
91
|
+
"typescript": "^5.4.5",
|
|
92
|
+
"vitest": "^1.4.0"
|
|
93
|
+
}
|
|
94
|
+
}
|