Index: DialityCoreCanProtocol.py =================================================================== diff -u -rb37f31a2923b1795a8d9c5095eafadab8d7c6354 -rd1a60e7570580cb962c8031394e04c3995a73057 --- DialityCoreCanProtocol.py (.../DialityCoreCanProtocol.py) (revision b37f31a2923b1795a8d9c5095eafadab8d7c6354) +++ DialityCoreCanProtocol.py (.../DialityCoreCanProtocol.py) (revision d1a60e7570580cb962c8031394e04c3995a73057) @@ -19,6 +19,7 @@ import can import math from time import sleep +import sys class DenaliMessage: @@ -87,14 +88,14 @@ if payload is None: payload = [] - message = [DenaliCanMessenger.START_BYTE] + message_list = [DenaliCanMessenger.START_BYTE] if 0 <= message_id <= DenaliMessage.MAX_MSG_ID_NUMBER: # Make sure an unsigned int was passed message_id_in_bytes = message_id.to_bytes(2, byteorder=DenaliMessage.BYTE_ORDER) - message += [message_id_in_bytes[0]] - message += [message_id_in_bytes[1]] + message_list += [message_id_in_bytes[0]] + message_list += [message_id_in_bytes[1]] else: @@ -106,23 +107,28 @@ # if payload is larger than 255 return nothing if payload_length <= DenaliMessage.MAX_NUMBER_OF_PAYLOAD_BYTES: # payload has to be a list - message += [payload_length] + message_list += [payload_length] else: return [] - message += payload + message_list += payload # Because CRC does not include first byte, then we pass a list with out it - message += [DenaliMessage.crc8(message[1:])] + message_list += [DenaliMessage.crc8(message_list[1:])] - message = DenaliMessage.__padMessageWithZeros(message) + message_list = DenaliMessage.__padMessageWithZeros(message_list) - return DenaliMessage.buildBasicMessage(channel_id=channel_id, message=message) + return DenaliMessage.buildBasicMessage(channel_id=channel_id, message=message_list) @staticmethod - def crc8(message): + def crc8(message_list): + """ + returns the calculated crc from a message list + :param message_list: is a list of integer numbers containing the message + :return: integer containing a unsigned byte + """ crc = 0 - for byte in message: + for byte in message_list: unsigned_byte = byte ^ crc crc = DenaliMessage.CRC_LIST[unsigned_byte] @@ -150,6 +156,39 @@ return message @staticmethod + def getCRC(message): + """ + gets the CRC in message + + :param message: Dialin complete message with CRC + + :return: CRC in message + """ + + crc_index = DenaliMessage.PAYLOAD_START_INDEX + DenaliMessage.getPayloadLength(message) + + return message['message'][crc_index] + + @staticmethod + def verifyCRC(message): + """ + verifies message CRC equals calculated message CRC + + :return: TRUE if CRC matches, FALSE otherwise + """ + + if message is None: + return False + else: + message_list = message['message'] + + message_length = DenaliMessage.PAYLOAD_START_INDEX + DenaliMessage.getPayloadLength(message) + calculated_crc = DenaliMessage.crc8(message_list[1:message_length]) + actual_crc = DenaliMessage.getCRC(message) + + return calculated_crc == actual_crc + + @staticmethod def getChannelID(message): """ returns request ID from message @@ -183,7 +222,6 @@ :param message: dictionary with channel_id and message keys :return: a unsigned payload length """ - return message['message'][DenaliMessage.PAYLOAD_LENGTH_INDEX] @staticmethod @@ -311,7 +349,7 @@ self.__longMessageBuilders = {} self.__longMsgChannelIDSet = set() - self.__dialinMessage = None + self.__dialinMessageList = None self.__dialinCommandResponseMessage = None self.__dialinResponseChannelID = -1 @@ -366,12 +404,12 @@ # if we are building a long message, then proceed to push it to the channel dictionary if channel_id in self.__longMsgChannelIDSet: - self.__dialinMessage = self.__longMessageBuilders[channel_id].push(can_data) + self.__dialinMessageList = self.__longMessageBuilders[channel_id].push(can_data) elif can_data[0] == self.START_BYTE and \ message_length <= DenaliMessage.PAYLOAD_LENGTH_FIRST_PACKET: # This is a short packet # This is the first time that we are building a message - self.__dialinMessage = can_data # deliver the packet + self.__dialinMessageList = can_data # deliver the packet elif can_data[0] == self.START_BYTE and \ message_length > DenaliMessage.PAYLOAD_LENGTH_FIRST_PACKET: # Long packet start @@ -380,21 +418,30 @@ if channel_id not in self.__longMessageBuilders.keys(): # if we don't have a builder. Create it! self.__longMessageBuilders[channel_id] = LongDenaliMessageBuilder(can_data) - self.__dialinMessage = None + self.__dialinMessageList = None else: # if we do have a builder. This is the first time - self.__dialinMessage = self.__longMessageBuilders[channel_id].push(can_data, first_packet=True) + self.__dialinMessageList = self.__longMessageBuilders[channel_id].push(can_data, first_packet=True) - # Need to verify CRC at this point - # At this point we have a complete (long or short) Diality Packet - if self.__dialinMessage is not None: + if self.__dialinMessageList is not None: complete_dialin_message = DenaliMessage.buildBasicMessage(channel_id=channel_id, - message=self.__dialinMessage) + message=self.__dialinMessageList) dialin_msg_id = DenaliMessage.getMessageID(complete_dialin_message) dialin_ch_id = DenaliMessage.getChannelID(complete_dialin_message) + # Need to verify CRC at this point + + if DenaliMessage.verifyCRC(complete_dialin_message) is False: + # if verify is False, let's drop (ignore) this message + dialin_ch_id = None + dialin_msg_id = None + sys.stderr.write("Incorrect CRC, received message: {}, crc: {}, calculated crc: {}\n".format( + self.__dialinMessageList, DenaliMessage.getCRC(complete_dialin_message), + DenaliMessage.crc8(self.__dialinMessageList))) + pass + if dialin_ch_id in self.__longMsgChannelIDSet: # We need to remove channel ID from the long message set self.__longMsgChannelIDSet.remove(dialin_ch_id) @@ -413,7 +460,7 @@ self.__sync_response_dictionary[dialin_ch_id][dialin_msg_id](complete_dialin_message) # Done with this message, let's get the next one - self.__dialinMessage = None + self.__dialinMessageList = None else: