Files
Kettenoeler/Reverse-Engineering CAN-Bus

Kettenöler CAN Reverse-Engineering Toolkit

Toolsuite (GUI + CLI) zum Analysieren von CAN-Logs im Kettenöler-Format. Funktionen: Logs splitten (pro CAN-ID), explorative Visualisierung (8-/16-Bit, LE/BE), Batch-Analysen über viele .trace, Ranking plausibler Signale und Range-Fit (lineare Abbildung phys = raw*scale + offset), optional unsupervised ohne vorgegebene Range.


Features (Überblick)

  • Einheitliche GUI (main.py) mit globalem Header (Workdir, Ordnerstruktur, Log-Auswahl).

  • Gemeinsame Trace-Auswahl in allen Trace-Tabs (gleiches Panel, synchronisiert über Tabs):

    • ID Explorer (Multi-Select)
    • Traces Batch-Analyse (Multi-Select oder kompletter Ordner)
    • Range-Fit (Single-Select, supervised oder unsupervised)
  • Splitter: Logs → .trace pro CAN-ID (traces/…, inkl. overview_ids.csv).

  • Einzel-ID-Explorer: Plots aller Byte-Kanäle (8-Bit) und Nachbar-Wortkombis (16-Bit LE/BE) + Kurzstatistik.

  • Batch-Analyzer: Kennzahlen/Plots für alle .trace in einem Ordner, globales Ranking.

  • Range-/Unsupervised-Fit:

    • Supervised: findet scale & offset für Zielbereich [rmin, rmax] (Offset via Intervall-Überdeckung, Scale aus plausibler Menge).
    • Unsupervised: identifiziert „ruhige“ physikalische Kandidaten ohne Range (Smoothness/Varianz/Rate/Spannweite).
  • Output-Hygiene: Ergebnisse stets unter analyze_out/<timestamp>_<tool>/…, optionale Zeitstempel-Unterordner verhindern Überschreiben.

  • Projektdatei (Projekt.json): speichert Workdir, Subfolder, Log-Auswahl, aktiven Traces-Ordner, etc.

  • „Neuester Split“-Button: springt in den jüngsten Unterordner von traces/.


Repository-Komponenten

  • GUI

    • main.py zentrales Frontend mit Tabs (Multi-Log Analyse, ID Explorer, Traces Batch-Analyse, Range-Fit).
  • CLI-Tools

    • can_split_by_id.py Splittet Logs nach CAN-ID → .trace.
    • id_signal_explorer.py Visualisiert/analysiert eine .trace (8-Bit, 16-Bit LE/BE) + summary_stats.csv.
    • trace_batch_analyzer.py Batch-Analyse für viele .trace + globales Ranking.
    • trace_signal_fitter.py Range-Fit (scale/offset) oder Unsupervised-Fit (ohne Range).

Optional/Alt: can_universal_signal_finder.py ursprünglicher Multi-Log-Analyzer (Ranking auf Rohdatenebene).


Installation

  • Python ≥ 3.10

  • Abhängigkeiten: pandas, numpy, matplotlib

  • Setup:

    python3 -m venv .venv
    source .venv/bin/activate      # Windows: .venv\Scripts\activate
    pip install -r requirements.txt
    

Logformat (Kettenöler)

Eine Zeile pro Frame:

<timestamp_ms> <TX|RX> 0x<ID_HEX> <DLC> <byte0> <byte1> ... <byte7>

Beispiel:

123456 RX 0x208 8 11 22 33 44 55 66 77 88

Projekt-/Ordnerstruktur

Ein Workdir bündelt alles zu einem Fahrzeug/Projekt:

<Workdir>/
  Projekt.json           # GUI-Einstellungen
  logs/                  # Input-Logs
  traces/                # per-ID .trace (vom Split)
  analyze_out/           # Ergebnisse; je Run eigener Timestamp-Unterordner

Namenskonventionen

  • Split-Ergebnisse: traces/<timestamp?>/0x<ID>_<ursprungslog>.trace
  • Outputs: analyze_out/<YYYYMMDD_HHMMSS>_<tool>/…

Modelle-Ordner & Git

Wenn du pro Modell arbeitest, z. B.:

models/
  Triumph 2023/
    logs/
    traces/
    analyze_out/
    Projekt.json

Lege in models/ folgende .gitignore ab, damit traces/ und analyze_out/ in jedem Modell-Unterordner ignoriert werden logs/ und .json bleiben versioniert:

