예제 #1
0
    def test_unresponsiveness(self):
        core_communicator = CoreCommunicator(controller_serial=Mock())
        core_communicator.do_command = Mock()
        slave_communicator = SlaveCommunicator(
            master_communicator=core_communicator, verbose=True)
        slave_communicator._transparent_mode = True
        address = '000.000.000.000'

        command_spec = SlaveCommandSpec(
            instruction=Instruction(instruction='AB'),
            request_fields=[ByteField('foo')],
            response_fields=[ByteField('bar')])

        with self.assertRaises(CommunicationTimedOutException):
            core_communicator.do_command.side_effect = lambda command, fields, timeout=None: time.sleep(
                2)
            slave_communicator.do_command(address,
                                          command_spec, {'foo': 0},
                                          timeout=1)  # No slave response
        with self.assertRaises(CommunicationTimedOutException):
            core_communicator.do_command.side_effect = CommunicationTimedOutException(
                'Master unresponsive')
            slave_communicator.do_command(address,
                                          command_spec, {'foo': 0},
                                          timeout=1)
예제 #2
0
    def test_transparent_mode(self):
        received_commands = []

        def do_command(command, fields, timeout=None):
            received_commands.append(fields)
            return {'mode': fields['mode']}

        core_communicator = CoreCommunicator(controller_serial=Mock())
        core_communicator.do_command = do_command
        slave_communicator = SlaveCommunicator(master_communicator=core_communicator, verbose=True)
        address = '000.000.000.000'

        command_spec = SlaveCommandSpec(instruction=Instruction(instruction='AB'),
                                        request_fields=[ByteField('foo')],
                                        response_fields=[ByteField('bar')])

        with self.assertRaises(RuntimeError):
            # Transparent mode inactive
            slave_communicator.do_command(address, command_spec, {'foo': 0}, timeout=None)

        self.assertFalse(slave_communicator._transparent_mode)
        with slave_communicator:
            # SlaveCommunicator as ContextManager activates transparent mode
            self.assertEqual(1, len(received_commands))
            self.assertEqual({'mode': CoreAPI.SlaveBusMode.TRANSPARENT}, received_commands[0])
            self.assertTrue(slave_communicator._transparent_mode)
        self.assertEqual(2, len(received_commands))
        self.assertEqual({'mode': CoreAPI.SlaveBusMode.LIVE}, received_commands[1])
        self.assertFalse(slave_communicator._transparent_mode)
예제 #3
0
파일: core_api.py 프로젝트: rolaya/gateway
 def get_slave_bus_mode():  # type: () -> CoreCommandSpec
     """ Receives the slave bus mode """
     return CoreCommandSpec(
         instruction='ST',
         request_fields=[LiteralBytesField(0)],
         response_fields=[ByteField('info_type'),
                          ByteField('mode')])
예제 #4
0
파일: core_api.py 프로젝트: rolaya/gateway
 def event_information():  # type: () -> CoreCommandSpec
     """ Event information """
     return CoreCommandSpec(instruction='EV',
                            response_fields=[
                                ByteField('type'),
                                ByteField('action'),
                                WordField('device_nr'),
                                RawByteArrayField('data', 4)
                            ])
예제 #5
0
파일: core_api.py 프로젝트: rolaya/gateway
 def error_information():  # type: () -> CoreCommandSpec
     """ Error information """
     return CoreCommandSpec(instruction='ER',
                            response_fields=[
                                ByteField('type'),
                                ByteField('parameter_a'),
                                WordField('parameter_b'),
                                WordField('parameter_c')
                            ])
예제 #6
0
파일: core_api.py 프로젝트: rolaya/gateway
 def ucan_rx_transport_message():  # type: () -> CoreCommandSpec
     """ uCAN transport layer packages """
     return CoreCommandSpec(instruction='FM',
                            response_fields=[
                                AddressField('cc_address'),
                                ByteField('nr_can_bytes'),
                                ByteField('sid'),
                                RawByteArrayField('payload', 8)
                            ])
예제 #7
0
 def get_master_modes():  # type: () -> CoreCommandSpec
     """ Receives various master modes (rs485 bus mode, BA debug mode) """
     return CoreCommandSpec(instruction='ST',
                            request_fields=[LiteralBytesField(0)],
                            response_fields=[
                                ByteField('info_type'),
                                ByteField('rs485_mode'),
                                ByteField('ba_debug_mode')
                            ])
예제 #8
0
파일: slave_api.py 프로젝트: rolaya/gateway
 def get_firmware_version():  # type: () -> SlaveCommandSpec
     """ Gets a slave firmware version """
     return SlaveCommandSpec(instruction=Instruction(instruction='FV',
                                                     padding=9),
                             response_fields=[
                                 ByteField('return_code'),
                                 ByteField('hardware_version'),
                                 VersionField('version'),
                                 ByteField('status')
                             ])
예제 #9
0
파일: core_api.py 프로젝트: rolaya/gateway
 def _sensor_values(instruction,
                    field):  # type: (int, Field) -> CoreCommandSpec
     """ Receive sensor byte values """
     return CoreCommandSpec(
         instruction='SI',
         request_fields=[
             ByteField('module_nr'),
             LiteralBytesField(instruction)
         ],
         response_fields=[ByteField('module_nr'),
                          PaddingField(1), field])
예제 #10
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')])
예제 #11
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')])
예제 #12
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)})
예제 #13
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')])
예제 #14
0
파일: core_api.py 프로젝트: rolaya/gateway
 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')
                            ])
예제 #15
0
파일: core_api.py 프로젝트: rolaya/gateway
 def basic_action():  # type: () -> CoreCommandSpec
     """ Basic action spec """
     return CoreCommandSpec(instruction='BA',
                            request_fields=[
                                ByteField('type'),
                                ByteField('action'),
                                WordField('device_nr'),
                                WordField('extra_parameter')
                            ],
                            response_fields=[
                                ByteField('type'),
                                ByteField('action'),
                                WordField('device_nr'),
                                WordField('extra_parameter')
                            ])
예제 #16
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')]])
예제 #17
0
파일: core_api.py 프로젝트: rolaya/gateway
 def get_firmware_version():  # type: () -> CoreCommandSpec
     """ Receives the Core firmware version """
     return CoreCommandSpec(
         instruction='ST',
         request_fields=[LiteralBytesField(1)],
         response_fields=[ByteField('info_type'),
                          VersionField('version')])
예제 #18
0
파일: core_api.py 프로젝트: rolaya/gateway
 def memory_read():  # type: () -> CoreCommandSpec
     """ Reads memory """
     return CoreCommandSpec(instruction='MR',
                            request_fields=[
                                CharField('type'),
                                WordField('page'),
                                ByteField('start'),
                                ByteField('length')
                            ],
                            response_fields=[
                                CharField('type'),
                                WordField('page'),
                                ByteField('start'),
                                RawByteArrayField('data',
                                                  lambda length: length - 4)
                            ])
예제 #19
0
 def request_slave_firmware_versions():  # type: () -> CoreCommandSpec
     """ Requests the slave firmware versions, which will be send to the GW in separate FW calls """
     return CoreCommandSpec(
         instruction='ST',
         request_fields=[LiteralBytesField(2)],
         response_fields=[ByteField('info_type'),
                          PaddingField(2)])
예제 #20
0
파일: core_api.py 프로젝트: rolaya/gateway
 def memory_write(length):  # type: (int) -> CoreCommandSpec
     """ Writes memory """
     return CoreCommandSpec(instruction='MW',
                            request_fields=[
                                CharField('type'),
                                WordField('page'),
                                ByteField('start'),
                                RawByteArrayField('data', length)
                            ],
                            response_fields=[
                                CharField('type'),
                                WordField('page'),
                                ByteField('start'),
                                ByteField('length'),
                                CharField('result')
                            ])
예제 #21
0
 def execute_basic_action_series(length):  # type: (int) -> CoreCommandSpec
     """ Executes a Basic action on multiple devices """
     if not 2 <= length <= 40:
         raise ValueError('Amount of device numbers should be 2 <= n <= 40')
     return CoreCommandSpec(instruction='ES',
                            request_fields=[
                                ByteField('type'),
                                ByteField('action'),
                                WordField('extra_parameter'),
                                WordArrayField('device_nrs', length)
                            ],
                            response_fields=[
                                ByteField('type'),
                                ByteField('action'),
                                WordField('extra_parameter')
                            ])
예제 #22
0
파일: slave_api.py 프로젝트: rolaya/gateway
 def write_firmware_block():  # type: () -> SlaveCommandSpec
     """ Writes a single 64-byte firmware block to a given address """
     return SlaveCommandSpec(instruction=Instruction(instruction='FD'),
                             request_fields=[
                                 WordField('address'),
                                 ByteArrayField('payload', length=64)
                             ],
                             response_fields=[ByteField('return_code')])
