このドキュメントは以下のドキュメントの翻訳版となります。
Getting Started
Welcome
Python-OBD
は車のオンボード診断ポート(OBD-II)からデータを処理するためのライブラリです。 リアルタイムのセンサーデータをストリーミングしたり、エンジン診断のコードを読み取るなどの診断を実行したり、あるいはラズベリーパイに適しています。 このライブラリは、標準のELM327 OBD-IIアダプタで動作するように設計されています。
注:Python-OBD
は 1.0.0 より下にあります。つまり、API がマイナーバージョン間で変更される可能性があります。 アップデートする前に GitHub のリリース・ページで Changelog を調べてください。
Installation
pypiから最新リリースをインストールします。
$ pip install obd
注意:Linux で Bluetooth アダプタを使用している場合は、Bluetooth スタックをインストールして設定する必要があります。 Debian ベースのシステムでは、これは通常以下のパッケージをインストールすることを意味します:
$ sudo apt-get install bluetooth bluez-utils blueman
Basic Usage
import obd
connection = obd.OBD() # auto-connects to USB or RF port
cmd = obd.commands.SPEED # select an OBD command (sensor)
response = connection.query(cmd) # send the command, and parse the response
print(response.value) # returns unit-bearing values thanks to Pint
print(response.value.to("mph")) # user-friendly unit conversions
OBD 接続は要求応答方式で動作します。 車からデータを取得するには、必要なデータ(RPM、車速など)を問い合わせるコマンドを送信する必要があります。 Python-OBD
では、これは query()
関数で行われます。 コマンド自体はオブジェクトとして表され、obd.commands
の名前または値で参照できます。 query()
関数は、value
プロパティに解析されたデータを含むレスポンスオブジェクトを返します。
Module Layout
import obd
obd.OBD # main OBD connection class
obd.Async # asynchronous OBD connection class
obd.commands # command tables
obd.Unit # unit tables (a Pint UnitRegistry)
obd.OBDStatus # enum for connection status
obd.scan_serial # util function for manually scanning for OBD adapters
obd.OBDCommand # class for making your own OBD Commands
obd.ECU # enum for marking which ECU a command should listen to
obd.logger # the OBD module's root logger (for debug)
License
GNU General Public License V2
OBD Connections
ライブラリをインストールしたら、単に import obd
して、新しい OBD 接続オブジェクトを作成します。 デフォルトでは、python-OBD
は Bluetooth と USB のシリアルポートを(その順番に)スキャンし、見つかった最初の接続を選択します。 ポートは OBD コンストラクタに接続文字列を渡すことで手動で指定することもできます。 また、scan_serial
ヘルパーを使用して、接続されているポートのリストを取得することもできます。
import obd
connection = obd.OBD() # auto connect
# OR
connection = obd.OBD("/dev/ttyUSB0") # create connection with USB 0
# OR
ports = obd.scan_serial() # return list of valid USB or RF ports
print ports # ['/dev/ttyUSB0', '/dev/ttyUSB1']
connection = obd.OBD(ports[0]) # connect to the first port in the list
OBD(portstr=None, baudrate=None,protocol=None,fast=True)
portstr
: ご使用のアダプターの UNIX デバイス・ファイルまたは Windows COM ポートを文字列で渡します。 デフォルト値(None
)はポートを自動的に選択します。
baudrate
: シリアル接続を設定するボーレートを渡します。 この値ははアダプタによって異なります。 典型的な値は 9600、38400、19200、57600、115200 です。デフォルト値(None)は自動的にボーレートを選択します。
protocol
: アダプタと通信するときに指定されたプロトコルを python-OBD
が強制的に使用するようにします。 可能な値については protocol_id()
を参照してください。 デフォルト値(None
)はプロトコルを自動的に選択します。
fast
: コマンドを最適化してから車に送ることができます。 Python-OBD
は現在、このような最適化を2つ行っています。
- キャリッジリターンを送信することで、前のコマンドを繰り返します。
- 応答の制限をコマンドの最後に追加し、N 応答(待機するのではなく最終的にタイムアウトする)を受け取った後でアダプタに返すよう指示します。 この機能は、個々のコマンドに対して有効または無効にすることができます。
高速モードを無効にすると、python-OBDがすべての要求に対して変更されていないコマンドを出力することが保証されます。
query(command, force=True)
OBDCommand
を車に送り、OBDResponse
オブジェクトを返します。 この機能は、車からの応答が受信されるまでブロックされます。 この機能は、指定されたコマンドがあなたの車によってサポートされているかどうかもチェックします。 コマンドがサポートされているとマークされていない場合、コマンドは送信されず、空の OBDResponse
が返されます。 サポートされていないコマンドを強制的に送信するには、便宜のためにオプションの force
パラメーターがあります。
ノンブロッキングクエリについては、Async Querying
を参照してください。
import obd
connection = obd.OBD()
r = connection.query(obd.commands.RPM) # returns the response from the car
status()
接続の状態を反映する文字列を値として返します。 これらの値は、OBDStatus
クラスと比較する必要があります。 それらが文字列であるという事実は、人間の可読性のためだけです。 現在、3つの状態があります。
from obd import OBDStatus
# no connection is made
OBDStatus.NOT_CONNECTED # "Not Connected"
# successful communication with the ELM327 adapter
OBDStatus.ELM_CONNECTED # "ELM Connected"
# successful communication with the ELM327 and the vehicle
OBDStatus.CAR_CONNECTED # "Car Connected"
中間状態の ELM_CONNECTED
は、主にエラーを診断するためのものです。 適切な接続が確立されると、この値に遭遇することは決してありません。
is_connected()
車両との接続が確立されたかどうかを示すブール値を返します。 それは以下と同一です:
connection.status() == OBDStatus.CAR_CONNECTED
port_name()
現在接続されているポート名(“/dev/ttyUSB0
”)の文字列を返します。 接続がない場合、この関数は空の文字列を返します。
supports(command)
コマンドが車両と python-OBD
の両方でサポートされているかどうかを示すブール値を返します。
protocol_id()
protocol_name()
どちらの関数も、現在アダプタで使用されているプロトコルの名前を文字列で返します。 プロトコルIDはアダプタで使用される短い値ですが、プロトコル名は人間が判読可能なものです。 protocol_id()
関数は、OBDコンストラクタのプロトコルフィールドで渡す値を検索するのに適しています(ただし、これは主に高度な使い方です)。 これらの関数はシリアルリクエストを行いません。 接続されていない場合、これらの関数は空文字列を返します。 可能な値は次のとおりです。
ID | Name |
---|---|
1 | SAE J1850 PWM |
2 | SAE J1850 VPW |
3 | AUTO, ISO 9141-2 |
4 | ISO 14230-4(KWP 5BAUD) |
5 | ISO 14230-4(KWP FAST) |
6 | ISO 15765-4(CAN 11/500) |
7 | ISO 15765-4(CAN 29/500) |
8 | ISO 15765-4(CAN 11/250) |
9 | ISO 15764-4(CAN 29/250) |
A | SAE J1939 (CAN 29/250) |
close()
接続を閉じます。
supported_commands
車両でサポートされている一連のコマンドを含むプロパティ。
コマンドをサポートされているものとして手動でマークしたい場合(query(force = True)
を使いたくないとき)、コマンドをこのセットに追加します。 これは python-OBD
の組み込みコマンドを使用する場合は必要ありませんが、カスタムコマンドを作成する場合には便利です。
import obd
connection = obd.OBD()
# manually mark the given command as supported
connection.supported_commands.add(<OBDCommand>)
Command Lookup
OBDCommand
は、車両から情報を照会するために使用されるオブジェクトです。 これらは、クエリを実行するために必要なすべての情報を含み、車の応答をデコードします。 Python-OBD
には、最も一般的なコマンド用のテーブルが組み込まれています。 それらは、名前またはモードと PID によって検索することができます。
import obd
c = obd.commands.RPM
# OR
c = obd.commands['RPM']
# OR
c = obd.commands[1][12] # mode 1, PID 12 (RPM)
commands
テーブルには、特定の名前または PID が存在するかどうかを判断するためのヘルパーメソッドもあります。
has_command(command)
指定された OBDCommand
オブジェクトの存在を内部コマンドテーブルでチェックします。 コマンドは、モードと PID 値で比較されます。
import obd
obd.commands.has_command(obd.commands.RPM) # True
has_name(name)
指定された名前のコマンドを内部コマンドテーブルでチェックします。 これは in
演算子の関数でもあります。
import obd
obd.commands.has_name('RPM') # True
# OR
'RPM' in obd.commands # True
has_pid(mode, pid)
指定されたモードと PID を持つコマンドの内部コマンドテーブルをチェックします。
import obd
obd.commands.has_pid(1, 12) # True
Command Tables
OBD-II adapter (ELM327 commands)
PID | Name | Description | Response Value |
---|---|---|---|
N/A | ELM_VERSION | OBD-II adapter version string | string |
N/A | ELM_VOLTAGE | Voltage detected by OBD-II adapter | Unit.volt |
Mode 01
PID | Name | Description | Response Value |
---|---|---|---|
00 | PIDS_A | Supported PIDs [01-20] | bitarray |
01 | STATUS | Status since DTCs cleared | special |
02 | FREEZE_DTC | DTC that triggered the freeze frame | special |
03 | FUEL_STATUS | Fuel System Status | (string, string) |
04 | ENGINE_LOAD | Calculated Engine Load | Unit.percent |
05 | COOLANT_TEMP | Engine Coolant Temperature | Unit.celsius |
06 | SHORT_FUEL_TRIM_1 | Short Term Fuel Trim - Bank 1 | Unit.percent |
07 | LONG_FUEL_TRIM_1 | Long Term Fuel Trim - Bank 1 | Unit.percent |
08 | SHORT_FUEL_TRIM_2 | Short Term Fuel Trim - Bank 2 | Unit.percent |
0A | FUEL_PRESSURE | Fuel Pressure | Unit.kilopascal |
0B | INTAKE_PRESSURE | Intake Manifold Pressure | Unit.kilopascal |
0C | RPM | Engine RPM | Unit.rpm |
0D | SPEED | Vehicle Speed | Unit.kph |
0E | TIMING_ADVANCE | Timing Advance | Unit.degree |
0F | INTAKE_TEMP | Intake Air Temp | Unit.celsius |
10 | MAF | Air Flow Rate (MAF) | Unit.grams_per_second |
11 | THROTTLE_POS | Throttle Position | Unit.percent |
12 | AIR_STATUS | Secondary Air Status | string |
13 | O2_SENSORS | O2 Sensors Present | special |
14 | O2_B1S1 | O2: Bank 1 - Sensor 1 Voltage | Unit.volt |
15 | O2_B1S2 | O2: Bank 1 - Sensor 2 Voltage | Unit.volt |
16 | O2_B1S3 | O2: Bank 1 - Sensor 3 Voltage | Unit.volt |
17 | O2_B1S4 | O2: Bank 1 - Sensor 4 Voltage | Unit.volt |
18 | O2_B2S1 | O2: Bank 2 - Sensor 1 Voltage | Unit.volt |
19 | O2_B2S2 | O2: Bank 2 - Sensor 2 Voltage | Unit.volt |
1A | O2_B2S3 | O2: Bank 2 - Sensor 3 Voltage | Unit.volt |
1B | O2_B2S4 | O2: Bank 2 - Sensor 4 Voltage | Unit.volt |
1C | OBD_COMPLIANCE | OBD Standards Compliance | string |
1D | O2_SENSORS_ALT | O2 Sensors Present (alternate) | special |
1E | AUX_INPUT_STATUS | Auxiliary input status (power take off) | boolean |
1F | RUN_TIME | Engine Run Time | Unit.second |
20 | PIDS_B | Supported PIDs [21-40] | bitarray |
21 | DISTANCE_W_MIL | Distance Traveled with MIL on | Unit.kilometer |
22 | FUEL_RAIL_PRESSURE_VAC | Fuel Rail Pressure (relative to vacuum) | Unit.kilopascal |
23 | FUEL_RAIL_PRESSURE_DIRECT | Fuel Rail Pressure (direct inject) | Unit.kilopascal |
24 | O2_S1_WR_VOLTAGE | 02 Sensor 1 WR Lambda Voltage | Unit.volt |
25 | O2_S2_WR_VOLTAGE | 02 Sensor 2 WR Lambda Voltage | Unit.volt |
26 | O2_S3_WR_VOLTAGE | 02 Sensor 3 WR Lambda Voltage | Unit.volt |
27 | O2_S4_WR_VOLTAGE | 02 Sensor 4 WR Lambda Voltage | Unit.volt |
28 | O2_S5_WR_VOLTAGE | 02 Sensor 5 WR Lambda Voltage | Unit.volt |
29 | O2_S6_WR_VOLTAGE | 02 Sensor 6 WR Lambda Voltage | Unit.volt |
2A | O2_S7_WR_VOLTAGE | 02 Sensor 7 WR Lambda Voltage | Unit.volt |
2B | O2_S8_WR_VOLTAGE | 02 Sensor 8 WR Lambda Voltage | Unit.volt |
2C | COMMANDED_EGR | Commanded EGR | Unit.percent |
2D | EGR_ERROR | EGR Error | Unit.percent |
2E | EVAPORATIVE_PURGE | Commanded Evaporative Purge | Unit.percent |
2F | FUEL_LEVEL | Fuel Level Input | Unit.percent |
30 | WARMUPS_SINCE_DTC_CLEAR | Number of warm-ups since codes cleared | Unit.count |
31 | DISTANCE_SINCE_DTC_CLEAR | Distance traveled since codes cleared | Unit.kilometer |
32 | EVAP_VAPOR_PRESSURE | Evaporative system vapor pressure | Unit.pascal |
33 | BAROMETRIC_PRESSURE | Barometric Pressure | Unit.kilopascal |
34 | O2_S1_WR_CURRENT | 02 Sensor 1 WR Lambda Current | Unit.milliampere |
35 | O2_S2_WR_CURRENT | 02 Sensor 2 WR Lambda Current | Unit.milliampere |
36 | O2_S3_WR_CURRENT | 02 Sensor 3 WR Lambda Current | Unit.milliampere |
37 | O2_S4_WR_CURRENT | 02 Sensor 4 WR Lambda Current | Unit.milliampere |
38 | O2_S5_WR_CURRENT | 02 Sensor 5 WR Lambda Current | Unit.milliampere |
39 | O2_S6_WR_CURRENT | 02 Sensor 6 WR Lambda Current | Unit.milliampere |
3A | O2_S7_WR_CURRENT | 02 Sensor 7 WR Lambda Current | Unit.milliampere |
3B | O2_S8_WR_CURRENT | 02 Sensor 8 WR Lambda Current | Unit.milliampere |
3C | CATALYST_TEMP_B1S1 | Catalyst Temperature: Bank 1 - Sensor 1 | Unit.celsius |
3D | CATALYST_TEMP_B2S1 | Catalyst Temperature: Bank 2 - Sensor 1 | Unit.celsius |
3E | CATALYST_TEMP_B1S2 | Catalyst Temperature: Bank 1 - Sensor 2 | Unit.celsius |
3F | CATALYST_TEMP_B2S2 | Catalyst Temperature: Bank 2 - Sensor 2 | Unit.celsius |
40 | PIDS_C | Supported PIDs [41-60] | bitarray |
41 | STATUS_DRIVE_CYCLE | Monitor status this drive cycle | special |
42 | CONTROL_MODULE_VOLTAGE | Control module voltage | Unit.volt |
43 | ABSOLUTE_LOAD | Absolute load value | Unit.percent |
44 | COMMANDED_EQUIV_RATIO | Commanded equivalence ratio | Unit.ratio |
45 | RELATIVE_THROTTLE_POS | Relative throttle position | Unit.percent |
46 | AMBIANT_AIR_TEMP | Ambient air temperature | Unit.celsius |
47 | THROTTLE_POS_B | Absolute throttle position B | Unit.percent |
48 | THROTTLE_POS_C | Absolute throttle position C | Unit.percent |
49 | ACCELERATOR_POS_D | Accelerator pedal position D | Unit.percent |
4A | ACCELERATOR_POS_E | Accelerator pedal position E | Unit.percent |
4B | ACCELERATOR_POS_F | Accelerator pedal position F | Unit.percent |
4C | THROTTLE_ACTUATOR | Commanded throttle actuator | Unit.percent |
4D | RUN_TIME_MIL | Time run with MIL on | Unit.minute |
4E | TIME_SINCE_DTC_CLEARED | Time since trouble codes cleared | Unit.minute |
4F | unsupported | unsupported | |
50 | MAX_MAF | Maximum value for mass air flow sensor | Unit.grams_per_second |
51 | FUEL_TYPE | Fuel Type | string |
52 | ETHANOL_PERCENT | Ethanol Fuel Percent | Unit.percent |
53 | EVAP_VAPOR_PRESSURE_ABS | Absolute Evap system Vapor Pressure | Unit.kilopascal |
54 | EVAP_VAPOR_PRESSURE_ALT | Evap system vapor pressure | Unit.pascal |
54 | EVAP_VAPOR_PRESSURE_ALT | Evap system vapor pressure | Unit.pascal |
55 | SHORT_O2_TRIM_B1 | Short term secondary O2 trim - Bank 1 | Unit.percent |
56 | LONG_O2_TRIM_B1 | Long term secondary O2 trim - Bank 1 | Unit.percent |
57 | SHORT_O2_TRIM_B2 | Short term secondary O2 trim - Bank 2 | Unit.percent |
58 | LONG_O2_TRIM_B2 | Long term secondary O2 trim - Bank 2 | Unit.percent |
59 | FUEL_RAIL_PRESSURE_ABS | Fuel rail pressure (absolute) | Unit.kilopascal |
5A | RELATIVE_ACCEL_POS | Relative accelerator pedal position | Unit.percent |
5B | HYBRID_BATTERY_REMAINING | Hybrid battery pack remaining life | Unit.percent |
5C | OIL_TEMP | Engine oil temperature | Unit.celsius |
5D | FUEL_INJECT_TIMING | Fuel injection timing | Unit.degree |
5E | FUEL_RATE | Engine fuel rate | Unit.liters_per_hour |
5F | unsupported | unsupported |
Mode 02
Mode 02 コマンドは Mode 01 と同じですが、最後の DTC が発生した時点(フリーズフレーム)からのメトリックです。 名前でアクセスするには、Mode 01 のコマンド名の前にDTC_を付加します。
import obd
obd.commands.RPM # the Mode 01 command
# vs.
obd.commands.DTC_RPM # the Mode 02 command
Mode 03
Mode 03 には、車両からのすべての診断トラブルコードを要求する単一のコマンド GET_DTC が含まれています。 レスポンスにはコード自体と記述(python-OBD
に記述がある場合)が含まれます。 詳細については、DTC の応答セクションを参照してください。
PID | Name | Description | Response Value |
---|---|---|---|
N/A | GET_DTC | Get Diagnostic Trouble Codes | special |
Mode 04
PID | Name | Description | Response Value |
---|---|---|---|
N/A | CLEAR_DTC | Clear DTCs and Freeze data | N/A |
Mode 06
警告:モード06は実験的なものです。 ソフトウェアテストに合格していますが、実際の車両ではテストされていません。 このモード用のデバッグ出力は非常に高く評価されます。
モード06コマンドは、車両からのさまざまなテスト結果を監視するために使用されます。 このモードのすべてのコマンドは、Monitor Response セクションで説明したのと同じデータ型を返します。 現在、Mode 06 コマンドは CAN プロトコル(ISO 15765-4)に対してのみ実装されています。
表は略
Mode 07
戻り値は、Mode 03 GET_DTC
コマンドと同じ構造体でエンコードされます。
PID | Name | Description | Response Value |
---|---|---|---|
N/A | GET_CURRENT_DTC | Get DTCs from the current/last driving cycle | special |
Responses
query()
関数は OBDResponse
オブジェクトを返します。 これらのオブジェクトには、次のプロパティがあります。
Property | Description |
---|---|
value | The decoded value from the car |
command | The OBDCommand object that triggered this response |
message | The internal Message object containing the raw response from the car |
time | Timestamp of response (as given by time.time() ) |
is_null()
この機能を使用して、応答が空であるかどうかを確認します。 Python-OBD
は、車からデータを取得できないときに空の応答を出します。
r = connection.query(obd.commands.RPM)
if not r.is_null():
print(r.value)
Pint Values
value
プロパティには通常、Pint Quantity
オブジェクトが含まれますが、要求に応じて複雑な構造も保持できます。 Pint の量は、値と単位を1つのクラスにまとめ、「4 秒」や「88 mph」などの物理的な値を表すために使用されます。 これにより、数学や単位変換を行う際に一貫性が得られます。 Pint は、Python-OBD
で obd.Unit
として公開されている単位のレジストリを管理しています。
以下は、Pint の単位と数量で行える一般的な操作です。 詳細については、Pint Documentation を参照してください。
注:以前のバージョンの python-OBD
との下位互換性のために、response.value
の代わりに response.value.magnitude
を使用してください
import obd
>>> response.value
<Quantity(100, 'kph')>
# get the raw python datatype
>>> response.value.magnitude
100
# converts quantities to strings
>>> str(response.value)
'100 kph'
# convert strings to quantities
>>> obd.Unit("100 kph")
<Quantity(100, 'kph')>
# handles conversions nicely
>>> response.value.to('mph')
<Quantity(62.13711922373341, 'mph')>
# scaler math
>>> response.value / 2
<Quantity(50.0, 'kph')>
# non-scaler math requires you to specify units yourself
>>> response.value + (20 * obd.Unit.kph)
<Quantity(120, 'kph')>
# non-scaler math with different units
# handles unit conversions transparently
>>> response.value + (20 * obd.Unit.mph)
<Quantity(132.18688, 'kph')>
Status
status コマンドは、故障インジケータライト(チェックエンジンライト)、スローされるトラブルコードの数、およびエンジンのタイプに関する情報を返します。
response.value.MIL # boolean for whether the check-engine is lit
response.value.DTC_count # number (int) of DTCs being thrown
response.value.ignition_type # "spark" or "compression"
status コマンドは、さまざまなシステムテストの可用性とステータスに関する情報も提供します。 これらは StatusTest
オブジェクトとして公開され、名前付きプロパティに読み込まれます。 各テストオブジェクトには、可用性と完了のためのブーリアンフラグがあります。
response.value.MISFIRE_MONITORING.available # boolean for test availability
response.value.MISFIRE_MONITORING.complete # boolean for test completion
以下は、python-OBDが報告するすべてのテスト名です:
Tests |
---|
MISFIRE_MONITORING |
FUEL_SYSTEM_MONITORING |
COMPONENT_MONITORING |
CATALYST_MONITORING |
HEATED_CATALYST_MONITORING |
EVAPORATIVE_SYSTEM_MONITORING |
SECONDARY_AIR_SYSTEM_MONITORING |
OXYGEN_SENSOR_MONITORING |
OXYGEN_SENSOR_HEATER_MONITORING |
EGR_VVT_SYSTEM_MONITORING |
NMHC_CATALYST_MONITORING |
NOX_SCR_AFTERTREATMENT_MONITORING |
BOOST_PRESSURE_MONITORING |
EXHAUST_GAS_SENSOR_MONITORING |
PM_FILTER_MONITORING |
Diagnostic Trouble Codes(DTCs)
各 DTC は、DTC コードと記述(Python-OBD
に1つがある場合)を含むタプルで表されます。 複数の DTC を返すコマンドの場合は、リストが使用されます。
# obd.commands.GET_DTC
response.value = [
("P0104", "Mass or Volume Air Flow Circuit Intermittent"),
("B0003", ""), # unknown error code, it's probably vehicle-specific
("C0123", "")
]
# obd.commands.FREEZE_DTC
response.value = ("P0104", "Mass or Volume Air Flow Circuit Intermittent")
Fuel Status
燃料の状態は、第1および第2の燃料システムの状態を示す2つのストリングのタプルである。 ほとんどの車には1つのシステムしかないので、2番目の要素は空の文字列になる可能性が高いです。 可能な燃料状態は次のとおりです。
Fuel Status |
---|
"" |
"Open loop due to insufficient engine temperature" |
"Closed loop, using oxygen sensor feedback to determine fuel mix" |
"Open loop due to engine load OR fuel cut due to deceleration" |
"Open loop due to system failure" |
"Closed loop, using at least one oxygen sensor but there is a fault in the feedback system" |
Air Status
空気の状態は、次の文字列のいずれかになります。
Air Status |
---|
"Upstream" |
"Downstream of catalytic converter" |
"From the outside atmosphere or off" |
"Pump commanded on for diagnostics" |
Oxygen Sensors Present
センサーの存在のブール値を保持するタプル(バンクとセンサー番号を表す)の 2 次元構造を返します。
# obd.commands.O2_SENSORS
response.value = (
(), # bank 0 is invalid, this is merely for correct indexing
(True, True, True, False), # bank 1
(False, False, False, False) # bank 2
)
# obd.commands.O2_SENSORS_ALT
response.value = (
(), # bank 0 is invalid, this is merely for correct indexing
(True, True), # bank 1
(True, False), # bank 2
(False, False), # bank 3
(False, False) # bank 4
)
# example usage:
response.value[1][2] == True # Bank 1, Sensor 2 is present
Monitors (Mode 06 Responses)
すべての Mode 06コマンドは、要求されたセンサのさまざまなテスト結果を保持する Monitor
オブジェクトを返します。 1つのモニター応答は、複数のテストを MonitorTest
オブジェクトの形式で保持できます。 OBD 規格ではいくつかのテストが定義されていますが、車両は常に標準を超えてカスタムテストを実装できます。 Python-OBD
が認識する標準のテストID(TID)は次のとおりです。
TID | Name | Description |
---|---|---|
01 | RTL_THRESHOLD_VOLTAGE | Rich to lean sensor threshold voltage |
02 | LTR_THRESHOLD_VOLTAGE | Lean to rich sensor threshold voltage |
03 | LOW_VOLTAGE_SWITCH_TIME | Low sensor voltage for switch time calculation |
04 | HIGH_VOLTAGE_SWITCH_TIME | High sensor voltage for switch time calculation |
05 | RTL_SWITCH_TIME | Rich to lean sensor switch time |
06 | LTR_SWITCH_TIME | Lean to rich sensor switch time |
07 | MIN_VOLTAGE | Minimum sensor voltage for test cycle |
08 | MAX_VOLTAGE | Maximum sensor voltage for test cycle |
09 | TRANSITION_TIME | Time between sensor transitions |
0A | SENSOR_PERIOD | Sensor period |
0B | MISFIRE_AVERAGE | Average misfire counts for last ten driving cycles |
0C | MISFIRE_COUNT | Misfire counts for last/current driving cycles |
テスト結果は、プロパティ名またはTID(obd.commands
表と同じ)によってアクセスできます。 上記の標準テストはすべて存在しますが、一部のテストでは null になることがあります。 MonitorTest.is_null()
関数を使用して、テストが null かどうかを判別します。
response.value.MISFIRE_COUNT
# OR
response.value["MISFIRE_COUNT"]
# OR
response.value[0x0C] # TID for MISFIRE_COUNT
すべての MonitorTest
オブジェクトには、次のプロパティがあります(null テストの場合、None
に設定されます)
result = response.value.MISFIRE_COUNT
result.tid # integer Test ID for this test
result.name # test name
result.desc # test description
result.value # value of the test (will be a Pint value, or in rare cases, a boolean)
result.min # maximum acceptable value
result.max # minimum acceptable value
result.passed # boolean marking the test as passing
エンジンの第2気筒の失火カウントを調べる例を以下に示します。
import obd
connection = obd.OBD()
response = connection.query(obd.commands.MONITOR_MISFIRE_CYLINDER_2)
# in the test results, lookup the result for MISFIRE_COUNT
result = response.value.MISFIRE_COUNT
# check that we got data for this test
if not result.is_null():
print(result.value) # will be a Pint value
else:
print("Misfire count wasn't reported")
Async Connections
標準の query()
関数はブロックされているため、UIイベントループの危険があります。 これを処理するために、python-OBD
には、標準の OBD
オブジェクトの代わりに使用できる Async
接続オブジェクトがあります。 Async
は OBD
のサブクラスであるため、すべての標準メソッドを継承します。 しかし、Async
はスレッド更新ループを制御するためにいくつかを追加します。 このループは、あなたのコマンドの値を車両と最新の状態に保ちます。 このようにして、ユーザーが自動車を query
すると、直ちに最新の応答が返されます。
更新ループは、start()
および stop()
を呼び出すことによって制御されます。 更新用のコマンドを購読するには、要求された OBDCommand
で watch()
を呼び出します。 更新ループはスレッド化されているため、ループが「停止」している間だけコマンドを「監視」することができます。
import obd
connection = obd.Async() # same constructor as 'obd.OBD()'
connection.watch(obd.commands.RPM) # keep track of the RPM
connection.start() # start the async update loop
print connection.query(obd.commands.RPM) # non-blocking, returns immediately
コールバックは watch()
で指定することもでき、利用可能な場合は新しい Response
を返します。
import obd
import time
connection = obd.Async()
# a callback that prints every new value to the console
def new_rpm(r):
print r.value
connection.watch(obd.commands.RPM, callback=new_rpm)
connection.start()
# the callback will now be fired upon receipt of new values
time.sleep(60)
connection.stop()
start()
更新ループを開始します。
stop()
更新ループを停止します。
paused()
更新ループを一時的に停止するためのコンテキストマネージャ(with
ステートメント)で使用するヘルパ関数。 これにより、watch()
と unwatch()
呼び出しを簡単に保護することができます。 一時停止中に更新ループが実行されていた場合は、コンテキストブロックを終了すると再起動されます。 例えば:
with connection.paused() as was_running:
# connection is stopped within this block
# your code here
上記のコードは次のものと等価です:
was_running = connection.running
connection.stop()
# your code here
if was_running:
connection.start()
watch(command, callback=None, force=false)
注意:この関数を呼び出すには、非同期ループを停止または一時停止する必要があります
継続的に更新するコマンドを登録します。 watch()
を呼び出した後、query()
関数はそのコマンドから最新の Response
を返します。 オプションのコールバックも設定することができ、新しい値を受け取ると起動されます。 同じコマンドに対する複数のコールバックは大歓迎です。 オプションの force
パラメーターを指定すると、サポートされていないコマンドが強制的に送信されます。
unwatch(command, callback=None)
注意:この関数を呼び出すには、非同期ループを停止または一時停止する必要があります
コマンドの更新を取り消します。 コールバックが指定されていない場合、そのコマンドのすべてのコールバックは破棄されます。 コールバックが指定されている場合、そのコールバックのみが登録解除されます(他はすべてライブ状態のままです)。
unwatch_all()
注意:この関数を呼び出すには、非同期ループを停止または一時停止する必要があります
すべてのコマンドとコールバックの登録を解除します。
Custom Commands
必要なコマンドがPython-OBDテーブルにない場合は、新しいOBDCommandオブジェクトを作成できます。 コンストラクタは次の引数を受け取ります(それぞれはプロパティになります)。
Argument | Type | Description |
---|---|---|
name | string | (human readability only) |
desc | string | (human readability only) |
command | bytes | OBD command in hex (typically mode + PID) |
bytes | int | Number of bytes expected in response (zero means unknown) |
decoder | callable | Function used for decoding messages from the OBD adapter |
ecu(optional) | ECU | ID of the ECU this command should listen to (ECU.ALL by default) |
fast(optional) | bool | Allows python-OBD to after this command for effecieny (False by default) |
Example
from obd import OBDCommand, Unit
from obd.protocols import ECU
from obd.utils import bytes_to_int
def rpm(messages):
""" decoder for RPM messages """
d = messages[0].data
v = bytes_to_int(d) / 4.0 # helper function for converting byte arrays to ints
return v * Unit.RPM # construct a Pint Quantity
c = OBDCommand("RPM", \ # name
"Engine RPM", \ # description
b"010C", \ # command
2, \ # number of return bytes to expect
rpm, \ # decoding function
ECU.ENGINE, \ # (optional) ECU filter
True) # (optional) allow a "01" to be added for speed
デフォルトでは、カスタムコマンドは「車両によってサポートされていません」と扱われます。 これを処理する方法は2つあります。
o = obd.OBD()
# use the `force` parameter when querying
o.query(c, force=True)
# OR
# add your command to the set of supported commands
o.supported_commands.add(c)
o.query(c)
OBDCommand
のあまり直感的ではないフィールドの詳細は次のとおりです。
OBDCommand.decoder
decoder
引数は、以下の形式の関数です。
def <name>(<list_of_messages>):
...
return <value>
デコーダの戻り値は、OBDResponse.value
フィールドにロードされます。デコーダには引数として Message
オブジェクトのリストが与えられます。デコーダが呼び出された場合、このリストには少なくとも1つの Message
オブジェクトがあることが必要です。各 Message
オブジェクトには、解析された bytearray
を保持する data
プロパティがあります。また、コマンドで指定されたバイト数を取得する必要があります。
注:古いバージョンの Python-OBD
(デコーダが生の16進文字列を引数として渡した)から移行する場合は、Message.hex()
関数をパッチとして使用できます。
def <name>(messages):
_hex = messages[0].hex()
...
return <value>
また、Message.raw()
関数を使用してアダプタから送信された元の文字列にアクセスすることもできます。
OBDCommand.ecu
ecu
引数は、受信メッセージをフィルタリングするために使用される定数です。いくつかのコマンドは、複数の ECU(DTCデコーダなど) を聴くことができ、他のものはエンジン (RPMなど) にのみ関係する場合があります。現在、python-OBD
はエンジンを区別することしかできませんが、このリストは時間の経過と共に拡張される可能性があります:
ECU.ALL
ECU.ALL_KNOWN
ECU.UNKNOWN
ECU.ENGINE
OBDCommand.fast
fast
引数は、コマンドの最後に “01” を追加するのが安全かどうかを python-OBD
に伝えます。これにより、アダプターは受信を待つのではなく、受信した最初の応答を返すように指示します(最終的にはタイムアウトに達する)。これはリクエストを大幅に高速化し、ほとんどの python-OBD
の内部コマンドで有効になります。ただし、異常なコマンドの場合は、これを無効にしておくのが最も安全です。
Debug
python-OBD
は python の組み込みログシステムを使用します。 デフォルトでは、stderr に出力を WARNING レベルで送信するように設定されています。 モジュールのロガーは、モジュールのルートにあるロガー変数を介してアクセスできます。 たとえば、すべてのデバッグメッセージのコンソール印刷を有効にするには、次のスニペットを使用します。
import obd
obd.logger.setLevel(obd.logging.DEBUG) # enables all debug information
または、python-OBD
からすべてのログ出力を無音にする:
import obd
obd.logger.removeHandler(obd.console_handler)
Troubleshooting
Debug Output
Python-OBD
が正しく動作していない場合、まずデバッグ出力を有効にする必要があります。 すべてのデバッグ情報をコンソールに出力するには、接続コードの前に次の行を追加します。
obd.logger.setLevel(obd.logging.DEBUG)
python-OBD
の一般的なログとその意味は次のとおりです。
Successful Connection
[obd] ========================== python-OBD (v0.4.0) ==========================
[obd] Explicit port defined
[obd] Opening serial port '/dev/pts/2'
[obd] Serial port successfully opened on /dev/pts/2
[obd] write: 'ATZ\r\n'
[obd] wait: 1 seconds
[obd] read: 'ATZ\rELM327 v2.1\r'
[obd] write: 'ATE0\r\n'
[obd] read: 'ATE0\rOK\r'
[obd] write: 'ATH1\r\n'
[obd] read: 'OK\r'
[obd] write: 'ATL0\r\n'
[obd] read: 'OK\r'
[obd] write: 'ATSPA8\r\n'
[obd] read: 'OK\r'
[obd] write: '0100\r\n'
[obd] read: '7E8 06 41 00 FF FF FF FF FC\r'
[obd] write: 'ATDPN\r\n'
[obd] read: 'A8\r'
[obd] Connection successful
[obd] querying for supported PIDs (commands)...
[obd] Sending command: 0100: Supported PIDs [01-20]
[obd] write: '0100\r\n'
[obd] read: '7E8 06 41 00 FF FF FF FF FC\r'
[obd] Sending command: 0120: Supported PIDs [21-40]
[obd] write: '0120\r\n'
[obd] read: '7E8 06 41 20 FF FF FF FF FC\r'
[obd] Sending command: 0140: Supported PIDs [41-60]
[obd] write: '0140\r\n'
[obd] read: '7E8 06 41 40 FF FF FF FE FB\r'
[obd] finished querying with 93 commands supported
[obd] =========================================================================
Unresponsive ELM
[obd] ========================== python-OBD (v0.4.0) ==========================
[obd] Explicit port defined
[obd] Opening serial port '/dev/pts/2'
[obd] Serial port successfully opened on /dev/pts/2
[obd] write: 'ATZ\r\n'
[obd] wait: 1 seconds
[obd] __read() found nothing
[obd] __read() found nothing
[obd] __read() never recieved prompt character
[obd] read: ''
[obd] write: 'ATE0\r\n'
[obd] __read() found nothing
[obd] __read() found nothing
[obd] __read() never recieved prompt character
[obd] read: ''
[obd] Connection Error:
[obd] ATE0 did not return 'OK'
[obd] Failed to connect
[obd] =========================================================================
これは、OBD-II アダプタとコンピュータのシリアル接続に問題がある可能性があります。 以下を確認してください:
- Bluetooth デバイスが正しくペア設定されている
- /dev の正しいポートに接続しているか(まったくポートがありません)
- ポートに書き込むための正しいアクセス許可を持っている
scan_serial()
ヘルパー関数を使用して、書き込み可能なポートを判別できます。
import obd
ports = obd.scan_serial() # return list of valid USB or RF ports
print ports # ['/dev/ttyUSB0', '/dev/ttyUSB1']
Unresponsive Vehicle
[obd] ========================== python-OBD (v0.4.0) ==========================
[obd] Explicit port defined
[obd] Opening serial port '/dev/pts/2'
[obd] Serial port successfully opened on /dev/pts/2
[obd] write: 'ATZ\r\n'
[obd] wait: 1 seconds
[obd] read: 'ATZ\rELM327 v2.1\r'
[obd] write: 'ATE0\r\n'
[obd] read: 'ATE0\rOK\r'
[obd] write: 'ATH1\r\n'
[obd] read: 'OK\r'
[obd] write: 'ATL0\r\n'
[obd] read: 'OK\r'
[obd] write: 'ATSPA8\r\n'
[obd] read: 'OK\r'
[obd] write: '0100\r\n'
[obd] read: 'SEARCHING...\rUNABLE TO CONNECT\r'
[obd] write: 'ATDPN\r\n'
[obd] read: '0\r'
[obd] Connection Error:
[obd] ELM responded with unknown protocol
[obd] Failed to connect
[obd] =========================================================================
これは、ELM アダプタと車の接続の問題です。 車両に電源が供給されていること、アダプタと車の OBD-II ポート間の電気的接続は健全であることを確認してください。