Now python files provided by extentions have init, start, stop and cleanup hooks
--- a/runtime/PLCObject.py Thu Apr 04 11:12:30 2013 +0900
+++ b/runtime/PLCObject.py Thu Apr 04 11:13:28 2013 +0900
@@ -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 Thu Apr 04 11:12:30 2013 +0900
+++ b/svgui/svgui.py Thu Apr 04 11:13:28 2013 +0900
@@ -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 Thu Apr 04 11:12:30 2013 +0900
+++ b/tests/logging/plc.xml Thu Apr 04 11:13:28 2013 +0900
@@ -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 Thu Apr 04 11:12:30 2013 +0900
+++ b/tests/logging/py_ext_0@py_ext/py_ext.xml Thu Apr 04 11:13:28 2013 +0900
@@ -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/wxglade_hmi/wxglade_hmi.py Thu Apr 04 11:12:30 2013 +0900
+++ b/wxglade_hmi/wxglade_hmi.py Thu Apr 04 11:13:28 2013 +0900
@@ -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