Giter VIP home page Giter VIP logo

python-j1939's Introduction

python-j1939

Society of Automotive Engineers standard SAE J1939 is the vehicle bus recommended practice used for communication and diagnostics among vehicle components. Originating in the car and heavy-duty truck industry in the United States, it is now widely used in other parts of the world.

SAE J1939 is used in the commercial vehicle area for communication throughout the vehicle, with the physical layer defined in ISO 11898. A different physical layer is used between the tractor and trailer, specified in ISO 11992.

This package is dependent on, was a part of, and broken out from, the python-can project that Brian Thorne has maintained for years..

This codce currently is compatable with the python-can version 3.3.2. After you clone the python-can repo be sure to checkout the 'release-3.3.2' branch

The Controller Area Network is a bus standard designed to allow microcontrollers and devices to communicate with each other. It has priority based bus arbitration, reliable deterministic communication. It is used in cars, trucks, boats, wheelchairs and more.

The can package provides controller area network support for Python developers; providing common abstractions to different hardware devices, and a suite of utilities for sending and receiving messages on a can bus.

In all of my code that used the former protocol import from python-can I needed only to make a small change. Generally a shortning of the import statements.. For example

from can.protocols import j1939

becomes

import j1939

The library (should) support Python 2.7, Python 3.3+ and run on Mac, Linux and Windows; however, at this early time I am only testing on Python 3.4.0 on Linux 3.16.0-38-generic #52~14.04.1-Ubuntu SMP Fri May 8 09:43:57 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

Discussion

If you run into bugs, you can file them in issue tracker. (Any help is appriciated!)

Wherever we interact, we strive to follow the Python Community Code of Conduct.

python-j1939's People

Contributors

akraa avatar brearl avatar jackm avatar johanbrus avatar jonenz avatar milhead2 avatar pjparks avatar rickklaus avatar rsmssnpdr avatar wang701 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-j1939's Issues

Official version and release package?

I am pretty new to this library, forgive me if I'm asking too much, but I was wondering:

  1. Is there any way this package could get an upgrade to make it an official pypi release for example "python-j1939"?
  2. Is there any way to pull a version number out of this package (e.g. with a .version command or similar?
  3. Are there any plans to set up some more extensive documentation for this project (e.g. using the readthedocs.io website)?
    I just feel this library has more potential, but myself am not too familiar with programming yet.

I had a look at another j1939 attempt https://github.com/benkfra/j1939 but this seemed to have come after the python-j1939 can and has not been maintained for about 2 years. Seems like the python-j1939 may be more worthwhile giving an upgrade to make it official.

j1939_notifier swallows non-transport messages in logger

I'm still learning j1939 protocols and python-j1939 structure regarding same.

When I started I commented out the creation of the self.j1939_notifier in j1939 Buss:init.. This allows the logger to actually see all the messages and it better lines up with CAN logs but includes much of the transport manipulations. The j1939_notifier was booting some of the inbound messages.

Unfortunately it breaks some of the examples and I hope that I can unwind how it works and fix it before I upset too many folks.

Install woes

Miller and all,
I'm having an issue running setup.py on a Raspberry Pi running the raspian version of debian 9.9 ("stretch" is the version name) . I installed python-can in my local directory and then ran "sudo python3 setup.py develop". I installed python-j1939-master in my local directory and ran "python3 setup.py test" and got the following output:
+++++++++++++++++++++++++++++++
/usr/lib/python3/dist-packages/setuptools/dist.py:333: UserWarning: Normalizing '0.1.0-alpha.3' to '0.1.0a3'
normalized_version,
running test
Searching for nose
Best match: nose 1.3.7
Processing nose-1.3.7-py3.5.egg

Using /home/pi/CANplay/wbwPlay/python-j1939-master/.eggs/nose-1.3.7-py3.5.egg
Searching for mock
Best match: mock 3.0.5
Processing mock-3.0.5-py3.5.egg

Using /home/pi/CANplay/wbwPlay/python-j1939-master/.eggs/mock-3.0.5-py3.5.egg
running egg_info
writing python_j1939.egg-info/PKG-INFO
writing dependency_links to python_j1939.egg-info/dependency_links.txt
writing top-level names to python_j1939.egg-info/top_level.txt
writing requirements to python_j1939.egg-info/requires.txt
reading manifest file 'python_j1939.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
warning: no files found matching '*.rst' under directory 'doc'
writing manifest file 'python_j1939.egg-info/SOURCES.txt'
running build_ext
Failure: SyntaxError (invalid syntax (init.py, line 15)) ... ERROR

======================================================================
ERROR: Failure: SyntaxError (invalid syntax (init.py, line 15))

Traceback (most recent call last):
File "/home/pi/CANplay/wbwPlay/python-j1939-master/.eggs/nose-1.3.7-py3.5.egg/nose/failure.py", line 39, in runTest
raise self.exc_val.with_traceback(self.tb)
File "/home/pi/CANplay/wbwPlay/python-j1939-master/.eggs/nose-1.3.7-py3.5.egg/nose/loader.py", line 417, in loadTestsFromName
addr.filename, addr.module)
File "/home/pi/CANplay/wbwPlay/python-j1939-master/.eggs/nose-1.3.7-py3.5.egg/nose/importer.py", line 47, in importFromPath
return self.importFromDir(dir_path, fqname)
File "/home/pi/CANplay/wbwPlay/python-j1939-master/.eggs/nose-1.3.7-py3.5.egg/nose/importer.py", line 94, in importFromDir
mod = load_module(part_fqname, fh, filename, desc)
File "/usr/lib/python3.5/imp.py", line 244, in load_module
return load_package(name, filename)
File "/usr/lib/python3.5/imp.py", line 216, in load_package
return _load(spec)
File "", line 693, in _load
File "", line 673, in _load_unlocked
File "", line 673, in exec_module
File "", line 222, in _call_with_frames_removed
File "/home/pi/CANplay/wbwPlay/python-j1939-master/j1939/init.py", line 25, in
from can import CanError
File "/home/pi/CANplay/wbwPlay/python-can-develop/can/init.py", line 15
rc: Dict[str, Any] = dict()
^
SyntaxError: invalid syntax


