Index: run.update_package.py
===================================================================
diff -u -r28ee439966c2b482352f1cadd913d558fcac2a05 -r5b6f3d91478d1da65e094cdb802d6c19ab4385d8
--- run.update_package.py (.../run.update_package.py) (revision 28ee439966c2b482352f1cadd913d558fcac2a05)
+++ run.update_package.py (.../run.update_package.py) (revision 5b6f3d91478d1da65e094cdb802d6c19ab4385d8)
@@ -26,7 +26,7 @@
start = time.time()
update = SoftwareUpdateScript()
update.update_software_packages(packages_directory, stack)
- print('Report Generation Time: {:.1f}s'.format(time.time() - start))
+ print('Package Update Time: {:.1f} s'.format(time.time() - start))
if __name__ == "__main__":
Index: scripts/base/base.py
===================================================================
diff -u -rdd30a8caf586169db067d42da875a31507628e8d -r5b6f3d91478d1da65e094cdb802d6c19ab4385d8
--- scripts/base/base.py (.../base.py) (revision dd30a8caf586169db067d42da875a31507628e8d)
+++ scripts/base/base.py (.../base.py) (revision 5b6f3d91478d1da65e094cdb802d6c19ab4385d8)
@@ -1,10 +1,27 @@
import os
-import shutil
+from enum import Enum, unique
+
+class SWUpdateEnum(Enum):
+
+ @classmethod
+ def has_value(cls, value):
+ return value in cls._value2member_map_
+
+@unique
+class SWUpdateTargets(SWUpdateEnum):
+ TARGET_TD = 0
+ TARGET_TD_FPGA = 1
+ TARGET_DD = 2
+ TARGET_DD_FPGA = 3
+ TARGET_RO = 4
+ TARGET_RO_FPGA = 5
+ NUM_OF_TARGETS = 6
+
class Base:
- SW_UPDATE_FLASH_BUFFER_SIZE = 128
+ SW_UPDATE_FLASH_BUFFER_SIZE = 256 #128
SIGNATURE_START = "SIGNATURE_START==================="
SIGNATURE_END = "SIGNATURE_END==================="
SIGNATURE_SIZE_BYTES = 344
Index: scripts/update_package_script/update_package.py
===================================================================
diff -u -rdd30a8caf586169db067d42da875a31507628e8d -r5b6f3d91478d1da65e094cdb802d6c19ab4385d8
--- scripts/update_package_script/update_package.py (.../update_package.py) (revision dd30a8caf586169db067d42da875a31507628e8d)
+++ scripts/update_package_script/update_package.py (.../update_package.py) (revision 5b6f3d91478d1da65e094cdb802d6c19ab4385d8)
@@ -1,24 +1,221 @@
import os
-import can
-import struct
-from scripts.base.base import Base
+import re
+from scripts.base.base import Base, SWUpdateTargets
+from scripts.update_package_script.utilities import Utilities, SWUpdateCommands, CanCommStatus
+
class SoftwareUpdateScript(Base):
+ _DECODED_BYTES_KEY_NAME = 'decoded_bytes'
+ _CUR_DATA_INDEX_KEY_NAME = 'cur_data_index'
+ _CUR_INSERT_DATA_INDEX_KEY_NAME = 'cur_insert_index'
+ _TOTAL_BYTES_TX_KEY_NAME = 'total_bytes_tx'
+ _RESIDUAL_BYTES_KEY_NAME = 'residual_bytes'
+ _BINARY_SEND_COMPLETE_KEY_NAME = 'is_binary_done'
+ _SIG_MSG_SEND_COMPLETE_KEY_NAME = 'is_sig_msg_done'
+
+ _XML_REPORT_FILE_TYPE_KEY_NAME = 'filetype'
+ _XML_REPORT_BIN_SIZE_KEY_NAME = 'size'
+
+ _DECODE_LIST_MAX_SIZE_BYTES = 4096
+ _SHIFT_BITS_BY_8 = 8
+ _DECODE_COPRIME_1 = 19
+ _DECODE_COPRIME_2 = 23
+ _DECODE_VALUE = 256
+ _DECODE_ADD_VALUE = 211
+ _XML_REPORT_END_TAG = ""
+ _XML_REPORT_HEADER_SIZE = 2
+
def __init__(self):
super().__init__()
+ self._signature_start_in_bytes = bytes(self.SIGNATURE_START, 'utf-8')
+ self._signature_end_in_bytes = bytes(self.SIGNATURE_END, 'utf-8')
+ self._decode_data_status = dict()
+ self._xml_report_values = dict()
+ self._utilities = Utilities()
- def _verify_signature(self):
+ def _reset_variables(self):
+
+ # TODO #define for the dictionary keys
+ self._decode_data_status['decode_values_found'] = False
+ self._decode_data_status['end_tag_found'] = False
+ self._decode_data_status['decode_found_index'] = 0
+ self._decode_data_status['converted_xml'] = ''
+ self._decode_data_status['is_first_line'] = False
+ self._decode_data_status['num_of_bytes_sent'] = 0 #TODO remove?
+ self._decode_data_status[self._RESIDUAL_BYTES_KEY_NAME] = list()
+ self._decode_data_status[self._DECODED_BYTES_KEY_NAME] = list()
+ self._decode_data_status[self._CUR_DATA_INDEX_KEY_NAME] = 0
+ self._decode_data_status[self._CUR_INSERT_DATA_INDEX_KEY_NAME] = 0
+ self._decode_data_status[self._TOTAL_BYTES_TX_KEY_NAME] = 0
+ self._decode_data_status[self._BINARY_SEND_COMPLETE_KEY_NAME] = False
+ self._decode_data_status[self._SIG_MSG_SEND_COMPLETE_KEY_NAME] = False
+
+ self._xml_report_values['name'] = ''
+ self._xml_report_values['version'] = ''
+ self._xml_report_values[self._XML_REPORT_FILE_TYPE_KEY_NAME] = ''
+ self._xml_report_values['security'] = ''
+ self._xml_report_values['version'] = ''
+ self._xml_report_values[self._XML_REPORT_BIN_SIZE_KEY_NAME] = 0
+ self._xml_report_values['raw'] = ''
+
+ self._utilities.clear_msg_ack_nack_status(self._utilities.SEND_MSG_ACK_STATUS_KEY_NAME)
+ self._utilities.clear_msg_ack_nack_status(self._utilities.UPDATE_MSG_ACK_STATUS_KEY_NAME)
+
+ def _verify_signature(self, signature: bytes):
+ # TODO fill up
pass
def _verify_key(self):
pass
- def _get_target_stack(self):
- pass
+ def _get_decode_variables(self, line_bytes: bytes):
+ if len(self._decode_data_status[self._RESIDUAL_BYTES_KEY_NAME]) != 0:
+ line_bytes = self._decode_data_status[self._RESIDUAL_BYTES_KEY_NAME] + line_bytes
+
+ if len(line_bytes) > 2:
+ a = int(line_bytes[0])
+ b = int(line_bytes[1])
+ if a is not None and b is not None:
+ code = (a << self._SHIFT_BITS_BY_8) + b
+ for s in range(0, 0xFF):
+ convert = ((s % self._DECODE_COPRIME_1) << self._SHIFT_BITS_BY_8) + (s % self._DECODE_COPRIME_2)
+
+ if code == convert:
+ self._decode_data_status['decode_found_index'] = s
+ self._decode_data_status['decode_values_found'] = True
+ print("Breaking {} {} {} {} {}".format(code, convert, s, a, b))
+ break
+
+ def _decode_line(self, line_bytes: bytes):
+
+ start_index = 0
+
+ if len(self._decode_data_status[self._RESIDUAL_BYTES_KEY_NAME]) != 0:
+ line_bytes = self._decode_data_status[self._RESIDUAL_BYTES_KEY_NAME] + line_bytes
+ self._decode_data_status[self._RESIDUAL_BYTES_KEY_NAME] = list()
+
+ if self._decode_data_status['is_first_line'] is False:
+ start_index = self._XML_REPORT_HEADER_SIZE
+ self._decode_data_status['is_first_line'] = True
+
+ for d in range(start_index, len(line_bytes)):
+ if self._decode_data_status['end_tag_found'] is False:
+ decoded_value_bytes = (line_bytes[d] - self._decode_data_status[
+ 'decode_found_index']) % self._DECODE_VALUE
+ self._decode_data_status['decode_found_index'] += self._DECODE_ADD_VALUE
+ self._decode_data_status['converted_xml'] += ''.join(chr(decoded_value_bytes)).replace('\n', '')
+
+ if self._XML_REPORT_END_TAG in self._decode_data_status['converted_xml']:
+
+ converted_xml = self._decode_data_status['converted_xml']
+ self._decode_data_status['end_tag_found'] = True
+ self._xml_report_values[self._XML_REPORT_FILE_TYPE_KEY_NAME] = \
+ re.search('(.*)', converted_xml).group(1)
+ binary_size_int = re.search('(.*)', converted_xml).group(1)
+ self._xml_report_values[self._XML_REPORT_BIN_SIZE_KEY_NAME] = int(binary_size_int)
+
+ print(self._xml_report_values['filetype'], self._xml_report_values['size'],
+ len(converted_xml), converted_xml, self._decode_data_status['decode_found_index'], 'H') # TODO remove
+ else:
+ self._decode_data_status[self._DECODED_BYTES_KEY_NAME].append(line_bytes[d])
+ self._decode_data_status[self._CUR_DATA_INDEX_KEY_NAME] += 1
+
+ def _process_read_line(self, line: bytes):
+
+ if self._signature_start_in_bytes in line:
+ if self._signature_end_in_bytes:
+ signature = line[len(self._signature_start_in_bytes):line.find(self._signature_end_in_bytes)]
+ self._verify_signature(signature)
+ end_of_signature_mark = line.find(self._signature_end_in_bytes) + len(self._signature_end_in_bytes)
+ xml_report_start = line[end_of_signature_mark:]
+ if (len(line) - end_of_signature_mark) > 2 and self._decode_data_status['decode_values_found'] is False:
+ self._get_decode_variables(xml_report_start)
+ else:
+ print(xml_report_start, 'D')
+ self._decode_data_status[self._RESIDUAL_BYTES_KEY_NAME] = xml_report_start
+
+ if self._decode_data_status['decode_values_found'] is True:
+ self._decode_line(xml_report_start)
+ else:
+ # TODO fill up
+ pass
+ else:
+ self._get_decode_variables(line) if self._decode_data_status['decode_values_found'] is False else None
+ self._decode_line(line)
+
+ def _handle_processed_data(self):
+
+ send_ack_status = self._utilities.get_msg_ack_nack_status(self._utilities.SEND_MSG_ACK_STATUS_KEY_NAME)
+ update_ack_status = self._utilities.get_msg_ack_nack_status(self._utilities.UPDATE_MSG_ACK_STATUS_KEY_NAME)
+ #print(send_ack_status, update_ack_status)
+
+ # TODO change the target right now they do not match because they are written for Leahi
+ # TODO for instance, it should be self._xml_report_values[self._XML_REPORT_FILE_TYPE_KEY_NAME] as the second parameter
+ target = 'TARGET_TD_FPGA' #'TARGET_TD' # self._xml_report_values[self._XML_REPORT_FILE_TYPE_KEY_NAME]
+ target = SWUpdateTargets[target].value
+ #print(self._decode_data_status[self._DECODED_BYTES_KEY_NAME])
+ if send_ack_status == CanCommStatus.CAN_COMM_NOT_STARTED.value:
+ if self._xml_report_values[self._XML_REPORT_FILE_TYPE_KEY_NAME] != '':
+ self._utilities.send_command_msg(SWUpdateCommands.SW_UPDATE_START.value, target)
+ # TODO change the target right now they do not match because they are written for Leahi
+ # CanCommStatus.CAN_COMM_SUCCESSFUL.value: # TODO this should be changed to successful but the ack is not received now yet
+ elif send_ack_status == 2 and self._decode_data_status[self._BINARY_SEND_COMPLETE_KEY_NAME] is False:
+ if update_ack_status == CanCommStatus.CAN_COMM_NOT_STARTED.value or \
+ update_ack_status == 2: #CanCommStatus.CAN_COMM_SUCCESSFUL.value):
+ current_write_index = self._decode_data_status[self._TOTAL_BYTES_TX_KEY_NAME]
+ current_insert_index = self._decode_data_status[self._CUR_DATA_INDEX_KEY_NAME]
+ binary_size = self._xml_report_values[self._XML_REPORT_BIN_SIZE_KEY_NAME]
+ var = ''
+ data_2_write = ''
+ if current_write_index == binary_size:
+ self._decode_data_status[self._BINARY_SEND_COMPLETE_KEY_NAME] = True
+
+ if current_insert_index - current_write_index >= self.SW_UPDATE_FLASH_BUFFER_SIZE:
+ data_2_write = self._decode_data_status[self._DECODED_BYTES_KEY_NAME] \
+ [current_write_index: current_write_index + self.SW_UPDATE_FLASH_BUFFER_SIZE]
+ self._decode_data_status[self._TOTAL_BYTES_TX_KEY_NAME] += self.SW_UPDATE_FLASH_BUFFER_SIZE
+ self._utilities.send_software_update_msg(target, data_2_write, self.SW_UPDATE_FLASH_BUFFER_SIZE)
+ var = 'A'
+ elif current_insert_index == binary_size and \
+ self._decode_data_status[self._BINARY_SEND_COMPLETE_KEY_NAME] is False:
+ remaining_bytes = current_insert_index - current_write_index
+ data_2_write = self._decode_data_status[self._DECODED_BYTES_KEY_NAME] \
+ [current_write_index: current_insert_index]
+ data_2_write += [0] * (self.SW_UPDATE_FLASH_BUFFER_SIZE - remaining_bytes)
+ self._decode_data_status[self._TOTAL_BYTES_TX_KEY_NAME] += remaining_bytes
+ self._utilities.send_software_update_msg(target, data_2_write, remaining_bytes)
+ var = 'B'
+ print(current_write_index, self._decode_data_status[self._CUR_DATA_INDEX_KEY_NAME],
+ current_insert_index - current_write_index, var, len(data_2_write))
+
+ elif update_ack_status == 2 and self._decode_data_status[self._BINARY_SEND_COMPLETE_KEY_NAME] is True: #CanCommStatus.CAN_COMM_SUCCESSFUL.value: # TODO this should be changed to successful but the ack is not received now yet
+ # TODO do we need the electronic signature from xml?
+ data_2_write = [0] * self.SW_UPDATE_FLASH_BUFFER_SIZE
+ self._utilities.send_software_update_msg(target, data_2_write, self.SW_UPDATE_FLASH_BUFFER_SIZE, signature_msg=True)
+
+ if self._utilities.get_msg_ack_nack_status(self._utilities.UPDATE_MSG_ACK_STATUS_KEY_NAME) == 2: #TODO change to successful
+ self._decode_data_status[self._SIG_MSG_SEND_COMPLETE_KEY_NAME] = True
+
+ def _process_remaining_data(self):
+
+ while True:
+ self._handle_processed_data()
+
+ if self._decode_data_status[self._SIG_MSG_SEND_COMPLETE_KEY_NAME] is True:
+ break
+
+ # TODO change the target right now they do not match because they are written for Leahi
+ # TODO for instance, it should be self._xml_report_values[self._XML_REPORT_FILE_TYPE_KEY_NAME] as the second parameter
+ target = 'TARGET_TD_FPGA' #'TARGET_TD' # self._xml_report_values[self._XML_REPORT_FILE_TYPE_KEY_NAME]
+ target = SWUpdateTargets[target].value
+ self._utilities.send_command_msg(SWUpdateCommands.SW_UPDATE_VERIFY.value, target)
+ # TODO change the target right now they do not match because they are written for Leahi
+
+
def update_software_packages(self, packages_dir: str, stack_to_update: str = None):
# 1. Verify signature
# 2. Verify key
@@ -29,65 +226,25 @@
# 7. Send the entire file
# 8. Show progress
- signature_start_in_bytes = bytes(self.SIGNATURE_START, 'utf-8')
- signature_end_in_bytes = bytes(self.SIGNATURE_END, 'utf-8')
-
for file in os.listdir(packages_dir):
if file.endswith(".bin"):
- signature_line = ''
- xml_report_bytes = bytearray()
- has_signature_been_found = False
- found = 0
with open(os.path.join(packages_dir, file), 'rb') as f:
+ # Get ready for the next binary file
+ self._reset_variables()
for line in f:
- if signature_start_in_bytes in line:
- if signature_end_in_bytes in line:
- signature_line = line[len(signature_start_in_bytes):line.find(signature_end_in_bytes)]
- xml_start = line[line.find(signature_end_in_bytes) + len(signature_end_in_bytes):]
- print((xml_start[0]), [hex(j) for j in xml_start], bytearray(xml_start))
- has_signature_been_found = True
- a = int(xml_start[0])
- b = int(xml_start[1])
- code = (a << 8) + b
- print(a, b, code)
- found = 0
- for s in range(0, 0xFF):
- test = ((s % 19) << 8) + (s % 23)
- if code == test:
- print("breaking {} {} {}".format(code, test, s))
- found = s
- break
- xml_list = list()
- for d in range(2,len(xml_start)):
- value = xml_start[d]
- xml_list.append((value - found) % 256)
- found += 211
+ self._process_read_line(line)
+ self._handle_processed_data()
- converted_xml = ''.join(chr(c) for c in xml_list)
+ self._process_remaining_data()
- print(xml_list, converted_xml.replace('\n', ''))
- #test = struct.unpack('c', bytearray(xml_start[:1]))
- #print(test, xml_list[:].decode('utf-8'))
- else:
- pass
- # TODO fill up
- elif has_signature_been_found:
- xml_start = line
- xml_list = list()
- for d in xml_start:
- value = d
- xml_list.append((value - found) % 256)
- found += 211
-
- converted_xml = ''.join(chr(c) for c in xml_list)
-
- print(converted_xml.replace('\n', ''))
-
- if "" in converted_xml:
- print(line)
f.close()
-
-
-
-
\ No newline at end of file
+ # TODO for testing remove
+ print(self._decode_data_status[self._CUR_DATA_INDEX_KEY_NAME],
+ self._decode_data_status[self._DECODED_BYTES_KEY_NAME][0],
+ self._decode_data_status[self._DECODED_BYTES_KEY_NAME][-4],
+ self._decode_data_status[self._DECODED_BYTES_KEY_NAME][-3],
+ self._decode_data_status[self._DECODED_BYTES_KEY_NAME][-2],
+ self._decode_data_status[self._DECODED_BYTES_KEY_NAME][-1],
+ len(self._decode_data_status[self._DECODED_BYTES_KEY_NAME]))
+ # TODO remove
Index: scripts/update_package_script/utilities.py
===================================================================
diff -u
--- scripts/update_package_script/utilities.py (revision 0)
+++ scripts/update_package_script/utilities.py (revision 5b6f3d91478d1da65e094cdb802d6c19ab4385d8)
@@ -0,0 +1,200 @@
+import os.path
+
+import can
+import struct
+from enum import unique
+from time import sleep
+from can.interfaces.socketcan.socketcan import SocketcanBus
+from scripts.base.base import Base, SWUpdateEnum, SWUpdateTargets
+
+@unique
+class SWUpdateCommands(SWUpdateEnum):
+ SW_UPDATE_START = 0
+ SW_UPDATE_ABORT = 1
+ SW_UPDATE_RUN_APP = 2
+ SW_UPDATE_VERIFY = 3
+ NUM_OF_SW_UPDATE_CMDS = 4
+
+class CanCommStatus(SWUpdateEnum):
+ CAN_COMM_NOT_STARTED = 0
+ CAN_COMM_IN_PROGRESS = 1
+ CAN_COMM_SUCCESSFUL = 2
+ CAN_COMM_TIME_OUT = 3
+ NUM_OF_CAN_COMM_STATES = 4
+
+class Utilities(Base):
+
+ _CRC32_TABLE = (
+ 0x00000000, 0x1EDC6F41, 0x3DB8DE82, 0x2364B1C3, 0x7B71BD04, 0x65ADD245, 0x46C96386, 0x58150CC7,
+ 0xF6E37A08, 0xE83F1549, 0xCB5BA48A, 0xD587CBCB, 0x8D92C70C, 0x934EA84D, 0xB02A198E, 0xAEF676CF,
+ 0xF31A9B51, 0xEDC6F410, 0xCEA245D3, 0xD07E2A92, 0x886B2655, 0x96B74914, 0xB5D3F8D7, 0xAB0F9796,
+ 0x05F9E159, 0x1B258E18, 0x38413FDB, 0x269D509A, 0x7E885C5D, 0x6054331C, 0x433082DF, 0x5DECED9E,
+ 0xF8E959E3, 0xE63536A2, 0xC5518761, 0xDB8DE820, 0x8398E4E7, 0x9D448BA6, 0xBE203A65, 0xA0FC5524,
+ 0x0E0A23EB, 0x10D64CAA, 0x33B2FD69, 0x2D6E9228, 0x757B9EEF, 0x6BA7F1AE, 0x48C3406D, 0x561F2F2C,
+ 0x0BF3C2B2, 0x152FADF3, 0x364B1C30, 0x28977371, 0x70827FB6, 0x6E5E10F7, 0x4D3AA134, 0x53E6CE75,
+ 0xFD10B8BA, 0xE3CCD7FB, 0xC0A86638, 0xDE740979, 0x866105BE, 0x98BD6AFF, 0xBBD9DB3C, 0xA505B47D,
+ 0xEF0EDC87, 0xF1D2B3C6, 0xD2B60205, 0xCC6A6D44, 0x947F6183, 0x8AA30EC2, 0xA9C7BF01, 0xB71BD040,
+ 0x19EDA68F, 0x0731C9CE, 0x2455780D, 0x3A89174C, 0x629C1B8B, 0x7C4074CA, 0x5F24C509, 0x41F8AA48,
+ 0x1C1447D6, 0x02C82897, 0x21AC9954, 0x3F70F615, 0x6765FAD2, 0x79B99593, 0x5ADD2450, 0x44014B11,
+ 0xEAF73DDE, 0xF42B529F, 0xD74FE35C, 0xC9938C1D, 0x918680DA, 0x8F5AEF9B, 0xAC3E5E58, 0xB2E23119,
+ 0x17E78564, 0x093BEA25, 0x2A5F5BE6, 0x348334A7, 0x6C963860, 0x724A5721, 0x512EE6E2, 0x4FF289A3,
+ 0xE104FF6C, 0xFFD8902D, 0xDCBC21EE, 0xC2604EAF, 0x9A754268, 0x84A92D29, 0xA7CD9CEA, 0xB911F3AB,
+ 0xE4FD1E35, 0xFA217174, 0xD945C0B7, 0xC799AFF6, 0x9F8CA331, 0x8150CC70, 0xA2347DB3, 0xBCE812F2,
+ 0x121E643D, 0x0CC20B7C, 0x2FA6BABF, 0x317AD5FE, 0x696FD939, 0x77B3B678, 0x54D707BB, 0x4A0B68FA,
+ 0xC0C1D64F, 0xDE1DB90E, 0xFD7908CD, 0xE3A5678C, 0xBBB06B4B, 0xA56C040A, 0x8608B5C9, 0x98D4DA88,
+ 0x3622AC47, 0x28FEC306, 0x0B9A72C5, 0x15461D84, 0x4D531143, 0x538F7E02, 0x70EBCFC1, 0x6E37A080,
+ 0x33DB4D1E, 0x2D07225F, 0x0E63939C, 0x10BFFCDD, 0x48AAF01A, 0x56769F5B, 0x75122E98, 0x6BCE41D9,
+ 0xC5383716, 0xDBE45857, 0xF880E994, 0xE65C86D5, 0xBE498A12, 0xA095E553, 0x83F15490, 0x9D2D3BD1,
+ 0x38288FAC, 0x26F4E0ED, 0x0590512E, 0x1B4C3E6F, 0x435932A8, 0x5D855DE9, 0x7EE1EC2A, 0x603D836B,
+ 0xCECBF5A4, 0xD0179AE5, 0xF3732B26, 0xEDAF4467, 0xB5BA48A0, 0xAB6627E1, 0x88029622, 0x96DEF963,
+ 0xCB3214FD, 0xD5EE7BBC, 0xF68ACA7F, 0xE856A53E, 0xB043A9F9, 0xAE9FC6B8, 0x8DFB777B, 0x9327183A,
+ 0x3DD16EF5, 0x230D01B4, 0x0069B077, 0x1EB5DF36, 0x46A0D3F1, 0x587CBCB0, 0x7B180D73, 0x65C46232,
+ 0x2FCF0AC8, 0x31136589, 0x1277D44A, 0x0CABBB0B, 0x54BEB7CC, 0x4A62D88D, 0x6906694E, 0x77DA060F,
+ 0xD92C70C0, 0xC7F01F81, 0xE494AE42, 0xFA48C103, 0xA25DCDC4, 0xBC81A285, 0x9FE51346, 0x81397C07,
+ 0xDCD59199, 0xC209FED8, 0xE16D4F1B, 0xFFB1205A, 0xA7A42C9D, 0xB97843DC, 0x9A1CF21F, 0x84C09D5E,
+ 0x2A36EB91, 0x34EA84D0, 0x178E3513, 0x09525A52, 0x51475695, 0x4F9B39D4, 0x6CFF8817, 0x7223E756,
+ 0xD726532B, 0xC9FA3C6A, 0xEA9E8DA9, 0xF442E2E8, 0xAC57EE2F, 0xB28B816E, 0x91EF30AD, 0x8F335FEC,
+ 0x21C52923, 0x3F194662, 0x1C7DF7A1, 0x02A198E0, 0x5AB49427, 0x4468FB66, 0x670C4AA5, 0x79D025E4,
+ 0x243CC87A, 0x3AE0A73B, 0x198416F8, 0x075879B9, 0x5F4D757E, 0x41911A3F, 0x62F5ABFC, 0x7C29C4BD,
+ 0xD2DFB272, 0xCC03DD33, 0xEF676CF0, 0xF1BB03B1, 0xA9AE0F76, 0xB7726037, 0x9416D1F4, 0x8ACABEB5,
+ )
+
+ _SHIFT_8_BITS_FOR_BYTE_SHIFT = 8
+ _SHIFT_24_BITS = 24
+ _SHIFT_BITS_BY_A_NIBBLE = 4
+
+ _NUM_OF_BYTES_PER_CAN_FRAME = 8
+ _CAN_INTERFACE = "can0"
+ _SEND_CMD_MAIL_BOX = 0x601
+ _RESP_CMD_MAIL_BOX = 0x606
+ _MIN_CAN_WAIT_FOR_RESP_S = 0.5
+
+ SEND_MSG_ACK_STATUS_KEY_NAME = 'cmd'
+ UPDATE_MSG_ACK_STATUS_KEY_NAME = 'update'
+
+ def __init__(self):
+
+ super().__init__()
+ self._can_bus = SocketcanBus(channel=self._CAN_INTERFACE)
+ self._msg_id_count = 0
+ self._msg_sw_update_index = 0
+ self._update_mail_boxes = self._prepare_update_mail_boxes()
+ self._msg_ack_nack_status = dict()
+ self._total_msg_count = 0
+
+ self._msg_ack_nack_status[self.SEND_MSG_ACK_STATUS_KEY_NAME] = CanCommStatus.CAN_COMM_NOT_STARTED.value
+ self._msg_ack_nack_status[self.UPDATE_MSG_ACK_STATUS_KEY_NAME] = CanCommStatus.CAN_COMM_NOT_STARTED.value
+
+ self.file_handle = open(os.path.join(os.getcwd(), 'ack_log.log'), 'w')
+
+ def get_msg_ack_nack_status(self, msg_type: str):
+ return self._msg_ack_nack_status[msg_type]
+
+ def clear_msg_ack_nack_status(self, msg_type: str):
+ self._msg_ack_nack_status[msg_type] = CanCommStatus.CAN_COMM_NOT_STARTED.value
+
+ def send_command_msg(self, cmd: int, target: int):
+
+ self._msg_id_count = self._msg_id_count + 1 if self._msg_id_count < 0xFF else 0
+ can_msg_bytes = self._convert_data_to_bytes(' 0:
+ left = (crc << cls._SHIFT_8_BITS_FOR_BYTE_SHIFT) & 0xFFFFFFFF
+ right = (crc >> cls._SHIFT_24_BITS) & 0xFFFFFFFF
+ crc = left ^ cls._CRC32_TABLE[data[i] ^ right]
+ i += 1
+ length -= 1
+
+ return crc
+
+ @staticmethod
+ def _prepare_update_mail_boxes():
+
+ temp = dict()
+ temp[SWUpdateTargets.TARGET_TD.value] = (0x602, 0.5)
+ temp[SWUpdateTargets.TARGET_TD_FPGA.value] = (0x602, 0.5) # TODO add more timeout for FPGAs
+ temp[SWUpdateTargets.TARGET_DD.value] = (0x603, 0.5)
+ temp[SWUpdateTargets.TARGET_DD_FPGA.value] = (0x603, 0.5)
+ temp[SWUpdateTargets.TARGET_RO.value] = (0x604, 0.5)
+ temp[SWUpdateTargets.TARGET_RO_FPGA.value] = (0x604, 0.5)
+
+ return temp
+
+ @staticmethod
+ def _convert_data_to_bytes(conversion: str, data: int):
+ return struct.pack(conversion, data)
+
+ def _send_can_message(self, mail_box: int, data: bytes, msg_type: str, wait_for_resp_s: float = 0.0):
+
+ self._msg_ack_nack_status[msg_type] = CanCommStatus.CAN_COMM_IN_PROGRESS.value
+ packet = can.Message(arbitration_id=mail_box, data=data, is_extended_id=False)
+ self._can_bus.send(packet, 0)
+
+ #sleep(0.2)
+ #self._msg_ack_nack_status[msg_type] = CanCommStatus.CAN_COMM_SUCCESSFUL.value
+ #if wait_for_resp_s >= self._MIN_CAN_WAIT_FOR_RESP_S:
+ # message = self._can_bus.recv(wait_for_resp_s) #TODO is this good? change it
+ # self._msg_ack_nack_status[msg_type] = CanCommStatus.CAN_COMM_TIME_OUT.value if message is None \
+ # else CanCommStatus.CAN_COMM_SUCCESSFUL.value
+ #print(message, self._msg_ack_nack_status[msg_type])