Working with J1939 Data

Python 3 tools and code snippets to transorm, parse, decode, and simulate heavy vehicle network data on J1939 Networks. The CAN Data page has recordings of heavy vehicle data.

Overview

The idea of J1939 is to build a reliable communication on top of a Contrller Area Network (CAN) using 29-bit arbitration identifiers. Working with the J1939 network requires performing some of the following tasks:

  • Reading the CAN bus
  • Decoding the CAN identifier into priority, parameter group number (PGN), destination address (DA), and source address (SA).
  • Decoding the data bytes according to the suspect parameter numbers (SPNs) that are allocated for each PGN.
  • Assembling and disassembling messages that are 9 bytes or larger into multiple CAN frames.
  • Claiming an address to participate on the network.

For the practical work described in this page, we need to have some hardware. Since the examples are in Python 3, Linux SocketCAN, and can-utils, we will use hardware that runs an embedded Linux operating system. The BeagleBone Black with a TruckCape is our prefered device. A Raspberry Pi with a CAN hat would also work.

Reading J1939 Traffic

Once you have a some hardware in hand and have access to a truck or J1939 network, you'll need to follow these steps:

  1. Login to a terminal on the Linux device. For example, follow the instructions for the truck cape.
  2. Confirm the can interfaces are present:

    ifconfig

  3. Confirm the bitrate for CAN

    ip -details link show can1

    where can1 is the physical channel connected to J1939. Check all valid CAN channels.

  4. If the bitrate needs to be changed, use the following 3 commands:

    sudo ip link set can1 down

    sudo ip link set can1 type can bitrate 250000

    sudo ip link set can1 up

    Note: you can omit the middle command to simply reset the interface.

  5. Use the candump command to capture network traffic without processing it.

    candump -s0 -l any

    where the -l switch creates a log file and -s0 turns off silent mode so you can see what's going on. when using 'any' for the interface means the command will log traffic from all channels. Just typing candump with no arguments gives the help documentation. Note: the format displayed on the screen is different than the candump file format.

What if we wanted to not only read, but also process the data in real time? This would be important to respond to requests or commands that are coming from the CAN bus. To do this, we'll need to write a program to process and read the data.


Let's assume we name the above script as 'candump_example.py'. Then it can be run at the command prompt as

python3 candump_example.py.

The output to both the screen and the file will match the candump format from can-utils. Since it is in a while True loop, press ctrl-C to stop.

This simple script only works for one interface. If we want more interfaces, then it makes sense to convert this to a class an instantiate a python object for each interface that's available. This class can be threaded, and part of a bigger program to work with the CAN data.


Decoding the CAN ID for J1939

A very useful tool to decode the CAN message is the pretty_j1939 project.

We take advantage of this database in json form when we work through the examples in the TruckCape Repository. In fact, this repository has all the solutions needed to work with the heavy vehicle CAN systems.