Utilisation de scripts pour accéder CODESYS Fonctionnalités
Tous les objets et commandes qui CODESYS des services de scripts sont également disponibles dans le "scriptengine " Module Python. Chaque fois qu'un script est démarré, un <code>from scriptengine import *</code> résultats. Cela permet un accès facile aux CODESYS. Cependant, si votre script importe des modules qui nécessitent un accès CODESYS API, ces modules doivent alors importer le module scriptengine eux-mêmes.
Le tableau suivant présente les principaux objets (catégories) pouvant servir de points d'entrée dans les scripts Python. Pour une documentation complète sur les points d'entrée, consultez la documentation de référence de l'API. CODESYS Moteur de script : API de script CODESYS.
Objets | Description |
|---|---|
system | Accès au général CODESYS fonctionnalités Exemples:
|
projects | Accès à la CODESYS projet sous forme d'arborescence d'objets qui combine les trois vues du navigateur (périphériques, POU, modules) dans une arborescence de projet Permet également le chargement, la création, l'enregistrement et la fermeture de projets Pour la plupart des objets d'un projet, il existe des méthodes spéciales avec des fonctionnalités détaillées, par exemple la compilation, l'accès aux POU ST, l'exportation, l'importation, la configuration des appareils, etc. |
online | Accès aux fonctionnalités en ligne Exemples:
|
librarymanager | Permet la gestion des référentiels de bibliothèques et la visualisation, l'installation et la suppression des bibliothèques |
device_repository | Gestion des référentiels d'appareils ; importation et exportation des descriptions d'appareils |
modulerepository | Gestion de CODESYS Application Composer modules et CODESYS Application Composer dépôts |
Consultez les exemples de scripts spécifiques suivants pour connaître les moyens d'y accéder CODESYS fonctionnalités. Pour des informations détaillées, consultez la documentation de référence de l'API CODESYS Moteur de script : API de script CODESYS.
Exemple : Impression de l'arborescence des périphériques du projet en cours
Le scénario PrintDeviceTree.py Voici un exemple de navigation dans un projet. Il génère un affichage hiérarchique de tous les appareils du projet ouvert.
Chargez un projet contenant des objets de périphérique et exécutez le script.
PrintDeviceTree.py# encoding:utf-8
# We enable the new python 3 print syntax
from __future__ import print_function
# Prints out all devices in the currently open project.
print("--- Printing the devices of the project: ---")
# Define the printing function. This function starts with the
# so called "docstring" which is the recommended way to document
# functions in python.
def print_tree(treeobj, depth=0):
""" Print a device and all its children
Arguments:
treeobj -- the object to print
depth -- The current depth within the tree (default 0).
The argument 'depth' is used by recursive call and
should not be supplied by the user.
"""
# if the current object is a device, we print the name and device identification.
if treeobj.is_device:
name = treeobj.get_name(False)
deviceid = treeobj.get_device_identification()
print("{0}- {1} {2}".format("--"*depth, name, deviceid))
# we recursively call the print_tree function for the child objects.
for child in treeobj.get_children(False):
print_tree(child, depth+1)
# We iterate over all top level objects and call the print_tree function for them.
for obj in projects.primary.get_children():
print_tree(obj)
print("--- Script finished. ---")L'arborescence des périphériques (de la vue « Périphériques ») s'affiche dans la vue des messages et tous les objets non périphériques sont laissés de côté :

