File Coverage

blib/lib/Device/ELM327.pm
Criterion Covered Total %
statement 12 687 1.7
branch 1 314 0.3
condition 0 108 0.0
subroutine 4 26 15.3
pod 22 22 100.0
total 39 1157 3.3


line stmt bran cond sub pod time code
1             package Device::ELM327;
2            
3 1     1   25278 use strict;
  1         2  
  1         47  
4 1     1   5 use warnings;
  1         2  
  1         34  
5 1     1   2323 use Data::Dumper;
  1         11901  
  1         194  
6            
7             my $null = "\x0";
8             my $lf = "\xa";
9             my $cr = "\xd";
10             my $max_ports_to_search = 64;
11             my @has_sub_command = (0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0);
12            
13             BEGIN
14             {
15 1 50   1   7 if ($^O eq "MSWin32")
16             {
17 0         0 require Win32::SerialPort;
18             }
19             else
20             {
21 1         1454 require Device::SerialPort;
22 1         64509 Device::SerialPort->import(qw( :PARAM :STAT 0.07 ));
23             }
24             }
25            
26             =head1 NAME
27            
28             Device::ELM327 - Methods for reading OBD data with an ELM327 module.
29            
30             =head1 VERSION
31            
32             Version 0.12
33            
34             =cut
35            
36             our $VERSION = '0.12';
37            
38             #*****************************************************************
39            
40             =head1 SYNOPSIS
41            
42             This module provides a Perl interface to a device containing an Elm Electronics ELM327 OBD Interpreter and provides access to the following functions:
43            
44             Read OBD parameters and extract individual values from results.
45             Read OBD Trouble Codes and expand them to their full form.
46             Reset OBD Trouble Codes.
47             Read ELM327 parameters.
48             Write and write the ELM327 data byte.
49             Calibrate ELM327 Voltage.
50             Switchable diagnostic trace and replay function for debugging.
51            
52             The module is written entirely in Perl and works with both Linux and Windows. Depending on which operating system it is run on it uses either the Win32::SerialPort or Device::SerialPort module (which you'll need to install first) so it should work on any platform that supports one of them.
53            
54             use Device::ELM327;
55            
56             my $obd = Device::ELM327->new();
57            
58             # Read status information...
59             $obd->Show("ELM identity");
60             $obd->Show("Vehicle Identification Number");
61             $obd->Show("Engine RPM");
62             $obd->ShowTroubleCodes();
63            
64             undef $obd;
65            
66             =head1 SUBROUTINES/METHODS
67            
68            
69             =head2 new - the constructor for the module.
70            
71             To open the device and have it search for an ELM module:
72            
73             my $obd = Device::ELM327->new();
74            
75             If you know the port name (e.g. 'COM5', '/dev/ttyUSB7' etc) it may be
76             quicker to pass it into the function:
77            
78             my $obd = Device::ELM327->new($port_name);
79            
80             To override the default serial port settings (38400, no parity, 8 data
81             bits, 1 stop bit, no handshaking), you can pass values with or instead
82             of the port name:
83            
84             my $port_details = "/dev/ttyUSB0:115200:none:8:1:none";
85             my $obd = Device::ELM327->new($port_details);
86            
87             The port name may be left out:
88            
89             my $port_details = "115200:none:8:1:none";
90            
91             It is also ok to just define the port name and/or baud rate and use
92             default values for parity, data bits, stop bits and handshake:
93            
94             my $port_details = "/dev/ttyUSB0:115200";
95            
96             or
97            
98             my $port_details = "115200";
99            
100             If you want extra debugging information, it can be enabled by setting
101             $debug_level to a positive number in the range 1 to 3, with more
102             information being displayed as the number increases:
103            
104             my $obd = Device::ELM327->new($port_name, $debug_level);
105            
106             A value of either undef or "" can be passed for the $port_name:
107            
108             my $obd = Device::ELM327->new("", $debug_level);
109            
110             The module can replay previously captured debugging information:
111            
112             my $obd = Device_ELM327->new(undef, $debug_level, $replay_filename);
113            
114             To produce a file containing replayable data simply set $debug_level to
115             1 or higher and pipe the output to a text file:
116            
117             perl test.pl>test_output.txt
118            
119             =cut
120            
121             sub new
122             {
123 0     0 1   my ($class, $port_details, $debug_level, $replay_filename) = @_;
124 0           my $self = bless { }, $class;
125            
126 0           $self->{'version'} = $VERSION;
127            
128 0           $self->{'debug_level'} = 0;
129 0 0         if (defined($debug_level))
130             {
131 0           $self->{'debug_level'} = $debug_level;
132             }
133            
134 0           $self->{'ELM_type'} = "NONE";
135 0           $self->{'bus_type'} = "unknown";
136 0           $self->{'replay_file'} = 0;
137 0           $self->{'replay_response'} = ();
138            
139 0           $self->{'last_command'} = 0;
140 0           $self->{'last_sub_command'} = 0;
141 0           $self->{'response'} = (); # Array of strings, one per line of the response.
142 0           $self->{'response_length'} = 0; # Total number of characters in the response.
143 0           $self->{'results'} = {};
144            
145 0           $self->{'number_of_results'} = 0;
146 0           $self->{'command_addresses'} = [];
147 0           $self->{'command_results'} = [];
148            
149 0           $self->{'trouble_codes'} = [];
150            
151             # Status codes
152 0           $self->{'status_meanings'} = {
153             "ok" => "No errors detected",
154             "Zero length response" => "No data was returned by the ECU",
155             "NO DATA" => "A 'NO DATA' response was returned by the ELM",
156             "STOPPED" => "A 'STOPPED' response was returned by the ELM",
157             "Port not ok" => "The connection to the ELM module failed",
158             "Negative response" => "The vehicle returned a negative response",
159             "Unsupported name" => "The vehicle does not support this value",
160             "Unrecognised name" => "ELM327.pm does not recognise this value",
161             "General Reject" => "Service was rejected. ECU did not specify the reason",
162             "Service Not Supported" => "The ECU does not support the requested service",
163             "Sub Function Not Supported - Invalid Format" => "The ECU does not support the arguments of the request message or the format of the argument bytes do not match the prescribed format for the service",
164             "Busy - Repeat Request" => "The ECU is temporarily too busy to perform the requested operation",
165             "Conditions Not Correct or Request Sequence Error" => "ECU prerequisite conditions not met. Have commands been issued in the correct order?",
166             "Request Correctly Received - Response Pending" => "Correct command and parameters received, but ECU is busy. Response will follow.",
167             };
168            
169            
170             # Negative response codes (received with a 7F Negative Response Service Identifier)
171 0           $self->{'negative_response_codes'} = {
172             "0" => "ok",
173             "10" => "General Reject",
174             "11" => "Service Not Supported",
175             "12" => "Sub Function Not Supported - Invalid Format",
176             "21" => "Busy - Repeat Request",
177             "22" => "Conditions Not Correct or Request Sequence Error",
178             "78" => "Request Correctly Received - Response Pending",
179             };
180            
181            
182             # ISO Standard Test Id's for use with function 6.
183 0           $self->{'Standardized_Test_IDs'} = {
184             "0" => {name => "ISO/SAE reserved"},
185             "1" => {name => "Rich to lean sensor threshold voltage (constant)"},
186             "2" => {name => "Lean to rich sensor threshold voltage (constant)"},
187             "3" => {name => "Low sensor voltage for switch time calculation (constant)"},
188             "4" => {name => "High sensor voltage for switch time calculation (constant)"},
189             "5" => {name => "Rich to lean sensor switch time (calculated)"},
190             "6" => {name => "Lean to rich sensor switch time (calculated)"},
191             "7" => {name => "Minimum sensor voltage for test cycle (calculated)"},
192             "8" => {name => "Maximum sensor voltage for test cycle (calculated)"},
193             "9" => {name => "Time between sensor transitions (calculated)"},
194             "10" => {name => "Sensor period (calculated)"},
195             "11" => {name => "Exponential Weighted Moving Average misfire counts for last ten driving cycles"},
196             "12" => {name => "Misfire counts for last/current driving cycles"},
197             "13" => {name => "Reserved for future standardization"},
198             };
199            
200            
201             # ISO Unit and scaling identifiers
202 0           $self->{'unit_and_scaling_identifiers'} = {
203             "1" => {description => "Raw Value", modifier =>"+0", unit => ""},
204             "2" => {description => "Raw Value", modifier =>"/10", unit => ""},
205             "3" => {description => "Raw Value", modifier =>"/100", unit => ""},
206             "4" => {description => "Raw Value", modifier =>"/100", unit => ""},
207             "5" => {description => "Raw Value", modifier =>"*0.0000305", unit => ""},
208             "6" => {description => "Raw Value", modifier =>"*0.000305", unit => ""},
209             "7" => {description => "rotational frequency", modifier =>"/4", unit => "rpm"},
210             "8" => {description => "Speed", modifier =>"/100", unit => "km/h"},
211             "9" => {description => "Speed", modifier =>"+0", unit => "km/h"},
212             "10" => {description => "Voltage", modifier =>"*0.000122", unit => "V"},
213             "11" => {description => "Voltage", modifier =>"/1000", unit => "V"},
214             "12" => {description => "Voltage", modifier =>"/100", unit => "V"},
215             "13" => {description => "Current", modifier =>"*0.00390625", unit => "mA"},
216             "14" => {description => "Current", modifier =>"*0.001", unit => "mA"},
217             "15" => {description => "Current", modifier =>"*0.01", unit => "mA"},
218             "16" => {description => "Time", modifier =>"+0", unit => "ms"},
219             "17" => {description => "Time", modifier =>"/10", unit => "s"},
220             "18" => {description => "Time", modifier =>"+0", unit => "s"},
221             "19" => {description => "Resistance", modifier =>"/1000", unit => "Ohm"},
222             "20" => {description => "Resistance", modifier =>"/1000", unit => "kOhm"},
223             "21" => {description => "Resistance", modifier =>"+0", unit => "kOhm"},
224             "22" => {description => "Temperature", modifier =>"/10-40", unit => "°C"},
225             "23" => {description => "Pressure (Gauge)", modifier =>"*0.01", unit => "kPa"},
226             "24" => {description => "Pressure (Air pressure)", modifier =>"*0.0117", unit => "kPa"},
227             "25" => {description => "Pressure (Fuel pressure)", modifier =>"*0.079", unit => "kPa"},
228             "26" => {description => "Pressure (Gauge)", modifier =>"+0", unit => "kPa"},
229             "27" => {description => "Pressure (Diesel pressure)", modifier =>"*10", unit => "kPa"},
230             "28" => {description => "Angle", modifier =>"*0.01", unit => "°"},
231             "29" => {description => "Angle", modifier =>"/2", unit => "°"},
232             "30" => {description => "Equivalence ratio (lambda)", modifier =>"*0.0000305", unit => "lambda"},
233             "31" => {description => "Air/Fuel Ratio", modifier =>"*0.05", unit => "A/F ratio"},
234             "32" => {description => "Ratio", modifier =>"*0.0039062", unit => ""},
235             "33" => {description => "Frequency", modifier =>"/1000", unit => "Hz"},
236             "34" => {description => "Frequency", modifier =>"+0", unit => "Hz"},
237             "35" => {description => "Frequency", modifier =>"/1000", unit => "MHz"},
238             "36" => {description => "Counts", modifier =>"+0", unit => "counts"},
239             "37" => {description => "Distance", modifier =>"+0", unit => "km"},
240             "38" => {description => "Voltage per time", modifier =>"/1000", unit => "V/ms"},
241             "39" => {description => "Mass per time", modifier =>"/100", unit => "g/s"},
242             "40" => {description => "Mass per time", modifier =>"+0", unit => "g/s"},
243             "41" => {description => "Pressure per time", modifier =>"/1000", unit => "kPa/s"},
244             "42" => {description => "Mass per time", modifier =>"/1000", unit => "kg/h"},
245             "43" => {description => "Switches", modifier =>"+0", unit => "switches"},
246             "44" => {description => "Mass per cylinder", modifier =>"/100", unit => "g/cyl"},
247             "45" => {description => "Mass per stroke", modifier =>"/100", unit => "mg/stroke"},
248             "46" => {description => "True/False", modifier =>"+0", unit => ""},
249             "47" => {description => "Percent", modifier =>"/100", unit => "%"},
250             "48" => {description => "Percent", modifier =>"*0.001526", unit => "%"},
251             "49" => {description => "volume", modifier =>"/1000", unit => "L"},
252             "50" => {description => "length", modifier =>"*0.0007747", unit => "mm"},
253             "51" => {description => "Equivalence ratio (lambda)", modifier =>"*0.00024414", unit => "lambda"},
254             "52" => {description => "Time", modifier =>"+0", unit => "min"},
255             "53" => {description => "Time", modifier =>"/100", unit => "s"},
256             "54" => {description => "Weight", modifier =>"/100", unit => "g"},
257             "55" => {description => "Weight", modifier =>"/10", unit => "g"},
258             "56" => {description => "Weight", modifier =>"+0", unit => "g"},
259             "57" => {description => "Percent", modifier =>"/100", unit => "%"},
260            
261             "129" => {description => "Raw Value", modifier =>"+0", unit => ""},
262             "130" => {description => "Raw Value", modifier =>"/10", unit => ""},
263             "131" => {description => "Raw Value", modifier =>"/100", unit => ""},
264             "132" => {description => "Raw Value", modifier =>"/1000", unit => ""},
265             "133" => {description => "Raw Value", modifier =>"*0.0000305", unit => ""},
266             "134" => {description => "Raw Value", modifier =>"*0.000305", unit => ""},
267            
268             "138" => {description => "Voltage", modifier =>"*0.000122", unit => "V"},
269             "139" => {description => "Voltage", modifier =>"/1000", unit => "V"},
270             "140" => {description => "Voltage", modifier =>"/100", unit => "V"},
271             "141" => {description => "Current", modifier =>"*0.00390625", unit => "mA"},
272             "142" => {description => "Current", modifier =>"*0.001", unit => "mA"},
273            
274             "144" => {description => "Time", modifier =>"/1000", unit => "s"},
275            
276             "150" => {description => "Temperature", modifier =>"/10", unit => "°C"},
277            
278             "156" => {description => "Angle", modifier =>"*0.01", unit => "°"},
279             "157" => {description => "Angle", modifier =>"/2", unit => "°"},
280            
281             "168" => {description => "Mass per time", modifier =>"+0", unit => "g/s"},
282             "169" => {description => "Pressure per time", modifier =>"/4", unit => "Pa/s"},
283            
284             "175" => {description => "Percent", modifier =>"/100", unit => "%"},
285             "176" => {description => "Percent", modifier =>"*0.003052", unit => "%"},
286             "177" => {description => "Voltage per time", modifier =>"*2", unit => "V/ms"},
287            
288             "253" => {description => "Pressure (absolute)", modifier =>"*0.001", unit => "kPa"},
289             "254" => {description => "Pressure (vacuum)", modifier =>"/4", unit => "Pa"},
290            
291             };
292            
293 0           $self->{'get'} = {
294             "ELM identity" => { command => "AT I", available => 1, result => [{type => "AT", modifier =>"", unit=>""}] },
295             "Stored data byte" => { command => "AT RD", available => 1, result => [{type => "AT", modifier =>"", unit=>""}] },
296             "Input Voltage" => { command => "AT RV", available => 1, result => [{type => "AT", modifier =>'=~ s/V//', unit=>"V"}] },
297             "Ignition state" => { command => "AT IGN", available => 1, result => [{type => "AT", modifier =>"", unit=>""}] },
298            
299             "01 PIDs supported (01-20)" => { command => "01 00", available => 1,
300             result => [
301             {name => "Monitor status since DTCs cleared", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
302             # {name => "DTC that caused required freeze frame data storage", type => "bool_0", modifier => "&64", unit => ""},
303             {name => "Fuel systems status", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
304             {name => "Calculated LOAD Value!", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
305             {name => "Engine Coolant Temperature", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
306             {name => "Short Term Fuel Trim - Bank 1/3", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
307             {name => "Long Term Fuel Trim - Bank 1/3", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
308             {name => "Short Term Fuel Trim - Bank 2/4", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
309            
310             {name => "Long Term Fuel Trim - Bank 2/4", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
311             {name => "Fuel Rail Pressure (gauge)", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
312             {name => "Intake Manifold Absolute Pressure", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
313             {name => "Engine RPM", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
314             {name => "Vehicle Speed Sensor", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
315             {name => "Ignition Timing Advance for #1 Cylinder", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
316             {name => "Intake Air Temperature", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
317             {name => "Air Flow Rate from Mass Air Flow Sensor", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
318            
319             {name => "Absolute Throttle Position", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
320             {name => "Commanded Secondary Air Status", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
321             {name => "Location of oxygen sensors 13", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
322             {name => "Bank 1 - Sensor 1", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
323             {name => "Bank 1 - Sensor 2", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
324            
325             {name => "Bank 1 - Sensor 3", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
326             {name => "Bank 1 - Sensor 4", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
327             {name => "Bank 2 - Sensor 1 13", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
328            
329             {name => "Bank 2 - Sensor 2 13", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
330             {name => "Bank 2 - Sensor 3", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
331             {name => "Bank 2 - Sensor 4", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
332             {name => "Bank 3 - Sensor 2", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
333             {name => "Bank 4 - Sensor 1", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
334             {name => "Bank 4 - Sensor 2", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
335             {name => "OBD requirements to which vehicle is designed", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
336             {name => "Location of oxygen sensors 1D", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
337             {name => "Bank 2 - Sensor 1 1D", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
338             {name => "Bank 2 - Sensor 2 1D", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
339             {name => "Bank 3 - Sensor 1", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
340             {name => "Auxiliary Input Status", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
341             {name => "Time Since Engine Start", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
342             {name => "01 PIDs supported (21-40)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
343             ] },
344            
345             "Monitor status since DTCs cleared" => { command => "01 01",
346             result => [
347             {name => "Number of DTCs stored in this ECU", type => "byte_0", modifier => "&127", unit => ""},
348             {name => "Malfunction Indicator Lamp (MIL) Status", type => "bool_0", modifier => "&128", unit => "off,on"},
349             {name => "Misfire monitoring supported", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
350             {name => "Fuel system monitoring supported", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
351             {name => "Comprehensive component monitoring supported", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
352             {name => "Misfire monitoring complete", type => "bool_1", modifier => "&16", unit => "not completed, completed"},
353             {name => "Fuel system monitoring complete", type => "bool_1", modifier => "&32", unit => "not completed, completed"},
354             {name => "Comprehensive component monitoring complete", type => "bool_1", modifier => "&64", unit => "not completed, completed"},
355             {name => "Catalyst monitoring supported", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
356             {name => "Heated catalyst monitoring supported", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
357             {name => "Evaporative system monitoring supported", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
358             {name => "Secondary air system monitoring supported", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
359             {name => "A/C system refrigerant monitoring supported", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
360             {name => "Oxygen sensor monitoring supported", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
361             {name => "Oxygen sensor heater monitoring supported", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
362             {name => "EGR system monitoring supported", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
363             {name => "Catalyst monitoring complete", type => "bool_3", modifier => "&1", unit => "not completed, completed"},
364             {name => "Heated catalyst monitoring complete", type => "bool_3", modifier => "&2", unit => "not completed, completed"},
365             {name => "Evaporative system monitoring complete", type => "bool_3", modifier => "&4", unit => "not completed, completed"},
366             {name => "Secondary air system monitoring complete", type => "bool_3", modifier => "&8", unit => "not completed, completed"},
367             {name => "A/C system refrigerant monitoring complete", type => "bool_3", modifier => "&16", unit => "not completed, completed"},
368             {name => "Oxygen sensor monitoring complete", type => "bool_3", modifier => "&32", unit => "not completed, completed"},
369             {name => "Oxygen sensor heater monitoring complete", type => "bool_3", modifier => "&64", unit => "not completed, completed"},
370             {name => "EGR system monitoring complete", type => "bool_3", modifier => "&128", unit => "not completed, completed"},
371             ] },
372             # DTC that caused required freeze frame data storage (PID 02) only exists for command 2.
373             "Fuel systems status" => { command => "01 03",
374             result => [
375             {name => "Fuel system 1 status", type => "byte_0", modifier => "&31", unit => "",
376             alternatives => [
377             {value => 1, meaning => "Open loop - has not yet satisfied conditions to go closed loop"},
378             {value => 2, meaning => "Closed loop - using oxygen sensor(s) as feedback for fuel control"},
379             {value => 4, meaning => "Open loop due to driving conditions (e.g., power enrichment, deceleration enleanment)"},
380             {value => 8, meaning => "Open loop - due to detected system fault"},
381             {value => 16, meaning => "Closed loop, but fault with at least one oxygen sensor - may be using single oxygen sensor for fuel control"}
382             ]
383             },
384             {name => "Fuel system 2 status", type => "byte_1", modifier => "&31", unit => "",
385             alternatives => [
386             {value => 1, meaning => "Open loop - has not yet satisfied conditions to go closed loop"},
387             {value => 2, meaning => "Closed loop - using oxygen sensor(s) as feedback for fuel control"},
388             {value => 4, meaning => "Open loop due to driving conditions (e.g., power enrichment, deceleration enleanment)"},
389             {value => 8, meaning => "Open loop - due to detected system fault"},
390             {value => 16, meaning => "Closed loop, but fault with at least one oxygen sensor - may be using single oxygen sensor for fuel control"}
391             ]
392             }
393             ] },
394            
395             "Calculated LOAD Value!" => { command => "01 04", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
396             "Engine Coolant Temperature" => { command => "01 05", result => [{type => "byte_0", modifier => "-40", unit => "°C"}] },
397            
398             "Short Term Fuel Trim - Bank 1/3" => { command => "01 06",
399             result => [
400             {name => "Short Term Fuel Trim - Bank 1", type => "signed_byte_0", modifier => "*100/128", unit => "%"},
401             {name => "Short Term Fuel Trim - Bank 3", type => "signed_byte_1", modifier => "*100/128", unit => "%"},
402             ] },
403            
404             "Long Term Fuel Trim - Bank 1/3" => { command => "01 07",
405             result => [
406             {name => "Long Term Fuel Trim - Bank 1", type => "signed_byte_0", modifier => "*100/128", unit => "%"},
407             {name => "Long Term Fuel Trim - Bank 3", type => "signed_byte_1", modifier => "*100/128", unit => "%"},
408             ] },
409            
410             "Short Term Fuel Trim - Bank 2/4" => { command => "01 08",
411             result => [
412             {name => "Short Term Fuel Trim - Bank 2", type => "signed_byte_0", modifier => "*100/128", unit => "%"},
413             {name => "Short Term Fuel Trim - Bank 4", type => "signed_byte_1", modifier => "*100/128", unit => "%"},
414             ] },
415            
416             "Long Term Fuel Trim - Bank 2/4" => { command => "01 09",
417             result => [
418             {name => "Long Term Fuel Trim - Bank 2", type => "signed_byte_0", modifier => "*100/128", unit => "%"},
419             {name => "Long Term Fuel Trim - Bank 4", type => "signed_byte_1", modifier => "*100/128", unit => "%"},
420             ] },
421            
422            
423             "Fuel Rail Pressure (gauge)" => { command => "01 0A", result => [{type => "byte_0", modifier => "*3", unit => "kPa"}] },
424             "Intake Manifold Absolute Pressure" => { command => "01 0B", result => [{type => "byte_0", modifier => "*1", unit => "kPa"}] },
425             "Engine RPM" => { command => "01 0C", result => [{type => "word_0", modifier => "/4", unit => "RPM"}] },
426             "Vehicle Speed Sensor" => { command => "01 0D", result => [{type => "byte_0", modifier => "+0", unit => "km/h"}] },
427             "Ignition Timing Advance for #1 Cylinder" => { command => "01 0E", result => [{type => "signed_byte_0", modifier => "/2", unit => "°"}] },
428             "Intake Air Temperature" => { command => "01 0F", result => [{type => "byte_0", modifier => "-40", unit => "°C"}] },
429             "Air Flow Rate from Mass Air Flow Sensor" => { command => "01 10", result => [{type => "word_0", modifier => "/100", unit => "g/s"}] },
430             "Absolute Throttle Position" => { command => "01 11", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
431             "Commanded Secondary Air Status" => { command => "01 12", result => [{type => "byte_0", modifier => "*100/255", unit => "",
432             alternatives => [
433             {value => 1, meaning => "upstream of first catalytic converter"},
434             {value => 2, meaning => "downstream of first catalytic converter inlet"},
435             {value => 4, meaning => "atmosphere / off"}
436             ] }
437             ] },
438            
439             "Location of oxygen sensors 13" => { command => "01 13",
440             result => [
441             {name => "Bank 1 - Sensor 1 present", type => "bool_0", modifier => "&1", unit => "not present,present"},
442             {name => "Bank 1 - Sensor 2 present", type => "bool_0", modifier => "&2", unit => "not present,present"},
443             {name => "Bank 1 - Sensor 3 present", type => "bool_0", modifier => "&4", unit => "not present,present"},
444             {name => "Bank 1 - Sensor 4 present", type => "bool_0", modifier => "&8", unit => "not present,present"},
445             {name => "Bank 2 - Sensor 1 present", type => "bool_0", modifier => "&16", unit => "not present,present"},
446             {name => "Bank 2 - Sensor 2 present", type => "bool_0", modifier => "&32", unit => "not present,present"},
447             {name => "Bank 2 - Sensor 3 present", type => "bool_0", modifier => "&64", unit => "not present,present"},
448             {name => "Bank 2 - Sensor 4 present", type => "bool_0", modifier => "&128", unit => "not present,present"}
449             ] },
450            
451             "Bank 1 - Sensor 1" => { command => "01 14",
452             result => [
453             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
454             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
455             ] },
456            
457             "Bank 1 - Sensor 2" => { command => "01 15",
458             result => [
459             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
460             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
461             ] },
462            
463             "Bank 1 - Sensor 3" => { command => "01 16",
464             result => [
465             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
466             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
467             ] },
468            
469             "Bank 1 - Sensor 4" => { command => "01 17",
470             result => [
471             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
472             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
473             ] },
474            
475             "Bank 2 - Sensor 1 13" => { command => "01 18",
476             result => [
477             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
478             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
479             ] },
480            
481             "Bank 2 - Sensor 2 13" => { command => "01 19",
482             result => [
483             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
484             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
485             ] },
486            
487             "Bank 2 - Sensor 3" => { command => "01 1A",
488             result => [
489             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
490             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
491             ] },
492            
493             "Bank 2 - Sensor 4" => { command => "01 1B",
494             result => [
495             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
496             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
497             ] },
498            
499            
500             "Bank 2 - Sensor 1 1D" => { command => "01 16",
501             result => [
502             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
503             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
504             ] },
505            
506             "Bank 2 - Sensor 2 1D" => { command => "01 17",
507             result => [
508             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
509             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
510             ] },
511            
512             "Bank 3 - Sensor 1" => { command => "01 18",
513             result => [
514             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
515             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
516             ] },
517            
518             "Bank 3 - Sensor 2" => { command => "01 19",
519             result => [
520             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
521             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
522             ] },
523            
524             "Bank 4 - Sensor 1" => { command => "01 1A",
525             result => [
526             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
527             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
528             ] },
529            
530             "Bank 4 - Sensor 2" => { command => "01 1B",
531             result => [
532             {name => "Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
533             {name => "Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
534             ] },
535            
536            
537             "OBD requirements to which vehicle is designed" => { command => "01 1C", result => [{type => "byte_0", modifier => "+0", unit => "",
538             alternatives => [
539             {value => 1, meaning => "OBD II (California ARB)"},
540             {value => 2, meaning => "OBD (Federal EPA)"},
541             {value => 3, meaning => "OBD and OBD II"},
542             {value => 4, meaning => "OBD I"},
543             {value => 5, meaning => "Not OBD compliant"},
544             {value => 6, meaning => "EOBD"},
545             {value => 7, meaning => "EOBD and OBD II"},
546             {value => 8, meaning => "EOBD and OBD"},
547             {value => 9, meaning => "EOBD, OBD and OBD II"},
548             {value => 10, meaning => "JOBD"},
549             {value => 11, meaning => "JOBD and OBD II"},
550             {value => 12, meaning => "JOBD and EOBD"},
551             {value => 13, meaning => "JOBD, EOBD, and OBD II"}
552             ] }
553             ] },
554            
555             "Location of oxygen sensors 1D" => { command => "01 1D",
556             result => [
557             {name => "Bank 1 - Sensor 1 present", type => "bool_0", modifier => "&1", unit => "not present,present"},
558             {name => "Bank 1 - Sensor 2 present", type => "bool_0", modifier => "&2", unit => "not present,present"},
559             {name => "Bank 2 - Sensor 1 present", type => "bool_0", modifier => "&4", unit => "not present,present"},
560             {name => "Bank 2 - Sensor 2 present", type => "bool_0", modifier => "&8", unit => "not present,present"},
561             {name => "Bank 3 - Sensor 1 present", type => "bool_0", modifier => "&16", unit => "not present,present"},
562             {name => "Bank 3 - Sensor 2 present", type => "bool_0", modifier => "&32", unit => "not present,present"},
563             {name => "Bank 4 - Sensor 1 present", type => "bool_0", modifier => "&64", unit => "not present,present"},
564             {name => "Bank 4 - Sensor 2 present", type => "bool_0", modifier => "&128", unit => "not present,present"},
565             ] },
566            
567             "Auxiliary Input Status" => { command => "01 1E", result => [{name => "Power Take Off (PTO) Status", type => "bool_0", modifier => "&1", unit => "off,on"}] },
568             "Time Since Engine Start" => { command => "01 1F", result => [{type => "word_0", modifier => "*10", unit => "s"}] },
569            
570             "01 PIDs supported (21-40)" => { command => "01 20",
571             result => [
572             {name => "Distance Travelled While MIL is Activated", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
573             {name => "Fuel Rail Pressure relative to manifold vacuum", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
574             {name => "Fuel Rail Pressure", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
575             {name => "Bank 1 - Sensor 1 (wide range O2S)", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
576             {name => "Bank 1 - Sensor 2 (wide range O2S)", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
577            
578             {name => "Bank 1 - Sensor 3 (wide range O2S)", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
579             {name => "Bank 1 - Sensor 4 (wide range O2S)", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
580             {name => "Bank 2 - Sensor 1 (wide range O2S) 13", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
581             {name => "Bank 2 - Sensor 1 (wide range O2S) 1D", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
582             {name => "Bank 2 - Sensor 2 (wide range O2S) 1D", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
583             {name => "Bank 3 - Sensor 1 (wide range O2S)", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
584            
585             {name => "Bank 2 - Sensor 2 (wide range O2S) 13", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
586             {name => "Bank 2 - Sensor 3 (wide range O2S)", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
587             {name => "Bank 2 - Sensor 4 (wide range O2S)", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
588             {name => "Bank 3 - Sensor 2 (wide range O2S)", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
589             {name => "Bank 4 - Sensor 1 (wide range O2S)", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
590             {name => "Bank 4 - Sensor 2 (wide range O2S)", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
591            
592             {name => "Commanded EGR", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
593             {name => "EGR Error", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
594             {name => "Commanded Evaporative Purge", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
595             {name => "Fuel Level Input", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
596             {name => "Number of warm-ups since diagnostic trouble codes cleared", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
597            
598             {name => "Distance since diagnostic trouble codes cleared", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
599             {name => "Evap System Vapor Pressure", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
600             {name => "Barometric Pressure", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
601             {name => "Bank 1 - Sensor 1 (wide range O2S) current", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
602             {name => "Bank 1 - Sensor 2 (wide range O2S) current", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
603             {name => "Bank 1 - Sensor 3 (wide range O2S) current", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
604             {name => "Bank 1 - Sensor 4 (wide range O2S) current", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
605             {name => "Bank 2 - Sensor 1 (wide range O2S) current 13", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
606            
607             {name => "Bank 2 - Sensor 1 (wide range O2S) current 1D", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
608             {name => "Bank 2 - Sensor 2 (wide range O2S) current 1D", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
609             {name => "Bank 3 - Sensor 1 (wide range O2S) current", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
610            
611             {name => "Bank 2 - Sensor 2 (wide range O2S) current 13", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
612             {name => "Bank 2 - Sensor 3 (wide range O2S) current", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
613             {name => "Bank 2 - Sensor 4 (wide range O2S) current", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
614             {name => "Bank 3 - Sensor 2 (wide range O2S) current", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
615             {name => "Bank 4 - Sensor 1 (wide range O2S) current", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
616             {name => "Bank 4 - Sensor 2 (wide range O2S) current", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
617             {name => "Catalyst Temperature Bank 1, Sensor 1", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
618             {name => "Catalyst Temperature Bank 1, Sensor 2", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
619             {name => "Catalyst Temperature Bank 2, Sensor 1", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
620             {name => "Catalyst Temperature Bank 2, Sensor 2", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
621             {name => "01 PIDs supported (41-60)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
622             ] },
623            
624             "Distance Travelled While MIL is Activated" => { command => "01 21", result => [{type => "word_0", modifier => "+0", unit => "km"}] },
625             "Fuel Rail Pressure relative to manifold vacuum" => { command => "01 22", result => [{type => "word_0", modifier => "*0.079", unit => "kPa"}] },
626             "Fuel Rail Pressure" => { command => "01 23", result => [{type => "word_0", modifier => "*10", unit => "kPa"}] },
627            
628             "Bank 1 - Sensor 1 (wide range O2S)" => { command => "01 24",
629             result => [
630             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
631             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
632             ] },
633            
634             "Bank 1 - Sensor 2 (wide range O2S)" => { command => "01 25",
635             result => [
636             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
637             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
638             ] },
639            
640             "Bank 1 - Sensor 3 (wide range O2S)" => { command => "01 26",
641             result => [
642             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
643             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
644             ] },
645            
646             "Bank 1 - Sensor 4 (wide range O2S)" => { command => "01 27",
647             result => [
648             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
649             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
650             ] },
651            
652             "Bank 2 - Sensor 1 (wide range O2S) 13" => { command => "01 28",
653             result => [
654             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
655             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
656             ] },
657            
658             "Bank 2 - Sensor 2 (wide range O2S) 13" => { command => "01 29",
659             result => [
660             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
661             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
662             ] },
663            
664             "Bank 2 - Sensor 3 (wide range O2S)" => { command => "01 2A",
665             result => [
666             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
667             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
668             ] },
669            
670             "Bank 2 - Sensor 4 (wide range O2S)" => { command => "01 2B",
671             result => [
672             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
673             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
674             ] },
675            
676            
677             "Bank 2 - Sensor 1 (wide range O2S) 1D" => { command => "01 26",
678             result => [
679             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
680             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
681             ] },
682            
683             "Bank 2 - Sensor 2 (wide range O2S) 1D" => { command => "01 27",
684             result => [
685             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
686             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
687             ] },
688            
689             "Bank 3 - Sensor 1 (wide range O2S)" => { command => "01 28",
690             result => [
691             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
692             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
693             ] },
694            
695             "Bank 3 - Sensor 2 (wide range O2S)" => { command => "01 29",
696             result => [
697             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
698             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
699             ] },
700            
701             "Bank 4 - Sensor 1 (wide range O2S)" => { command => "01 2A",
702             result => [
703             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
704             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
705             ] },
706            
707             "Bank 4 - Sensor 2 (wide range O2S)" => { command => "01 2B",
708             result => [
709             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
710             {name => "Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
711             ] },
712            
713             "Commanded EGR" => { command => "01 2C", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
714             "EGR Error" => { command => "01 2D", result => [{type => "signed_byte_0", modifier => "*100/128", unit => "%"}] },
715             "Commanded Evaporative Purge" => { command => "01 2E", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
716             "Fuel Level Input" => { command => "01 2F", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
717             "Number of warm-ups since diagnostic trouble codes cleared" => { command => "01 30", result => [{type => "byte_0", modifier => "+0", unit => ""}] },
718             "Distance since diagnostic trouble codes cleared" => { command => "01 31", result => [{type => "word_0", modifier => "+0", unit => "km"}] },
719             "Evap System Vapor Pressure" => { command => "01 32", result => [{type => "signed_word_0", modifier => "*0.25", unit => "Pa"}] },
720             "Barometric Pressure" => { command => "01 33", result => [{type => "byte_0", modifier => "+0", unit => "kPa"}] },
721            
722             "Bank 1 - Sensor 1 (wide range O2S) current" => { command => "01 34",
723             result => [
724             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
725             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
726             ] },
727            
728             "Bank 1 - Sensor 2 (wide range O2S) current" => { command => "01 35",
729             result => [
730             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
731             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
732             ] },
733            
734             "Bank 1 - Sensor 3 (wide range O2S) current" => { command => "01 36",
735             result => [
736             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
737             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
738             ] },
739            
740             "Bank 1 - Sensor 4 (wide range O2S) current" => { command => "01 37",
741             result => [
742             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
743             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
744             ] },
745            
746             "Bank 2 - Sensor 1 (wide range O2S) current 13" => { command => "01 38",
747             result => [
748             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
749             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
750             ] },
751            
752             "Bank 2 - Sensor 2 (wide range O2S) current 13" => { command => "01 39",
753             result => [
754             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
755             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
756             ] },
757            
758             "Bank 2 - Sensor 3 (wide range O2S) current" => { command => "01 3A",
759             result => [
760             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
761             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
762             ] },
763            
764             "Bank 2 - Sensor 4 (wide range O2S) current" => { command => "01 3B",
765             result => [
766             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
767             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
768             ] },
769            
770            
771             "Bank 2 - Sensor 1 (wide range O2S) current 1D" => { command => "01 36",
772             result => [
773             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
774             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
775             ] },
776            
777             "Bank 2 - Sensor 2 (wide range O2S) current 1D" => { command => "01 37",
778             result => [
779             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
780             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
781             ] },
782            
783             "Bank 3 - Sensor 1 (wide range O2S) current" => { command => "01 38",
784             result => [
785             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
786             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
787             ] },
788            
789             "Bank 3 - Sensor 2 (wide range O2S) current" => { command => "01 39",
790             result => [
791             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
792             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
793             ] },
794            
795             "Bank 4 - Sensor 1 (wide range O2S) current" => { command => "01 3A",
796             result => [
797             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
798             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
799             ] },
800            
801             "Bank 4 - Sensor 2 (wide range O2S) current" => { command => "01 3B",
802             result => [
803             {name => "Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
804             {name => "Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
805             ] },
806            
807             "Catalyst Temperature Bank 1, Sensor 1" => { command => "01 3C", result => [{type => "word_0", modifier => "/10-40", unit => "°C"}] },
808             "Catalyst Temperature Bank 1, Sensor 2" => { command => "01 3D", result => [{type => "word_0", modifier => "/10-40", unit => "°C"}] },
809             "Catalyst Temperature Bank 2, Sensor 1" => { command => "01 3E", result => [{type => "word_0", modifier => "/10-40", unit => "°C"}] },
810             "Catalyst Temperature Bank 2, Sensor 2" => { command => "01 3F", result => [{type => "word_0", modifier => "/10-40", unit => "°C"}] },
811            
812             "01 PIDs supported (41-60)" => { command => "01 40",
813             result => [
814             {name => "Monitor status this driving cycle", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
815             {name => "Control Module Voltage", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
816             {name => "Absolute Load Value", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
817             {name => "Commanded Equivalence Ratio", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
818             {name => "Relative Throttle Position", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
819             {name => "Ambiant Air Temperature", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
820             {name => "Absolute Throttle Position B", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
821             {name => "Absolute Throttle Position C", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
822            
823             {name => "Absolute Throttle Position D", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
824             {name => "Absolute Throttle Position E", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
825             {name => "Absolute Throttle Position F", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
826             {name => "Commanded Throttle Actuator Control", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
827             {name => "Minutes run by the engine while MIL activated", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
828             {name => "Time since diagnostic trouble codes cleared", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
829             {name => "External Test Equipment Configuration Information #1", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
830             {name => "External Test Equipment Configuration Information #2", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
831            
832             {name => "Type of fuel currently being utilized by the vehicle", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
833             {name => "Alcohol Fuel Percentage", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
834             {name => "Absolute Evap System Vapour Pressure", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
835             {name => "Evap System Vapour Pressure", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
836             {name => "Short Term Secondary O2 Sensor Fuel Trim - Bank 1", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
837             {name => "Long Term Secondary O2 Sensor Fuel Trim - Bank 1", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
838             {name => "Short Term Secondary O2 Sensor Fuel Trim - Bank 2", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
839             {name => "Long Term Secondary O2 Sensor Fuel Trim - Bank 2", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
840             {name => "Short Term Secondary O2 Sensor Fuel Trim - Bank 3", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
841             {name => "Long Term Secondary O2 Sensor Fuel Trim - Bank 3", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
842             {name => "Short Term Secondary O2 Sensor Fuel Trim - Bank 4", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
843             {name => "Long Term Secondary O2 Sensor Fuel Trim - Bank 4", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
844            
845             {name => "Fuel Rail Pressure (absolute)", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
846             {name => "Relative Accelerator Pedal Position", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
847             # {name => "", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
848             # {name => "", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
849             # {name => "", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
850             # {name => "", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
851             # {name => "", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
852             # {name => "01 PIDs supported (61-80)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
853             ] },
854            
855            
856             "Monitor status this driving cycle" => { command => "01 41",
857             result => [
858             {name => "Misfire monitoring Enable Status", type => "bool_1", modifier => "&1", unit => "not enabled,enabled"},
859             {name => "Fuel system monitoring Enable Status", type => "bool_1", modifier => "&2", unit => "not enabled,enabled"},
860             {name => "Comprehensive component monitoring Enable Status", type => "bool_1", modifier => "&4", unit => "not enabled,enabled"},
861             {name => "Misfire monitoring Completion Status", type => "bool_1", modifier => "&16", unit => "not completed,completed"},
862             {name => "Fuel system monitoring Completion Status", type => "bool_1", modifier => "&32", unit => "not completed,completed"},
863             {name => "Comprehensive component monitoring Completion Status", type => "bool_1", modifier => "&64", unit => "not completed,completed"},
864             {name => "Catalyst monitoring Enable Status", type => "bool_2", modifier => "&1", unit => "not enabled,enabled"},
865             {name => "Heated catalyst monitoring Enable Status", type => "bool_2", modifier => "&2", unit => "not enabled,enabled"},
866             {name => "Evaporative system monitoring Enable Status", type => "bool_2", modifier => "&4", unit => "not enabled,enabled"},
867             {name => "Secondary air system monitoring Enable Status", type => "bool_2", modifier => "&8", unit => "not enabled,enabled"},
868             {name => "A/C system refrigerant monitoring Enable Status", type => "bool_2", modifier => "&16", unit => "not enabled,enabled"},
869             {name => "Oxygen sensor monitoring Enable Status", type => "bool_2", modifier => "&32", unit => "not enabled,enabled"},
870             {name => "Oxygen sensor heater monitoring Enable Status", type => "bool_2", modifier => "&64", unit => "not enabled,enabled"},
871             {name => "EGR monitoring Enable Status", type => "bool_2", modifier => "&128", unit => "not enabled,enabled"},
872             {name => "Catalyst monitoring Completion Status", type => "bool_3", modifier => "&1", unit => "not completed,completed"},
873             {name => "Heated catalyst monitoring Completion Status", type => "bool_3", modifier => "&2", unit => "not completed,completed"},
874             {name => "Evaporative system monitoring Completion Status", type => "bool_3", modifier => "&4", unit => "not completed,completed"},
875             {name => "Secondary air system monitoring Completion Status", type => "bool_3", modifier => "&8", unit => "not completed,completed"},
876             {name => "A/C system refrigerant monitoring Completion Status", type => "bool_3", modifier => "&16", unit => "not completed,completed"},
877             {name => "Oxygen sensor monitoring Completion Status", type => "bool_3", modifier => "&32", unit => "not completed,completed"},
878             {name => "Oxygen sensor heater monitoring Completion Status", type => "bool_3", modifier => "&64", unit => "not completed,completed"},
879             {name => "EGR monitoring Completion Status", type => "bool_3", modifier => "&128", unit => "not completed,completed"}
880             ] },
881            
882             "Control Module Voltage" => { command => "01 42", result => [{type => "word_0", modifier => "*0.001", unit => "V"}] },
883             "Absolute Load Value" => { command => "01 43", result => [{type => "word_0", modifier => "*100/255", unit => "%"}] },
884             "Commanded Equivalence Ratio" => { command => "01 44", result => [{type => "word_0", modifier => "*0.0000305", unit => ""}] },
885             "Relative Throttle Position" => { command => "01 45", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
886             "Ambiant Air Temperature" => { command => "01 46", result => [{type => "byte_0", modifier => "-40", unit => "°C"}] },
887             "Absolute Throttle Position B" => { command => "01 47", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
888             "Absolute Throttle Position C" => { command => "01 48", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
889             "Accelerator Pedal Position D" => { command => "01 49", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
890             "Accelerator Pedal Position E" => { command => "01 4A", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
891             "Accelerator Pedal Position F" => { command => "01 4B", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
892             "Commanded Throttle Actuator Control" => { command => "01 4C", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
893             "Minutes run by the engine while MIL activated" => { command => "01 4D", result => [{type => "word_0", modifier => "+0", unit => "min"}] },
894             "Time since diagnostic trouble codes cleared" => { command => "01 4E", result => [{type => "word_0", modifier => "+0", unit => "min"}] },
895             "External Test Equipment Configuration Information #1" => { command => "01 4F",
896             result => [
897             {name => "Maximum value for Equivalence Ratio", type => "byte_0", modifier => "+0", unit => ""},
898             {name => "Maximum value for Oxygen Sensor Voltage", type => "byte_1", modifier => "+0", unit => "V"},
899             {name => "Maximum value for Oxygen Sensor Current", type => "byte_2", modifier => "+0", unit => "mA"},
900             {name => "Maximum value for Intake Manifold Absolute Pressure", type => "byte_3", modifier => "+0", unit => "kPa"},
901             ] },
902             "External Test Equipment Configuration Information #2" => { command => "01 50",
903             result => [
904             {name => "Maximum value for Air Flow Rate from Mass Air Flow Sensor", type => "byte_0", modifier => "+0", unit => "g/s"}
905             ] },
906            
907             "Type of fuel currently being utilized by the vehicle" => { command => "01 51", result => [{type => "byte_0", modifier => "+0", unit => "",
908             alternatives => [
909             {value => 1, meaning => "Gasoline/petrol"},
910             {value => 2, meaning => "Methanol"},
911             {value => 3, meaning => "Ethanol"},
912             {value => 4, meaning => "Diesel"},
913             {value => 5, meaning => "Liquefied Petroleum Gas (LPG)"},
914             {value => 6, meaning => "Compressed Natural Gas (CNG)"},
915             {value => 7, meaning => "Propane"},
916             {value => 8, meaning => "Battery/electric"},
917             {value => 9, meaning => "Bi-fuel vehicle using gasoline"},
918             {value => 10, meaning => "Bi-fuel vehicle using methanol"},
919             {value => 11, meaning => "Bi-fuel vehicle using ethanol"},
920             {value => 12, meaning => "Bi-fuel vehicle using LPG"},
921             {value => 13, meaning => "Bi-fuel vehicle using CNG"},
922             {value => 14, meaning => "Bi-fuel vehicle using propane"},
923             {value => 15, meaning => "Bi-fuel vehicle using battery"}
924             ] }
925             ] },
926            
927             "Alcohol Fuel Percentage" => { command => "01 52", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
928             "Absolute Evap System Vapour Pressure" => { command => "01 53", result => [{type => "word_0", modifier => "/200", unit => "kPa"}] },
929             "Evap System Vapour Pressure" => { command => "01 54", result => [{type => "signed_word_0", modifier => "+1", unit => "Pa"}] },
930             "Short Term Secondary O2 Sensor Fuel Trim - Bank 1" => { command => "01 55", result => [{type => "signed_byte_0", modifier => "*100/128", unit => "%"}] },
931             "Long Term Secondary O2 Sensor Fuel Trim - Bank 1" => { command => "01 56", result => [{type => "signed_byte_0", modifier => "*100/128", unit => "%"}] },
932             "Short Term Secondary O2 Sensor Fuel Trim - Bank 2" => { command => "01 57", result => [{type => "signed_byte_0", modifier => "*100/128", unit => "%"}] },
933             "Long Term Secondary O2 Sensor Fuel Trim - Bank 2" => { command => "01 58", result => [{type => "signed_byte_0", modifier => "*100/128", unit => "%"}] },
934            
935             "Short Term Secondary O2 Sensor Fuel Trim - Bank 3" => { command => "01 55", result => [{type => "signed_byte_1", modifier => "*100/128", unit => "%"}] },
936             "Long Term Secondary O2 Sensor Fuel Trim - Bank 3" => { command => "01 56", result => [{type => "signed_byte_1", modifier => "*100/128", unit => "%"}] },
937             "Short Term Secondary O2 Sensor Fuel Trim - Bank 4" => { command => "01 57", result => [{type => "signed_byte_1", modifier => "*100/128", unit => "%"}] },
938             "Long Term Secondary O2 Sensor Fuel Trim - Bank 4" => { command => "01 58", result => [{type => "signed_byte_1", modifier => "*100/128", unit => "%"}] },
939            
940             "Fuel Rail Pressure (absolute)" => { command => "01 59", result => [{type => "word_0", modifier => "*10", unit => "kPa"}] },
941             "Relative Accelerator Pedal Position" => { command => "01 5A", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
942            
943            
944            
945             "02 PIDs supported (01-20)" => { command => "02 00", available => 1,
946             result => [
947             {name => "Freeze frame Monitor status since DTCs cleared", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
948             {name => "DTC that caused required freeze frame data storage", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
949             {name => "Freeze frame Fuel systems status", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
950             {name => "Freeze frame Calculated LOAD Value!", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
951             {name => "Freeze frame Engine Coolant Temperature", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
952             {name => "Freeze frame Short Term Fuel Trim - Bank 1/3", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
953             {name => "Freeze frame Long Term Fuel Trim - Bank 1/3", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
954             {name => "Freeze frame Short Term Fuel Trim - Bank 2/4", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
955            
956             {name => "Freeze frame Long Term Fuel Trim - Bank 2/4", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
957             {name => "Freeze frame Fuel Rail Pressure (gauge)", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
958             {name => "Freeze frame Intake Manifold Absolute Pressure", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
959             {name => "Freeze frame Engine RPM", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
960             {name => "Freeze frame Vehicle Speed Sensor", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
961             {name => "Freeze frame Ignition Timing Advance for #1 Cylinder", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
962             {name => "Freeze frame Intake Air Temperature", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
963             {name => "Freeze frame Air Flow Rate from Mass Air Flow Sensor", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
964            
965             {name => "Freeze frame Absolute Throttle Position", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
966             {name => "Freeze frame Commanded Secondary Air Status", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
967             {name => "Freeze frame Location of oxygen sensors 13", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
968             {name => "Freeze frame Bank 1 - Sensor 1", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
969             {name => "Freeze frame Bank 1 - Sensor 2", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
970            
971             {name => "Freeze frame Bank 1 - Sensor 3", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
972             {name => "Freeze frame Bank 1 - Sensor 4", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
973             {name => "Freeze frame Bank 2 - Sensor 1 13", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
974            
975             {name => "Freeze frame Bank 2 - Sensor 2 13", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
976             {name => "Freeze frame Bank 2 - Sensor 3", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
977             {name => "Freeze frame Bank 2 - Sensor 4", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
978             {name => "Freeze frame Bank 3 - Sensor 2", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
979             {name => "Freeze frame Bank 4 - Sensor 1", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
980             {name => "Freeze frame Bank 4 - Sensor 2", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
981             {name => "Freeze frame OBD requirements to which vehicle is designed", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
982             {name => "Freeze frame Location of oxygen sensors 1D", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
983             {name => "Freeze frame Bank 2 - Sensor 1 1D", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
984             {name => "Freeze frame Bank 2 - Sensor 2 1D", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
985             {name => "Freeze frame Bank 3 - Sensor 1", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
986             {name => "Freeze frame Auxiliary Input Status", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
987             {name => "Freeze frame Time Since Engine Start", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
988             {name => "02 PIDs supported (21-40)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
989             ] },
990            
991             "Freeze frame Monitor status since DTCs cleared" => { command => "02 01",
992             result => [
993             {name => "Freeze frame Number of DTCs stored in this ECU", type => "byte_0", modifier => "&127", unit => ""},
994             {name => "Freeze frame Malfunction Indicator Lamp (MIL) Status", type => "bool_0", modifier => "&128", unit => "off,on"},
995             {name => "Freeze frame Misfire monitoring supported", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
996             {name => "Freeze frame Fuel system monitoring supported", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
997             {name => "Freeze frame Comprehensive component monitoring supported", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
998             {name => "Freeze frame Misfire monitoring complete", type => "bool_1", modifier => "&16", unit => "not completed, completed"},
999             {name => "Freeze frame Fuel system monitoring complete", type => "bool_1", modifier => "&32", unit => "not completed, completed"},
1000             {name => "Freeze frame Comprehensive component monitoring complete", type => "bool_1", modifier => "&64", unit => "not completed, completed"},
1001             {name => "Freeze frame Catalyst monitoring supported", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
1002             {name => "Freeze frame Heated catalyst monitoring supported", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
1003             {name => "Freeze frame Evaporative system monitoring supported", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
1004             {name => "Freeze frame Secondary air system monitoring supported", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
1005             {name => "Freeze frame A/C system refrigerant monitoring supported", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
1006             {name => "Freeze frame Oxygen sensor monitoring supported", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
1007             {name => "Freeze frame Oxygen sensor heater monitoring supported", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
1008             {name => "Freeze frame EGR system monitoring supported", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
1009             {name => "Freeze frame Catalyst monitoring complete", type => "bool_3", modifier => "&1", unit => "not completed, completed"},
1010             {name => "Freeze frame Heated catalyst monitoring complete", type => "bool_3", modifier => "&2", unit => "not completed, completed"},
1011             {name => "Freeze frame Evaporative system monitoring complete", type => "bool_3", modifier => "&4", unit => "not completed, completed"},
1012             {name => "Freeze frame Secondary air system monitoring complete", type => "bool_3", modifier => "&8", unit => "not completed, completed"},
1013             {name => "Freeze frame A/C system refrigerant monitoring complete", type => "bool_3", modifier => "&16", unit => "not completed, completed"},
1014             {name => "Freeze frame Oxygen sensor monitoring complete", type => "bool_3", modifier => "&32", unit => "not completed, completed"},
1015             {name => "Freeze frame Oxygen sensor heater monitoring complete", type => "bool_3", modifier => "&64", unit => "not completed, completed"},
1016             {name => "Freeze frame EGR system monitoring complete", type => "bool_3", modifier => "&128", unit => "not completed, completed"},
1017             ] },
1018            
1019             "DTC that caused required freeze frame data storage" => { command => "02 02", result => [{type => "word_0", modifier => "+0", unit => ""}] },
1020            
1021             "Freeze frame Fuel systems status" => { command => "02 03",
1022             result => [
1023             {name => "Freeze frame Fuel system 1 status", type => "byte_0", modifier => "&31", unit => "",
1024             alternatives => [
1025             {value => 1, meaning => "Open loop - has not yet satisfied conditions to go closed loop"},
1026             {value => 2, meaning => "Closed loop - using oxygen sensor(s) as feedback for fuel control"},
1027             {value => 4, meaning => "Open loop due to driving conditions (e.g., power enrichment, deceleration enleanment)"},
1028             {value => 8, meaning => "Open loop - due to detected system fault"},
1029             {value => 16, meaning => "Closed loop, but fault with at least one oxygen sensor - may be using single oxygen sensor for fuel control"}
1030             ]
1031             },
1032             {name => "Freeze frame Fuel system 2 status", type => "byte_1", modifier => "&31", unit => "",
1033             alternatives => [
1034             {value => 1, meaning => "Open loop - has not yet satisfied conditions to go closed loop"},
1035             {value => 2, meaning => "Closed loop - using oxygen sensor(s) as feedback for fuel control"},
1036             {value => 4, meaning => "Open loop due to driving conditions (e.g., power enrichment, deceleration enleanment)"},
1037             {value => 8, meaning => "Open loop - due to detected system fault"},
1038             {value => 16, meaning => "Closed loop, but fault with at least one oxygen sensor - may be using single oxygen sensor for fuel control"}
1039             ]
1040             }
1041             ] },
1042            
1043             "Freeze frame Calculated LOAD Value!" => { command => "02 04", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1044             "Freeze frame Engine Coolant Temperature" => { command => "02 05", result => [{type => "byte_0", modifier => "-40", unit => "°C"}] },
1045            
1046             "Freeze frame Short Term Fuel Trim - Bank 1/3" => { command => "02 06",
1047             result => [
1048             {name => "Freeze frame Short Term Fuel Trim - Bank 1", type => "signed_byte_0", modifier => "*100/128", unit => "%"},
1049             {name => "Freeze frame Short Term Fuel Trim - Bank 3", type => "signed_byte_1", modifier => "*100/128", unit => "%"},
1050             ] },
1051            
1052             "Freeze frame Long Term Fuel Trim - Bank 1/3" => { command => "02 07",
1053             result => [
1054             {name => "Freeze frame Long Term Fuel Trim - Bank 1", type => "signed_byte_0", modifier => "*100/128", unit => "%"},
1055             {name => "Freeze frame Long Term Fuel Trim - Bank 3", type => "signed_byte_1", modifier => "*100/128", unit => "%"},
1056             ] },
1057            
1058             "Freeze frame Short Term Fuel Trim - Bank 2/4" => { command => "02 08",
1059             result => [
1060             {name => "Freeze frame Short Term Fuel Trim - Bank 2", type => "signed_byte_0", modifier => "*100/128", unit => "%"},
1061             {name => "Freeze frame Short Term Fuel Trim - Bank 4", type => "signed_byte_1", modifier => "*100/128", unit => "%"},
1062             ] },
1063            
1064             "Freeze frame Long Term Fuel Trim - Bank 2/4" => { command => "02 09",
1065             result => [
1066             {name => "Freeze frame Long Term Fuel Trim - Bank 2", type => "signed_byte_0", modifier => "*100/128", unit => "%"},
1067             {name => "Freeze frame Long Term Fuel Trim - Bank 4", type => "signed_byte_1", modifier => "*100/128", unit => "%"},
1068             ] },
1069            
1070            
1071             "Freeze frame Fuel Rail Pressure (gauge)" => { command => "02 0A", result => [{type => "byte_0", modifier => "*3", unit => "kPa"}] },
1072             "Freeze frame Intake Manifold Absolute Pressure" => { command => "02 0B", result => [{type => "byte_0", modifier => "*1", unit => "kPa"}] },
1073             "Freeze frame Engine RPM" => { command => "02 0C", result => [{type => "word_0", modifier => "/4", unit => "RPM"}] },
1074             "Freeze frame Vehicle Speed Sensor" => { command => "02 0D", result => [{type => "byte_0", modifier => "+0", unit => "km/h"}] },
1075             "Freeze frame Ignition Timing Advance for #1 Cylinder" => { command => "02 0E", result => [{type => "signed_byte_0", modifier => "/2", unit => "°"}] },
1076             "Freeze frame Intake Air Temperature" => { command => "02 0F", result => [{type => "byte_0", modifier => "-40", unit => "°C"}] },
1077             "Freeze frame Air Flow Rate from Mass Air Flow Sensor" => { command => "02 10", result => [{type => "word_0", modifier => "/100", unit => "g/s"}] },
1078             "Freeze frame Absolute Throttle Position" => { command => "02 11", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1079             "Freeze frame Commanded Secondary Air Status" => { command => "02 12", result => [{type => "byte_0", modifier => "*100/255", unit => "",
1080             alternatives => [
1081             {value => 1, meaning => "upstream of first catalytic converter"},
1082             {value => 2, meaning => "downstream of first catalytic converter inlet"},
1083             {value => 4, meaning => "atmosphere / off"}
1084             ] }
1085             ] },
1086            
1087             "Freeze frame Location of oxygen sensors 13" => { command => "02 13",
1088             result => [
1089             {name => "Freeze frame Bank 1 - Sensor 1 present", type => "bool_0", modifier => "&1", unit => "not present,present"},
1090             {name => "Freeze frame Bank 1 - Sensor 2 present", type => "bool_0", modifier => "&2", unit => "not present,present"},
1091             {name => "Freeze frame Bank 1 - Sensor 3 present", type => "bool_0", modifier => "&4", unit => "not present,present"},
1092             {name => "Freeze frame Bank 1 - Sensor 4 present", type => "bool_0", modifier => "&8", unit => "not present,present"},
1093             {name => "Freeze frame Bank 2 - Sensor 1 present", type => "bool_0", modifier => "&16", unit => "not present,present"},
1094             {name => "Freeze frame Bank 2 - Sensor 2 present", type => "bool_0", modifier => "&32", unit => "not present,present"},
1095             {name => "Freeze frame Bank 2 - Sensor 3 present", type => "bool_0", modifier => "&64", unit => "not present,present"},
1096             {name => "Freeze frame Bank 2 - Sensor 4 present", type => "bool_0", modifier => "&128", unit => "not present,present"}
1097             ] },
1098            
1099             "Freeze frame Bank 1 - Sensor 1" => { command => "02 14",
1100             result => [
1101             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1102             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1103             ] },
1104            
1105             "Freeze frame Bank 1 - Sensor 2" => { command => "02 15",
1106             result => [
1107             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1108             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1109             ] },
1110            
1111             "Freeze frame Bank 1 - Sensor 3" => { command => "02 16",
1112             result => [
1113             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1114             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1115             ] },
1116            
1117             "Freeze frame Bank 1 - Sensor 4" => { command => "02 17",
1118             result => [
1119             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1120             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1121             ] },
1122            
1123             "Freeze frame Bank 2 - Sensor 1 13" => { command => "02 18",
1124             result => [
1125             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1126             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1127             ] },
1128            
1129             "Freeze frame Bank 2 - Sensor 2 13" => { command => "02 19",
1130             result => [
1131             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1132             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1133             ] },
1134            
1135             "Freeze frame Bank 2 - Sensor 3" => { command => "02 1A",
1136             result => [
1137             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1138             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1139             ] },
1140            
1141             "Freeze frame Bank 2 - Sensor 4" => { command => "02 1B",
1142             result => [
1143             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1144             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1145             ] },
1146            
1147            
1148             "Freeze frame Bank 2 - Sensor 1 1D" => { command => "02 16",
1149             result => [
1150             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1151             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1152             ] },
1153            
1154             "Freeze frame Bank 2 - Sensor 2 1D" => { command => "02 17",
1155             result => [
1156             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1157             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1158             ] },
1159            
1160             "Freeze frame Bank 3 - Sensor 1" => { command => "02 18",
1161             result => [
1162             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1163             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1164             ] },
1165            
1166             "Freeze frame Bank 3 - Sensor 2" => { command => "02 19",
1167             result => [
1168             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1169             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1170             ] },
1171            
1172             "Freeze frame Bank 4 - Sensor 1" => { command => "02 1A",
1173             result => [
1174             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1175             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1176             ] },
1177            
1178             "Freeze frame Bank 4 - Sensor 2" => { command => "02 1B",
1179             result => [
1180             {name => "Freeze frame Oxygen Sensor Output Voltage (Bx-Sy)", type => "byte_0", modifier => "*0.005", unit => "V"},
1181             {name => "Freeze frame Short Term Fuel Trim (Bx-Sy)", type => "byte_1", modifier => "*100/255", unit => "%"}
1182             ] },
1183            
1184            
1185             "Freeze frame OBD requirements to which vehicle is designed" => { command => "02 1C", result => [{type => "byte_0", modifier => "+0", unit => "",
1186             alternatives => [
1187             {value => 1, meaning => "OBD II (California ARB)"},
1188             {value => 2, meaning => "OBD (Federal EPA)"},
1189             {value => 3, meaning => "OBD and OBD II"},
1190             {value => 4, meaning => "OBD I"},
1191             {value => 5, meaning => "Not OBD compliant"},
1192             {value => 6, meaning => "EOBD"},
1193             {value => 7, meaning => "EOBD and OBD II"},
1194             {value => 8, meaning => "EOBD and OBD"},
1195             {value => 9, meaning => "EOBD, OBD and OBD II"},
1196             {value => 10, meaning => "JOBD"},
1197             {value => 11, meaning => "JOBD and OBD II"},
1198             {value => 12, meaning => "JOBD and EOBD"},
1199             {value => 13, meaning => "JOBD, EOBD, and OBD II"}
1200             ] }
1201             ] },
1202            
1203             "Freeze frame Location of oxygen sensors 1D" => { command => "02 1D",
1204             result => [
1205             {name => "Freeze frame Bank 1 - Sensor 1 present", type => "bool_0", modifier => "&1", unit => "not present,present"},
1206             {name => "Freeze frame Bank 1 - Sensor 2 present", type => "bool_0", modifier => "&2", unit => "not present,present"},
1207             {name => "Freeze frame Bank 2 - Sensor 1 present", type => "bool_0", modifier => "&4", unit => "not present,present"},
1208             {name => "Freeze frame Bank 2 - Sensor 2 present", type => "bool_0", modifier => "&8", unit => "not present,present"},
1209             {name => "Freeze frame Bank 3 - Sensor 1 present", type => "bool_0", modifier => "&16", unit => "not present,present"},
1210             {name => "Freeze frame Bank 3 - Sensor 2 present", type => "bool_0", modifier => "&32", unit => "not present,present"},
1211             {name => "Freeze frame Bank 4 - Sensor 1 present", type => "bool_0", modifier => "&64", unit => "not present,present"},
1212             {name => "Freeze frame Bank 4 - Sensor 2 present", type => "bool_0", modifier => "&128", unit => "not present,present"},
1213             ] },
1214            
1215             "Freeze frame Auxiliary Input Status" => { command => "02 1E", result => [{name => "Freeze frame Power Take Off (PTO) Status", type => "bool_0", modifier => "&1", unit => "off,on"}] },
1216             "Freeze frame Time Since Engine Start" => { command => "02 1F", result => [{type => "word_0", modifier => "*10", unit => "s"}] },
1217            
1218             "02 PIDs supported (21-40)" => { command => "02 20",
1219             result => [
1220             {name => "Freeze frame Distance Travelled While MIL is Activated", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
1221             {name => "Freeze frame Fuel Rail Pressure relative to manifold vacuum", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
1222             {name => "Freeze frame Fuel Rail Pressure", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
1223             {name => "Freeze frame Bank 1 - Sensor 1 (wide range O2S)", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
1224             {name => "Freeze frame Bank 1 - Sensor 2 (wide range O2S)", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
1225            
1226             {name => "Freeze frame Bank 1 - Sensor 3 (wide range O2S)", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
1227             {name => "Freeze frame Bank 1 - Sensor 4 (wide range O2S)", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
1228             {name => "Freeze frame Bank 2 - Sensor 1 (wide range O2S) 13", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
1229             {name => "Freeze frame Bank 2 - Sensor 1 (wide range O2S) 1D", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
1230             {name => "Freeze frame Bank 2 - Sensor 2 (wide range O2S) 1D", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
1231             {name => "Freeze frame Bank 3 - Sensor 1 (wide range O2S)", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
1232            
1233             {name => "Freeze frame Bank 2 - Sensor 2 (wide range O2S) 13", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
1234             {name => "Freeze frame Bank 2 - Sensor 3 (wide range O2S)", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
1235             {name => "Freeze frame Bank 2 - Sensor 4 (wide range O2S)", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
1236             {name => "Freeze frame Bank 3 - Sensor 2 (wide range O2S)", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
1237             {name => "Freeze frame Bank 4 - Sensor 1 (wide range O2S)", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
1238             {name => "Freeze frame Bank 4 - Sensor 2 (wide range O2S)", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
1239            
1240             {name => "Freeze frame Commanded EGR", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
1241             {name => "Freeze frame EGR Error", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
1242             {name => "Freeze frame Commanded Evaporative Purge", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
1243             {name => "Freeze frame Fuel Level Input", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
1244             {name => "Freeze frame Number of warm-ups since diagnostic trouble codes cleared", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
1245            
1246             {name => "Freeze frame Distance since diagnostic trouble codes cleared", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
1247             {name => "Freeze frame Evap System Vapor Pressure", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
1248             {name => "Freeze frame Barometric Pressure", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
1249             {name => "Freeze frame Bank 1 - Sensor 1 (wide range O2S) current", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
1250             {name => "Freeze frame Bank 1 - Sensor 2 (wide range O2S) current", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
1251             {name => "Freeze frame Bank 1 - Sensor 3 (wide range O2S) current", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
1252             {name => "Freeze frame Bank 1 - Sensor 4 (wide range O2S) current", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
1253             {name => "Freeze frame Bank 2 - Sensor 1 (wide range O2S) current 13", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
1254            
1255             {name => "Freeze frame Bank 2 - Sensor 1 (wide range O2S) current 1D", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
1256             {name => "Freeze frame Bank 2 - Sensor 2 (wide range O2S) current 1D", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
1257             {name => "Freeze frame Bank 3 - Sensor 1 (wide range O2S) current", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
1258            
1259             {name => "Freeze frame Bank 2 - Sensor 2 (wide range O2S) current 13", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
1260             {name => "Freeze frame Bank 2 - Sensor 3 (wide range O2S) current", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
1261             {name => "Freeze frame Bank 2 - Sensor 4 (wide range O2S) current", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
1262             {name => "Freeze frame Bank 3 - Sensor 2 (wide range O2S) current", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
1263             {name => "Freeze frame Bank 4 - Sensor 1 (wide range O2S) current", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
1264             {name => "Freeze frame Bank 4 - Sensor 2 (wide range O2S) current", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
1265             {name => "Freeze frame Catalyst Temperature Bank 1, Sensor 1", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
1266             {name => "Freeze frame Catalyst Temperature Bank 1, Sensor 2", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
1267             {name => "Freeze frame Catalyst Temperature Bank 2, Sensor 1", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
1268             {name => "Freeze frame Catalyst Temperature Bank 2, Sensor 2", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
1269             {name => "02 PIDs supported (41-60)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
1270             ] },
1271            
1272             "Freeze frame Distance Travelled While MIL is Activated" => { command => "02 21", result => [{type => "word_0", modifier => "+0", unit => "km"}] },
1273             "Freeze frame Fuel Rail Pressure relative to manifold vacuum" => { command => "02 22", result => [{type => "word_0", modifier => "*0.079", unit => "kPa"}] },
1274             "Freeze frame Fuel Rail Pressure" => { command => "02 23", result => [{type => "word_0", modifier => "*10", unit => "kPa"}] },
1275            
1276             "Freeze frame Bank 1 - Sensor 1 (wide range O2S)" => { command => "02 24",
1277             result => [
1278             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1279             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1280             ] },
1281            
1282             "Freeze frame Bank 1 - Sensor 2 (wide range O2S)" => { command => "02 25",
1283             result => [
1284             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1285             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1286             ] },
1287            
1288             "Freeze frame Bank 1 - Sensor 3 (wide range O2S)" => { command => "02 26",
1289             result => [
1290             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1291             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1292             ] },
1293            
1294             "Freeze frame Bank 1 - Sensor 4 (wide range O2S)" => { command => "02 27",
1295             result => [
1296             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1297             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1298             ] },
1299            
1300             "Freeze frame Bank 2 - Sensor 1 (wide range O2S) 13" => { command => "02 28",
1301             result => [
1302             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1303             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1304             ] },
1305            
1306             "Freeze frame Bank 2 - Sensor 2 (wide range O2S) 13" => { command => "02 29",
1307             result => [
1308             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1309             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1310             ] },
1311            
1312             "Freeze frame Bank 2 - Sensor 3 (wide range O2S)" => { command => "02 2A",
1313             result => [
1314             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1315             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1316             ] },
1317            
1318             "Freeze frame Bank 2 - Sensor 4 (wide range O2S)" => { command => "02 2B",
1319             result => [
1320             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1321             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1322             ] },
1323            
1324            
1325             "Freeze frame Bank 2 - Sensor 1 (wide range O2S) 1D" => { command => "02 26",
1326             result => [
1327             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1328             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1329             ] },
1330            
1331             "Freeze frame Bank 2 - Sensor 2 (wide range O2S) 1D" => { command => "02 27",
1332             result => [
1333             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1334             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1335             ] },
1336            
1337             "Freeze frame Bank 3 - Sensor 1 (wide range O2S)" => { command => "02 28",
1338             result => [
1339             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1340             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1341             ] },
1342            
1343             "Freeze frame Bank 3 - Sensor 2 (wide range O2S)" => { command => "02 29",
1344             result => [
1345             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1346             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1347             ] },
1348            
1349             "Freeze frame Bank 4 - Sensor 1 (wide range O2S)" => { command => "02 2A",
1350             result => [
1351             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1352             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1353             ] },
1354            
1355             "Freeze frame Bank 4 - Sensor 2 (wide range O2S)" => { command => "02 2B",
1356             result => [
1357             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1358             {name => "Freeze frame Oxygen Sensor Voltage (Bx-Sy)", type => "word_1", modifier => "*0.000122", unit => "V"}
1359             ] },
1360            
1361             "Freeze frame Commanded EGR" => { command => "02 2C", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1362             "Freeze frame EGR Error" => { command => "02 2D", result => [{type => "signed_byte_0", modifier => "*100/128", unit => "%"}] },
1363             "Freeze frame Commanded Evaporative Purge" => { command => "02 2E", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1364             "Freeze frame Fuel Level Input" => { command => "02 2F", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1365             "Freeze frame Number of warm-ups since diagnostic trouble codes cleared" => { command => "02 30", result => [{type => "byte_0", modifier => "+0", unit => ""}] },
1366             "Freeze frame Distance since diagnostic trouble codes cleared" => { command => "02 31", result => [{type => "word_0", modifier => "+0", unit => "km"}] },
1367             "Freeze frame Evap System Vapor Pressure" => { command => "02 32", result => [{type => "signed_word_0", modifier => "*0.25", unit => "Pa"}] },
1368             "Freeze frame Barometric Pressure" => { command => "02 33", result => [{type => "byte_0", modifier => "+0", unit => "kPa"}] },
1369            
1370             "Freeze frame Bank 1 - Sensor 1 (wide range O2S) current" => { command => "02 34",
1371             result => [
1372             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1373             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1374             ] },
1375            
1376             "Freeze frame Bank 1 - Sensor 2 (wide range O2S) current" => { command => "02 35",
1377             result => [
1378             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1379             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1380             ] },
1381            
1382             "Freeze frame Bank 1 - Sensor 3 (wide range O2S) current" => { command => "02 36",
1383             result => [
1384             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1385             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1386             ] },
1387            
1388             "Freeze frame Bank 1 - Sensor 4 (wide range O2S) current" => { command => "02 37",
1389             result => [
1390             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1391             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1392             ] },
1393            
1394             "Freeze frame Bank 2 - Sensor 1 (wide range O2S) current 13" => { command => "02 38",
1395             result => [
1396             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1397             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1398             ] },
1399            
1400             "Freeze frame Bank 2 - Sensor 2 (wide range O2S) current 13" => { command => "02 39",
1401             result => [
1402             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1403             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1404             ] },
1405            
1406             "Freeze frame Bank 2 - Sensor 3 (wide range O2S) current" => { command => "02 3A",
1407             result => [
1408             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1409             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1410             ] },
1411            
1412             "Freeze frame Bank 2 - Sensor 4 (wide range O2S) current" => { command => "02 3B",
1413             result => [
1414             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1415             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1416             ] },
1417            
1418            
1419             "Freeze frame Bank 2 - Sensor 1 (wide range O2S) current 1D" => { command => "02 36",
1420             result => [
1421             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1422             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1423             ] },
1424            
1425             "Freeze frame Bank 2 - Sensor 2 (wide range O2S) current 1D" => { command => "02 37",
1426             result => [
1427             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1428             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1429             ] },
1430            
1431             "Freeze frame Bank 3 - Sensor 1 (wide range O2S) current" => { command => "02 38",
1432             result => [
1433             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1434             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1435             ] },
1436            
1437             "Freeze frame Bank 3 - Sensor 2 (wide range O2S) current" => { command => "02 39",
1438             result => [
1439             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1440             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1441             ] },
1442            
1443             "Freeze frame Bank 4 - Sensor 1 (wide range O2S) current" => { command => "02 3A",
1444             result => [
1445             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1446             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1447             ] },
1448            
1449             "Freeze frame Bank 4 - Sensor 2 (wide range O2S) current" => { command => "02 3B",
1450             result => [
1451             {name => "Freeze frame Equivalence Ratio (lambda) (Bx-Sy)", type => "word_0", modifier => "*0.0000305", unit => ""},
1452             {name => "Freeze frame Oxygen Sensor Current (Bx-Sy)", type => "signed_word_1", modifier => "*0.000122", unit => "A"}
1453             ] },
1454            
1455             "Freeze frame Catalyst Temperature Bank 1, Sensor 1" => { command => "02 3C", result => [{type => "word_0", modifier => "/10-40", unit => "°C"}] },
1456             "Freeze frame Catalyst Temperature Bank 1, Sensor 2" => { command => "02 3D", result => [{type => "word_0", modifier => "/10-40", unit => "°C"}] },
1457             "Freeze frame Catalyst Temperature Bank 2, Sensor 1" => { command => "02 3E", result => [{type => "word_0", modifier => "/10-40", unit => "°C"}] },
1458             "Freeze frame Catalyst Temperature Bank 2, Sensor 2" => { command => "02 3F", result => [{type => "word_0", modifier => "/10-40", unit => "°C"}] },
1459            
1460             "02 PIDs supported (41-60)" => { command => "02 40",
1461             result => [
1462             {name => "Freeze frame Monitor status this driving cycle", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
1463             {name => "Freeze frame Control Module Voltage", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
1464             {name => "Freeze frame Absolute Load Value", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
1465             {name => "Freeze frame Commanded Equivalence Ratio", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
1466             {name => "Freeze frame Relative Throttle Position", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
1467             {name => "Freeze frame Ambiant Air Temperature", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
1468             {name => "Freeze frame Absolute Throttle Position B", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
1469             {name => "Freeze frame Absolute Throttle Position C", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
1470            
1471             {name => "Freeze frame Absolute Throttle Position D", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
1472             {name => "Freeze frame Absolute Throttle Position E", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
1473             {name => "Freeze frame Absolute Throttle Position F", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
1474             {name => "Freeze frame Commanded Throttle Actuator Control", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
1475             {name => "Freeze frame Minutes run by the engine while MIL activated", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
1476             {name => "Freeze frame Time since diagnostic trouble codes cleared", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
1477             {name => "Freeze frame External Test Equipment Configuration Information #1", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
1478             {name => "Freeze frame External Test Equipment Configuration Information #2", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
1479            
1480             {name => "Freeze frame Type of fuel currently being utilized by the vehicle", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
1481             {name => "Freeze frame Alcohol Fuel Percentage", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
1482             {name => "Freeze frame Absolute Evap System Vapour Pressure", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
1483             {name => "Freeze frame Evap System Vapour Pressure", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
1484             {name => "Freeze frame Short Term Secondary O2 Sensor Fuel Trim - Bank 1", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
1485             {name => "Freeze frame Long Term Secondary O2 Sensor Fuel Trim - Bank 1", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
1486             {name => "Freeze frame Short Term Secondary O2 Sensor Fuel Trim - Bank 2", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
1487             {name => "Freeze frame Long Term Secondary O2 Sensor Fuel Trim - Bank 2", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
1488             {name => "Freeze frame Short Term Secondary O2 Sensor Fuel Trim - Bank 3", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
1489             {name => "Freeze frame Long Term Secondary O2 Sensor Fuel Trim - Bank 3", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
1490             {name => "Freeze frame Short Term Secondary O2 Sensor Fuel Trim - Bank 4", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
1491             {name => "Freeze frame Long Term Secondary O2 Sensor Fuel Trim - Bank 4", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
1492            
1493             {name => "Freeze frame Fuel Rail Pressure (absolute)", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
1494             {name => "Freeze frame Relative Accelerator Pedal Position", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
1495             # {name => "Freeze frame ", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
1496             # {name => "Freeze frame ", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
1497             # {name => "Freeze frame ", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
1498             # {name => "Freeze frame ", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
1499             # {name => "Freeze frame ", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
1500             # {name => "02 PIDs supported (61-80)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
1501             ] },
1502            
1503            
1504             "Freeze frame Monitor status this driving cycle" => { command => "02 41",
1505             result => [
1506             {name => "Freeze frame Misfire monitoring Enable Status", type => "bool_1", modifier => "&1", unit => "not enabled,enabled"},
1507             {name => "Freeze frame Fuel system monitoring Enable Status", type => "bool_1", modifier => "&2", unit => "not enabled,enabled"},
1508             {name => "Freeze frame Comprehensive component monitoring Enable Status", type => "bool_1", modifier => "&4", unit => "not enabled,enabled"},
1509             {name => "Freeze frame Misfire monitoring Completion Status", type => "bool_1", modifier => "&16", unit => "not completed,completed"},
1510             {name => "Freeze frame Fuel system monitoring Completion Status", type => "bool_1", modifier => "&32", unit => "not completed,completed"},
1511             {name => "Freeze frame Comprehensive component monitoring Completion Status", type => "bool_1", modifier => "&64", unit => "not completed,completed"},
1512             {name => "Freeze frame Catalyst monitoring Enable Status", type => "bool_2", modifier => "&1", unit => "not enabled,enabled"},
1513             {name => "Freeze frame Heated catalyst monitoring Enable Status", type => "bool_2", modifier => "&2", unit => "not enabled,enabled"},
1514             {name => "Freeze frame Evaporative system monitoring Enable Status", type => "bool_2", modifier => "&4", unit => "not enabled,enabled"},
1515             {name => "Freeze frame Secondary air system monitoring Enable Status", type => "bool_2", modifier => "&8", unit => "not enabled,enabled"},
1516             {name => "Freeze frame A/C system refrigerant monitoring Enable Status", type => "bool_2", modifier => "&16", unit => "not enabled,enabled"},
1517             {name => "Freeze frame Oxygen sensor monitoring Enable Status", type => "bool_2", modifier => "&32", unit => "not enabled,enabled"},
1518             {name => "Freeze frame Oxygen sensor heater monitoring Enable Status", type => "bool_2", modifier => "&64", unit => "not enabled,enabled"},
1519             {name => "Freeze frame EGR monitoring Enable Status", type => "bool_2", modifier => "&128", unit => "not enabled,enabled"},
1520             {name => "Freeze frame Catalyst monitoring Completion Status", type => "bool_3", modifier => "&1", unit => "not completed,completed"},
1521             {name => "Freeze frame Heated catalyst monitoring Completion Status", type => "bool_3", modifier => "&2", unit => "not completed,completed"},
1522             {name => "Freeze frame Evaporative system monitoring Completion Status", type => "bool_3", modifier => "&4", unit => "not completed,completed"},
1523             {name => "Freeze frame Secondary air system monitoring Completion Status", type => "bool_3", modifier => "&8", unit => "not completed,completed"},
1524             {name => "Freeze frame A/C system refrigerant monitoring Completion Status", type => "bool_3", modifier => "&16", unit => "not completed,completed"},
1525             {name => "Freeze frame Oxygen sensor monitoring Completion Status", type => "bool_3", modifier => "&32", unit => "not completed,completed"},
1526             {name => "Freeze frame Oxygen sensor heater monitoring Completion Status", type => "bool_3", modifier => "&64", unit => "not completed,completed"},
1527             {name => "Freeze frame EGR monitoring Completion Status", type => "bool_3", modifier => "&128", unit => "not completed,completed"}
1528             ] },
1529            
1530             "Freeze frame Control Module Voltage" => { command => "02 42", result => [{type => "word_0", modifier => "*0.001", unit => "V"}] },
1531             "Freeze frame Absolute Load Value" => { command => "02 43", result => [{type => "word_0", modifier => "*100/255", unit => "%"}] },
1532             "Freeze frame Commanded Equivalence Ratio" => { command => "02 44", result => [{type => "word_0", modifier => "*0.0000305", unit => ""}] },
1533             "Freeze frame Relative Throttle Position" => { command => "02 45", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1534             "Freeze frame Ambiant Air Temperature" => { command => "02 46", result => [{type => "byte_0", modifier => "-40", unit => "°C"}] },
1535             "Freeze frame Absolute Throttle Position B" => { command => "02 47", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1536             "Freeze frame Absolute Throttle Position C" => { command => "02 48", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1537             "Freeze frame Accelerator Pedal Position D" => { command => "02 49", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1538             "Freeze frame Accelerator Pedal Position E" => { command => "02 4A", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1539             "Freeze frame Accelerator Pedal Position F" => { command => "02 4B", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1540             "Freeze frame Commanded Throttle Actuator Control" => { command => "02 4C", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1541             "Freeze frame Minutes run by the engine while MIL activated" => { command => "02 4D", result => [{type => "word_0", modifier => "+0", unit => "min"}] },
1542             "Freeze frame Time since diagnostic trouble codes cleared" => { command => "02 4E", result => [{type => "word_0", modifier => "+0", unit => "min"}] },
1543             "Freeze frame External Test Equipment Configuration Information #1" => { command => "02 4F",
1544             result => [
1545             {name => "Freeze frame Maximum value for Equivalence Ratio", type => "byte_0", modifier => "+0", unit => ""},
1546             {name => "Freeze frame Maximum value for Oxygen Sensor Voltage", type => "byte_1", modifier => "+0", unit => "V"},
1547             {name => "Freeze frame Maximum value for Oxygen Sensor Current", type => "byte_2", modifier => "+0", unit => "mA"},
1548             {name => "Freeze frame Maximum value for Intake Manifold Absolute Pressure", type => "byte_3", modifier => "+0", unit => "kPa"},
1549             ] },
1550             "Freeze frame External Test Equipment Configuration Information #2" => { command => "02 50",
1551             result => [
1552             {name => "Freeze frame Maximum value for Air Flow Rate from Mass Air Flow Sensor", type => "byte_0", modifier => "+0", unit => "g/s"}
1553             ] },
1554            
1555             "Freeze frame Type of fuel currently being utilized by the vehicle" => { command => "02 51", result => [{type => "byte_0", modifier => "+0", unit => "",
1556             alternatives => [
1557             {value => 1, meaning => "Gasoline/petrol"},
1558             {value => 2, meaning => "Methanol"},
1559             {value => 3, meaning => "Ethanol"},
1560             {value => 4, meaning => "Diesel"},
1561             {value => 5, meaning => "Liquefied Petroleum Gas (LPG)"},
1562             {value => 6, meaning => "Compressed Natural Gas (CNG)"},
1563             {value => 7, meaning => "Propane"},
1564             {value => 8, meaning => "Battery/electric"},
1565             {value => 9, meaning => "Bi-fuel vehicle using gasoline"},
1566             {value => 10, meaning => "Bi-fuel vehicle using methanol"},
1567             {value => 11, meaning => "Bi-fuel vehicle using ethanol"},
1568             {value => 12, meaning => "Bi-fuel vehicle using LPG"},
1569             {value => 13, meaning => "Bi-fuel vehicle using CNG"},
1570             {value => 14, meaning => "Bi-fuel vehicle using propane"},
1571             {value => 15, meaning => "Bi-fuel vehicle using battery"}
1572             ] }
1573             ] },
1574            
1575             "Freeze frame Alcohol Fuel Percentage" => { command => "02 52", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1576             "Freeze frame Absolute Evap System Vapour Pressure" => { command => "02 53", result => [{type => "word_0", modifier => "/200", unit => "kPa"}] },
1577             "Freeze frame Evap System Vapour Pressure" => { command => "02 54", result => [{type => "signed_word_0", modifier => "+1", unit => "Pa"}] },
1578             "Freeze frame Short Term Secondary O2 Sensor Fuel Trim - Bank 1" => { command => "02 55", result => [{type => "signed_byte_0", modifier => "*100/128", unit => "%"}] },
1579             "Freeze frame Long Term Secondary O2 Sensor Fuel Trim - Bank 1" => { command => "02 56", result => [{type => "signed_byte_0", modifier => "*100/128", unit => "%"}] },
1580             "Freeze frame Short Term Secondary O2 Sensor Fuel Trim - Bank 2" => { command => "02 57", result => [{type => "signed_byte_0", modifier => "*100/128", unit => "%"}] },
1581             "Freeze frame Long Term Secondary O2 Sensor Fuel Trim - Bank 2" => { command => "02 58", result => [{type => "signed_byte_0", modifier => "*100/128", unit => "%"}] },
1582            
1583             "Freeze frame Short Term Secondary O2 Sensor Fuel Trim - Bank 3" => { command => "02 55", result => [{type => "signed_byte_1", modifier => "*100/128", unit => "%"}] },
1584             "Freeze frame Long Term Secondary O2 Sensor Fuel Trim - Bank 3" => { command => "02 56", result => [{type => "signed_byte_1", modifier => "*100/128", unit => "%"}] },
1585             "Freeze frame Short Term Secondary O2 Sensor Fuel Trim - Bank 4" => { command => "02 57", result => [{type => "signed_byte_1", modifier => "*100/128", unit => "%"}] },
1586             "Freeze frame Long Term Secondary O2 Sensor Fuel Trim - Bank 4" => { command => "02 58", result => [{type => "signed_byte_1", modifier => "*100/128", unit => "%"}] },
1587            
1588             "Freeze frame Fuel Rail Pressure (absolute)" => { command => "02 59", result => [{type => "word_0", modifier => "*10", unit => "kPa"}] },
1589             "Freeze frame Relative Accelerator Pedal Position" => { command => "02 5A", result => [{type => "byte_0", modifier => "*100/255", unit => "%"}] },
1590            
1591            
1592             "Emission-related diagnostic trouble codes" => { command => "03", available => 1,
1593             result => [
1594             {name => "DTC#1", type => "word_0", modifier => "+0", unit => ""},
1595             {name => "DTC#2", type => "word_1", modifier => "+0", unit => ""},
1596             {name => "DTC#3", type => "word_2", modifier => "+0", unit => ""},
1597             ] },
1598            
1599             "05 TIDs supported (01-20)" => { command => "05 00",
1600             result => [
1601             {name => "Rich to lean sensor threshold voltage", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
1602             {name => "Lean to rich sensor threshold voltage", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
1603             {name => "Low sensor voltage for switch time calculation", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
1604             {name => "High sensor voltage for switch time calculation", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
1605             {name => "Rich to lean sensor switch time", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
1606             {name => "Lean to rich sensor switch time", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
1607             {name => "Minimum sensor voltage for test cycle", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
1608             {name => "Maximum sensor voltage for test cycle", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
1609            
1610             {name => "Time between sensor transitions", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
1611             {name => "Sensor period", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
1612             # {name => "", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
1613             # {name => "", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
1614             # {name => "", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
1615             # {name => "", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
1616             # {name => "", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
1617             # {name => "", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
1618            
1619             # {name => "", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
1620             # {name => "", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
1621             # {name => "", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
1622             # {name => "", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
1623             # {name => "", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
1624             # {name => "", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
1625             # {name => "", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
1626             # {name => "", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
1627            
1628             # {name => "", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
1629             # {name => "", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
1630             # {name => "", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
1631             # {name => "", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
1632             # {name => "", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
1633             # {name => "", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
1634             # {name => "", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
1635             # {name => "05 TIDs supported (21-40)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
1636             ] },
1637            
1638             "Rich to lean sensor threshold voltage" => { command => "05 01", result => [{type => "byte_0", modifier => "*0.005", unit => "V"}] },
1639             "Lean to rich sensor threshold voltage" => { command => "05 02", result => [{type => "byte_0", modifier => "*0.005", unit => "V"}] },
1640             "Low sensor voltage for switch time calculation" => { command => "05 03", result => [{type => "byte_0", modifier => "*0.005", unit => "V"}] },
1641             "High sensor voltage for switch time calculation" => { command => "05 04", result => [{type => "byte_0", modifier => "*0.005", unit => "V"}] },
1642            
1643             "Rich to lean sensor switch time" => { command => "05 05",
1644             result => [
1645             {type => "byte_0", modifier => "*0.004", unit => "s"},
1646             {name => "Rich to lean sensor switch time - low limit", type => "byte_1", modifier => "*0.004", unit => "s"},
1647             {name => "Rich to lean sensor switch time - high limit", type => "byte_2", modifier => "*0.004", unit => "s"},
1648             ] },
1649            
1650             "Lean to rich sensor switch time" => { command => "05 06",
1651             result => [
1652             {type => "byte_0", modifier => "*0.004", unit => "s"},
1653             {name => "Lean to rich sensor switch time - low limit", type => "byte_1", modifier => "*0.004", unit => "s"},
1654             {name => "Lean to rich sensor switch time - high limit", type => "byte_2", modifier => "*0.004", unit => "s"},
1655             ] },
1656            
1657             "Minimum sensor voltage for test cycle" => { command => "05 07",
1658             result => [
1659             {type => "byte_0", modifier => "*0.005", unit => "V"},
1660             {name => "Minimum sensor voltage for test cycle - low limit", type => "byte_1", modifier => "*0.005", unit => "V"},
1661             {name => "Minimum sensor voltage for test cycle - high limit", type => "byte_2", modifier => "*0.005", unit => "V"},
1662             ] },
1663            
1664             "Maximum sensor voltage for test cycle" => { command => "05 08",
1665             result => [
1666             {type => "byte_0", modifier => "*0.005", unit => "V"},
1667             {name => "Maximum sensor voltage for test cycle - low limit", type => "byte_1", modifier => "*0.005", unit => "V"},
1668             {name => "Maximum sensor voltage for test cycle - high limit", type => "byte_2", modifier => "*0.005", unit => "V"},
1669             ] },
1670            
1671             "Time between sensor transitions" => { command => "05 09",
1672             result => [
1673             {type => "byte_0", modifier => "*0.04", unit => "s"},
1674             {name => "Time between sensor transitions - low limit", type => "byte_1", modifier => "*0.04", unit => "s"},
1675             {name => "Time between sensor transitions - high limit", type => "byte_2", modifier => "*0.04", unit => "s"},
1676             ] },
1677            
1678             "Sensor period" => { command => "05 0A",
1679             result => [
1680             {type => "byte_0", modifier => "*0.04", unit => "s"},
1681             {name => "Sensor period - low limit", type => "byte_1", modifier => "*0.04", unit => "s"},
1682             {name => "Sensor period - high limit", type => "byte_2", modifier => "*0.04", unit => "s"},
1683             ] },
1684            
1685            
1686             "06 MIDs supported (01-20)" => { command => "06 00",
1687             result => [
1688             {name => "Oxygen Sensor Monitor Bank 1 - Sensor 1", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
1689             {name => "Oxygen Sensor Monitor Bank 1 - Sensor 2", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
1690             {name => "Oxygen Sensor Monitor Bank 1 - Sensor 3", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
1691             {name => "Oxygen Sensor Monitor Bank 1 - Sensor 4", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
1692             {name => "Oxygen Sensor Monitor Bank 2 - Sensor 1", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
1693             {name => "Oxygen Sensor Monitor Bank 2 - Sensor 2", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
1694             {name => "Oxygen Sensor Monitor Bank 2 - Sensor 3", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
1695             {name => "Oxygen Sensor Monitor Bank 2 - Sensor 4", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
1696            
1697             {name => "Oxygen Sensor Monitor Bank 3 - Sensor 1", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
1698             {name => "Oxygen Sensor Monitor Bank 3 - Sensor 2", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
1699             {name => "Oxygen Sensor Monitor Bank 3 - Sensor 3", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
1700             {name => "Oxygen Sensor Monitor Bank 3 - Sensor 4", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
1701             {name => "Oxygen Sensor Monitor Bank 4 - Sensor 1", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
1702             {name => "Oxygen Sensor Monitor Bank 4 - Sensor 2", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
1703             {name => "Oxygen Sensor Monitor Bank 4 - Sensor 3", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
1704             {name => "Oxygen Sensor Monitor Bank 4 - Sensor 4", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
1705            
1706             # 11 -1F reserved by ISO/SAE
1707             # {name => "", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
1708             # {name => "", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
1709             # {name => "", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
1710             # {name => "", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
1711             # {name => "", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
1712             # {name => "", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
1713             # {name => "", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
1714             # {name => "", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
1715            
1716             # {name => "", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
1717             # {name => "", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
1718             # {name => "", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
1719             # {name => "", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
1720             # {name => "", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
1721             # {name => "", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
1722             # {name => "", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
1723             {name => "06 MIDs supported (21-40)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
1724             ] },
1725            
1726             "Oxygen Sensor Monitor Bank 1 - Sensor 1" => { command => "06 01", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1727             "Oxygen Sensor Monitor Bank 1 - Sensor 2" => { command => "06 02", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1728             "Oxygen Sensor Monitor Bank 1 - Sensor 3" => { command => "06 03", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1729             "Oxygen Sensor Monitor Bank 1 - Sensor 4" => { command => "06 04", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1730             "Oxygen Sensor Monitor Bank 2 - Sensor 1" => { command => "06 05", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1731             "Oxygen Sensor Monitor Bank 2 - Sensor 2" => { command => "06 06", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1732             "Oxygen Sensor Monitor Bank 2 - Sensor 3" => { command => "06 07", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1733             "Oxygen Sensor Monitor Bank 2 - Sensor 4" => { command => "06 08", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1734             "Oxygen Sensor Monitor Bank 3 - Sensor 1" => { command => "06 09", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1735             "Oxygen Sensor Monitor Bank 3 - Sensor 2" => { command => "06 0A", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1736             "Oxygen Sensor Monitor Bank 3 - Sensor 3" => { command => "06 0B", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1737             "Oxygen Sensor Monitor Bank 3 - Sensor 4" => { command => "06 0C", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1738             "Oxygen Sensor Monitor Bank 4 - Sensor 1" => { command => "06 0D", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1739             "Oxygen Sensor Monitor Bank 4 - Sensor 2" => { command => "06 0E", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1740             "Oxygen Sensor Monitor Bank 4 - Sensor 3" => { command => "06 0F", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1741             "Oxygen Sensor Monitor Bank 4 - Sensor 4" => { command => "06 10", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1742            
1743             "06 MIDs supported (21-40)" => { command => "06 20",
1744             result => [
1745             {name => "Catalyst Monitor Bank 1", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
1746             {name => "Catalyst Monitor Bank 2", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
1747             {name => "Catalyst Monitor Bank 3", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
1748             {name => "Catalyst Monitor Bank 4", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
1749             # {name => "", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
1750             # {name => "", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
1751             # {name => "", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
1752             # {name => "", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
1753            
1754             # {name => "", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
1755             # {name => "", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
1756             # {name => "", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
1757             # {name => "", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
1758             # {name => "", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
1759             # {name => "", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
1760             # {name => "", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
1761             # {name => "", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
1762            
1763             {name => "EGR Monitor Bank 1", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
1764             {name => "EGR Monitor Bank 2", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
1765             {name => "EGR Monitor Bank 3", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
1766             {name => "EGR Monitor Bank 4", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
1767             # {name => "", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
1768             # {name => "", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
1769             # {name => "", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
1770             # {name => "", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
1771            
1772             {name => "EVAP Monitor (Cap Off)", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
1773             {name => "EVAP Monitor (0,090)", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
1774             {name => "EVAP Monitor (0,040)", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
1775             {name => "EVAP Monitor (0,020)", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
1776             {name => "Purge Flow Monitor", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
1777             # {name => "", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
1778             # {name => "", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
1779             {name => "06 MIDs supported (41-60)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
1780             ] },
1781            
1782             "Catalyst Monitor Bank 1" => { command => "06 21", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1783             "Catalyst Monitor Bank 2" => { command => "06 22", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1784             "Catalyst Monitor Bank 3" => { command => "06 23", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1785             "Catalyst Monitor Bank 4" => { command => "06 24", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1786            
1787             "EGR Monitor Bank 1" => { command => "06 31", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1788             "EGR Monitor Bank 2" => { command => "06 32", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1789             "EGR Monitor Bank 3" => { command => "06 33", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1790             "EGR Monitor Bank 4" => { command => "06 34", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1791            
1792             "EVAP Monitor (Cap Off)" => { command => "06 39", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1793             "EVAP Monitor (0,090)" => { command => "06 3A", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1794             "EVAP Monitor (0,040)" => { command => "06 3B", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1795             "EVAP Monitor (0,020)" => { command => "06 3C", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1796             "Purge Flow Monitor" => { command => "06 3D", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1797            
1798            
1799             "06 MIDs supported (41-60)" => { command => "06 40",
1800             result => [
1801             {name => "Oxygen Sensor Heater Monitor Bank 1 - Sensor 1", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
1802             {name => "Oxygen Sensor Heater Monitor Bank 1 - Sensor 2", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
1803             {name => "Oxygen Sensor Heater Monitor Bank 1 - Sensor 3", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
1804             {name => "Oxygen Sensor Heater Monitor Bank 1 - Sensor 4", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
1805             {name => "Oxygen Sensor Heater Monitor Bank 2 - Sensor 1", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
1806             {name => "Oxygen Sensor Heater Monitor Bank 2 - Sensor 2", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
1807             {name => "Oxygen Sensor Heater Monitor Bank 2 - Sensor 3", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
1808             {name => "Oxygen Sensor Heater Monitor Bank 2 - Sensor 4", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
1809            
1810             {name => "Oxygen Sensor Heater Monitor Bank 3 - Sensor 1", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
1811             {name => "Oxygen Sensor Heater Monitor Bank 3 - Sensor 2", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
1812             {name => "Oxygen Sensor Heater Monitor Bank 3 - Sensor 3", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
1813             {name => "Oxygen Sensor Heater Monitor Bank 3 - Sensor 4", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
1814             {name => "Oxygen Sensor Heater Monitor Bank 4 - Sensor 1", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
1815             {name => "Oxygen Sensor Heater Monitor Bank 4 - Sensor 2", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
1816             {name => "Oxygen Sensor Heater Monitor Bank 4 - Sensor 3", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
1817             {name => "Oxygen Sensor Heater Monitor Bank 4 - Sensor 4", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
1818            
1819             # {name => "", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
1820             # {name => "", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
1821             # {name => "", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
1822             # {name => "", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
1823             # {name => "", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
1824             # {name => "", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
1825             # {name => "", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
1826             # {name => "", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
1827            
1828             # {name => "", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
1829             # {name => "", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
1830             # {name => "", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
1831             # {name => "", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
1832             # {name => "", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
1833             # {name => "", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
1834             # {name => "", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
1835             {name => "06 MIDs supported (61-80)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
1836             ] },
1837            
1838             "Oxygen Sensor Heater Monitor Bank 1 - Sensor 1" => { command => "06 41", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1839             "Oxygen Sensor Heater Monitor Bank 1 - Sensor 2" => { command => "06 42", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1840             "Oxygen Sensor Heater Monitor Bank 1 - Sensor 3" => { command => "06 43", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1841             "Oxygen Sensor Heater Monitor Bank 1 - Sensor 4" => { command => "06 44", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1842             "Oxygen Sensor Heater Monitor Bank 2 - Sensor 1" => { command => "06 45", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1843             "Oxygen Sensor Heater Monitor Bank 2 - Sensor 2" => { command => "06 46", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1844             "Oxygen Sensor Heater Monitor Bank 2 - Sensor 3" => { command => "06 47", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1845             "Oxygen Sensor Heater Monitor Bank 2 - Sensor 4" => { command => "06 48", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1846             "Oxygen Sensor Heater Monitor Bank 3 - Sensor 1" => { command => "06 49", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1847             "Oxygen Sensor Heater Monitor Bank 3 - Sensor 2" => { command => "06 4A", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1848             "Oxygen Sensor Heater Monitor Bank 3 - Sensor 3" => { command => "06 4B", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1849             "Oxygen Sensor Heater Monitor Bank 3 - Sensor 4" => { command => "06 4C", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1850             "Oxygen Sensor Heater Monitor Bank 4 - Sensor 1" => { command => "06 4D", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1851             "Oxygen Sensor Heater Monitor Bank 4 - Sensor 2" => { command => "06 4E", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1852             "Oxygen Sensor Heater Monitor Bank 4 - Sensor 3" => { command => "06 4F", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1853             "Oxygen Sensor Heater Monitor Bank 4 - Sensor 4" => { command => "06 50", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1854            
1855            
1856            
1857             "06 MIDs supported (61-80)" => { command => "06 60",
1858             result => [
1859             {name => "Heated Catalyst Monitor Bank 1", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
1860             {name => "Heated Catalyst Monitor Bank 2", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
1861             {name => "Heated Catalyst Monitor Bank 3", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
1862             {name => "Heated Catalyst Monitor Bank 4", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
1863             # {name => "", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
1864             # {name => "", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
1865             # {name => "", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
1866             # {name => "", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
1867            
1868             # {name => "", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
1869             # {name => "", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
1870             # {name => "", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
1871             # {name => "", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
1872             # {name => "", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
1873             # {name => "", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
1874             # {name => "", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
1875             # {name => "", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
1876            
1877             {name => "Secondary Air Monitor 1", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
1878             {name => "Secondary Air Monitor 2", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
1879             {name => "Secondary Air Monitor 3", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
1880             {name => "Secondary Air Monitor 4", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
1881             # {name => "", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
1882             # {name => "", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
1883             # {name => "", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
1884             # {name => "", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
1885            
1886             # {name => "", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
1887             # {name => "", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
1888             # {name => "", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
1889             # {name => "", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
1890             # {name => "", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
1891             # {name => "", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
1892             # {name => "", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
1893             {name => "06 MIDs supported (81-A0)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
1894             ] },
1895            
1896             "Heated Catalyst Monitor Bank 1" => { command => "06 61", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1897             "Heated Catalyst Monitor Bank 2" => { command => "06 62", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1898             "Heated Catalyst Monitor Bank 3" => { command => "06 63", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1899             "Heated Catalyst Monitor Bank 4" => { command => "06 64", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1900            
1901             "Secondary Air Monitor 1" => { command => "06 71", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1902             "Secondary Air Monitor 2" => { command => "06 72", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1903             "Secondary Air Monitor 3" => { command => "06 73", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1904             "Secondary Air Monitor 4" => { command => "06 74", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1905            
1906             "06 MIDs supported (81-A0)" => { command => "06 80",
1907             result => [
1908             {name => "Fuel System Monitor Bank 1", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
1909             {name => "Fuel System Monitor Bank 2", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
1910             {name => "Fuel System Monitor Bank 3", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
1911             {name => "Fuel System Monitor Bank 4", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
1912             # {name => "", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
1913             # {name => "", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
1914             # {name => "", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
1915             # {name => "", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
1916            
1917             # {name => "", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
1918             # {name => "", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
1919             # {name => "", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
1920             # {name => "", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
1921             # {name => "", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
1922             # {name => "", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
1923             # {name => "", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
1924             # {name => "", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
1925            
1926             # {name => "", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
1927             # {name => "", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
1928             # {name => "", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
1929             # {name => "", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
1930             # {name => "", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
1931             # {name => "", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
1932             # {name => "", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
1933             # {name => "", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
1934            
1935             # {name => "", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
1936             # {name => "", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
1937             # {name => "", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
1938             # {name => "", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
1939             # {name => "", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
1940             # {name => "", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
1941             # {name => "", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
1942             {name => "06 MIDs supported (A1-C0)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
1943             ] },
1944            
1945             "Fuel System Monitor Bank 1" => { command => "06 81", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1946             "Fuel System Monitor Bank 2" => { command => "06 82", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1947             "Fuel System Monitor Bank 3" => { command => "06 83", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1948             "Fuel System Monitor Bank 4" => { command => "06 84", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1949            
1950            
1951             "06 MIDs supported (A1-C0)" => { command => "06 A0",
1952             result => [
1953             {name => "Misfire Monitor General Data", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
1954             {name => "Misfire Cylinder 1 Data", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
1955             {name => "Misfire Cylinder 2 Data", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
1956             {name => "Misfire Cylinder 3 Data", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
1957             {name => "Misfire Cylinder 4 Data", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
1958             {name => "Misfire Cylinder 5 Data", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
1959             {name => "Misfire Cylinder 6 Data", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
1960             {name => "Misfire Cylinder 7 Data", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
1961            
1962             {name => "Misfire Cylinder 8 Data", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
1963             {name => "Misfire Cylinder 9 Data", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
1964             {name => "Misfire Cylinder 10 Data", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
1965             {name => "Misfire Cylinder 11 Data", type => "bool_1", modifier => "&16", unit => "not supported,supported"},
1966             {name => "Misfire Cylinder 12 Data", type => "bool_1", modifier => "&8", unit => "not supported,supported"},
1967             # {name => "", type => "bool_1", modifier => "&4", unit => "not supported,supported"},
1968             # {name => "", type => "bool_1", modifier => "&2", unit => "not supported,supported"},
1969             # {name => "", type => "bool_1", modifier => "&1", unit => "not supported,supported"},
1970            
1971             # {name => "", type => "bool_2", modifier => "&128", unit => "not supported,supported"},
1972             # {name => "", type => "bool_2", modifier => "&64", unit => "not supported,supported"},
1973             # {name => "", type => "bool_2", modifier => "&32", unit => "not supported,supported"},
1974             # {name => "", type => "bool_2", modifier => "&16", unit => "not supported,supported"},
1975             # {name => "", type => "bool_2", modifier => "&8", unit => "not supported,supported"},
1976             # {name => "", type => "bool_2", modifier => "&4", unit => "not supported,supported"},
1977             # {name => "", type => "bool_2", modifier => "&2", unit => "not supported,supported"},
1978             # {name => "", type => "bool_2", modifier => "&1", unit => "not supported,supported"},
1979            
1980             # {name => "", type => "bool_3", modifier => "&128", unit => "not supported,supported"},
1981             # {name => "", type => "bool_3", modifier => "&64", unit => "not supported,supported"},
1982             # {name => "", type => "bool_3", modifier => "&32", unit => "not supported,supported"},
1983             # {name => "", type => "bool_3", modifier => "&16", unit => "not supported,supported"},
1984             # {name => "", type => "bool_3", modifier => "&8", unit => "not supported,supported"},
1985             # {name => "", type => "bool_3", modifier => "&4", unit => "not supported,supported"},
1986             # {name => "", type => "bool_3", modifier => "&2", unit => "not supported,supported"},
1987             {name => "06 MIDs supported (C1-E0)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
1988             ] },
1989            
1990             "Misfire Monitor General Data" => { command => "06 A1", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1991             "Misfire Cylinder 1 Data" => { command => "06 A2", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1992             "Misfire Cylinder 2 Data" => { command => "06 A3", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1993             "Misfire Cylinder 3 Data" => { command => "06 A4", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1994             "Misfire Cylinder 4 Data" => { command => "06 A5", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1995             "Misfire Cylinder 5 Data" => { command => "06 A6", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1996             "Misfire Cylinder 6 Data" => { command => "06 A7", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1997             "Misfire Cylinder 7 Data" => { command => "06 A8", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1998             "Misfire Cylinder 8 Data" => { command => "06 A9", result => [{type => "word_0", modifier => "*1", unit => ""}] },
1999             "Misfire Cylinder 9 Data" => { command => "06 AA", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2000             "Misfire Cylinder 10 Data" => { command => "06 AB", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2001             "Misfire Cylinder 11 Data" => { command => "06 AC", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2002             "Misfire Cylinder 12 Data" => { command => "06 AD", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2003            
2004            
2005            
2006             "06 MIDs supported (C1-E0)" => { command => "06 C0",
2007             result => [
2008             # {name => "", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
2009             # {name => "", type => "bool_0", modifier => "&64", unit => ""},
2010             # {name => "", type => "bool_0", modifier => "&32", unit => ""},
2011             # {name => "", type => "bool_0", modifier => "&16", unit => ""},
2012             # {name => "", type => "bool_0", modifier => "&8", unit => ""},
2013             # {name => "", type => "bool_0", modifier => "&4", unit => ""},
2014             # {name => "", type => "bool_0", modifier => "&2", unit => ""},
2015             # {name => "", type => "bool_0", modifier => "&1", unit => ""},
2016            
2017             # {name => "", type => "bool_1", modifier => "&128", unit => ""},
2018             # {name => "", type => "bool_1", modifier => "&64", unit => ""},
2019             # {name => "", type => "bool_1", modifier => "&32", unit => ""},
2020             # {name => "", type => "bool_1", modifier => "&16", unit => ""},
2021             # {name => "", type => "bool_1", modifier => "&8", unit => ""},
2022             # {name => "", type => "bool_1", modifier => "&4", unit => ""},
2023             # {name => "", type => "bool_1", modifier => "&2", unit => ""},
2024             # {name => "", type => "bool_1", modifier => "&1", unit => ""},
2025            
2026             # {name => "", type => "bool_2", modifier => "&128", unit => ""},
2027             # {name => "", type => "bool_2", modifier => "&64", unit => ""},
2028             # {name => "", type => "bool_2", modifier => "&32", unit => ""},
2029             # {name => "", type => "bool_2", modifier => "&16", unit => ""},
2030             # {name => "", type => "bool_2", modifier => "&8", unit => ""},
2031             # {name => "", type => "bool_2", modifier => "&4", unit => ""},
2032             # {name => "", type => "bool_2", modifier => "&2", unit => ""},
2033             # {name => "", type => "bool_2", modifier => "&1", unit => ""},
2034            
2035             # {name => "", type => "bool_3", modifier => "&128", unit => ""},
2036             # {name => "", type => "bool_3", modifier => "&64", unit => ""},
2037             # {name => "", type => "bool_3", modifier => "&32", unit => ""},
2038             # {name => "", type => "bool_3", modifier => "&16", unit => ""},
2039             # {name => "", type => "bool_3", modifier => "&8", unit => ""},
2040             # {name => "", type => "bool_3", modifier => "&4", unit => ""},
2041             # {name => "", type => "bool_3", modifier => "&2", unit => ""},
2042             {name => "06 MIDs supported (E1-FF)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
2043             ] },
2044            
2045             "06 MIDs supported (E1-FF)" => { command => "06 E0",
2046             result => [
2047             # {name => "Vehicle manufacturer defined OBDMID E1", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
2048             # {name => "Vehicle manufacturer defined OBDMID E2", type => "bool_0", modifier => "&64", unit => ""},
2049             # {name => "Vehicle manufacturer defined OBDMID E3", type => "bool_0", modifier => "&32", unit => ""},
2050             # {name => "Vehicle manufacturer defined OBDMID E4", type => "bool_0", modifier => "&16", unit => ""},
2051             # {name => "Vehicle manufacturer defined OBDMID E5", type => "bool_0", modifier => "&8", unit => ""},
2052             # {name => "Vehicle manufacturer defined OBDMID E6", type => "bool_0", modifier => "&4", unit => ""},
2053             # {name => "Vehicle manufacturer defined OBDMID E7", type => "bool_0", modifier => "&2", unit => ""},
2054             # {name => "Vehicle manufacturer defined OBDMID E8", type => "bool_0", modifier => "&1", unit => ""},
2055            
2056             # {name => "Vehicle manufacturer defined OBDMID E9", type => "bool_1", modifier => "&128", unit => ""},
2057             # {name => "Vehicle manufacturer defined OBDMID EA", type => "bool_1", modifier => "&64", unit => ""},
2058             # {name => "Vehicle manufacturer defined OBDMID EB", type => "bool_1", modifier => "&32", unit => ""},
2059             # {name => "Vehicle manufacturer defined OBDMID EC", type => "bool_1", modifier => "&16", unit => ""},
2060             # {name => "Vehicle manufacturer defined OBDMID ED", type => "bool_1", modifier => "&8", unit => ""},
2061             # {name => "Vehicle manufacturer defined OBDMID EE", type => "bool_1", modifier => "&4", unit => ""},
2062             # {name => "Vehicle manufacturer defined OBDMID EF", type => "bool_1", modifier => "&2", unit => ""},
2063             # {name => "Vehicle manufacturer defined OBDMID F0", type => "bool_1", modifier => "&1", unit => ""},
2064            
2065             # {name => "Vehicle manufacturer defined OBDMID F1", type => "bool_2", modifier => "&128", unit => ""},
2066             # {name => "Vehicle manufacturer defined OBDMID F2", type => "bool_2", modifier => "&64", unit => ""},
2067             # {name => "Vehicle manufacturer defined OBDMID F3", type => "bool_2", modifier => "&32", unit => ""},
2068             # {name => "Vehicle manufacturer defined OBDMID F4", type => "bool_2", modifier => "&16", unit => ""},
2069             # {name => "Vehicle manufacturer defined OBDMID F5", type => "bool_2", modifier => "&8", unit => ""},
2070             # {name => "Vehicle manufacturer defined OBDMID F6", type => "bool_2", modifier => "&4", unit => ""},
2071             # {name => "Vehicle manufacturer defined OBDMID F7", type => "bool_2", modifier => "&2", unit => ""},
2072             # {name => "Vehicle manufacturer defined OBDMID F8", type => "bool_2", modifier => "&1", unit => ""},
2073            
2074             # {name => "Vehicle manufacturer defined OBDMID F9", type => "bool_3", modifier => "&128", unit => ""},
2075             # {name => "Vehicle manufacturer defined OBDMID FA", type => "bool_3", modifier => "&64", unit => ""},
2076             # {name => "Vehicle manufacturer defined OBDMID FB", type => "bool_3", modifier => "&32", unit => ""},
2077             # {name => "Vehicle manufacturer defined OBDMID FC", type => "bool_3", modifier => "&16", unit => ""},
2078             # {name => "Vehicle manufacturer defined OBDMID FD", type => "bool_3", modifier => "&8", unit => ""},
2079             # {name => "Vehicle manufacturer defined OBDMID FE", type => "bool_3", modifier => "&4", unit => ""},
2080             # {name => "Vehicle manufacturer defined OBDMID FF", type => "bool_3", modifier => "&2", unit => ""},
2081             ] },
2082            
2083             "Vehicle manufacturer defined OBDMID E1" => { command => "06 E1", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2084             "Vehicle manufacturer defined OBDMID E2" => { command => "06 E2", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2085             "Vehicle manufacturer defined OBDMID E3" => { command => "06 E3", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2086             "Vehicle manufacturer defined OBDMID E4" => { command => "06 E4", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2087             "Vehicle manufacturer defined OBDMID E5" => { command => "06 E5", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2088             "Vehicle manufacturer defined OBDMID E6" => { command => "06 E6", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2089             "Vehicle manufacturer defined OBDMID E7" => { command => "06 E7", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2090             "Vehicle manufacturer defined OBDMID E8" => { command => "06 E8", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2091             "Vehicle manufacturer defined OBDMID E9" => { command => "06 E9", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2092             "Vehicle manufacturer defined OBDMID EA" => { command => "06 EA", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2093             "Vehicle manufacturer defined OBDMID EB" => { command => "06 EB", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2094             "Vehicle manufacturer defined OBDMID EC" => { command => "06 EC", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2095             "Vehicle manufacturer defined OBDMID ED" => { command => "06 ED", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2096             "Vehicle manufacturer defined OBDMID EE" => { command => "06 EE", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2097             "Vehicle manufacturer defined OBDMID EF" => { command => "06 EF", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2098             "Vehicle manufacturer defined OBDMID F0" => { command => "06 F0", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2099             "Vehicle manufacturer defined OBDMID F1" => { command => "06 F1", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2100             "Vehicle manufacturer defined OBDMID F2" => { command => "06 F2", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2101             "Vehicle manufacturer defined OBDMID F3" => { command => "06 F3", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2102             "Vehicle manufacturer defined OBDMID F4" => { command => "06 F4", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2103             "Vehicle manufacturer defined OBDMID F5" => { command => "06 F5", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2104             "Vehicle manufacturer defined OBDMID F6" => { command => "06 F6", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2105             "Vehicle manufacturer defined OBDMID F7" => { command => "06 F7", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2106             "Vehicle manufacturer defined OBDMID F8" => { command => "06 F8", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2107             "Vehicle manufacturer defined OBDMID F9" => { command => "06 F9", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2108             "Vehicle manufacturer defined OBDMID FA" => { command => "06 FA", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2109             "Vehicle manufacturer defined OBDMID FB" => { command => "06 FB", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2110             "Vehicle manufacturer defined OBDMID FC" => { command => "06 FC", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2111             "Vehicle manufacturer defined OBDMID FD" => { command => "06 FD", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2112             "Vehicle manufacturer defined OBDMID FE" => { command => "06 FE", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2113             "Vehicle manufacturer defined OBDMID FF" => { command => "06 FF", result => [{type => "word_0", modifier => "*1", unit => ""}] },
2114            
2115            
2116             "Emission-related diagnostic trouble codes detected during current or last completed driving cycle" => { command => "07", available => 1,
2117             result => [
2118             {name => "DTC#1", type => "word_0", modifier => "+0", unit => ""},
2119             {name => "DTC#2", type => "word_1", modifier => "+0", unit => ""},
2120             {name => "DTC#3", type => "word_2", modifier => "+0", unit => ""},
2121             ] },
2122            
2123            
2124             "09 PIDs supported (01-20)" => { command => "09 00", available => 1,
2125             result => [
2126             {name => "MessageCount VIN", type => "bool_0", modifier => "&128", unit => "not supported,supported"},
2127             {name => "Vehicle Identification Number", type => "bool_0", modifier => "&64", unit => "not supported,supported"},
2128             {name => "MessageCount CALID", type => "bool_0", modifier => "&32", unit => "not supported,supported"},
2129             {name => "Calibration Identifications", type => "bool_0", modifier => "&16", unit => "not supported,supported"},
2130             {name => "MessageCount CVN", type => "bool_0", modifier => "&8", unit => "not supported,supported"},
2131             {name => "Calibration Verification Numbers", type => "bool_0", modifier => "&4", unit => "not supported,supported"},
2132             {name => "MessageCount IPT", type => "bool_0", modifier => "&2", unit => "not supported,supported"},
2133             {name => "In-use Performance Tracking", type => "bool_0", modifier => "&1", unit => "not supported,supported"},
2134            
2135             {name => "MessageCount ECUNAME", type => "bool_1", modifier => "&128", unit => "not supported,supported"},
2136             {name => "ECUNAME", type => "bool_1", modifier => "&64", unit => "not supported,supported"},
2137             # {name => "", type => "bool_1", modifier => "&32", unit => "not supported,supported"},
2138             # {name => "", type => "bool_1", modifier => "&16", unit => ""},
2139             # {name => "", type => "bool_1", modifier => "&8", unit => ""},
2140             # {name => "", type => "bool_1", modifier => "&4", unit => ""},
2141             # {name => "", type => "bool_1", modifier => "&2", unit => ""},
2142             # {name => "", type => "bool_1", modifier => "&1", unit => ""},
2143            
2144             # {name => "", type => "bool_2", modifier => "&128", unit => ""},
2145             # {name => "", type => "bool_2", modifier => "&64", unit => ""},
2146             # {name => "", type => "bool_2", modifier => "&32", unit => ""},
2147             # {name => "", type => "bool_2", modifier => "&16", unit => ""},
2148             # {name => "", type => "bool_2", modifier => "&8", unit => ""},
2149             # {name => "", type => "bool_2", modifier => "&4", unit => ""},
2150             # {name => "", type => "bool_2", modifier => "&2", unit => ""},
2151             # {name => "", type => "bool_2", modifier => "&1", unit => ""},
2152            
2153             # {name => "", type => "bool_3", modifier => "&128", unit => ""},
2154             # {name => "", type => "bool_3", modifier => "&64", unit => ""},
2155             # {name => "", type => "bool_3", modifier => "&32", unit => ""},
2156             # {name => "", type => "bool_3", modifier => "&16", unit => ""},
2157             # {name => "", type => "bool_3", modifier => "&8", unit => ""},
2158             # {name => "", type => "bool_3", modifier => "&4", unit => ""},
2159             # {name => "", type => "bool_3", modifier => "&2", unit => ""},
2160             # {name => "09 PIDs supported (41-60)", type => "bool_3", modifier => "&1", unit => "not supported,supported"},
2161             ] },
2162            
2163             "MessageCount VIN" => { command => "09 01", result => [{type => "byte_0", modifier => "+0", unit => ""}] },
2164             "Vehicle Identification Number" => { command => "09 02", result => [{type => "string_1", modifier => "", unit => ""}] },
2165             "MessageCount CALID" => { command => "09 03", result => [{type => "byte_0", modifier => "+0", unit => ""}] },
2166             "Calibration Identifications" => { command => "09 04", result => [{type => "string_1", modifier => "", unit => ""}] },
2167             "MessageCount CVN" => { command => "09 05", result => [{type => "byte_0", modifier => "+0", unit => ""}] },
2168             "Calibration Verification Numbers" => { command => "09 06", result => [{type => "dword_0", modifier => "+0", unit => ""}] },
2169             "MessageCount IPT" => { command => "09 07", result => [{type => "byte_0", modifier => "+0", unit => ""}] },
2170             "In-use Performance Tracking" => { command => "09 08",
2171             result => [
2172             {name => "OBD Monitoring Conditions Encountered Counts", type => "word_0", modifier => "+0", unit => ""},
2173             {name => "Ignition Counter", type => "word_1", modifier => "+0", unit => ""},
2174             {name => "Catalyst Monitor Completion Counts Bank 1", type => "word_2", modifier => "+0", unit => ""},
2175             {name => "Catalyst Monitor Conditions Encountered Counts Bank 1", type => "word_3", modifier => "+0", unit => ""},
2176             {name => "Catalyst Monitor Completion Counts Bank 2", type => "word_4", modifier => "+0", unit => ""},
2177             {name => "Catalyst Monitor Conditions Encountered Counts Bank 2", type => "word_5", modifier => "+0", unit => ""},
2178             {name => "O2 Sensor Monitor Completion Counts Bank 1", type => "word_6", modifier => "+0", unit => ""},
2179             {name => "O2 Sensor Monitor Conditions Encountered Counts Bank 1", type => "word_7", modifier => "+0", unit => ""},
2180             {name => "O2 Sensor Monitor Completion Counts Bank 2", type => "word_8", modifier => "+0", unit => ""},
2181             {name => "O2 Sensor Monitor Conditions Encountered Counts Bank 2", type => "word_9", modifier => "+0", unit => ""},
2182             {name => "EGR Monitor Completion Condition Counts", type => "word_10", modifier => "+0", unit => ""},
2183             {name => "EGR Monitor Conditions Encountered Counts", type => "word_11", modifier => "+0", unit => ""},
2184             {name => "AIR Monitor Completion Condition Counts (Secondary Air)", type => "word_12", modifier => "+0", unit => ""},
2185             {name => "AIR Monitor Conditions Encountered Counts (Secondary Air)", type => "word_13", modifier => "+0", unit => ""},
2186             {name => "EVAP Monitor Completion Condition Counts", type => "word_14", modifier => "+0", unit => ""},
2187             {name => "EVAP Monitor Conditions Encountered Counts", type => "word_15", modifier => "+0", unit => ""}
2188             ] },
2189             "MessageCount ECUNAME" => { command => "09 09", result => [{type => "byte_0", modifier => "+0", unit => ""}] },
2190             "ECUNAME" => { command => "09 0A", result => [{type => "string_0", modifier => "", unit => ""}] },
2191            
2192            
2193             "Permanent diagnostic trouble codes" => { command => "0A", available => 1,
2194             result => [
2195             {name => "DTC#1", type => "word_0", modifier => "+0", unit => ""},
2196             {name => "DTC#2", type => "word_1", modifier => "+0", unit => ""},
2197             {name => "DTC#3", type => "word_2", modifier => "+0", unit => ""},
2198             ] },
2199            
2200             };
2201            
2202            
2203 0 0         if (defined($replay_filename))
2204             {
2205 0           $self->Replay($replay_filename);
2206            
2207             # $self->ShowReadableValues();
2208             #print Dumper($self->{'get'});
2209             }
2210             else
2211             {
2212 0           $self->OpenPort($port_details);
2213 0           $self->ConfigureDevice();
2214 0           $self->FindAvailableCommands();
2215             }
2216            
2217 0           return $self;
2218             }
2219            
2220            
2221             #*****************************************************************
2222            
2223             =head2 PortOK
2224            
2225             Returns 1 if the serial port and ELM module are working or 0 if no ELM device could be connected to.
2226            
2227             $obd->PortOK();
2228             =cut
2229            
2230             sub PortOK
2231             {
2232 0     0 1   my ($self) = @_;
2233            
2234 0 0         if ($self->{'port'} == -1)
2235             {
2236 0 0         if ($self->{'debug_level'} > 0) { print "Serial port not initialised!\n"; }
  0            
2237 0           return 0;
2238             }
2239             else
2240             {
2241 0           return 1;
2242             }
2243             }
2244            
2245            
2246             #*****************************************************************
2247            
2248             =head2 ShowReadableValues
2249            
2250             Displays the list of values that can be read from the ELM/ECU.
2251            
2252             $obd->ShowReadableValues();
2253             =cut
2254            
2255             sub ShowReadableValues
2256             {
2257 0     0 1   my ($self) = @_;
2258            
2259 0           print "Values that the Read and Show functions can fetch from this vehicle:\n\n";
2260            
2261 0           while ( my ($parameter_name, $definition) = each %{$self->{'get'}} )
  0            
2262             {
2263 0 0 0       if (exists($definition->{'available'}) && $definition->{'available'} == 1)
2264             {
2265 0           print "Value: \"$parameter_name\"\n";
2266 0           print "Returns:\n";
2267 0           foreach my $result (@{$definition->{'result'}})
  0            
2268             {
2269 0 0         if (exists($result->{'name'}))
2270             {
2271 0           print "$result->{'name'}";
2272             }
2273             else
2274             {
2275 0           print "$parameter_name";
2276             }
2277 0 0 0       if (exists($result->{'unit'}) && $result->{'unit'} ne "")
    0          
2278             {
2279 0           print " ($result->{'unit'})";
2280             }
2281             elsif (substr($result->{'type'}, 0, 4) eq "bool")
2282             {
2283 0           print " (0 or 1)";
2284             }
2285 0           print "\n";
2286             }
2287 0           print "\n";
2288             }
2289             }
2290             }
2291            
2292            
2293             #*****************************************************************
2294            
2295             =head2 Show
2296            
2297             When passed the name of an OBD value (e.g. "Engine RPM") in $value_name,
2298             it displays the address of the ECU which returned the value, the name of
2299             the value which was read or the name of one of many parameters returned
2300             followed by the value and the name of any unit associated with the value.
2301            
2302             If an error occurred, a message will be displayed instead.
2303            
2304             $obd->Show($value_name);
2305            
2306             This function calls the 'Read' function.
2307             =cut
2308             sub Show
2309             {
2310 0     0 1   my ($self, $name, $parameter) = @_;
2311            
2312 0 0         if ($self->{'debug_level'} > 0) { print "~Show: $name\n"; }
  0            
2313            
2314 0           my $response = $self->Read($name, $parameter);
2315            
2316 0           print "$name:\n";
2317            
2318 0 0         if ($response->{'status'} eq "ok")
2319             {
2320 0           foreach my $result (@{$response->{'results'}})
  0            
2321             {
2322 0           print "$result->{'address'} - $result->{'name'}: $result->{'value'} $result->{'unit'}.";
2323 0 0         if (exists($result->{'min_limit'}))
2324             {
2325 0           print " Min: $result->{'min_limit'} $result->{'unit'}.";
2326             }
2327 0 0         if (exists($result->{'max_limit'}))
2328             {
2329 0           print " Max: $result->{'max_limit'} $result->{'unit'}.";
2330             }
2331 0           print "\n";
2332             }
2333             }
2334             else
2335             {
2336 0           print "$response->{'status_message'}\n";
2337             }
2338 0           print "\n";
2339            
2340 0           return $response;
2341             }
2342            
2343            
2344             #*****************************************************************
2345            
2346             =head2 Read
2347            
2348             When passed the name of an OBD value (e.g. "Engine RPM") in $value_name,
2349             it returns a reference to a structure containing a status flag and any
2350             responses:
2351            
2352             my $response = $obd->Read($value_name);
2353            
2354             if ($response->{'status'} eq "ok")
2355             {
2356             foreach my $result (@{$response->{'results'}})
2357             {
2358             print "$result->{'address'} - $result->{'name'}: $result->{'value'} $result->{'unit'}\n"
2359             }
2360             }
2361            
2362             In the example above, $result->{'address'} contains the address of the
2363             ECU which returned the value, $result->{'name'} contains the name of
2364             the value which was read or the name of one of many parameters returned.
2365             $result->{'value'} and $result->{'unit'} contain the value and the name
2366             of any unit associated with the value.
2367            
2368             Error conditions are indicated by a value of $response->{'status'} other
2369             than 'ok' and an expanded error message in $response->{'status_message'}
2370             (the default is 'No errors detected' when there is no error).
2371            
2372             Error Meaning
2373             ok No errors detected
2374             Zero length response No data was returned by the ECU
2375             NO DATA A 'NO DATA' response was returned by the ELM
2376             STOPPED A 'STOPPED' response was returned by the ELM
2377             Port not ok The connection to the ELM module failed
2378             Negative response The vehicle returned a negative response
2379             Unsupported name The vehicle does not support this value
2380             Unrecognised name ELM327.pm does not recognise this value
2381             =cut
2382            
2383             sub Read
2384             {
2385 0     0 1   my ($self, $name, $parameter) = @_;
2386            
2387 0           my $unit = "";
2388            
2389 0           my $results=();
2390            
2391 0           my $id;
2392             my $value;
2393            
2394 0 0         if ($self->{'debug_level'} > 0) { print "~Read: $name\n"; }
  0            
2395            
2396 0 0         if (exists($self->{'get'}->{$name}))
2397             {
2398 0 0 0       if (exists($self->{'get'}->{$name}->{'available'}) && $self->{'get'}->{$name}->{'available'} == 1)
2399             {
2400 0           my $command = $self->{'get'}->{$name}->{'command'};
2401            
2402 0 0 0       if (substr($name, 0, 12) eq "Freeze frame")
    0          
2403             {
2404 0 0         if (defined($parameter))
2405             {
2406 0           $command .= " ";
2407 0           $command .= sprintf("%02X", $parameter);
2408             }
2409             else
2410             {
2411 0           $command .= " 00"; # Default to freeze frame 0.
2412             }
2413             }
2414             elsif (substr($command, 0, 2) eq "05" && substr($command, 0, 5) ne "05 00")
2415             {
2416 0 0         if (defined($parameter))
2417             {
2418 0           $command .= " ";
2419 0           $command .= sprintf("%02X", $parameter);
2420             }
2421             else
2422             {
2423 0           $command .= " 01"; # Default to O2Sensor = Bank 1 - Sensor 1.
2424             }
2425             }
2426            
2427 0           $results->{'status'} = $self->Command($command);
2428            
2429 0 0         if ($results->{'status'} ne "ok")
2430             {
2431 0           $results->{'status_message'} = $self->{'status_meanings'}->{$results->{'status'}};
2432 0           return $results;
2433             }
2434            
2435 0 0 0       if (substr($command, 0, 2) eq "06" && substr($command, 0, 5) ne "06 00"
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
2436             && substr($command, 0, 5) ne "06 20" && substr($command, 0, 5) ne "06 40"
2437             && substr($command, 0, 5) ne "06 60" && substr($command, 0, 5) ne "06 80"
2438             && substr($command, 0, 5) ne "06 A0" && substr($command, 0, 5) ne "06 C0"
2439             && substr($command, 0, 5) ne "06 E0" && $self->{'bus_type'} eq "CAN") # Command 6 works differently from 1,2,5,9 etc.
2440             {
2441 0           $self->GetResultsCommand06_CAN(\$results);
2442             }
2443             else
2444             {
2445 0           foreach my $result (@{$self->{'get'}->{$name}->{'result'}})
  0            
2446             {
2447 0 0         if ($self->{'debug_level'} > 2) { print Dumper($result); }
  0            
2448 0 0         if (exists($result->{'name'}))
2449             {
2450 0           $id = $result->{'name'};
2451             }
2452             else
2453             {
2454 0           $id = $name;
2455             }
2456            
2457             # Parse the result type...
2458 0           my @type = split('_', , $result->{'type'});
2459            
2460 0           my $index = 0;
2461 0           my $sign = 0;
2462 0 0         if ($type[0] eq "signed")
2463             {
2464 0           $sign = 1;
2465 0           $index = 1;
2466             }
2467            
2468 0 0         if ($type[$index] eq "AT")
2469             {
2470 0           $value = ${$self->{'response'}}[0];
  0            
2471            
2472 0 0         if (defined($result->{'modifier'}))
2473             {
2474 0           my $statement = '$value' . $result->{'modifier'};
2475 0           eval( $statement ); # Allow the use of a regex if required
2476 0 0         if ($self->{'debug_level'} > 2) { print "Statement: $statement\n"; }
  0            
2477             }
2478            
2479 0 0         if ($self->{'debug_level'} > 1) { print "$id, $value$result->{'unit'}\n"; }
  0            
2480 0           push @{$results->{'results'}},{name => $id, value => $value, unit => $result->{'unit'}, address => "ELM327"};
  0            
2481             }
2482             else
2483             {
2484 0           $value = $self->GetResult($type[$index], $type[$index+1]);
2485 0 0         if ($self->{'debug_level'} > 2) { print "GetResult value: $value\n"; }
  0            
2486            
2487 0           my $iteration = 0;
2488 0           foreach $value (@{$self->{'command_results'}})
  0            
2489             {
2490 0 0         if ($self->{'debug_level'} > 2) { print "Raw value: $value\n"; }
  0            
2491            
2492 0 0         if ($value ne "no result")
2493             {
2494 0           $unit = $result->{'unit'};
2495            
2496 0 0 0       if ($type[$index] eq "byte" && $type[0] eq "signed")
    0 0        
2497             {
2498 0           my $byte_sign_mask = 128;
2499 0           my $byte_value_mask = 127;
2500            
2501 0           $value = ($value & $byte_value_mask) - ($value & $byte_sign_mask);
2502             }
2503             elsif ($type[$index] eq "word" && $type[0] eq "signed")
2504             {
2505 0           my $word_sign_mask = 32768;
2506 0           my $word_value_mask = 32767;
2507            
2508 0           $value = ($value & $word_value_mask) - ($value & $word_sign_mask);
2509             }
2510            
2511 0 0         if ($type[$index] ne "string")
2512             {
2513 0 0         if ($self->{'debug_level'} > 2) { print "$value $result->{'modifier'}\n"; }
  0            
2514 0           $value = eval( "$value $result->{'modifier'}" );
2515 0 0         if ($self->{'debug_level'} > 2) { print "$value\n"; }
  0            
2516            
2517             }
2518             else
2519             {
2520 0           my $statement = '$value' . $result->{'modifier'};
2521 0           eval( $statement ); # Allow the use of a regex if required
2522 0 0         if ($self->{'debug_level'} > 2) { print "Statement: $statement\n"; }
  0            
2523            
2524             }
2525            
2526 0 0         if ($type[$index] eq "bool")
2527             {
2528 0 0         if ($value != 0) { $value = 1; } # Other bits are masked out.
  0            
2529 0 0         if ($unit ne "")
2530             {
2531 0           my @meanings = split(',', $unit);
2532 0           $unit = "($meanings[$value])";
2533             }
2534             }
2535            
2536 0 0         if (exists($result->{'alternatives'}))
2537             {
2538 0           foreach my $alternative (@{$result->{'alternatives'}})
  0            
2539             {
2540 0 0         if ($alternative->{'value'} == $value)
2541             {
2542 0           $value = $alternative->{'meaning'};
2543 0           last;
2544             }
2545             }
2546             }
2547             }
2548            
2549            
2550 0 0         if ($self->{'debug_level'} > 2) { print "$id, $value $unit\n"; }
  0            
2551            
2552 0 0 0       if ($command eq "03" || $command eq "07" || $command eq "0A")
      0        
2553             {
2554 0           push @{$results->{'results'}},{name => $id, value_read => $value, value => $self->DecodeTroubleCode($value), unit => $unit, address => ${$self->{'command_addresses'}}[$iteration]};
  0            
  0            
2555             }
2556             else
2557             {
2558 0           push @{$results->{'results'}},{name => $id, value => $value, unit => $unit, address => ${$self->{'command_addresses'}}[$iteration]};
  0            
  0            
2559             }
2560 0           $iteration++;
2561             }
2562 0           $self->{'command_results'} = [];
2563             }
2564             }
2565             }
2566             }
2567             else
2568             {
2569 0 0         if ($self->{'debug_level'} > 2) { print "Unsupported name: $name\n"; }
  0            
2570 0           $results->{'status'} = "Unsupported name";
2571             }
2572             }
2573             else
2574             {
2575 0 0         if ($self->{'debug_level'} > 2) { print "Unrecognised name: $name\n"; }
  0            
2576 0           $results->{'status'} = "Unrecognised name";
2577             }
2578            
2579 0           $results->{'status_message'} = $self->{'status_meanings'}->{$results->{'status'}};
2580 0           return $results;
2581             }
2582            
2583            
2584             #*****************************************************************
2585            
2586             =head2 ShowTroubleCodes
2587            
2588             Display any trouble codes on the console:
2589            
2590             $obd->ShowTroubleCodes();
2591             =cut
2592            
2593             sub ShowTroubleCodes
2594             {
2595 0     0 1   my ($self) = @_;
2596            
2597 0           my $malfunction_indicator_lamp_mask = 128;
2598 0           my $number_of_codes_mask = 127;
2599            
2600 0 0         if ($self->{'debug_level'} > 0) { print "ShowTroubleCodes\n"; }
  0            
2601            
2602 0           $self->Command("01 01"); # Get number of trouble codes
2603            
2604 0           my $number_of_codes = $self->GetResult("byte");
2605            
2606 0           my $malfunction_indicator_lamp_state = $number_of_codes & $malfunction_indicator_lamp_mask;
2607 0           $number_of_codes &= $number_of_codes_mask;
2608            
2609 0           print "Malfunction indicator lamp state: ";
2610 0 0         if ($malfunction_indicator_lamp_state > 0)
2611             {
2612 0           print "ON\n";
2613             }
2614             else
2615             {
2616 0           print "OFF\n";
2617             }
2618            
2619 0 0 0       if ($number_of_codes > 0 || $malfunction_indicator_lamp_state > 0)
2620             {
2621 0           print "$number_of_codes trouble code";
2622 0 0         if ($number_of_codes != 1) { print "s"; }
  0            
2623 0           print ":\n";
2624            
2625 0           $self->Show("Emission-related diagnostic trouble codes");
2626 0           $self->Show("Emission-related diagnostic trouble codes detected during current or last completed driving cycle");
2627             }
2628             else
2629             {
2630 0           print "No trouble codes found.\n";
2631             }
2632             }
2633            
2634            
2635             #*****************************************************************
2636            
2637             =head2 ClearTroubleCodes
2638            
2639             Clear any Trouble Codes and sensor data:
2640            
2641             $obd->ClearTroubleCodes();
2642            
2643             Note that clearing the sensor data will cause the vehicle to run on
2644             default values until it has recalibrated itself. This may affect
2645             performance and fuel economy.
2646            
2647             The ISO specification also insists that any user interface which
2648             invokes this function should display an "are you sure?" message
2649             to the user before calling it.
2650            
2651             =cut
2652            
2653             sub ClearTroubleCodes
2654             {
2655 0     0 1   my ($self) = @_;
2656            
2657 0 0         if ($self->{'debug_level'} > 0) { print "~ClearTroubleCodes\n"; }
  0            
2658 0           $self->Command("04"); # Clear Trouble Codes and sensor data
2659            
2660 0           my $result = $self->GetResult("byte");
2661            
2662 0           return $result; # Returns 0 if codes have been cleared or error code.
2663             }
2664            
2665            
2666             #*****************************************************************
2667            
2668             =head2 DecodeTroubleCode
2669            
2670             Expand a trouble code (e.g. 4216) to the full ISO code (C0216)
2671            
2672             This function is called by 'Read'.
2673            
2674             $decoded_code = $obd->DecodeTroubleCode($code);
2675             =cut
2676            
2677             sub DecodeTroubleCode
2678             {
2679 0     0 1   my ($self, $code) = @_;
2680            
2681 0           my @codes = ("P0","P1","P2","P3","C0","C1","C2","C3","B0","B1","B2","B3","U0","U1","U2","U3");
2682            
2683 0           my $code_prefix_mask = 61440;
2684 0           my $code_mask = 4095;
2685 0           my $number_of_codes_mask = 127;
2686            
2687 0 0 0       if ($code eq "no result" || $code == 0)
2688             {
2689 0           return "No Trouble Code";
2690             }
2691            
2692 0           my $code_prefix = ($code & $code_prefix_mask) >> 12;
2693 0           $code &= $code_mask;
2694 0           $code = sprintf("%03X", $code);
2695 0           my $decoded_code = "$codes[$code_prefix]$code";
2696            
2697 0 0         if ($self->{'debug_level'} > 1)
2698             {
2699 0           print "Code prefix: $code_prefix, Code: $code, Decoded: $decoded_code\n";
2700             }
2701 0           return $decoded_code;
2702             }
2703            
2704            
2705             #*****************************************************************
2706            
2707             =head2 CalibrateVoltage
2708            
2709             Changes the calibration value used by the ELM module. The value
2710             $Voltage is a string containing a fixed point value of the form:
2711             xx.xx, e.g "11.99", "12.01" etc.
2712            
2713             $obd->CalibrateVoltage($Voltage);
2714            
2715             The Voltage can be read by calling:
2716            
2717             my $response = $obd->read("Input Voltage");
2718            
2719             =cut
2720            
2721             sub CalibrateVoltage
2722             {
2723 0     0 1   my ($self, $Voltage) = @_;
2724            
2725 0 0         if ($self->{'debug_level'} > 0) { print "~CalibrateVoltage: $Voltage\n"; }
  0            
2726            
2727 0           $self->Command("AT CV $Voltage"); # Calibrate Voltage
2728 0           return ${$self->{'response'}}[0];
  0            
2729             }
2730            
2731            
2732             #*****************************************************************
2733            
2734             =head2 ResetVoltage
2735            
2736             Resets the ELM module's Voltage calibration to the factory setting:
2737            
2738             $obd->ResetVoltage();
2739             =cut
2740            
2741             sub ResetVoltage
2742             {
2743 0     0 1   my ($self) = @_;
2744            
2745 0 0         if ($self->{'debug_level'} > 0) { print "~ResetVoltage:\n"; }
  0            
2746            
2747 0           $self->Command("AT CV 0000"); # Reset Voltage to factory setting
2748 0           return ${$self->{'response'}}[0];
  0            
2749             }
2750            
2751            
2752             #*****************************************************************
2753            
2754             =head2 WriteStoredDataByte
2755            
2756             Writes $byte_value to the ELM module's non-volatile storage area.
2757            
2758             $obd->WriteStoredDataByte($byte_value);
2759            
2760             The value of this byte can be read using:
2761            
2762             $obd->Read("Stored data byte");
2763            
2764             =cut
2765            
2766             sub WriteStoredDataByte
2767             {
2768 0     0 1   my ($self, $value) = @_;
2769            
2770 0 0         if ($self->{'debug_level'} > 0) { print "~WriteStoredDataByte: $value\n"; }
  0            
2771            
2772 0           $self->Command("AT SD $value"); # Save Data byte value
2773 0           return ${$self->{'response'}}[0];
  0            
2774             }
2775            
2776            
2777             #*****************************************************************
2778            
2779             =head2 Command
2780            
2781             Send a command to the ELM, read any response and decode it if
2782             was an ECU command.
2783             AT command responses are placed in the $self->{'response'} array.
2784             Responses to ECU commands are written to the $self->{'results'}
2785             structure. On return a status of 0 indicates no errors.
2786            
2787             This function is called by other module functions 'Read',
2788             'ClearTroubleCodes' etc., but can be used to send commands that aren't
2789             otherwise supported.
2790            
2791             $status = $obd->Command($command_string);
2792             =cut
2793            
2794             sub Command
2795             {
2796 0     0 1   my ($self, $command) = @_;
2797            
2798 0           my $status = "ok";
2799            
2800 0 0         if ($self->{'debug_level'} > 0) { print "~Command: $command\n"; }
  0            
2801 0           my @command_parts = split(' ', $command);
2802            
2803 0           $status = $self->WriteCommand("$command");
2804            
2805             do
2806 0           {
2807 0           $status = $self->ReadResponse();
2808            
2809 0 0 0       if ($command_parts[0] ne "AT" && $status eq "ok")
2810             {
2811 0           $self->{'last_command'} = hex($command_parts[0]);
2812 0 0         if ($has_sub_command[$self->{'last_command'}])
2813             {
2814 0           $self->{'last_sub_command'} = hex($command_parts[1]);
2815             }
2816             else
2817             {
2818 0           $self->{'last_sub_command'} = 0;
2819             }
2820            
2821 0           $status = $self->DecodeResponse();
2822             }
2823            
2824             } while ($status eq "Request Correctly Received - Response Pending");
2825            
2826 0           return $status;
2827             }
2828            
2829            
2830             #*****************************************************************
2831            
2832             =head2 GetResult
2833            
2834             Returns a value from the last set of results from the ELM/ECU
2835            
2836             $type can be one of the following:
2837             bool (1 bit), byte (8 bit), word (16 bit), dword (32 bit) or string.
2838             $number is the zero-based index into the array of results and takes
2839             the type into account such that $number=0 returns the first byte,
2840             word or dword and $number=1, returns the second.
2841             Booleans are treated the same as bytes and require individual bits
2842             to be extracted separately.
2843             For strings, $number is the offset of the start of the string.
2844            
2845             This function is called by 'Read'.
2846            
2847             $obd->GetResult($type, $number);
2848             =cut
2849            
2850             sub GetResult
2851             {
2852 0     0 1   my ($self, $type, $number) = @_;
2853            
2854 0           my $result;
2855 0           $self->{'number_of_results'} = 0;
2856            
2857 0 0         if (!defined($number)) { $number = 0; }
  0            
2858            
2859 0 0         if ($self->{'debug_level'} > 1) { print "GetResult: Type: $type: Number: $number\n"; }
  0            
2860            
2861 0           foreach my $address (sort keys %{$self->{'results'}})
  0            
2862             {
2863 0           my $number_of_result_bytes = $self->{'results'}->{$address}->{'response_length'};
2864 0 0 0       if ($self->{'results'}->{$address}->{'command'} == $self->{'last_command'} &&
2865             $self->{'results'}->{$address}->{'sub_command'} == $self->{'last_sub_command'})
2866             {
2867 0 0         if ($type eq "bool")
    0          
    0          
    0          
    0          
2868             {
2869 0 0         if ($number_of_result_bytes < ($number+1))
2870             {
2871 0           $result = "no result";
2872             }
2873             else
2874             {
2875 0           $result = ${$self->{'results'}->{$address}->{'result'}}[$number];
  0            
2876             }
2877 0           push @{$self->{'command_addresses'}}, $address;
  0            
2878 0           push @{$self->{'command_results'}}, $result;
  0            
2879 0           $self->{'number_of_results'}++;
2880             }
2881             elsif ($type eq "byte")
2882             {
2883 0 0         if ($number_of_result_bytes < ($number+1))
2884             {
2885 0           $result = "no result";
2886             }
2887             else
2888             {
2889 0           $result = ${$self->{'results'}->{$address}->{'result'}}[$number];
  0            
2890             }
2891 0           push @{$self->{'command_addresses'}}, $address;
  0            
2892 0           push @{$self->{'command_results'}}, $result;
  0            
2893 0           $self->{'number_of_results'}++;
2894             }
2895             elsif ($type eq "word")
2896             {
2897 0 0         if ($number_of_result_bytes < (($number*2)+2))
2898             {
2899 0 0         if ($self->{'debug_level'} > 2) { print "Number of result bytes: $number_of_result_bytes\n"; }
  0            
2900 0           $result = "no result";
2901             }
2902             else
2903             {
2904 0           $result = ((${$self->{'results'}->{$address}->{'result'}}[$number*2] * 256) + ${$self->{'results'}->{$address}->{'result'}}[($number*2)+1] );
  0            
  0            
2905             }
2906 0           push @{$self->{'command_addresses'}}, $address;
  0            
2907 0           push @{$self->{'command_results'}}, $result;
  0            
2908 0           $self->{'number_of_results'}++;
2909             }
2910             elsif ($type eq "dword")
2911             {
2912 0 0         if ($number_of_result_bytes < (($number*4)+4))
2913             {
2914 0           $result = "no result";
2915             }
2916             else
2917             {
2918 0           $result = ((${$self->{'results'}->{$address}->{'result'}}[$number*4] * 16777216) + ${$self->{'results'}->{$address}->{'result'}}[($number*4)+1] * 65536);
  0            
  0            
2919 0           $result += ((${$self->{'results'}->{$address}->{'result'}}[($number*4)+2] * 256) + ${$self->{'results'}->{$address}->{'result'}}[($number*4)+3] );
  0            
  0            
2920             }
2921 0           push @{$self->{'command_addresses'}}, $address;
  0            
2922 0           push @{$self->{'command_results'}}, $result;
  0            
2923 0           $self->{'number_of_results'}++;
2924             }
2925             elsif ($type eq "string")
2926             {
2927 0 0         if ($number_of_result_bytes < $number)
2928             {
2929 0           $result = "no result";
2930             }
2931             else
2932             {
2933 0           $result = "";
2934 0           foreach (@{$self->{'results'}->{$address}->{'result'}})
  0            
2935             {
2936 0 0         if ($number > 0)
2937             {
2938 0           $number--;
2939             }
2940             else
2941             {
2942 0 0 0       if ($_ > 32 && $_ < 127) # Ignore non-printable characters
2943             {
2944 0           $result .= chr($_);
2945             }
2946             }
2947             }
2948             }
2949 0           push @{$self->{'command_addresses'}}, $address;
  0            
2950 0           push @{$self->{'command_results'}}, $result;
  0            
2951 0           $self->{'number_of_results'}++;
2952             }
2953             }
2954             else
2955             {
2956 0           $result = 0;
2957             }
2958             }
2959            
2960 0           return $result;
2961             }
2962            
2963            
2964             #*****************************************************************
2965            
2966            
2967             =head2 WriteCommand
2968            
2969             Write a command to the serial port unless replay is in progress.
2970            
2971             This function is called by the 'Command' function.
2972            
2973             $status = $obd->WriteCommand($command_string);
2974             =cut
2975            
2976             sub WriteCommand
2977             {
2978 0     0 1   my ($self, $command) = @_;
2979            
2980 0           my $status = "ok";
2981            
2982 0 0         if ($self->{'debug_level'} > 0) { print "~WriteCommand: $command\n"; }
  0            
2983            
2984 0 0         if ($self->{'replay_file'} == 0)
2985             {
2986 0 0         if ($self->PortOK)
2987             {
2988 0           $command .= "$cr$lf";
2989 0           $self->{'port'}->write("$command");
2990             }
2991             else
2992             {
2993 0           $status = "Port not ok";
2994             }
2995             }
2996            
2997 0           return $status;
2998             }
2999            
3000             #*****************************************************************
3001            
3002             =head2 ReadResponse
3003            
3004             Read the ELM's response from the serial port and put each line
3005             into the $self->{'response'} array.
3006             Turn on debugging for a dump of the response array.
3007            
3008             This function is called by the 'Command' function.
3009            
3010             $status = $obd->ReadResponse();
3011             =cut
3012            
3013             sub ReadResponse
3014             {
3015 0     0 1   my ($self) = @_;
3016            
3017 0           my $bytes_to_read = 1;
3018 0           my $count_in = 0;
3019 0           my $string_in = "";
3020 0           my $status = "ok";
3021 0           my $timeout = 4; # Command 01 04 failed when timeout was 2
3022 0           my $line = "";
3023 0           $self->{'response'} = (); # Array of strings, one per line of the response.
3024 0           $self->{'response_length'} = 0;
3025            
3026 0 0         if ($self->{'debug_level'} > 1) { print "ReadResponse\n"; }
  0            
3027            
3028 0 0 0       if ($self->{'replay_file'} == 0 && $self->PortOK)
3029             {
3030             do
3031 0   0       {
3032 0           ($count_in, $string_in) = $self->{'port'}->read($bytes_to_read);
3033 0 0 0       if ($count_in == $bytes_to_read && $string_in ne $null)
3034             {
3035 0           $line .= $string_in;
3036 0           $self->{'response_length'}++;
3037             }
3038             else
3039             {
3040 0           sleep 1;
3041 0           $timeout--;
3042             }
3043             } while ($count_in == 0 && $timeout>0);
3044            
3045             do
3046 0           {
3047 0           ($count_in, $string_in) = $self->{'port'}->read($bytes_to_read);
3048 0 0         if ($count_in == $bytes_to_read)
3049             {
3050 0 0 0       if ($string_in ne ">" && $string_in ne $null)
3051             {
3052 0 0         if ($string_in eq $cr)
3053             {
3054 0 0         if ($line ne "")
3055             {
3056 0           push @{$self->{'response'}}, $line;
  0            
3057 0           $line = "";
3058             }
3059             }
3060             else
3061             {
3062 0           $line .= $string_in;
3063 0           $self->{'response_length'}++;
3064             }
3065             }
3066             }
3067             } while ($count_in == $bytes_to_read);
3068             }
3069             else
3070             {
3071             # Load in the lines of the response from the replay file
3072 0           while (scalar(@{$self->{'replay_response'}}) > 0)
  0            
3073             {
3074 0           $line = shift @{$self->{'replay_response'}};
  0            
3075 0           push @{$self->{'response'}}, $line;
  0            
3076 0           $self->{'response_length'} += length($line);
3077             }
3078             }
3079            
3080 0 0         if ($self->{'response_length'} == 0)
    0          
    0          
3081             {
3082 0           $status = "Zero length response";
3083             }
3084             elsif ($self->{'response'}[0] eq "NO DATA")
3085             {
3086 0           $status = "NO DATA";
3087             }
3088             elsif ($self->{'response'}[0] eq "STOPPED")
3089             {
3090 0           $status = "STOPPED";
3091             }
3092            
3093 0 0         if ($self->{'debug_level'} > 0)
3094             {
3095 0           print "Response\n";
3096 0           foreach (@{$self->{'response'}})
  0            
3097             {
3098 0           print "$_\n";
3099             }
3100 0           print "End of response\n";
3101             }
3102            
3103 0           return $status;
3104             }
3105            
3106            
3107             #*****************************************************************
3108            
3109             =head2 DecodeResponse
3110            
3111             Decode the ECU response (in the $self->{'response'} array) and
3112             write the result to the $self->{'results'} structure.
3113            
3114             This function is called by the 'Command' function.
3115            
3116             $status = $obd->DecodeResponse();
3117             =cut
3118            
3119             sub DecodeResponse
3120             {
3121 0     0 1   my ($self) = @_;
3122            
3123 0           my $status = "ok";
3124 0           my $results = {};
3125 0           my $command_mask = 63;
3126 0           my $line_number = 0;
3127 0           my $result_string;
3128            
3129 0           $self->{'command_addresses'} = [];
3130 0           $self->{'command_results'} = [];
3131 0           $self->{'number_of_results'} = 0;
3132            
3133 0 0         if ($self->{'debug_level'} > 1)
3134             {
3135 0           print "\nDecodeResponse\n";
3136 0           print "Lines: ".scalar(@{$self->{'response'}})."\n";
  0            
3137             }
3138            
3139 0           for (keys %{$self->{'results'}})
  0            
3140             {
3141 0           delete $self->{'results'}->{$_};
3142             }
3143            
3144 0           foreach (@{$self->{'response'}})
  0            
3145             {
3146 0           my @line_parts = split(' ', $_);
3147 0 0         if (scalar(@line_parts) > 2)
3148             {
3149 0           my $address = shift @line_parts;
3150 0 0         if (length($address) < 3)
3151             {
3152             # Not CAN ($address contains the priority byte)
3153 0 0         if ($self->{'debug_level'} > 4) { print "Response type: SAE J1979\n"; }
  0            
3154 0           $line_number++;
3155 0           my $recipient_address = shift @line_parts;
3156 0           $address = shift @line_parts; # Transmitter address
3157 0           $self->{'results'}->{$address}->{'response_code'} = 0;
3158 0           $self->{'results'}->{$address}->{'format'} = "Other";
3159 0           $self->{'results'}->{$address}->{'command'} = (hex(shift @line_parts) & $command_mask);
3160 0 0         if ($self->{'results'}->{$address}->{'command'} == 4) { push(@line_parts, "00"); }
  0            
3161 0 0         if ($self->{'results'}->{$address}->{'command'} == $command_mask)
3162             {
3163 0           $self->{'results'}->{$address}->{'command'} = (hex(shift @line_parts));
3164             }
3165 0 0         if ($has_sub_command[$self->{'results'}->{$address}->{'command'}])
3166             {
3167 0           $self->{'results'}->{$address}->{'sub_command'} = hex(shift @line_parts);
3168             }
3169             else
3170             {
3171 0           $self->{'results'}->{$address}->{'sub_command'} = 0;
3172             }
3173 0 0         if ($self->{'results'}->{$address}->{'command'} == 2)
    0          
    0          
3174             {
3175 0           $self->{'results'}->{$address}->{'frame'} = hex(shift @line_parts);
3176             }
3177             elsif ($self->{'results'}->{$address}->{'command'} == 5)
3178             {
3179 0           $self->{'results'}->{$address}->{'O2sensor'} = hex(shift @line_parts);
3180             }
3181             elsif ($self->{'results'}->{$address}->{'command'} == 6)
3182             {
3183 0           $self->{'results'}->{$address}->{'Limit_type_and_component_id'} = hex(shift @line_parts);
3184             }
3185 0 0         if (exists($self->{'results'}->{$address}->{'response_length'}))
3186             {
3187 0           $self->{'results'}->{$address}->{'response_length'} += hex(scalar(@line_parts));
3188             }
3189             else
3190             {
3191 0           $self->{'results'}->{$address}->{'response_length'} = hex(scalar(@line_parts));
3192             }
3193             }
3194             else
3195             {
3196             # CAN
3197 0 0         if ($self->{'debug_level'} > 4) { print "Response type: CAN\n"; }
  0            
3198 0           $self->{'results'}->{$address}->{'response_code'} = 0;
3199 0           $self->{'results'}->{$address}->{'format'} = "CAN";
3200 0           $line_number = hex(shift @line_parts);
3201            
3202 0 0         if ($line_number <= 16)
3203             {
3204 0 0         if ($line_number == 16)
3205             {
3206 0           $self->{'results'}->{$address}->{'response_length'} = hex(shift @line_parts);
3207             }
3208            
3209 0           $self->{'results'}->{$address}->{'command'} = (hex(shift @line_parts) & $command_mask); # Error code will now be 63 rather than 7F
3210            
3211 0 0         if ($line_number < 16)
3212             {
3213 0 0 0       if ($has_sub_command[$self->{'results'}->{$address}->{'command'}] || $self->{'results'}->{$address}->{'command'} == $command_mask)
3214             {
3215 0           $self->{'results'}->{$address}->{'response_length'} = $line_number - 2; # Do not include command and sub-command bytes
3216             }
3217             else
3218             {
3219 0           $self->{'results'}->{$address}->{'response_length'} = $line_number - 1; # Do not include command byte (no sub-command byte)
3220             }
3221             }
3222            
3223 0 0         if ($self->{'results'}->{$address}->{'command'} == 4) { push(@line_parts, "00"); } # Command 04 only returns a 44 SID on success. Append a 0 byte to the result.
  0            
3224            
3225 0 0         if ($self->{'results'}->{$address}->{'command'} == $command_mask) # If there was an error, shift out the real command number.
3226             {
3227 0           $self->{'results'}->{$address}->{'command'} = (hex(shift @line_parts));
3228 0           $self->{'results'}->{$address}->{'response_code'} = $line_parts[0];
3229             }
3230             else
3231             {
3232 0 0         if ($has_sub_command[$self->{'results'}->{$address}->{'command'}])
3233             {
3234 0           $self->{'results'}->{$address}->{'sub_command'} = hex(shift @line_parts);
3235             }
3236             else
3237             {
3238 0           $self->{'results'}->{$address}->{'sub_command'} = 0;
3239             }
3240 0 0         if ($self->{'results'}->{$address}->{'command'} == 2)
3241             {
3242 0           $self->{'results'}->{$address}->{'frame'} = hex(shift @line_parts);
3243             }
3244             }
3245             }
3246             }
3247 0           $self->{'bus_type'} = $self->{'results'}->{$address}->{'format'};
3248 0           $results->{$address}->{$line_number} = join(" ", @line_parts);
3249 0           $self->{'results'}->{$address}->{'response_reason'} = $self->{'negative_response_codes'}->{$self->{'results'}->{$address}->{'response_code'}};
3250 0           $status = $self->{'results'}->{$address}->{'response_reason'};
3251             }
3252             }
3253            
3254 0 0         if ($self->{'debug_level'} > 2)
3255             {
3256 0           print "Decoded results:\n";
3257 0           print Dumper($results);
3258             }
3259            
3260 0           foreach my $address (sort keys %{$results})
  0            
3261             {
3262 0           $result_string = "";
3263 0           foreach my $line (sort keys %{$results->{$address}})
  0            
3264             {
3265 0           $result_string .= "$results->{$address}->{$line} ";
3266             }
3267 0           @{$self->{'results'}->{$address}->{'result'}} = split(' ', $result_string);
  0            
3268            
3269            
3270             #Now turn the hex byte strings into numbers...
3271 0           foreach (@{$self->{'results'}->{$address}->{'result'}})
  0            
3272             {
3273 0           $_ = hex($_);
3274             }
3275             }
3276            
3277 0 0         if ($self->{'debug_level'} > 1)
3278             {
3279 0           print "\nFully decoded results:\n";
3280 0           print Dumper($self->{'results'});
3281             }
3282            
3283 0           return $status;
3284             }
3285            
3286            
3287             #*****************************************************************
3288            
3289             =head2 GetResultsCommand06_CAN
3290            
3291             Get the results for command 06 on a CAN system.
3292            
3293             This function is called by 'Read' and is not intended to be called by
3294             other functions.
3295            
3296             $obd->GetResultsCommand06_CAN($results_reference);
3297             =cut
3298            
3299             sub GetResultsCommand06_CAN
3300             {
3301 0     0 1   my ($self, $results_ref) = @_;
3302            
3303 0           my $results = $$results_ref;
3304            
3305 0           foreach my $address (sort keys %{$self->{'results'}})
  0            
3306             {
3307 0           my $index = 0;#1;
3308 0           my $number_of_header_bytes = 2; # Allow for TID and OBDMIDID
3309 0           my $number_of_result_bytes = $self->{'results'}->{$address}->{'response_length'} - $number_of_header_bytes;
3310             do
3311 0           {
3312 0 0         if ($index != 0)
3313             {
3314 0           $index++; # Skip over OBDMIDID in subsequent records.
3315             }
3316             # my $obdmid_id = ${$self->{'results'}->{$address}->{'result'}}[$index];
3317 0           my $sdt_id = ${$self->{'results'}->{$address}->{'result'}}[$index];
  0            
3318 0           my $uas_id = ${$self->{'results'}->{$address}->{'result'}}[$index+1];
  0            
3319            
3320 0           my $test_value = ${$self->{'results'}->{$address}->{'result'}}[$index+2] * 256;
  0            
3321 0           $test_value += ${$self->{'results'}->{$address}->{'result'}}[$index+3];
  0            
3322            
3323 0           my $min_test_limit = ${$self->{'results'}->{$address}->{'result'}}[$index+4] * 256;
  0            
3324 0           $min_test_limit += ${$self->{'results'}->{$address}->{'result'}}[$index+5];
  0            
3325            
3326 0           my $max_test_limit = ${$self->{'results'}->{$address}->{'result'}}[$index+6] * 256;
  0            
3327 0           $max_test_limit += ${$self->{'results'}->{$address}->{'result'}}[$index+7];
  0            
3328            
3329 0           my $test_name = "Unrecognised test Id ($sdt_id)";
3330            
3331 0 0         if (exists($self->{'Standardized_Test_IDs'}->{$sdt_id}))
3332             {
3333 0           $test_name = $self->{'Standardized_Test_IDs'}->{$sdt_id}->{'name'};
3334             }
3335            
3336 0           my $unit = "unknown";
3337            
3338 0 0         if ($uas_id >= 128)
3339             {
3340 0           my $word_sign_mask = 32768;
3341 0           my $word_value_mask = 32767;
3342            
3343 0           $test_value = ($test_value & $word_value_mask) - ($test_value & $word_sign_mask);
3344 0           $min_test_limit = ($min_test_limit & $word_value_mask) - ($min_test_limit & $word_sign_mask);
3345 0           $max_test_limit = ($max_test_limit & $word_value_mask) - ($max_test_limit & $word_sign_mask);
3346             }
3347            
3348 0 0         if (exists($self->{'unit_and_scaling_identifiers'}->{$uas_id}))
3349             {
3350 0           $unit = $self->{'unit_and_scaling_identifiers'}->{$uas_id}->{'unit'};
3351            
3352 0           $test_value = eval( "$test_value $self->{'unit_and_scaling_identifiers'}->{$uas_id}->{'modifier'}" );
3353 0           $min_test_limit = eval( "$min_test_limit $self->{'unit_and_scaling_identifiers'}->{$uas_id}->{'modifier'}" );
3354 0           $max_test_limit = eval( "$max_test_limit $self->{'unit_and_scaling_identifiers'}->{$uas_id}->{'modifier'}" );
3355             }
3356            
3357 0           push @{$results->{'results'}},{address => $address, name => $test_name, value => $test_value, max_limit => $max_test_limit, min_limit => $min_test_limit, unit => $unit};
  0            
3358            
3359 0           $index += 8;
3360             } while(($index+8) < $number_of_result_bytes);
3361             }
3362            
3363 0 0         if ($self->{'debug_level'} > 2)
3364             {
3365 0           print "Command 06 - results:\n";
3366 0           print Dumper($self->{'results'});
3367             }
3368             }
3369            
3370            
3371             #*****************************************************************
3372            
3373             =head2 OpenPort
3374            
3375             Try to find an ELM module on a COM port.
3376             If $port_details contains the name of a port, start with that one and
3377             work upwards.
3378            
3379             To override the default serial port settings (38400, no parity, 8 data
3380             bits, 1 stop bit, no handshaking), you can pass values in $port_details
3381             in the following format:
3382            
3383             port_name:baud_rate:parity:data_bits:stop_bits:handshake
3384            
3385             e.g.
3386            
3387             $port_details = "/dev/ttyUSB0:115200:none:8:1:none";
3388            
3389             The port name may be left out:
3390            
3391             $port_details = "115200:none:8:1:none";
3392            
3393             It is also ok to just define the port name and/or baud rate and use
3394             default values for parity, data bits, stop bits and handshake:
3395            
3396             $port_details = "/dev/ttyUSB0:115200";
3397             or
3398             $port_details = "115200";
3399            
3400            
3401             This function is called by 'new'.
3402            
3403             $obd->OpenPort($port_details);
3404             =cut
3405            
3406             sub OpenPort
3407             {
3408 0     0 1   my ($self, $port_details) = @_;
3409 0           my $quiet = 0;
3410 0           my $port = -1;
3411 0           my $port_count = 0;
3412 0           my $port_name = undef;
3413 0           my $baud_rate = 38400;
3414 0           my $parity = "none";
3415 0           my $data_bits = 8;
3416 0           my $stop_bits = 1;
3417 0           my $handshake = "none";
3418            
3419 0 0 0       if (defined($port_details) && $port_details ne "")
3420             {
3421 0           my @parameters= split(":", $port_details);
3422            
3423 0 0         if ($parameters[0] ne "")
3424             {
3425 0           my $parameter = $parameters[0];
3426 0           $parameter =~ s/[0-9]//g; # Strip everything that is numeric
3427 0 0         if ($parameter ne "") # If a valid serial port name has been passed
3428             {
3429 0           $port_name = shift @parameters;
3430             }
3431             }
3432 0 0         if (scalar(@parameters) > 0)
3433             {
3434 0           $baud_rate = shift @parameters;
3435 0 0         if (scalar(@parameters) > 0)
3436             {
3437 0           $parity = shift @parameters;
3438 0 0         if (scalar(@parameters) > 0)
3439             {
3440 0           $data_bits = shift @parameters;
3441 0 0         if (scalar(@parameters) > 0)
3442             {
3443 0           $stop_bits = shift @parameters;
3444 0 0         if (scalar(@parameters) > 0)
3445             {
3446 0           $handshake = shift @parameters;
3447             }
3448             }
3449             }
3450             }
3451             }
3452             }
3453            
3454 0 0 0       if (!defined($port_name) || $port_name eq "")
3455             {
3456 0 0         if ($^O eq "MSWin32")
3457             {
3458 0           $port_name = "COM1";
3459             }
3460             else
3461             {
3462 0           $port_name = "/dev/ttyUSB0";
3463             }
3464             }
3465            
3466 0           my $port_number = $port_name;
3467 0           $port_number =~ s/[^0-9]//g; # Strip everything that isn't numeric
3468            
3469 0           my $port_text = $port_name;
3470 0           $port_text =~ s/[0-9]//g; # Strip everything that is numeric
3471            
3472             do
3473 0   0       {
      0        
3474 0           $port_name = $port_text.$port_number;
3475            
3476 0 0         if ($^O eq "MSWin32")
3477             {
3478 0           $port = Win32::SerialPort->new ($port_name);
3479             }
3480             else
3481             {
3482 0           $port = Device::SerialPort->new($port_name, $quiet);
3483             }
3484            
3485 0 0         if (defined($port))
3486             {
3487 0           $port->user_msg(1); # misc. warnings
3488 0           $port->error_msg(1); # hardware and data errors
3489            
3490 0           $port->baudrate($baud_rate);
3491 0           $port->parity($parity);
3492 0 0         if ($parity eq "none")
3493             {
3494 0           $port->parity_enable(0);
3495             }
3496             else
3497             {
3498 0           $port->parity_enable(1); # for any parity except "none"
3499             }
3500 0           $port->databits($data_bits);
3501 0           $port->stopbits($stop_bits);
3502 0           $port->handshake($handshake);
3503            
3504 0           $port->write_settings;
3505            
3506 0           $self->{'port'} = $port;
3507 0           $self->Command("AT Z"); # Reset Device
3508 0           foreach (@{$self->{'response'}})
  0            
3509             {
3510 0 0         if (substr($_, 0, 5) eq "ELM32") # Allow 328 & 329 as well
3511             {
3512 0           $self->{'ELM_type'} = substr($_, 0, 6);
3513             }
3514             }
3515 0 0 0       if ($self->{'ELM_type'} eq "NONE" && $self->{'debug_level'} > 0)
3516             {
3517 0           print "Can't find an ELM module on $port_name\n";
3518             }
3519             }
3520             else
3521             {
3522 0 0         if ($self->{'debug_level'} > 0)
3523             {
3524 0           print "Can't open $port_name: $!\n";
3525             }
3526 0           $self->{'port'} = -1;
3527             }
3528            
3529 0           $port_number++;
3530 0           $port_count++;
3531             } until(($self->{'port'} != -1 && $self->{'ELM_type'} ne "NONE") || $port_count > $max_ports_to_search);
3532            
3533 0 0         if ($self->{'ELM_type'} eq "NONE")
3534             {
3535 0           $self->{'port'} = -1;
3536 0           die "Couldn't find an ELM module!\n";
3537             }
3538             }
3539            
3540            
3541             #*****************************************************************
3542            
3543             =head2 ConfigureDevice
3544            
3545             Set up the ELM module to return data in the required form.
3546            
3547             This function is called by 'new' and should not be called again.
3548            
3549             $obd->ConfigureDevice();
3550             =cut
3551            
3552             sub ConfigureDevice
3553             {
3554 0     0 1   my ($self) = @_;
3555            
3556 0 0         if ($self->{'debug_level'} > 0) { print "ConfigureDevice\n"; }
  0            
3557            
3558 0 0         if ($self->PortOK)
3559             {
3560 0           $self->Command("AT E0"); # Turn echo off
3561            
3562 0           $self->Command("AT L0"); # Turn linefeeds off
3563            
3564 0           $self->Command("AT SP 0"); # Set Protocol to auto
3565            
3566 0           $self->Command("AT DPN"); # Display Protocol number
3567            
3568 0           $self->Command("AT DP"); # Display Protocol
3569            
3570 0           $self->Command("AT H1"); # Turn headers on
3571            
3572 0           $self->Command("01 00"); # Prepare to talk and get available PID's
3573             }
3574             }
3575            
3576            
3577             #*****************************************************************
3578            
3579             =head2 FindAvailableCommands
3580            
3581             Query the ECU to find out which commands are supported and
3582             annotate the value entries in the 'get' structure with the
3583             'available' flag set to 0 (not supported) or 1 (supported).
3584            
3585             This function is called by 'new' and should not be called again.
3586            
3587             $obd->FindAvailableCommands();
3588             =cut
3589            
3590             sub FindAvailableCommands
3591             {
3592 0     0 1   my ($self) = @_;
3593            
3594 0           my @commands = ( "01 PIDs supported (01-20)",
3595             "02 PIDs supported (01-20)",
3596             "09 PIDs supported (01-20)"
3597             );
3598            
3599 0 0         if ($self->{'debug_level'} > 0) { print "FindAvailableCommands:\n"; }
  0            
3600            
3601 0 0         if ($self->{'bus_type'} eq "CAN")
3602             {
3603 0           push @commands, "06 MIDs supported (01-20)"; # Command only supported by CAN systems
3604             }
3605             else
3606             {
3607 0           push @commands, "05 TIDs supported (01-20)"; # Command only supported by non-CAN systems
3608             # push @commands, "06 TIDs supported (01-20)"; # Command only supported by non-CAN systems
3609             }
3610            
3611 0           foreach my $next_command (@commands)
3612             {
3613             do
3614 0           {
3615 0           $next_command = $self->ProcessAvailableCommands($next_command);
3616             } while (defined($next_command));
3617             }
3618             }
3619            
3620            
3621             #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3622            
3623             =head2 ProcessAvailableCommands
3624            
3625             Query the ECU to find out which commands are supported and
3626             annotate the value entries in the 'get' structure with the
3627             'available' flag set to 0 (not supported) or 1 (supported).
3628            
3629             This function is called by 'FindAvailableCommands' and should not be
3630             called by any other functions.
3631            
3632             $obd->ProcessAvailableCommands($command);
3633             =cut
3634            
3635             sub ProcessAvailableCommands
3636             {
3637 0     0 1   my ($self, $command) = @_;
3638            
3639 0           my $next_command = undef;
3640            
3641 0 0         if ($self->{'debug_level'} > 0) { print "~ProcessAvailableCommands: $command\n"; }
  0            
3642            
3643 0           $self->{'get'}->{$command}->{'available'} = 1; # Flag the command as available
3644            
3645 0           my $response = $self->Read($command);
3646            
3647 0 0         if ($self->{'debug_level'} > 1) { print "$command\n"; }
  0            
3648            
3649 0 0         if ($response->{'status'} eq "ok")
3650             {
3651 0           foreach my $result (@{$response->{'results'}})
  0            
3652             {
3653 0           $self->{'get'}->{$result->{'name'}}->{'available'} = $result->{'value'};
3654 0 0         if ($self->{'debug_level'} > 1) { print "$result->{'address'} - $result->{'name'}: $result->{'value'} $result->{'unit'}\n"; }
  0            
3655 0 0         if ($self->{'debug_level'} > 4)
3656             {
3657 0           print Dumper($result);
3658             }
3659            
3660             # print Dumper($self->{'get'}->{'Location of oxygen sensors 13'});
3661             # print Dumper($self->{'get'}->{'Location of oxygen sensors'});
3662            
3663 0 0 0       if (substr($result->{'name'}, 4, 15) eq "IDs supported (" && $result->{'value'} == 1)
    0 0        
      0        
3664             {
3665 0           $next_command = $result->{'name'};
3666             }
3667             elsif ( $result->{'value'} == 1 &&
3668             ((substr($result->{'name'}, -2, 2) eq "13" && $self->{'get'}->{'Location of oxygen sensors 13'}->{'available'} == 1)
3669             || (substr($result->{'name'}, -2, 2) eq "1D" && $self->{'get'}->{'Location of oxygen sensors 1D'}->{'available'} == 1))
3670             )
3671             {
3672 0           my $new_name = substr($result->{'name'}, 0, length($result->{'name'})-3);
3673            
3674 0 0         if ($self->{'debug_level'} > 2)
3675             {
3676 0           print "Old name: >$result->{'name'}<\n";
3677 0           print "New name: >$new_name<\n";
3678             }
3679            
3680 0 0 0       if ($result->{'name'} eq "Location of oxygen sensors 13" || $result->{'name'} eq "Location of oxygen sensors 1D")
3681             {
3682 0           $self->{'get'}->{$new_name} = $self->{'get'}->{$result->{'name'}};
3683             }
3684             else
3685             {
3686 0           $self->{'get'}->{$new_name} = delete($self->{'get'}->{$result->{'name'}});
3687             }
3688 0 0         if ($self->{'debug_level'} > 3)
3689             {
3690 0           print Dumper($self->{'get'}->{$new_name});
3691             }
3692             }
3693             }
3694             }
3695             else
3696             {
3697             # Flag command as unavailable
3698 0           $self->{'get'}->{$command}->{'available'} = 0;
3699             }
3700            
3701 0           return $next_command;
3702             }
3703            
3704            
3705             #*****************************************************************
3706            
3707            
3708             =head2 Replay
3709            
3710             Process a file containing debugging output and replay the commands
3711             through the module.
3712            
3713             This function is called by 'new' and should not be called by other functions.
3714            
3715             $obd->Replay($replay_filename);
3716             =cut
3717            
3718             sub Replay
3719             {
3720 0     0 1   my ($self, $replay_filename) = @_;
3721 0           $self->{'replay_file'} = 1;
3722            
3723 0           my $status = "ok";
3724 0           my $replay_command="";
3725            
3726             # Open the file containing the command and response data
3727 0           open (REPLAYFILE, $replay_filename);
3728            
3729 0           my $get_command = 0;
3730 0           my $seek_response = 1;
3731 0           my $read_response = 2;
3732 0           my $get_result = 4;
3733            
3734 0           my $replay_state = $get_command;
3735            
3736 0           while ()
3737             {
3738             # Iterate through issuing commands and parsing responses
3739 0           $_ =~ s/\r?\n//g; # Strip all carriage returns
3740            
3741 0 0         if ($replay_state == $get_command)
    0          
    0          
3742             {
3743 0 0         if (substr($_, 0, 1) eq "~")
3744             {
3745 0           $_ = substr($_, 1);
3746 0           my @linepart = split(":", $_);
3747 0           foreach my $part (@linepart)
3748             {
3749 0           $part =~ s/^\s+|\s+$//g; # Strip unwanted whitespace
3750             }
3751            
3752 0           $replay_command = '$self->'.$linepart[0]."(\"";
3753 0           my $number_of_parameters = scalar(@linepart);
3754 0           for (my $index=1; $index<$number_of_parameters; $index++)
3755             {
3756 0           $replay_command .= $linepart[$index];
3757 0 0         if ($index < ($number_of_parameters-1))
3758             {
3759 0           $replay_command .= ",";
3760             }
3761             }
3762 0           $replay_command .= "\");";
3763 0           $replay_state = $seek_response;
3764             }
3765             }
3766             elsif ($replay_state == $seek_response)
3767             {
3768 0 0         if ($_ eq "Response")
3769             {
3770 0           $replay_state = $read_response;
3771             }
3772             }
3773             elsif ($replay_state == $read_response)
3774             {
3775 0 0         if ($_ eq "End of response")
3776             {
3777             # Execute the command we just got the response to...
3778 0           $status = "ok";
3779 0           $status = eval($replay_command);
3780 0 0         if ($self->{'debug_level'} > 1)
3781             {
3782 0           print "Status: ";
3783 0           print Dumper($status);
3784 0           print "\n";
3785             }
3786 0           $replay_state = $get_command;
3787             }
3788             else
3789             {
3790 0 0         if (length($_) > 0)
3791             {
3792 0           push @{$self->{'replay_response'}}, $_;
  0            
3793             }
3794             }
3795             }
3796             }
3797 0           close (REPLAYFILE);
3798             }
3799            
3800            
3801             #*****************************************************************
3802            
3803             =head1 AUTHOR
3804            
3805             Alister Perrott, C<< >>
3806            
3807             =head1 BUGS
3808            
3809             Please report any bugs or feature requests to C, or through
3810             the web interface at L.
3811             I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
3812            
3813             Please also include a debug trace showing the error so that I can replay your vehicle data and see exactly what you're seeing. This can be done by setting $debug_level in the constructor to 1 and piping the output to a file.
3814             e.g. perl myOBD.pl&>trace.txt
3815            
3816            
3817             =head1 SUPPORT
3818            
3819             You can find documentation for this module with the perldoc command.
3820            
3821             perldoc Device::ELM327
3822            
3823            
3824             You can also look for information at:
3825            
3826             =over 5
3827            
3828             =item * RT: CPAN's request tracker
3829            
3830             L
3831            
3832             =item * AnnoCPAN: Annotated CPAN documentation
3833            
3834             L
3835            
3836             =item * CPAN Ratings
3837            
3838             L
3839            
3840             =item * Search CPAN
3841            
3842             L
3843            
3844             =item * My ELM327 page
3845            
3846             L
3847            
3848             =back
3849            
3850            
3851             =head1 ACKNOWLEDGEMENTS
3852            
3853             Many thanks to:
3854             The authors of Win32::SerialPort and Device::SerialPort.
3855             Kedar Warriner and Thomas Kaiser for their suggestions.
3856             George R Ahearn for sending sample SAE J1979 debug information.
3857             Larry Wall and all the other people who have worked on Perl.
3858             ELM Electronics for creating the ELM327 module.
3859             Everyone involved with CPAN.
3860            
3861             =head1 LICENSE AND COPYRIGHT
3862            
3863             Copyright 2012 Alister Perrott.
3864            
3865             This program is free software; you can redistribute it and/or modify it
3866             under the terms of either: the GNU General Public License as published
3867             by the Free Software Foundation; or the Artistic License.
3868            
3869             See http://dev.perl.org/licenses/ for more information.
3870            
3871            
3872             =cut
3873            
3874             #********************************************************************
3875             1; # End of Device::ELM327 - Return success to require/use statement
3876             #********************************************************************
3877