I am receiving a can message over udp in the format (data_length, frame_id, data) and trying to translate it into json. I am using the cantools library to load a dbc file with cantools.database.load_file() and then translating the message with decode_message(). The message is being decoded without any errors except the values I am receiving are wrong when compared to when I decode it manually and when I use other software to decode the messages. For example, the following data 00 00 03 d0 01 40 00 ad
should be decoded to be {‘Engine_Speed’: 0, ‘Inlet_Manifold_Pressure’: 97.6, ‘Inlet_Air_Temperature’: 32, ‘Throttle_Position’: 17.3}
but instead it is {‘Engine_Speed’: 12336, ‘Inlet_Manifold_Pressure’: 1233.6000000000001, ‘Inlet_Air_Temperature’: 1233.9, ‘Throttle_Position’: 2564.8}
. Here is the image of this part of the dbc in kvsar CAN DBC for this frame_id
I have tried reversing the data in 3 different ways:
Given the original data 12 34 56 78
I have transformed it to be 87 65 43 21
, 78 56 34 12
, and 21 43 65 87
but none of these have gotten me the proper value. I also have code that formats the data in a bite string that looks like the following b'\\x10\\x00\\x00\\x10\\x10\\x00\\x00\\x30'
which fixes the issue for some but not all variables. I have checked that the dbc has no offsets, the scaling I am using is correct, and that the proper bytes are assigned to the proper variables but none of this worked.
Here is the code:
`import cantools
import json
import time
def start(receive_socket, socket):
print('Starting CAN Translator')
global send_socket
send_socket = socket
setup()
main(receive_socket)
def setup():
global sel
global db
global CANSocket
global serverIP
global receivePort
global bufferSize
global nonLiterals
global json_file_name
bufferSize = 1024
nonLiterals = set()
json_file_name = 'json_data.json'
# Add the DBC file to the CAN reader
db = cantools.database.load_file('DBCS/DBC3.dbc', database_format='dbc', encoding='cp1252', frame_id_mask=None, prune_choices=False, strict=True, cache_dir=None)
# Reset the json file
json_file = open(json_file_name, 'w')
json_file.write('{}')
def find_nth(haystack, needle, n):
start = haystack.find(needle)
while start >= 0 and n > 1:
start = haystack.find(needle, start + len(needle))
n -= 1
return start
# Translate each string from the decoded CAN message into a dictionary and then output that dictionary to the json file
def to_json(message):
print(message)
with open(json_file_name, 'r+') as json_file:
json_dict = json.load(json_file)
# print(json_dict)
json_dict.update(message)
# Add a value to hold the current time
json_dict.update({'Timestamp': time.time()})
json_file.close()
open(json_file_name, 'w').close()
json_file = open(json_file_name, 'r+')
json.dump(json_dict, json_file)
send_json(json_dict)
def reformatter(data_string):
# print(data_string)
start_pos = 0
current_space = 0
next_space = 0
i = 0
data_reformatted = ''
while next_space >= 0:
# print(data_string)
next_space = find_nth(data_string, ' ', i + 1)
# print(next_space)
# print(next_space-current_space)
if next_space - current_space == 1:
data_reformatted += ('\\x0' + data_string[start_pos:next_space])
elif next_space - current_space == 2:
data_reformatted += ('\\x' + data_string[start_pos:next_space])
else:
data_reformatted += ('\\x' + data_string[start_pos:])
# print('looking for more spaces')
i += 1
current_space = next_space + 1
start_pos = current_space
# print(data_reformatted)
return data_reformatted
def data_handler(data):
# Extract the message from the socket
message = data.decode().strip()
# Separate CAN message into id and data
# Except non hexadecimal values
try:
frame_id = int(message[find_nth(message, ',', 1) + 1:find_nth(message, ',', 2)], 16)
except ValueError as error:
# print('Non hexadecimal frame_id: %s' % error)
nonLiterals.add(str(error))
frame_id = 'ERROR'
print(message)
print(f'Frame ID: {frame_id} data: {data}')
data_string = message[find_nth(message, ',', 2) + 1:]
data = bytes(data_string, 'utf-8')
data_reformatted = reformatter(data_string)
fixed_data = bytes(data_reformatted, 'utf-8')
# print(fixed_data)
reversed_reformatted = bytes(reverse(data_reformatted), 'utf-8')
regular_reversed = data_string[::-1]
regular_reversed_reformatted = bytes(reformatter(regular_reversed), 'utf-8')
weird_reversed = bytes(reverse(reformatter(regular_reversed)), 'utf-8')
to_send = fixed_data
print(to_send)
try:
# Decode each incoming message
to_json(db.decode_message(frame_id_or_name=frame_id, data=to_send, decode_choices=False, scaling=True, decode_containers=False, allow_truncated=False))
except KeyError as error:
print('Key error: %s' % error)
except ValueError as error:
print(error)
except Exception as error:
print(error)
def send_json(json_string):
json_result = json.dumps(json_string)
try:
send_socket.send(json_result.encode())
except ConnectionResetError as error:
print(error)
# print(json_result, 'was sent!')
# time.sleep(1)
def reverse(data_string):
# print(data_string)
length = len(data_string)
i = int(length/4)
reverse_string = ''
while i > 0:
startpos = find_nth(data_string, '\\', i)
reverse_string += data_string[startpos:startpos+4]
i -= 1
# print(reverse_string)
return reverse_string
def main(receive_socket):
while True:
data_handler(receive_socket.recv())
`