예제 #1
0
    def _write_eeprom(self, eeprom_file, slave, file_format):
        """Loads an EEPROM file to use as configuration.

        Args:
            eeprom_file (str): Path to the EEPROM file.
            slave (int): Target slave number to be connected
            file_format (EEPROM_FILE_FORMAT): EEPROM tool mode.

        Raises:
            ILError: In case the operation does not succeed.

        """
        if file_format not in EEPROM_FILE_FORMAT:
            raise ILError('Invalid file format')
        if file_format == EEPROM_FILE_FORMAT.BINARY:
            mode = EEPROM_TOOL_MODE.MODE_WRITEBIN.value
        else:
            mode = EEPROM_TOOL_MODE.MODE_WRITEINTEL.value

        self._cffi_network = ffi.new('il_net_t **')
        _interface_name = cstr(
            self.interface_name) if self.interface_name else ffi.NULL
        _eeprom_file = cstr(eeprom_file) if eeprom_file else ffi.NULL

        r = lib.il_net_eeprom_tool(self._cffi_network, _interface_name, slave,
                                   mode, _eeprom_file)
        if r < 0:
            raise ILError('Failed writing EEPROM file.')
예제 #2
0
    def connect_to_slave(self,
                         target=1,
                         dictionary="",
                         use_eoe_comms=1,
                         reconnection_retries=DEFAULT_MESSAGE_RETRIES,
                         reconnection_timeout=DEFAULT_MESSAGE_TIMEOUT,
                         servo_status_listener=False,
                         net_status_listener=False):
        """Connect a slave through an EtherCAT connection.

        Args:
            target (int): Number of the target slave.
            dictionary (str): Path to the dictionary to be loaded.
            use_eoe_comms (int): Specify which architecture is the target based on.
            reconnection_retries (int): Number of reconnection retried before declaring
                a connected or disconnected stated.
            reconnection_timeout (int): Time in ms of the reconnection timeout.
            servo_status_listener (bool): Toggle the listener of the servo for
                its status, errors, faults, etc.
            net_status_listener (bool): Toggle the listener of the network
                status, connection and disconnection.

        Returns:
            EthercatServo: Instance of the connected servo.

        """
        _interface_name = cstr(self.interface_name) \
            if self.interface_name else ffi.NULL
        _dictionary = cstr(dictionary) if dictionary else ffi.NULL

        _servo = ffi.new('il_servo_t **')
        self._cffi_network = ffi.new('il_net_t **')
        r = lib.il_servo_connect_ecat(3, _interface_name, self._cffi_network,
                                      _servo, _dictionary, 1061, target,
                                      use_eoe_comms)
        if r <= 0:
            _servo = None
            self._cffi_network = None
            raise ILError('Could not find any servos connected.')

        net_ = ffi.cast('il_net_t *', self._cffi_network[0])
        servo_ = ffi.cast('il_servo_t *', _servo[0])
        servo = EthercatServo(servo_, net_, target, dictionary,
                              servo_status_listener)
        self._cffi_network = net_
        self.servos.append(servo)

        if net_status_listener:
            self.start_status_listener()

        self.set_reconnection_retries(reconnection_retries)
        self.set_recv_timeout(reconnection_timeout)

        return servo
예제 #3
0
    def labels(self, scat_id):
        """Obtain labels for a certain sub-category identifiers.

        Returns:
            dict: Labels dictionary.

        """
        labels_p = ffi.new('il_dict_labels_t **')
        r = lib.il_dict_scat_get(self._dict, cstr(self._cat_id), cstr(scat_id),
                                 labels_p)
        raise_err(r)

        return LabelsDictionary._from_labels(labels_p[0])
예제 #4
0
    def __getitem__(self, _id):
        reg_p = ffi.new('il_reg_t **')
        r = lib.il_dict_reg_get(self._dict, cstr(_id), reg_p, self._subnode)
        if r < 0:
            raise KeyError(_id)

        return ipb_register_from_cffi(reg_p[0])
예제 #5
0
    def __init__(self, cffi_net, target, slave_num, dictionary_path):
        _dictionary = cstr(dictionary_path) if dictionary_path else ffi.NULL
        servo = lib.il_servo_create(cffi_net, slave_num, _dictionary)
        raise_null(servo)

        cffi_servo = ffi.gc(servo, lib.il_servo_destroy)
        super(SerialServo, self).__init__(cffi_servo, cffi_net, target,
                                          dictionary_path)
예제 #6
0
    def save(self, filename):
        """Save dictionary.

        Args:
            filename (str): Output file name/path.

        """
        r = lib.il_dict_save(self._cffi_dictionary, cstr(filename))
        raise_err(r)
