laurent@366: import os laurent@654: from PLCControler import UndoBuffer laurent@657: from PythonEditor import PythonEditor laurent@366: laurent@366: from xml.dom import minidom Laurent@1124: from xmlclass import GenerateClassesFromXSD laurent@366: import cPickle laurent@366: Laurent@1097: from CodeFileTreeNode import CodeFile Laurent@1097: Edouard@721: PythonClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "py_ext_xsd.xsd")) laurent@366: Laurent@1097: class PythonFileCTNMixin(CodeFile): laurent@366: Laurent@1124: CODEFILE_NAME = "PyFile" Laurent@1124: SECTIONS_NAMES = [ Laurent@1124: "globals", Laurent@1124: "init", Laurent@1124: "cleanup", Laurent@1124: "start", Laurent@1124: "stop"] laurent@657: EditorType = PythonEditor laurent@657: laurent@366: def __init__(self): Laurent@1097: CodeFile.__init__(self) laurent@366: laurent@366: filepath = self.PythonFileName() laurent@366: Laurent@1097: python_code = PythonClasses["Python"]() laurent@366: if os.path.isfile(filepath): laurent@366: xmlfile = open(filepath, 'r') laurent@366: tree = minidom.parse(xmlfile) laurent@366: xmlfile.close() laurent@366: laurent@366: for child in tree.childNodes: laurent@366: if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "Python": Laurent@1097: python_code.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"]) Laurent@1097: self.CodeFile.globals.settext(python_code.gettext()) Laurent@1097: os.remove(filepath) Laurent@1097: self.CreateCodeFileBuffer(False) Laurent@1097: self.OnCTNSave() Laurent@1097: Laurent@1097: def CodeFileName(self): Laurent@1097: return os.path.join(self.CTNPath(), "pyfile.xml") Laurent@1097: laurent@366: def PythonFileName(self): Edouard@721: return os.path.join(self.CTNPath(), "py_ext.xml") laurent@366: Edouard@1132: PreSectionsTexts = {} Edouard@1132: PostSectionsTexts = {} Edouard@1132: def GetSection(self,section): Edouard@1132: return self.PreSectionsTexts.get(section,"") + "\n" + \ Edouard@1132: getattr(self.CodeFile, section).gettext() + "\n" + \ Edouard@1132: self.PostSectionsTexts.get(section,"") Edouard@1132: Edouard@1132: Edouard@1132: def CTNGenerate_C(self, buildpath, locations): Edouard@1144: # location string for that CTN Edouard@1144: location_str = "_".join(map(lambda x:str(x), Edouard@1144: self.GetCurrentLocation())) Edouard@1144: configname = self.GetCTRoot().GetProjectConfigNames()[0] Edouard@1144: Edouard@1144: Edouard@1144: # python side PLC global variables access stub Edouard@1144: globalstubs = "\n".join(["""\ Edouard@1144: _%(name)s_ctype, _%(name)s_unpack, _%(name)s_pack = \\ Edouard@1144: TypeTranslator["%(IECtype)s"] Edouard@1144: _PySafeGetPLCGlob_%(name)s = PLCBinary.__SafeGetPLCGlob_%(name)s Edouard@1145: _PySafeGetPLCGlob_%(name)s.restype = None Edouard@1145: _PySafeGetPLCGlob_%(name)s.argtypes = [ctypes.POINTER(_%(name)s_ctype)] Edouard@1144: _PySafeSetPLCGlob_%(name)s = PLCBinary.__SafeSetPLCGlob_%(name)s Edouard@1144: _PySafeSetPLCGlob_%(name)s.restype = None Edouard@1144: _PySafeSetPLCGlob_%(name)s.argtypes = [ctypes.POINTER(_%(name)s_ctype)] Edouard@1144: """ % { "name": variable.getname(), Edouard@1144: "configname": configname.upper(), Edouard@1144: "uppername": variable.getname().upper(), Edouard@1154: "IECtype": variable.gettype()} Edouard@1144: for variable in self.CodeFile.variables.variable]) Edouard@1132: Edouard@1132: # Runtime calls (start, stop, init, and cleanup) Edouard@1132: rtcalls = "" Laurent@1124: for section in self.SECTIONS_NAMES: Laurent@1124: if section != "globals": Edouard@1132: rtcalls += "def _runtime_%s_%s():\n" % (location_str, section) Edouard@1132: sectiontext = self.GetSection(section).strip() Edouard@1132: if sectiontext: Edouard@1132: rtcalls += ' ' + \ Edouard@1154: sectiontext.replace('\n', '\n ')+"\n\n" Edouard@1132: else: Edouard@1132: rtcalls += " pass\n\n" Edouard@1144: Edouard@1144: globalsection = self.GetSection("globals") Edouard@1144: Edouard@1144: PyFileContent = """\ Edouard@1132: #!/usr/bin/env python Edouard@1132: # -*- coding: utf-8 -*- Edouard@1132: ## Code generated by Beremiz python mixin confnode Edouard@1132: ## Edouard@1132: Edouard@1132: ## Code for PLC global variable access Edouard@1144: from targets.typemapping import TypeTranslator Edouard@1144: import ctypes Edouard@1144: %(globalstubs)s Edouard@1132: Edouard@1132: ## User code in "global" scope Edouard@1144: %(globalsection)s laurent@366: Edouard@1132: ## Beremiz python runtime calls Edouard@1144: %(rtcalls)s Edouard@1144: Edouard@1144: """ % locals() Edouard@1144: Edouard@1144: # write generated content to python file Edouard@1132: runtimefile_path = os.path.join(buildpath, Edouard@1132: "runtime_%s.py"%location_str) Edouard@1132: runtimefile = open(runtimefile_path, 'w') Edouard@1144: runtimefile.write(PyFileContent.encode('utf-8')) Edouard@1132: runtimefile.close() Edouard@1132: Edouard@1144: # C code for safe global variables access Edouard@1144: Edouard@1144: vardecfmt = """\ Edouard@1154: extern __IEC_%(IECtype)s_t %(configname)s__%(uppername)s; Edouard@1154: IEC_%(IECtype)s __%(name)s_rbuffer = __INIT_%(IECtype)s; Edouard@1154: IEC_%(IECtype)s __%(name)s_wbuffer; Edouard@1144: long __%(name)s_rlock = 0; Edouard@1144: long __%(name)s_wlock = 0; Edouard@1144: int __%(name)s_wbuffer_written = 0; Edouard@1154: void __SafeGetPLCGlob_%(name)s(IEC_%(IECtype)s *pvalue){ Edouard@1144: while(AtomicCompareExchange(&__%(name)s_rlock, 0, 1)); Edouard@1145: *pvalue = __%(name)s_rbuffer; Edouard@1144: AtomicCompareExchange((long*)&__%(name)s_rlock, 1, 0); Edouard@1144: } Edouard@1160: void __SafeSetPLCGlob_%(name)s(IEC_%(IECtype)s *value){ Edouard@1144: while(AtomicCompareExchange(&__%(name)s_wlock, 0, 1)); Edouard@1144: __%(name)s_wbuffer = *value; Edouard@1144: __%(name)s_wbuffer_written = 1; Edouard@1144: AtomicCompareExchange((long*)&__%(name)s_wlock, 1, 0); Edouard@1144: } Edouard@1144: Edouard@1144: """ Edouard@1144: varretfmt = """\ Edouard@1144: if(!AtomicCompareExchange(&__%(name)s_wlock, 0, 1)){ Edouard@1144: if(__%(name)s_wbuffer_written == 1){ Edouard@1144: %(configname)s__%(uppername)s.value = __%(name)s_wbuffer; Edouard@1144: __%(name)s_wbuffer_written = 0; Edouard@1144: } Edouard@1144: AtomicCompareExchange((long*)&__%(name)s_wlock, 1, 0); Edouard@1144: } Edouard@1144: """ Edouard@1144: varpubfmt = """\ Edouard@1144: if(!AtomicCompareExchange(&__%(name)s_rlock, 0, 1)){ Edouard@1144: __%(name)s_rbuffer = %(configname)s__%(uppername)s.value; Edouard@1144: AtomicCompareExchange((long*)&__%(name)s_rlock, 1, 0); Edouard@1144: } Edouard@1144: """ Edouard@1144: Laurent@1148: var_str = map("\n".join, zip(*[ Edouard@1144: map(lambda f : f % varinfo, Edouard@1144: (vardecfmt, varretfmt, varpubfmt)) Edouard@1144: for varinfo in map(lambda variable : { Edouard@1144: "name": variable.getname(), Edouard@1144: "configname": configname.upper(), Edouard@1144: "uppername": variable.getname().upper(), Edouard@1154: "IECtype": variable.gettype()}, Edouard@1144: self.CodeFile.variables.variable)])) Laurent@1148: if len(var_str) > 0: Laurent@1148: vardec, varret, varpub = var_str Laurent@1148: else: Laurent@1148: vardec = varret = varpub = "" Edouard@1144: Edouard@1144: PyCFileContent = """\ Edouard@1132: /* Edouard@1132: * Code generated by Beremiz py_ext confnode Edouard@1132: * for safe global variables access Edouard@1132: */ Edouard@1132: #include "iec_types_all.h" Edouard@1144: #include "beremiz.h" Edouard@1144: Edouard@1144: /* User variables reference */ Edouard@1144: %(vardec)s Edouard@1144: Edouard@1144: /* Beremiz confnode functions */ Edouard@1144: int __init_%(location_str)s(int argc,char **argv){ Edouard@1144: return 0; Edouard@1144: } Edouard@1144: Edouard@1144: void __cleanup_%(location_str)s(void){ Edouard@1144: } Edouard@1144: Edouard@1144: void __retrieve_%(location_str)s(void){ Edouard@1144: %(varret)s Edouard@1144: } Edouard@1144: Edouard@1144: void __publish_%(location_str)s(void){ Edouard@1144: %(varpub)s Edouard@1144: } Edouard@1144: """ % locals() Edouard@1132: Edouard@1132: Gen_PyCfile_path = os.path.join(buildpath, "PyCFile_%s.c"%location_str) Edouard@1132: pycfile = open(Gen_PyCfile_path,'w') Edouard@1144: pycfile.write(PyCFileContent) Edouard@1132: pycfile.close() Edouard@1132: Edouard@1132: matiec_flags = '"-I%s"'%os.path.abspath( Edouard@1132: self.GetCTRoot().GetIECLibPath()) Edouard@1132: Edouard@1132: return ([(Gen_PyCfile_path, matiec_flags)], Edouard@1132: "", Edouard@1145: True, Edouard@1132: ("runtime_%s.py"%location_str, file(runtimefile_path,"rb"))) Edouard@1132: