def ucan_tx_transport_message(): """ uCAN transport layer packages """ return CoreCommandSpec(instruction='FM', request_fields=[ AddressField('cc_address'), ByteField('nr_can_bytes'), ByteField('sid'), ByteArrayField('payload', 8) ], response_fields=[AddressField('cc_address')])
def get_ucan_address(): """ 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) ])
def get_amount_of_ucans(): """ 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) ])
def read_ucan_config(): """ Reads the full uCAN config """ return UCANCommandSpec(sid=SID.NORMAL_COMMAND, instruction=Instruction(instruction=[0, 199]), identifier=AddressField('ucan_address', 3), response_instructions=[ Instruction(instruction=[i, 199], checksum_byte=7) for i in xrange(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') ])
def test_string_parsing(self): core_communicator = Mock() ucan_communicator = UCANCommunicator(master_communicator=core_communicator, verbose=True) 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 = [0, 0, 0, 0, 0, 0, PalletType.MCU_ID_REPLY] payload_segment_2 = [ord(x) for x in '{0}\x00'.format(foo)] crc_payload = Int32Field.encode_bytes(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': [129] + payload_segment_1}) ucan_communicator._process_transport_message({'cc_address': cc_address, 'nr_can_bytes': 8, 'sid': 1, 'payload': [0] + payload_segment_2}) self.assertDictEqual(consumer.get(1), {'foo': foo})
def erase_flash(): """ Erases uCAN flash Note: uCAN needs to be in bootloader """ return UCANPalletCommandSpec( identifier=AddressField('ucan_address', 3), pallet_type=PalletType.FLASH_ERASE_REQUEST)
def get_bootloader_id(): """ 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')])
def reset(sid=SID.NORMAL_COMMAND): """ Resets the uCAN """ return UCANCommandSpec(sid=sid, instruction=Instruction(instruction=[0, 94]), identifier=AddressField('ucan_address', 3), response_instructions=[ Instruction(instruction=[94, 94], checksum_byte=6) ], response_fields=[ByteField('application_mode')])
def set_bootloader_safety_flag(): """ Sets the bootloader's safety flag """ return UCANCommandSpec(sid=SID.BOOTLOADER_COMMAND, instruction=Instruction(instruction=[0, 125]), identifier=AddressField('ucan_address', 3), request_fields=[ByteField('safety_flag')], response_instructions=[ Instruction(instruction=[125, 125], checksum_byte=6) ], response_fields=[ByteField('safety_flag')])
def set_bootloader_timeout(sid=SID.NORMAL_COMMAND): """ Sets the bootloader timeout """ return UCANCommandSpec(sid=sid, instruction=Instruction(instruction=[0, 123]), identifier=AddressField('ucan_address', 3), request_fields=[ByteField('timeout')], response_instructions=[ Instruction(instruction=[123, 123], checksum_byte=6) ], response_fields=[ByteField('timeout')])
def ping(sid=SID.NORMAL_COMMAND): """ Basic action spec """ return UCANCommandSpec(sid=sid, instruction=Instruction(instruction=[0, 96]), identifier=AddressField('ucan_address', 3), request_fields=[ByteField('data')], response_instructions=[ Instruction(instruction=[1, 96], checksum_byte=6) ], response_fields=[ByteField('data')])
def write_flash(data_length): """ Writes uCAN flash Note: uCAN needs to be in bootloader """ return UCANPalletCommandSpec( identifier=AddressField('ucan_address', 3), pallet_type=PalletType.FLASH_WRITE_REQUEST, request_fields=[ Int32Field('start_address'), ByteArrayField('data', data_length) ])
def test_pallet_reconstructing(self): received_commands = [] def send_command(_cid, _command, _fields): received_commands.append(_fields) core_communicator = CoreCommunicator(controller_serial=Mock(), verbose=True) core_communicator._send_command = send_command ucan_communicator = UCANCommunicator(master_communicator=core_communicator, verbose=True) 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': [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': [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 = [0, 0, 0, 0, 0, 0, pallet_type] variable_payload = range(7, 7 + length) # [7] or [7, 8, 9] crc_payload = Int32Field.encode_bytes(UCANPalletCommandSpec.calculate_crc(fixed_payload + variable_payload)) ucan_communicator._process_transport_message({'cc_address': cc_address, 'nr_can_bytes': 8, 'sid': 1, 'payload': [129] + fixed_payload}) ucan_communicator._process_transport_message({'cc_address': cc_address, 'nr_can_bytes': length + 5, 'sid': 1, 'payload': [0] + variable_payload + crc_payload}) self.assertDictEqual(consumer.get(1), {'other': variable_payload})
def read_flash(data_length): """ 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)])
def ucan_module_information(): """ 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') ])
def test_bootload_lock(self): core_communicator = Mock() ucan_communicator = UCANCommunicator(master_communicator=core_communicator, verbose=True) cc_address = '000.000.000.000' ucan_address = '000.000.000' command = UCANCommandSpec(sid=SID.NORMAL_COMMAND, instruction=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, instruction=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, instruction=Instruction(instruction=[0, 0]), identifier=AddressField('ucan_address', 3)) ucan_communicator.do_command(cc_address, command, ucan_address, {}, timeout=None)
def module_information(): """ 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') ])
def set_max_led_brightness(): """ Sets the maximum brightness for a uCAN led """ return UCANCommandSpec(sid=SID.NORMAL_COMMAND, instruction=Instruction(instruction=[0, 247]), identifier=AddressField('ucan_address', 3), request_fields=[ByteField('brightness')])