*/traces/
*/traces/**
*/analyze_out/
*/analyze_out/**

traces/
traces/**
analyze_out/
analyze_out/**

# optional: typos
*/analyze.out/
*/analyze.out/**
analyze.out/
analyze.out/**

Leere Ordner wie logs/ ggf. mit .gitkeep befüllen.


GUI-Benutzung

python3 main.py

Globaler Header (immer oben)

  • Workdir wählen, Logs scannen → Liste aller gefundenen Logfiles (Multi-Select).
  • Subfolder einstellen: logs, traces, analyze_out (alle parallel im Workdir).
  • Projekt speichern/laden (Projekt.json).
  • Beim Workdir-Wechsel/Projekt-Laden setzt die GUI den aktiven Traces-Ordner automatisch auf traces/ bzw. den jüngsten Unterordner.

Einheitliches Trace-Panel (in allen Trace-Tabs)

  • Links: Liste der .trace
  • Rechts: Traces-Ordner wählen, Workdir/traces, Neuester Split, Refresh, (optional Alle, Keine)
  • Änderungen am Ordner/Liste wirken sofort in allen Tabs.

Tab: Multi-Log Analyse

  • Ranking direkt aus Logs (Include/Exclude-IDs, optional Range mit scale/offset).
  • Output: analyze_out/<ts>_multilog/…
  • Optional: „Jede Logdatei separat“ → je Log eigener Unterordner.

Tab: ID Explorer

  • Split (aus Header-Logauswahl): Logs → .trace nach traces[/<ts>], plus overview_ids.csv. Danach wird der neue Traces-Pfad automatisch aktiviert.

  • Einzel-ID Analyse (Multi-Select):

    • Plots: Byte[0..7] (8-Bit) + LE/BE für Paare (0-1 … 6-7)
    • summary_stats.csv pro Trace
    • Output: analyze_out/<ts>_id_explore/…

Tab: Traces Batch-Analyse

  • Nutzt die gemeinsame Trace-Liste.

  • Ohne Auswahl → kompletter Ordner; mit Auswahl → es wird ein Subset-Ordner gebaut (Hardlinks/Kopie) und nur dieses analysiert.

  • Parameter: --rx-only, scale, offset, range-min/max, top, --plots.

  • Output:

    • je Trace: *_combostats.csv (+ Plots),
    • global: summary_top_combinations.csv
    • unter analyze_out/<ts>_trace_batch/…

Tab: Range-Fit (Single-Select)

  • Zwei Modi:

    1. Supervised (Range-Min/Max gesetzt): findet scale & offset, maximiert Hit-Ratio im Zielbereich. Output: <trace>_encoding_candidates.csv + phys-Plots (Top-N).
    2. Unsupervised (Range leer): bewertet Kandidaten nach Smoothness, Spannweite, Varianz, Rate, Uniqueness. Output: <trace>_unsupervised_candidates.csv + Roh-Plots (Top-N).
  • Optionen: nur RX, negative Scale erlauben (nur supervised), Min. Hit-Ratio, Min. Smoothness, Plots Top-N, Output-Label.

  • Output: analyze_out/<ts>_rangefit/…


CLI-Quickstart

1) Splitten

python3 can_split_by_id.py logs/run1.log logs/run2.log \
  --outdir <Workdir>/traces/20250827_1200 \
  --rx-only

2) Einzel-ID-Explorer

python3 id_signal_explorer.py <Workdir>/traces/20250827_1200/0x208_run1.trace \
  --outdir <Workdir>/analyze_out/20250827_1210_id_explore

3) Batch-Analyse

python3 trace_batch_analyzer.py \
  --traces-dir <Workdir>/traces/20250827_1200 \
  --outdir <Workdir>/analyze_out/20250827_1220_trace_batch \
  --rx-only --plots --top 8 \
  --range-min 31 --range-max 80

4) Range-/Unsupervised-Fit (eine .trace)

# Supervised (z. B. Kühlmittel 31..80°C)
python3 trace_signal_fitter.py <trace> \
  --rmin 31 --rmax 80 \
  --outdir <Workdir>/analyze_out/20250827_1230_rangefit \
  --plots-top 8 --min-hit 0.5 --allow-neg-scale

# Unsupervised (ohne Range)
python3 trace_signal_fitter.py <trace> \
  --outdir <Workdir>/analyze_out/20250827_1240_unsupervised \
  --plots-top 8 --min-smooth 0.2

Algorithmen & Heuristiken

  • Kombinationen:

    • 8-Bit: D0..D7
    • 16-Bit (adjazent): LE & BE für Paare (0,1)…(6,7) (32-Bit & bit-gepackte Felder: auf der Roadmap)
  • Prefilter (für „ruhige“ physikalische Größen): Mindestanzahl Samples, nicht (nahezu) konstant, keine exzessiven Sprünge (p95 der |Δ| relativ zur Spannweite).

  • Range-Fit: Für jeden Kandidaten raw wird über eine Menge plausibler Scales gesucht; für jedes scale wird das Offset via Intervall-Überdeckung bestimmt (rmin ≤ scale*raw_i + offset ≤ rmax). Ranking: Hit-Ratio ↓, dann Glattheit (p95 phys) ↑, Rate ↓, n ↓.

  • Unsupervised: Smoothness = 1 clamp(p95(|Δ|)/span, 0..1); zusätzlich span, var, rate, uniq_ratio. Ranking auf diese Metriken.


Tipps & Troubleshooting

  • Keine Kandidaten (Range-Fit): --min-hit senken, --allow-neg-scale testen, Range prüfen, längeres/variableres Log nutzen.
  • Alles wird gefiltert (Unsupervised): --min-smooth senken; ggf. --rx-only aktivieren.
  • Leere/komische Plots: DLC < 8 → teils keine 16-Bit-Kombis; Frames sehr selten → Rate niedrig.
  • Ordner stets sauber: Zeitstempel-Unterordner aktiv lassen; pro Run eigene Artefakte.

Roadmap

  • 32-Bit-Kombinationen, bit-gepackte Felder.
  • Histogramme, Autokorrelation, Ausreißer-Detektoren.
  • vordefinierte Signal-Profile (z. B. WheelSpeed, CoolantTemp).

Lizenz / Haftung

Nur zu Analyse-/Reverse-Engineering-Zwecken. Nutzung auf eigene Verantwortung.