Rewrite of J1979 to use a pid dictionary rather than if - elif.

This commit is contained in:
JoshuaArking 2019-10-04 12:26:13 -04:00
parent 53c94a832e
commit c01f603cda
1 changed files with 14 additions and 86 deletions

View File

@ -1,97 +1,25 @@
from pandas import DataFrame, Series
from numpy import int8, float16, uint8, uint16
from numpy import dtype
class J1979:
def __init__(self, pid: int, original_data: DataFrame):
def __init__(self, pid: int, original_data: DataFrame, pid_dict: DataFrame):
self.pid: int = pid
self.title: str = ""
self.data: Series = self.process_response_data(original_data)
self.title: str = pid_dict.at[pid, 'title']
self.data: Series = self.process_response_data(original_data, pid_dict)
print("Found " + str(self.data.shape[0]) + " responses for J1979 PID " + str(hex(self.pid)) + ":", self.title)
def process_response_data(self, original_data) -> Series:
# ISO-TP formatted Universal Diagnostic Service (UDS) requests that were sent by the CAN collection device
# during sampling. Request made using Arb ID 0x7DF with DLC of 8. Response should use Arb ID 7E8 (0x7DF + 0x8).
# DataFrame Columns: b0 b1 b2 b3 ... b7
# -- -- -- -- --
# PID 0x0C (12 dec) (Engine RPM): 02 01 0c 00 ... 00
# PID 0x0D (13 dec) (Vehicle Speed): 02 01 0d 00 ... 00
# PID 0x11 (17 dec) (Trottle Pos.): 02 01 11 00 ... 00
# PID 0x61 (97 dec) (Demand % Torque): 02 01 61 00 ... 00
# PID 0x62 (98 dec) (Engine % Torque): 02 01 62 00 ... 00
# PID 0x63 (99 dec) (Ref. Torque): 02 01 63 00 ... 00
# PID 0x8e (142 dec) (Friction Torque): 02 01 8e 00 ... 00
# Responses being managed here should follow the ISO-TP + UDS per-byte format AA BB CC DD .. DD
# BYTE: AA BB CC DD ... DD
# USE: response size (bytes) UDS mode + 0x40 UDS PID response data
# DF COLUMN: b0 b1 b2 b3 ... b7
# Remember that this response data is already converted to decimal. Thus, byte BB = 65 = 0x41 = 0x01 + 0x40.
# If BB isn't 0x41, check what the error code is. Some error code are listed in the UDS chapter of the car
# hacker's handbook available at http://opengarages.org/handbook/ebook/.
if self.pid == 12:
self.title = 'Engine RPM'
# PID is 0x0C: Engine RPM. 2 byte of data AA BB converted using 1/4 RPM per bit: (256*AA+BB)/4
# Min value: 0 Max value: 16,383.75 units: rpm
return Series(data=(256*original_data['b3']+original_data['b4'])/4,
def process_response_data(self, original_data, pid_dict) -> Series:
A = original_data['b3']
B = original_data['b4']
C = original_data['b5']
D = original_data['b6']
try:
return Series(data=pid_dict.at[self.pid, 'formula'](A,B,C,D),
index=original_data.index,
name=self.title,
dtype=float16)
elif self.pid == 13:
self.title = 'Speed km/h'
# PID is 0x0D: Vehicle Speed. 1 byte of data AA using 1km/h per bit: no conversion necessary
# Min value: 0 Max value: 255 (158.44965mph) units: km/h
return Series(data=original_data['b3'],
index=original_data.index,
name=self.title,
dtype=uint8)
elif self.pid == 17:
self.title = 'Throttle %'
# PID is 0x11: Throttle Position. 1 byte of data AA using 100/255 % per bit: AA * 100/255% throttle.
# Min value: 0 Max value: 100 units: %
return Series(data=100 * original_data['b3'] / 255,
index=original_data.index,
name=self.title,
dtype=uint8)
elif self.pid == 97:
self.title = 'Demand Torque %'
# PID is 0x61: Driver's demand engine - percent torque. 1 byte of data AA using 1%/bit with -125 offset
# AA - 125
# Min value: -125 Max value: 130 units: %
return Series(data=original_data['b3'] - 125,
index=original_data.index,
name=self.title,
dtype=int8)
elif self.pid == 98:
self.title = 'Actual Torque %'
# PID is 0x62: Actual engine - percent torque. 1 byte of data AA using 1%/bit with -125 offset
# AA - 125
# Min value: -125 Max value: 130 units: %
return Series(data=original_data['b3'] - 125,
index=original_data.index,
name=self.title,
dtype=int8)
elif self.pid == 99:
self.title = 'Reference Torque Nm'
# PID is 0x63: Engine reference torque. 2 byte of data AA BB using 1 Nm/bit: 256*AA + BB Nm torque
# Min value: 0 Max value: 65,535 units: Nm
return Series(data=256*original_data['b3'] + original_data['b4'],
index=original_data.index,
name=self.title,
dtype=uint16)
elif self.pid == 142:
self.title = 'Engine Friction Torque %'
# PID is 0x8E: Engine Friction - Percent Torque. 1 byte of data AA using 1%/bit with -125 offset. AA - 125
# Min value: -125 Max value: 130 units: %
return Series(data=original_data['b3'] - 125,
index=original_data.index,
name=self.title,
dtype=int8)
else:
# Looks like you were requesting J1979 data with your sniffer that hasn't been implemented in this code.
# Time to do the leg work to expand this class accordingly then re-run the pipeline.
dtype=dtype(pid_dict.at[self.pid, 'formula'](A,B,C,D)))
except:
raise ValueError("Encountered J1979 PID " + str(hex(self.pid)) +
" in Pre-Processing that hasn't been programmed. Expand the J1979 class to handle all "
" in Pre-Processing that hasn't been programmed. Expand the OBD2_pids.csv file to handle all "
"J1979 requests made during data collection.")