Пример #1
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]})
Пример #2
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})
Пример #3
0
 def update_ucan(address, hex_filename, version):
     if '@' not in address:
         raise RuntimeError('Address must be in the form of <ucan address>@<cc address>')
     ucan_address, cc_address = address.split('@')
     return UCANUpdater.update(cc_address=cc_address,
                               ucan_address=ucan_address,
                               ucan_communicator=UCANCommunicator(),
                               hex_filename=hex_filename,
                               version=version)
Пример #4
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)})
Пример #5
0
    def setUp(self):
        self.memory = {}
        self.return_data = {}

        def _do_command(command, fields, timeout=None):
            _ = timeout
            instruction = ''.join(str(chr(c)) for c in command.instruction)
            if instruction == 'MR':
                page = fields['page']
                start = fields['start']
                length = fields['length']
                return {'data': self.memory.get(page, bytearray([255] * 256))[start:start + length]}
            elif instruction == 'MW':
                page = fields['page']
                start = fields['start']
                page_data = self.memory.setdefault(page, bytearray([255] * 256))
                for index, data_byte in enumerate(fields['data']):
                    page_data[start + index] = data_byte
            elif instruction in self.return_data:
                return self.return_data[instruction]
            else:
                raise AssertionError('unexpected instruction: {0}'.format(instruction))

        def _do_basic_action(action_type, action, device_nr=0, extra_parameter=0, timeout=2, log=True):
            _ = device_nr, extra_parameter, timeout, log
            if action_type == 200 and action == 1:
                # Send EEPROM_ACTIVATE event
                eeprom_file._handle_event({'type': 254, 'action': 0, 'device_nr': 0, 'data': 0})

        self.communicator = mock.Mock(CoreCommunicator)
        self.communicator.do_command = _do_command
        self.communicator.do_basic_action = _do_basic_action
        self.pubsub = PubSub()
        SetUpTestInjections(master_communicator=self.communicator,
                            pubsub=self.pubsub)

        eeprom_file = MemoryFile(MemoryTypes.EEPROM)
        eeprom_file._cache = self.memory
        SetUpTestInjections(memory_files={MemoryTypes.EEPROM: eeprom_file,
                                          MemoryTypes.FRAM: MemoryFile(MemoryTypes.FRAM)},
                            ucan_communicator=UCANCommunicator(),
                            slave_communicator=SlaveCommunicator())
        self.controller = MasterCoreController()

        # For testing purposes, remove read-only flag from certain properties
        for field_name in ['device_type', 'address', 'firmware_version']:
            for model_type in [OutputModuleConfiguration, InputModuleConfiguration, SensorModuleConfiguration]:
                if hasattr(model_type, '_{0}'.format(field_name)):
                    getattr(model_type, '_{0}'.format(field_name))._read_only = False
                else:
                    getattr(model_type, field_name)._read_only = False
Пример #6
0
    def update_all(module_type, hex_filename, gen3_firmware, version):  # type: (str, str, bool, Optional[str]) -> bool
        def _default_if_255(value, default):
            return value if value != 255 else default

        global_configuration = GlobalConfiguration()
        executed_update = False
        success = True

        # Classic master slave modules: ['O', 'R', 'D', 'I', 'T', 'C']
        update_map = {'I': (InputModuleConfiguration, _default_if_255(global_configuration.number_of_input_modules, 0)),
                      'O': (OutputModuleConfiguration, _default_if_255(global_configuration.number_of_output_modules, 0)),
                      'D': (OutputModuleConfiguration, _default_if_255(global_configuration.number_of_output_modules, 0)),
                      'T': (SensorModuleConfiguration, _default_if_255(global_configuration.number_of_sensor_modules, 0)),
                      'C': (CanControlModuleConfiguration, _default_if_255(global_configuration.number_of_can_control_modules, 0))}
        if module_type in update_map:
            module_configuration_class, number_of_modules = update_map[module_type]
            for module_id in range(number_of_modules):
                module_configuration = module_configuration_class(module_id)  # type: Union[InputModuleConfiguration, OutputModuleConfiguration, SensorModuleConfiguration, CanControlModuleConfiguration]
                if module_configuration.device_type == module_type:
                    executed_update = True
                    success &= SlaveUpdater.update(address=module_configuration.address,
                                                   hex_filename=hex_filename,
                                                   gen3_firmware=gen3_firmware,
                                                   version=version)
                else:
                    logger.info('Skip updating unsupported module {0}: {1} != {2}'.format(
                        module_configuration.address, module_configuration.device_type, module_type
                    ))

        # MicroCAN (uCAN)
        if module_type == 'UC':
            number_of_ucs = _default_if_255(global_configuration.number_of_ucan_modules, 0)
            if number_of_ucs:
                ucan_communicator = UCANCommunicator()
                for module_id in range(number_of_ucs):
                    ucan_configuration = UCanModuleConfiguration(module_id)
                    executed_update = True
                    cc_address = ucan_configuration.module.address if ucan_configuration.module is not None else '000.000.000.000'
                    success &= UCANUpdater.update(cc_address=cc_address,
                                                  ucan_address=ucan_configuration.address,
                                                  ucan_communicator=ucan_communicator,
                                                  hex_filename=hex_filename,
                                                  version=version)

        if not executed_update:
            logger.info('No modules of type {0} were updated'.format(module_type))
            return True
        return success
Пример #7
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)