Пример #1
0
    def test_bootload_lock(self):
        core_communicator = Mock()
        ucan_communicator = UCANCommunicator(
            master_communicator=core_communicator)
        cc_address = '000.000.000.000'
        ucan_address = '000.000.000'

        command = UCANCommandSpec(
            sid=SID.NORMAL_COMMAND,
            instructions=[Instruction(instruction=[0, 0])],
            identifier=AddressField('ucan_address', 3))
        ucan_communicator.do_command(cc_address,
                                     command,
                                     ucan_address, {},
                                     timeout=None)

        command = UCANPalletCommandSpec(identifier=AddressField(
            'ucan_address', 3),
                                        pallet_type=PalletType.MCU_ID_REPLY)
        ucan_communicator.do_command(cc_address,
                                     command,
                                     ucan_address, {},
                                     timeout=None)
        pallet_consumer = ucan_communicator._consumers[cc_address][
            -1]  # Load last consumer

        command = UCANCommandSpec(
            sid=SID.NORMAL_COMMAND,
            instructions=[Instruction(instruction=[0, 0])],
            identifier=AddressField('ucan_address', 3))
        with self.assertRaises(BootloadingException):
            ucan_communicator.do_command(cc_address,
                                         command,
                                         ucan_address, {},
                                         timeout=None)

        command = UCANPalletCommandSpec(identifier=AddressField(
            'ucan_address', 3),
                                        pallet_type=PalletType.MCU_ID_REPLY)
        with self.assertRaises(BootloadingException):
            ucan_communicator.do_command(cc_address,
                                         command,
                                         ucan_address, {},
                                         timeout=None)

        try:
            pallet_consumer.get(0.1)
        except Exception:
            pass  #

        command = UCANCommandSpec(
            sid=SID.NORMAL_COMMAND,
            instructions=[Instruction(instruction=[0, 0])],
            identifier=AddressField('ucan_address', 3))
        ucan_communicator.do_command(cc_address,
                                     command,
                                     ucan_address, {},
                                     timeout=None)
Пример #2
0
 def ucan_tx_transport_message():  # type: () -> CoreCommandSpec
     """ uCAN transport layer packages """
     return CoreCommandSpec(instruction='FM',
                            request_fields=[
                                AddressField('cc_address'),
                                ByteField('nr_can_bytes'),
                                ByteField('sid'),
                                RawByteArrayField('payload', 8)
                            ],
                            response_fields=[AddressField('cc_address')])
Пример #3
0
 def get_ucan_address():  # type: () -> CoreCommandSpec
     """ Receives the uCAN address of a specific uCAN """
     return CoreCommandSpec(instruction='FS',
                            request_fields=[
                                AddressField('cc_address'),
                                LiteralBytesField(1),
                                ByteField('ucan_nr')
                            ],
                            response_fields=[
                                AddressField('cc_address'),
                                PaddingField(2),
                                AddressField('ucan_address', 3)
                            ])
Пример #4
0
 def get_amount_of_ucans():  # type: () -> CoreCommandSpec
     """ Receives amount of uCAN modules """
     return CoreCommandSpec(instruction='FS',
                            request_fields=[
                                AddressField('cc_address'),
                                LiteralBytesField(0),
                                LiteralBytesField(0)
                            ],
                            response_fields=[
                                AddressField('cc_address'),
                                PaddingField(2),
                                ByteField('amount'),
                                PaddingField(2)
                            ])
Пример #5
0
 def set_min_led_brightness():  # type: () -> UCANCommandSpec
     """ Sets the minimum brightness for a uCAN led """
     return UCANCommandSpec(
         sid=SID.NORMAL_COMMAND,
         identifier=AddressField('ucan_address', 3),
         instructions=[Instruction(instruction=[0, 246])],
         request_fields=[[ByteField('brightness')]])
Пример #6
0
    def test_string_parsing(self):
        core_communicator = Mock()
        ucan_communicator = UCANCommunicator(master_communicator=core_communicator)
        cc_address = '000.000.000.000'
        ucan_address = '000.000.000'
        pallet_type = PalletType.MCU_ID_REQUEST  # Not important for this test
        foo = 'XY'  # 2 chars max, otherwise more segments are needed and the test might get too complex

        # Build response-only command
        command = UCANPalletCommandSpec(identifier=AddressField('ucan_address', 3),
                                        pallet_type=pallet_type,
                                        response_fields=[StringField('foo')])
        ucan_communicator.do_command(cc_address, command, ucan_address, {}, timeout=None)
        consumer = ucan_communicator._consumers[cc_address][0]

        # Build and validate fake reply from Core
        payload_segment_1 = bytearray([0, 0, 0, 0, 0, 0, PalletType.MCU_ID_REPLY])
        payload_segment_2 = bytearray([ord(x) for x in '{0}\x00'.format(foo)])
        crc_payload = self._uint32_helper.encode(UCANPalletCommandSpec.calculate_crc(payload_segment_1 + payload_segment_2))
        payload_segment_2 += crc_payload
        ucan_communicator._process_transport_message({'cc_address': cc_address,
                                                      'nr_can_bytes': 8,
                                                      'sid': 1,
                                                      'payload': bytearray([129]) + payload_segment_1})
        ucan_communicator._process_transport_message({'cc_address': cc_address,
                                                      'nr_can_bytes': 8,
                                                      'sid': 1,
                                                      'payload': bytearray([0]) + payload_segment_2})
        self.assertDictEqual(consumer.get(1), {'foo': foo})
Пример #7
0
    def __init__(self,
                 instruction,
                 request_fields=None,
                 response_fields=None
                 ):  # type: (Instruction, List[Field], List[Field]) -> None
        self.instruction = instruction
        self.address = None  # type: Optional[bytearray]
        self.expected_response_hash = None  # type: Optional[int]
        self._address_field = AddressField('destination')

        self._request_fields = [] if request_fields is None else request_fields
        self.response_fields = [] if response_fields is None else response_fields

        self.header_length = 6  # Literal 'ST/RC' + 4 address bytes
        self._instruction_length = len(self.instruction.instruction)
        self._request_padded_suffix = bytearray(
            [0] * self.instruction.padding) + b'\r\n'
        self._response_prefix_length = len(SlaveCommandSpec.RESPONSE_PREFIX)
        self._response_footer_length = 3 + len(
            SlaveCommandSpec.RESPONSE_SUFFIX
        )  # Literal 'C' + 2 CRC bytes + RESPONSE_SUFFIX
        if any(not isinstance(field.length, int)
               for field in self.response_fields):
            raise RuntimeError(
                'SlaveCommandSpec expects fields with integer lengths')
        self.response_length = (self.header_length + self._instruction_length +
                                sum(field.length
                                    for field in self.response_fields
                                    if isinstance(field.length, int)) +
                                self._response_footer_length)
Пример #8
0
    def test_multi_messages(self):
        core_communicator = Mock()
        ucan_communicator = UCANCommunicator(master_communicator=core_communicator)
        cc_address = '000.000.000.000'
        ucan_address = '000.000.000'

        command = UCANCommandSpec(sid=SID.NORMAL_COMMAND,
                                  identifier=AddressField('ucan_address', 3),
                                  instructions=[Instruction(instruction=[0, 10]), Instruction(instruction=[0, 10])],
                                  request_fields=[[LiteralBytesField(1)], [LiteralBytesField(2)]],
                                  response_instructions=[Instruction(instruction=[1, 10], checksum_byte=7),
                                                         Instruction(instruction=[2, 10], checksum_byte=7)],
                                  response_fields=[ByteArrayField('foo', 4)])
        ucan_communicator.do_command(cc_address, command, ucan_address, {}, timeout=None)
        consumer = ucan_communicator._consumers[cc_address][0]

        # Build and validate fake reply from Core
        payload_reply_1 = bytearray([1, 10, 0, 0, 0, 20, 21])
        payload_reply_2 = bytearray([2, 10, 0, 0, 0, 22, 23])
        ucan_communicator._process_transport_message({'cc_address': cc_address,
                                                      'nr_can_bytes': 8,
                                                      'sid': 5,
                                                      'payload': payload_reply_1 + bytearray([UCANCommandSpec.calculate_crc(payload_reply_1)])})
        ucan_communicator._process_transport_message({'cc_address': cc_address,
                                                      'nr_can_bytes': 8,
                                                      'sid': 5,
                                                      'payload': payload_reply_2 + bytearray([UCANCommandSpec.calculate_crc(payload_reply_2)])})
        self.assertDictEqual(consumer.get(1), {'foo': [20, 21, 22, 23]})
