Créer mon premier téléchargeur
Introduction
L’image ci-dessous montre la séquence simplifiée des appels de fonction standard.
Chaque fonction a accès à l’objet dédié, par exemple une opération, mais aussi au contrôleur, aux ressources électriques connectées et au programme complet.
Motion : Un mouvement se compose d’un objet de position (linéaire ou point à point) ou de deux objets de position (circulaires) (c’est-à-dire des éléments de trajet d’outil). Chaque position a ses propres coordonnées, valeurs d’axes, configuration, virage, etc. Le mouvement peut avoir des événements qui s’appliquent avant ou après avoir atteint la position. Cela signifie que les événements sont gérés en conséquence dans le HandleMotion().
Operation : Une opération comporte normalement plusieurs mouvements et les combine en une unité technologique, par exemple un point de forage, une soudure ou une surface de peinture.
Operation group : Un groupe d’opérations regroupe des opérations logiques ou technologiquement liées dans un groupe. Les opérations regroupées peuvent être manipulées ensemble, en une seule entité.
Étapes
1. Débuts
In Visual Studio Code open HelloWorld.py from the example plugin, that has been implemented during the preparation. If everything is set up correctly, the picture should look like this.

Trouble shooting:
- If the title bar is not green, please check if you selected the correct folder.
- If the imports are underlined yellow, please select the Python interpreter from the FASTSUITE Edition 2 installation.
Both issues are described in the Preparation page.
The name of the translator (file) and the class names can be different. The file name is used and visible in the user interface. The class name is used internally. Important is, that the name in DOWNLOAD_CLASS_NAME is equal with the used class name.

The class from which it is derived, is specified within the brackets after the class name. In this case, it is the base class Downloader.

Important: It can only be derived from translators within the installation directory or the current plugin. Taking these conditions into account, several derivations are possible (like described in infrastructure overview picture in the Introduction page).
2. Créer un fichier programme et ajouter du contenu
There is a library command available which creates a file if it does not exist, opens the file, adds content, and closes the file. To access that library, the import of FileUtility from cenpylib is necessary at the beginning of the downloader.
![]()
To get access to the library in the entire class, we create class-wide access with self.FileUtil = FileUtility(). This means that the code only must be implemented in the first derivation. The access is then also available in the derived (child) classes (more later). Do not forget to call the parent implementation of the __init__ function with super().__init__() especially in the child classes.

In self.OutputFilePath we will store the output directory, including the file name and the file extension.
![]()
The string array self.ProgramContent is used to add single lines to that array.
![]()
At the end, the complete array is transferred to a file using the function AppendTextArrayToFile() from self.FileUtil.

3. Obtenir les informations du contrôleur et tous les joints connectés
Here is an example of how to read the necessary information from the controller and access the axis mapping. Add the following lines to the OutputHeader() function.
# get log operator
logger = operator.GetLogOperator()
logger.LogInfo("Default OutputHeader called")
self.ProgramContent.append("Controller: %s, Manufacturer: %s" % (controller.GetName(), controller.GetManufacturer()))
self.ProgramContent.append("Model: %s, Series: %s" % (controller.GetModel(), controller.GetSeries()))
# get all electrically connected joints
connectedJoints = controller.GetConnectedJoints()
# iterate through the list of joints
for joint in connectedJoints:
self.ProgramContent.append("Joint: %s, DOF number: %d" % (joint.GetName(), joint.GetDofNumber()))
self.ProgramContent.append("Group index: %d, joint index: %d" % (joint.GetJointGroupIndex(), joint.GetJointIndex()))
Téléchargez le programme de votre scénario avec cette mise à jour et cherchez les résultats. Exemple :

4. Sortir tous les attributs définis sur l’opération
To be able to access an attribute in download, the attribute must be of type PROCESS_ATTRIBUTE. It is possible to change the property and visibility of attributes via technology customizing.

Output all operation attributes with the property PROCESS_ATTRIBUTE. Add the following lines to the OperationStart() function.
for att in operation.GetAttributes():
self.ProgramContent.append('Operation attributes: ' + str(att.GetName()) + ',' + str(att.GetValue()))
Téléchargez le programme de votre scénario avec cette mise à jour et cherchez les résultats. Exemple de la sortie ajoutée :
In this following example, only attributes that can be found on the operation or have been set on the operation are considered and have the property PROCESS_ATTRIBUTE. To get a specific process attribute on the operation, the following function should be used.
![]()
5. Sortie des mouvements
The entry to the motions and events is in the function HandleMotion(). First, the events before the movement are processed. Then the movements themselves are translated and finally then the events after the movement. The example below contains an implementation for point to point, linear and circular motions. In this document we will only describe the linear output.

Within the OutputLin() function, the string for the output is generated and added to the self.ProgramContent. The output of the self.ProgramContent has already been dealt with in the beginning. Add the following lines to the OutputLin() function.
# get cartesian coordinates
xyz = position.GetXYZ()
angles = position.GetOrientation()
# convert them to meter
convertToMM = 1000
X = xyz[0] * convertToMM
Y = xyz[1] * convertToMM
Z = xyz[2] * convertToMM
# add motion instruction to the program content
self.ProgramContent.append(" X:%.3f mm Y:%.3f mm Z:%.3f mm" % (X, Y, Z))
self.ProgramContent.append(" Rx:%.3f deg Ry:%.3f deg Rz:%.3f deg" % (angles[0], angles[1], angles[2]))
self.ProgramContent.append("")
Téléchargez le programme de votre scénario avec cette mise à jour et cherchez les résultats. Exemple :
