# 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/_/…`, 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: ```bash python3 -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate pip install -r requirements.txt ``` --- ## Logformat (Kettenöler) Eine Zeile pro Frame: ``` 0x ... ``` Beispiel: ``` 123456 RX 0x208 8 11 22 33 44 55 66 77 88 ``` --- ## Projekt-/Ordnerstruktur Ein **Workdir** bündelt alles zu einem Fahrzeug/Projekt: ``` / 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//0x_.trace` * Outputs: `analyze_out/_/…` --- ## 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: ```gitignore */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 ```bash 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/_multilog/…` * Optional: „Jede Logdatei separat“ → je Log eigener Unterordner. ### Tab: ID Explorer * **Split** (aus Header-Logauswahl): Logs → `.trace` nach `traces[/]`, 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/_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/_trace_batch/…` ### Tab: Range-Fit (Single-Select) * **Zwei Modi**: 1. **Supervised** (Range-Min/Max gesetzt): findet `scale` & `offset`, maximiert **Hit-Ratio** im Zielbereich. Output: `_encoding_candidates.csv` + phys-Plots (Top-N). 2. **Unsupervised** (Range leer): bewertet Kandidaten nach **Smoothness**, **Spannweite**, **Varianz**, **Rate**, **Uniqueness**. Output: `_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/_rangefit/…` --- ## CLI-Quickstart ### 1) Splitten ```bash python3 can_split_by_id.py logs/run1.log logs/run2.log \ --outdir /traces/20250827_1200 \ --rx-only ``` ### 2) Einzel-ID-Explorer ```bash python3 id_signal_explorer.py /traces/20250827_1200/0x208_run1.trace \ --outdir /analyze_out/20250827_1210_id_explore ``` ### 3) Batch-Analyse ```bash python3 trace_batch_analyzer.py \ --traces-dir /traces/20250827_1200 \ --outdir /analyze_out/20250827_1220_trace_batch \ --rx-only --plots --top 8 \ --range-min 31 --range-max 80 ``` ### 4) Range-/Unsupervised-Fit (eine `.trace`) ```bash # Supervised (z. B. Kühlmittel 31..80°C) python3 trace_signal_fitter.py \ --rmin 31 --rmax 80 \ --outdir /analyze_out/20250827_1230_rangefit \ --plots-top 8 --min-hit 0.5 --allow-neg-scale # Unsupervised (ohne Range) python3 trace_signal_fitter.py \ --outdir /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.