CODESYS - the IEC 61131-3 automation software

Welcome to the official CODESYS Forum by 3S-Smart Software Solutions GmbH | A member of the CODESYS Group
Deutsche Version English version russian version 
It is currently Sat Mar 23, 2019 12:06 pm

All times are UTC+01:00




Post new topic  Reply to topic  [ 42 posts ]  Go to page 1 2 3 Next
Author Message
PostPosted: Thu May 05, 2011 3:03 pm 
Offline
Frequent User
Frequent User
User avatar

Joined: Fri Mar 18, 2011 4:12 pm
Posts: 266
In this thread we would like to collect samples and recipes to show you how to implement more complex procedures in the CoDeSys script language.

_________________
Check out the CODESYS store: http://store.codesys.com/

CODESYS® a trademark of 3S-Smart Software Solutions GmbH
Inspiring Automation Solutions


Top
   
PostPosted: Thu May 05, 2011 3:10 pm 
Offline
Frequent User
Frequent User
User avatar

Joined: Fri Mar 18, 2011 4:12 pm
Posts: 266
This example is a further development of example 1 from the documentation.

Purpose: To read a controller variable out of an external program or a batch file and to print it on the standard display so that it can be evaluated, e.g.:
Code:
C:\Program Files\3S CoDeSys V3.4 SP3\CoDeSys\Common>start /wait CoDeSys.exe --profile="CoDeSys V3.4 SP3" --noUI --runscript="D:\TestScripts\ReadVariable.py" 

This is the actual code:
Code:
# We use the python 3 syntax for print
from __future__ import print_function
   
# Our project file is in the data subdirectory of the directory containing
# the script, so we calculate the appropriate path.
import os
scriptdir = os.path.dirname(__file__) # Directory of our script.
datadir = os.path.join(scriptdir, "Data") # Enter the subdirectory.
projectpath = os.path.join(datadir, "Ampel.project") # And add the project name.

# Now, we can open the project.
proj = projects.open(projectpath)

# We fetch the active application.
app = proj.active_application

# And create the online application for it.
onlineapp = online.create_online_application(app)

# We login into the device.
onlineapp.login(OnlineChangeOption.Try, True)

# We start the application, if necessary.
if not onlineapp.application_state == ApplicationState.run:
    onlineapp.start()

# We let the app do its work for some time...
system.delay(1000)

# We read the value of the variable we're interested in.
value = onlineapp.read_value("PLC_PRG.iVar1")

# We output the value to standard output, so our caller can process it.
print(value)

# Last but not least, we clean up.
onlineapp.logout()
proj.close()


In a windows command window, this looks as follows:

Code:
C:\Program Files\3S CoDeSys V3.4 SP3\CoDeSys\Common>start /wait CoDeSys --profile="CoDeSys V3.4 SP3" --noUI --runscript="D:\TestScripts\Forum_ReadVariable.py"
------ Build started: Application: Device.App -------
The application is up to date
Build: Information: Size of generated code: 6419 bytes
Build: Information: Size of global data: 2594 bytes
Build: Information: Total allocated memory size for code and data: 10997 bytes
Build: Information: Memory area 0 contains  Data, Input, Output, Memory and Code
: highest used address: 1048576, largest contiguous memory gap: 1037579 (98 %)
Compile complete -- 0 errors, 0 warnings
INT#2263

C:\Program Files\3S CoDeSys V3.4 SP3\CoDeSys\Common>

_________________
Check out the CODESYS store: http://store.codesys.com/

CODESYS® a trademark of 3S-Smart Software Solutions GmbH
Inspiring Automation Solutions


Last edited by M.Schaber on Wed Jun 29, 2011 3:17 pm, edited 1 time in total.

Top
   
PostPosted: Thu May 05, 2011 3:14 pm 
Offline
Frequent User
Frequent User
User avatar

Joined: Fri Mar 18, 2011 4:12 pm
Posts: 266
Expecially when one calls Scripts from the command line interpreter, a possibility to pass parameters to the scripts would be handy.

As a workaroound, one can use environment variables:
Code:
from __future__ import print_function
import os

print("project to open: ", os.environ["PROJECT"])

# We assert that the application on the device is already running.
proj = projects.open(os.environ["PROJECT"])
onlineapp = online.create_online_application(proj.active_application)
onlineapp.login(OnlineChangeOption.Try, True)

print("variables to read:")
for var in os.environ["VARIABLES"].split(","):
   print ("    ", var, " = ", onlineapp.read_value(var))


This can be launched from a batch file as follows:
Code:
@echo off
SET PROJECT=D:\TestScripts\Data\OnlineTest.project
SET VARIABLES=POU.testint,POU.testoutput
start /wait CoDeSys.exe --profile="CoDeSys V3.4 SP3" --noUI --runscript="D:\TestScripts\Forum_Environment.py"


