Merged
authorLaurent Bessard
Fri, 05 Apr 2013 00:56:54 +0200
changeset 1018 6b7ba640f49e
parent 1014 e2f7d6c95db0 (diff)
parent 1017 2925d6e49893 (current diff)
child 1019 e5686874eaef
Merged
--- a/runtime/PLCObject.py	Fri Apr 05 00:08:02 2013 +0200
+++ b/runtime/PLCObject.py	Fri Apr 05 00:56:54 2013 +0200
@@ -67,7 +67,7 @@
         self.hmi_frame = None
         self.website = website
         self._loading_error = None
-        self.python_threads_vars = None
+        self.python_runtime_vars = None
         
         # Get the last transfered PLC if connector must be restart
         try:
@@ -231,49 +231,63 @@
         self.PLClibraryLock.release()
         return False
 
-    def PrepareRuntimePy(self):
-        self.python_threads_vars = globals().copy()
-        self.python_threads_vars["WorkingDir"] = self.workingdir
-        self.python_threads_vars["website"] = self.website
-        self.python_threads_vars["_runtime_begin"] = []
-        self.python_threads_vars["_runtime_cleanup"] = []
-        self.python_threads_vars["PLCObject"] = self
-        self.python_threads_vars["PLCBinary"] = self.PLClibraryHandle
+    def PythonRuntimeCall(self, methodname):
+        """ 
+        Calls init, start, stop or cleanup method provided by 
+        runtime python files, loaded when new PLC uploaded
+        """
+        try :
+            for method in self.python_runtime_vars.get("_runtime_%s"%methodname, []):
+                res,exp = self.evaluator(method)
+                if exp is not None: raise(exp)
+        except:
+            self.LogMessage(0,traceback.format_exc())
+            raise
+
+    def PythonRuntimeInit(self):
+        MethodNames = ["init", "start", "stop", "cleanup"]
+        self.python_runtime_vars = globals().copy()
+        self.python_runtime_vars["WorkingDir"] = self.workingdir
+        self.python_runtime_vars["website"] = self.website
+        for methodname in MethodNames :
+            self.python_runtime_vars["_runtime_%s"%methodname] = []
+        self.python_runtime_vars["PLCObject"] = self
+        self.python_runtime_vars["PLCBinary"] = self.PLClibraryHandle
         
         try:
             for filename in os.listdir(self.workingdir):
                 name, ext = os.path.splitext(filename)
                 if name.upper().startswith("RUNTIME") and ext.upper() == ".PY":
-                    execfile(os.path.join(self.workingdir, filename), self.python_threads_vars)
-                    runtime_begin = self.python_threads_vars.get("_%s_begin" % name, None)
-                    if runtime_begin is not None:
-                        self.python_threads_vars["_runtime_begin"].append(runtime_begin)
-                    runtime_cleanup = self.python_threads_vars.get("_%s_cleanup" % name, None)
-                    if runtime_cleanup is not None:
-                        self.python_threads_vars["_runtime_cleanup"].append(runtime_cleanup)
-            
-            for runtime_begin in self.python_threads_vars.get("_runtime_begin", []):
-                runtime_begin()
+                    execfile(os.path.join(self.workingdir, filename), self.python_runtime_vars)
+                    for methodname in MethodNames: 
+                        method = self.python_runtime_vars.get("_%s_%s" % (name, methodname), None)
+                        if method is not None:
+                            self.python_runtime_vars["_runtime_%s"%methodname].append(method)
+            
         except:
             self.LogMessage(0,traceback.format_exc())
             raise
             
+        self.PythonRuntimeCall("init")
+
         if self.website is not None:
             self.website.PLCStarted()
 
-    def FinishRuntimePy(self):
-        for runtime_cleanup in self.python_threads_vars.get("_runtime_cleanup", []):
-            runtime_cleanup()    
+
+    def PythonRuntimeCleanup(self):
+        if self.python_runtime_vars is not None:
+            self.PythonRuntimeCall("cleanup")
+
         if self.website is not None:
             self.website.PLCStopped()
-        self.python_threads_vars = None
+
+        self.python_runtime_vars = None
 
     def PythonThreadProc(self):
         self.PLCStatus = "Started"
         self.StatusChange()
         self.StartSem.release()