Ran 1 test in 0.023s

FAILED (errors=1)
Test failed: <unittest.runner.TextTestResult run=1 errors=1 failures=0>
error: Test failed: <unittest.runner.TextTestResult run=1 errors=1 failures=0>
+++++++++++++++++++
Is there an environment variable I need to set? Anything obvious that I've done here or failed to do? Thanks in advance for your help.

Regards,
Bill Walden

Python J1939 library usage

Hi all,
I am new to Python and have good knowledge in J1939 protocol.
We have some J1939 modules developed in LabVIEW and using them in our project, but we are looking to automate the same module using Python, I have gone through Python J1939 library, and I could see there are some functions which can be used to send or receive messages I believe, just for push up I am looking for following code:

  1. Connect to PCAN hardware to transmit J1939 messages.
  2. Transmit a basic J1939 frame with 8 bytes of data or should be more helpful if could be able to transfer 1785 bytes of data (Large message).

Please help me in getting this code so that it will help me in getting into it and start analyzing more on code.

I have installed J1939 library and using Python 3.8.3 32-bit version of software.

18 bit PGN changes break 16 bit masking

The 18 bit PGN mask changes break the 16 bit masking and don't appear to work correctly for 18 bit PGNs. The patch below appears to correct this:

diff --git a/j1939/pgn.py b/j1939/pgn.py
index 24611c1..4305ffc 100644
--- a/j1939/pgn.py
+++ b/j1939/pgn.py
@@ -42,9 +42,9 @@ class PGN(object):

 @value.setter
 def value(self, value):
  •    self.reserved_flag = (value & 0x080000) >> 17
    
  •    self.data_page_flag = (value & 0x040000) >> 16
    
  •    self.pdu_format = (value & 0x03FF00) >> 8
    
  •    self.reserved_flag = (value & 0x020000) >> 17
    
  •    self.data_page_flag = (value & 0x010000) >> 16
    
  •    self.pdu_format = (value & 0x00FF00) >> 8
       self.pdu_specific = value & 0x0000FF
       #MIL logger.debug("PGN.@valueSetter, value=0x%08x, pdu_format=0x%08x" % (value, self.pdu_format))
    

@@ -52,9 +52,9 @@ class PGN(object):
def from_value(pgn_value):
logger.debug("PGN.@from_value, pgn_value=0x%08x" % (pgn_value))
pgn = PGN()

  •    pgn.reserved_flag = (pgn_value & 0x080000) >> 17
    
  •    pgn.data_page_flag = (pgn_value & 0x040000) >> 16
    
  •    pgn.pdu_format = (pgn_value & 0x03FF00) >> 8
    
  •    pgn.reserved_flag = (pgn_value & 0x020000) >> 17
    
  •    pgn.data_page_flag = (pgn_value & 0x010000) >> 16
    
  •    pgn.pdu_format = (pgn_value & 0x00FF00) >> 8
       pgn.pdu_specific = pgn_value & 0x0000FF
       return pgn
    

@@ -64,9 +64,9 @@ class PGN(object):
canid = canid>>8
pgn = PGN()

  •    pgn.reserved_flag = (canid & 0x080000) >> 17
    
  •    pgn.data_page_flag = (canid & 0x040000) >> 16
    
  •    pgn.pdu_format = (canid & 0x03FF00) >> 8
    
  •    pgn.reserved_flag = (canid & 0x020000) >> 17
    
  •    pgn.data_page_flag = (canid & 0x010000) >> 16
    
  •    pgn.pdu_format = (canid & 0x00FF00) >> 8
       pgn.pdu_specific = canid & 0x0000FF
       logger.info("{} staticmethod: PGN Creation, res={}, dp={}, pdu_format=0x{:02x}, pdu_specific=0x{:02x}".format(inspect.stack()[0][3],
               pgn.reserved_flag, 
    

Not so much an issue....

Is it possible to use your library to decode DM1s from a BLF file recorded with Vector tools?

Do you have any examples of doing this?

Thoughts/questions on the Node class and j1939_nodes example

I am looking at the j1939_nodes.py example code and seeing the comment:

# This example is an attempt to operate two address endpoints concurrently.
#
# Currently it's not tested and I suspect it's not handling the address claims correctly
# among other things

In the code, we are giving node1 and node2 both the same j1939 name value (of 0), here. This might be getting get in the way of things working correctly? Part of the j1939 name is a unique ID, and so placing two nodes with identical uniqueID is possibly going to play havoc with j1939 name arbitration? To make the example more real-world, maybe make a tweak that gives the two nodes unique names.

One reason why I am here looking at this file is that this particular example code has the only usage I can find (here) for the function node.send_parameter_group. I am interested in this function because it calls a function Bus.write (on this line), which I would like to look at because it looks very useful, but I am having trouble finding it anywhere in the python-1939 codebase, nor in the python-can base class. Does the write function no longer exist, or is this pehaps a typo and a different function is intended?

direct address transport protocol initiated through Node.send_parameter_group() results in a broadcast transfer

When sending a directed long message through Node.send_parameter_group, the resulting transfer is always broadcast. j1939.Bus.send is always seeing a destination address of 0xFF.

I added some logging in Node.send_parameter_group immediately prior to the send:

            logger.debug('send_parameter_group: to address: %s', pdu.arbitration_id.pgn.pdu_specific)
            logger.info("DKP: send_parameter_group: is_destination_specific={}, destAddr={}".format(pdu.arbitration_id.pgn.is_destination_specific, pdu.arbitration_id.destination_address))

When sending a long message that requires the use of the transport protocol, I see the following results:

DEBUG:j1939:send_parameter_group: to address: 176                  <---- correct address
DEBUG:j1939:PGN is_pdu1 00ef: True
DEBUG:j1939:            (self.pdu_format & 0xFF) < 240 00ef: True
DEBUG:j1939:            self.reserved_flag 00ef: 0
DEBUG:j1939:            self.data_page_flag 00ef: 0
DEBUG:j1939:value-result = 00efb0
DEBUG:j1939:PGN is_destination_specific efb0: True
DEBUG:j1939:PGN is_pdu1 00ef: True
DEBUG:j1939:            (self.pdu_format & 0xFF) < 240 00ef: True
DEBUG:j1939:            self.reserved_flag 00ef: 0
DEBUG:j1939:            self.data_page_flag 00ef: 0
DEBUG:j1939:value-result = 00efb0
DEBUG:j1939:PGN is_destination_specific efb0: True
INFO:j1939:DKP: j1939.send: is_destination_specific=True, destAddr=255   <---- global address

I believe the root issue is in ArbitrationID, where destination_address_value is maintained separately from pgn.pdu_specific, allowing them to hold different values that I believe should never be different. Node.send_parameter_group sets pdu.arbitration_id.pgn.pdu_specific to the destination_address, but not pdu.arbitration_id.destination_address.

My gut feel is that ArbitrationID.destination_address_value should just be a property that defers to pgn.pdu_specific. I see the following in ArbitrationID.__init__, which kinda indicates the separation may be intentional, and the commented assert makes me think the intention was that they should always be the same (yet it's been commented out...). I'm not sure if there's more to this than I'm seeing.

                        if  self.destination_address_value != self._pgn.pdu_specific:
                                logger.debug("self._pgn=%s, self.destination_address_value = %x, pgn.pdu_specific = %x" %
                                        (self._pgn, self.destination_address_value, self._pgn.pdu_specific))
#                        assert( self.destination_address_value == pgn.pdu_specific)

My workaround is to assign the destination address to both within Node.send_parameter_group, which gets me by for now, but isn't a fix, IMO:

        pdu.arbitration_id.pgn.pdu_specific = pdu.arbitration_id.destination_address = destination_address

I'm happy to take a stab at a fix, but would need some guidance/clarification on the reason for separate address storage.

compatibility with 11-bit CAN messaging

Hello Miller,

I'm on a project where I need to support simultaneous 11-bit and J1939 messaging. I've hacked this package a bit to make it work (it doesn't really take much) and thought I could make a contribution to provide that support.

The changes include:

  1. building J1939 filters on any specified can_filters,
  2. dispatching incoming non-PDU messages to a method that still ignores them but can be sub-classed for addition to the queue,
  3. dispatching outgoing non-PDU messages directly to self.can_bus.send

Another change I made was to put the construction of RawCanBus into a method so a sub-class can swap in a dummy bus for tests.

Dave

Windows installation error

For working with Vector hardware, I need to use Windows 10 to run this library.

In Windows Powershell, I cd'ed into the cloned directory and installed the library using pip install .. But when I tried to import the library using import j1939, the library gives error on this line. Specifically,

fileHandler = logging.handlers.RotatingFileHandler('/tmp/j1939.log', \

The reason is that the specified log file path works only for unix like systems. My test environment:

OS: Windows 10 Pro
Version: 10.0.18363 Build 18363
Python version: 3.7.7

Leverage the kernel J1939 implementation for socketcan interfaces?

According to the What's New for the socket library, Python 3.9+ supports the kernel J1939 protocol family on supported Linux kernel versions. This is kernel 5.4+ per the eLinux wiki, which is the version shipped with Ubuntu 20.04 LTS.

I'm not sure how feasible this is considering the API this library provides and the desire to support Python 2 (although I suppose this could just be treated as progressive enhancement or an option that can be opted into, falling back to the userspace implementation if unavailable), but it would be nice to support an abstraction of that as well so the work can be deferred to the kernel instead of the implementation being purely userspace in Python.

Not able to find j1939.Bus() definition

I would like can Tx errors and if accumulated may be flush them or reset my can node, otherwise I would like to thank you I have used this package to send can messages its working absolutely fine

Periodic message using send_periodic() gives error message

I observed that although the send() command from the python-can library handles the 'pdu' message from the python-J1939 library fine, the send_periodic() command is gives the following error message:

File "C:\Program Files\Python37\lib\site-packages\can\broadcastmanager.py", line 125, in start
    name = "Cyclic send task for 0x%X" % (self.message.arbitration_id)
    TypeError: %X format: an integer is required, not ArbitrationID

Which is understandable as the arbitration_id argument which is found in the can.Message object is done differently in the python-j1939 way. However, I don't understand why the normal send() function seems to work fine.

Is this intended (maybe there is another way to send periodic messages with python-j1939?) or am I missing something?

Code for error reproduction:

import time
import j1939
if __name__ == "__main__":
    channel = 0
    bustype = 'kvaser'
    sourceaddr = 0xFE
    destaddr = 0xF1

    bus = j1939.Bus(channel=channel, bustype=bustype, timeout=0.01, broadcast=True)

    data = [0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF]
    pgn = j1939.PGN()
    pgn.value = 0xFECA # DM1 
    aid = j1939.ArbitrationID(pgn=pgn, source_address=sourceaddr, destination_address=destaddr)
    pdu = j1939.PDU(timestamp=0.0, arbitration_id=aid, data=data, info_strings=None)
    
    bus.send_periodic(pdu, 0.5, duration=10.0)
    #bus.send(pdu)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.