Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
from udsoncan.client import Client
from udsoncan import services
from udsoncan.exceptions import *
from udsoncan import DidCodec, AsciiCodec
import struct
from test.ClientServerTest import ClientServerTest
class StubbedDidCodec(DidCodec):
def encode(self, did_value):
return struct.pack('B', did_value+1)
def decode(self, did_payload):
return struct.unpack('B', did_payload)[0] - 1
def __len__(self):
return 1
class TestReadDataByIdentifier(ClientServerTest):
def __init__(self, *args, **kwargs):
ClientServerTest.__init__(self, *args, **kwargs)
def postClientSetUp(self):
self.udsclient.config["data_identifiers"] = {
1 : '>H',
def test_DIDCodec_bad_values(self):
with self.assertRaises(NotImplementedError):
codec = DidCodec();
codec.encode("asd")
with self.assertRaises(NotImplementedError):
codec = DidCodec();
codec.decode(b"asd")
with self.assertRaises(ValueError):
DidCodec.from_config("")
from udsoncan import IOValues, IOMasks
import struct
from test.ClientServerTest import ClientServerTest
class StubbedCodec(DidCodec):
def encode(self, did_value):
return struct.pack('B', did_value+1)
def decode(self, did_payload):
return struct.unpack('B', did_payload)[0] - 1
def __len__(self):
return 1
class StubbedCompositeCodec(DidCodec):
def encode(self, IAC_pintle, rpm, pedalA, pedalB, EGR_duty):
pedal = (pedalA << 4) | pedalB
return struct.pack('>BHBB', IAC_pintle, rpm, pedal, EGR_duty)
def decode(self, payload):
vals = struct.unpack('>BHBB', payload)
return {
'IAC_pintle': vals[0],
'rpm' : vals[1],
'pedalA' : (vals[2] >> 4) & 0xF,
'pedalB' : vals[2] & 0xF,
'EGR_duty' : vals[3]
}
def __len__(self):
return 5
import struct
from udsoncan import DidCodec
def test_algo(seed):
key = bytearray(seed)
for i in range(len(key)):
key[i] ^= 0xFF
return key
class MyDidCodec(DidCodec):
def encode(self, did_value):
return struct.pack('B', did_value+1)
def decode(self, did_payload):
return struct.unpack('B', did_payload)[0] - 1
def __len__(self):
return 1
client_config = {
'security_algo' : test_algo,
'data_identifiers' : {
1 : '>H',
2 : '
from udsoncan.client import Client
from udsoncan import services
from udsoncan.exceptions import *
from udsoncan import DidCodec
import struct
from test.ClientServerTest import ClientServerTest
class StubbedDidCodec(DidCodec):
def encode(self, did_value):
return struct.pack('B', did_value+1)
def decode(self, did_payload):
return struct.unpack('B', did_payload)[0] - 1
def __len__(self):
return 1
class StubbedCodecThatExpectTuple(DidCodec):
def encode(self, the_tuple):
if not isinstance(the_tuple, tuple):
raise ValueError('Given value is not a tuple')
return struct.pack('BB', the_tuple[0], the_tuple[1])
def decode(self, did_payload):
from udsoncan.client import Client
from udsoncan import services
from udsoncan.exceptions import *
from udsoncan import DidCodec
from udsoncan import IOValues, IOMasks
import struct
from test.ClientServerTest import ClientServerTest
class StubbedCodec(DidCodec):
def encode(self, did_value):
return struct.pack('B', did_value+1)
def decode(self, did_payload):
return struct.unpack('B', did_payload)[0] - 1
def __len__(self):
return 1
class StubbedCompositeCodec(DidCodec):
def encode(self, IAC_pintle, rpm, pedalA, pedalB, EGR_duty):
pedal = (pedalA << 4) | pedalB
return struct.pack('>BHBB', IAC_pintle, rpm, pedal, EGR_duty)
def decode(self, payload):
vals = struct.unpack('>BHBB', payload)
:param value: Value given to the :ref:`DidCodec `.encode method. If involved codec is defined with a pack string (default codec), multiple values may be passed with a tuple.
:type value: object
:param didconfig: Definition of DID codecs. Dictionary mapping a DID (int) to a valid :ref:`DidCodec ` class or pack/unpack string
:type didconfig: dict[int] = :ref:`DidCodec `
:raises ValueError: If parameters are out of range, missing or wrong type
:raises ConfigError: If ``didlist`` contains a DID not defined in ``didconfig``
"""
from udsoncan import Request, DidCodec
ServiceHelper.validate_int(did, min=0, max=0xFFFF, name='Data Identifier')
req = Request(cls)
didconfig = ServiceHelper.check_did_config(did, didconfig=didconfig) # Make sure all DIDs are correctly defined in client config
req.data = struct.pack('>H', did) # encode DID number
codec = DidCodec.from_config(didconfig[did])
if codec.__class__ == DidCodec and isinstance(value, tuple):
req.data += codec.encode(*value) # Fixes issue #29
else:
req.data += codec.encode(value)
return req
# For each DID
for i in range(number_of_did):
remaining_data = response.data[actual_byte:]
snapshot = Dtc.Snapshot() # One snapshot epr DID for convenience
snapshot.record_number = record_number
# As standard does not specify the length of the DID, we craft it based on a config
did = 0
for j in range(dtc_snapshot_did_size):
offset = dtc_snapshot_did_size-1-j
did |= (remaining_data[offset] << (8*j))
# Decode the data based on DID number.
snapshot.did = did
didconfig = ServiceHelper.check_did_config(did, didconfig)
codec = DidCodec.from_config(didconfig[did])
data_offset = dtc_snapshot_did_size;
if len(remaining_data[data_offset:]) < len(codec):
raise InvalidResponseException(response, 'Incomplete response. Data for DID 0x%04x is only %d bytes while %d bytes is expected' % (did, len(remaining_data[data_offset:]), len(codec)))
snapshot.raw_data = remaining_data[data_offset:data_offset + len(codec)]
snapshot.data = codec.decode(snapshot.raw_data)
dtc.snapshots.append(snapshot)
actual_byte += dtc_snapshot_did_size + len(codec)
response.service_data.dtcs.append(dtc)
response.service_data.dtc_count = len(response.service_data.dtcs)
# These subfunctions include DTC ExtraData. We give it raw to user.
break # Done
if len(response.data) <= offset +1:
if tolerate_zero_padding and response.data[-1] == 0: # One extra byte, but it's a 0 and we accept that. So we're done
break
raise InvalidResponseException(response, "Response given by server is incomplete.")
did = struct.unpack('>H', response.data[offset:offset+2])[0] # Get the DID number
if did == 0 and did not in didconfig and tolerate_zero_padding: # We read two zeros and that is not a DID bu we accept that. So we're done.
if response.data[offset:] == b'\x00' * (len(response.data) - offset):
break
if did not in didconfig: # Already checked in check_did_config. Paranoid check
raise ConfigError(key=did, msg='Actual data identifier configuration contains no definition for data identifier 0x%04x' % did)
codec = DidCodec.from_config(didconfig[did])
offset+=2
if len(response.data) < offset+len(codec):
raise InvalidResponseException(response, "Value for data identifier 0x%04x was incomplete according to definition in configuration" % did)
subpayload = response.data[offset:offset+len(codec)]
offset += len(codec) # Codec must define a __len__ function that matches the encoded payload length.
val = codec.decode(subpayload)
response.service_data.values[did] = val
return response
raise ValueError("masks must be an instance of IOMask or a boolean value")
if values is None and masks is not None:
raise ValueError('An IOValue must be given if a IOMask is provided.')
request = Request(service=cls)
request.data = b''
ioconfig = ServiceHelper.check_io_config(did, ioconfig) # IO dids are defined in client config.
request.data += struct.pack('>H', did)
# This parameter is optional according to standard
if control_param is not None:
request.data += struct.pack('B', control_param)
codec = DidCodec.from_config(ioconfig[did]) # Get IO codec from config
if values is not None:
request.data += codec.encode(*values.args, **values.kwargs)
if masks is not None: # Skip the masks byte if none is given.
if isinstance(masks, bool):
byte = b'\xFF' if masks == True else b'\x00'
if 'mask_size' in ioconfig[did]:
request.data += (byte * ioconfig[did]['mask_size'])
else:
raise ConfigError('mask_size', msg='Given mask is boolean value, indicating that all mask should be set to same value, but no mask_size is defined in configuration. Cannot guess how many bits to set.')
elif isinstance(masks, IOMasks):
if 'mask' not in ioconfig[did]:
raise ConfigError('mask', msg='Cannot apply given mask. Input/Output configuration does not define their position (and size).')
masks_config = ioconfig[did]['mask']