def _data_transfer_handler(self, msg): msg_source = msg.arbitration_id.source_address pdu_specific = msg.arbitration_id.pgn.pdu_specific if msg_source in self._incomplete_received_pdus: if pdu_specific in self._incomplete_received_pdus[msg_source]: self._incomplete_received_pdus[msg_source][ pdu_specific].data.extend(msg.data[1:]) total = self._incomplete_received_pdu_lengths[msg_source][ pdu_specific]["total"] if len(self._incomplete_received_pdus[msg_source] [pdu_specific].data) >= total: if pdu_specific == constants.DESTINATION_ADDRESS_GLOBAL: # Looks strange but makes sense - in the absence of explicit flow control, # the last CAN packet in a long message *is* the end of message acknowledgement return self._process_eom_ack(msg) # Find a Node object so we can search its list of known node addresses for this node # so we can find if we are responsible for sending the EOM ACK message send_ack = any(True for l in self.j1939_notifier.listeners if isinstance(l, Node) and ( l.address == pdu_specific or pdu_specific in l.address_list)) if send_ack: arbitration_id = ArbitrationID() arbitration_id.pgn.value = constants.PGN_TP_CONNECTION_MANAGEMENT arbitration_id.pgn.pdu_specific = msg_source arbitration_id.source_address = pdu_specific total_length = self._incomplete_received_pdu_lengths[ msg_source][pdu_specific]["total"] _num_packages = self._incomplete_received_pdu_lengths[ msg_source][pdu_specific]["num_packages"] pgn = self._incomplete_received_pdus[msg_source][ pdu_specific].arbitration_id.pgn pgn_msb = ((pgn.value & 0xFF0000) >> 16) _pgn_middle = ((pgn.value & 0x00FF00) >> 8) _pgn_lsb = 0 div, mod = divmod(total_length, 256) can_message = Message( arbitration_id=arbitration_id.can_id, extended_id=True, dlc=8, data=[ constants.CM_MSG_TYPE_EOM_ACK, mod, # total_length % 256, div, # total_length / 256, _num_packages, 0xFF, _pgn_lsb, _pgn_middle, pgn_msb ]) self.can_bus.send(can_message) return self._process_eom_ack(msg)
def test_simple_periodic_send(): print("Trying to send a message...") msg = Message(arbitration_id=0x0cf02200, data=[0, 1, 3, 1, 4, 1]) task = can.send_periodic('vcan0', msg, 0.020) time.sleep(2) print("Trying to change data") msg.data[0] = 99 task.modify_data(msg) time.sleep(2) task.stop() print("stopped cyclic send") time.sleep(1) task.start() print("starting again") time.sleep(1) print("done")
def test_dual_rate_periodic_send(): """Send a message 10 times at 1ms intervals, then continue to send every 500ms""" msg = Message(arbitration_id=0x0c112200, data=[0, 1, 2, 3, 4, 5]) print("Creating cyclic task to send message 10 times at 1ms, then every 500ms") task = MultiRateCyclicSendTask('vcan0', msg, 10, 0.001, 0.50) time.sleep(2) print("Changing data[0] = 0x42") msg.data[0] = 0x42 task.modify_data(msg) time.sleep(2) task.stop() print("stopped cyclic send") time.sleep(2) task.start() print("starting again") time.sleep(2) print("done")
def test_dual_rate_periodic_send(): """Send a message 10 times at 1ms intervals, then continue to send every 500ms""" msg = Message(arbitration_id=0x0c112200, data=[0, 1, 2, 3, 4, 5]) print( "Creating cyclic task to send message 10 times at 1ms, then every 500ms" ) task = MultiRateCyclicSendTask('vcan0', msg, 10, 0.001, 0.50) time.sleep(2) print("Changing data[0] = 0x42") msg.data[0] = 0x42 task.modify_data(msg) time.sleep(2) task.stop() print("stopped cyclic send") time.sleep(2) task.start() print("starting again") time.sleep(2) print("done")
def _process_rts(self, msg): if msg.arbitration_id.source_address not in self._incomplete_received_pdus: self._incomplete_received_pdus[ msg.arbitration_id.source_address] = {} self._incomplete_received_pdu_lengths[ msg.arbitration_id.source_address] = {} # Delete any previous messages that were not finished correctly if msg.arbitration_id.pgn.pdu_specific in self._incomplete_received_pdus[ msg.arbitration_id.source_address]: del self._incomplete_received_pdus[ msg.arbitration_id.source_address][ msg.arbitration_id.pgn.pdu_specific] del self._incomplete_received_pdu_lengths[ msg.arbitration_id.source_address][ msg.arbitration_id.pgn.pdu_specific] if msg.data[0] == constants.CM_MSG_TYPE_BAM: self._incomplete_received_pdus[ msg.arbitration_id.source_address][0xFF] = self._pdu_type() self._incomplete_received_pdus[msg.arbitration_id.source_address][ 0xFF].arbitration_id.pgn.value = int( ("%.2X%.2X%.2X" % (msg.data[7], msg.data[6], msg.data[5])), 16) if self._incomplete_received_pdus[ msg.arbitration_id.source_address][ 0xFF].arbitration_id.pgn.is_destination_specific: self._incomplete_received_pdus[msg.arbitration_id.source_address][ 0xFF].arbitration_id.pgn.pdu_specific = msg.arbitration_id.pgn.pdu_specific self._incomplete_received_pdus[msg.arbitration_id.source_address][ 0xFF].arbitration_id.source_address = msg.arbitration_id.source_address self._incomplete_received_pdus[ msg.arbitration_id.source_address][0xFF].data = [] _message_size = int("%.2X%.2X" % (msg.data[2], msg.data[1]), 16) self._incomplete_received_pdu_lengths[ msg.arbitration_id.source_address][0xFF] = { "total": _message_size, "chunk": 255, "num_packages": msg.data[3], } else: self._incomplete_received_pdus[msg.arbitration_id.source_address][ msg.arbitration_id.pgn.pdu_specific] = self._pdu_type() self._incomplete_received_pdus[msg.arbitration_id.source_address][ msg.arbitration_id.pgn. pdu_specific].arbitration_id.pgn.value = int( ("%.2X%.2X%.2X" % (msg.data[7], msg.data[6], msg.data[5])), 16) if self._incomplete_received_pdus[msg.arbitration_id.source_address][ msg.arbitration_id.pgn. pdu_specific].arbitration_id.pgn.is_destination_specific: self._incomplete_received_pdus[msg.arbitration_id.source_address][ msg.arbitration_id.pgn. pdu_specific].arbitration_id.pgn.pdu_specific = msg.arbitration_id.pgn.pdu_specific self._incomplete_received_pdus[msg.arbitration_id.source_address][ msg.arbitration_id.pgn. pdu_specific].arbitration_id.source_address = msg.arbitration_id.source_address self._incomplete_received_pdus[msg.arbitration_id.source_address][ msg.arbitration_id.pgn.pdu_specific].data = [] _message_size = int("%.2X%.2X" % (msg.data[2], msg.data[1]), 16) self._incomplete_received_pdu_lengths[ msg.arbitration_id.source_address][ msg.arbitration_id.pgn.pdu_specific] = { "total": _message_size, "chunk": 255, "num_packages": msg.data[3], } if msg.data[0] != constants.CM_MSG_TYPE_BAM: for _listener in self.j1939_notifier.listeners: if isinstance(_listener, Node): # find a Node object so we can search its list of known node addresses # for this node - if we find it we are responsible for sending the CTS message if _listener.address == msg.arbitration_id.pgn.pdu_specific or msg.arbitration_id.pgn.pdu_specific in _listener.address_list: _cts_arbitration_id = ArbitrationID( source_address=msg.arbitration_id.pgn.pdu_specific) _cts_arbitration_id.pgn.value = constants.PGN_TP_CONNECTION_MANAGEMENT _cts_arbitration_id.pgn.pdu_specific = msg.arbitration_id.source_address _data = [0x11, msg.data[4], 0x01, 0xFF, 0xFF] _data.extend(msg.data[5:]) cts_msg = Message( extended_id=True, arbitration_id=_cts_arbitration_id.can_id, data=_data, dlc=8) # send clear to send self.can_bus.send(cts_msg) return
def send(self, msg): messages = [] if len(msg.data) > 8: # Making a copy of the PDU so that the original # is not altered by the data padding. pdu = copy.deepcopy(msg) pdu.data = bytearray(pdu.data) pdu_length_lsb, pdu_length_msb = divmod(len(pdu.data), 256) while len(pdu.data) % 7 != 0: pdu.data += b'\xFF' for i, segment in enumerate(pdu.data_segments(segment_length=7)): arbitration_id = copy.deepcopy(pdu.arbitration_id) arbitration_id.pgn.value = constants.PGN_TP_DATA_TRANSFER if pdu.arbitration_id.pgn.is_destination_specific and \ pdu.arbitration_id.destination_address != constants.DESTINATION_ADDRESS_GLOBAL: arbitration_id.pgn.pdu_specific = pdu.arbitration_id.pgn.pdu_specific else: arbitration_id.pgn.pdu_specific = constants.DESTINATION_ADDRESS_GLOBAL message = Message(arbitration_id=arbitration_id.can_id, extended_id=True, dlc=(len(segment) + 1), data=(bytearray([i + 1]) + segment)) messages.append(message) if pdu.arbitration_id.pgn.is_destination_specific and \ pdu.arbitration_id.destination_address != constants.DESTINATION_ADDRESS_GLOBAL: destination_address = pdu.arbitration_id.pgn.pdu_specific if pdu.arbitration_id.source_address in self._incomplete_transmitted_pdus: if destination_address in self._incomplete_transmitted_pdus[ pdu.arbitration_id.source_address]: logger.warning( "Duplicate transmission of PDU:\n{}".format(pdu)) else: self._incomplete_transmitted_pdus[ pdu.arbitration_id.source_address] = {} self._incomplete_transmitted_pdus[ pdu.arbitration_id. source_address][destination_address] = messages else: destination_address = constants.DESTINATION_ADDRESS_GLOBAL rts_arbitration_id = ArbitrationID(source_address=pdu.source) rts_arbitration_id.pgn.value = constants.PGN_TP_CONNECTION_MANAGEMENT rts_arbitration_id.pgn.pdu_specific = pdu.arbitration_id.pgn.pdu_specific temp_pgn = copy.deepcopy(pdu.arbitration_id.pgn) if temp_pgn.is_destination_specific: temp_pgn.value -= temp_pgn.pdu_specific pgn_msb = ((temp_pgn.value & 0xFF0000) >> 16) pgn_middle = ((temp_pgn.value & 0x00FF00) >> 8) pgn_lsb = (temp_pgn.value & 0x0000FF) if pdu.arbitration_id.pgn.is_destination_specific and \ pdu.arbitration_id.destination_address != constants.DESTINATION_ADDRESS_GLOBAL: # send request to send rts_msg = Message(extended_id=True, arbitration_id=rts_arbitration_id.can_id, data=[ constants.CM_MSG_TYPE_RTS, pdu_length_msb, pdu_length_lsb, len(messages), 0xFF, pgn_lsb, pgn_middle, pgn_msb ], dlc=8) self.can_bus.send(rts_msg) else: rts_arbitration_id.pgn.pdu_specific = constants.DESTINATION_ADDRESS_GLOBAL bam_msg = Message(extended_id=True, arbitration_id=rts_arbitration_id.can_id, data=[ constants.CM_MSG_TYPE_BAM, pdu_length_msb, pdu_length_lsb, len(messages), 0xFF, pgn_lsb, pgn_middle, pgn_msb ], dlc=8) # send BAM self.can_bus.send(bam_msg) for message in messages: # send data messages - no flow control, so no need to wait # for receiving devices to acknowledge self._long_message_segment_queue.put_nowait(message) else: can_message = Message(arbitration_id=msg.arbitration_id.can_id, extended_id=True, dlc=len(msg.data), data=msg.data) self.can_bus.send(can_message)