Пример #9
0
 def read_ucan_config():  # type: () -> UCANCommandSpec
     """ Reads the full uCAN config """
     return UCANCommandSpec(
         sid=SID.NORMAL_COMMAND,
         identifier=AddressField('ucan_address', 3),
         instructions=[Instruction(instruction=[0, 199])],
         response_instructions=[
             Instruction(instruction=[i, 199], checksum_byte=7)
             for i in range(1, 14)
         ],
         response_fields=[
             ByteField('input_link_0'),
             ByteField('input_link_1'),
             ByteField('input_link_2'),
             ByteField('input_link_3'),
             ByteField('input_link_4'),
             ByteField('input_link_5'),
             ByteField('sensor_link_0'),
             ByteField('sensor_link_1'),
             ByteField('sensor_type'),
             VersionField('firmware_version'),
             ByteField('bootloader'),
             ByteField('new_indicator'),
             ByteField('min_led_brightness'),
             ByteField('max_led_brightness'),
             WordField('adc_input_2'),
             WordField('adc_input_3'),
             WordField('adc_input_4'),
             WordField('adc_input_5'),
             WordField('adc_dc_input')
         ])
Пример #10
0
 def __init__(self, data):
     self._type = data['type']
     self._action = data['action']
     self._device_nr = data['device_nr']
     self._data = data['data']
     self._word_helper = WordField('')
     self._address_helper = AddressField('', length=3)
Пример #11
0
 def get_bootloader_id():  # type: () -> UCANCommandSpec
     """
     Gets the uCAN bootloader ID
     Note: uCAN needs to be in bootloader
     """
     return UCANPalletCommandSpec(
         identifier=AddressField('ucan_address', 3),
         pallet_type=PalletType.BOOTLOADER_ID_REQUEST,
         response_fields=[StringField('bootloader_id')])
Пример #12
0
 def erase_flash():  # type: () -> UCANCommandSpec
     """
     Erases uCAN flash
     Note: uCAN needs to be in bootloader
     """
     return UCANPalletCommandSpec(
         identifier=AddressField('ucan_address', 3),
         pallet_type=PalletType.FLASH_ERASE_REQUEST,
         response_fields=[ByteField('success')])
Пример #13
0
 def reset(sid=SID.NORMAL_COMMAND):  # type: (int) -> UCANCommandSpec
     """ Resets the uCAN """
     return UCANCommandSpec(sid=sid,
                            identifier=AddressField('ucan_address', 3),
                            instructions=[Instruction(instruction=[0, 94])],
                            response_instructions=[
                                Instruction(instruction=[94, 94],
                                            checksum_byte=6)
                            ],
                            response_fields=[ByteField('application_mode')])
Пример #14
0
 def set_bootloader_safety_flag():  # type: () -> UCANCommandSpec
     """ Sets the bootloader's safety flag """
     return UCANCommandSpec(
         sid=SID.BOOTLOADER_COMMAND,
         identifier=AddressField('ucan_address', 3),
         instructions=[Instruction(instruction=[0, 125])],
         request_fields=[[ByteField('safety_flag')]],
         response_instructions=[
             Instruction(instruction=[125, 125], checksum_byte=6)
         ],
         response_fields=[ByteField('safety_flag')])
Пример #15
0
 def ping(sid=SID.NORMAL_COMMAND):  # type: (int) -> UCANCommandSpec
     """ Basic action spec """
     return UCANCommandSpec(sid=sid,
                            identifier=AddressField('ucan_address', 3),
                            instructions=[Instruction(instruction=[0, 96])],
                            request_fields=[[ByteField('data')]],
                            response_instructions=[
                                Instruction(instruction=[1, 96],
                                            checksum_byte=6)
                            ],
                            response_fields=[ByteField('data')])
