8.7 KiB
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 →
.tracepro 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
.tracein einem Ordner, globales Ranking. -
Range-/Unsupervised-Fit:
- Supervised: findet
scale&offsetfür Zielbereich[rmin, rmax](Offset via Intervall-Überdeckung, Scale aus plausibler Menge). - Unsupervised: identifiziert „ruhige“ physikalische Kandidaten ohne Range (Smoothness/Varianz/Rate/Spannweite).
- Supervised: findet
-
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 →
.tracenachtraces[/<ts>], plusoverview_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.csvpro 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/…
- je Trace:
Tab: Range-Fit (Single-Select)
-
Zwei Modi:
- Supervised (Range-Min/Max gesetzt): findet
scale&offset, maximiert Hit-Ratio im Zielbereich. Output:<trace>_encoding_candidates.csv+ phys-Plots (Top-N). - Unsupervised (Range leer): bewertet Kandidaten nach Smoothness, Spannweite, Varianz, Rate, Uniqueness.
Output:
<trace>_unsupervised_candidates.csv+ Roh-Plots (Top-N).
- Supervised (Range-Min/Max gesetzt): findet
-
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)
- 8-Bit:
-
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
rawwird über eine Menge plausibler Scales gesucht; für jedesscalewird 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-hitsenken,--allow-neg-scaletesten, Range prüfen, längeres/variableres Log nutzen. - Alles wird gefiltert (Unsupervised):
--min-smoothsenken; ggf.--rx-onlyaktivieren. - 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.