Skip to main content

スクリプトを使用してアクセスする CODESYS 機能性

すべてのオブジェクトとコマンド CODESYS スクリプトの提供は、「scriptengine"Pythonモジュール。スクリプトが開始されるたびに、暗黙的に <code>from scriptengine import *</code> 結果。これにより、簡単にアクセスできます CODESYS。ただし、スクリプトがアクセスを必要とするモジュールをインポートする場合 CODESYS APIの場合、これらのモジュールはモジュールをインポートする必要があります scriptengine 彼ら自身。

Pythonスクリプトのエントリポイントとして使用できる主なオブジェクト(カテゴリ)を次の表に示します。エントリポイントの詳細なドキュメントは、 APIリファレンスドキュメントCODESYS ScriptEngine。

オブジェクト

説明

システム

一般へのアクセス CODESYS 機能性

例:

  • 終了 CODESYS

  • 一般的なユーザーインターフェイスの処理

  • メッセージメモリへのアクセス(コンパイラメッセージを含む)

  • 遅延バーとプログレスバーの制御

プロジェクト

へのアクセス CODESYS 3つのナビゲータービュー(デバイス、POU、モジュール)を1つのプロジェクトツリーに結合するオブジェクトツリーとしてのプロジェクト

プロジェクトのロード、作成、保存、およびクローズも可能です

プロジェクト内のほとんどのオブジェクトには、コンパイル、ST POUへのアクセス、エクスポート、インポート、デバイス構成など、詳細な機能を備えた特別なメソッドがあります。

オンライン

オンライン機能へのアクセス

例:

  • デバイスとアプリケーションにログインします

  • アクセスデータ(ユーザー名、パスワード)の管理

  • ネットワークスキャンのパフォーマンス

  • ゲートウェイ管理

librarymanager

ライブラリリポジトリの管理、およびライブラリの表示、インストール、削除を許可します

device_repository

デバイスリポジトリの処理。デバイスの説明のインポートとエクスポート

modulerepository

の管理 CODESYS Application Composer モジュールと CODESYS Application Composer リポジトリ

アクセス用の特定のサンプルスクリプトについては、以下を参照してください CODESYS-機能。詳細については、を参照してください。 APIリファレンスドキュメントCODESYS

例:現在のプロジェクトのデバイスツリーを印刷する

スクリプト PrintDeviceTree.py プロジェクト内を移動するための例です。開いているプロジェクト内のすべてのデバイスの階層表示の出力を作成します。

いくつかのデバイスオブジェクトを含むプロジェクトをロードし、スクリプトを実行します。

22. 例: 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. ---")

(「デバイス」ビューからの)デバイスツリーがメッセージビューに表示され、デバイス以外のすべてのオブジェクトが除外されます。

_cds_script_messages_print_device_tree.png


例:変数の読み取り

スクリプト ReadVariable.py デバイスにログインし、必要に応じてアプリケーションを起動します。次に、変数の値 PLC_PRG.iVar1 読み取られて出力されます。スクリプトを試すには、プロジェクトパスと変数名を変更する必要があります。

23. 例: 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()


スクリプトの拡張で ReadVariable.py、 スクリプト MailVariables.py レシピファイルから変数と式をロードし、コントローラーからそれらの現在の値を読み取ります。次に、これらの値が同じファイルに書き戻されます。さらに、はPython SMTPライブラリを使用して、すべての変数のリストを含む添付ファイル付きの電子メールを送信します。

スクリプトを使用するには、環境へのパス、電子メールアドレス、およびSMTPサーバーの名前を変更する必要があります。

24. 例: 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()


例:POUの作成と編集

スクリプト CreateDut.py オブジェクトを作成します MyStructMyAlias、 と MyUnion の中に CODESYS 事業。フォルダ DataTypes すでに存在している必要があります。

25. 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)


例:ユーザーインターフェース/ユーザーとの対話

場合によっては、スクリプトはユーザーと対話する必要があります。最も一般的なインタラクション用にいくつかのシンプルなAPIを提供します。サンプルスクリプト System_UI_Test.py この点で可能なすべての機能を示しています。

26. 例: 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!")

print("Username and passwort prompts...")
res = system.ui.query_password("Please enter your favourite password!", cancellable=True)
if res:
        print("Huh, it's very careless to tell me your favourite password '%s'!" % res)
else:
    print("Ok, if you don't want...")

res = system.ui.query_credentials("Now, for real...")
if res:
        print("Username '%s' and password '%s'" % res) # res is a 2-tuple
else:
    print("Sigh...")


例:操作 プロジェクト情報 物体

スクリプト内 ProjectInfoExample.py、にいくつかの情報を設定します プロジェクト情報 物体。などの最も重要な情報項目 タイトルバージョン、明示的なプロパティがあります。ただし、を使用して他の情報フィールドを読み書きできます。 dictionary 構文。たとえば、ライブラリプロジェクトのプロパティに推奨されるもの。

以下の例はやや非現実的に見えるかもしれませんが、自動ライブラリプロジェクトやその他のプロジェクトを作成、テスト、場合によってはリリースするビルドサーバーで同様のコードが使用されています。 ScriptEngineは、CI(継続的インテグレーション)およびCD(継続的デリバリー)システムを作成するための重要な要素の1つです。

27. 例: 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()


例:外部コマンドの呼び出しとPLCOpenXMLファイルのインポート

サンプルスクリプト DeviceImportFromSVN.py 外部プログラム(この場合はSVNクライアント)からPLCOpenXMLファイルを取得し、新しく作成されたものにインポートします CODESYS 事業。

スクリプトを使用するには、環境へのパスを変更する必要があります。

28. 例: 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. ---")


高度な例:SVNからライブラリを呼び出してインストールする CODESYS

次のサンプルスクリプトは、CT(継続的テスト)環境の一部としてライブラリの呼び出しとインストールを実行して、ライブラリをテストできるようにすることができます。標準に加えて-CODESYSCODESYS SVN アドオンも有効なライセンスでインストールする必要があります。

29.
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()