Skip to content

Latest commit

 

History

17 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OpenCLI Compliant

Follow F1 Live Timing Telemetry in the Terminal

go run ./cmd/tui

TUI GIF

F1 Live Timing Capture and Replay

This repository can record raw F1 Live Timing SignalR events to SQLite and expose a recorded session through a local SignalR-compatible replay server.

The recorder does not merge reference messages and deltas. It stores each raw event independently with its sequence number and receive timestamp.

Prerequisites

  • Go 1.26 or newer
  • Network access to the F1 Live Timing service when recording

Record a Session

Start the recorder before or during a live F1 session:

go run ./cmd/recorder -database f1-livetiming.db

The default database file is f1-livetiming.db. You can provide another path:

go run ./cmd/recorder -database data/monza-practice.db

The recorder prints the generated session ID when it starts:

recording live timing to f1-livetiming.db (session 20260902T212436.123456789Z)

Save this session ID. It is required to start the replay server.

Stop recording with Ctrl+C. Events are written as they arrive. If SQLite temporarily fails, the recorder retries each write and then drops the event after the retry limit; dropped sequence numbers are logged so the loss is visible.

Start the Replay Server

Start the local SignalR-compatible server using the database and session ID from the recording step:

go run ./cmd/replay \
  -database f1-livetiming.db \
  -session 20260902T212436.123456789Z \
  -address :8080

The server listens at:

http://localhost:8080

Each subscriber gets its own replay iterator, so every new subscriber receives the session from its first stored event. Subscribers do not share replay position.

Connect and Log Replayed Events

A Go subscriber can connect to the replay server through the same thin client used for the live F1 service:

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/bcdxn/f1/livetiming"
)

func main() {
    ctx := context.Background()

    client := livetiming.NewClient(
        livetiming.WithBaseURL("http://localhost:8080"),
        livetiming.UnsafeWithoutTLS(),
    )

    events, err := client.Stream(ctx)
    if err != nil {
        log.Fatal(err)
    }

    for event := range events {
        if event.Err != nil {
            log.Fatal(event.Err)
        }
        fmt.Println(string(event.Data))
    }
}

The client performs the SignalR handshake and subscription automatically. The replayed payloads are the original raw JSON SignalR messages, emitted in their recorded order.

Replay Faster

Set the speed query parameter for an individual WebSocket subscriber. A speed of 1 uses the original timing, 2 is twice as fast, and 10 is ten times as fast:

client := livetiming.NewClient(
    livetiming.WithBaseURL("http://localhost:8080"),
    livetiming.UnsafeWithoutTLS(),
    livetiming.WithWebSocketQuery("speed", "10"),
)

The server applies this speed independently per subscriber. One subscriber can use real-time playback while another uses accelerated playback.

The speed must be a positive finite number. If it is omitted, the server uses speed 1.

Multiple Subscribers

Create one client per consumer, or call Stream independently for each consumer. Each connection negotiates separately and starts at the beginning of the selected recording:

replay server
    |-- subscriber A: speed=1
    |-- subscriber B: speed=10
    `-- subscriber C: speed=100

Run the Timing TUI

The TUI reconstructs timing state in memory and uses the same client for live and replay connections. Start the replay server with a session from one of the recordings in data/, then connect the TUI at an accelerated speed:

go run ./cmd/replay \
    -database data/monza-practice.db \
    -session <session-id> \
    -address :8080

go run ./cmd/tui \
    --mode replay \
    --address http://localhost:8080 \
    --speed 10

Use q or Ctrl+C to exit; use j/k, arrow keys, or page keys to navigate race-control messages. Replay is the deterministic development path: inspect the standings, mini-sectors, status, weather, and race-control ticker, then repeat the run after any rendering or state correction. Live mode uses the default F1 service:

go run ./cmd/tui --mode live

The dashboard selects its timing table by session: free practice and testing use the existing mini-sector view, qualifying and sprint qualifying show best-lap sectors plus Q1/Q2/Q3 columns, and races and sprint races show interval, last lap, sectors, tyre, and best lap. The repository's captured sessions are practice sessions; qualifying Q1/Q2/Q3 rendering is covered by deterministic synthetic fixtures until a qualifying capture is available.

Run the reducer and view tests independently while iterating:

go test ./tui
go test -race ./...

The replay server is transport-focused. Consumers can log events, decode them into application state, or forward them to another system without changing the stored event stream.

The TUI also displays Team Radio captures below the weather panel. Captures show the driver name and transcript when supplied; otherwise they show message.... Team Radio playback uses pure-Go MP3 decoding through Beep and ALSA output. The devcontainer includes the required ALSA development packages:

go run ./cmd/tui --mode replay --address http://localhost:8080 --speed 10

Team Radio dialogs appear one second before playback, remain visible while the MP3 plays, and stay for two seconds after playback completes.

Useful Commands

Count data-stream events in a recorded session. A single stored database row containing WeatherData, Position, and TimingAppData counts as three events. SignalR control/ping rows are excluded:

go run ./cmd/event-counter \
    -database data/monza-qualifying.db \
    -session 20260905T135428.431444000Z

The command prints both the stream-event count and the number of stored rows.

Run the tests:

go test ./...

Run the race detector:

go test -race ./...

Use a different server port if 8080 is already in use:

go run ./cmd/replay \
  -database f1-livetiming.db \
  -session <session-id> \
  -address :9090

About

Follow F1 sessions in your terminal

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages