transport: transport¶
obd_diag.transport.base¶
.. py:module:: obd_diag.transport.base
Gemeinsame Schnittstelle aller Transporte.
Jede Implementierung (USB-Seriell, Bluetooth, Emulator, Test-Fake) erfüllt dieses
Protocol. Höhere Schichten kennen nur Transport und laufen damit ohne Auto.
.. py:exception:: TransportError :module: obd_diag.transport.base
Bases: :py:class:Exception
Verbindung zum Adapter fehlgeschlagen oder abgebrochen.
.. py:exception:: TransportTimeout :module: obd_diag.transport.base
Bases: :py:class:~obd_diag.transport.base.TransportError
Der Adapter hat nicht rechtzeitig geantwortet.
.. py:class:: Transport(*args, **kwargs) :module: obd_diag.transport.base
Bases: :py:class:~typing.Protocol
.. py:method:: Transport.read_until(terminator, timeout) :module: obd_diag.transport.base
Liest bis einschließlich ``terminator``; wirft ``TransportTimeout`` sonst.
obd_diag.transport.serial¶
.. py:module:: obd_diag.transport.serial
USB-Seriell-Transport über pyserial (z. B. /dev/ttyUSB0).
obd_diag.transport.discovery¶
.. py:module:: obd_diag.transport.discovery
Angeschlossene Adapter finden (USB-Seriell und gebundene Bluetooth-RFCOMM-Geräte).
.. py:class:: PortInfo(device: str, description: str) :module: obd_diag.transport.discovery
Bases: :py:class:object
.. py:function:: list_ports() :module: obd_diag.transport.discovery
USB-Seriell-Adapter und RFCOMM-Geräte, sortiert nach Gerätenamen.
Eingebaute serielle Schnittstellen (/dev/ttyS* ohne USB) werden übergangen,
an ihnen hängt praktisch nie ein OBD-Adapter.
obd_diag.transport.demo¶
.. py:module:: obd_diag.transport.demo
Demo-Fahrzeug: ein simulierter ELM327 mit einem Beispielauto, ganz ohne Adapter.
DemoTransport beantwortet die Befehle, die obd-diag sendet, wie ein ELM327 v1.5 an
einem Mercedes-Benz A 180 d (W177) mit laufendem Motor im Stand. Die Antworten stammen
aus den Mitschnitten der beiden Tests an diesem Auto (tests/fixtures/traces/ mercedes_w177, Diagnose bei laufendem Motor und Live-Daten im Leerlauf): vier
Steuergeräte, ein gespeicherter Code (U1218) mit Freeze Frame, ein offener Readiness-Test
(Abgassensor), FIN mit geschwärzter Seriennummer. Live-Werte laufen die aufgezeichneten
Runden der Reihe nach durch und beginnen danach von vorn.
Nicht aufgezeichnet, aber vom Auto als unterstützt gemeldet und von obd-diag lesbar sind
die PIDs 21, 30, 31, 41, 49, 66, 68, 6C, 6D, 70 und 85; dafür stehen hier erfundene,
plausible Beispielwerte (Leerlauf, warmer Motor). Ebenso erfunden sind die Antworten auf
Mode 09 (Steuergerätenamen, Kalibrierungs-IDs, CVN, Überwachungszähler) und Mode 06
(Testergebnisse): zu beiden gibt es noch keinen Mitschnitt vom Auto.
Auch die Steuergeräte-Adressen (nur mit ATH1 sichtbar) sind angenommen; die
Mitschnitte sind ohne Header entstanden.
Weil der simulierte Adapter auf Byte-Ebene antwortet, laufen im Demo-Modus Treiber,
Parser und Dienste genau wie am echten Auto, einschließlich Freigabeliste und
Mindestpause. Nur Anfragen, für die es keine Daten gibt, beantwortet er mit NO DATA,
unbekannte Adapterbefehle mit ?. Löschen (Mode 04) beantwortet er nie: der Motor läuft,
also bricht clear_codes schon an der Vorbedingung „Drehzahl 0“ ab.
Für den Batterie- und Anlasstest (engine_start=True) steht der Motor zunächst, Zündung
an; CRANK_AT Sekunden nach der ersten Drehzahlabfrage dreht der Anlasser
CRANK_SECONDS lang, danach läuft der Motor wie oben. Die Werte sind erfunden, aber an
die Mitschnitte angelehnt (Adapter misst etwa 0,75 V weniger als das Steuergerät): Ruhe
12,55 V, Einbruch auf 9,5 V laut Adapter (kurz 8,9 V beim Einschalten), Ladung 14,8 V.
.. py:class:: DemoTransport(*, engine_start=False, clock=
Bases: :py:class:object
Simulierter ELM327 am Demo-Fahrzeug; erfüllt das Transport-Protocol.
Zustand wie beim echten Adapter: Echo nach ATZ an, Header, Leerzeichen und
Zeilenvorschub nach AT…-Einstellung, die erste Anfrage nach ATSP0 meldet
SEARCHING.... Jede Instanz beginnt die Live-Runden von vorn.
engine_start: Motor steht und springt von selbst an (Batterietest, siehe Modul);
clock misst dafür die Zeit.
obd_diag.transport.trace¶
.. py:module:: obd_diag.transport.trace
Mitschnitt der Adapter-Kommunikation für die Fehlersuche an echten Fahrzeugen.
TracingTransport legt sich um einen beliebigen Transport und schreibt jede
gesendete und empfangene Byte-Folge mit Zeitstempel in eine Textdatei. Steuer- und
Nicht-ASCII-Zeichen werden sichtbar gemacht (\r, \x00), damit sich die
Rohantworten später exakt als Test-Fixtures nachspielen lassen. Jede Zeile wird
sofort geschrieben, sodass der Mitschnitt auch nach einem Absturz vollständig ist.
Die Datei enthält die FIN, falls sie gelesen wird; sie bleibt lokal.
.. py:function:: new_free_path(directory, prefix, suffix) :module: obd_diag.transport.trace
Freier Dateiname <prefix>-YYYYmmdd-HHMMSS[-n]<suffix>; legt den Ordner an.
.. py:function:: new_trace_path(directory) :module: obd_diag.transport.trace
Freier Dateiname trace-YYYYmmdd-HHMMSS[-n].log; legt den Ordner an.
.. py:function:: escape(data) :module: obd_diag.transport.trace
Bytes als lesbarer, eindeutiger Text: druckbares ASCII bleibt, der Rest wird
als \r, \n oder \xNN geschrieben, \ als \\.
.. py:class:: TracingTransport(inner, log, label=’’) :module: obd_diag.transport.trace
Bases: :py:class:object
Reicht alles an inner weiter und protokolliert es in log.
Zeilenformat: <Sekunden seit Öffnen> <Richtung> <Daten> mit >> für
gesendet, << für empfangen und !! für Fehler.
.. py:class:: FileTracingTransport(inner, path, label=’’) :module: obd_diag.transport.trace
Bases: :py:class:~obd_diag.transport.trace.TracingTransport
Mitschnitt von inner in die Datei path; sie wird angehängt.
.. py:function:: open_serial(port, baudrate, trace=None, *, engine_start=False) :module: obd_diag.transport.trace
Serieller Transport, mit Mitschnitt nach trace, falls angegeben.
DEMO_PORT öffnet statt eines Adapters das Demo-Fahrzeug (transport/demo.py),
mit engine_start mit stehendem Motor, der von selbst anspringt (Batterietest).
.. py:function:: unescape(text) :module: obd_diag.transport.trace
Umkehrung von escape.
.. py:function:: read_trace(path) :module: obd_diag.transport.trace
Liest einen Mitschnitt als Liste von (Richtung, Bytes); Richtung >>/<<.
.. py:class:: ReplayTransport(entries) :module: obd_diag.transport.trace
Bases: :py:class:object
Spielt einen Mitschnitt ab: erwartet die aufgezeichneten Befehle in derselben Reihenfolge und liefert die aufgezeichneten Antworten. So lässt sich eine Sitzung an einem echten Fahrzeug ohne Adapter nachstellen (z. B. als Test-Fixture).