-        res,exp = self.evaluator(self.PrepareRuntimePy)
-        if exp is not None: raise(exp)
+        self.PythonRuntimeCall("start")
         res,cmd,blkid = "None","None",ctypes.c_void_p()
         compile_cache={}
         while True:
@@ -284,24 +298,23 @@
             if cmd is None:
                 break
             try :
-                self.python_threads_vars["FBID"]=FBID
+                self.python_runtime_vars["FBID"]=FBID
                 ccmd,AST =compile_cache.get(FBID, (None,None))
                 if ccmd is None or ccmd!=cmd:
                     AST = compile(cmd, '<plc>', 'eval')
                     compile_cache[FBID]=(cmd,AST)
-                result,exp = self.evaluator(eval,cmd,self.python_threads_vars)
+                result,exp = self.evaluator(eval,cmd,self.python_runtime_vars)
                 if exp is not None: 
                     raise(exp)
                 else:
                     res=str(result)
-                self.python_threads_vars["FBID"]=None
+                self.python_runtime_vars["FBID"]=None
             except Exception,e:
                 res = "#EXCEPTION : "+str(e)
                 self.LogMessage(1,('PyEval@0x%x(Code="%s") Exception "%s"')%(FBID,cmd,str(e)))
         self.PLCStatus = "Stopped"
         self.StatusChange()
-        exp,res = self.evaluator(self.FinishRuntimePy)
-        if exp is not None: raise(exp)
+        self.PythonRuntimeCall("stop")
     
     def StartPLC(self):
         if self.CurrentPLCFilename is not None and self.PLCStatus == "Stopped":
@@ -347,6 +360,8 @@
             NewFileName = md5sum + lib_ext
             extra_files_log = os.path.join(self.workingdir,"extra_files.txt")
 
+            self.PythonRuntimeCleanup()
+
             self._FreePLC()
             self.LogMessage("NewPLC (%s)"%md5sum)
             self.PLCStatus = "Empty"
@@ -387,6 +402,10 @@
 
             if self._LoadNewPLC():
                 self.PLCStatus = "Stopped"
+                try:
+                    self.PythonRuntimeInit()
+                except:
+                    self.PLCStatus = "Broken"
             else:
                 self._FreePLC()
             self.StatusChange()
--- a/svgui/svgui.py	Fri Apr 05 00:08:02 2013 +0200
+++ b/svgui/svgui.py	Fri Apr 05 00:56:54 2013 +0200
@@ -72,10 +72,10 @@
         runtimefile = open(runtimefile_path, 'w')
         runtimefile.write(svguiservercode % {"svgfile" : "gui.svg"})
         runtimefile.write("""
-def _runtime_%(location)s_begin():
+def _runtime_%(location)s_start():
     website.LoadHMI(%(svgui_class)s, %(jsmodules)s)
     
-def _runtime_%(location)s_cleanup():
+def _runtime_%(location)s_stop():
     website.UnLoadHMI()
     
 """ % {"location": location_str,
--- a/tests/logging/plc.xml	Fri Apr 05 00:08:02 2013 +0200
+++ b/tests/logging/plc.xml	Fri Apr 05 00:56:54 2013 +0200
@@ -8,7 +8,7 @@
               productVersion="1"
               creationDateTime="2013-01-29T14:01:00"/>
   <contentHeader name="Unnamed"
-                 modificationDateTime="2013-02-26T16:22:11">
+                 modificationDateTime="2013-04-04T11:06:06">
     <coordinateInfo>
       <fbd>
         <scaling x="0" y="0"/>
--- a/tests/logging/py_ext_0@py_ext/py_ext.xml	Fri Apr 05 00:08:02 2013 +0200
+++ b/tests/logging/py_ext_0@py_ext/py_ext.xml	Fri Apr 05 00:56:54 2013 +0200
@@ -1,23 +1,26 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <Python xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.w3.org/2001/XMLSchema" xsi:schemaLocation="py_ext_xsd.xsd">
-<![CDATA[import threading
+<![CDATA[import threading, time
 
 MyT = None
 Stop = False
 
+def StartLog():
+    global MyT
+    MyT=threading.Thread(target = DoLog)
+    MyT.start()
+
 def DoLog():
-    global MyT,Stop
-    MyT=threading.Timer(0.3, DoLog)
-    if not Stop : MyT.start()
-    Stop = False
-    PLCObject.LogMessage("Python side Logging")
+    global Stop
+    while not Stop:
+        PLCObject.LogMessage("Python side Logging (PLC is %s)"%PLCObject.PLCStatus)
+        time.sleep(0.3)
 
 def StopLog():
     global MyT,Stop
     Stop=True
-    if MyT is not None: MyT.cancel()
 
-_runtime_begin.append(DoLog)
+_runtime_init.append(StartLog)
 _runtime_cleanup.append(StopLog)
 ]]>
 </Python>
--- a/tests/python/plc.xml	Fri Apr 05 00:08:02 2013 +0200
+++ b/tests/python/plc.xml	Fri Apr 05 00:56:54 2013 +0200
@@ -3,12 +3,12 @@
          xsi:schemaLocation="http://www.plcopen.org/xml/tc6.xsd"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:xhtml="http://www.w3.org/1999/xhtml">
-  <fileHeader companyName="beremiz"
+  <fileHeader companyName=""
               productName="Beremiz"
               productVersion="0.0"
               creationDateTime="2008-12-14T16:21:19"/>
   <contentHeader name="Beremiz Python Support Tests"
-                 modificationDateTime="2013-02-23T23:37:47">
+                 modificationDateTime="2013-04-04T10:25:57">
     <coordinateInfo>
       <pageSize x="1024" y="1024"/>
       <fbd>
@@ -181,6 +181,16 @@
                 <derived name="RS"/>
               </type>
             </variable>
+            <variable name="TUTU">
+              <type>
+                <INT/>
+              </type>
+            </variable>
+            <variable name="TOTO">
+              <type>
+                <INT/>
+              </type>
+            </variable>
           </externalVars>
         </interface>
         <body>
@@ -1048,6 +1058,37 @@
               </connectionPointOut>
               <expression>Test_TOD</expression>
             </inOutVariable>
+            <inVariable localId="49" height="30" width="30">
+              <position x="765" y="1200"/>
+              <connectionPointOut>
+                <relPosition x="30" y="15"/>
+              </connectionPointOut>
+              <expression>42</expression>
+            </inVariable>
+            <outVariable localId="57" height="30" width="50">
+              <position x="845" y="1200"/>
+              <connectionPointIn>
+                <relPosition x="0" y="15"/>
+                <connection refLocalId="49">
+                  <position x="845" y="1215"/>
+                  <position x="795" y="1215"/>
+                </connection>
+              </connectionPointIn>
+              <expression>TOTO</expression>
+            </outVariable>
+            <outVariable localId="56" height="30" width="50">
+              <position x="845" y="1240"/>
+              <connectionPointIn>
+                <relPosition x="0" y="15"/>
+                <connection refLocalId="49">
+                  <position x="845" y="1255"/>
+                  <position x="820" y="1255"/>
+                  <position x="820" y="1215"/>
+                  <position x="795" y="1215"/>
+                </connection>
+              </connectionPointIn>
+              <expression>TUTU</expression>
+            </outVariable>
           </FBD>
         </body>
       </pou>
@@ -1182,6 +1223,11 @@
               <derived name="RS"/>
             </type>
           </variable>
+          <variable name="TUTU">
+            <type>
+              <INT/>
+            </type>
+          </variable>
         </globalVars>
       </configuration>
     </configurations>
--- a/wxglade_hmi/wxglade_hmi.py	Fri Apr 05 00:08:02 2013 +0200
+++ b/wxglade_hmi/wxglade_hmi.py	Fri Apr 05 00:56:54 2013 +0200
@@ -73,7 +73,7 @@
         runtimefile.write("""
 %(declare)s
 
-def _runtime_%(location)s_begin():
+def _runtime_%(location)s_start():
     global %(global)s
     
     def OnCloseFrame(evt):
@@ -81,7 +81,7 @@
     
     %(init)s
     
-def _runtime_%(location)s_cleanup():
+def _runtime_%(location)s_stop():
     global %(global)s
     
     %(cleanup)s