J1939 CAN to DDS Gateway

The J1939 CAN to DDS Gateway service (gva-j1939-gateway) provides integration between J1939 automotive networks and the GVA DDS data bus. It reads J1939 CAN messages from a SocketCAN interface, decodes them according to the SAE J1939 standard, and publishes the parameters as DDS topics defined in the J1939 Automotive Platform Specific Model (PSM).

Overview

The gateway implements bidirectional communication:

  • CAN to DDS: Reads J1939 CAN frames, decodes PGNs (Parameter Group Numbers) and SPNs (Suspect Parameter Numbers), and publishes them as C_Parameter messages on DDS
  • DDS to CAN: Subscribes to J1939 command topics and transmits corresponding CAN frames (future enhancement)

Key Features

  • ✅ SocketCAN interface support (hardware and virtual CAN)
  • ✅ J1939 protocol decoding (29-bit CAN ID, PGN/SPN extraction)
  • ✅ Configurable PGN/SPN mappings via JSON
  • ✅ DDS publishing of J1939 parameters with status and metadata
  • ✅ Systemd service integration
  • ✅ Real-time monitoring via LDMX J1939 tab

Architecture

graph LR A[CAN Bus] -->|SocketCAN| B[SocketCanReader] B -->|CanFrame| C[J1939Decoder] C -->|J1939Message| D[J1939Gateway] D -->|C_Parameter| E[DDS Topic] E --> F[LDMX Monitor] E --> G[Other GVA Apps]

Components

  1. SocketCanReader: Qt thread that reads CAN frames from a SocketCAN interface
  2. J1939Decoder: Decodes J1939 protocol from CAN frames (PGN, SPN, source address, priority)
  3. J1939Gateway: Main service that coordinates CAN reading and DDS publishing
  4. J1939Config: Configuration manager for PGN/SPN definitions and scaling

Installation

Prerequisites

# Install can-utils for testing
sudo apt-get install can-utils

# Ensure kernel vcan module is available
sudo modprobe vcan

Build

The gateway is built as part of the LDM SDK:

cd build
cmake ..
make gva-j1939-gateway

The executable is installed to /usr/bin/gva-j1939-gateway.

Systemd Service

Install the systemd service:

sudo systemctl daemon-reload
sudo systemctl enable gva-j1939-gateway
sudo systemctl start gva-j1939-gateway

Check service status:

sudo systemctl status gva-j1939-gateway
sudo journalctl -u gva-j1939-gateway -f

Configuration

Command-Line Options

gva-j1939-gateway [OPTIONS]

Options:
  -d, --domain <id>       DDS domain ID (default: 0)
  -i, --interface <name>  CAN interface name (default: vcan0)
  -c, --config <path>     Configuration file path (default: /etc/gva/j1939-config.json)
  -h, --help             Display help
  -v, --version          Display version

Configuration File

The gateway uses a JSON configuration file to define PGN and SPN mappings. Default location: /etc/gva/j1939-config.json

Example Configuration:

{
  "gatewayResourceId": 6457,
  "j1939Address": 249,
  "pgns": [
    {
      "pgn": 61444,
      "name": "Electronic Engine Controller 1",
      "updateRateHz": 10.0,
      "spns": [
        {
          "spn": 190,
          "name": "Engine Speed",
          "startBit": 24,
          "lengthBits": 16,
          "scale": 0.125,
          "offset": 0,
          "unit": "rpm"
        }
      ]
    },
    {
      "pgn": 65265,
      "name": "Cruise Control/Vehicle Speed",
      "updateRateHz": 10.0,
      "spns": [
        {
          "spn": 84,
          "name": "Wheel-Based Vehicle Speed",
          "startBit": 8,
          "lengthBits": 16,
          "scale": 0.00390625,
          "offset": 0,
          "unit": "km/h"
        }
      ]
    }
  ],
  "applicationAreas": [
    {
      "resourceId": 6464,
      "descriptor": "Engine",
      "pgns": [61444]
    },
    {
      "resourceId": 6465,
      "descriptor": "Vehicle",
      "pgns": [65265]
    }
  ]
}

Configuration Fields

Field Type Description
gatewayResourceId integer DDS resource ID for the gateway
j1939Address integer J1939 source address (0-253, 249=NULL)
pgns array List of Parameter Group Number definitions
pgns[].pgn integer PGN number
pgns[].name string Human-readable PGN name
pgns[].updateRateHz number Expected update rate in Hz
pgns[].spns array List of SPNs in this PGN
pgns[].spns[].spn integer SPN number
pgns[].spns[].name string Parameter name
pgns[].spns[].startBit integer Start bit position (0-63)
pgns[].spns[].lengthBits integer Length in bits (1-64)
pgns[].spns[].scale number Scaling factor (value = raw * scale + offset)
pgns[].spns[].offset number Offset value
pgns[].spns[].unit string Unit of measurement
applicationAreas array Logical groupings of PGNs

Testing with Virtual CAN

