Skip to content

Commit c960b76

Browse files
authored
SonarQube - Reduce Complexity (#143)
* Refactor binary.py/_dict_to_protobuf() * Replace RawMessage which is deprecated * Refactor binary.py/_build_control_command_message * Refactor binary.py/_protobuf_to_dict() * Renamed methods for consistency * Update method names to match previous renaming * Refactor _build_control_command_parsed_message() * Extract printing diagnostic response * Remove unnecessary conditional statement * Refactor control.py/main() * Minimal refactor of scanner.py/scan() * Refactor structures.py/merge_message() * Refactor base.py/run()
1 parent 3ff3dc2 commit c960b76

6 files changed

Lines changed: 396 additions & 295 deletions

File tree

openxc/formats/binary.py

Lines changed: 296 additions & 216 deletions
Large diffs are not rendered by default.

openxc/generator/structures.py

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -100,17 +100,7 @@ def id(self, value):
100100
value = int(value, 0)
101101
self._id = value
102102

103-
def merge_message(self, data):
104-
self.bus_name = self.bus_name or data.get('bus', None)
105-
106-
message_attributes = dir(self)
107-
message_attributes = [a.replace('bus_name', 'bus') for a in message_attributes]
108-
data_attributes = list(data.keys())
109-
extra_attributes = set(data_attributes) - set(message_attributes)
110-
111-
if extra_attributes:
112-
fatal_error('ERROR: Message %s has unrecognized attributes: %s' % (data.get('id'), ', '.join(extra_attributes)))
113-
103+
def validate_bus(self):
114104
if getattr(self, 'message_set'):
115105
self.bus = self.message_set.lookup_bus(name=self.bus_name)
116106
if not self.bus.valid():
@@ -123,6 +113,19 @@ def merge_message(self, data):
123113
msg = "Bus '%s' is disabled" % self.bus_name
124114
LOG.warning("%s - message 0x%x will be disabled" % (msg, self.id))
125115

116+
def merge_message(self, data):
117+
self.bus_name = self.bus_name or data.get('bus', None)
118+
119+
message_attributes = dir(self)
120+
message_attributes = [a.replace('bus_name', 'bus') for a in message_attributes]
121+
data_attributes = list(data.keys())
122+
extra_attributes = set(data_attributes) - set(message_attributes)
123+
124+
if extra_attributes:
125+
fatal_error('ERROR: Message %s has unrecognized attributes: %s' % (data.get('id'), ', '.join(extra_attributes)))
126+
127+
self.validate_bus()
128+
126129
self.id = self.id or data.get('id')
127130
self.name = self.name or data.get('name', None)
128131
self.bit_numbering_inverted = (self.bit_numbering_inverted or

openxc/sources/base.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,20 @@ def _message_valid(self, message):
185185
return False
186186
return True
187187

188+
def parse_messages(self):
189+
while True:
190+
message = self.streamer.parse_next_message()
191+
if message is None:
192+
break
193+
194+
if not self._message_valid(message):
195+
self.corrupted_messages += 1
196+
break
197+
198+
if self.callback is not None:
199+
self.callback(message)
200+
self._receive_command_response(message)
201+
188202
def run(self):
189203
"""Continuously read data from the source and attempt to parse a valid
190204
message from the buffer of bytes. When a message is parsed, passes it
@@ -210,18 +224,7 @@ def run(self):
210224
self.format = "protobuf"
211225
self.streamer.receive(payload)
212226

213-
while True:
214-
message = self.streamer.parse_next_message()
215-
if message is None:
216-
break
217-
218-
if not self._message_valid(message):
219-
self.corrupted_messages += 1
220-
break
221-
222-
if self.callback is not None:
223-
self.callback(message)
224-
self._receive_command_response(message)
227+
self.parse_messages()
225228

226229
def _receive_command_response(self, message):
227230
# TODO the controller/source are getting a little mixed up since the

openxc/tools/control.py

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,37 @@ def parse_options():
134134
parser.set_defaults(format="json")
135135
return parser.parse_args()
136136

137+
def handle_set_command(arguments, interface):
138+
if arguments.passthrough_enabled is not None:
139+
passthrough(interface, int(arguments.bus), arguments.passthrough_enabled)
140+
if arguments.af_bypass is not None:
141+
af_bypass(interface, int(arguments.bus), arguments.af_bypass)
142+
if arguments.new_payload_format is not None:
143+
set_payload_format(interface, arguments.new_payload_format)
144+
if arguments.unix_time is not None:
145+
set_rtc_time(interface, int(arguments.unix_time))
146+
if arguments.host is not None:
147+
modem_configuration(interface, arguments.host, arguments.port)
148+
149+
def handle_write_command(arguments, interface):
150+
if arguments.write_name:
151+
interface.write(name=arguments.write_name,
152+
value=arguments.write_value,
153+
event=arguments.write_event)
154+
elif arguments.write_id:
155+
if not arguments.write_data:
156+
sys.exit("%s requires an id and data" % arguments.command)
157+
# TODO we should use unhexlify as with the diagnostic command
158+
# payloads so we can standardize the API and not deal with hex
159+
# strings in code
160+
interface.write(bus=int(arguments.bus),
161+
id=arguments.write_id,
162+
data=arguments.write_data,
163+
frame_format=arguments.write_frame_format)
164+
elif arguments.write_input_file:
165+
write_file(interface, arguments.write_input_file)
166+
else:
167+
sys.exit("%s requires a signal name, message ID or filename" % arguments.command)
137168

138169
def main():
139170
configure_logging()
@@ -152,35 +183,8 @@ def main():
152183
elif arguments.command == "id":
153184
device_id(interface)
154185
elif arguments.command == "set":
155-
if arguments.passthrough_enabled is not None:
156-
passthrough(interface, int(arguments.bus), arguments.passthrough_enabled)
157-
if arguments.af_bypass is not None:
158-
af_bypass(interface, int(arguments.bus), arguments.af_bypass)
159-
if arguments.new_payload_format is not None:
160-
set_payload_format(interface, arguments.new_payload_format)
161-
if arguments.unix_time is not None:
162-
set_rtc_time(interface, int(arguments.unix_time))
163-
if arguments.host is not None:
164-
modem_configuration(interface, arguments.host, arguments.port)
165-
elif arguments.command.startswith("write"):
166-
if arguments.command == "write":
167-
if arguments.write_name:
168-
interface.write(name=arguments.write_name,
169-
value=arguments.write_value,
170-
event=arguments.write_event)
171-
elif arguments.write_id:
172-
if not arguments.write_data:
173-
sys.exit("%s requires an id and data" % arguments.command)
174-
# TODO we should use unhexlify as with the diagnostic command
175-
# payloads so we can standardize the API and not deal with hex
176-
# strings in code
177-
interface.write(bus=int(arguments.bus),
178-
id=arguments.write_id,
179-
data=arguments.write_data,
180-
frame_format=arguments.write_frame_format)
181-
elif arguments.write_input_file:
182-
write_file(interface, arguments.write_input_file)
183-
else:
184-
sys.exit("%s requires a signal name, message ID or filename" % arguments.command)
186+
handle_set_command(arguments, interface)
187+
elif arguments.command == "write":
188+
handle_write_command(arguments, interface)
185189
else:
186190
print(("Unrecognized command \"%s\"" % arguments.command))

openxc/tools/diagnostics.py

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,23 @@
1313

1414
from .common import device_options, configure_logging, select_device
1515

16+
def print_diagnostic_response(responses):
17+
for response in responses:
18+
# After sending a diagnostic request, it will return with a signal message saying if the
19+
# request was recieved. After that it used to show about 30 vehicle messages (rpm, speed, etc)
20+
# with the actual diagnostic response mixed in. So, if the response length is more than
21+
# 1, it's the response, if its less (only 1) it's the recieved message.
22+
if len(response) > 1:
23+
# Stripping all of the unnesseary data we get after sending a diag request in python
24+
# Just like in enabler, it's a diag response if it contains the keys "mode", "bus",
25+
# "id", and "success".
26+
diag_mgs_req_keys = ['mode', 'bus', 'id', 'success']
27+
indices = [i for i, s in enumerate(response) if all(x in s for x in diag_mgs_req_keys)]
28+
if indices:
29+
print(("Response: %s" % response[indices[0]]))
30+
else:
31+
print(("Response: %s" % response))
32+
1633
def diagnostic_request(arguments, controller):
1734
message = int(arguments.message, 0)
1835
mode = int(arguments.mode, 0)
@@ -40,21 +57,7 @@ def diagnostic_request(arguments, controller):
4057
if len(responses) == 0:
4158
print("No response received before timeout")
4259
else:
43-
for response in responses:
44-
# After sending a diagnostic request, it will return with a signal message saying if the
45-
# request was recieved. After that it used to show about 30 vehicle messages (rpm, speed, etc)
46-
# with the actual diagnostic response mixed in. So, if the response length is more than
47-
# 1, it's the response, if its less (only 1) it's the recieved message.
48-
if len(response) > 1:
49-
# Stripping all of the unnesseary data we get after sending a diag request in python
50-
# Just like in enabler, it's a diag response if it contains the keys "mode", "bus",
51-
# "id", and "success".
52-
diag_mgs_req_keys = ['mode', 'bus', 'id', 'success']
53-
indices = [i for i, s in enumerate(response) if all(x in s for x in diag_mgs_req_keys)]
54-
if indices:
55-
print(("Response: %s" % response[indices[0]]))
56-
else:
57-
print(("Response: %s" % response))
60+
print_diagnostic_response(responses)
5861
elif arguments.command == "cancel":
5962
if controller.delete_diagnostic_request(message, mode, bus=bus,
6063
pid=pid):

openxc/tools/scanner.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,7 @@
1515
TESTER_PRESENT_MODE = 0x3e
1616
TESTER_PRESENT_PAYLOAD = bytearray([0])
1717

18-
def scan(controller, bus=None, message_id=None):
19-
message_ids = []
20-
if message_id is not None:
21-
message_ids.append(message_id)
22-
else:
23-
# using 11-bit IDs
24-
message_ids = list(range(0, 0x7ff + 1))
25-
26-
print("Sending tester present message to find valid modules arb IDs")
18+
def find_active_modules(controller, bus, message_ids):
2719
active_modules = set()
2820
for arb_id in message_ids:
2921
response = controller.create_diagnostic_request(arb_id, TESTER_PRESENT_MODE,
@@ -32,9 +24,9 @@ def scan(controller, bus=None, message_id=None):
3224
if response is not None:
3325
print(("0x%x responded to tester present: %s" % (arb_id, response)))
3426
active_modules.add(arb_id)
27+
return active_modules
3528

36-
# Scan for active services on each active module by sending blank requests
37-
print("Scanning for services on active modules")
29+
def find_active_modes(controller, bus, active_modules):
3830
active_modes = defaultdict(list)
3931
for active_module in active_modules:
4032
controller.create_diagnostic_request(active_module, TESTER_PRESENT_MODE,
@@ -56,6 +48,22 @@ def scan(controller, bus=None, message_id=None):
5648

5749
controller.create_diagnostic_request(active_module, TESTER_PRESENT_MODE, bus=bus,
5850
frequency=0)
51+
return active_modes
52+
53+
def scan(controller, bus=None, message_id=None):
54+
message_ids = []
55+
if message_id is not None:
56+
message_ids.append(message_id)
57+
else:
58+
# using 11-bit IDs
59+
message_ids = list(range(0, 0x7ff + 1))
60+
61+
print("Sending tester present message to find valid modules arb IDs")
62+
active_modules = find_active_modules(controller, bus, message_ids)
63+
64+
# Scan for active services on each active module by sending blank requests
65+
print("Scanning for services on active modules")
66+
active_modes = find_active_modes(controller, bus, active_modules)
5967

6068
# Scan for what each mode can do and what data it can return by fuzzing the
6169
# payloads

0 commit comments

Comments
 (0)