Zum Hauptinhalt springen

Datenfluss

Diese Seite erklärt, wie GPS-Positionsdaten und Sessionereignisse vom physischen TRACKTICS-Tracker zu Ihrer Anwendung gelangen — in Echtzeit und als historische Datensätze.

Überblick

Tracker (GPS-Gerät)

│ Geräte-WebSocket (Firmware → Backend)

TRACKTICS Backend

├──▶ WebSocket-Kanäle ──▶ Live-Clients (Dashboards, Apps)

└──▶ Positionsspeicher ──▶ REST-API (historische Abfragen)
  1. Ein physischer Tracker sendet kontinuierlich Positionspakete über einen dedizierten Geräte-WebSocket an das TRACKTICS-Backend.
  2. Das Backend verteilt jedes Paket an alle verbundenen Clients, die den entsprechenden WebSocket-Kanal abonniert haben.
  3. Alle Positionsdatensätze werden gespeichert. Nach Beendigung einer Session sind sie über die REST-API für historische Abfragen verfügbar.

Wann werden Daten gesendet?

Positionsdaten werden gesendet, sobald ein Tracker eingeschaltet und verbunden ist. In der Praxis bedeutet das:

  • Daten beginnen kurz vor dem Start einer Session zu fließen, sobald die Tracker eingeschaltet sind und GPS-Signal haben.
  • Daten werden während der gesamten Session mit hoher Frequenz gesendet (mehrere Positionsproben pro Sekunde, gebündelt in Paketen).
  • Daten stoppen, wenn die Tracker am Ende der Session ausgeschaltet werden.

Es gibt keinen expliziten Sessionsstart, der den Datenfluss steuert — das Backend zeichnet alles auf, was der Tracker sendet. Ihre Anwendung kann bei Bedarf nach Sessionzeitraum filtern.

Marker (Tore, Ereignisse) werden über den Marker-WebSocket-Kanal gesendet, sobald ein Trainer sie in der Portal-App erstellt.


WebSocket-Authentifizierung

Der WebSocket-Server befindet sich unter:

wss://ws.dp.dev.tracktics.systems (Staging)

Kanäle werden durch Anhängen eines path-Query-Parameters an die WebSocket-Basis-URL ausgewählt. Zwei Authentifizierungsmethoden werden unterstützt:

Option 1 — Ticket-basiert (empfohlen für Browser)

Browser können keine benutzerdefinierten HTTP-Header bei WebSocket-Verbindungen setzen. Daher bietet TRACKTICS einen Einmalticket-Mechanismus:

Schritt 1 — Ticket anfordern

POST /ws/ticket
Authorization: Bearer <ihr-firebase-jwt>

Antwort

{
"ws_ticket_id": "f6a7b8c9-d0e1-2345-f123-456789012345"
}

Das Ticket ist einmalig verwendbar und kurzlebig.

Schritt 2 — Mit Ticket verbinden

wss://ws.dp.dev.tracktics.systems?ticket=<ws_ticket_id>&path=<Kanalpfad>

Beispiel:

wss://ws.dp.dev.tracktics.systems?ticket=f6a7b8c9-d0e1-2345-f123-456789012345&path=/position/clubs/a1b2c3d4-e5f6-7890-abcd-ef1234567890

Option 2 — Direktes Bearer-Token (nur Nicht-Browser-Clients)

Wenn Sie den WebSocket-Client vollständig kontrollieren (z. B. eine native App oder ein Server-seitiger Prozess), können Sie den Firebase-JWT direkt im HTTP-Upgrade-Request-Header übergeben:

Authorization: Bearer <ihr-firebase-jwt>

Verbindung zu:

wss://ws.dp.dev.tracktics.systems?path=<Kanalpfad>

Schnelltest mit wscat

wscat ist ein einfacher WebSocket-Kommandozeilen-Client, der sich zum Testen von Kanälen ohne Programmieraufwand eignet.

Ersetzen Sie <session_id> oder <tracker_id> in den Beispielen unten durch eine echte ID. Wie Sie Tracker- und Session-IDs über die API abrufen, ist Schritt für Schritt in Den Verein erkunden beschrieben.

Installation

npm install -g wscat

Verbindung mit Bearer-Token (Option 2)

wscat \
--header "Authorization: Bearer <ihr-firebase-jwt>" \
--connect "wss://ws.dp.dev.tracktics.systems?path=/position/sessions/<session_id>"

Verbindung mit Ticket (Option 1)

Zunächst ein Ticket anfordern, dann verbinden:

TICKET=$(curl -s -X POST https://dp.stg.tracktics.systems/ws/ticket \
-H "Authorization: Bearer <ihr-firebase-jwt>" \
| jq -r '.ws_ticket_id')

