GitHub - f/carspeed: Reliable browser GPS speed and movement detection · GitHub
Skip to content

Repository files navigation

browser-car-speed

Tiny, typed browser GPS speed and movement detection.

npm install browser-car-speed

browser-car-speed reads the standard Geolocation API, prefers the browser's reported coords.speed, and uses a guarded rolling-coordinate estimate when that value is missing or stuck at zero. It has no runtime dependencies and does nothing until you call start().

Live example: Speedo · Simulated demo without location

Quick start

import {
  start,
  stop,
  subscribe,
  getCarSpeed,
  isCarMoving,
} from "browser-car-speed";

const unsubscribe = subscribe((snapshot) => {
  console.log(snapshot.status);                 // "locating" | "live" | ...
  console.log(snapshot.reading?.kilometersPerHour);
});

// Call from a click/tap because the browser may show a location prompt.
startButton.addEventListener("click", start);

getCarSpeed();        // km/h: number | null
getCarSpeed("mph");  // mph:  number | null
isCarMoving();        // boolean | null

unsubscribe();
stop();

null always means unknown or unavailable. It is never silently converted to zero. This distinction matters when GPS accuracy is too weak to prove that the device is stationary.

Independent trackers

Use createCarSpeed() when an app needs custom thresholds, an injected adapter, or more than one tracker.

import { createCarSpeed } from "browser-car-speed";

const car = createCarSpeed({
  movingThresholdKmh: 4,
  stationaryThresholdKmh: 2,
  staleAfterMs: 8_000,
});

const unsubscribe = car.subscribe(({ status, reading, moving }) => {
  if (status !== "live") return;
  console.log(reading.kilometersPerHour, moving);
});

car.start();

// Later:
unsubscribe();
car.stop();

API

Convenience singleton

  • start() / startCarSpeed() — begin high-accuracy location tracking.
  • stop() / stopCarSpeed() — clear the watcher, timer, and retained state.
  • getCarSpeed(unit?) — current full-precision speed in "km/h" (default), "mph", or "m/s"; null when unavailable or stale.
  • isCarMoving() — hysteresis-based true or false; null when unknown.
  • getSnapshot() / getCarSpeedSnapshot() — current state and metadata.
  • subscribe(listener, options?) / subscribeCarSpeed(...) — state updates; returns an idempotent unsubscribe function.
  • carSpeed — the shared tracker used by these functions.

Tracker

createCarSpeed(options?) returns:

interface CarSpeedTracker {
  start(): void;
  stop(): void;
  getCarSpeed(unit?: "km/h" | "mph" | "m/s"): number | null;
  isCarMoving(): boolean | null;
  getSnapshot(): CarSpeedSnapshot;
  subscribe(listener: CarSpeedListener, options?: { emitCurrent?: boolean }): () => void;
}

Snapshot

interface CarSpeedSnapshot {
  status: "idle" | "locating" | "live" | "stale" | "error" | "unsupported";
  reading: SpeedReading | null;      // fresh reading only
  lastReading: SpeedReading | null;  // retained while stale
  moving: boolean | null;
  error: CarSpeedError | null;
  running: boolean;
  supported: boolean;
  accuracyMeters: number | null;
  lastPositionTimestamp: number | null;
}

interface SpeedReading {
  metersPerSecond: number;
  kilometersPerHour: number;
  milesPerHour: number;
  source: "sensor" | "calculated";
  accuracyMeters: number | null;
  timestamp: number;
}

Snapshots and readings are immutable.

Options

Option Default Purpose
movingThresholdKmh 3 Enter the moving state at or above this speed.
stationaryThresholdKmh 1.5 Leave the moving state at or below this speed.
staleAfterMs 10000 Stop exposing a reading after this age.
maximumSpeedKmh 260 Reject implausibly high values.
maximumFallbackAccuracyMeters 15 Accuracy ceiling for coordinate-derived speed.
coordinateFallback true Estimate speed when coords.speed is unavailable.
minimumFallbackIntervalMs 500 Shortest coordinate baseline.
fallbackWindowMs 20000 Longest rolling coordinate baseline.
fallbackMinimumDisplacementMeters 3 Minimum absolute displacement evidence.
smoothingWindow 3 Accepted readings in the median filter (19).
maximumAccelerationKmhPerSecond 60 Maximum filtered change per second.
speedJumpToleranceKmh 15 Free jump tolerance before limiting changes.
freshnessIntervalMs 500 Stale-state notification interval; 0 disables it.
positionOptions high accuracy, no cache, 15 s timeout Native watch options.
geolocation browser API Structural adapter for testing or hybrid runtimes.
now Date.now Epoch-millisecond clock, injectable for tests.

How fallback avoids common GPS mistakes

  • Displacement inside the reported accuracy radius remains unknown, not stationary.
  • A rolling window preserves evidence of slow movement instead of repeatedly resetting the baseline.
  • Two consistent, progressing coordinate estimates are required before fallback speed is accepted.
  • A fixed GPS jump is rejected because its displacement does not continue.
  • Old smoothing samples are reset after a stale gap.
  • A browser-provided zero can be overridden by sustained coordinate evidence.
  • Separate enter/exit thresholds keep movement state from flickering near zero.

Browser and vehicle limitations

This package estimates whether the browser/device is moving. It does not read Tesla CAN data, vehicle telemetry, wheel speed, or a calibrated dashboard sensor. Results are indicative and depend on the browser's Geolocation implementation, GPS conditions, hardware, permissions, and software version.

  • Use HTTPS (or localhost); browsers normally restrict Geolocation on insecure origins.
  • Ask for location from a user gesture where possible.
  • Do not use this package as a safety system or a replacement for the vehicle's speedometer.
  • Tesla fullscreen/Theater workarounds belong in the application layer and are deliberately not included here.

Utilities

import { convertSpeed, haversineMeters } from "browser-car-speed";

convertSpeed(100, "km/h", "mph");
haversineMeters(41.0082, 28.9784, 41.0151, 28.9795);

Development

npm install
npm run verify

The verification suite type-checks and builds the package, runs behavior tests, checks package exports/types, inspects the tarball allow-list, and installs the packed tarball into a clean temporary project.

License

MIT

About

Reliable browser GPS speed and movement detection

Resources

Stars

8 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages