If the command you need is not in python-OBDs tables, you can create a new
OBDCommand object. The constructor accepts the following arguments (each will become a property).
|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 (
|fast (optional)||bool||Allows python-OBD to alter this command for efficieny (
|header (optional)||string||If set, use a custom header instead of the defalut one (7E0)|
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.data # only operate on a single message d = d[2:] # chop off mode and PID bytes 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 4, \ # number of return bytes to expect rpm, \ # decoding function ECU.ENGINE, \ # (optional) ECU filter True) # (optional) allow a "01" to be added for speed
By default, custom commands will be treated as "unsupported by the vehicle". There are two ways to handle this:
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)
Here are some details on the less intuitive fields of an OBDCommand:
decoder argument is a function of following form.
def <name>(<list_of_messages>): ... return <value>
The return value of your decoder will be loaded into the
OBDResponse.value field. Decoders are given a list of
Message objects as an argument. If your decoder is called, this list is garaunteed to have at least one message object. Each
Message object has a
data property, which holds a parsed bytearray, and is also garauteed to have the number of bytes specified by the command. This bytearray includes any mode and PID bytes in the vehicle's response.
NOTE: If you are transitioning from an older version of Python-OBD (where decoders were given raw hex strings as arguments), you can use the
Message.hex() function as a patch.
def <name>(messages): _hex = messages.hex() ... return <value>
You can also access the original string sent by the adapter using the
ecu argument is a constant used to filter incoming messages. Some commands may listen to multiple ECUs (such as DTC decoders), where others may only be concerned with the engine (such as RPM). Currently, python-OBD can only distinguish the engine, but this list may be expanded over time:
fast argument tells python-OBD whether it is safe to append a
"01" to the end of the command. This will instruct the adapter to return the first response it recieves, rather than waiting for more (and eventually reaching a timeout). This can speed up requests significantly, and is enabled for most of python-OBDs internal commands. However, for unusual commands, it is safest to leave this disabled.
header argument tells python-OBD to use a custom header when querying the command. If not set, python-OBD assumes that the default 7E0 header is needed for querying the command. The switch between default and custom header (and vice versa) is automatically done by python-OBD.