Alle Artikel
/ 3 Min. Lesezeit

Laufband-Hacking: NordicTrack C990 mit Raspberry Pi steuern

NordicTrack C990 per Raspberry Pi Zero hacken — WebSocket-Steuerung, selbstgebauter Bandsensor und Live-Dashboard ohne iFit-Abo.

Raspberry PiIoTNordicTrackNode.jsMaker
suetti.it/dev-log
Laufband-Hacking: NordicTrack C990 mit Raspberry Pi steuern

Mein NordicTrack C990 hat einen Steigungsmotor, Geschwindigkeitsregelung und ein 7-Zoll-Display — aber alles steckt hinter einem iFit-Abo. Die Lösung: ein Raspberry Pi Zero W, der das Laufband über WebSocket steuert, einen selbstgebauten Bandsensor und ein Live-Dashboard im Browser.

Das Setup

  • Laufband: NordicTrack C990 (Modell ETNE14716) mit Android-Steuereinheit
  • Controller: Raspberry Pi Zero W
  • Kommunikation: WebSocket-API auf dem Laufband-Display
  • Extras: GPIO-Sensor für unabhängige Geschwindigkeitsmessung
  • Frontend: Socket.io-Dashboard auf dem Pi

Die Android-Einheit des C990 läuft intern mit einer WebSocket-API. Dank der Community rund um iFit-Laufbänder — u.a. die Projekte nordichack und iFitController — sind die Kommandos dokumentiert. Das Laufband akzeptiert JSON-Nachrichten im lokalen Netz.

Die Laufband-Klasse: WebSocket-Steuerung

Das Herzstück ist eine Node.js-Klasse, die sich per WebSocket mit dem Laufband verbindet und alle Werte in Echtzeit empfängt:

const WebSocketClient = require("websocket").client;
const client = new WebSocketClient();
const EventEmitter = require("events");

class Laufband extends EventEmitter {
  constructor(ip) {
    super();
    this.ip = ip;
    this.running = false;

    this.promise = new Promise((resolve) => {
      client.connect(`ws://${this.ip}/control`);
      client.on("connect", connection => {
        this.socket = connection;

        connection.on("message", msg => {
          const json = JSON.parse(msg.utf8Data);
          if (json.values) {
            if (json.values["Current KPH"]) {
              this.kmh = parseFloat(json.values["Current KPH"]);
              if (this.kmh > 0 && !this.running) {
                this.running = true;
                this.emit("start", this.data);
              }
            }
            this.emit("data", this.data);
          }
        });
        resolve(this);
      });
    });
  }
}

Steigung und Geschwindigkeit setzen ist dann simpel — eine JSON-Nachricht mit dem gewünschten Wert:

this.incline = steigung => {
  this.socket.sendUTF(JSON.stringify({
    type: "set",
    values: { Incline: steigung + "" }
  }));
};

this.speed = kmh => {
  this.socket.sendUTF(JSON.stringify({
    type: "set",
    values: { KPH: kmh + "" }
  }));
};

Das Laufband antwortet kontinuierlich mit dem aktuellen Status: Geschwindigkeit, Steigung, Distanz, Gesamtzeit. Der Steigungsbereich liegt beim C990 bei 0% bis 12%.

Der Bandsensor: Hardware-Hacking am GPIO

Das Spannendste am Projekt: ein selbstgebauter Sensor, der die Geschwindigkeit unabhängig vom Laufband misst. Ein Magnetschalter am Laufband-Rahmen erkennt jede Umdrehung des Bandes (Umfang: 3140mm) über einen GPIO-Pin am Raspberry Pi.

const gpio = require("rpi-gpio");

class Sensor extends EventEmitter {
  constructor(GPIO, BELT_LENGTH) {
    super();
    this.beltlength = BELT_LENGTH; // 3140mm

    this.data = { distanz: 0, ticks: 0 };

    gpio.on("change", (channel, val) => {
      if (val) this.calc();
    });

    gpio.setup(GPIO, gpio.DIR_IN, gpio.EDGE_BOTH);
  }

  calc() {
    const blkm = this.beltlength / 1000 / 1000;
    this.data.distanz += blkm;
    this.data.ticks++;

    const ts2 = new Date().getTime();
    const diff = ts2 - this.ts;
    this.data.ms = this.beltlength / diff;
    this.data.kmh = parseFloat(
      (this.data.ms / 1000 / (1 / 3600)).toFixed(2)
    );

    this.emit("data", this.data);
    this.ts = ts2;
  }
}

Der Sensor berechnet aus der Zeit zwischen zwei Umdrehungen die aktuelle Geschwindigkeit in km/h. Damit lässt sich die Genauigkeit des eingebauten Laufband-Sensors verifizieren — und man hat eine zweite, unabhängige Datenquelle.

Server und Live-Dashboard

Ein Express-Server auf dem Pi bringt alles zusammen. Socket.io streamt die Daten in Echtzeit an ein minimales Frontend:

const sensor = new Sensor(40, 3140).on("data", d => {
  if (LB.data) d.laufband = LB.data;

  // Workout-Daten mitloggen
  if (workoutName) {
    fs.appendFileSync(workoutName,
      `${time}|${d.laufband.Kilometers}|${d.laufband.Incline}` +
      `|${d.laufband.KPH}|${sensor.data.distanz}|${sensor.data.kmh}\n`
    );
  }

  if (socket) socket.emit("data", d);
});

Das Dashboard zeigt Geschwindigkeit, Distanz, Steigung und Sensor-Ticks. Bewusst minimal — HTML, etwas CSS, Vanilla JS. Auf dem Pi Zero zählt jedes Megabyte. Jedes Workout wird automatisch als Textdatei mitgeschrieben — Zeitstempel, Distanz, Steigung, Speed vom Laufband und vom Sensor. So lassen sich die Läufe später auswerten.

Herausforderungen

Netzwerk: Der Pi Zero W hat nur 2.4 GHz WLAN. Im Keller war das Signal anfangs zu schwach — ein WLAN-Repeater hat das gelöst.

Sensor-Kalibrierung: Die Bandlänge exakt zu messen ist entscheidend. Eine Abweichung von wenigen Zentimetern summiert sich über eine Stunde Laufen spürbar auf.

WebSocket-Stabilität: Die Verbindung zum Laufband ist solide, solange man auf dem gleichen Subnetz bleibt. Ab und zu bricht sie nach Standby ab — ein Reconnect-Handler im Code fängt das ab.

Fazit

Das Projekt hat aus einem 900€-Laufband mit Zwangs-Abo eine offene Plattform gemacht. Steigung per Code setzen, unabhängige Geschwindigkeitsmessung über einen Magnet-Sensor und automatisches Workout-Logging — alles mit einem 15€-Raspberry Pi Zero. Wer ein iFit-fähiges Laufband hat und gerne bastelt: Die Community hat die Vorarbeit bei der WebSocket-Dokumentation gemacht. Der Rest ist Node.js und ein Nachmittag Löten.

TS

Timo Sütterlin

Fullstack-Entwickler — Web, Mobile, KI

Weitere Artikel

← Alle Artikel