import os
from PLCControler import UndoBuffer
from PythonEditor import PythonEditor
from xml.dom import minidom
from xmlclass import GenerateClassesFromXSD
import cPickle
from CodeFileTreeNode import CodeFile
PythonClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "py_ext_xsd.xsd"))
class PythonFileCTNMixin(CodeFile):
CODEFILE_NAME = "PyFile"
SECTIONS_NAMES = [
"globals",
"init",
"cleanup",
"start",
"stop"]
EditorType = PythonEditor
def __init__(self):
CodeFile.__init__(self)
filepath = self.PythonFileName()
python_code = PythonClasses["Python"]()
if os.path.isfile(filepath):
xmlfile = open(filepath, 'r')
tree = minidom.parse(xmlfile)
xmlfile.close()
for child in tree.childNodes:
if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "Python":
python_code.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"])
self.CodeFile.globals.settext(python_code.gettext())
os.remove(filepath)
self.CreateCodeFileBuffer(False)
self.OnCTNSave()
def CodeFileName(self):
return os.path.join(self.CTNPath(), "pyfile.xml")
def PythonFileName(self):
return os.path.join(self.CTNPath(), "py_ext.xml")
PreSectionsTexts = {}
PostSectionsTexts = {}
def GetSection(self,section):
return self.PreSectionsTexts.get(section,"") + "\n" + \
getattr(self.CodeFile, section).gettext() + "\n" + \
self.PostSectionsTexts.get(section,"")
def CTNGenerate_C(self, buildpath, locations):
current_location = self.GetCurrentLocation()
# define a unique name for the generated C file
location_str = "_".join(map(lambda x:str(x), current_location))
# Generate Beremiz python runtime variables code
config = self.GetCTRoot().GetProjectConfigNames()[0]
variables_str = ""
for variable in self.CodeFile.variables.variable:
global_name = "%s_%s" % (config.upper(), variable.getname().upper())
variables_str += "# global_var:%s python_var:%s type:%s initial:%s\n" % (
global_name,
variable.getname(),
variable.gettype(),
str(variable.getinitial()))
# Runtime calls (start, stop, init, and cleanup)
rtcalls = ""
for section in self.SECTIONS_NAMES:
if section != "globals":
rtcalls += "def _runtime_%s_%s():\n" % (location_str, section)
sectiontext = self.GetSection(section).strip()
if sectiontext:
rtcalls += ' ' + \
sectiontext.strip().replace('\n', '\n ')+"\n"
else:
rtcalls += " pass\n\n"
text = """\
#!/usr/bin/env python
# -*- coding: utf-8 -*-
## Code generated by Beremiz python mixin confnode
##
## Code for PLC global variable access
%s
## User code in "global" scope
%s
## Beremiz python runtime calls
%s
"""%( # variables
variables_str,
# globals
self.GetSection("globals"),
# Beremiz python runtime functions
rtcalls)
runtimefile_path = os.path.join(buildpath,
"runtime_%s.py"%location_str)
runtimefile = open(runtimefile_path, 'w')
runtimefile.write(text.encode('utf-8'))
runtimefile.close()
text = """\
/*
* Code generated by Beremiz py_ext confnode
* for safe global variables access
*/
#include "iec_types_all.h"
"""
# Adding variables
text += "/* User variables reference */\n"
for variable in self.CodeFile.variables.variable:
var_infos = {
"name": variable.getname(),
"global": "%s__%s" % (config.upper(),
variable.getname().upper()),
"type": "__IEC_%s_t" % variable.gettype()}
text += "extern %(type)s %(global)s;\n" % var_infos
text += "%(type)s __buffer_%(name)s;\n" % var_infos
text += "\n"
# Adding Beremiz confnode functions
text += "/* Beremiz confnode functions */\n"
text += "int __init_%s(int argc,char **argv)\n{\n"%location_str
text += "/*TODO*/\n"
text += " return 0;\n}\n\n"
text += "void __cleanup_%s(void)\n{\n"%location_str
text += "/*TODO*/\n"
text += "\n}\n\n"
text += "void __retrieve_%s(void)\n{\n"%location_str
text += "/*TODO*/\n"
text += "\n}\n\n"
text += "void __publish_%s(void)\n{\n"%location_str
text += "/*TODO*/\n"
text += "\n}\n\n"
Gen_PyCfile_path = os.path.join(buildpath, "PyCFile_%s.c"%location_str)
pycfile = open(Gen_PyCfile_path,'w')
pycfile.write(text)
pycfile.close()
matiec_flags = '"-I%s"'%os.path.abspath(
self.GetCTRoot().GetIECLibPath())
return ([(Gen_PyCfile_path, matiec_flags)],
"",
False,
("runtime_%s.py"%location_str, file(runtimefile_path,"rb")))