diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 00000000..0bc5b768
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,28 @@
+name: CI Pipeline
+
+on:
+ push:
+ branches: 'master'
+ pull_request:
+ branches: '*'
+
+jobs:
+ build:
+ runs-on: ubuntu-18.04
+ strategy:
+ max-parallel: 4
+ fail-fast: false
+ matrix:
+ python-version: ['3.8', '3.9', '3.10']
+ steps:
+ - uses: actions/checkout@v1
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v2
+ with:
+ python-version: ${{ matrix.python-version }}
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ python -m pip install tox tox-gh-actions
+ - name: Test with tox
+ run: tox
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
new file mode 100644
index 00000000..9c6dea9a
--- /dev/null
+++ b/.readthedocs.yaml
@@ -0,0 +1,14 @@
+version: 2
+
+build:
+ os: ubuntu-22.04
+ tools:
+ python: "3.11"
+
+python:
+ install:
+ - requirements: docs/requirements.txt
+
+mkdocs:
+ configuration: mkdocs.yml
+ fail_on_warning: false
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index ae1b63cb..00000000
--- a/.travis.yml
+++ /dev/null
@@ -1,30 +0,0 @@
-language: python
-dist: xenial
-sudo: false
-
-
-install:
- - pip install tox
-
-matrix:
- include:
- - python: '2.7'
- env: TOXENV=check27
- - python: '3.6'
- env: TOXENV=check36
- - python: '2.7'
- env: TOXENV=py27
- - python: '3.4'
- env: TOXENV=py34
- - python: '3.5'
- env: TOXENV=py35
- - python: '3.6'
- env: TOXENV=py36
- - python: '3.7'
- env: TOXENV=py37
-
-script:
- - tox
-
-cache:
- pip: true
diff --git a/README.md b/README.md
index 526c197f..791611f3 100644
--- a/README.md
+++ b/README.md
@@ -55,6 +55,7 @@ Here are a handful of the supported commands (sensors). For a full list, see [th
- Time since trouble codes cleared
- Hybrid battery pack remaining life
- Engine fuel rate
+- Vehicle Identification Number (VIN)
License
-------
diff --git a/docs/Async Connections.md b/docs/Async Connections.md
index b4074be1..d655faff 100644
--- a/docs/Async Connections.md
+++ b/docs/Async Connections.md
@@ -1,3 +1,5 @@
+# Async Connections
+
Since the standard `query()` function is blocking, it can be a hazard for UI event loops. To deal with this, python-OBD has an `Async` connection object that can be used in place of the standard `OBD` object. `Async` is a subclass of `OBD`, and therefore inherits all of the standard methods. However, `Async` adds a few in order to control a threaded update loop. This loop will keep the values of your commands up to date with the vehicle. This way, when the user `query`s the car, the latest response is returned immediately.
The update loop is controlled by calling `start()` and `stop()`. To subscribe a command for updating, call `watch()` with your requested OBDCommand. Because the update loop is threaded, commands can only be `watch`ed while the loop is `stop`ed.
@@ -32,7 +34,7 @@ connection = obd.Async()
# a callback that prints every new value to the console
def new_rpm(r):
- print r.value
+ print (r.value)
connection.watch(obd.commands.RPM, callback=new_rpm)
connection.start()
diff --git a/docs/Command Lookup.md b/docs/Command Lookup.md
index 43e9ace7..f87ea39a 100644
--- a/docs/Command Lookup.md
+++ b/docs/Command Lookup.md
@@ -1,4 +1,6 @@
-`OBDCommand`s are objects used to query information from the vehicle. They contain all of the information neccessary to perform the query, and decode the cars response. Python-OBD has [built in tables](Command Tables.md) for the most common commands. They can be looked up by name, or by mode & PID.
+# Command Lookup
+
+`OBDCommand`s are objects used to query information from the vehicle. They contain all of the information necessary to perform the query and decode the car's response. Python-OBD has [built in tables](Command Tables.md) for the most common commands. They can be looked up by name or by mode & PID.
```python
import obd
diff --git a/docs/Command Tables.md b/docs/Command Tables.md
index 8ea0046f..aebaf85d 100644
--- a/docs/Command Tables.md
+++ b/docs/Command Tables.md
@@ -1,4 +1,6 @@
-# OBD-II adapter (ELM327 commands)
+# Commands
+
+## OBD-II adapter (ELM327 commands)
|PID | Name | Description | Response Value |
|-----|-------------|-----------------------------------------|-----------------------|
@@ -7,7 +9,7 @@
-# Mode 01
+## Mode 01
|PID | Name | Description | Response Value |
|----|---------------------------|-----------------------------------------|-----------------------|
@@ -110,7 +112,7 @@
-# Mode 02
+## Mode 02
Mode 02 commands are the same as mode 01, but are metrics from when the last DTC occurred (the freeze frame). To access them by name, simple prepend `DTC_` to the Mode 01 command name.
@@ -124,7 +126,7 @@ obd.commands.DTC_RPM # the Mode 02 command
-# Mode 03
+## Mode 03
Mode 03 contains a single command `GET_DTC` which requests all diagnostic trouble codes from the vehicle. The response will contain the codes themselves, as well as a description (if python-OBD has one). See the [DTC Responses](Responses.md#diagnostic-trouble-codes-dtcs) section for more details.
@@ -135,7 +137,7 @@ Mode 03 contains a single command `GET_DTC` which requests all diagnostic troubl
-# Mode 04
+## Mode 04
|PID | Name | Description | Response Value |
|-----|-----------|-----------------------------------------|-----------------------|
@@ -143,7 +145,7 @@ Mode 03 contains a single command `GET_DTC` which requests all diagnostic troubl
-# Mode 06
+## Mode 06
*WARNING: mode 06 is experimental. While it passes software tests, it has not been tested on a real vehicle. Any debug output for this mode would be greatly appreciated.*
@@ -252,7 +254,7 @@ Mode 06 commands are used to monitor various test results from the vehicle. All
-# Mode 07
+## Mode 07
The return value will be encoded in the same structure as the Mode 03 `GET_DTC` command.
@@ -261,3 +263,25 @@ The return value will be encoded in the same structure as the Mode 03 `GET_DTC`
| N/A | GET_CURRENT_DTC | Get DTCs from the current/last driving cycle | [special](Responses.md#diagnostic-trouble-codes-dtcs) |
+
+## Mode 09
+
+*WARNING: mode 09 is experimental. While it has been tested on a hardware simulator, only a subset of the supported
+commands have (00-06) been tested. Any debug output for this mode, especially for the untested PIDs, would be greatly appreciated.*
+
+|PID | Name | Description | Response Value |
+|----|------------------------------|----------------------------------------------------|-----------------------|
+| 00 | PIDS_9A | Supported PIDs [01-20] | BitArray |
+| 01 | VIN_MESSAGE_COUNT | VIN Message Count | Unit.count |
+| 02 | VIN | Vehicle Identification Number | string |
+| 03 | CALIBRATION_ID_MESSAGE_COUNT | Calibration ID message count for PID 04 | Unit.count |
+| 04 | CALIBRATION_ID | Calibration ID | string |
+| 05 | CVN_MESSAGE_COUNT | CVN Message Count for PID 06 | Unit.count |
+| 06 | CVN | Calibration Verification Numbers | hex string |
+| 07 | PERF_TRACKING_MESSAGE_COUNT | Performance tracking message count | TODO |
+| 08 | PERF_TRACKING_SPARK | In-use performance tracking (spark ignition) | TODO |
+| 09 | ECU_NAME_MESSAGE_COUNT | ECU Name Message Count for PID 0A | TODO |
+| 0a | ECU_NAME | ECU Name | TODO |
+| 0b | PERF_TRACKING_COMPRESSION | In-use performance tracking (compression ignition) | TODO |
+
+
diff --git a/docs/Connections.md b/docs/Connections.md
index 8ffa9051..1df861fd 100644
--- a/docs/Connections.md
+++ b/docs/Connections.md
@@ -1,3 +1,4 @@
+# Connections
After installing the library, simply `import obd`, and create a new OBD connection object. By default, python-OBD will scan for Bluetooth and USB serial ports (in that order), and will pick the first connection it finds. The port can also be specified manually by passing a connection string to the OBD constructor. You can also use the `scan_serial` helper retrieve a list of connected ports.
@@ -26,7 +27,7 @@ connection = obd.OBD(ports[0]) # connect to the first port in the list
`baudrate`: The baudrate at which to set the serial connection. This can vary from adapter to adapter. Typical values are: 9600, 38400, 19200, 57600, 115200. The default value (`None`) will auto select a baudrate.
-`protocol`: Forces python-OBD to use the given protocol when communicating with the adapter. See [protocol_id()](Connections.md/#protocol_id) for possible values. The default value (`None`) will auto select a protocol.
+`protocol`: Forces python-OBD to use the given protocol when communicating with the adapter. See [protocol_id()](#protocol_id) for possible values. The default value (`None`) will auto select a protocol.
`fast`: Allows commands to be optimized before being sent to the car. Python-OBD currently makes two such optimizations:
diff --git a/docs/Custom Commands.md b/docs/Custom Commands.md
index 466deb29..e726030d 100644
--- a/docs/Custom Commands.md
+++ b/docs/Custom Commands.md
@@ -1,3 +1,4 @@
+# Custom Commands
If the command you need is not in python-OBDs tables, you can create a new `OBDCommand` object. The constructor accepts the following arguments (each will become a property).
@@ -13,8 +14,7 @@ If the command you need is not in python-OBDs tables, you can create a new `OBDC
| header (optional) | string | If set, use a custom header instead of the default one (7E0) |
-Example
--------
+## Example
```python
from obd import OBDCommand, Unit
@@ -58,7 +58,7 @@ Here are some details on the less intuitive fields of an OBDCommand:
---
-### OBDCommand.decoder
+## OBDCommand.decoder
The `decoder` argument is a function of following form.
@@ -83,7 +83,7 @@ def (messages):
---
-### OBDCommand.ecu
+## OBDCommand.ecu
The `ecu` argument is a constant used to filter incoming messages. Some commands may listen to multiple ECUs (such as DTC decoders), where others may only be concerned with the engine (such as RPM). Currently, python-OBD can only distinguish the engine, but this list may be expanded over time:
@@ -94,13 +94,13 @@ The `ecu` argument is a constant used to filter incoming messages. Some commands
---
-### OBDCommand.fast
+## OBDCommand.fast
The optional `fast` argument tells python-OBD whether it is safe to append a `"01"` to the end of the command. This will instruct the adapter to return the first response it recieves, rather than waiting for more (and eventually reaching a timeout). This can speed up requests significantly, and is enabled for most of python-OBDs internal commands. However, for unusual commands, it is safest to leave this disabled.
---
-### OBDCommand.header
+## OBDCommand.header
The optional `header` argument tells python-OBD to use a custom header when querying the command. If not set, python-OBD assumes that the default 7E0 header is needed for querying the command. The switch between default and custom header (and vice versa) is automatically done by python-OBD.
diff --git a/docs/Debug.md b/docs/Debug.md
index 0f929826..5e1df610 100644
--- a/docs/Debug.md
+++ b/docs/Debug.md
@@ -1,3 +1,5 @@
+# Debug
+
python-OBD uses python's builtin logging system. By default, it is setup to send output to `stderr` with a level of WARNING. The module's logger can be accessed via the `logger` variable at the root of the module. For instance, to enable console printing of all debug messages, use the following snippet:
```python
diff --git a/docs/Responses.md b/docs/Responses.md
index 30b992e6..0eef78f9 100644
--- a/docs/Responses.md
+++ b/docs/Responses.md
@@ -1,3 +1,5 @@
+# Responses
+
The `query()` function returns `OBDResponse` objects. These objects have the following properties:
| Property | Description |
@@ -11,7 +13,7 @@ The `query()` function returns `OBDResponse` objects. These objects have the fol
---
-### is_null()
+## is_null()
Use this function to check if a response is empty. Python-OBD will emit empty responses when it is unable to retrieve data from the car.
@@ -25,7 +27,7 @@ if not r.is_null():
---
-# Pint Values
+## Pint Values
The `value` property typically contains a [Pint](http://pint.readthedocs.io/en/latest/) `Quantity` object, but can also hold complex structures (depending on the request). Pint quantities combine a value and unit into a single class, and are used to represent physical values such as "4 seconds", and "88 mph". This allows for consistency when doing math and unit conversions. Pint maintains a registry of units, which is exposed in python-OBD as `obd.Unit`.
@@ -71,7 +73,7 @@ import obd
---
-# Status
+## Status
The status command returns information about the Malfunction Indicator Light (check-engine light), the number of trouble codes being thrown, and the type of engine.
@@ -111,7 +113,7 @@ Here are all of the tests names that python-OBD reports:
---
-# Diagnostic Trouble Codes (DTCs)
+## Diagnostic Trouble Codes (DTCs)
Each DTC is represented by a tuple containing the DTC code, and a description (if python-OBD has one). For commands that return multiple DTCs, a list is used.
@@ -129,7 +131,7 @@ response.value = ("P0104", "Mass or Volume Air Flow Circuit Intermittent")
---
-# Fuel Status
+## Fuel Status
The fuel status is a tuple of two strings, telling the status of the first and second fuel systems. Most cars only have one system, so the second element will likely be an empty string. The possible fuel statuses are:
@@ -144,7 +146,7 @@ The fuel status is a tuple of two strings, telling the status of the first and s
---
-# Air Status
+## Air Status
The air status will be one of these strings:
@@ -157,7 +159,7 @@ The air status will be one of these strings:
---
-# Oxygen Sensors Present
+## Oxygen Sensors Present
Returns a 2D structure of tuples (representing bank and sensor number), that holds boolean values for sensor presence.
@@ -183,7 +185,7 @@ response.value[1][2] == True # Bank 1, Sensor 2 is present
```
---
-# Monitors (Mode 06 Responses)
+## Monitors (Mode 06 Responses)
All mode 06 commands return `Monitor` objects holding various test results for the requested sensor. A single monitor response can hold multiple tests, in the form of `MonitorTest` objects. The OBD standard defines some tests, but vehicles can always implement custom tests beyond the standard. Here are the standard Test IDs (TIDs) that python-OBD will recognize:
diff --git a/docs/Troubleshooting.md b/docs/Troubleshooting.md
index f2b9baca..7889e251 100644
--- a/docs/Troubleshooting.md
+++ b/docs/Troubleshooting.md
@@ -1,4 +1,3 @@
-
# Debug Output
If python-OBD is not working properly, the first thing you should do is enable debug output. Add the following line before your connection code to print all of the debug information to your console:
@@ -52,7 +51,7 @@ Here are some common logs from python-OBD, and their meanings:
### Unresponsive ELM
-```
+```none
[obd] ========================== python-OBD (v0.4.0) ==========================
[obd] Explicit port defined
[obd] Opening serial port '/dev/pts/2'
@@ -93,7 +92,7 @@ print ports # ['/dev/ttyUSB0', '/dev/ttyUSB1']
### Unresponsive Vehicle
-```
+```none
[obd] ========================== python-OBD (v0.4.0) ==========================
[obd] Explicit port defined
[obd] Opening serial port '/dev/pts/2'
diff --git a/docs/index.md b/docs/index.md
index 7688edea..3d2c1e69 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -6,7 +6,7 @@ Python-OBD is a library for handling data from a car's [**O**n-**B**oard **D**ia
-# Installation
+## Installation
Install the latest release from pypi:
@@ -22,7 +22,7 @@ $ sudo apt-get install bluetooth bluez-utils blueman
-# Basic Usage
+## Basic Usage
```python
import obd
@@ -41,7 +41,7 @@ OBD connections operate in a request-reply fashion. To retrieve data from the ca
-# Module Layout
+## Module Layout
```python
import obd
@@ -59,7 +59,7 @@ obd.logger # the OBD module's root logger (for debug)
-# License
+## License
GNU General Public License V2
diff --git a/docs/requirements.txt b/docs/requirements.txt
new file mode 100644
index 00000000..49ec98c5
--- /dev/null
+++ b/docs/requirements.txt
@@ -0,0 +1 @@
+mkdocs==1.5.2
diff --git a/mkdocs.yml b/mkdocs.yml
index bec2ac65..ad9086bb 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -3,7 +3,7 @@ repo_url: https://github.com/brendan-w/python-OBD
repo_name: GitHub
extra_javascript:
- assets/extra.js
-pages:
+nav:
- 'Getting Started': 'index.md'
- 'OBD Connections': 'Connections.md'
- 'Command Lookup': 'Command Lookup.md'
diff --git a/obd/UnitsAndScaling.py b/obd/UnitsAndScaling.py
index b49650b1..fe0fae4d 100644
--- a/obd/UnitsAndScaling.py
+++ b/obd/UnitsAndScaling.py
@@ -36,8 +36,8 @@
# export the unit registry
Unit = pint.UnitRegistry()
-Unit.define("percent = [] = %")
Unit.define("ratio = []")
+Unit.define("percent = 1e-2 ratio = %")
Unit.define("gps = gram / second = GPS = grams_per_second")
Unit.define("lph = liter / hour = LPH = liters_per_hour")
Unit.define("ppm = count / 1000000 = PPM = parts_per_million")
diff --git a/obd/__version__.py b/obd/__version__.py
index f0788a87..fb9b668f 100644
--- a/obd/__version__.py
+++ b/obd/__version__.py
@@ -1 +1 @@
-__version__ = '0.7.1'
+__version__ = '0.7.2'
diff --git a/obd/commands.py b/obd/commands.py
index 43ec8f3c..9162f1c8 100644
--- a/obd/commands.py
+++ b/obd/commands.py
@@ -279,6 +279,27 @@
OBDCommand("GET_CURRENT_DTC", "Get DTCs from the current/last driving cycle", b"07", 0, dtc, ECU.ALL, False),
]
+
+__mode9__ = [
+ # name description cmd bytes decoder ECU fast
+ OBDCommand("PIDS_9A" , "Supported PIDs [01-20]" , b"0900", 7, pid, ECU.ALL, True),
+ OBDCommand("VIN_MESSAGE_COUNT" , "VIN Message Count" , b"0901", 3, count, ECU.ENGINE, True),
+ OBDCommand("VIN" , "Vehicle Identification Number" , b"0902", 22, encoded_string(17), ECU.ENGINE, True),
+ OBDCommand("CALIBRATION_ID_MESSAGE_COUNT","Calibration ID message count for PID 04" , b"0903", 3, count, ECU.ALL, True),
+ OBDCommand("CALIBRATION_ID" , "Calibration ID" , b"0904", 18, encoded_string(16), ECU.ALL, True),
+ OBDCommand("CVN_MESSAGE_COUNT" , "CVN Message Count for PID 06" , b"0905", 3, count, ECU.ALL, True),
+ OBDCommand("CVN" , "Calibration Verification Numbers" , b"0906", 10, cvn, ECU.ALL, True),
+
+#
+# NOTE: The following are untested
+#
+# OBDCommand("PERF_TRACKING_MESSAGE_COUNT", "Performance tracking message count" , b"0907", 3, count, ECU.ALL, True),
+# OBDCommand("PERF_TRACKING_SPARK" , "In-use performance tracking (spark ignition)" , b"0908", 4, raw_string, ECU.ALL, True),
+# OBDCommand("ECU_NAME_MESSAGE_COUNT" , "ECU Name Message Count for PID 0A" , b"0909", 3, count, ECU.ALL, True),
+# OBDCommand("ECU_NAME" , "ECU Name" , b"090a", 20, raw_string, ECU.ALL, True),
+# OBDCommand("PERF_TRACKING_COMPRESSION" , "In-use performance tracking (compression ignition)", b"090b", 4, raw_string, ECU.ALL, True),
+]
+
__misc__ = [
OBDCommand("ELM_VERSION", "ELM327 version string", b"ATI", 0, raw_string, ECU.UNKNOWN, False),
OBDCommand("ELM_VOLTAGE", "Voltage detected by OBD-II adapter", b"ATRV", 0, elm_voltage, ECU.UNKNOWN, False),
@@ -303,6 +324,7 @@ def __init__(self):
__mode6__,
__mode7__,
[],
+ __mode9__,
]
# allow commands to be accessed by name
@@ -350,6 +372,7 @@ def base_commands(self):
"""
return [
self.PIDS_A,
+ self.PIDS_9A,
self.MIDS_A,
self.GET_DTC,
self.CLEAR_DTC,
diff --git a/obd/decoders.py b/obd/decoders.py
index 3020be0c..fffca50a 100644
--- a/obd/decoders.py
+++ b/obd/decoders.py
@@ -94,6 +94,10 @@ def decode_uas(messages, id_):
Return pint Quantities
"""
+def count(messages):
+ d = messages[0].data[2:]
+ v = bytes_to_int(d)
+ return v * Unit.count
# 0 to 100 %
def percent(messages):
@@ -484,3 +488,28 @@ def monitor(messages):
mon.add_test(test)
return mon
+
+
+def encoded_string(length):
+ """ Extract an encoded string from multi-part messages """
+ return functools.partial(decode_encoded_string, length=length)
+
+
+def decode_encoded_string(messages, length):
+ d = messages[0].data[2:]
+
+ if len(d) < length:
+ logger.debug("Invalid string {}. Discarding...", d)
+ return None
+
+ # Encoded strings come in bundles of messages with leading null values to
+ # pad out the string to the next full message size. We strip off the
+ # leading null characters here and return the resulting string.
+ return d.strip().strip(b'\x00' b'\x01' b'\x02' b'\\x00' b'\\x01' b'\\x02')
+
+
+def cvn(messages):
+ d = decode_encoded_string(messages, 4)
+ if d is None:
+ return None
+ return bytes_to_hex(d)
diff --git a/obd/elm327.py b/obd/elm327.py
index 726e4fd6..5391f0ba 100644
--- a/obd/elm327.py
+++ b/obd/elm327.py
@@ -53,7 +53,9 @@ class ELM327:
ecus()
"""
+ # chevron (ELM prompt character)
ELM_PROMPT = b'>'
+ # an 'OK' which indicates we are entering low power state
ELM_LP_ACTIVE = b'OK'
_SUPPORTED_PROTOCOLS = {
@@ -116,8 +118,8 @@ def __init__(self, addr, port, protocol, timeout,
self.__protocol = UnknownProtocol([])
self.__low_power = False
self.timeout = timeout
-
- # ------------- open port -------------
+
+ # ------------- open port -------------
try:
self.__port = socket.socket()
self.__port.connect((addr, port))
@@ -133,7 +135,6 @@ def __init__(self, addr, port, protocol, timeout,
self.__write(b" ")
time.sleep(1)
-
# ---------------------------- ATZ (reset) ----------------------------
try:
self.__send(b"ATZ", delay=1) # wait 1 second for ELM to initialize
@@ -503,4 +504,4 @@ def __read(self):
# splits into lines while removing empty lines and trailing spaces
lines = [s.strip() for s in re.split("[\r\n]", string) if bool(s)]
- return lines
+ return lines
\ No newline at end of file
diff --git a/obd/protocols/protocol.py b/obd/protocols/protocol.py
index 49ce169f..340be559 100644
--- a/obd/protocols/protocol.py
+++ b/obd/protocols/protocol.py
@@ -146,6 +146,12 @@ def __init__(self, lines_0100):
# for example: self.TX_ID_ENGINE : ECU.ENGINE
self.ecu_map = {}
+ if (self.TX_ID_ENGINE is not None):
+ self.ecu_map[self.TX_ID_ENGINE] = ECU.ENGINE
+
+ if (self.TX_ID_TRANSMISSION is not None):
+ self.ecu_map[self.TX_ID_TRANSMISSION] = ECU.TRANSMISSION
+
# parse the 0100 data into messages
# NOTE: at this point, their "ecu" property will be UNKNOWN
messages = self(lines_0100)
diff --git a/setup.py b/setup.py
index b39ec4d1..55438d8d 100644
--- a/setup.py
+++ b/setup.py
@@ -8,7 +8,7 @@
setup(
name="obd",
- version="0.7.1",
+ version="0.7.2",
description=("Serial module for handling live sensor data from a vehicle's OBD-II port over wifi suited for a Panda Adapater"),
long_description=long_description,
long_description_content_type="text/markdown",
@@ -30,5 +30,5 @@
packages=find_packages(),
include_package_data=True,
zip_safe=False,
- install_requires=["pyserial==3.*", "pint==0.7.*"],
+ install_requires=["pyserial==3.*", "pint==0.20.*"],
)
diff --git a/tests/test_decoders.py b/tests/test_decoders.py
index 9f49b062..062d9655 100644
--- a/tests/test_decoders.py
+++ b/tests/test_decoders.py
@@ -295,6 +295,14 @@ def test_dtc():
("B0003", ""),
]
+def test_vin_message_count():
+ assert d.count(m("0901")) == 0
+
+def test_vin():
+ assert d.encoded_string(17)(m("0201575030" + "5A5A5A39395A54" + "53333932313234")) == bytearray(b'WP0ZZZ99ZTS392124')
+
+def test_cvn():
+ assert d.cvn(m("6021791bc8216e0b")) == '791bc8216e'
def test_monitor():
# single test -----------------------------------------
diff --git a/tests/test_protocol.py b/tests/test_protocol.py
index b2757276..0c6ccc75 100644
--- a/tests/test_protocol.py
+++ b/tests/test_protocol.py
@@ -74,4 +74,4 @@ def test_populate_ecu_map():
# if no messages were received, then the map is empty
p = SAE_J1850_PWM([])
- assert len(p.ecu_map) == 0
+ assert p.ecu_map[p.TX_ID_ENGINE] == ECU.ENGINE
diff --git a/tox.ini b/tox.ini
index 50d3cff8..20476082 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,49 +1,32 @@
[tox]
envlist =
- check{27,36},
- py{27,py,34,35,36,37},
+ py{38,39,310,311},
coverage
+[gh-actions]
+python =
+ 3.8: py38
+ 3.9: py39
+ 3.10: py310
+ 3.11: py311
[testenv]
usedevelop = true
setenv =
COVERAGE_FILE={toxinidir}/.coverage_{envname}
deps =
- pdbpp==0.9.6
- pytest==3.10.1
- pytest-cov==2.6.1
-whitelist_externals =
- rm
+ pdbpp==0.10.3
+ pytest==7.2.1
+ pytest-cov==4.0.0
commands =
- rm -vf {toxinidir}/.coverage_{envname}
pytest --cov-report= --cov=obd {posargs}
-[testenv:check27]
-basepython = python2.7
-skipsdist = true
-deps =
- check-manifest==0.37
- flake8==3.7.7
-commands =
- flake8 {envsitepackagesdir}/obd
- python setup.py check --strict --metadata
-
-
-[testenv:check36]
-basepython = python3.6
-skipsdist = true
-deps = {[testenv:check27]deps}
-commands = {[testenv:check27]commands}
-
-
[testenv:coverage]
skipsdist = true
deps =
coverage
whitelist_externals =
/bin/bash
- rm
commands =
/bin/bash -c 'coverage combine {toxinidir}/.coverage_*'
coverage html -i
@@ -52,7 +35,6 @@ commands =
[flake8]
max-line-length = 120
-
[coverage:run]
omit =
.tox/*