def _data_transfer_handler(self, msg): logger.debug("_data_transfer_handler:") msg_source = msg.arbitration_id.source_address pdu_specific = msg.arbitration_id.pgn.pdu_specific if msg_source in self._incomplete_received_pdus: logger.debug("in self._incomplete_received_pdus:") if pdu_specific in self._incomplete_received_pdus[msg_source]: logger.debug("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: logger.debug( "allReceived: %s" % type(self._incomplete_received_pdus[msg_source])) logger.debug("allReceived: %s" % pprint.pformat( self._incomplete_received_pdus[msg_source])) logger.debug( "allReceived: %s from 0x%x" % (type(self._incomplete_received_pdus[msg_source] [pdu_specific]), pdu_specific)) logger.debug("allReceived: %s" % (self._incomplete_received_pdus[msg_source] [pdu_specific])) if pdu_specific == DESTINATION_ADDRESS_GLOBAL: logger.debug( "pdu_specific == 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 # TODO: Was self.j1939_notifier.listeners send_ack = any( True for (_listener, l_notifier) in self.node_queue_list if isinstance(_listener, Node) and ( _listener.address == pdu_specific or pdu_specific in _listener.address_list)) #send_ack = any(True for l in self.can_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 = PGN_TP_CONNECTION_MANAGEMENT arbitration_id.pgn.pdu_specific = msg_source arbitration_id.source_address = pdu_specific arbitration_id.destination_address = 0x17 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 logger.debug( "in send_ack: arbitration_id=[%s], can_id=[%x], destAdder=0x%0x" % (arbitration_id, int(arbitration_id.can_id), arbitration_id.destination_address)) logger.debug("in send_ack: " % ()) div, mod = divmod(total_length, 256) can_message = Message( arbitration_id=arbitration_id.can_id, extended_id=True, dlc=8, data=[ CM_MSG_TYPE_EOM_ACK, mod, # total_length % 256, div, # total_length / 256, _num_packages, 0xFF, _pgn_lsb, _pgn_middle, pgn_msb ]) try: self.can_bus.send(can_message) except CanError: if self._ignore_can_send_error: pass raise logger.debug("_data_transfer_handler: returning %s" % (msg)) return self._process_eom_ack(msg)
def _process_rts(self, msg): logger.debug("process_rts, source=0x%x" % (msg.arbitration_id.source_address)) 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] == CM_MSG_TYPE_BAM: logger.debug("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: logger.debug("not CM_MSG_TYPE_BAM, source=0x%x" % (msg.arbitration_id.source_address)) 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] != CM_MSG_TYPE_BAM: logger.debug("not CM_MSG_TYPE_BAM--2") logger.debug("self.can_notifier.listeners = %s" % self.can_notifier.listeners) logger.debug("self.node_queue_list = %s" % self.node_queue_list) #for _listener in self.can_notifier.listeners: for (_listener, l_notifier) in self.node_queue_list: logger.debug("MIL2: _listner/l_notifier = %s/%s" % (_listener, l_notifier)) if isinstance(_listener, Node): logger.debug("6, dest=0x%x" % (msg.arbitration_id.source_address)) # 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 logger.debug("MIL3: Node: %s" % (Node)) logger.debug("MIL3: _listener.address: %s" % (_listener.address)) logger.debug( "MIL3: msg.arbitration_id.pgn.pdu_specific: %s" % (msg.arbitration_id.pgn.pdu_specific)) logger.debug("MIL3: _listener.address_list: %s" % (_listener.address_list)) 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 = PGN_TP_CONNECTION_MANAGEMENT _cts_arbitration_id.pgn.pdu_specific = msg.arbitration_id.source_address _cts_arbitration_id.destination_address = msg.arbitration_id.source_address _data = [0x11, msg.data[4], 0x01, 0xFF, 0xFF] _data.extend(msg.data[5:]) logger.debug("send CTS: AID: %s" % _cts_arbitration_id) cts_msg = Message( extended_id=True, arbitration_id=_cts_arbitration_id.can_id, data=_data, dlc=8) # send clear to send logger.debug("send CTS: %s" % cts_msg) try: self.can_bus.send(cts_msg) except CanError: if self._ignore_can_send_error: pass raise return
def send(self, msg, timeout=None): logger.info("j1939.send: msg=%s" % msg) messages = [] if len(msg.data) > 8: logger.info("j1939.send: message is > than 8 bytes") # 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) logger.info("j1939.send: Copied msg = %s" % pdu) pdu_length_lsb, pdu_length_msb = divmod(len(pdu.data), 256) while len(pdu.data) % 7 != 0: pdu.data += b'\xFF' logger.info("j1939.send: padded msg (mod 7) = %s" % pdu) logger.info("MIL8:---------------------") # # segment the longer message into 7 byte segments. We need to prefix each # data[0] with a sequence number for the transfer # for i, segment in enumerate(pdu.data_segments(segment_length=7)): arbitration_id = copy.deepcopy(pdu.arbitration_id) arbitration_id.pgn.value = PGN_TP_DATA_TRANSFER logger.info( "MIL8: j1939.send: i=%d, pdu.arbitration_id.pgn.is_destination_specific=%d, data=%s" % (i, pdu.arbitration_id.pgn.is_destination_specific, segment)) if pdu.arbitration_id.pgn.is_destination_specific and \ pdu.arbitration_id.destination_address != DESTINATION_ADDRESS_GLOBAL: arbitration_id.pgn.pdu_specific = pdu.arbitration_id.pgn.pdu_specific else: arbitration_id.pgn.pdu_specific = DESTINATION_ADDRESS_GLOBAL arbitration_id.destination_address = DESTINATION_ADDRESS_GLOBAL logger.info("MIL8: j1939.send: segment=%d, arb = %s" % (i, arbitration_id)) message = Message(arbitration_id=arbitration_id.can_id, extended_id=True, dlc=(len(segment) + 1), data=(bytearray([i + 1]) + segment)) messages.append(message) # # At this point we have the queued messages sequenced in 'messages' # logger.info( "MIL8: j1939.send: is_destination_specific=%d, destAddr=%s" % (pdu.arbitration_id.pgn.is_destination_specific, pdu.arbitration_id.destination_address)) logger.info("MIL8: j1939.send: messages=%s" % messages) if pdu.arbitration_id.pgn.is_destination_specific and \ pdu.arbitration_id.destination_address != 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] = {} # append the messages to the 'incomplete' list self._incomplete_transmitted_pdus[ pdu.arbitration_id. source_address][destination_address] = messages else: destination_address = DESTINATION_ADDRESS_GLOBAL logger.debug("MIL8: rts arbitration id: src=%s, dest=%s" % (pdu.source, destination_address)) rts_arbitration_id = ArbitrationID( pgn=PGN_TP_CONNECTION_MANAGEMENT, source_address=pdu.source, destination_address=destination_address) 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 != DESTINATION_ADDRESS_GLOBAL: # send request to send logger.debug("MIL8: rts to specific dest: src=%s, dest=%s" % (pdu.source, destination_address)) rts_msg = Message(extended_id=True, arbitration_id=rts_arbitration_id.can_id, data=[ CM_MSG_TYPE_RTS, pdu_length_msb, pdu_length_lsb, len(messages), 0xFF, pgn_lsb, pgn_middle, pgn_msb ], dlc=8) try: logger.info("MIL08: j1939.send: sending TP.RTS to %s: %s" % (destination_address, rts_msg)) self.can_bus.send(rts_msg) except CanError: if self._ignore_can_send_error: pass raise else: rts_arbitration_id.pgn.pdu_specific = DESTINATION_ADDRESS_GLOBAL rts_arbitration_id.destination_address = DESTINATION_ADDRESS_GLOBAL logger.debug("MIL8: rts to Global dest: src=%s, dest=%s" % (pdu.source, destination_address)) bam_msg = Message( extended_id=True, arbitration_id=rts_arbitration_id.can_id | pdu.source, data=[ CM_MSG_TYPE_BAM, pdu_length_msb, pdu_length_lsb, len(messages), 0xFF, pgn_lsb, pgn_middle, pgn_msb ], dlc=8) bam_msg.destination_address = DESTINATION_ADDRESS_GLOBAL # bam_msg.arbitration_id.destination_address = DESTINATION_ADDRESS_GLOBAL # send BAM try: logger.info("j1939.send: sending TP.BAM to %s: %s" % (destination_address, bam_msg)) self.can_bus.send(bam_msg) time.sleep(0.05) except CanError: if self._ignore_can_send_error: pass raise for message in messages: # send data messages - no flow control, so no need to wait # for receiving devices to acknowledge logger.info("j1939.send: queue TP.BAM data to %s: %s" % (destination_address, message)) self._long_message_segment_queue.put_nowait(message) else: msg.display_radix = 'hex' logger.debug("j1939.send: calling can_bus_send: j1939-msg: %s" % (msg)) can_message = Message(arbitration_id=msg.arbitration_id.can_id, extended_id=True, dlc=len(msg.data), data=msg.data) logger.debug("j1939.send: calling can_bus_send: can-msg: %s" % can_message) try: self.can_bus.send(can_message) except CanError: if self._ignore_can_send_error: pass raise