Пример #16
0
    def test_pallet_reconstructing(self):
        received_commands = []

        def send_command(_cid, _command, _fields):
            received_commands.append(_fields)

        core_communicator = CoreCommunicator(controller_serial=Mock())
        core_communicator._send_command = send_command
        ucan_communicator = UCANCommunicator(master_communicator=core_communicator)
        cc_address = '000.000.000.000'
        ucan_address = '000.000.000'
        pallet_type = PalletType.MCU_ID_REQUEST  # Not important for this test

        for length in [1, 3]:
            # Build command
            command = UCANPalletCommandSpec(identifier=AddressField('ucan_address', 3),
                                            pallet_type=pallet_type,
                                            request_fields=[ByteField('foo'), ByteField('bar')],
                                            response_fields=[ByteArrayField('other', length)])

            # Send command to mocked Core communicator
            received_commands = []
            ucan_communicator.do_command(cc_address, command, ucan_address, {'foo': 1, 'bar': 2}, timeout=None)

            # Validate whether the correct data was send to the Core
            self.assertEqual(len(received_commands), 2)
            self.assertDictEqual(received_commands[0], {'cc_address': cc_address,
                                                        'nr_can_bytes': 8,
                                                        'payload': bytearray([129, 0, 0, 0, 0, 0, 0, pallet_type]),
                                                        #                          +--------------+ = source and destination uCAN address
                                                        'sid': SID.BOOTLOADER_PALLET})
            self.assertDictEqual(received_commands[1], {'cc_address': cc_address,
                                                        'nr_can_bytes': 7,
                                                        'payload': bytearray([0, 1, 2, 219, 155, 250, 178, 0]),
                                                        #                        |  |  +----------------+ = checksum
                                                        #                        |  + = bar
                                                        #                        + = foo
                                                        'sid': SID.BOOTLOADER_PALLET})

            # Build fake reply from Core
            consumer = ucan_communicator._consumers[cc_address][0]
            fixed_payload = bytearray([0, 0, 0, 0, 0, 0, pallet_type])
            variable_payload = bytearray(list(range(7, 7 + length)))  # [7] or [7, 8, 9]
            crc_payload = self._uint32_helper.encode(UCANPalletCommandSpec.calculate_crc(fixed_payload + variable_payload))
            ucan_communicator._process_transport_message({'cc_address': cc_address,
                                                          'nr_can_bytes': 8,
                                                          'sid': 1,
                                                          'payload': bytearray([129]) + fixed_payload})
            ucan_communicator._process_transport_message({'cc_address': cc_address,
                                                          'nr_can_bytes': length + 5,
                                                          'sid': 1,
                                                          'payload': bytearray([0]) + variable_payload + crc_payload})
            self.assertDictEqual(consumer.get(1), {'other': list(variable_payload)})
Пример #17
0
 def set_bootloader_timeout(
         sid=SID.NORMAL_COMMAND):  # type: (int) -> UCANCommandSpec
     """ Sets the bootloader timeout """
     return UCANCommandSpec(
         sid=sid,
         identifier=AddressField('ucan_address', 3),
         instructions=[Instruction(instruction=[0, 123])],
         request_fields=[[ByteField('timeout')]],
         response_instructions=[
             Instruction(instruction=[123, 123], checksum_byte=6)
         ],
         response_fields=[ByteField('timeout')])
Пример #18
0
 def read_flash(data_length):  # type: (int) -> UCANCommandSpec
     """
     Reads uCAN flash
     Note: uCAN needs to be in bootloader
     """
     return UCANPalletCommandSpec(
         identifier=AddressField('ucan_address', 3),
         pallet_type=PalletType.FLASH_READ_REQUEST,
         request_fields=[
             UInt32Field('start_address'),
             ByteField('data_length')
         ],
         response_fields=[ByteArrayField('data', data_length)])
Пример #19
0
 def ucan_module_information():  # type: () -> CoreCommandSpec
     """ Receives information from a uCAN module """
     return CoreCommandSpec(instruction='CD',
                            response_fields=[
                                AddressField('ucan_address', 3),
                                WordArrayField('input_links', 6),
                                ByteArrayField('sensor_links', 2),
                                ByteField('sensor_type'),
                                VersionField('version'),
                                ByteField('bootloader'),
                                CharField('new_indicator'),
                                ByteField('min_led_brightness'),
                                ByteField('max_led_brightness')
                            ])
Пример #20
0
 def module_information():  # type: () -> CoreCommandSpec
     """ Receives module information """
     return CoreCommandSpec(instruction='MC',
                            request_fields=[
                                ByteField('module_nr'),
                                ByteField('module_family')
                            ],
                            response_fields=[
                                ByteField('module_nr'),
                                ByteField('module_family'),
                                ByteField('module_type'),
                                AddressField('address'),
                                WordField('bus_errors'),
                                ByteField('module_status')
                            ])
Пример #21
0
 def get_version():  # type: () -> UCANCommandSpec
     """ Gets a uCAN version """
     return UCANCommandSpec(sid=SID.NORMAL_COMMAND,
                            identifier=AddressField('ucan_address', 3),
                            instructions=[
                                Instruction(instruction=[0, 198]),
                                Instruction(instruction=[0, 198])
                            ],
                            request_fields=[[LiteralBytesField(5)],
                                            [LiteralBytesField(6)]],
                            response_instructions=[
                                Instruction(instruction=[5, 199],
                                            checksum_byte=7),
                                Instruction(instruction=[6, 199],
                                            checksum_byte=7)
                            ],
                            response_fields=[
                                ByteField('sensor_type'),
                                VersionField('firmware_version')
                            ])
Пример #22
0
 def firmware_information():  # type: () -> CoreCommandSpec
     """ Firmware information """
     return CoreCommandSpec(
         instruction='FW',
         response_fields=[AddressField('address'),
                          VersionField('version')])