Example #1
0
    def test_addr_claim_fixed(self):
        """Test CA Address claim on the bus with fixed address
        This test runs a "Single Address Capable" claim procedure with a fixed
        address of 128.
        """
        self.can_messages = [
            (TestCA.MsgType.CANTX, 0x18EEFF80,
             [83, 54, 201, 130, 83, 82, 214, 135], 0.0),  # Address Claimed
        ]

        name = j1939.Name(arbitrary_address_capable=0,
                          industry_group=j1939.Name.IndustryGroup.Industrial,
                          vehicle_system_instance=2,
                          vehicle_system=155,
                          function=201,
                          function_instance=16,
                          ecu_instance=2,
                          manufacturer_code=666,
                          identity_number=1234567)
        # create new CA on the bus with given NAME and ADDRESS
        new_ca = self.ecu.add_ca(name=name, device_address=128)
        # by starting the CA it announces the given ADDRESS on the bus
        new_ca.start()

        # wait until all messages are processed asynchronously
        while len(self.can_messages) > 0:
            time.sleep(0.500)
        # wait for final processing
        time.sleep(0.500)

        self.assertEqual(new_ca.state,
                         j1939.ControllerApplication.State.NORMAL)
Example #2
0
    def _process_addressclaim(self, mid, data, timestamp):
        """Processes an address claim message

        :param j1939.MessageId mid:
            A MessageId object holding the information extracted from the can_id.
        :param bytearray data:
            The data contained in the can-message.
        :param float timestamp:
            The timestamp the message was received (mostly) in fractions of Epoch-Seconds.
        """
        src_address = mid.source_address
        logger.debug("Received ADDRESS CLAIMED message from source '%d'", src_address)

        # are we awaiting this address claimed message?
        if (0
            or (self._device_address_state == ControllerApplication.State.NORMAL and src_address == self._device_address)
            or (self._device_address_state == ControllerApplication.State.WAIT_VETO and src_address == self._device_address_announced)
            ):

            logger.info("Received ADDRESS CLAIMED message with conflicting address '%d'", src_address)

            contenders_name = j1939.Name(bytes = data)

            if self._name.value > contenders_name.value:
                # we have to release our address and claim another one
                logger.info("We have to release our address '%d' because the contenders name is less than ours", src_address)
                # TODO: are there any state variables we have to care about?
                self._device_address = j1939.ParameterGroupNumber.Address.NULL
                # TODO: maybe we should call an overloadable function here
                if self._name.arbitrary_address_capable == False:
                    # bad luck
                    logger.error("After releasing our address we are configured to stop operation (CANNOT CLAIM)")
                    self._device_address_state = ControllerApplication.State.CANNOT_CLAIM
                    self._device_address = None
                    self._send_address_claimed(j1939.ParameterGroupNumber.Address.NULL) # send CANNOT CLAIM
                else:
                    # TODO: we should check the address range here
                    self._device_address_announced += 1
                    logger.info("Try the next address '%d'", self._device_address_announced)
                    self._send_address_claimed(self._device_address_announced)
                    # TODO: it's not possible to set the VETO-Timeout from here
                    self._device_address_state = ControllerApplication.State.WAIT_VETO

            else:
                # we have higher prio - repeat our claim message
                logger.info("Contender lost the competition - we can keep our address")
                if self._device_address_state == ControllerApplication.State.NORMAL:
                    # we own our address already
                    self._send_address_claimed(self._device_address)
                else:
                    # we are in the middle of the claim-process
                    self._send_address_claimed(self._device_address_announced)
Example #3
0
def main():
    print("Initializing")

    # create the ElectronicControlUnit (one ECU can hold multiple ControllerApplications)
    ecu = j1939.ElectronicControlUnit()

    # Connect to the CAN bus
    # Arguments are passed to python-can's can.interface.Bus() constructor
    # (see https://python-can.readthedocs.io/en/stable/bus.html).
    # ecu.connect(bustype='socketcan', channel='can0')
    # ecu.connect(bustype='kvaser', channel=0, bitrate=250000)
    ecu.connect(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000)
    # ecu.connect(bustype='ixxat', channel=0, bitrate=250000)
    # ecu.connect(bustype='vector', app_name='CANalyzer', channel=0, bitrate=250000)
    # ecu.connect(bustype='nican', channel='CAN0', bitrate=250000)

    # subscribe to all (global) messages on the bus
    ecu.subscribe(on_message)

    # name descriptor for the ca
    CA_NAME = j1939.Name(arbitrary_address_capable=0,
                         industry_group=j1939.Name.IndustryGroup.Industrial,
                         vehicle_system_instance=1,
                         vehicle_system=1,
                         function=1,
                         function_instance=1,
                         ecu_instance=1,
                         manufacturer_code=666,
                         identity_number=1234567)
    ca = j1939.ControllerApplication(CA_NAME, 0xF1)
    # add CA to the ECU
    ecu.add_ca(controller_application=ca)
    # by starting the CA it starts the address claiming procedure on the bus
    ca.start()

    # create the instance of the Dm1 to be able to receive active DTCs
    Dm1_rec = j1939.Dm1(ca)
    # subscribe to DM1-messages on the bus
    Dm1_rec.subscribe(dm1_receive)

    # create the instance of the Dm1 to be able to send active DTCs
    Dm1_snd = j1939.Dm1(ca)
    # start sending Dm1-message from source-id 10
    Dm1_snd.start_send(callback=dm1_before_send)

    time.sleep(120)

    print("Deinitializing")
    ecu.disconnect()
