runtime/PLCObject.py
changeset 1014 e2f7d6c95db0
parent 1011 388777d307de
child 1027 4e44c2c3e081
equal deleted inserted replaced
1013:d54ca1ec9090 1014:e2f7d6c95db0
    65         self.daemon = daemon
    65         self.daemon = daemon
    66         self.statuschange = statuschange
    66         self.statuschange = statuschange
    67         self.hmi_frame = None
    67         self.hmi_frame = None
    68         self.website = website
    68         self.website = website
    69         self._loading_error = None
    69         self._loading_error = None
    70         self.python_threads_vars = None
    70         self.python_runtime_vars = None
    71         
    71         
    72         # Get the last transfered PLC if connector must be restart
    72         # Get the last transfered PLC if connector must be restart
    73         try:
    73         try:
    74             self.CurrentPLCFilename=open(
    74             self.CurrentPLCFilename=open(
    75                              self._GetMD5FileName(),
    75                              self._GetMD5FileName(),
   229             self._PLClibraryHandle = None
   229             self._PLClibraryHandle = None
   230         
   230         
   231         self.PLClibraryLock.release()
   231         self.PLClibraryLock.release()
   232         return False
   232         return False
   233 
   233 
   234     def PrepareRuntimePy(self):
   234     def PythonRuntimeCall(self, methodname):
   235         self.python_threads_vars = globals().copy()
   235         """ 
   236         self.python_threads_vars["WorkingDir"] = self.workingdir
   236         Calls init, start, stop or cleanup method provided by 
   237         self.python_threads_vars["website"] = self.website
   237         runtime python files, loaded when new PLC uploaded
   238         self.python_threads_vars["_runtime_begin"] = []
   238         """
   239         self.python_threads_vars["_runtime_cleanup"] = []
   239         try :
   240         self.python_threads_vars["PLCObject"] = self
   240             for method in self.python_runtime_vars.get("_runtime_%s"%methodname, []):
   241         self.python_threads_vars["PLCBinary"] = self.PLClibraryHandle
   241                 res,exp = self.evaluator(method)
       
   242                 if exp is not None: raise(exp)
       
   243         except:
       
   244             self.LogMessage(0,traceback.format_exc())
       
   245             raise
       
   246 
       
   247     def PythonRuntimeInit(self):
       
   248         MethodNames = ["init", "start", "stop", "cleanup"]
       
   249         self.python_runtime_vars = globals().copy()
       
   250         self.python_runtime_vars["WorkingDir"] = self.workingdir
       
   251         self.python_runtime_vars["website"] = self.website
       
   252         for methodname in MethodNames :
       
   253             self.python_runtime_vars["_runtime_%s"%methodname] = []
       
   254         self.python_runtime_vars["PLCObject"] = self
       
   255         self.python_runtime_vars["PLCBinary"] = self.PLClibraryHandle
   242         
   256         
   243         try:
   257         try:
   244             for filename in os.listdir(self.workingdir):
   258             for filename in os.listdir(self.workingdir):
   245                 name, ext = os.path.splitext(filename)
   259                 name, ext = os.path.splitext(filename)
   246                 if name.upper().startswith("RUNTIME") and ext.upper() == ".PY":
   260                 if name.upper().startswith("RUNTIME") and ext.upper() == ".PY":
   247                     execfile(os.path.join(self.workingdir, filename), self.python_threads_vars)
   261                     execfile(os.path.join(self.workingdir, filename), self.python_runtime_vars)
   248                     runtime_begin = self.python_threads_vars.get("_%s_begin" % name, None)
   262                     for methodname in MethodNames: 
   249                     if runtime_begin is not None:
   263                         method = self.python_runtime_vars.get("_%s_%s" % (name, methodname), None)
   250                         self.python_threads_vars["_runtime_begin"].append(runtime_begin)
   264                         if method is not None:
   251                     runtime_cleanup = self.python_threads_vars.get("_%s_cleanup" % name, None)
   265                             self.python_runtime_vars["_runtime_%s"%methodname].append(method)
   252                     if runtime_cleanup is not None:
   266             
   253                         self.python_threads_vars["_runtime_cleanup"].append(runtime_cleanup)
       
   254             
       
   255             for runtime_begin in self.python_threads_vars.get("_runtime_begin", []):
       
   256                 runtime_begin()
       
   257         except:
   267         except:
   258             self.LogMessage(0,traceback.format_exc())
   268             self.LogMessage(0,traceback.format_exc())
   259             raise
   269             raise
   260             
   270             
       
   271         self.PythonRuntimeCall("init")
       
   272 
   261         if self.website is not None:
   273         if self.website is not None:
   262             self.website.PLCStarted()
   274             self.website.PLCStarted()
   263 
   275 
   264     def FinishRuntimePy(self):
   276 
   265         for runtime_cleanup in self.python_threads_vars.get("_runtime_cleanup", []):
   277     def PythonRuntimeCleanup(self):
   266             runtime_cleanup()    
   278         if self.python_runtime_vars is not None:
       
   279             self.PythonRuntimeCall("cleanup")
       
   280 
   267         if self.website is not None:
   281         if self.website is not None:
   268             self.website.PLCStopped()
   282             self.website.PLCStopped()
   269         self.python_threads_vars = None
   283 
       
   284         self.python_runtime_vars = None
   270 
   285 
   271     def PythonThreadProc(self):
   286     def PythonThreadProc(self):
   272         self.PLCStatus = "Started"
   287         self.PLCStatus = "Started"
   273         self.StatusChange()
   288         self.StatusChange()
   274         self.StartSem.release()
   289         self.StartSem.release()
   275         res,exp = self.evaluator(self.PrepareRuntimePy)
   290         self.PythonRuntimeCall("start")
   276         if exp is not None: raise(exp)
       
   277         res,cmd,blkid = "None","None",ctypes.c_void_p()
   291         res,cmd,blkid = "None","None",ctypes.c_void_p()
   278         compile_cache={}
   292         compile_cache={}
   279         while True:
   293         while True:
   280             # print "_PythonIterator(", res, ")",
   294             # print "_PythonIterator(", res, ")",
   281             cmd = self._PythonIterator(res,blkid)
   295             cmd = self._PythonIterator(res,blkid)
   282             FBID = blkid.value 
   296             FBID = blkid.value 
   283             # print " -> ", cmd, blkid
   297             # print " -> ", cmd, blkid
   284             if cmd is None:
   298             if cmd is None:
   285                 break
   299                 break
   286             try :
   300             try :
   287                 self.python_threads_vars["FBID"]=FBID
   301                 self.python_runtime_vars["FBID"]=FBID
   288                 ccmd,AST =compile_cache.get(FBID, (None,None))
   302                 ccmd,AST =compile_cache.get(FBID, (None,None))
   289                 if ccmd is None or ccmd!=cmd:
   303                 if ccmd is None or ccmd!=cmd:
   290                     AST = compile(cmd, '<plc>', 'eval')
   304                     AST = compile(cmd, '<plc>', 'eval')
   291                     compile_cache[FBID]=(cmd,AST)
   305                     compile_cache[FBID]=(cmd,AST)
   292                 result,exp = self.evaluator(eval,cmd,self.python_threads_vars)
   306                 result,exp = self.evaluator(eval,cmd,self.python_runtime_vars)
   293                 if exp is not None: 
   307                 if exp is not None: 
   294                     raise(exp)
   308                     raise(exp)
   295                 else:
   309                 else:
   296                     res=str(result)
   310                     res=str(result)
   297                 self.python_threads_vars["FBID"]=None
   311                 self.python_runtime_vars["FBID"]=None
   298             except Exception,e:
   312             except Exception,e:
   299                 res = "#EXCEPTION : "+str(e)
   313                 res = "#EXCEPTION : "+str(e)
   300                 self.LogMessage(1,('PyEval@0x%x(Code="%s") Exception "%s"')%(FBID,cmd,str(e)))
   314                 self.LogMessage(1,('PyEval@0x%x(Code="%s") Exception "%s"')%(FBID,cmd,str(e)))
   301         self.PLCStatus = "Stopped"
   315         self.PLCStatus = "Stopped"
   302         self.StatusChange()
   316         self.StatusChange()
   303         exp,res = self.evaluator(self.FinishRuntimePy)
   317         self.PythonRuntimeCall("stop")
   304         if exp is not None: raise(exp)
       
   305     
   318     
   306     def StartPLC(self):
   319     def StartPLC(self):
   307         if self.CurrentPLCFilename is not None and self.PLCStatus == "Stopped":
   320         if self.CurrentPLCFilename is not None and self.PLCStatus == "Stopped":
   308             c_argv = ctypes.c_char_p * len(self.argv)
   321             c_argv = ctypes.c_char_p * len(self.argv)
   309             error = None
   322             error = None
   345     def NewPLC(self, md5sum, data, extrafiles):
   358     def NewPLC(self, md5sum, data, extrafiles):
   346         if self.PLCStatus in ["Stopped", "Empty", "Broken"]:
   359         if self.PLCStatus in ["Stopped", "Empty", "Broken"]:
   347             NewFileName = md5sum + lib_ext
   360             NewFileName = md5sum + lib_ext
   348             extra_files_log = os.path.join(self.workingdir,"extra_files.txt")
   361             extra_files_log = os.path.join(self.workingdir,"extra_files.txt")
   349 
   362 
       
   363             self.PythonRuntimeCleanup()
       
   364 
   350             self._FreePLC()
   365             self._FreePLC()
   351             self.LogMessage("NewPLC (%s)"%md5sum)
   366             self.LogMessage("NewPLC (%s)"%md5sum)
   352             self.PLCStatus = "Empty"
   367             self.PLCStatus = "Empty"
   353 
   368 
   354             try:
   369             try:
   385                 PLCprint(traceback.format_exc())
   400                 PLCprint(traceback.format_exc())
   386                 return False
   401                 return False
   387 
   402 
   388             if self._LoadNewPLC():
   403             if self._LoadNewPLC():
   389                 self.PLCStatus = "Stopped"
   404                 self.PLCStatus = "Stopped"
       
   405                 try:
       
   406                     self.PythonRuntimeInit()
       
   407                 except:
       
   408                     self.PLCStatus = "Broken"
   390             else:
   409             else:
   391                 self._FreePLC()
   410                 self._FreePLC()
   392             self.StatusChange()
   411             self.StatusChange()
   393 
   412 
   394             return self.PLCStatus == "Stopped"
   413             return self.PLCStatus == "Stopped"