The result looks like this:
Code:
C:\Program Files\3S CoDeSys V3.4 SP3\CoDeSys\Common>d:\TestScripts\Forum_Environment.bat
project to open:  D:\TestScripts\Data\OnlineTest.project
------ Build started: Application: CoDeSys_Control_Win_V3.Application -------
The application is up to date
Build: Information: Size of generated code: 6453 bytes
Build: Information: Size of global data: 2606 bytes
Build: Information: Total allocated memory size for code and data: 12505 bytes
Build: Information: Memory area 0 contains  Data, Input, Output, Memory and Code: highest used address: 1048576, largest contiguous memory gap: 1036071 (98 %)
Compile complete -- 0 errors, 0 warnings
variables to read:
     POU.testint  =  INT#1
     POU.testoutput  =  INT#3
C:\Program Files\3S CoDeSys V3.4 SP3\CoDeSys\Common>

_________________
Check out the CODESYS store: http://store.codesys.com/

CODESYS® a trademark of 3S-Smart Software Solutions GmbH
Inspiring Automation Solutions


Top
   
PostPosted: Thu May 05, 2011 3:17 pm 
Offline
Frequent User
Frequent User
User avatar

Joined: Fri Mar 18, 2011 4:12 pm
Posts: 266
Currently, scripts can add devices only via the Device ID. If one doesn't know the ID of a specific device, the following script can help to find out. Just insert the device into the current project, and launch the script:

Code:
# Prints out all devices and other objects in the currently open project.

# We enable the new python 3 print syntax
from __future__ import print_function

# define the printing function
def printtree(treeobj, depth=0):
    name = treeobj.get_name(False)   
    if treeobj.is_device:
      deviceid = treeobj.get_device_identification()
      print("{0} - {1} {2}".format("   "*depth, name, deviceid))
   
    for child in treeobj.get_children(False):
        printtree(child, depth+1)

for obj in projects.primary.get_children():
   printtree(obj)

print("--- Script finished. ---")


The output looks like this:
Code:
- CoDeSys_Control_Win_V3 DeviceID(type=4096, Id='0000 0001', Version='3.4.2.0')
   - CANbus DeviceID(type=15, Id='181015', Version='3.4.2.0')
      - CANopen_Manager DeviceID(type=16, Id='181016', Version='3.4.2.0')
--- Script finished. ---


And now you know the Device ID you needed.

_________________
Check out the CODESYS store: http://store.codesys.com/

CODESYS® a trademark of 3S-Smart Software Solutions GmbH
Inspiring Automation Solutions


Top
   
PostPosted: Thu May 05, 2011 3:21 pm 
Offline
Frequent User
Frequent User
User avatar

Joined: Fri Mar 18, 2011 4:12 pm
Posts: 266
Some users want to fetch the starting basis for their projects from a Subversion repository.

The following example (which is similar to Example 4 in the documentation) creates a new project, and adds a device via PLCOpenXML.
Code:
# 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.
# 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)

# create the import reporter
class Reporter(ImportReporter):
   def error(self, message):
      system.write_message(Severity.Error, message)

   def warning(self, message):
      system.write_message(Severity.Warning, message)
   
   def resolve_conflict(self, obj):
      return ConflictResolve.Copy
   
   def added(self, obj):
      print("added: ", obj)

   def replaced(self, obj):
      print("replaced: ", obj)

   def skipped(self, obj):
      print("skipped: ", obj)
      
   @property
   def aborting(self):
      return False

# create the importer instance.
reporter = Reporter()      

# import the data into the project.
proj.import_xml(reporter, xmldata)

# and finally save. :-)
proj.save()

print("--- Script finished. ---")


The subversion command line client which is needed for the script above is available for free from several providers. The Subversion Download Page contains links to some of them, the Cygwin-Project contains another one.

_________________
Check out the CODESYS store: http://store.codesys.com/

CODESYS® a trademark of 3S-Smart Software Solutions GmbH
Inspiring Automation Solutions


Top
   
PostPosted: Tue Aug 02, 2011 1:31 pm 
Offline
Frequent User
Frequent User
User avatar

Joined: Fri Mar 18, 2011 4:12 pm
Posts: 266
Example snippets: Quickly finding library managers:

Find all library managers in the project:
Code:
objects = proj.get_children(recursive=True)

for candidate in objects:
    if candidate.is_libman:   
        print(candidate)


The quick way is via list comprehension:
Code:
managers = [i for i in proj.get_children(True) if i.is_libman]


Or via the filter function:
Code:
managers = filter(lambda i: i.is_libman, proj.get_children(True))


If you are only interested in the top level library manager (the one in the POU view), you set recursive to False.

Remind that you can also search under a specific device or application if you call get_children on that object instead of the project.

