dtc_statuses()   A
last analyzed

Complexity

Conditions 4

Size

Total Lines 57

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 57
rs 9.0309
cc 4

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
from obdlib.obd.pids import *
2
from binascii import unhexlify
3
4
unit_english = 0
5
6
7
def set_unit(v):
8
    """
9
        Sets unit flag
10
    """
11
    global unit_english
12
    unit_english = v
13
14
15
def zfill(string, width):
16
    """
17
        Wrapper for str.zfill which is not exists in micropython
18
        :param string: a string for alignment
19
        :param width: width of the resulted string
20
        :return: a string that has been aligned to the width
21
    """
22
    return string.zfill(width) if hasattr(
23
        string,
24
        'zfill') else (
25
        '{0:0%d}' %
26
        (width)).format(
27
        __digit(string))
28
29
def bitwise_pids(hex_string, start=0):
30
    """
31
        Determine supported PIDs based on the supplied hexadecimal string
32
        :param hex_string:a hex string representing bitwise encoded PID support
33
        :return: a dictionary of PID number: boolean pairs that indicate
34
        whether or not a PID is supported
35
    """
36
    bits = zfill(bin(int(hex_string, 16))[2:], 32)
37
    return dict(
38
        (zfill(hex(i + 1 + start)[2:], 2).upper(), 1 if value == '1' else 0)
39
        for i, value in enumerate(bits)
40
    )
41
42
43
def rpm(value):
44
    """
45
        Converts the vehicle's current engine RPM value
46
        :return: the current engine RPM
47
    """
48
    return __digit(value) / 4.0
49
50
51
def speed(value):
52
    """
53
        Converts the vehicle's current engine RPM value
54
        :return: the current engine speed
55
    """
56
    value = __digit(value)
57
    # English - > mph
58
    if unit_english:
59
        # km/h - > mph conversion
60
        value = value * 0.621371192
61
    return value
62
63
64
def load_value(value):
65
    """
66
        Converts the vehicle's current engine load value
67
        :return: the current engine value
68
    """
69
    return __digit(value) * 100 / 255
70
71
def term_fuel(value):
72
    """
73
        Converts the vehicle's short term fuel or long term fuel
74
        :return: the current engine value
75
    """
76
    return round((__digit(value) - 128) * 100 / 128.0, 2)
77
78
79
def fuel_pressure(value):
80
    """
81
        Converts the vehicle's fuel pressure
82
        :return: the current engine value
83
    """
84
    value = __digit(value) * 3
85
    # English - > psi
86
    if unit_english:
87
        # kPa - > psi conversion
88
        value = value * 0.145037738
89
    return round(value, 2)
90
91
92
def absolute_pressure(value):
93
    """
94
        Converts the vehicle's intake manifold absolute pressure
95
        :return: the current engine value
96
    """
97
    value = __digit(value)
98
    # English - > psi
99
    if unit_english:
100
        # kPa - > psi conversion
101
        value = value * 0.145037738
102
    return round(value, 2)
103
104
105
def timing_advance(value):
106
    """
107
        Converts the vehicle's Timing advance
108
        :return: the current engine value
109
    """
110
    return round((__digit(value) - 128) / 2.0, 2)
111
112
113
def air_flow_rate(value):
114
    """
115
        Converts the vehicle's MAF air flow rate
116
        :return: the current engine value
117
    """
118
    return round(__digit(value) / 100.0, 2)
119
120
121
def throttle_pos(value):
122
    """
123
        Converts the vehicle's Throttle position
124
        :return: the current engine value
125
    """
126
    return __digit(value) * 100 / 255
127
128
129
def air_status(value):
130
    """
131
        Converts the vehicle's Commanded secondary air status
132
        :return: the current engine value
133
    """
134
    return SECONDARY_AIR_STATUS.get(__digit(value), None)
135
136
137
def voltage(value):
138
    """
139
        Converts the vehicle's Oxygen sensor voltage
140
        0 - 1.275 Volts
141
        :return: the current engine value
142
    """
143
    return __digit(value) / 200.0
144
145
146
def coolant_temp(value):
147
    """
148
        Converts the vehicle's current engine coolant temperature
149
        :return: the current engine coolant temperature in degrees Celsius
150
    """
151
    # The data returned in the OBD response is in hexadecimal with a zero
152
    # offset to account for negative temperatures. To return the current
153
    # temperature in degrees Celsius, we must first convert to decimal and
154
    # then subtract 40 to account for the zero offset.
155
    value = __digit(value) - 40
156
    # English - > F
157
    if unit_english:
158
        # C - > F
159
        value = value * 9 / 5 + 32
160
    return value
161
162
163
def obd_standards(value):
164
    """
165
        Converts the vehicle's OBD standards this vehicle conforms to
166
        :return: the current engine value
167
    """
168
    return OBD_STANDARDS[__digit(value)] if len(
169
        OBD_STANDARDS) >= __digit(value) else None
170
171
172
def time(value):
173
    """
174
        Converts the vehicle's Run time since engine start
175
        :return: the current engine value
176
    """
177
    return __digit(value)
178
179
180
def oil_temp(value):
181
    """
182
        Converts the vehicle's current engine oil temperature
183
        :return: the current engine oil temperature in degrees Celsius
184
    """
185
    # The data returned in the OBD response is in hexadecimal with a zero
186
    # offset to account for negative temperatures. To return the current
187
    # temperature in degrees Celsius, we must first convert to decimal and
188
    # then subtract 40 to account for the zero offset.
189
    value = __digit(value) - 40
190
    # English - > F
191
    if unit_english:
192
        # C - > F
193
        value = value * 9 / 5 + 32
194
    return value
195
196
197
def vin(value):
198
    """
199
        Returns the name of the VIN
200
        :return: the VIN
201
    """
202
    # checks the first 3 bytes
203
    # if 00 - remove
204
    for s in range(3):
205
        if __digit(value[0:2]) == 0:
206
            value = value[2:]
207
208
    return unhexlify(value).decode()
209
210
211
def ecu_name(value):
212
    """
213
        Returns the name of the Engine Control Unit (ECU)
214
        :return: the name of the ECU (if available)
215
    """
216
    return unhexlify(value).decode()
217
218
219
def fuel_type(value):
220
    """
221
        Converts the vehicle's fuel type
222
        :return: a description of the type of fuel used by the vehicle
223
    """
224
    try:
225
        return FUEL_TYPE_DESCRIPTION[__digit(value)]
226
    except IndexError:
227
        return None
228
229
230
def fuel_system_status(value):
231
    """
232
        Converts the vehicle's Fuel system status
233
        :return: tuple of Fuel system status, (fuel_1, fuel_2)
234
    """
235
    # fuel system #1
236
    fuel_1 = __digit(value[0:2])
237
    # fuel system #2
238
    fuel_2 = __digit(value[2:])
239
    return (
240
        FUEL_SYSTEM_STATUS_DESC.get(fuel_1, FUEL_SYSTEM_STATUS_DESC[0]),
241
        FUEL_SYSTEM_STATUS_DESC.get(fuel_2, FUEL_SYSTEM_STATUS_DESC[0])
242
    )
243
244
245
def oxygen_sensors(value):
246
    """
247
        Checks the vehicle's Oxygen sensors
248
        :return: list of available sensors
249
    """
250
    # if PID 13 - [A0..A3] == Bank 1, Sensors 1-4. [A4..A7] == Bank 2...
251
    #
252
    # if PID 1D - Similar to PID 13,
253
    # but [A0..A7] == [B1S1, B1S2, B2S1, B2S2, B3S1, B3S2, B4S1, B4S2]
254
    value = bin(__digit(value))[2:]
255
    sensors = []
256
    for sensor in value:
257
        if sensor:
258
            sensors.append(int(sensor))
259
    return sensors
260
261
262
def aux_input_status(value):
263
    """
264
        Checks the vehicle's Auxiliary input status
265
        :return: boolean, Power Take Off (PTO) status
266
        True - active
267
    """
268
    return bin(__digit(value))[2:][0] == '1'
269
270
271
def dtc_statuses(value):
272
    # see https://en.wikipedia.org/wiki/OBD-II_PIDs#Mode_1_PID_01
273
    monitor_statuses = {
274
        'mil': 0,
275
        'dtc': 0,
276
        'ignition_test': 0,
277
        'base_tests': [
278
            (0, 0),  # Misfire
279
            (0, 0),  # Fuel-System
280
            (0, 0)  # Components
281
        ],
282
        'spark_tests': [
283
            (0, 0),  # Catalyst
284
            (0, 0),  # Heated-Catalyst
285
            (0, 0),  # Evaporative-Systems
286
            (0, 0),  # Secondary-Air-System
287
            (0, 0),  # A/C-Refrigerant
288
            (0, 0),  # Oxygen-Sensor
289
            (0, 0),  # Oxygen-Sensor-Heater
290
            (0, 0)  # EGR-Sytem
291
        ],
292
        'compression_tests': [
293
            (0, 0),  # NMHC-Cat
294
            (0, 0),  # N0x/Scr-Monitor
295
            (0, 0),  # Boost-Pressure
296
            (0, 0),  # Exhaust-Gas-Sensor
297
            (0, 0),  # PM-Filter-Monitoring
298
            (0, 0)  # EGR/VVT-System
299
        ]}
300
    # converts hex string to bits string
301
    value = bin(__digit(value))[2:]
302
    monitor_statuses['mil'] = int(value[0])  # A7
303
    monitor_statuses['dtc'] = int(value[1:8], 2)  # A6-A0
304
    monitor_statuses['ignition_test'] = int(value[11])  # B3
305
306
    for item in range(3):
307
        monitor_statuses['base_tests'][item] = (
308
            int(value[8 + item]),  # B0, B1, B2
309
            int(value[12 + item])  # B4, B5, B6
310
        )
311
    except_compr_bits = (2, 4)
312
    curr_compr_step = 0
313
    for item in range(8):
314
        # spark tests
315
        monitor_statuses['spark_tests'][item] = (
316
            int(value[16 + item]),  # C0-C7
317
            int(value[24 + item])  # D0-D7
318
        )
319
        # compression tests
320
        if item not in except_compr_bits:
321
            monitor_statuses['compression_tests'][curr_compr_step] = (
322
                int(value[16 + item]),  # C0, C1, C3, C5, C6, C7
323
                int(value[24 + item])  # D0, D1, D3, D5, D6, D7
324
            )
325
            curr_compr_step += 1
326
327
    return monitor_statuses
328
329
330
def trouble_codes(value):
331
    """
332
        Checks the vehicle's trouble codes
333
        :return list of codes
334
    """
335
    codes = []
336
    # trouble data frame include 6 bytes - 3 trouble codes
337
    # ex: 0133 0000 0000
338
    for item in range(0, 12, 4):
339
        # get trouble code
340
        code = value[item:item + 4]
341
        # check first byte
342
        first_char = DTCs_table.get(code[0])
343
        if first_char and __digit(code):
344
            codes.append(first_char + code[1:])
345
346
    return codes
347
348
349
def __digit(value):
350
    """
351
        Converts hex to digit
352
    """
353
    return int(value, 16)
354