py_ext user python code can now know about global variables shared with PLC. updated tests/python accordingly
--- a/py_ext/PythonFileCTNMixin.py Mon Feb 02 16:51:35 2015 +0100
+++ b/py_ext/PythonFileCTNMixin.py Mon Feb 02 23:11:01 2015 +0100
@@ -7,7 +7,7 @@
from PythonEditor import PythonEditor
class PythonFileCTNMixin(CodeFile):
-
+
CODEFILE_NAME = "PyFile"
SECTIONS_NAMES = [
"globals",
@@ -16,45 +16,45 @@
"start",
"stop"]
EditorType = PythonEditor
-
+
def __init__(self):
CodeFile.__init__(self)
-
+
filepath = self.PythonFileName()
-
+
if os.path.isfile(filepath):
PythonParser = GenerateParserFromXSD(
- os.path.join(os.path.dirname(__file__), "py_ext_xsd.xsd"))
-
+ os.path.join(os.path.dirname(__file__), "py_ext_xsd.xsd"))
+
xmlfile = open(filepath, 'r')
pythonfile_xml = xmlfile.read()
xmlfile.close()
-
+
pythonfile_xml = pythonfile_xml.replace(
- 'xmlns="http://www.w3.org/2001/XMLSchema"',
+ 'xmlns="http://www.w3.org/2001/XMLSchema"',
'xmlns:xhtml="http://www.w3.org/1999/xhtml"')
for cre, repl in [
(re.compile("(?<!<xhtml:p>)(?:<!\[CDATA\[)"), "<xhtml:p><![CDATA["),
(re.compile("(?:]]>)(?!</xhtml:p>)"), "]]></xhtml:p>")]:
pythonfile_xml = cre.sub(repl, pythonfile_xml)
-
+
try:
python_code, error = PythonParser.LoadXMLString(pythonfile_xml)
- if error is None:
+ if error is None:
self.CodeFile.globals.setanyText(python_code.getanyText())
os.remove(filepath)
self.CreateCodeFileBuffer(False)
self.OnCTNSave()
except Exception, exc:
error = unicode(exc)
-
+
if error is not None:
self.GetCTRoot().logger.write_error(
- _("Couldn't import old %s file.") % CTNName)
-
+ _("Couldn't import old %s file.") % self.CTNName())
+
def CodeFileName(self):
return os.path.join(self.CTNPath(), "pyfile.xml")
-
+
def PythonFileName(self):
return os.path.join(self.CTNPath(), "py_ext.xml")
@@ -64,25 +64,26 @@
return self.PreSectionsTexts.get(section,"") + "\n" + \
getattr(self.CodeFile, section).getanyText() + "\n" + \
self.PostSectionsTexts.get(section,"")
-
+
def CTNGenerate_C(self, buildpath, locations):
- # location string for that CTN
- location_str = "_".join(map(lambda x:str(x),
+ # location string for that CTN
+ location_str = "_".join(map(lambda x:str(x),
self.GetCurrentLocation()))
configname = self.GetCTRoot().GetProjectConfigNames()[0]
-
-
+
+
# python side PLC global variables access stub
globalstubs = "\n".join(["""\
_%(name)s_ctype, _%(name)s_unpack, _%(name)s_pack = \\
TypeTranslator["%(IECtype)s"]
_PySafeGetPLCGlob_%(name)s = PLCBinary.__SafeGetPLCGlob_%(name)s
_PySafeGetPLCGlob_%(name)s.restype = None
-_PySafeGetPLCGlob_%(name)s.argtypes = [ctypes.POINTER(_%(name)s_ctype)]
+_PySafeGetPLCGlob_%(name)s.argtypes = [ctypes.POINTER(_%(name)s_ctype)]
_PySafeSetPLCGlob_%(name)s = PLCBinary.__SafeSetPLCGlob_%(name)s
_PySafeSetPLCGlob_%(name)s.restype = None
_PySafeSetPLCGlob_%(name)s.argtypes = [ctypes.POINTER(_%(name)s_ctype)]
+_PySafePLCGlobals.append(("%(name)s","%(IECtype)s"))
""" % { "name": variable.getname(),
"configname": configname.upper(),
"uppername": variable.getname().upper(),
@@ -101,19 +102,23 @@
else:
rtcalls += " pass\n\n"
- globalsection = self.GetSection("globals")
+ globalsection = self.GetSection("globals")
+
+ pyextname = self.CTNName()
PyFileContent = """\
#!/usr/bin/env python
# -*- coding: utf-8 -*-
## Code generated by Beremiz python mixin confnode
-##
-
+##
+
## Code for PLC global variable access
from targets.typemapping import TypeTranslator
-import ctypes
+import ctypes
+_PyExtName = "%(pyextname)s"
+_PySafePLCGlobals = []
%(globalstubs)s
-
+
## User code in "global" scope
%(globalsection)s
@@ -123,14 +128,14 @@
""" % locals()
# write generated content to python file
- runtimefile_path = os.path.join(buildpath,
+ runtimefile_path = os.path.join(buildpath,
"runtime_%s.py"%location_str)
runtimefile = open(runtimefile_path, 'w')
runtimefile.write(PyFileContent.encode('utf-8'))
runtimefile.close()
# C code for safe global variables access
-
+
vardecfmt = """\
extern __IEC_%(IECtype)s_t %(configname)s__%(uppername)s;
IEC_%(IECtype)s __%(name)s_rbuffer = __INIT_%(IECtype)s;
@@ -159,13 +164,13 @@
}
AtomicCompareExchange((long*)&__%(name)s_wlock, 1, 0);
}
-"""
+"""
varpubfmt = """\
if(!AtomicCompareExchange(&__%(name)s_rlock, 0, 1)){
__%(name)s_rbuffer = %(configname)s__%(uppername)s.value;
AtomicCompareExchange((long*)&__%(name)s_rlock, 1, 0);
}
-"""
+"""
var_str = map("\n".join, zip(*[
map(lambda f : f % varinfo,
@@ -180,10 +185,10 @@
vardec, varret, varpub = var_str
else:
vardec = varret = varpub = ""
-
+
PyCFileContent = """\
-/*
- * Code generated by Beremiz py_ext confnode
+/*
+ * Code generated by Beremiz py_ext confnode
* for safe global variables access
*/
#include "iec_types_all.h"
@@ -208,15 +213,15 @@
%(varpub)s
}
""" % locals()
-
+
Gen_PyCfile_path = os.path.join(buildpath, "PyCFile_%s.c"%location_str)
pycfile = open(Gen_PyCfile_path,'w')
pycfile.write(PyCFileContent)
pycfile.close()
-
+
matiec_flags = '"-I%s"'%os.path.abspath(
self.GetCTRoot().GetIECLibPath())
-
+
return ([(Gen_PyCfile_path, matiec_flags)],
"",
True,
--- a/tests/python/plc.xml Mon Feb 02 16:51:35 2015 +0100
+++ b/tests/python/plc.xml Mon Feb 02 23:11:01 2015 +0100
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<project xmlns="http://www.plcopen.org/xml/tc6_0201" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xhtml="http://www.w3.org/1999/xhtml" xsi:schemaLocation="http://www.plcopen.org/xml/tc6_0201">
<fileHeader companyName="" productName="Beremiz" productVersion="0.0" creationDateTime="2008-12-14T16:21:19"/>
- <contentHeader name="Beremiz Python Support Tests" modificationDateTime="2014-06-12T17:48:28">
+ <contentHeader name="Beremiz Python Support Tests" modificationDateTime="2015-02-02T23:04:42">
<coordinateInfo>
<pageSize x="1024" y="1024"/>
<fbd>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/python/py_ext_0@py_ext/baseconfnode.xml Mon Feb 02 23:11:01 2015 +0100
@@ -0,0 +1,2 @@
+<?xml version='1.0' encoding='utf-8'?>
+<BaseParams xmlns:xsd="http://www.w3.org/2001/XMLSchema" IEC_Channel="2" Name="py_ext_0"/>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/python/py_ext_0@py_ext/pyfile.xml Mon Feb 02 23:11:01 2015 +0100
@@ -0,0 +1,29 @@
+<?xml version='1.0' encoding='utf-8'?>
+<PyFile xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <variables>
+ <variable name="SomeVarName" type="DINT"/>
+ <variable name="Grumpf" type="STRING"/>
+ </variables>
+ <globals>
+ <xhtml:p><![CDATA[
+]]></xhtml:p>
+ </globals>
+ <init>
+ <xhtml:p><![CDATA[
+print "Exposed variables :", _PySafePLCGlobals
+print "PyExtName :", _PyExtName
+]]></xhtml:p>
+ </init>
+ <cleanup>
+ <xhtml:p><![CDATA[
+]]></xhtml:p>
+ </cleanup>
+ <start>
+ <xhtml:p><![CDATA[
+]]></xhtml:p>
+ </start>
+ <stop>
+ <xhtml:p><![CDATA[
+]]></xhtml:p>
+ </stop>
+</PyFile>