Skip to content

Commit

Permalink
Merge pull request #154 from openxc/next
Browse files Browse the repository at this point in the history
Next
  • Loading branch information
GenoJAFord authored Sep 14, 2020
2 parents 2054c3d + 8f1eb8b commit 31655a9
Show file tree
Hide file tree
Showing 22 changed files with 531 additions and 377 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ coverage.xml
diffcover.html
htmlcov
*~
.scannerwork/
8 changes: 8 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
OpenXC Python Library Changelog
===============================

v2.1.0
----------
* SonarQube integration
* Fix: Modem configuration for c5 cellar build now properly sets baud rate
* Fix: Protobuf general improvements
* Keyboard interupt via <ctrl>c added to openxc-dump and Obd2 Scanner
* Stitching Feature, large messages are now packaged and sent in smaller chunks from the vi

v2.0.0
----------
* Known Issue: OpenXC python must be used with firmware 8.0.0 or greater.
Expand Down
5 changes: 3 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ OpenXC for Python

.. image:: https://github.com/openxc/openxc-python/raw/master/docs/_static/logo.png

:Version: 2.0.0
:Version: 2.1.0
:Web: http://openxcplatform.com
:Download: http://pypi.python.org/pypi/openxc/
:Documentation: http://python.openxcplatform.com
Expand All @@ -31,6 +31,7 @@ number of command-line tools for connecting to the CAN translator and
manipulating previously recorded vehicle data.

Due to changes in signals.cpp openxc-python Version 2.0.0 must be used with vi-firmware 8.0.0 or greater.
Due to changes with large diagnostic responses Version 2.1.0 must be used with vi-firmware 8.1.0 or greater.

To package run "setup.py sdist bdist_wheel"
to push to pypi run "python -m twine upload dist/\*"
Expand All @@ -44,6 +45,6 @@ Version files:
License
========

Copyright (c) 2012-2017 Ford Motor Company
Copyright (c) 2012-2020 Ford Motor Company

Licensed under the BSD license.
6 changes: 0 additions & 6 deletions docs/_static/rtd.css
Original file line number Diff line number Diff line change
Expand Up @@ -382,12 +382,6 @@ div.sphinxsidebar p a:hover {
border: 1px solid #888;
}

/* Tweak any link appearing in a heading */
div.sphinxsidebar h3 a {
}




/* OTHER STUFF ------------------------------------------------------------ */

Expand Down
2 changes: 1 addition & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ OpenXC for Python

.. image:: https://github.com/openxc/openxc-python/raw/master/docs/_static/logo.png

:Version: 2.0.0
:Version: 2.1.0
:Web: http://openxcplatform.com
:Download: http://pypi.python.org/pypi/openxc/
:Documentation: http://python.openxcplatform.com
Expand Down
2 changes: 1 addition & 1 deletion docs/tools/control.rst
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ Set the host and port for the C5 Cellular device

.. code-block:: bash
$ openxc-control set --network-host www.server.com --port 80
$ openxc-control set --host www.server.com --port 80
This will return true when successful. If network-host is supplied, but not port,
port will default to 80.
Expand Down
70 changes: 56 additions & 14 deletions openxc/controllers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def __init__(self, queue, request, quit_after_first=True):
queue - A multithreading queue that this receiver will pull potential responses from.
request - The request we are trying to match up with a response.
"""
self.diag_dict = {}
self.request = request
self.queue = queue
self.responses = []
Expand Down Expand Up @@ -82,12 +83,44 @@ def handle_responses(self):
response = self.queue.get(
timeout=self.COMMAND_RESPONSE_TIMEOUT_S)
if self._response_matches_request(response):
if type(self) == DiagnosticResponseReceiver:
if self._response_is_multiframe(response):
if response['id'] in self.diag_dict:
self.diag_dict[response['id']].addFrame(response)
else:
self.diag_dict[response['id']] = MultiframeDiagnosticMessage(response)
if self._return_final(response):
self.responses.append(self.diag_dict[response['id']].getResponse())
self.diag_dict.pop(response['id'])
self.responses.append(response)
if self.quit_after_first:
self.running = False
self.queue.task_done()
except Empty:
break

class MultiframeDiagnosticMessage:
def __init__(self, response):
self.id = response['id'] - 16
self.mode = response['mode']
self.bus = response['bus']
self.pid = response['pid']
self.payload = '0x' + response['payload'][8:]

def addFrame(self, response):
self.payload += response['payload'][8:]

def getResponse(self):
request = {
'timestamp': 0,
'bus': self.bus,
'id': self.id,
'mode': self.mode,
'success': True,
'pid': self.pid,
'payload': self.payload
}
return request

class CommandResponseReceiver(ResponseReceiver):
"""A receiver that matches the 'command' field in responses to the
Expand All @@ -104,7 +137,7 @@ class DiagnosticResponseReceiver(ResponseReceiver):
"""A receiver that matches the bus, ID, mode and PID from a
diagnostic request to an incoming response.
"""

def __init__(self, queue, request):
super(DiagnosticResponseReceiver, self).__init__(queue, request,
quit_after_first=False)
Expand Down Expand Up @@ -135,7 +168,16 @@ def _response_matches_request(self, response):
return False

return response.get('mode', None) == self.diagnostic_request['mode']


def _response_is_multiframe(self, response):
if 'frame' in response:
return True
return False

def _return_final(self, response):
if response['frame'] == -1:
return True
return False

class Controller(object):
"""A Controller is a physical vehicle interface that accepts commands to be
Expand Down Expand Up @@ -175,17 +217,17 @@ def complex_request(self, request, wait_for_first_response=True):
if wait_for_first_response:
responses = receiver.wait_for_responses()
return responses

def _send_complex_request(self, request):
self.write_bytes(self.streamer.serialize_for_stream(request))

@classmethod
def _build_diagnostic_request(cls, message_id, mode, bus=None, pid=None,
def _build_diagnostic_request(cls, id, mode, bus=None, pid=None,
frequency=None, payload=None, decoded_type=None):
request = {
'command': "diagnostic_request",
'request': {
'id': message_id,
'id': id,
'mode': mode
}
}
Expand All @@ -205,19 +247,19 @@ def _build_diagnostic_request(cls, message_id, mode, bus=None, pid=None,

return request

def delete_diagnostic_request(self, message_id, mode, bus=None, pid=None):
request = self._build_diagnostic_request(message_id, mode, bus, pid)
def delete_diagnostic_request(self, id, mode, bus=None, pid=None):
request = self._build_diagnostic_request(id, mode, bus, pid)
request['action'] = 'cancel'
return self._check_command_response_status(request)

def create_diagnostic_request(self, message_id, mode, bus=None, pid=None,
def create_diagnostic_request(self, id, mode, bus=None, pid=None,
frequency=None, payload=None, wait_for_ack=True,
wait_for_first_response=False, decoded_type=None):
"""Send a new diagnostic message request to the VI
Required:
message_id - The message ID (arbitration ID) for the request.
id - The message ID (arbitration ID) for the request.
mode - the diagnostic mode (or service).
Optional:
Expand Down Expand Up @@ -245,7 +287,7 @@ def create_diagnostic_request(self, message_id, mode, bus=None, pid=None,
"""

request = self._build_diagnostic_request(message_id, mode, bus, pid,
request = self._build_diagnostic_request(id, mode, bus, pid,
frequency, payload, decoded_type)

diag_response_receiver = None
Expand Down Expand Up @@ -411,15 +453,15 @@ def write_translated(self, name, value, event=None):
assert bytes_written == len(message)
return bytes_written

def write_raw(self, message_id, data, bus=None, frame_format=None):
def write_raw(self, id, data, bus=None, frame_format=None):
"""Send a raw write request to the VI.
"""
if not isinstance(message_id, numbers.Number):
if not isinstance(id, numbers.Number):
try:
message_id = int(message_id, 0)
id = int(id, 0)
except ValueError:
raise ValueError("ID must be numerical")
data = {'id': message_id, 'data': data}
data = {'id': id, 'data': data}
if bus is not None:
data['bus'] = bus
if frame_format is not None:
Expand Down
1 change: 1 addition & 0 deletions openxc/controllers/usb.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def _send_complex_request(self, request):
"""Send a request via the USB control request endpoint, rather than as a
bulk transfer.
"""
# LOG.warn("DEBUG STUFF ________________ " + str(self.streamer.serialize_for_stream(request)))
self.device.ctrl_transfer(0x40, self.COMPLEX_CONTROL_COMMAND, 0, 0,
self.streamer.serialize_for_stream(request))

Expand Down
Loading

0 comments on commit 31655a9

Please sign in to comment.