Streaming live sensor data from Ball 2

Ball 2 can stream its live motion data — raw IMU samples plus high-level events like taps, tosses, rolls and spins — out to a program you write. It's built for makers, developers and researchers who want to build their own apps, visualizations or experiments on top of the ball's sensors.

This guide walks through the free example receiver and how to connect the Ball 2 app to it. No account or API key is required — everything runs on your own machine and local network.

⬇ Download the example app (.zip)


How it works

The Ball 2 app is a WebSocket client. It connects out to a small WebSocket server that you run, then pushes each ball event to it as JSON. Because the app dials out to you, there's nothing to configure on your phone or tablet beyond the address of your server.

  Ball 2 (IMU)  ──Bluetooth──▶  Ball 2 app  ──ws:// (client)──▶  Your server
                                (Sensor Lab)      JSON events      (example code)

This means you start your server first, then point the app at it. The app and the machine running the server must be on the same network. Most people run the ball app on a phone or tablet and the server on a laptop or desktop.


Step 1 — Start the receiver server

Download and unzip the example app. Inside you'll find a minimal WebSocket server in two flavours — Python and Node.js — plus the full event reference. Use whichever you prefer; both listen on port 8080 and print every event they receive.

Option A — Python

cd sensor-stream
pip install -r requirements.txt
python server.py                 # listens on 0.0.0.0:8080
# python server.py --plot        # also show a live accel plot (needs matplotlib)

Option B — Node.js

cd sensor-stream
npm install
node server.js                   # listens on 0.0.0.0:8080
# PORT=9000 node server.js       # custom port

Once running, the server prints the address it's listening on and waits for the ball to connect.

Find your computer's IP address

You'll need your computer's address on the local network so the app can reach it:

  • macOS: ipconfig getifaddr en0
  • Windows: ipconfig (look for the IPv4 address)
  • Linux: hostname -I

You'll get something like 192.168.1.42. Your server address is then ws://192.168.1.42:8080.


Step 2 — Connect the Ball 2 app

  1. Open the Ball 2 app and go to the Sensor Lab tab.
  2. Tap the stream icon in the top toolbar to open the Stream Events dialog.
  3. Enter your server address, e.g. ws://192.168.1.42:8080.
  4. Choose which events you want to send (see below). Raw IMU stream is on by default.
  5. Tap Connect.
  6. Move the ball — events start printing in your server's terminal.

The stream icon

The toolbar icon shows your streaming state at a glance:

  • White — not streaming.
  • Red and pulsing — connected and streaming to your server.


Choosing which events to stream

The events selector lets you pick any combination of event types. Leave Raw IMU stream selected for the high-rate sensor feed, or add higher-level events that fire when the ball detects a specific motion. You can change your selection at any time while connected — updates take effect immediately, no need to reconnect.

Event Fires when…
Raw IMU stream Continuous, high-rate accelerometer + gyroscope samples.
Movement Orientation / velocity updates as the ball moves.
Tap A tap is detected on the ball.
Toss The ball is tossed / in free fall.
Roll The ball is rolling.
Spin The ball is spinning.
Shake A shake gesture is detected.
Hit An impact is detected.

Tip: high-level events are sparse — they only appear when the motion actually happens. The raw IMU stream, by contrast, is continuous. If you're testing, Movement is the easiest to trigger: just rotate the ball.


Event format

Every event arrives as a single JSON object, one per WebSocket message. All events share these fields:

Field Type Meaning
eventType string stream, movement, tap, etc.
ballId string Stable identifier for the ball.
time number Seconds since the sensor started streaming.

A raw stream event looks like this:

{
  "eventType": "stream",
  "ballId": "a1b2c3",
  "time": 12.345,
  "samples": [
    { "timestamp": 12.290, "accel": [0.12, -9.79, 0.04], "gyro": [0.01, 0.00, -0.02] },
    { "timestamp": 12.295, "accel": [0.10, -9.80, 0.05], "gyro": [0.01, 0.00, -0.01] }
  ],
  "modes":       ["GeneralMotion", "GeneralMotion"],
  "accelBodies": [[0.12, -9.79, 0.04], [0.10, -9.80, 0.05]],
  "velocities":  [[0.00, 0.01, 0.00], [0.00, 0.01, 0.00]]
}

The samples, modes, accelBodies and velocities arrays are parallel — index i of each describes the same instant. Acceleration is in m/s², angular velocity in rad/s. The full field-by-field reference for every event type is in the README.md inside the download.


ws:// vs wss://

The examples use plain ws://, which is perfect for native apps, Python, Node and command-line tools on your local network. If you want to consume the stream from a web page served over https://, browsers require a secure wss:// connection — you'll need to terminate TLS at your own server and connect the app to a wss:// address instead.


Good to know

  • Auto-reconnect: the app retries with backoff, so you can start your server after connecting, or restart it, without re-tapping Connect.
  • Low latency: if your server can't keep up, the app drops the newest frames rather than buffering — the stream stays current.
  • One server at a time: the app maintains a single outbound connection.
  • Leaving the Sensor Lab disconnects the stream automatically.

Troubleshooting

  • Nothing appears in the terminal: double-check the IP address and that both devices are on the same Wi-Fi network. Firewalls can also block port 8080.
  • Only raw stream shows up: make sure the higher-level event is selected in the dialog, and remember those events only fire on the actual motion (tap the ball, roll it, etc.).
  • The icon stays white: the server isn't reachable yet — confirm it's running and the address is correct.

Questions? Contact us at info@ball2.ai.