python-can-j1939

repository·master·Indexed 11 days ago

https://github.com/juergenh87/python-can-j1939

A Python implementation of the SAE J1939 standard, including support for J1939-FD (J1939-22). It enables developers to simulate or interface with Electronic Control Units (ECUs) and Controller Applications (CAs) on a CAN network, featuring support for address claiming, Transport Protocol (TP) for large data transfers, and integration with the python-can library.

Tokens
1.2K
Snippets
4
Records
8
Agent score
0%

What's inside python-can-j1939

  1. How ElectronicControlUnit (ECU) and ControllerApplication (CA) work together

    master

    In this library, an ElectronicControlUnit (ECU) acts as a container that can hold one or more ControllerApplications (CA).

    • An ECU manages the connection to the CAN bus and can subscribe to all passing messages globally.
    • A CA represents a specific logical entity on the bus with its own unique address. It handles its own address claiming, message sending (via send_pgn), and specific timers.

    To use them, you typically create an ElectronicControlUnit, create one or more ControllerApplication objects, and then add the CAs to the ECU using ecu.add_ca(controller_application=ca).

    import j1939
    
    # Create the ECU
    ecu = j1939.ElectronicControlUnit()
    
    # Create a CA with a specific name and address
    name = j1939.Name(manufacturer_code=666, identity_number=1234567, ...)
    ca = j1939.ControllerApplication(name, 128)
    
    # Link them
    ecu.add_ca(controller_application=ca)
    
    # Connect and start
    ecu.connect(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000)
    ca.start()
  2. Use timers in ControllerApplication

    master

    You can register periodic callbacks within a ControllerApplication using add_timer(interval, callback). These callbacks are executed by the ECU's timer event mechanism.

    Timer Callback Signature: def callback(cookie):

    • cookie: A value registered at add_timer (can be None).
    • Return Value: Returning True keeps the timer active; returning False (or implicitly returning nothing if not handled) stops the timer.

    Example:

    def my_timer(cookie):
        # Perform periodic task
        ca.send_pgn(0, 0x123, 0x00, 8, [0]*8)
        return True # Keep timer running
    
    ca.add_timer(0.500, my_timer) # Run every 500ms
  3. Connect to the CAN bus

    master

    The ecu.connect() method is used to establish a connection to the hardware. It accepts arguments that are passed directly to the python-can library's can.interface.Bus() constructor.

    Common usage patterns include:

    • Socketcan: ecu.connect(bustype='socketcan', channel='can0')
    • Kvaser: ecu.connect(bustype='kvaser', channel=0, bitrate=250000)
    • PCAN: ecu.connect(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000)
    • IXXAT: ecu.connect(bustype='ixxat', channel=0, bitrate=250000)
    • Vector: ecu.connect(bustype='vector', app_name='CANalyzer', channel=0, bitrate=250000)
  4. Subscribe to messages on the ECU or CA

    master

    You can receive incoming J1939 messages by subscribing a callback function to either the ElectronicControlUnit (for all global messages) or a specific ControllerApplication (for messages relevant to that CA).

    Callback Signature: The callback function must accept the following arguments:

    • priority (int): Message priority
    • pgn (int): Parameter Group Number
    • sa (int/source): Source Address (or source in CA context)
    • timestamp (int): Timestamp
    • data (bytearray): The PDU data

    Example (Global Subscription):

    def on_message(priority, pgn, sa, timestamp, data):
        print(f"PGN {pgn} received")
    
    ecu.subscribe(on_message)
  5. Send PGNs using ControllerApplication

    master

    A ControllerApplication can send messages using the send_pgn method. This supports both broadcast and peer-to-peer communication.

    Method Signature: ca.send_pgn(priority, pgn, destination_address, size, data)

    • Broadcast Message: Set the destination address to a broadcast value (e.g., 0xFD).
    • Peer-to-Peer Message: Set the destination address to the specific target address (e.g., 0x04).
    • Multi-packet (TP): The library supports Transport Protocol (TP) for large data transfers (up to 1785 bytes for standard and much larger for J1939-FD/Multi-PG).

    Example:

    # Sending a 6-byte broadcast message
    data = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06]
    ca.send_pgn(0, 0xFD, 0xED, 6, data)