예제 #23
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')])
예제 #24
0
파일: core_api.py 프로젝트: rolaya/gateway
 def device_information_list_inputs():  # type: () -> CoreCommandSpec
     """ Device information list for inputs """
     return CoreCommandSpec(instruction='DL',
                            request_fields=[LiteralBytesField(1)],
                            response_fields=[
                                ByteField('type'),
                                ByteArrayField('information',
                                               lambda length: length - 1)
                            ])
예제 #25
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')])
예제 #26
0
파일: core_api.py 프로젝트: rolaya/gateway
 def general_configuration_number_of_modules(
 ):  # type: () -> CoreCommandSpec
     """ Receives general configuration regarding number of modules """
     return CoreCommandSpec(instruction='GC',
                            request_fields=[LiteralBytesField(0)],
                            response_fields=[
                                ByteField('type'),
                                ByteField('output'),
                                ByteField('input'),
                                ByteField('sensor'),
                                ByteField('ucan'),
                                ByteField('ucan_input'),
                                ByteField('ucan_sensor'),
                                ByteField('power_rs485'),
                                ByteField('power_can')
                            ])
예제 #27
0
파일: core_api.py 프로젝트: rolaya/gateway
 def get_date_time():  # type: () -> CoreCommandSpec
     """ Reads the date/time from the Core """
     return CoreCommandSpec(instruction='TR',
                            request_fields=[LiteralBytesField(0)],
                            response_fields=[
                                ByteField('info_type'),
                                ByteField('hours'),
                                ByteField('minutes'),
                                ByteField('seconds'),
                                ByteField('weekday'),
                                ByteField('day'),
                                ByteField('month'),
                                ByteField('year')
                            ])
예제 #28
0
    def test_rxtx(self):
        received_commands = []

        def do_command(command, fields, timeout=None):
            received_commands.append(fields)

        core_communicator = CoreCommunicator(controller_serial=Mock())
        core_communicator.do_command = do_command
        slave_communicator = SlaveCommunicator(master_communicator=core_communicator, verbose=True)
        slave_communicator._transparent_mode = True
        address = '000.000.000.000'

        command_spec = SlaveCommandSpec(instruction=Instruction(instruction='AB'),
                                        request_fields=[ByteField('foo')],
                                        response_fields=[ByteField('bar')])

        slave_communicator.do_command(address, command_spec, {'foo': 0}, timeout=None)
        self.assertEqual(1, len(received_commands))
        self.assertTrue('payload' in received_commands[0])
        payload = received_commands[0]['payload']
        self.assertEqual(SlaveCommunicatorTest._build_request_message(b'\x00\x00\x00\x00AB\x00'), payload)
        consumer = slave_communicator._consumers[0]
        response_payload = SlaveCommunicatorTest._build_response_message(b'\x00\x00\x00\x00AC\x04')
        slave_communicator._process_transport_message({'payload': bytearray(b'FOO') + response_payload[:5]})
        slave_communicator._process_transport_message({'payload': response_payload[5:]})
        slave_communicator._process_transport_message({'payload': SlaveCommunicatorTest._build_response_message(b'\x00\x00\x00\x01AB\x03')})
        slave_communicator._process_transport_message({'payload': SlaveCommunicatorTest._build_response_message(b'\x00\x00\x00\x00AB\x02', bad_crc=True)})
        with self.assertRaises(CommunicationTimedOutException):
            self.assertEqual({'bar': 1}, consumer.get(1))  # Invalid CRC
        slave_communicator.do_command(address, command_spec, {'foo': 0}, timeout=None)
        consumer = slave_communicator._consumers[0]
        slave_communicator._process_transport_message({'payload': SlaveCommunicatorTest._build_response_message(b'\x00\x00\x00\x00AB\x01')})
        self.assertEqual({'bar': 1}, consumer.get(1))

        command_spec = SlaveCommandSpec(instruction=Instruction(instruction='AB'),
                                        request_fields=[ByteField('foo')])
        slave_communicator.do_command(address, command_spec, {'foo': 0}, timeout=None)
        consumer = slave_communicator._consumers[0]
        with self.assertRaises(CommunicationTimedOutException):
            consumer.get(0)
예제 #29
0
파일: core_api.py 프로젝트: rolaya/gateway
 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)
                            ])
예제 #30
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)])