Example #4
0
    def test_addr_claim_arbitrary_veto_lose(self):
        """Test CA Address claim on the bus with arbitrary capability a veto counterpart
        This test runs a "Arbitrary Address Capable" claim procedure with an
        address of 128. A counterpart on the bus declines the address claimed message
        with a veto and we lose our address. Our device should claim the next address
        (129) automatically.
        """
        self.can_messages = [
            (TestCA.MsgType.CANTX, 0x18EEFF80,
             [211, 54, 201, 130, 83, 82, 214,
              135], 0.0),  # Address Claimed 128
            (TestCA.MsgType.CANRX, 0x18EEFF80,
             [83, 54, 111, 130, 83, 82, 214,
              135], 0.0),  # Veto from Counterpart with lower name
            (TestCA.MsgType.CANTX, 0x18EEFF81,
             [211, 54, 201, 130, 83, 82, 214,
              135], 0.0),  # Address Claimed 129
        ]

        name = j1939.Name(arbitrary_address_capable=1,
                          industry_group=j1939.Name.IndustryGroup.Industrial,
                          vehicle_system_instance=2,
                          vehicle_system=155,
                          function=201,
                          function_instance=16,
                          ecu_instance=2,
                          manufacturer_code=666,
                          identity_number=1234567)
        # create new CA on the bus with given NAME and ADDRESS
        new_ca = self.ecu.add_ca(name=name, device_address=128)
        # by starting the CA it announces the given ADDRESS on the bus
        new_ca.start()

        # wait until all messages are processed asynchronously
        while len(self.can_messages) > 0:
            time.sleep(0.500)
        # wait for final processing
        time.sleep(0.500)

        self.assertEqual(new_ca.state,
                         j1939.ControllerApplication.State.NORMAL)
Example #5
0
def main():
    print("Initializing")

    # create the ElectronicControlUnit (one ECU can hold multiple ControllerApplications)
    ecu = j1939.ElectronicControlUnit()

    # Connect to the CAN bus
    # Arguments are passed to python-can's can.interface.Bus() constructor
    # (see https://python-can.readthedocs.io/en/stable/bus.html).
    # ecu.connect(bustype='socketcan', channel='can0')
    # ecu.connect(bustype='kvaser', channel=0, bitrate=250000)
    ecu.connect(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000)
    # ecu.connect(bustype='ixxat', channel=0, bitrate=250000)
    # ecu.connect(bustype='vector', app_name='CANalyzer', channel=0, bitrate=250000)
    # ecu.connect(bustype='nican', channel='CAN0', bitrate=250000)
    # ecu.connect('testchannel_1', bustype='virtual')

    # compose the name descriptor for the new ca
    name = j1939.Name(arbitrary_address_capable=0,
                      industry_group=j1939.Name.IndustryGroup.Industrial,
                      vehicle_system_instance=1,
                      vehicle_system=1,
                      function=1,
                      function_instance=1,
                      ecu_instance=1,
                      manufacturer_code=666,
                      identity_number=1234567)

    # create derived CA with given NAME and ADDRESS
    ca = OwnCaToProduceCyclicMessages(name, 128)
    # add CA to the ECU
    ecu.add_ca(controller_application=ca)
    # by starting the CA it starts the address claiming procedure on the bus
    ca.start()

    time.sleep(120)

    print("Deinitializing")
    ca.stop()
    ecu.disconnect()
Example #6
0
 def __init__(self, cfg, rxqueue, mapper):
     # compose the name descriptor for the new ca
     name = j1939.Name(arbitrary_address_capable=0,
                       industry_group=j1939.Name.IndustryGroup.Industrial,
                       vehicle_system_instance=1,
                       vehicle_system=1,
                       function=1,
                       function_instance=1,
                       ecu_instance=1,
                       manufacturer_code=666,
                       identity_number=1234567)
     device_address_preferred = 128
     # old fashion calling convention for compatibility with Python2
     j1939.ControllerApplication.__init__(self, name,
                                          device_address_preferred)
     # adaptation
     self.queue = rxqueue
     self.cfg = cfg
     self.db = cantools.database.load_file(cfg['vss.dbcfile'])
     self.mapper = mapper
     self.canidwl = self.get_whitelist()
     self.parseErr = 0
import logging
import time
import can
import j1939

logging.getLogger('j1939').setLevel(logging.DEBUG)
logging.getLogger('can').setLevel(logging.DEBUG)

# compose the name descriptor for the new ca
name = j1939.Name(
    arbitrary_address_capable=0, 
    industry_group=j1939.Name.IndustryGroup.Industrial,
    vehicle_system_instance=1,
    vehicle_system=1,
    function=1,
    function_instance=1,
    ecu_instance=1,
    manufacturer_code=666,
    identity_number=1234567
    )

# create the ControllerApplications
ca = j1939.ControllerApplication(name, 128)


def ca_receive(priority, pgn, source, timestamp, data):
    """Feed incoming message to this CA.
    (OVERLOADED function)
    :param int priority:
        Priority of the message
    :param int pgn: