### ECU Setup and Periodic Transmission Source: https://context7.com/juergenh87/python-can-j1939/llms.txt This example demonstrates the basic setup of an Electronic Control Unit (ECU) and a Controller Application (CA) using the python-can J1939 library. It includes setting up timers for periodic message transmission and handling callbacks. ```APIDOC ## ECU Setup and Periodic Transmission ### Description This section shows how to initialize an ECU, connect to a CAN bus, define a Controller Application with a specific name, and add it to the ECU. It also demonstrates setting up periodic and one-shot timers for transmitting messages and executing callback functions. ### Method N/A (Setup and Timer Management) ### Endpoint N/A ### Parameters N/A ### Request Example ```python import j1939 import time ecu = j1939.ElectronicControlUnit() ecu.connect(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000) name = j1939.Name( arbitrary_address_capable=0, industry_group=j1939.Name.IndustryGroup.Industrial, vehicle_system_instance=1, vehicle_system=1, function=1, function_instance=1, ecu_instance=1, manufacturer_code=666, identity_number=1234567 ) ca = j1939.ControllerApplication(name, 128) ecu.add_ca(controller_application=ca) ca.start() def send_periodic_status(cookie): """Timer callback for periodic transmission""" if ca.state != j1939.ControllerApplication.State.NORMAL: return True # Keep trying data = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08] ca.send_pgn(0, 0xFD, 0xED, 6, data) print(f"Sent status message, counter: {cookie['count']}") cookie['count'] += 1 return True # Keep timer active def one_shot_callback(cookie): """One-shot timer example""" print("One-shot timer fired!") return False # Remove timer after execution ca.add_timer(0.500, send_periodic_status, cookie={'count': 0}) ecu.add_timer(1.0, lambda c: print("ECU timer") or True) time.sleep(10) ca.remove_timer(send_periodic_status) ca.stop() ecu.disconnect() ``` ### Response N/A ``` -------------------------------- ### Initialize ECU and Controller Application Source: https://github.com/juergenh87/python-can-j1939/blob/master/docs/readme.md Demonstrates the setup of an ElectronicControlUnit, connecting to a CAN bus interface, and registering a ControllerApplication to handle J1939 communication. ```python import j1939 import time ca = j1939.ControllerApplication(name, 128) ecu = j1939.ElectronicControlUnit() ecu.connect(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000) ecu.add_ca(controller_application=ca) ca.start() ``` -------------------------------- ### Create and Configure a J1939 Controller Application Source: https://github.com/juergenh87/python-can-j1939/blob/master/README.rst This example shows how to initialize a J1939 ControllerApplication with a custom Name descriptor, subscribe to incoming messages, and register periodic timer callbacks for sending broadcast and peer-to-peer messages. ```python import logging import time import can import j1939 logging.getLogger('j1939').setLevel(logging.DEBUG) logging.getLogger('can').setLevel(logging.DEBUG) name = j1939.Name( arbitrary_address_capable=0, industry_group=j1939.Name.IndustryGroup.Industrial, vehicle_system_instance=1, vehicle_system=1, function=1, function_instance=1, ecu_instance=1, manufacturer_code=666, identity_number=1234567 ) ca = j1939.ControllerApplication(name, 128) def ca_receive(priority, pgn, source, timestamp, data): print("PGN {} length {}".format(pgn, len(data))) def ca_timer_callback1(cookie): if ca.state != j1939.ControllerApplication.State.NORMAL: return True data = [j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_8] * 8 ca.send_pgn(0, 0xFD, 0xED, 6, data) ca.send_pgn(0, 0xE0, 0x04, 6, data) return True def main(): ecu = j1939.ElectronicControlUnit() ecu.connect(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000) ecu.add_ca(controller_application=ca) ca.subscribe(ca_receive) ca.add_timer(0.500, ca_timer_callback1) ca.start() time.sleep(120) ca.stop() ecu.disconnect() if __name__ == '__main__': main() ``` -------------------------------- ### ControllerApplication Initialization and Management Source: https://github.com/juergenh87/python-can-j1939/blob/master/docs/source/j1939.md Demonstrates the initialization of a J1939 ControllerApplication (CA) with a name and optional preferred device address. It also covers starting and stopping the CA, managing its state, and handling address claims. ```python from j1939.controller_application import ControllerApplication # Initialize a ControllerApplication ca = ControllerApplication(name="MyController", device_address_preferred=128) # Start the CA and begin the address claim procedure ca.start(claim_delay=0.5) # ... perform operations ... # Stop the CA ca.stop() ``` -------------------------------- ### Install can-j1939 via pip Source: https://github.com/juergenh87/python-can-j1939/blob/master/README.rst Standard installation command for the can-j1939 library using the Python package manager. ```bash pip install can-j1939 ``` -------------------------------- ### Setup ECU and Controller Application Source: https://context7.com/juergenh87/python-can-j1939/llms.txt Initializes a J1939 ECU and a Controller Application (CA) with specific identity parameters. This is the foundational step for all J1939 communication. ```python import j1939 ecu = j1939.ElectronicControlUnit() ecu.connect(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000) name = j1939.Name(arbitrary_address_capable=0, industry_group=j1939.Name.IndustryGroup.Industrial, vehicle_system_instance=1, vehicle_system=1, function=1, function_instance=1, ecu_instance=1, manufacturer_code=666, identity_number=1234567) ca = j1939.ControllerApplication(name, 128) ecu.add_ca(controller_application=ca) ca.start() ``` -------------------------------- ### Subscribe to J1939 Messages Source: https://context7.com/juergenh87/python-can-j1939/llms.txt Shows how to register callback functions to receive J1939 messages at both the ECU (global) and CA (specific address) levels. Includes setup of the ECU connection and subscription lifecycle management. ```python def on_message(priority, pgn, sa, timestamp, data): print(f"PGN: {pgn}, From: {sa}, Priority: {priority}, Length: {len(data)}") ecu = j1939.ElectronicControlUnit() ecu.connect(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000) ecu.subscribe(on_message) ca = j1939.ControllerApplication(name, 0x80) ecu.add_ca(controller_application=ca) ca.start() ca.subscribe(on_message) time.sleep(120) ecu.unsubscribe(on_message) ca.unsubscribe(on_message) ecu.disconnect() ``` -------------------------------- ### DM11 - Clear Active DTCs Source: https://context7.com/juergenh87/python-can-j1939/llms.txt This example demonstrates how to use the Dm11 class to request the clearing of active diagnostic trouble codes from other ECUs on the network. ```APIDOC ## DM11 - Clear Active DTCs ### Description This section explains how to use the `j1939.Dm11` class to send requests to clear active diagnostic trouble codes (DTCs) from ECUs on the J1939 network. It covers requesting a clear from a specific destination address or a global clear request to all devices. ### Method N/A (DM11 Message Handling) ### Endpoint N/A ### Parameters N/A ### Request Example ```python import j1939 import time ecu = j1939.ElectronicControlUnit() ecu.connect(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000) name = j1939.Name( arbitrary_address_capable=0, industry_group=j1939.Name.IndustryGroup.Industrial, vehicle_system_instance=1, vehicle_system=1, function=1, function_instance=1, ecu_instance=1, manufacturer_code=666, identity_number=1234567 ) ca = j1939.ControllerApplication(name, 0xF1) ecu.add_ca(controller_application=ca) ca.start() # Create DM11 handler dm11 = j1939.Dm11(ca) # === As a Tool: Request DTC Clear from another device === # Request device at address 0x00 to clear all active DTCs dm11.request_clear_all(destination=0x00) # Request global clear (all devices) dm11.request_clear_all(destination=0xFF) ``` ### Response N/A ``` -------------------------------- ### DM1 - Active Diagnostic Trouble Codes Source: https://context7.com/juergenh87/python-can-j1939/llms.txt This example shows how to use the Dm1 class to subscribe to and send SAE J1939 DM1 messages, which are used for reporting active diagnostic trouble codes and their associated lamp statuses. ```APIDOC ## DM1 - Active Diagnostic Trouble Codes ### Description This section details the usage of the `j1939.Dm1` class for handling J1939 Diagnostic Message 1 (DM1). It covers both receiving DM1 messages by subscribing to them and sending DM1 messages periodically with custom diagnostic trouble codes and lamp statuses. ### Method N/A (DM1 Message Handling) ### Endpoint N/A ### Parameters N/A ### Request Example ```python import j1939 import time # Setup ECU and CA ecu = j1939.ElectronicControlUnit() ecu.connect(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000) name = j1939.Name( arbitrary_address_capable=0, industry_group=j1939.Name.IndustryGroup.Industrial, vehicle_system_instance=1, vehicle_system=1, function=1, function_instance=1, ecu_instance=1, manufacturer_code=666, identity_number=1234567 ) ca = j1939.ControllerApplication(name, 0xF1) ecu.add_ca(controller_application=ca) ca.start() # === Receiving DM1 Messages === def dm1_receive(sa, lamp_status, dtc_dic_list, timestamp): """Callback for received DM1 messages""" print(f"DM1 from {sa}:") print(f" Protect Lamp: {lamp_status.get('pl')}") print(f" Amber Warning: {lamp_status.get('awl')}") print(f" Red Stop: {lamp_status.get('rsl')}") print(f" MIL: {lamp_status.get('mil')}") for dtc in dtc_dic_list: print(f" DTC - SPN: {dtc['spn']}, FMI: {dtc['fmi']}, Count: {dtc['oc']}") dm1_receiver = j1939.Dm1(ca) dm1_receiver.subscribe(dm1_receive) # === Sending DM1 Messages === def dm1_data_callback(): """Called before each DM1 transmission to collect current DTCs""" lamp_status = { 'pl': j1939.DtcLamp.ON_FAST_FLASH, # Protect lamp 'awl': j1939.DtcLamp.ON_SLOW_FLASH, # Amber warning 'rsl': j1939.DtcLamp.OFF, # Red stop lamp 'mil': j1939.DtcLamp.OFF # Malfunction indicator } dtc_list = [ {'spn': 123, 'fmi': 31}, {'spn': 456, 'fmi': 1, 'oc': 132}, {'spn': 91, 'fmi': 4, 'oc': 5} ] return lamp_status, dtc_list dm1_sender = j1939.Dm1(ca) dm1_sender.start_send(callback=dm1_data_callback, cycletime=1) time.sleep(60) dm1_sender.stop_send() ecu.disconnect() ``` ### Response N/A ``` -------------------------------- ### ControllerApplication Message Handling Source: https://github.com/juergenh87/python-can-j1939/blob/master/docs/source/j1939.md Illustrates how to subscribe to and unsubscribe from different message streams (general messages, acknowledgments, requests) for a ControllerApplication. It also shows how to send various types of J1939 messages. ```python def message_handler(message): print(f"Received message: {message}") def request_handler(src_address, dest_address, pgn): print(f"Received request for PGN {pgn} from {src_address}") # Subscribe to general messages ca.subscribe(message_handler) # Subscribe to request messages ca.subscribe_request(request_handler) # Send a PGN message ca.send_pgn(data_page=0, pdu_format=254, pdu_specific=200, priority=7, data=[0x01, 0x02, 0x03]) # Send a request for a PGN ca.send_request(data_page=0, pgn=65262, destination=255) # Unsubscribe from general messages ca.unsubscribe(message_handler) # Unsubscribe from request messages ca.unsubscribe_request(request_handler) ``` -------------------------------- ### ControllerApplication - Manage Device on Bus Source: https://context7.com/juergenh87/python-can-j1939/llms.txt Details on how to create and manage a `ControllerApplication` instance, including setting preferred addresses, bypassing address claiming, and adding it to an `ElectronicControlUnit`. ```APIDOC ## ControllerApplication - Manage Device on Bus ### Description The `ControllerApplication` class represents a single device function on the J1939 bus. It handles address claiming, message subscription, and PGN transmission. ### Method Instantiation and management methods for `ControllerApplication`. ### Endpoint N/A (Class instantiation and ECU integration) ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A ### Request Example ```python import j1939 import time # Create ECU and connect ecu = j1939.ElectronicControlUnit() ecu.connect(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000) # Define NAME for the controller application name = j1939.Name( arbitrary_address_capable=0, industry_group=j1939.Name.IndustryGroup.Industrial, vehicle_system_instance=1, vehicle_system=1, function=1, function_instance=1, ecu_instance=1, manufacturer_code=666, identity_number=1234567 ) # Create Controller Application with preferred address 0x80 (128) ca = j1939.ControllerApplication(name, device_address_preferred=128) # Or bypass address claiming for fixed-address devices ca_fixed = j1939.ControllerApplication(name, device_address_preferred=0x10, bypass_address_claim=True) # Add CA to ECU ecu.add_ca(controller_application=ca) # Start address claiming procedure ca.start() ``` ### Response N/A (This is a class usage example) #### Success Response (200) N/A #### Response Example N/A ``` -------------------------------- ### Manage Controller Application Address Claiming Source: https://context7.com/juergenh87/python-can-j1939/llms.txt Demonstrates how to initialize a Controller Application (CA) and wait for the address claim process to reach the NORMAL state before proceeding with communication. ```python while ca.state != j1939.ControllerApplication.State.NORMAL: time.sleep(0.1) print(f"Device address: {ca.device_address}") ca.stop() ecu.disconnect() ``` -------------------------------- ### Manage Device on Bus with python-can-j1939 ControllerApplication Source: https://context7.com/juergenh87/python-can-j1939/llms.txt Shows how to create and manage a Controller Application (CA) on the J1939 bus. This includes defining its NAME, setting a preferred address, and optionally bypassing address claiming for fixed-address devices. It also demonstrates adding the CA to an ECU and initiating the address claiming procedure. ```python import j1939 import time # Create ECU and connect ecu = j1939.ElectronicControlUnit() ecu.connect(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000) # Define NAME for the controller application name = j1939.Name( arbitrary_address_capable=0, industry_group=j1939.Name.IndustryGroup.Industrial, vehicle_system_instance=1, vehicle_system=1, function=1, function_instance=1, ecu_instance=1, manufacturer_code=666, identity_number=1234567 ) # Create Controller Application with preferred address 0x80 (128) ca = j1939.ControllerApplication(name, device_address_preferred=128) # Or bypass address claiming for fixed-address devices ca_fixed = j1939.ControllerApplication(name, device_address_preferred=0x10, bypass_address_claim=True) # Add CA to ECU ecu.add_ca(controller_application=ca) # Start address claiming procedure ca.start() ``` -------------------------------- ### Manage Periodic and One-Shot Timers Source: https://context7.com/juergenh87/python-can-j1939/llms.txt Demonstrates how to schedule periodic tasks and one-shot events within a Controller Application or ECU. Timers use callback functions and optional cookie data for state management. ```python def send_periodic_status(cookie): if ca.state != j1939.ControllerApplication.State.NORMAL: return True ca.send_pgn(0, 0xFD, 0xED, 6, [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]) cookie['count'] += 1 return True ca.add_timer(0.500, send_periodic_status, cookie={'count': 0}) ca.add_timer(2.0, lambda c: False) # One-shot example ``` -------------------------------- ### Create and Connect ECU with python-can-j1939 Source: https://context7.com/juergenh87/python-can-j1939/llms.txt Demonstrates how to create an ElectronicControlUnit (ECU) instance, supporting both standard J1939-21 and J1939-22 (CAN FD). It shows how to connect to various CAN interfaces like SocketCAN, PCAN, and Kvaser, including specific CAN FD timing parameters. ```python import j1939 import logging # Enable debug logging logging.getLogger('j1939').setLevel(logging.DEBUG) # Create ECU with J1939-21 data link layer (default) ecu = j1939.ElectronicControlUnit() # Or create ECU with J1939-22 (CAN FD) support ecu_fd = j1939.ElectronicControlUnit( data_link_layer='j1939-22', max_cmdt_packets=200 # Max segments for transport protocol ) # Connect to CAN bus - multiple interface options available # SocketCAN (Linux) ecu.connect(bustype='socketcan', channel='can0') # PCAN USB adapter ecu.connect(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000) # Kvaser ecu.connect(bustype='kvaser', channel=0, bitrate=250000) # Vector CANalyzer ecu.connect(bustype='vector', app_name='CANalyzer', channel=0, bitrate=250000) # CAN FD connection with timing parameters ecu_fd.connect( bustype='pcan', channel='PCAN_USBBUS1', fd=True, f_clock_mhz=80, nom_brp=10, nom_tseg1=12, nom_tseg2=3, nom_sjw=1, data_brp=4, data_tseg1=7, data_tseg2=2, data_sjw=1 ) # Disconnect when done ecu.disconnect() ``` -------------------------------- ### ECU Initialization and Message Subscription Source: https://github.com/juergenh87/python-can-j1939/blob/master/docs/readme.md This endpoint-like structure demonstrates how to initialize an ECU, connect to a physical CAN interface, and register a callback function to process incoming J1939 messages. ```APIDOC ## ECU Connection and Subscription ### Description Initializes the J1939 ElectronicControlUnit and establishes a connection to the CAN bus hardware. It allows the user to subscribe to all incoming messages on the bus using a callback function. ### Method N/A (Library Method) ### Parameters #### ecu.connect - **bustype** (string) - Required - The interface type (e.g., 'socketcan', 'pcan', 'kvaser') - **channel** (string/int) - Required - The specific hardware channel - **bitrate** (int) - Required - The bus communication speed #### ecu.subscribe - **callback** (function) - Required - Function signature: (priority, pgn, sa, timestamp, data) ### Request Example ```python ecu = j1939.ElectronicControlUnit() ecu.connect(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000) ecu.subscribe(on_message) ``` ### Response #### Success Response - **on_message** (callback) - Invoked when a new PDU is received on the bus containing priority, pgn, sa, timestamp, and data. ``` -------------------------------- ### Receive CAN Messages with J1939 Source: https://github.com/juergenh87/python-can-j1939/blob/master/README.rst This snippet demonstrates how to initialize an ElectronicControlUnit, connect to a CAN bus using a specific interface, and subscribe to incoming messages using a callback function. ```python import logging import time import can import j1939 logging.getLogger('j1939').setLevel(logging.DEBUG) logging.getLogger('can').setLevel(logging.DEBUG) def on_message(priority, pgn, sa, timestamp, data): print("PGN {} length {}".format(pgn, len(data))) def main(): print("Initializing") ecu = j1939.ElectronicControlUnit() ecu.connect(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000) ecu.subscribe(on_message) time.sleep(120) print("Deinitializing") ecu.disconnect() if __name__ == '__main__': main() ``` -------------------------------- ### Work with Parameter Group Numbers (PGN) Source: https://context7.com/juergenh87/python-can-j1939/llms.txt This code snippet explains how to use the ParameterGroupNumber class to work with J1939 PGNs. It shows how to create a PGN object from its components (data page, PDU format, PDU specific) and access its value and format properties. It also lists common PGN constants and special address constants like NULL and GLOBAL. ```python import j1939 # Create PGN from components pgn = j1939.ParameterGroupNumber( data_page=0, # Data page (0 or 1) pdu_format=0xFE, # PDU Format (0-255) pdu_specific=0xCA # PDU Specific / Destination Address ) print(f"PGN Value: {pgn.value}") # Combined 18-bit PGN print(f"Is PDU1 (peer-to-peer): {pgn.is_pdu1_format}") # PF 0-239 print(f"Is PDU2 (broadcast): {pgn.is_pdu2_format}") # PF 240-255 # Common PGNs available as constants print(f"DM1 PGN: {j1939.ParameterGroupNumber.PGN.DM01}") # 65226 print(f"DM11 PGN: {j1939.ParameterGroupNumber.PGN.DM11}") # 65235 print(f"DM22 PGN: {j1939.ParameterGroupNumber.PGN.DM22}") # 49920 print(f"Request PGN: {j1939.ParameterGroupNumber.PGN.REQUEST}") # 59904 print(f"Address Claim PGN: {j1939.ParameterGroupNumber.PGN.ADDRESSCLAIM}") # 60928 # Special addresses print(f"NULL Address: {j1939.ParameterGroupNumber.Address.NULL}") # 254 print(f"GLOBAL Address: {j1939.ParameterGroupNumber.Address.GLOBAL}") # 255 ``` -------------------------------- ### ElectronicControlUnit ControllerApplication Management Source: https://github.com/juergenh87/python-can-j1939/blob/master/docs/source/j1939.md Explains how to add ControllerApplications (CAs) to an ElectronicControlUnit (ECU). This involves providing the CA object, its name, and optionally a preferred device address. ```python from j1939.electronic_control_unit import ElectronicControlUnit from j1939.name import Name from j1939.controller_application import ControllerApplication ecu = ElectronicControlUnit() # Create a Name object for the CA ca_name = Name(manufacturer_code=2, identity_number=12345, vehicle_system=1, vehicle_system_instance=1, ecu_instance=1, function_code=1, function_instance=1, industry_group=1) # Create a ControllerApplication instance ca = ControllerApplication(name=ca_name) # Add the CA to the ECU ecu.add_ca(controller_application=ca, name=ca_name, device_address=128) ``` -------------------------------- ### ElectronicControlUnit - Create and Connect ECU Source: https://context7.com/juergenh87/python-can-j1939/llms.txt Demonstrates how to create an ElectronicControlUnit instance and connect it to various CAN bus interfaces, including support for J1939-21 and J1939-22 (CAN FD). ```APIDOC ## ElectronicControlUnit - Create and Connect ECU ### Description The `ElectronicControlUnit` class represents a J1939 ECU that can hold multiple Controller Applications. It manages the CAN bus connection, message routing, and background processing threads. ### Method Instantiation and connection methods for `ElectronicControlUnit`. ### Endpoint N/A (Class instantiation and connection) ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A ### Request Example ```python import j1939 import logging # Enable debug logging logging.getLogger('j1939').setLevel(logging.DEBUG) # Create ECU with J1939-21 data link layer (default) ecu = j1939.ElectronicControlUnit() # Or create ECU with J1939-22 (CAN FD) support ecu_fd = j1939.ElectronicControlUnit( data_link_layer='j1939-22', max_cmdt_packets=200 # Max segments for transport protocol ) # Connect to CAN bus - multiple interface options available # SocketCAN (Linux) ecu.connect(bustype='socketcan', channel='can0') # PCAN USB adapter ecu.connect(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000) # Kvaser ecu.connect(bustype='kvaser', channel=0, bitrate=250000) # Vector CANalyzer ecu.connect(bustype='vector', app_name='CANalyzer', channel=0, bitrate=250000) # CAN FD connection with timing parameters ecu_fd.connect( bustype='pcan', channel='PCAN_USBBUS1', fd=True, f_clock_mhz=80, nom_brp=10, nom_tseg1=12, nom_tseg2=3, nom_sjw=1, data_brp=4, data_tseg1=7, data_tseg2=2, data_sjw=1 ) # Disconnect when done ecu.disconnect() ``` ### Response N/A (This is a setup and connection example) #### Success Response (200) N/A #### Response Example N/A ``` -------------------------------- ### ElectronicControlUnit Initialization and Bus Management Source: https://github.com/juergenh87/python-can-j1939/blob/master/docs/source/j1939.md Details the initialization of an Electronic Control Unit (ECU) and how to add CAN buses to it. It also covers setting up filters for the underlying CAN bus to manage incoming messages. ```python import can from j1939.electronic_control_unit import ElectronicControlUnit # Initialize an ElectronicControlUnit ecu = ElectronicControlUnit() # Create a CAN bus interface (example using 'virtual' bus) bus = can.interface.Bus(interface='virtual', channel='vcan0') # Add the CAN bus to the ECU ecu.add_bus(bus) # Define filters for the CAN bus filters = [ {"can_id": 0x18DAF100, "can_mask": 0x1FFFFFFF, "extended": True}, {"can_id": 0x18FEF100, "can_mask": 0x1FFFFFFF, "extended": True} ] ecu.add_bus_filters(filters=filters) ``` -------------------------------- ### Handle Incoming Clear Requests (DM11) Source: https://context7.com/juergenh87/python-can-j1939/llms.txt This snippet demonstrates how to handle incoming DM11 clear requests for all DTCs. It defines a callback function `on_clear_request` that is subscribed to the DM11 request. The function prints the request details and includes a placeholder for DTC clearing logic and sending acknowledgments. It concludes with a sleep and ECU disconnection. ```python def on_clear_request(src_address, dest_address, pgn): """Handle incoming DM11 clear request""" print(f"Clear request from {src_address} to {dest_address}") # Implement your DTC clearing logic here # Then send acknowledgement dm11.subscribe_request_clear_all(on_clear_request) time.sleep(30) ecu.disconnect() ``` -------------------------------- ### subscribe - Receive Messages Source: https://context7.com/juergenh87/python-can-j1939/llms.txt Demonstrates how to subscribe to incoming J1939 messages at both the ECU level (all messages) and the Controller Application (CA) level (messages for a specific address). ```APIDOC ## subscribe - Receive Messages ### Description Subscribe to incoming J1939 messages either at the ECU level (all messages) or CA level (messages for specific address). ### Method ECU.subscribe(callback, device_address=None) CA.subscribe(callback) ### Endpoint N/A (Library functions) ### Parameters #### ECU.subscribe Parameters - **callback** (function) - Required - The function to call when a message is received. - **device_address** (int) - Optional - If provided, only messages addressed to this specific device address will be received. If None, all broadcast messages are received. #### CA.subscribe Parameters - **callback** (function) - Required - The function to call when a message addressed to this CA is received. ### Request Example ```python import j1939 import time def on_message(priority, pgn, sa, timestamp, data): """Callback for receiving J1939 messages""" print(f"PGN: {pgn}, From: {sa}, Priority: {priority}, Length: {len(data)}") print(f"Data: {data.hex()}") # Create and connect ECU ecu = j1939.ElectronicControlUnit() ecu.connect(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000) # Subscribe at ECU level - receives all broadcast messages ecu.subscribe(on_message) # Subscribe with specific device address for peer-to-peer reception ecu.subscribe(on_message, device_address=0x80) # Create CA and subscribe at CA level name = j1939.Name( arbitrary_address_capable=0, industry_group=j1939.Name.IndustryGroup.Industrial, vehicle_system_instance=1, vehicle_system=1, function=1, function_instance=1, ecu_instance=1, manufacturer_code=666, identity_number=1234567 ) ca = j1939.ControllerApplication(name, 0x80) ecu.add_ca(controller_application=ca) ca.start() # CA subscription receives messages addressed to this CA ca.subscribe(on_message) # Listen for messages time.sleep(120) # Unsubscribe when done ecu.unsubscribe(on_message) ca.unsubscribe(on_message) ecu.disconnect() ``` ### Response N/A (Callback function is executed upon message reception) ### Response Example N/A ``` -------------------------------- ### ControllerApplication Timer Management Source: https://github.com/juergenh87/python-can-j1939/blob/master/docs/source/j1939.md Shows how to add and remove timer events for a ControllerApplication. Timers are used to trigger callback functions after a specified delay, useful for periodic tasks or timeouts. ```python def my_callback(cookie=None): print("Timer triggered!") # Add a timer that triggers after 5 seconds ca.add_timer(delta_time=5, callback=my_callback, cookie="timer1") # Remove the timer associated with my_callback ca.remove_timer(callback=my_callback) ``` -------------------------------- ### add_timer - Schedule Periodic Callbacks Source: https://context7.com/juergenh87/python-can-j1939/llms.txt This section is intended to document the `add_timer` functionality for scheduling periodic callbacks, but the provided text does not contain implementation details for this feature. -------------------------------- ### Name - Define Controller Application Identity Source: https://context7.com/juergenh87/python-can-j1939/llms.txt Explains how to create and use the `Name` class to define a unique J1939 NAME descriptor for a Controller Application, including various identity fields. ```APIDOC ## Name - Define Controller Application Identity ### Description The `Name` class represents the 64-bit NAME descriptor that uniquely identifies a Controller Application on the J1939 network. It includes manufacturer code, device function, and address claiming capability. ### Method Instantiation and attribute access for the `Name` class. ### Endpoint N/A (Class instantiation) ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A ### Request Example ```python import j1939 # Create a NAME descriptor for an industrial device name = j1939.Name( arbitrary_address_capable=0, # 0=Single Address, 1=Can negotiate address industry_group=j1939.Name.IndustryGroup.Industrial, # Industry classification vehicle_system_instance=1, # Vehicle system instance (0-15) vehicle_system=1, # Vehicle system number (0-127) function=1, # Device function (0-255) function_instance=1, # Function instance (0-31) ecu_instance=1, # ECU instance (0-7) manufacturer_code=666, # SAE assigned manufacturer code (0-2047) identity_number=1234567 # Unique device serial number (0-2097151) ) # Available industry groups # j1939.Name.IndustryGroup.Global # j1939.Name.IndustryGroup.OnHighway # j1939.Name.IndustryGroup.AgriculturalAndForestry # j1939.Name.IndustryGroup.Construction # j1939.Name.IndustryGroup.Marine # j1939.Name.IndustryGroup.Industrial # Access individual fields print(f"Manufacturer: {name.manufacturer_code}") print(f"Identity: {name.identity_number}") # Get 64-bit value or 8-byte representation name_value = name.value # 64-bit integer name_bytes = name.bytes # List of 8 bytes # Create NAME from raw bytes (e.g., from received message) received_name = j1939.Name(bytes=[0x87, 0xD6, 0x12, 0x00, 0x01, 0x01, 0x59, 0x14]) ``` ### Response N/A (This is a class usage example) #### Success Response (200) N/A #### Response Example N/A ``` -------------------------------- ### Create Custom J1939 Name Descriptor in Python Source: https://github.com/juergenh87/python-can-j1939/blob/master/docs/readme.md This Python snippet shows how to create a custom J1939 Name descriptor by subclassing the `j1939.Name` class. It allows for detailed configuration of various J1939 network identity parameters such as arbitrary address capability, industry group, and manufacturer code. This is useful for defining unique controller applications on the J1939 network. ```python import logging import time import can import j1939 logging.getLogger('j1939').setLevel(logging.DEBUG) logging.getLogger('can').setLevel(logging.DEBUG) # compose the name descriptor for the new ca name = j1939.Name( arbitrary_address_capable=0, industry_group=j1939.Name.IndustryGroup.Industrial, vehicle_system_instance=1, vehicle_system=1, function=1, function_instance=1, ecu_instance=1, manufacturer_code=666, identity_number=1234567 ) ``` -------------------------------- ### Name Class Source: https://github.com/juergenh87/python-can-j1939/blob/master/docs/source/j1939.md Represents the 64-bit Name of a Controller Application in a J1939 network. ```APIDOC ## Name Class ### Description Defines the 64-bit Name of a Controller Application, including fields like Industry Group, Vehicle System, Function, and Manufacturer Code. ### Properties - **arbitrary_address_capable** (bool) - Capability to solve address conflicts. - **industry_group** (int) - Predefined J1939 industry group. - **vehicle_system** (int) - Subcomponent of a vehicle. - **function** (int) - Predefined J1939 function. - **manufacturer_code** (int) - Predefined manufacturer code. - **identity_number** (int) - Unique device identifier. ### Usage Example ```python name = j1939.name.Name() name.industry_group = j1939.name.IndustryGroup.Global print(name.bytes) ``` ``` -------------------------------- ### Send Periodic J1939 Messages Source: https://github.com/juergenh87/python-can-j1939/blob/master/docs/readme.md Shows how to implement timer callbacks to send broadcast and peer-to-peer messages, including support for multi-packet transmissions like TP-BAM and TP-CMDT. ```python def ca_timer_callback1(cookie): if ca.state != j1939.ControllerApplication.State.NORMAL: return True data = [j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_8] * 8 ca.send_pgn(0, 0xFD, 0xED, 6, data) ca.send_pgn(0, 0xE0, 0x04, 6, data) return True ``` -------------------------------- ### Define Controller Application Identity with python-can-j1939 Name Source: https://context7.com/juergenh87/python-can-j1939/llms.txt Illustrates the creation of a J1939 NAME descriptor, which uniquely identifies a Controller Application. It shows how to set various attributes like industry group, manufacturer code, and identity number, and how to retrieve the NAME as a 64-bit integer or byte representation. ```python import j1939 # Create a NAME descriptor for an industrial device name = j1939.Name( arbitrary_address_capable=0, # 0=Single Address, 1=Can negotiate address industry_group=j1939.Name.IndustryGroup.Industrial, # Industry classification vehicle_system_instance=1, # Vehicle system instance (0-15) vehicle_system=1, # Vehicle system number (0-127) function=1, # Device function (0-255) function_instance=1, # Function instance (0-31) ecu_instance=1, # ECU instance (0-7) manufacturer_code=666, # SAE assigned manufacturer code (0-2047) identity_number=1234567 # Unique device serial number (0-2097151) ) # Available industry groups # j1939.Name.IndustryGroup.Global # j1939.Name.IndustryGroup.OnHighway # j1939.Name.IndustryGroup.AgriculturalAndForestry # j1939.Name.IndustryGroup.Construction # j1939.Name.IndustryGroup.Marine # j1939.Name.IndustryGroup.Industrial # Access individual fields print(f"Manufacturer: {name.manufacturer_code}") print(f"Identity: {name.identity_number}") # Get 64-bit value or 8-byte representation name_value = name.value # 64-bit integer name_bytes = name.bytes # List of 8 bytes # Create NAME from raw bytes (e.g., from received message) received_name = j1939.Name(bytes=[0x87, 0xD6, 0x12, 0x00, 0x01, 0x01, 0x59, 0x14]) ``` -------------------------------- ### POST /electronic_control_unit/add_ca Source: https://github.com/juergenh87/python-can-j1939/blob/master/docs/source/j1939.md Adds a new ControllerApplication to an ElectronicControlUnit instance. ```APIDOC ## POST /electronic_control_unit/add_ca ### Description Registers a new ControllerApplication to the ECU to manage its address and communication. ### Method POST ### Endpoint /electronic_control_unit/add_ca ### Parameters #### Request Body - **name** (object) - Required - The j1939.Name object - **device_address** (int) - Required - The preferred device address ### Request Example { "name": { "identity_number": 12345 }, "device_address": 128 } ### Response #### Success Response (200) - **ca_id** (string) - The identifier of the created ControllerApplication ``` -------------------------------- ### MessageListener Class Source: https://github.com/juergenh87/python-can-j1939/blob/master/docs/source/j1939.md A listener class that receives CAN messages and forwards them to an ECU. ```APIDOC ## j1939.electronic_control_unit.MessageListener Bases: `Listener` Listens for messages on CAN bus and feeds them to an ECU instance. * **Parameters:** **ecu** (*j1939.ElectronicControlUnit*) – The ECU to notify on new messages. ### on_message_received(msg: Message) This method is called to handle the given message. * **Parameters:** **msg** – the delivered message ### stop() Stop handling new messages, carry out any final tasks to ensure data is persisted and cleanup any open resources. Concrete implementations override. ``` -------------------------------- ### J1939 Version Module Source: https://github.com/juergenh87/python-can-j1939/blob/master/docs/source/j1939.md Information about the version of the j1939 library. ```APIDOC ## j1939.version module ### Description This module contains version information for the j1939 Python library. ### Module Contents - **__version__** (str): The version string of the library (e.g., '1.2.3'). - **__build__** (str): The build number or commit hash (if available). ### Example Usage ```python import j1939 print(f"J1939 Library Version: {j1939.__version__}") ``` ``` -------------------------------- ### Parse Diagnostic Trouble Codes (DTC) Source: https://context7.com/juergenh87/python-can-j1939/llms.txt This snippet illustrates how to create and parse J1939 Diagnostic Trouble Codes (DTCs) using the DTC class. It shows how to instantiate a DTC object with SPN, FMI, and occurrence counter, and then print its attributes. It also demonstrates parsing a DTC from a raw 32-bit value received from the bus and lists common FMI codes. ```python import j1939 # Create DTC from SPN and FMI dtc = j1939.DTC(spn=91, fmi=4, oc=10) print(f"SPN: {dtc.spn}") # Suspect Parameter Number print(f"FMI: {dtc.fmi}") # Failure Mode Identifier print(f"OC: {dtc.oc}") # Occurrence Counter print(f"DTC Raw: {dtc.dtc:#010x}") # 32-bit DTC value # Parse DTC from raw 32-bit value (received from bus) raw_dtc = 0x0A04005B # Example raw DTC bytes parsed_dtc = j1939.DTC(dtc=raw_dtc) print(f"Parsed SPN: {parsed_dtc.spn}") print(f"Parsed FMI: {parsed_dtc.fmi}") print(f"Parsed OC: {parsed_dtc.oc}") # Common FMI codes: # 0 - Data valid but above normal range # 1 - Data valid but below normal range # 2 - Data erratic # 3 - Voltage above normal # 4 - Voltage below normal # 5 - Current below normal # 6 - Current above normal # 7 - Mechanical system not responding # 31 - Condition exists ``` -------------------------------- ### J1939 Parameter Group Number (PGN) Representation (Python) Source: https://github.com/juergenh87/python-can-j1939/blob/master/docs/source/j1939.md Illustrates the structure and usage of the Parameter Group Number (PGN) class in J1939. It covers the components of a PGN, including data page, PDU format, and PDU specific fields, and distinguishes between PDU1 (peer-to-peer) and PDU2 (broadcast) formats. ```Python from j1939.parameter_group_number import ParameterGroupNumber, Address, PGN # Example of creating a PGN object # pgn_data_transfer = ParameterGroupNumber(data_page=0, pdu_format=57, pdu_specific=240) # Example PGN for Data Transfer # print(f"PGN Value: {pgn_data_transfer.value}") # Example of using predefined PGN constants # print(f"Address Claim PGN: {PGN.ADDRESSCLAIM}") # print(f"Global Address: {Address.GLOBAL}") ```