_________________
Check out the CODESYS store: http://store.codesys.com/

CODESYS® a trademark of 3S-Smart Software Solutions GmbH
Inspiring Automation Solutions


Top
   
PostPosted: Tue Aug 02, 2011 1:42 pm 
Offline
Frequent User
Frequent User
User avatar

Joined: Tue Jun 06, 2006 9:03 am
Posts: 408
About the device ID (for automatically inserting devices to your project):

Since 3.4.4.0 you can go to the information tab of the device which shows all details like type, ID and version.
This makes it much easier than first creating a script to get this information.


Top
   
PostPosted: Tue Aug 02, 2011 2:05 pm 
Offline
Frequent User
Frequent User
User avatar

Joined: Fri Mar 18, 2011 4:12 pm
Posts: 266
TimvH wrote:
About the device ID (for automatically inserting devices to your project):

Since 3.4.4.0 you can go to the information tab of the device which shows all details like type, ID and version.
This makes it much easier than first creating a script to get this information.


It seems you're right, but unfortunately, it seems that module IDs are not displayed there. :cry:

_________________
Check out the CODESYS store: http://store.codesys.com/

CODESYS® a trademark of 3S-Smart Software Solutions GmbH
Inspiring Automation Solutions


Top
   
PostPosted: Thu Oct 06, 2011 9:50 am 
Offline

Joined: Tue Oct 04, 2011 9:21 am
Posts: 27
Hi hi,

i was trying to understand the following code:

# We use the python 3 syntax for print
from __future__ import print_function

# Our project file is in the data subdirectory of the directory containing
# the script, so we calculate the appropriate path.
import os
scriptdir = os.path.dirname(__file__) # Directory of our script.
datadir = os.path.join(scriptdir, "Data") # Enter the subdirectory.
projectpath = os.path.join(datadir, "Ampel.project") # And add the project name.
...................................

but I recieve always the following error: NameError: name 'projects' is not defined
could u help please and tell me how to correct it?
Thank you


Top
   
PostPosted: Fri Oct 07, 2011 9:45 am 
Offline
Frequent User
Frequent User
User avatar

Joined: Fri Mar 18, 2011 4:12 pm
Posts: 266
Hi,

aoj wrote:

i was trying to understand the following code:

# We use the python 3 syntax for print
from __future__ import print_function


This statement enables the python 3 syntax for print (See the python documentation for more details). I use this syntax so that this script can run with both Python 2 and python 3 without modifications.

aoj wrote:
# Our project file is in the data subdirectory of the directory containing
# the script, so we calculate the appropriate path.
import os
scriptdir = os.path.dirname(__file__) # Directory of our script.
datadir = os.path.join(scriptdir, "Data") # Enter the subdirectory.
projectpath = os.path.join(datadir, "Ampel.project") # And add the project name.
...................................

This code calculates the location of the project "Ampel.project" relative to the directory where the script itsself is. It assumes that in the directory containing the script file there is a subdirectory "Data" containing the "Ampel.project" file. This just happens to be the directory layout I used for my internal test scripts.

aoj wrote:
but I recieve always the following error: NameError: name 'projects' is not defined
could u help please and tell me how to correct it?


"projects" is an object imported into the namespace for scripts running in CoDeSys, so it is only available if your script is being started in CoDeSys directly (either via the "Execute Script" menu command or button, or via the "--runscript" command line parameter.)

For modules imported by your scripts, this automatic injection does not take place because it would break some modules from the standard library. Simply add "from scriptengine import *" at the top of your module.

If you run the script from outside of CoDeSys (for example in the py.exe or ipy.exe interpreters, or an IDE like IDLE or Eric), it won't work, since the codesys environment is not available there.

But remember that you can start CoDeSys with the "--runscript" and "--NoUI" parameters to execute python scripts within CoDeSys. (See the documentation for more information.)

_________________
Check out the CODESYS store: http://store.codesys.com/

CODESYS® a trademark of 3S-Smart Software Solutions GmbH
Inspiring Automation Solutions


Last edited by M.Schaber on Mon Oct 10, 2011 10:27 am, edited 1 time in total.

Top
   
PostPosted: Fri Oct 07, 2011 2:35 pm 
Offline

Joined: Tue Oct 04, 2011 9:21 am
Posts: 27
Hi Hi,

thank u for the reply.

"If you run the script from outside of CoDeSys (for example in the py.exe or ipy.exe interpreters, or an IDE like IDLE or Eric), it won't work, since the codesys environment is not available there."
I run the script from IDLE! It means it won't work.

I want actually to export a xml-file with python. I have a CoDeSys-Project named Test.project. The first step ist to open this project, which i did with "os.startfile". The second step is to export the xml-file directly from python.

Could you give some tips??


Top
   
