主要是通过python-can模块与pcan等支持的硬件通讯,uds协议层使用udsoncan模块和can-isotp模块实现uds诊断。
python-can模块
pip install python-can
相关文档链接:Installation - python-can 4.1.0 documentation
udsoncan模块
pip install udsoncan
相关文档链接:Python implementation of UDS standard (ISO-14229) — udsoncan 0 documentation
can-isotp模块
pip install can-isotp
相关文档链接:Python support for IsoTP Transport protocol (ISO-15765) — isotp 0 documentation
下面示例展示了如何将PythonIsoTpConnection与Vector接口一起使用。
from can.interfaces.vector import VectorBusfrom udsoncan.connections import PythonIsoTpConnectionfrom udsoncan.client import Clientimport isotp# Refer to isotp documentation for full details about parametersisotp_params = { 'stmin' : 32, # Will request the sender to wait 32ms between consecutive frame. 0-127ms or 100-900ns with values from 0xF1-0xF9 'blocksize' : 8, # Request the sender to send 8 consecutives frames before sending a new flow control message 'wftmax' : 0, # Number of wait frame allowed before triggering an error 'tx_data_length' : 8, # Link layer (CAN layer) works with 8 byte payload (CAN 2.0) 'tx_data_min_length' : None, # Minimum length of CAN messages. When different from None, messages are padded to meet this length. Works with CAN 2.0 and CAN FD. 'tx_padding' : 0, # Will pad all transmitted CAN messages with byte 0x00. 'rx_flowcontrol_timeout' : 1000, # Triggers a timeout if a flow control is awaited for more than 1000 milliseconds 'rx_consecutive_frame_timeout' : 1000, # Triggers a timeout if a consecutive frame is awaited for more than 1000 milliseconds 'squash_stmin_requirement' : False, # When sending, respect the stmin requirement of the receiver. If set to True, go as fast as possible. 'max_frame_size' : 4095 # Limit the size of receive frame.}bus = VectorBus(channel=0, bitrate=500000) # Link Layer (CAN protocol)tp_addr = isotp.Address(isotp.AddressingMode.Normal_11bits, txid=0x123, rxid=0x456) # Network layer addressing schemestack = isotp.CanStack(bus=bus, address=tp_addr, params=isotp_params) # Network/Transport layer (IsoTP protocol)stack.set_sleep_timing(0, 0)# Speed First (do not sleep)conn = PythonIsoTpConnection(stack) # interface between Application and Transport layerwith Client(conn, request_timeout=1) as client: # Application layer (UDS protocol) client.change_session(1) # ...
其他uds服务相关使用示例:
import udsoncanfrom udsoncan.connections import IsoTPSocketConnectionfrom udsoncan.client import Clientfrom udsoncan.exceptions import *from udsoncan.services import *udsoncan.setup_logging()conn = IsoTPSocketConnection('can0', rxid=0x123, txid=0x456)with Client(conn, request_timeout=2, config=MyCar.config) as client: try: client.change_session(DiagnosticSessionControl.Session.extendedDiagnosticSession) # integer with value of 3 client.unlock_security_access(MyCar.debug_level) # Fictive security level. Integer coming from fictive lib, let's say its value is 5 client.write_data_by_identifier(udsoncan.DataIdentifier.VIN, 'ABC123456789') # Standard ID for VIN is 0xF190. Codec is set in the client configuration print('Vehicle Identification Number successfully changed.') client.ecu_reset(ECUReset.ResetType.hardReset) # HardReset = 0x01 except NegativeResponseException as e: print('Server refused our request for service %s with code "%s" (0x%02x)' % (e.response.service.get_name(), e.response.code_name, e.response.code)) except InvalidResponseException, UnexpectedResponseException as e: print('Server sent an invalid payload : %s' % e.response.original_payload)
安全算法示例,需要实现myalgo函数,并且uds的configs中的security_algo配置为myalgo,同时配置security_algo_params。
def myalgo(level, seed, params):"""Builds the security key to unlock a security level. Returns the seed xor'ed with pre-shared key.""" output_key = bytearray(seed) xorkey = bytearray(params['xorkey']) for i in range(len(seed)): output_key[i] = seed[i] ^ xorkey[i%len(xorkey)] return bytes(output_key)client.config['security_algo'] = myalgoclient.config['security_algo_params'] = dict(xorkey=b'\x12\x34\x56\x78')
使用DID配置配置客户端,并使用ReadDataByIdentifier请求服务器
import udsoncanfrom udsoncan.connections import IsoTPSocketConnectionfrom udsoncan.client import Clientimport udsoncan.configsimport structclass MyCustomCodecThatShiftBy4(udsoncan.DidCodec): def encode(self, val): val = (val << 4) & 0xFFFFFFFF # Do some stuff return struct.pack('> 4 # Do some stuff (reversed) def __len__(self): return 4 # encoded payload is 4 byte long.config = dict(udsoncan.configs.default_client_config)config['data_identifiers'] = { 0x1234 : MyCustomCodecThatShiftBy4, # Uses own custom defined codec. Giving the class is ok 0x1235 : MyCustomCodecThatShiftBy4(), # Same as 0x1234, giving an instance is good also 0xF190 : udsoncan.AsciiCodec(15) # Codec that read ASCII string. We must tell the length of the string }# IsoTPSocketconnection only works with SocketCAN under Linux. Use another connection if needed.conn = IsoTPSocketConnection('vcan0', rxid=0x123, txid=0x456)with Client(conn, request_timeout=2, config=config) as client: response = client.read_data_by_identifier([0xF190]) print(response.service_data.values[0xF190]) # This is a dict of DID:Value # Or, if a single DID is expected, a shortcut to read the value of the first DID vin = client.read_data_by_identifier_first(0xF190) print(vin) # 'ABCDE0123456789' (15 chars)
来源地址:https://blog.csdn.net/qq_45303968/article/details/126251064