-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcan_decoder.py
184 lines (153 loc) · 6.47 KB
/
can_decoder.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# date: 04.09.2020
# author: Yannik Motzet
# description: script to extract signal values of a CAN datagram
import numpy as np
is_decode = False # True for decoding, False for encoding
is_decimal = False # True for dec input/output, False for hex input/output
filepath_database = 'database.txt'
paramater_number = 4 # number of signal parameter in database file
# loads database info in numpy array
def load_database(filepath):
f = open(filepath)
number_of_signals = len(open(filepath).readlines())
database = np.full((number_of_signals, paramater_number), None)
counter = 0
for line in f:
database_line = line.split(",")
# signal name
database[counter, 0] = database_line[0]
# bit length
database[counter, 1] = int(database_line[1])
# signedness
database[counter, 2] = database_line[2]
# factor
database[counter, 3] = float(database_line[3])
counter = counter + 1
f.close()
return database
# extract signal values from CAN message
def decode_can_message(input_message, is_input_dec, database_filepath):
# transform heximal/decimal to binary
#####################################
can_bytes_list = []
# input in dec
if is_input_dec:
can_message = input_message.split(",")
for message in can_message:
can_bytes_list.append(bin(int(message))[2:].zfill(8))
# input in hex
else:
can_message = input_message.split(",")
for message in can_message:
can_bytes_list.append(bin(int(message, 16))[2:].zfill(8))
# extract binary values of signals
#####################################
# load the database
database = load_database(database_filepath)
signal_list_bin = [None] * database.shape[0]
byte_index = 0
# iterate through database signals
for i in range(database.shape[0]):
# itarate through length of signal
for j in range(database[i, 1]):
if len(can_bytes_list[byte_index]) == 0:
byte_index = byte_index + 1
if signal_list_bin[i] is None:
signal_list_bin[i] = can_bytes_list[byte_index][-1]
else:
signal_list_bin[i] = can_bytes_list[byte_index][-1] + signal_list_bin[i]
# delete last bit
can_bytes_list[byte_index] = can_bytes_list[byte_index][:-1]
# transform binary values to physical values
#####################################
signal_list = []
for i in range(database.shape[0]):
# unsigned
if database[i, 2] == "u":
signal_value = int(signal_list_bin[i], 2) * database[i, 3]
# unsigned
elif database[i, 2] == "s":
# positive sign
if signal_list_bin[i][0] == "0":
signal_value = int(signal_list_bin[i], 2) * database[i, 3]
# negative sign
elif signal_list_bin[i][0] == "1":
signal_value = (int(signal_list_bin[i], 2) - 2**len(signal_list_bin[i])) * database[i, 3]
# signal name + signal value (# format method removes .0 in a value)
signal_list.append(database[i, 0] + ": " + '{:g}'.format(signal_value))
return signal_list
def request_signal_values(filepath):
database = load_database(filepath)
number_of_signals = database.shape[0]
signal_values = [None] * number_of_signals
# asking for signals and storing it
for i in range(number_of_signals):
signal_values[i] = input(database[i, 0] +': ')
return signal_values
def encode_can_message(signal_values, is_output_dec, filepath):
database = load_database(filepath)
for i in range(len(signal_values)):
# divide by factor
signal_values[i] = round(float(signal_values[i]) / float(database[i, 3]))
# check for negative values and signedness
if signal_values[i] < 0 and database[i, 2] == "s":
signal_values[i] = int(2**database[i, 1]) + signal_values[i]
# transfer to binary
signal_values[i] = bin(int(signal_values[i]))[2:].zfill(database[i, 1])
# push signal bits in bytes
bytes_list = [None] * 8
byte_index = 0
bit_index = 0
# iterate through database signals
for i in range(database.shape[0]):
# itarate through length of signal
for j in range(database[i, 1]):
# if byte has reached 8 bits go to next byte
if bit_index == 8:
byte_index = byte_index + 1
bit_index = 0
bit_index = bit_index + 1
if bytes_list[byte_index] is None:
bytes_list[byte_index] = signal_values[i][-1]
else:
bytes_list[byte_index] = signal_values[i][-1] + bytes_list[byte_index]
# delete last bit
signal_values[i] = signal_values[i][:-1]
# transfer binary values of bytes to hex/dec
hex_value_list = []
for element in bytes_list:
if is_output_dec:
hex_value_list.append(int(element, 2))
else:
hex_value_list.append(hex(int(element, 2))[2:])
return hex_value_list
if __name__ == "__main__":
# decode CAN message
if is_decode:
if is_decimal:
# can_message_input = "165, 182, 240, 0, 178, 151, 195, 4" # for testing purpose
can_message_input = input("Input CAN message (dec): ")
else:
# can_message_input = "A5, B6, F0, 00, B2, 97, C3, 04" # for testing purpose
can_message_input = input("Input CAN message (hex): ")
# extract signal values from CAN message
signal_values = decode_can_message(can_message_input, is_decimal, filepath_database)
# print signal values
print("-" * (len("Input CAN message (xxx): ") + len(can_message_input)))
for value in signal_values:
print(value)
# encode CAN message
else:
if is_decimal: print("Please enter signal values (dec).")
else: is_decimal: print("Please enter signal values (hex).")
signal_values = request_signal_values(filepath_database)
byte_values = encode_can_message(signal_values, is_decimal, filepath_database)
print("-" * 30)
if is_decimal:
print("CAN message (dec): ")
else:
print("CAN message (hex): ")
for byte in byte_values[:-1]:
print(byte.upper(), end=', ')
# print last byte without "," in the end
print(byte_values[-1].upper())