PostPosted: Fri Oct 07, 2011 3:01 pm 
Offline
Frequent User
Frequent User
User avatar

Joined: Fri Mar 18, 2011 4:12 pm
Posts: 266
Hi,

aoj wrote:
"If you run the script from outside of CoDeSys (for example in the py.exe or ipy.exe interpreters, or an IDE like IDLE or Eric), it won't work, since the codesys environment is not available there."
I run the script from IDLE! It means it won't work.


Yes. If you run the script from IDLE, it has no way to access the CoDeSys functionality. The CoDeSys ScriptEngine is not a bunch of ordinary python modules, but a so-called hosted environment, that means the Python interpreter is embedded (and deeply integrated) into the CoDeSys application.

aoj wrote:
I want actually to export a xml-file with python. I have a CoDeSys-Project named Test.project. The first step ist to open this project, which i did with "os.startfile". The second step is to export the xml-file directly from python.

Could you give some tips??


Ah, now I see. Your current approach would require the Python script from IDLE to magically recognize the running CoDeSys instance, and then send the commands to that application. Unfortunately, that is not how it currently works. (Note that os.startfile() gives you no way to wait for the application to finish startup and loading, so you would not know when you could actually start to send commands to CoDeSys.)

What you currently could do is something like
Code:
os.system(r'c:\Path\to\CoDeSys.exe --runscript="c:\Path\to\CoDeSysScript.py"')
and use an environment variable to pass the name of the CoDeSys project to the script. (See viewtopic.php?p=3803#p3803 for an example of parameter passing via environment variables.) Then, in the CoDeSysScript.py, you can load the project and export the files.

_________________
Check out the CODESYS store: http://store.codesys.com/

CODESYS® a trademark of 3S-Smart Software Solutions GmbH
Inspiring Automation Solutions


Top
   
PostPosted: Mon Oct 10, 2011 10:09 am 
Offline

Joined: Tue Oct 04, 2011 9:21 am
Posts: 27
Hi M.Schaber,

if i use the code: os.system(r'c:\Path\to\CoDeSys.exe --runscript="c:\Path\to\CoDeSysScript.py"' and in my CoDeSysScript.py should only open the project Test.project; is it fine to use os.startfile()??? or is there a better command to load the project?

Another question: what is the difference between using PLCOpenXML and using the native Export format of CoDeSys?

Thanks a lot.


Top
   
PostPosted: Mon Oct 10, 2011 10:25 am 
Offline
Frequent User
Frequent User
User avatar

Joined: Fri Mar 18, 2011 4:12 pm
Posts: 266
Hi, Aoj,

aoj wrote:
if i use the code: os.system(r'c:\Path\to\CoDeSys.exe --runscript="c:\Path\to\CoDeSysScript.py"' and in my CoDeSysScript.py should only open the project Test.project; is it fine to use os.startfile()??? or is there a better command to load the project?

Inside the CoDeSysScript.py, do not use os.startfile(). That will start a second instance of codesys loading the project, and you still don't have control over that second instance.

You need to open the project and do the export from within the CoDeSysScript.py. This may look like:
Code:
# .. initialization skipped
proj = projects.open(PathToProject)
device = proj.find('_3S_Testspec_Device')[0]
device.export_xml(reporter, ExportFileName, recursive = True)


projects.open, and the find and export_xml methods are provided by the CoDeSys environment.

aoj wrote:
Another question: what is the difference between using PLCOpenXML and using the native Export format of CoDeSys?

PLCOpenXML is a standardized format for interchange of data between independent IEC-61131 implementations. Due to that, it is interoperable with other software, but it is not lossless (some aspects may be lost if you export in that format).

The native Export format is CoDeSys-specific and less human-readable, but it is lossless.

So if you only use those exported objects for re-importing them into CoDeSys later, you use the native format. If you want to process those files using 3rd-party tools, you should use the PLCOpenXML format.

_________________
Check out the CODESYS store: http://store.codesys.com/

CODESYS® a trademark of 3S-Smart Software Solutions GmbH
Inspiring Automation Solutions


Top
   
PostPosted: Mon Oct 10, 2011 12:44 pm 
Offline

Joined: Tue Oct 04, 2011 9:21 am
Posts: 27
Thank you for the explanation about the difference between the PLCOpenXML and the native export format.

in a previous post we talked about the error: "NameError: name 'projects' is not defined".
you said i can correct this error by adding "from scriptengine import *" at the top of the module in condition i am starting CoDeSys with the "--runscript".

after adding "from scriptengine import *", i get the following error: "ImportError: No module named scriptengine" !!!!


Top
   
Display posts from previous:  Sort by  
Post new topic  Reply to topic  [ 42 posts ]  Go to page 1 2 3 Next

All times are UTC+01:00


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Limited