wscat --connect "wss://ws.dp.dev.tracktics.systems?ticket=${TICKET}&path=/position/sessions/<session_id>"

Sobald die Verbindung besteht, werden eingehende JSON-Nachrichten zeilenweise im Terminal angezeigt.


WebSocket-Kanäle

Nach dem Verbindungsaufbau beginnt der Server, JSON-Nachrichten für den gewählten Kanal zu senden. Alle Kanäle sind nur zum Empfangen — Clients empfangen, senden aber nie.

Vereins-Positionskanal

Empfängt Positionsaktualisierungen von allen aktiven Trackern innerhalb des Vereins.

path=/position/clubs/{club_id}

Geeignet für ein vereinsweites Live-Dashboard, auf dem alle Spieler gleichzeitig angezeigt werden sollen.

Tracker-Positionskanal

Empfängt Positionsaktualisierungen für einen einzelnen Tracker.

path=/position/trackers/{tracker_id}

Geeignet, wenn ein bestimmtes Gerät unabhängig von Session oder Verein verfolgt werden soll.

Session-Positionskanal

Empfängt Positionsaktualisierungen für alle einer bestimmten Session zugeordneten Tracker.

path=/position/sessions/{session_id}

Dies ist der häufigste Kanal für eine Live-Spiel- oder Trainingsansicht: einmal auf die Session abonnieren und Daten für alle teilnehmenden Spieler empfangen.

Session-Marker-Kanal

Empfängt Marker-Benachrichtigungen (Tore, Fouls, Trainer-Annotationen), sobald sie während einer bestimmten Session erstellt werden.

path=/marker/sessions/{session_id}

Format der Positionsnachrichten

Jede Positionsnachricht auf einem Positionskanal hat dieselbe Struktur. Ein einzelnes Paket kann mehrere Proben enthalten, die über Mikrosekunden-Deltas relativ zueinander zeitgestempelt sind, um Bandbreite zu sparen.

{
"device_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"club_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"tracker_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"position_id": "d4e5f6a7-b8c9-0123-def1-234567890123",
"sequence_number": 12345,
"timestamp": "2025-01-15T12:30:00Z",
"positions": [
{
"us_delta": 0,
"latitude": 37.7749,
"longitude": -122.4194,
"altitude": 100.0,
"speed": [5.2, 0.0, 0.0],
"attitude": [0.707, 0.0, 0.707, 0.0],
"acceleration": [0.1, 0.0, 9.8],
"relative_position": [10.5, 20.3]
}
]
}
FeldBeschreibung
tracker_idUUID des Trackers, der diese Daten erzeugt hat
position_idEindeutige ID dieses Pakets (zur Deduplizierung verwenden)
sequence_numberMonoton steigender Zähler pro Tracker
timestampISO-8601-Zeitstempel der ersten Probe im positions-Array
positions[].us_deltaMikrosekunden seit der vorherigen Probe (0 bei der ersten Probe)
positions[].latitude / longitudeWGS-84-Koordinaten
positions[].altitudeHöhe in Metern
positions[].speedGeschwindigkeitsvektor in m/s [x, y, z]
positions[].attitudeGeräteausrichtung als Einheitsquaternion [w, x, y, z]
positions[].accelerationBeschleunigung in m/s² [x, y, z]
positions[].relative_positionPosition in Metern relativ zur Feldmitte [x, y]

Format der Marker-Nachrichten

Nachrichten auf dem Marker-Kanal folgen dem Benachrichtigungs-Umschlag:

{
"operation": "create",
"resource": "club/team/session/marker",
"timestamp": "2025-01-15T10:30:00Z",
"payload": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"title": "Tor",
"session_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"comment": "Toller Schuss vom linken Flügel",
"player_id": ["c3d4e5f6-a7b8-9012-cdef-123456789012"],
"user_id": "d4e5f6a7-b8c9-0123-def1-234567890123"
}
}

Historische Positionsdaten über REST

Nach dem Ende einer Session sind alle Positionsdatensätze eines Trackers über den Standard-Collection-Endpunkt verfügbar:

GET /clubs/{club_id}/trackers/{tracker_id}/positions

Dieser Endpunkt unterstützt die Standard-Paginierungsparameter (limit, next_token, order, from, until). Mit from und until kann der Zeitraum auf eine bestimmte Session eingegrenzt werden.

GET /clubs/a1b2c3d4.../trackers/c3d4e5f6.../positions?from=2025-01-15T12:00:00Z&until=2025-01-15T14:00:00Z&order=asc
Authorization: Bearer <ihr-firebase-jwt>

Jedes Element der Antwort hat dieselbe Struktur wie eine Live-WebSocket-Positionsnachricht.