Exemple : Lecture de variables
Le scénario ReadVariable.py se connecte à l'appareil et lance l'application si nécessaire. La valeur de la variable PLC_PRG.iVar1 est lu et généré. Pour tester le script, vous devez modifier le chemin du projet et les noms des variables.
ReadVariable.py# encoding:utf-8
from __future__ import print_function
# close open project if necessary:
if projects.primary:
projects.primary.close()
# opens project
proj = projects.open(r"D:\data\projects\Ampel.project")
# set "Ampel.project" to active application
app = proj.active_application
onlineapp = online.create_online_application(app)
# login to device
onlineapp.login(OnlineChangeOption.Try, True)
# set status of application to "run", if not in "run"
if not onlineapp.application_state == ApplicationState.run:
onlineapp.start()
# wait 1 second
system.delay(1000)
# read value of iVar1
value = onlineapp.read_value("PLC_PRG.iVar1")
# display value in message view or command line
print(value)
# log out from device and close "Ampel.project"
onlineapp.logout()
proj.close()Dans le prolongement du script ReadVariable.py, le scénario MailVariables.py Charge les variables et expressions d'un fichier de recette et lit leurs valeurs actuelles depuis le contrôleur. Ces valeurs sont ensuite réécrites dans le même fichier. De plus, il utilise la bibliothèque SMTP Python pour envoyer un e-mail avec une pièce jointe contenant la liste de toutes les variables.
Pour utiliser le script, vous devez modifier les chemins, l'adresse e-mail et le nom du serveur SMTP de votre environnement.
MailVariables.py# encoding:utf-8
from __future__ import print_function
# Close current project if necessary and open "ScriptTest.project"
if not projects.primary == None:
projects.primary.close()
project = projects.open("D:\\Data\\projects\\scriptTest.project")
# retrieve active application
application = project.active_application
# create online application
online_application = online.create_online_application(application)
# login to application.
online_application.login(OnlineChangeOption.Try, True)
# start PLC if necessary
if not online_application.application_state == ApplicationState.run:
online_application.start()
# wait 2 seconds
system.delay(2000)
# open recipe file to read values.
recipe_input_file = open("D:\\Data\\projects\\RecipeInput.txt", "r")
watch_expressions = []
for watch_expression in recipe_input_file:
watch_expressions.append(watch_expression.strip())
print watch_expressions
# read values from the controllerd
watch_values = online_application.read_values(watch_expressions)
print watch_values
# open output file to write values
recipe_output_file = open("D:\\Data\\projects\\RecipeOutput.txt", "w")
for i in range(len(watch_expressions)):
recipe_output_file.write(watch_expressions[i])
recipe_output_file.write(" = ")
recipe_output_file.write(watch_values[i])
recipe_output_file.write("\n")
# Close files
recipe_input_file.close()
recipe_output_file.close()
# send Email
# import respective libraries
import smtplib
from email.mime.text import MIMEText
#open output file
recipe_output_file = open("D:\\Data\\projects\\RecipeOutput.txt", "r")
mail = MIMEText(recipe_output_file.read())
recipe_output_file.close()
#email address sender and recipient
fromm = "info@example.com"
to = "info@example.com"
# set sender and recipient
mail["Subject"] = "Attention value has changed"
mail["From"] = fromm
mail["To"] = to
# send email
smtp = smtplib.SMTP("name of smtp server")
smtp.sendmail(fromm, [to], mail.as_string())
smtp.quit()
# logout and close application
online_application.logout()
project.close()Exemple : création et modification de POU
Le scénario CreateDut.py crée les objets MyStruct, MyAlias, et MyUnion dans le CODESYS projet. Le dossier DataTypes doit déjà être présent.
CreateDut.py# encoding:utf-8
from __future__ import print_function
STRUCT_CONTENT = """\
a : BOOL;
b : BIT;
c : BIT;
"""
UNION_WHOLE = """\
TYPE MyUnion :
UNION
Zahl : INT;
Prozent : MyAlias;
Bits : MyStruct;
END_UNION
END_TYPE
"""
proj = projects.primary
folder = proj.find('DataTypes', recursive = True)[0]
# Create a struct DUT and insert the list of variables just into the right
# place in line two, row 0 (line numbering starts with line 0)
struktur = folder.create_dut('MyStruct') # DutType.Structure is the default
struktur.textual_declaration.insert(2, 0, STRUCT_CONTENT)
# Alias types get their "content" via the base type, which will just end up
# as one line in the declaration part:
# TYPE MyAlias : INT (0..100); END_TYPE
bereich = folder.create_dut('MyAlias', DutType.Alias, "INT (0..100)")
# Instead of injecting the variables into the existing declaration,
# one can also just replace the complete declaration part, including the
# boilerplate code.
union = folder.create_dut('MyUnion', DutType.Union)
union.textual_declaration.replace(UNION_WHOLE)Exemple : Interface utilisateur / Interaction avec l'utilisateur
Dans certains cas, les scripts doivent interagir avec l'utilisateur. Nous fournissons des API simples pour les interactions les plus courantes. Exemple de script. System_UI_Test.py montre toutes les fonctions possibles à cet égard.
System_UI_Test.py# encoding:utf-8
from __future__ import print_function
"""Performs some tests on the messagestore and UI."""
print("Some Error, Warning and Information popups:")
system.ui.error("Fatal error: Everything is OK. :-)")
system.ui.warning("Your bank account is surprisingly low")
system.ui.info("Just for your information: 42")
print("Now, we ask the user something.")
res = system.ui.prompt("Do you like this?", PromptChoice.YesNo, PromptResult.Yes);
print("The user selected '%s'" % res)
print("Now, the user can choose between custom options:")
res = system.ui.choose("Please choose:", ("First", 2, 7.5, "Something else"))
print("The user selected option '%s'" % str(res)) # res is a tuple
print("Now, the user can choose several options:")
res = system.ui.select_many("Please select one or more options", PromptChoice.OKCancel, PromptResult.OK, ("La Premiere", "The Second", "Das Dritte"))
print("The returned result is: '%s'" % str(res)) # res is a tuple
print("Now, the user can select files and directories")
res = system.ui.open_file_dialog("Choose multiple files:", filter="Text files (*.txt)|*.txt|Image Files(*.BMP;*.JPG;*.GIF)|*.BMP;*.JPG;*.GIF|All files (*.*)|*.*", filter_index = 0, multiselect=True)
print("The user did choose: '%s'" % str(res)) # res is a tuple as multiselect is true.
res = system.ui.save_file_dialog("Choose a file to save:", filter="Text files (*.txt)|*.txt|Image Files(*.BMP;*.JPG;*.GIF)|*.BMP;*.JPG;*.GIF|All files (*.*)|*.*", filter_index = 0)
print("The user did choose: '%s'" % res)
res = system.ui.browse_directory_dialog("Choose a directory", path="C:\\")
print("The user did choose: '%s'" % res)
print("Now we query a single line string")
res = system.ui.query_string("What's your name?")
print("Nice to meet you, dear %s." % res)
print("Now we query a multi line string")
res = system.ui.query_string("Please tell me a nice story about your life!", multi_line=True)
if (res):
print("Huh, that has been a long text, at least %s characters!" % len(res))
else:
print("Hey, don't be lazy!")
Exemple : manipulation de l'objet Informations sur le projet
Dans le script ProjectInfoExample.py, nous avons mis quelques informations dans le Informations sur le projet objet. Les informations les plus importantes, telles que Titre et Version, possèdent des propriétés explicites. Cependant, vous pouvez lire et écrire tout autre champ d'information au moyen de dictionary syntaxe. Par exemple, celles recommandées pour les propriétés d'un projet de bibliothèque.
L'exemple ci-dessous peut paraître irréaliste, mais un code similaire est utilisé dans les serveurs de build qui créent, testent et, éventuellement, publient des projets de bibliothèques automatiques et d'autres projets. Le ScriptEngine est un élément clé de la création de systèmes d'intégration continue (CI) et de livraison continue (CD).
ProjectInfoExample.py# encoding:utf-8
from __future__ import print_function
proj = projects.load("D:\Some.library")
info = proj.get_project_info()
# Set some values
info.company = "Test Library Ltd"
info.title = "Script Test Project"
info.version = (0, 8, 15, 4711)
info.default_namespace = "testlibrary"
info.author = "Python von Scriptinger"
# some values recommended in the library toolchain
info.values["DefaultNamespace"] = "testlibrary"
info.values["Placeholder"] = "testlibrary"
info.values["DocFormat"] = "reStructuredText"
# now we set a custom / vendor specific value.
info.values["SpecialDeviceId"] = "PLC0815_4711"
# Enable generation of Accessor functions, so the IEC
# application can display the version in an info screen.
info.change_accessor_generation(True)
# And set the library to released
info.released = True;
proj.save()Exemple : appel de commandes externes et importation de fichiers PLCopenXML
L'exemple de script DeviceImportFromSVN.py obtient un fichier PLCopenXML à partir d'un programme externe (dans ce cas, un client SVN) et l'importe dans un nouveau fichier créé CODESYS projet.
Pour utiliser le script, vous devez modifier les chemins d'accès à votre environnement.
DeviceImportFromSVN.py# encoding:utf-8
# Imports a Device in PLCopenXML from Subversion via command line svn client.
# We enable the new python 3 print syntax
from __future__ import print_function
import sys, os
# some variable definitions:
SVNEXE = r"C:\Program Files\Subversion\bin\svn.exe"
XMLURL = "file:///D:/testrepo/testfolder/TestExport.xml"
PROJECT = r"D:\test.project"
# clean up any open project:
if projects.primary:
projects.primary.close()
# Fetch the plcopenxml data from subversion.
# We'll catch the output of the program into the xmldata variable.
# The 'with' construct automatically closes the open pipe for us.
with os.popen('"' + SVNEXE + '" cat ' + XMLURL, 'r') as pipe:
xmldata = pipe.read()
# create a new project:
proj = projects.create(PROJECT)
# import the data into the project.
proj.import_xml(xmldata, False)
# and finally save. :-)
proj.save()
print("--- Script finished. ---")Exemples : Archivage de projets
Les fonctions open_archive() et save_archive() sont des fonctions de script permettant d'extraire une archive de projet ou de sauvegarder un projet en tant qu'archive. Pour ces deux fonctions, ArchiveCategories peut être spécifié.
Pour ça,
open_archive()accepte le paramètrecategories_to_extract.save_archive()accepte le paramètreadditional_categories.
ArchiveCategories sont des catégories d'archives de projet qui sont extraites avec les archives de projet dans le cas de open_archive() ou archivé avec les archives du projet dans le cas de save_archive().
Exemples: open_archive()
Divers exemples de open_archive() avec le paramètre categories_to_extract sont présentés ci-dessous :
Comportement par défaut: categories_to_extract=None
Si categories_to_extract ne sont pas explicitement spécifiés, alors le paramètre est défini sur None. Toutes les catégories sont extraites des archives du projet.
# Default projects.open_archive(stArchiveFile=r"D:\Tests\Test.projectarchive", stProjectPath=r"D:\Tests", bOverwrite=True)
Liste vide: categories_to_extract=[]
Si le paramètre categories_to_extract est explicitement spécifié avec une liste vide, alors aucune catégorie n'est extraite de l'archive du projet.
# Passing empty list projects.open_archive(stArchiveFile=r"D:\Tests\Test.projectarchive", stProjectPath=r"D:\Tests", bOverwrite=True, categories_to_extract=[])
Plusieurs catégories
Plusieurs catégories peuvent être spécifiées dans le paramètre categories_to_extract Seules les catégories spécifiées sont également extraites.
# Multiple categories projects.open_archive(stArchiveFile=r"D:\Tests\Test.projectarchive", stProjectPath=r"D:\Tests", bOverwrite=True, categories_to_extract=[ArchiveCategories.libraries, ArchiveCategories.devices])
Erreurs possibles
Si les catégories sont spécifiées dans categories_to_extract qui n'existent pas dans le présent CODESYS Lors de l'installation, un message d'erreur s'affiche. L'archive du projet ne peut être extraite tant que la catégorie manquante n'est pas installée ou que la catégorie n'est pas supprimée du paramètre du script.
Exemples: save_archive()
Divers exemples de save_archive() avec le paramètre additional_categories sont présentés ci-dessous :
Comportement par défaut
Si additional_categories ne sont pas explicitement définies, alors les catégories par défaut de la CODESYS Les interfaces sont également archivées.
Aucune catégorie: additional_categories=None
Si additional_categories est explicitement défini sur None dans le script, aucune catégorie ne sera archivée.
Plusieurs catégories
Plusieurs catégories peuvent être spécifiées dans le paramètre additional_categories Seules les catégories spécifiées seront incluses dans les archives.
# Muliple categories projects.save_archive(path=r"D:\Tests", comment="A new project", additional_files=[], additional_categories=[ArchiveCategories.libraries, ArchiveCategories.devices])
Exemple avancé : Appeler une bibliothèque depuis SVN et l'installer dans CODESYS
L'exemple de script suivant permet d'appeler et d'installer une bibliothèque dans un environnement de test continu (CT) afin de la tester. Outre les tests standard,CODESYS, le CODESYS SVN le module complémentaire doit également être installé avec une licence valide.
import tempfile
if projects.primary:
projects.primary.close()
tempdir = tempfile.mkdtemp()
URL = "svn://localhost/testrepo/trunk/SvnTestLibrary/"
proj = svn.checkout(URL, tempdir, "testlibrary", as_library=True)
proj.save()
repo = librarymanager.repositories[0]
librarymanager.install_library(proj.path, repo, True)
proj.close()