def testStopAfterStart(self): a = ResettableTimer(0.4) a.start() self.assertEqual(True, a.isRunning()) self.assertEqual(False, a.isExpired()) a.stop() self.assertEqual(False, a.isRunning()) self.assertEqual(False, a.isExpired())
def testStateAfterRestart(self): a = ResettableTimer(0.4) a.start() sleep(0.3) a.restart() sleep(0.2) self.assertEqual(True, a.isRunning()) self.assertEqual(False, a.isExpired())
def recv(self, timeout_s): #return self.__connection.recv(... can pass timeout from here if required ...) # .... implemented in the LIN bus impl, so the rest of function replaced by this timeoutTimer = ResettableTimer(timeout_s) payload = [] payloadPtr = 0 payloadLength = None sequenceNumberExpected = 1 endOfMessage_flag = False state = LinTpState.IDLE timeoutTimer.start() while endOfMessage_flag is False: rxPdu = self.getNextBufferedMessage() if rxPdu is not None: N_PCI = (rxPdu[N_PCI_INDEX] & 0xF0) >> 4 if state == LinTpState.IDLE: if N_PCI == LinTpMessageType.SINGLE_FRAME: payloadLength = rxPdu[N_PCI_INDEX & 0x0F] payload = rxPdu[SINGLE_FRAME_DATA_START_INDEX: SINGLE_FRAME_DATA_START_INDEX + payloadLength] endOfMessage_flag = True elif N_PCI == LinTpMessageType.FIRST_FRAME: payload = rxPdu[FIRST_FRAME_DATA_START_INDEX:] payloadLength = ((rxPdu[FIRST_FRAME_DL_INDEX_HIGH] & 0x0F) << 8) + rxPdu[ FIRST_FRAME_DL_INDEX_LOW] payloadPtr = self.__maxPduLength - 1 state = LinTpState.RECEIVING_CONSECUTIVE_FRAME timeoutTimer.restart() elif state == LinTpState.RECEIVING_CONSECUTIVE_FRAME: if N_PCI == LinTpMessageType.CONSECUTIVE_FRAME: sequenceNumber = rxPdu[CONSECUTIVE_FRAME_SEQUENCE_NUMBER_INDEX] & 0x0F if sequenceNumber != sequenceNumberExpected: raise Exception("Consecutive frame sequence out of order") else: sequenceNumberExpected = (sequenceNumberExpected + 1) % 16 payload += rxPdu[CONSECUTIVE_FRAME_SEQUENCE_DATA_START_INDEX:] payloadPtr += (self.__maxPduLength) timeoutTimer.restart() else: raise Exception("Unexpected PDU received") if payloadLength is not None: if payloadPtr >= payloadLength: endOfMessage_flag = True if timeoutTimer.isExpired(): raise Exception("Timeout in waiting for message") return list(payload[:payloadLength])
def testTimerAccuracy(self): testTimes = [1, 0.3, 0.2, 0.1, 0.01, 0.01] for i in testTimes: a = ResettableTimer(i) startTime = perf_counter() a.start() while (a.isRunning()): pass endTime = perf_counter() delta = endTime - startTime self.assertAlmostEqual(delta, i, delta=0.001)
def send(self, payload, functionalReq=False): # TODO: functionalReq not used??? #self.__connection.send(payload) # .... implemented in the LIN bus impl, so the rest of function replaced by this payloadLength = len(payload) if payloadLength > LINTP_MAX_PAYLOAD_LENGTH: raise Exception("Payload too large for CAN Transport Protocol") if payloadLength <= self.__maxPduLength: state = LinTpState.SEND_SINGLE_FRAME else: # we might need a check for functional request as we may not be able to service functional requests for # multi frame requests state = LinTpState.SEND_FIRST_FRAME firstFrameData = payload[0:self.__maxPduLength-1] cfBlocks = self.create_blockList(payload[5:]) sequenceNumber = 1 txPdu = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] endOfMessage_flag = False ## this needs fixing to get the timing from the config timeoutTimer = ResettableTimer(1) stMinTimer = ResettableTimer(self.__STMin) self.clearBufferedMessages() timeoutTimer.start() while endOfMessage_flag is False: rxPdu = self.getNextBufferedMessage() if rxPdu is not None: raise Exception("Unexpected receive frame") if state == LinTpState.SEND_SINGLE_FRAME: txPdu[N_PCI_INDEX] += (LinTpMessageType.SINGLE_FRAME << 4) txPdu[SINGLE_FRAME_DL_INDEX] += payloadLength txPdu[SINGLE_FRAME_DATA_START_INDEX:] = fillArray(payload, self.__maxPduLength) self.transmit(txPdu) endOfMessage_flag = True elif state == LinTpState.SEND_FIRST_FRAME: payloadLength_highNibble = (payloadLength & 0xF00) >> 8 payloadLength_lowNibble = (payloadLength & 0x0FF) txPdu[N_PCI_INDEX] += (LinTpMessageType.FIRST_FRAME << 4) txPdu[FIRST_FRAME_DL_INDEX_HIGH] += payloadLength_highNibble txPdu[FIRST_FRAME_DL_INDEX_LOW] += payloadLength_lowNibble txPdu[FIRST_FRAME_DATA_START_INDEX:] = firstFrameData self.transmit(txPdu) state = LinTpState.SEND_CONSECUTIVE_FRAME stMinTimer.start() timeoutTimer.restart() elif state == LinTpState.SEND_CONSECUTIVE_FRAME: if( stMinTimer.isExpired() and (self.__transmitBuffer is None) ): txPdu[N_PCI_INDEX] += (LinTpMessageType.CONSECUTIVE_FRAME << 4) txPdu[CONSECUTIVE_FRAME_SEQUENCE_NUMBER_INDEX] += sequenceNumber txPdu[CONSECUTIVE_FRAME_SEQUENCE_DATA_START_INDEX:] = cfBlocks.pop(0) self.transmit(txPdu) sequenceNumber = (sequenceNumber + 1) % 16 stMinTimer.restart() timeoutTimer.restart() if len(cfBlocks) == 0: endOfMessage_flag = True txPdu = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] sleep(0.001) if timeoutTimer.isExpired(): raise Exception("Timeout")
def recv(self, timeout_s): timeoutTimer = ResettableTimer(timeout_s) payload = [] payloadPtr = 0 payloadLength = None sequenceNumberExpected = 1 txPdu = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] endOfMessage_flag = False state = CanTpState.IDLE timeoutTimer.start() while endOfMessage_flag is False: rxPdu = self.getNextBufferedMessage() if rxPdu is not None: N_PCI = (rxPdu[N_PCI_INDEX] & 0xF0) >> 4 if state == CanTpState.IDLE: if N_PCI == CanTpMessageType.SINGLE_FRAME: payloadLength = rxPdu[N_PCI_INDEX & 0x0F] payload = rxPdu[SINGLE_FRAME_DATA_START_INDEX: SINGLE_FRAME_DATA_START_INDEX + payloadLength] endOfMessage_flag = True elif N_PCI == CanTpMessageType.FIRST_FRAME: payload = rxPdu[FIRST_FRAME_DATA_START_INDEX:] payloadLength = ( (rxPdu[FIRST_FRAME_DL_INDEX_HIGH] & 0x0F) << 8) + rxPdu[FIRST_FRAME_DL_INDEX_LOW] payloadPtr = self.__maxPduLength - 1 state = CanTpState.SEND_FLOW_CONTROL elif state == CanTpState.RECEIVING_CONSECUTIVE_FRAME: if N_PCI == CanTpMessageType.CONSECUTIVE_FRAME: sequenceNumber = rxPdu[ CONSECUTIVE_FRAME_SEQUENCE_NUMBER_INDEX] & 0x0F if sequenceNumber != sequenceNumberExpected: raise Exception( "Consecutive frame sequence out of order") else: sequenceNumberExpected = (sequenceNumberExpected + 1) % 16 payload += rxPdu[ CONSECUTIVE_FRAME_SEQUENCE_DATA_START_INDEX:] payloadPtr += (self.__maxPduLength) timeoutTimer.restart() else: raise Exception("Unexpected PDU received") if state == CanTpState.SEND_FLOW_CONTROL: txPdu[N_PCI_INDEX] = 0x30 txPdu[FLOW_CONTROL_BS_INDEX] = 0 txPdu[FLOW_CONTROL_STMIN_INDEX] = 0x1E self.transmit(txPdu) state = CanTpState.RECEIVING_CONSECUTIVE_FRAME if payloadLength is not None: if payloadPtr >= payloadLength: endOfMessage_flag = True if timeoutTimer.isExpired(): raise Exception("Timeout in waiting for message") return list(payload[:payloadLength])
def send(self, payload, functionalReq=False): payloadLength = len(payload) payloadPtr = 0 state = CanTpState.IDLE if payloadLength > CANTP_MAX_PAYLOAD_LENGTH: raise Exception("Payload too large for CAN Transport Protocol") if payloadLength < self.__maxPduLength: state = CanTpState.SEND_SINGLE_FRAME else: # we might need a check for functional request as we may not be able to service functional requests for # multi frame requests state = CanTpState.SEND_FIRST_FRAME txPdu = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] sequenceNumber = 1 endOfMessage_flag = False blockList = [] currBlock = [] ## this needs fixing to get the timing from the config timeoutTimer = ResettableTimer(1) stMinTimer = ResettableTimer() self.clearBufferedMessages() while endOfMessage_flag is False: rxPdu = self.getNextBufferedMessage() if rxPdu is not None: N_PCI = (rxPdu[0] & 0xF0) >> 4 if N_PCI == CanTpMessageType.FLOW_CONTROL: fs = rxPdu[0] & 0x0F if fs == CanTpFsTypes.WAIT: raise Exception("Wait not currently supported") elif fs == CanTpFsTypes.OVERFLOW: raise Exception("Overflow received from ECU") elif fs == CanTpFsTypes.CONTINUE_TO_SEND: if state == CanTpState.WAIT_FLOW_CONTROL: if fs == CanTpFsTypes.CONTINUE_TO_SEND: bs = rxPdu[FC_BS_INDEX] if (bs == 0): bs = 585 blockList = self.create_blockList( payload[payloadPtr:], bs) stMin = self.decode_stMin( rxPdu[FC_STMIN_INDEX]) currBlock = blockList.pop(0) state = CanTpState.SEND_CONSECUTIVE_FRAME stMinTimer.timeoutTime = stMin stMinTimer.start() timeoutTimer.stop() else: raise Exception( "Unexpected Flow Control Continue to Send request" ) else: raise Exception("Unexpected fs response from ECU") else: raise Exception("Unexpected response from device") if state == CanTpState.SEND_SINGLE_FRAME: txPdu[N_PCI_INDEX] += (CanTpMessageType.SINGLE_FRAME << 4) txPdu[SINGLE_FRAME_DL_INDEX] += payloadLength txPdu[SINGLE_FRAME_DATA_START_INDEX:] = fillArray( payload, self.__maxPduLength) self.transmit(txPdu, functionalReq) endOfMessage_flag = True elif state == CanTpState.SEND_FIRST_FRAME: payloadLength_highNibble = (payloadLength & 0xF00) >> 8 payloadLength_lowNibble = (payloadLength & 0x0FF) txPdu[N_PCI_INDEX] += (CanTpMessageType.FIRST_FRAME << 4) txPdu[FIRST_FRAME_DL_INDEX_HIGH] += payloadLength_highNibble txPdu[FIRST_FRAME_DL_INDEX_LOW] += payloadLength_lowNibble txPdu[FIRST_FRAME_DATA_START_INDEX:] = payload[0:self. __maxPduLength - 1] payloadPtr += self.__maxPduLength - 1 self.transmit(txPdu, functionalReq) timeoutTimer.start() state = CanTpState.WAIT_FLOW_CONTROL elif state == CanTpState.SEND_CONSECUTIVE_FRAME: if (stMinTimer.isExpired()): txPdu[N_PCI_INDEX] += ( CanTpMessageType.CONSECUTIVE_FRAME << 4) txPdu[ CONSECUTIVE_FRAME_SEQUENCE_NUMBER_INDEX] += sequenceNumber txPdu[ CONSECUTIVE_FRAME_SEQUENCE_DATA_START_INDEX:] = currBlock.pop( 0) payloadPtr += self.__maxPduLength self.transmit(txPdu, functionalReq) sequenceNumber = (sequenceNumber + 1) % 16 stMinTimer.restart() if (len(currBlock) == 0): if (len(blockList) == 0): endOfMessage_flag = True else: timeoutTimer.start() state = CanTpState.WAIT_FLOW_CONTROL #print("waiting for flow control") txPdu = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] # timer / exit condition checks if (timeoutTimer.isExpired()): raise Exception("Timeout waiting for message") sleep(0.001)
def testIsExpiredWith0Time(self): a = ResettableTimer(0) a.start() self.assertEqual(False, a.isRunning()) self.assertEqual(True, a.isExpired())