Esempio n. 1
0
    def notify(self, can_id, data, timestamp):
        """Feed incoming CAN message into this ecu.

        If a custom interface is used, this function must be called for each
        29-bit standard message read from the CAN bus.

        :param int can_id:
            CAN-ID of the message (always 29-bit)
        :param bytearray data:
            Data part of the message (0 - 8 bytes)
        :param float timestamp:
            The timestamp field in a CAN message is a floating point number
            representing when the message was received since the epoch in
            seconds.
            Where possible this will be timestamped in hardware.
        """

        mid = j1939.MessageId(can_id=can_id)
        pgn = j1939.ParameterGroupNumber()
        pgn.from_message_id(mid)

        if pgn.is_pdu2_format:
            # direct broadcast
            self.notify_subscribers(mid.priority, pgn.value,
                                    mid.source_address,
                                    j1939.ParameterGroupNumber.Address.GLOBAL,
                                    timestamp, data)
            return

        # peer to peer
        # pdu_specific is destination Address
        pgn_value = pgn.value & 0x1FF00
        dest_address = pgn.pdu_specific  # may be Address.GLOBAL

        # iterate all CAs to check if we have to handle this destination address
        if dest_address != j1939.ParameterGroupNumber.Address.GLOBAL:
            reject = True
            for ca in self._cas:
                if ca.message_acceptable(dest_address):
                    reject = False
                    break
            if reject == True:
                return

        if pgn_value == j1939.ParameterGroupNumber.PGN.ADDRESSCLAIM:
            for ca in self._cas:
                ca._process_addressclaim(mid, data, timestamp)
        elif pgn_value == j1939.ParameterGroupNumber.PGN.REQUEST:
            for ca in self._cas:
                if ca.message_acceptable(dest_address):
                    ca._process_request(mid, dest_address, data, timestamp)
        elif pgn_value == j1939.ParameterGroupNumber.PGN.TP_CM:
            self._process_tp_cm(mid, dest_address, data, timestamp)
        elif pgn_value == j1939.ParameterGroupNumber.PGN.DATATRANSFER:
            self._process_tp_dt(mid, dest_address, data, timestamp)
        else:
            self.notify_subscribers(mid.priority, pgn_value,
                                    mid.source_address, dest_address,
                                    timestamp, data)
            return
Esempio n. 2
0
 def _send_address_claimed(self, address):
     # TODO: Normally the (initial) address claimed message must not be an auto repeat message.
     #       We have to use a single-shot message instead!
     #       After a (send-)error occurs we have to wait 0..153 msec before repeating.
     pgn = j1939.ParameterGroupNumber(0, 238, j1939.ParameterGroupNumber.Address.GLOBAL)
     mid = j1939.MessageId(priority=6, parameter_group_number=pgn.value, source_address=address)
     data = self._name.bytes
     self._ecu.send_message(mid.can_id, data)
    def send_pgn(self, data_page, pdu_format, pdu_specific, priority,
                 src_address, data):
        pgn = j1939.ParameterGroupNumber(data_page, pdu_format, pdu_specific)
        if len(data) <= 8:
            # send normal message
            mid = j1939.MessageId(priority=priority,
                                  parameter_group_number=pgn.value,
                                  source_address=src_address)
            self.send_message(mid.can_id, data)
        else:
            # init sequence
            buffer_hash = self._buffer_hash(src_address, pdu_specific)
            if buffer_hash in self._snd_buffer:
                # There is already a sequence active for this pair
                return False
            message_size = len(data)
            num_packets = int(message_size /
                              7) if (message_size %
                                     7 == 0) else int(message_size / 7) + 1

            if pdu_specific == j1939.ParameterGroupNumber.Address.GLOBAL:
                # send BAM
                self.send_tp_bam(src_address, priority, pgn.value,
                                 message_size, num_packets)

                # init new buffer for this connection
                self._snd_buffer[buffer_hash] = {
                    "pgn": pgn.value,
                    "priority": priority,
                    "message_size": message_size,
                    "num_packages": num_packets,
                    "data": data,
                    "state": ElectronicControlUnit.SendBufferState.SENDING_BM,
                    "deadline": time.time() + ElectronicControlUnit.Timeout.Tb,
                    'src_address': src_address,
                    'dest_address': pdu_specific,
                    'next_packet_to_send': 0,
                }
            else:
                # send RTS/CTS
                # init new buffer for this connection
                self._snd_buffer[buffer_hash] = {
                    "pgn": pgn.value,
                    "priority": priority,
                    "message_size": message_size,
                    "num_packages": num_packets,
                    "data": data,
                    "state": ElectronicControlUnit.SendBufferState.WAITING_CTS,
                    "deadline": time.time() + ElectronicControlUnit.Timeout.T3,
                    'src_address': src_address,
                    'dest_address': pdu_specific,
                }
                self.send_tp_rts(src_address, pdu_specific, priority,
                                 pgn.value, message_size, num_packets)

            self._job_thread_wakeup()

        return True
    def send_message(self, priority, parameter_group_number, data):
        if self.state != ControllerApplication.State.NORMAL:
            raise RuntimeError(
                "Could not send message unless address claiming has finished")

        mid = j1939.MessageId(priority=priority,
                              parameter_group_number=parameter_group_number,
                              source_address=self._device_address)
        self._ecu.send_message(mid.can_id, data)
 def send_acknowledgement(self, control_byte, group_function_value,
                          address_acknowledged, pgn):
     data = [
         control_byte, group_function_value, 0xFF, 0xFF,
         address_acknowledged, (pgn & 0xFF), ((pgn >> 8) & 0xFF),
         ((pgn >> 16) & 0xFF)
     ]
     mid = j1939.MessageId(priority=6,
                           parameter_group_number=0x00E800,
                           source_address=255)
     self.send_message(mid.can_id, data)
 def send_tp_abort(self, src_address, dest_address, reason, pgn_value):
     pgn = j1939.ParameterGroupNumber(0, 236, dest_address)
     mid = j1939.MessageId(priority=7,
                           parameter_group_number=pgn.value,
                           source_address=src_address)
     data = [
         ElectronicControlUnit.ConnectionMode.ABORT, reason, 0xFF,
         0xFF, 0xFF, pgn_value & 0xFF, (pgn_value >> 8) & 0xFF,
         (pgn_value >> 16) & 0xFF
     ]
     self.send_message(mid.can_id, data)
 def send_tp_rts(self, src_address, dest_address, priority, pgn_value,
                 message_size, num_packets):
     pgn = j1939.ParameterGroupNumber(0, 236, dest_address)
     mid = j1939.MessageId(priority=priority,
                           parameter_group_number=pgn.value,
                           source_address=src_address)
     data = [
         ElectronicControlUnit.ConnectionMode.RTS, message_size & 0xFF,
         (message_size >> 8) & 0xFF, num_packets, 0xFF, pgn_value & 0xFF,
         (pgn_value >> 8) & 0xFF, (pgn_value >> 16) & 0xFF
     ]
     self.send_message(mid.can_id, data)
 def send_tp_dt(self, src_address, dest_address, data):
     pgn = j1939.ParameterGroupNumber(0, 235, dest_address)
     mid = j1939.MessageId(priority=7,
                           parameter_group_number=pgn.value,
                           source_address=src_address)
     self.send_message(mid.can_id, data)
Esempio n. 9
0
    def send_pgn(self, data_page, pdu_format, pdu_specific, priority,
                 src_address, data):
        pgn = j1939.ParameterGroupNumber(data_page, pdu_format, pdu_specific)
        if len(data) <= 8:
            # send normal message
            mid = j1939.MessageId(priority=priority,
                                  parameter_group_number=pgn.value,
                                  source_address=src_address)
            self.send_message(mid.can_id, data)
        else:
            # if the PF is between 0 and 239, the message is destination dependent when pdu_specific != 255
            # if the PF is between 240 and 255, the message can only be broadcast
            if (pdu_specific == j1939.ParameterGroupNumber.Address.GLOBAL
                ) or j1939.ParameterGroupNumber(0, pdu_format,
                                                pdu_specific).is_pdu2_format:
                dest_address = j1939.ParameterGroupNumber.Address.GLOBAL
            else:
                dest_address = pdu_specific

            # init sequence
            # known limitation: only one BAM can be sent in parallel to a destination node
            buffer_hash = self._buffer_hash(src_address, dest_address)
            if buffer_hash in self._snd_buffer:
                # There is already a sequence active for this pair
                return False
            message_size = len(data)
            num_packets = int(message_size /
                              7) if (message_size %
                                     7 == 0) else int(message_size / 7) + 1

            # if the PF is between 240 and 255, the message can only be broadcast
            if dest_address == j1939.ParameterGroupNumber.Address.GLOBAL:
                # send BAM
                self.send_tp_bam(src_address, priority, pgn.value,
                                 message_size, num_packets)

                # init new buffer for this connection
                self._snd_buffer[buffer_hash] = {
                    "pgn": pgn.value,
                    "priority": priority,
                    "message_size": message_size,
                    "num_packages": num_packets,
                    "data": data,
                    "state": ElectronicControlUnit.SendBufferState.SENDING_BM,
                    "deadline": time.time() + ElectronicControlUnit.Timeout.Tb,
                    'src_address': src_address,
                    'dest_address': j1939.ParameterGroupNumber.Address.GLOBAL,
                    'next_packet_to_send': 0,
                }
            else:
                # send RTS/CTS
                pgn.pdu_specific = 0  # this is 0 for peer-to-peer transfer
                # init new buffer for this connection
                self._snd_buffer[buffer_hash] = {
                    "pgn": pgn.value,
                    "priority": priority,
                    "message_size": message_size,
                    "num_packages": num_packets,
                    "data": data,
                    "state": ElectronicControlUnit.SendBufferState.WAITING_CTS,
                    "deadline": time.time() + ElectronicControlUnit.Timeout.T3,
                    'src_address': src_address,
                    'dest_address': pdu_specific,
                }
                self.send_tp_rts(src_address, pdu_specific, priority,
                                 pgn.value, message_size, num_packets)

            self._job_thread_wakeup()

        return True