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.')
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
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])
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])
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)
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)
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)]
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.')
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)
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])
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)
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