Setup vcan0 Interface

cd scripts/test/j1939
sudo ./setup-vcan.sh

This creates a vcan0 virtual CAN interface for testing without hardware.

Send Test Frames

./send-j1939-frames.sh

This script sends sample J1939 messages including: - Engine speed (PGN 61444) - Vehicle speed (PGN 65265) - Engine temperature (PGN 65262)

Monitor with LDMX

  1. Start the gateway:

    gva-j1939-gateway --interface=vcan0 --domain=0
    

  2. Start LDMX:

    ldmx
    

  3. Navigate to the J1939 tab

  4. Run the test script in another terminal:

    ./send-j1939-frames.sh
    

  5. Observe J1939 parameters appearing in the LDMX table with timestamps, PGN, SPN, values, and status

Manual Testing

Send individual CAN frames:

# Engine speed = 1500 RPM
cansend vcan0 18F00400#FFFFFFFFFFE02E00

# Vehicle speed = 60 km/h
cansend vcan0 18FEF100#FF003C0000FFFFFF

Monitor CAN traffic:

candump vcan0

J1939 Protocol Details

CAN ID Format (29-bit)

Bits Field Description
28-26 Priority Message priority (0=highest, 7=lowest)
25 Reserved Reserved bit
24 Data Page (DP) Extended page select (0 or 1)
23-16 PDU Format (PF) Protocol Data Unit Format
15-8 PDU Specific (PS) Group extension or destination address
7-0 Source Address (SA) Source controller address (0-253)

PGN Calculation

if PF < 240:
    PGN = DP << 16 | PF << 8 | 0x00  (PDU1 - destination specific)
else:
    PGN = DP << 16 | PF << 8 | PS     (PDU2 - broadcast)

Common PGNs

PGN Name Update Rate
61444 Electronic Engine Controller 1 10 Hz
65265 Cruise Control/Vehicle Speed 10 Hz
65262 Engine Temperature 1 1 Hz
65263 Engine Fluid Level/Pressure 1 1 Hz

DDS Topics

The gateway publishes to the following DDS topics defined in J1939_Automotive_PSM.idl:

C_Parameter

Individual parameter values (SPNs).

Topic Name: J1939_Automotive__Parameter

Key Fields: - A_sourceID.A_resourceID: Gateway resource ID - A_sourceID.A_instanceID: SPN number

Data Fields: - A_suspectParameterNumber: SPN - A_value: Parameter value (GenericValueType) - A_valueStatus: Available/Error/Not_Available - A_metadata: Timestamp and validity period

C_Parameter_Group_Definition

PGN definitions.

Topic Name: J1939_Automotive__Parameter_Group_Definition

Fields: - A_parameterGroupNumber: PGN - A_transmitSupported: Whether transmit is supported - A_frequency: Update rate in Hz

C_Data_Source

Gateway status.

Topic Name: J1939_Automotive__Data_Source

Fields: - A_onStatus: Operational/Standby/Off/Failed - A_specification_sourceID: Link to specification

Troubleshooting

CAN Interface Not Found

Error: Failed to get interface index for vcan0

Solution:

# Check if interface exists
ip link show vcan0

# If not, create it
sudo ./scripts/test/j1939/setup-vcan.sh

Permission Denied

Error: Failed to create CAN socket: Operation not permitted

Solution: Run with sudo or add user to relevant groups:

sudo usermod -a -G dialout $USER
# Log out and back in

No Messages in LDMX

  1. Check gateway is running:

    sudo systemctl status gva-j1939-gateway
    

  2. Check DDS domain matches:

    # Gateway and LDMX must use same domain
    gva-j1939-gateway --domain=0
    ldmx  # Uses domain 0 by default
    

  3. Verify CAN traffic:

    candump vcan0
    

  4. Check gateway logs:

    sudo journalctl -u gva-j1939-gateway -f
    

LDMX J1939 Tab

The LDMX monitoring tool includes a dedicated J1939 tab for real-time visualization of J1939 parameters.

Features

  • Table View: Displays all received J1939 parameters with columns:
  • Timestamp
  • PGN (Parameter Group Number)
  • PGN Name
  • SPN (Suspect Parameter Number)
  • SPN Name
  • Value
  • Unit
  • Status (Available/Error/Not Available)

  • Controls:

  • Clear: Clear all messages from the table
  • Pause/Resume: Pause or resume message updates
  • Filter: Filter messages by PGN or SPN number

  • Status Bar: Shows total message count

Usage

  1. Start LDMX: ldmx
  2. Click on the J1939 tab
  3. Start the gateway (if not already running)
  4. Messages will appear in real-time as they are received

References

Future Enhancements

  • [ ] DDS to CAN transmission (command support)
  • [ ] Multi-frame transport protocol support (TP)
  • [ ] DM1 diagnostic message support
  • [ ] Address claiming support
  • [ ] Configuration GUI
  • [ ] CAN frame timestamping from hardware
  • [ ] Statistics and diagnostics dashboard