Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
6a1456d
testing code changes to add get_vin as a openxc control command.
jstoke53 Jul 13, 2020
88f307a
add git_vin command to main() so openxc-python can understand the new…
jstoke53 Jul 20, 2020
4976002
Update usb.py
pjt0620 Sep 30, 2020
7e01017
Update README.rst
pjt0620 Sep 30, 2020
b8c00b9
Update README.rst
pjt0620 Sep 30, 2020
0a94f1c
Merge pull request #155 from openxc/64-bit-python-fix
pjt0620 Sep 30, 2020
14f32f7
Regenerated the Python protobuf file and fixed glue file binary to pr…
GenoJAFord Oct 15, 2020
26ed7fa
Unit test failure fixes
GenoJAFord Oct 19, 2020
8db96a8
Python unit tests must define certain subfields
GenoJAFord Oct 19, 2020
e5a932b
Fixed Protobuf diag response by fixing python memory management issue
GenoJAFord Oct 20, 2020
2606b03
Fixed unit tests depending on binary protobuf message structure
GenoJAFord Oct 20, 2020
ce8d48b
More unit tests fixes for message elements
GenoJAFord Oct 20, 2020
e845ad1
protected string conversion line
GenoJAFord Oct 20, 2020
3585f06
Unit tests
GenoJAFord Oct 20, 2020
0ab445e
Merge pull request #156 from openxc/regenproto
GenoJAFord Oct 20, 2020
25d5e1c
Fixed the sonar major issues
SamaVinod Dec 7, 2020
41cc1fb
Merge pull request #157 from openxc/Sonar-major-fix
SamaVinod Dec 9, 2020
f7ba31c
Create initial github actions yml
pjt0620 Feb 9, 2021
015e014
Update python-test.yml
pjt0620 Feb 9, 2021
f7a1316
Update python-test.yml
pjt0620 Feb 9, 2021
b8f76ca
Create python-publish.yml
pjt0620 Feb 9, 2021
ee47e52
update badge
pjt0620 Feb 9, 2021
b787623
update name
pjt0620 Feb 9, 2021
f4d3374
fix link
pjt0620 Feb 9, 2021
d222e25
fix link
pjt0620 Feb 9, 2021
25f9288
Merge branch 'next' into Github-actions-test
pjt0620 Feb 9, 2021
3107fe4
Merge branch 'next' into github-actions-publish
pjt0620 Feb 9, 2021
b7f8e47
Merge pull request #158 from openxc/Github-actions-test
pjt0620 Feb 9, 2021
3d18279
Merge branch 'next' into github-actions-publish
pjt0620 Feb 9, 2021
2782a8b
Merge pull request #159 from openxc/github-actions-publish
pjt0620 Feb 9, 2021
4579243
Travis Decommission
pjt0620 Feb 23, 2021
e6c228d
Merge pull request #160 from openxc/Travis-Decommission
pjt0620 Feb 23, 2021
09fee20
Update proto file
pjt0620 Jun 1, 2021
1339794
Merge pull request #161 from openxc/pb_fix
pjt0620 Jun 1, 2021
127f753
Merge remote-tracking branch 'origin/next' into get-vin-heartbeat
GenoJAFord Jun 15, 2021
26275d9
Update python-test.yml
pjt0620 Jun 21, 2021
8b894a7
Merge pull request #162 from openxc/get-vin-heartbeat
GenoJAFord Jun 23, 2021
9077b60
parse the --new_payload-format option before using it
GenoJAFord Jul 29, 2021
cc6765c
Protobuf format argument now properly streaming out protobuf binary
GenoJAFord Aug 2, 2021
24a06a4
Merge pull request #163 from openxc/release820
GenoJAFord Aug 3, 2021
77dab4d
Updated python openxc version to 2.2.0 and added update notes
GenoJAFord Aug 9, 2021
08f7647
Merge pull request #165 from openxc/release820
GenoJAFord Aug 10, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# This workflow will upload a Python Package using Twine when a release is created
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries

name: Upload Python Package

on:
release:
types: [created]

jobs:
deploy:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel twine
- name: Build and publish
env:
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run: |
python setup.py sdist bdist_wheel
twine upload dist/*
33 changes: 33 additions & 0 deletions .github/workflows/python-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

name: Test Open XC Pyton

on: [ pull_request ]

jobs:
build:

runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.6.7]

steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install python-bluetooth -qq -y
python -m pip install --upgrade pip
python -m pip install pytest pyserial==3.1.1 coveralls
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi

- name: Test
run: |
python setup.py test

20 changes: 0 additions & 20 deletions .travis.yml

This file was deleted.

10 changes: 10 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
OpenXC Python Library Changelog
===============================

v2.2.0
----------
* Improvements to usb traffic handling
* Updated message format based upton the protobuf file
* Improved memory management for protobuf
* SonarQube updates
* Github actions updated,travis decommissioned
* Support for the new get_vin command
openxc-control get_vin

v2.1.0
----------
* SonarQube integration
Expand Down
8 changes: 5 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ OpenXC for Python

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

:Version: 2.1.0
:Version: 2.2.0
:Web: http://openxcplatform.com
:Download: http://pypi.python.org/pypi/openxc/
:Documentation: http://python.openxcplatform.com
:Source: http://github.com/openxc/openxc-python/
:Keywords: vehicle, openxc, python

.. image:: https://travis-ci.org/openxc/openxc-python.svg?branch=master
:target: https://travis-ci.org/openxc/openxc-python
.. image:: https://github.com/openxc/openxc-python/workflows/Test%20Open%20XC%20Pyton/badge.svg
:target: https://github.com/openxc/openxc-python/actions?query=workflow%3A%22Test+Open+XC+Pyton%22

.. image:: https://coveralls.io/repos/openxc/openxc-python/badge.png?branch=master
:target: https://coveralls.io/r/openxc/openxc-python?branch=master
Expand All @@ -30,6 +30,8 @@ In addition to a port of the Android library API, the package also contains a
number of command-line tools for connecting to the CAN translator and
manipulating previously recorded vehicle data.

If you are getting the error "ValueError: No backend available" on windows please reinstall your libusb0 driver using https://github.com/openxc/vi-windows-driver if you are in a envirment where you can not use an unsigned driver please use https://zadig.akeo.ie/

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.

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.1.0
:Version: 2.2.0
:Web: http://openxcplatform.com
:Download: http://pypi.python.org/pypi/openxc/
:Documentation: http://python.openxcplatform.com
Expand Down
25 changes: 18 additions & 7 deletions openxc/controllers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,16 @@ 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 type(self) == DiagnosticResponseReceiver and 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())
save = self.responses.pop()
dentry = self.diag_dict[response['id']].getResponse() # DO NOT REMOVE This MUST be saved to a local variable to prevent deallocation
self.responses.append(dentry) # DO NOT REMOVE This MUST be saved to a local variable to prevent deallocation
self.responses.append(save)
self.diag_dict.pop(response['id'])
self.responses.append(response)
if self.quit_after_first:
Expand All @@ -101,14 +103,14 @@ def handle_responses(self):

class MultiframeDiagnosticMessage:
def __init__(self, response):
self.id = response['id'] - 16
self.id = response['id']
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:]
self.payload += response['payload'][2:]

def getResponse(self):
request = {
Expand Down Expand Up @@ -170,8 +172,9 @@ def _response_matches_request(self, response):
return response.get('mode', None) == self.diagnostic_request['mode']

def _response_is_multiframe(self, response):
if 'frame' in response:
return True
print(response)
if 'total_size' in response.keys() and response["total_size"] > 0:
return True
return False

def _return_final(self, response):
Expand Down Expand Up @@ -427,6 +430,14 @@ def device_id(self):
}
return self._check_command_response_message(request)

def get_vin(self):
"""Request vehicle VIN
"""
request = {
"command": "get_vin"
}
return self._check_command_response_message(request)

def write(self, **kwargs):
"""Serialize a raw or translated write request and send it to the VI,
following the OpenXC message format.
Expand Down
2 changes: 0 additions & 2 deletions openxc/formats/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ class VehicleMessageStreamer(object):
bytes_received = 0

def receive(self, payload):
if not isinstance(payload, bytes):
payload = payload.encode("utf-8")
if len(payload) > 0:
self.message_buffer += payload
self.bytes_received += len(payload)
95 changes: 47 additions & 48 deletions openxc/formats/binary.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ def _handle_diagnostic_cc_message(cls, data, message):
request_command.action = openxc_pb2.DiagnosticControlCommand.CANCEL
request = request_command.request
request_data = data['request']
request.bus = request_data['bus']
if 'bus' in request_data:
request.bus = request_data['bus']
request.message_id = request_data['id']
request.mode = request_data['mode']
if 'frequency' in request_data:
Expand Down Expand Up @@ -184,6 +185,10 @@ def _build_diagnostic_message(cls, data, message):
response.bus = data['bus']
response.message_id = data['id']
response.mode = data['mode']
if 'total_size' in data:
response.total_size = data['total_size']
if 'frame' in data:
response.frame = data['frame']
if 'pid' in data:
response.pid = data['pid']
if 'success' in data:
Expand Down Expand Up @@ -243,63 +248,57 @@ def _dict_to_protobuf(cls, data):
@classmethod
def _build_can_parsed_message(cls, message, parsed_message):
can_message = message.can_message
if can_message.HasField('bus'):
if can_message.bus != 0:
parsed_message['bus'] = can_message.bus
if can_message.HasField('id'):
if can_message.id != 0:
parsed_message['id'] = can_message.id
if can_message.HasField('data'):
if len(binascii.hexlify(can_message.data).decode("ascii")) > 0:
parsed_message['data'] = "0x%s" % binascii.hexlify(can_message.data).decode("ascii")
if can_message.HasField('frame_format'):
if can_message.frame_format == openxc_pb2.CanMessage.STANDARD:
parsed_message['frame_format'] = "standard"
elif can_message.frame_format == openxc_pb2.CanMessage.EXTENDED:
parsed_message['frame_format'] = "extended"
if can_message.frame_format == openxc_pb2.CanMessage.STANDARD:
parsed_message['frame_format'] = "standard"
elif can_message.frame_format == openxc_pb2.CanMessage.EXTENDED:
parsed_message['frame_format'] = "extended"

@classmethod
def _build_diagnostic_parsed_message(cls, message, parsed_message):
diagnostic_message = message.diagnostic_response
if diagnostic_message.HasField('bus'):
if diagnostic_message.bus != 0:
parsed_message['bus'] = diagnostic_message.bus
if diagnostic_message.HasField('message_id'):
if diagnostic_message.message_id != 0:
parsed_message['id'] = diagnostic_message.message_id
if diagnostic_message.HasField('mode'):
parsed_message['mode'] = diagnostic_message.mode
if diagnostic_message.HasField('pid'):
parsed_message['pid'] = diagnostic_message.pid
if diagnostic_message.HasField('success'):
parsed_message['success'] = diagnostic_message.success
if diagnostic_message.HasField('value'):
parsed_message['mode'] = diagnostic_message.mode
parsed_message['pid'] = diagnostic_message.pid
if diagnostic_message.total_size != 0:
parsed_message['total_size'] = diagnostic_message.total_size
parsed_message['frame'] = diagnostic_message.frame
parsed_message['success'] = diagnostic_message.success
if diagnostic_message.value.type != openxc_pb2.DynamicField.UNUSED: ##GJA
parsed_message['value'] = diagnostic_message.value
if diagnostic_message.HasField('negative_response_code'):
if diagnostic_message.negative_response_code !=0:
parsed_message['negative_response_code'] = diagnostic_message.negative_response_code
if diagnostic_message.HasField('payload'):
if len(binascii.hexlify(diagnostic_message.payload).decode("ascii")) > 0:
parsed_message['payload'] = "0x%s" % binascii.hexlify(diagnostic_message.payload).decode("ascii")

@classmethod
def _build_simple_parsed_message(cls, message, parsed_message):
simple_message = message.simple_message
parsed_message['name'] = simple_message.name
if simple_message.HasField('event'):
event = simple_message.event
if event.HasField('numeric_value'):
parsed_message['event'] = event.numeric_value
elif event.HasField('boolean_value'):
parsed_message['event'] = event.boolean_value
elif event.HasField('string_value'):
parsed_message['event'] = event.string_value

if simple_message.HasField('value'):
value = simple_message.value
if value.HasField('numeric_value'):
parsed_message['value'] = value.numeric_value
elif value.HasField('boolean_value'):
parsed_message['value'] = value.boolean_value
elif value.HasField('string_value'):
parsed_message['value'] = value.string_value
else:
parsed_message = None
event = simple_message.event
if (len(event.string_value) > 0):
parsed_message['event'] = event.string_value
elif event.numeric_value != 0:
parsed_message['event'] = event.numeric_value
else:
parsed_message = None
parsed_message['event'] = event.boolean_value

value = simple_message.value
if (len(value.string_value) > 0):
parsed_message['value'] = value.string_value
elif value.numeric_value != 0:
parsed_message['value'] = value.numeric_value
else:
parsed_message['value'] = value.boolean_value


@classmethod
def _handle_diagnostic_cc_parsed_message(cls, command, parsed_message):
Expand All @@ -316,16 +315,16 @@ def _handle_diagnostic_cc_parsed_message(cls, command, parsed_message):
parsed_message['request']['bus'] = request.bus
parsed_message['request']['mode'] = request.mode

if request.HasField('frequency'):
if request.frequency != 0:
parsed_message['request']['frequency'] = request.frequency
if request.HasField('name'):
if len(request.name) > 0:
parsed_message['request']['name'] = request.name
if request.HasField('multiple_responses'):
parsed_message['request']['multiple_responses'] = request.multiple_responses
if request.HasField('pid'):
parsed_message['request']['multiple_responses'] = request.multiple_responses
if request.pid != 0:
parsed_message['request']['pid'] = request.pid
if request.HasField('payload'):
if len(binascii.hexlify(request.payload).decode("ascii")) > 0:
parsed_message['request']['payload'] = "0x%s" % binascii.hexlify(request.payload).decode("ascii")
print("Finished _handle_diagnostic_cc_parsed_message")

@classmethod
def _handle_passthrough_cc_parsed_message(cls, command, parsed_message):
Expand Down Expand Up @@ -393,14 +392,14 @@ def _build_command_response_parsed_message(cls, message, parsed_message):
raise UnrecognizedBinaryCommandError(response.type)

parsed_message['status'] = response.status
if response.HasField('message'):
if len(response.message) > 0:
parsed_message['message'] = response.message

@classmethod
def _protobuf_to_dict(cls, message):
parsed_message = {}
if message is not None:
if message.type == message.CAN and message.HasField('can_message'):
if message.type == message.CAN:
cls._build_can_parsed_message(message, parsed_message)
elif message.type == message.DIAGNOSTIC:
cls._build_diagnostic_parsed_message(message, parsed_message)
Expand Down
Loading