runtime/PLCObject.py
changeset 2582 8f0d6c5fd55f
parent 2546 f5dae7b85906
child 2583 e172ab28d04e
equal deleted inserted replaced
2581:20eb4e7a0647 2582:8f0d6c5fd55f
    21 # License along with this library; if not, write to the Free Software
    21 # License along with this library; if not, write to the Free Software
    22 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
    22 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
    23 
    23 
    24 
    24 
    25 from __future__ import absolute_import
    25 from __future__ import absolute_import
    26 from threading import Thread, Lock, Semaphore, Event
    26 from threading import Thread, Lock, Event, Condition
    27 import ctypes
    27 import ctypes
    28 import os
    28 import os
    29 import sys
    29 import sys
    30 import traceback
    30 import traceback
    31 import shutil
    31 import shutil
   377                             self.python_runtime_vars["_runtime_%s" % methodname].append(method)
   377                             self.python_runtime_vars["_runtime_%s" % methodname].append(method)
   378         except Exception:
   378         except Exception:
   379             self.LogMessage(0, traceback.format_exc())
   379             self.LogMessage(0, traceback.format_exc())
   380             raise
   380             raise
   381 
   381 
   382         self.PythonRuntimeCall("init")
   382         self.PythonThreadCondLock = Lock()
       
   383         self.PythonThreadCond = Condition(self.PythonThreadCondLock)
       
   384         self.PythonThreadCmd = "Wait"
       
   385         self.PythonThread = Thread(target=self.PythonThreadProc)
       
   386         self.PythonThread.start()
       
   387 
   383 
   388 
   384     # used internaly
   389     # used internaly
   385     def PythonRuntimeCleanup(self):
   390     def PythonRuntimeCleanup(self):
   386         if self.python_runtime_vars is not None:
   391         if self.python_runtime_vars is not None:
   387             self.PythonRuntimeCall("cleanup")
   392             self.PythonThreadCommand("Finish")
       
   393             self.PythonThread.join()
   388 
   394 
   389         self.python_runtime_vars = None
   395         self.python_runtime_vars = None
   390 
   396 
   391     def PythonThreadProc(self):
   397     def PythonThreadLoop(self):
   392         self.StartSem.release()
       
   393         res, cmd, blkid = "None", "None", ctypes.c_void_p()
   398         res, cmd, blkid = "None", "None", ctypes.c_void_p()
   394         compile_cache = {}
   399         compile_cache = {}
   395         while True:
   400         while True:
   396             cmd = self._PythonIterator(res, blkid)
   401             cmd = self._PythonIterator(res, blkid)
   397             FBID = blkid.value
   402             FBID = blkid.value
   413                 self.python_runtime_vars["FBID"] = None
   418                 self.python_runtime_vars["FBID"] = None
   414             except Exception as e:
   419             except Exception as e:
   415                 res = "#EXCEPTION : "+str(e)
   420                 res = "#EXCEPTION : "+str(e)
   416                 self.LogMessage(1, ('PyEval@0x%x(Code="%s") Exception "%s"') % (FBID, cmd, str(e)))
   421                 self.LogMessage(1, ('PyEval@0x%x(Code="%s") Exception "%s"') % (FBID, cmd, str(e)))
   417 
   422 
       
   423     def PythonThreadProc(self):
       
   424         print('self.PythonRuntimeCall("init")')
       
   425         self.PythonRuntimeCall("init")
       
   426 
       
   427         while True:
       
   428             self.PythonThreadCondLock.acquire()
       
   429             cmd = self.PythonThreadCmd
       
   430             while cmd == "Wait":
       
   431                 self.PythonThreadCond.wait()
       
   432                 cmd = self.PythonThreadCmd
       
   433                 self.PythonThreadCmd = "Wait"
       
   434             self.PythonThreadCondLock.release()
       
   435             
       
   436             if cmd == "Activate" :
       
   437                 print('self.PythonRuntimeCall("start")')
       
   438                 self.PythonRuntimeCall("start")
       
   439 
       
   440                 self.PythonThreadLoop()
       
   441                 
       
   442                 self.PythonRuntimeCall("stop")
       
   443             else:  # "Finish"
       
   444                 break
       
   445 
       
   446         self.PythonRuntimeCall("cleanup")
       
   447 
       
   448     def PythonThreadCommand(self, cmd):
       
   449         self.PythonThreadCondLock.acquire()
       
   450         self.PythonThreadCmd = cmd 
       
   451         self.PythonThreadCond.notify()
       
   452         self.PythonThreadCondLock.release()
       
   453 
   418     @RunInMain
   454     @RunInMain
   419     def StartPLC(self):
   455     def StartPLC(self):
   420         if self.CurrentPLCFilename is not None and self.PLCStatus == PlcStatus.Stopped:
   456         if self.CurrentPLCFilename is not None and self.PLCStatus == PlcStatus.Stopped:
   421             c_argv = ctypes.c_char_p * len(self.argv)
   457             c_argv = ctypes.c_char_p * len(self.argv)
   422             res = self._startPLC(len(self.argv), c_argv(*self.argv))
   458             res = self._startPLC(len(self.argv), c_argv(*self.argv))
   423             if res == 0:
   459             if res == 0:
   424                 self.PLCStatus = PlcStatus.Started
   460                 self.PLCStatus = PlcStatus.Started
   425                 self.StatusChange()
   461                 self.StatusChange()
   426                 self.PythonRuntimeCall("start")
   462                 self.PythonThreadCommand("Activate")
   427                 self.StartSem = Semaphore(0)
       
   428                 self.PythonThread = Thread(target=self.PythonThreadProc)
       
   429                 self.PythonThread.start()
       
   430                 self.StartSem.acquire()
       
   431                 self.LogMessage("PLC started")
   463                 self.LogMessage("PLC started")
   432             else:
   464             else:
   433                 self.LogMessage(0, _("Problem starting PLC : error %d" % res))
   465                 self.LogMessage(0, _("Problem starting PLC : error %d" % res))
   434                 self.PLCStatus = PlcStatus.Broken
   466                 self.PLCStatus = PlcStatus.Broken
   435                 self.StatusChange()
   467                 self.StatusChange()
   437     @RunInMain
   469     @RunInMain
   438     def StopPLC(self):
   470     def StopPLC(self):
   439         if self.PLCStatus == PlcStatus.Started:
   471         if self.PLCStatus == PlcStatus.Started:
   440             self.LogMessage("PLC stopped")
   472             self.LogMessage("PLC stopped")
   441             self._stopPLC()
   473             self._stopPLC()
   442             self.PythonThread.join()
       
   443             self.PLCStatus = PlcStatus.Stopped
   474             self.PLCStatus = PlcStatus.Stopped
   444             self.StatusChange()
   475             self.StatusChange()
   445             self.PythonRuntimeCall("stop")
       
   446             if self.TraceThread is not None:
   476             if self.TraceThread is not None:
   447                 self.TraceThread.join()
   477                 self.TraceThread.join()
   448                 self.TraceThread = None
   478                 self.TraceThread = None
   449             return True
   479             return True
   450         return False
   480         return False