예제 #7
0
    def scan_slaves(self):
        """Scan all the slaves connected in the network.

        Returns:
            list: List of number of slaves connected to the network.

        """
        _interface_name = cstr(self.interface_name) \
            if self.interface_name else ffi.NULL

        number_slaves = lib.il_net_num_slaves_get(_interface_name)
        return [slave + 1 for slave in range(number_slaves)]
예제 #8
0
    def _write_eeprom_alias(self, eeprom_file, slave):
        """Writes the configuration station alias.

        Args:
            eeprom_file (str): Path to the EEPROM file.
            slave (int): Target slave number to be connected

        Raises:
            ILError: In case the operation does not succeed.

        """
        self._cffi_network = ffi.new('il_net_t **')
        _interface_name = cstr(
            self.interface_name) if self.interface_name else ffi.NULL
        _eeprom_file = cstr(eeprom_file) if eeprom_file else ffi.NULL

        r = lib.il_net_eeprom_tool(self._cffi_network, _interface_name, slave,
                                   EEPROM_TOOL_MODE.MODE_WRITEALIAS.value,
                                   _eeprom_file)
        if r < 0:
            raise ILError('Failed writing EEPROM alias.')
예제 #9
0
    def _load_scat_ids(self):
        """Load sub-category IDs from dictionary."""
        scat_ids = lib.il_dict_scat_ids_get(self._dict, cstr(self._cat_id))

        self._scat_ids = []
        i = 0
        scat_id = scat_ids[0]
        while scat_id != ffi.NULL:
            self._scat_ids.append(pstr(scat_id))
            i += 1
            scat_id = scat_ids[i]

        lib.il_dict_scat_ids_destroy(scat_ids)
예제 #10
0
    def labels(self, category_id):
        """Obtain labels for a certain category ID.

        Returns:
            dict: Labels dictionary.

        """
        labels_p = ffi.new('il_dict_labels_t **')
        r = lib.il_dict_cat_get(self.__ipb_dictionary._cffi_dictionary,
                                cstr(category_id), labels_p)
        raise_err(r)

        return LabelsDictionary._from_labels(labels_p[0])
예제 #11
0
    def load_firmware(self, fw_file, target=1, boot_in_app=True):
        """Loads a given firmware file to a target.

        .. warning::
            Choose the ``boot_in_app`` flag accordingly to your
            servo specifications otherwise the servo could enter
            a blocking state.

        .. warning ::
            It is needed to disconnect the drive(:func:`disconnect_from_slave`)
            after loading the firmware since the `Servo` object's data will
            become obsolete.

        Args:
            target (int): Targeted node ID to be loaded.
            fw_file (str): Path to the firmware file.
            boot_in_app (bool): If summit series -> True.
                                If capitan series -> False.
                                If custom device -> Contact manufacturer.

        Raises:
            ILFirmwareLoadError: The firmware load process fails
                with an error message.

        """
        if not os.path.isfile(fw_file):
            raise FileNotFoundError('Could not find {}.'.format(fw_file))

        self._cffi_network = ffi.new('il_net_t **')
        _interface_name = cstr(self.interface_name) \
            if self.interface_name else ffi.NULL
        _fw_file = cstr(fw_file) if fw_file else ffi.NULL
        r = lib.il_net_update_firmware(self._cffi_network, _interface_name,
                                       target, _fw_file, boot_in_app)
        if r < 0:
            error_msg = 'Error updating firmware. Error code: {}'.format(r)
            if r in FIRMWARE_UPDATE_ERROR:
                error_msg = FIRMWARE_UPDATE_ERROR[r]
            raise ILFirmwareLoadError(error_msg)
예제 #12
0
    def connect_to_slave(self, target, dictionary=""):
        """Connects to a slave through the given network settings.

        Args:
            target (str): IP of the target slave.
            dictionary (str): Path to the target dictionary file.

        Returns:
            SerialServo: Instance of the servo connected.

        """
        self._on_found = ffi.NULL

        callback = ffi.NULL
        handle = ffi.NULL

        opts = ffi.new('il_net_opts_t *')
        _port = ffi.new('char []', cstr(target))
        opts.port = _port
        opts.timeout_rd = to_ms(self.timeout_rd)
        opts.timeout_wr = to_ms(self.timeout_wr)

        self.__net_interface = lib.il_net_create(NET_PROT.MCB.value, opts)
        raise_null(self.__net_interface)

        servos = lib.il_net_servos_list_get(self.__net_interface, callback, handle)

        found = []
        curr = servos

        while curr:
            found.append(int(curr.id))
            curr = curr.next

        lib.il_net_servos_list_destroy(servos)

        if not found:
            raise ILError('Could not connect to "{}"'.format(target))

        servo = SerialServo(self.__net_interface, target, found[0], dictionary)
        self._cffi_network = self.__net_interface
        self.servos.append(servo)
        return servo