runtime/PLCObject.py
changeset 483 bc26c42d2eec
parent 479 c28f40b27798
child 504 688e84df3408
equal deleted inserted replaced
482:7c83eb6a55bd 483:bc26c42d2eec
    84     def _LoadNewPLC(self):
    84     def _LoadNewPLC(self):
    85         """
    85         """
    86         Load PLC library
    86         Load PLC library
    87         Declare all functions, arguments and return values
    87         Declare all functions, arguments and return values
    88         """
    88         """
    89         PLCprint("Load PLC")
       
    90         try:
    89         try:
    91             self._PLClibraryHandle = dlopen(self._GetLibFileName())
    90             self._PLClibraryHandle = dlopen(self._GetLibFileName())
    92             self.PLClibraryHandle = ctypes.CDLL(self.CurrentPLCFilename, handle=self._PLClibraryHandle)
    91             self.PLClibraryHandle = ctypes.CDLL(self.CurrentPLCFilename, handle=self._PLClibraryHandle)
    93     
    92     
    94             self._startPLC = self.PLClibraryHandle.startPLC
    93             self._startPLC = self.PLClibraryHandle.startPLC
   101             self._PythonIterator = getattr(self.PLClibraryHandle, "PythonIterator", None)
   100             self._PythonIterator = getattr(self.PLClibraryHandle, "PythonIterator", None)
   102             if self._PythonIterator is not None:
   101             if self._PythonIterator is not None:
   103                 self._PythonIterator.restype = ctypes.c_char_p
   102                 self._PythonIterator.restype = ctypes.c_char_p
   104                 self._PythonIterator.argtypes = [ctypes.c_char_p]
   103                 self._PythonIterator.argtypes = [ctypes.c_char_p]
   105                 
   104                 
   106                 def StopPLCLock():
   105                 self._stopPLC = self._stopPLC_real
   107                     self.PLClibraryLock.acquire()
       
   108                     self._stopPLC_real()
       
   109                     self.PLClibraryLock.release()
       
   110                 
       
   111             else:
   106             else:
   112                 # If python plugin is not enabled, we reuse _PythonIterator
   107                 # If python plugin is not enabled, we reuse _PythonIterator
   113                 # as a call that block pythonthread until StopPLC 
   108                 # as a call that block pythonthread until StopPLC 
   114                 self.PythonIteratorLock = Lock()
   109                 self.PythonIteratorLock = Lock()
   115                 self.PythonIteratorLock.acquire()
   110                 self.PythonIteratorLock.acquire()
   117                     self.PythonIteratorLock.acquire()
   112                     self.PythonIteratorLock.acquire()
   118                     self.PythonIteratorLock.release()
   113                     self.PythonIteratorLock.release()
   119                     return None
   114                     return None
   120                 self._PythonIterator = PythonIterator
   115                 self._PythonIterator = PythonIterator
   121                 
   116                 
   122                 def StopPLCLock():
   117                 def __StopPLC():
   123                     self.PLClibraryLock.acquire()
       
   124                     self._stopPLC_real()
   118                     self._stopPLC_real()
   125                     self.PythonIteratorLock.release()
   119                     self.PythonIteratorLock.release()
   126                     self.PLClibraryLock.release()
   120                 self._stopPLC = __StopPLC
   127             
   121             
   128             self._stopPLC = StopPLCLock
       
   129     
   122     
   130             self._ResetDebugVariables = self.PLClibraryHandle.ResetDebugVariables
   123             self._ResetDebugVariables = self.PLClibraryHandle.ResetDebugVariables
   131             self._ResetDebugVariables.restype = None
   124             self._ResetDebugVariables.restype = None
   132     
   125     
   133             self._RegisterDebugVariable = self.PLClibraryHandle.RegisterDebugVariable
   126             self._RegisterDebugVariable = self.PLClibraryHandle.RegisterDebugVariable
   161         self.PLClibraryLock.acquire()
   154         self.PLClibraryLock.acquire()
   162         # Forget all refs to library
   155         # Forget all refs to library
   163         self._startPLC = lambda:None
   156         self._startPLC = lambda:None
   164         self._stopPLC = lambda:None
   157         self._stopPLC = lambda:None
   165         self._ResetDebugVariables = lambda:None
   158         self._ResetDebugVariables = lambda:None
   166         self._RegisterDebugVariable = lambda x:None
   159         self._RegisterDebugVariable = lambda x, y:None
   167         self._IterDebugData = lambda x,y:None
   160         self._IterDebugData = lambda x,y:None
   168         self._FreeDebugData = lambda:None
   161         self._FreeDebugData = lambda:None
   169         self._GetDebugData = lambda:-1
   162         self._GetDebugData = lambda:-1
   170         self._suspendDebug = lambda x:None
   163         self._suspendDebug = lambda x:None
   171         self._resumeDebug = lambda:None
   164         self._resumeDebug = lambda:None
   215         if self.website is not None:
   208         if self.website is not None:
   216             self.website.PLCStopped()
   209             self.website.PLCStopped()
   217         self.python_threads_vars = None
   210         self.python_threads_vars = None
   218 
   211 
   219     def PythonThreadProc(self):
   212     def PythonThreadProc(self):
   220         PLCprint("PythonThreadProc started")
       
   221         c_argv = ctypes.c_char_p * len(self.argv)
   213         c_argv = ctypes.c_char_p * len(self.argv)
   222         error = None
   214         error = None
   223         if self._LoadNewPLC():
   215         if self._LoadNewPLC():
   224             if self._startPLC(len(self.argv),c_argv(*self.argv)) == 0:
   216             if self._startPLC(len(self.argv),c_argv(*self.argv)) == 0:
   225                 self.PLCStatus = "Started"
   217                 self.PLCStatus = "Started"
   246             error = "loading"
   238             error = "loading"
   247         if error is not None:
   239         if error is not None:
   248             PLCprint("Problem %s PLC"%error)
   240             PLCprint("Problem %s PLC"%error)
   249             self.PLCStatus = "Broken"
   241             self.PLCStatus = "Broken"
   250         self._FreePLC()
   242         self._FreePLC()
   251         PLCprint("PythonThreadProc interrupted")
       
   252     
   243     
   253     def StartPLC(self):
   244     def StartPLC(self):
   254         PLCprint("StartPLC")
   245         PLCprint("StartPLC")
   255         if self.CurrentPLCFilename is not None and self.PLCStatus == "Stopped":
   246         if self.CurrentPLCFilename is not None and self.PLCStatus == "Stopped":
   256             self.PLCStatus = "Started"
   247             self.PLCStatus = "Started"
   258             self.PythonThread.start()
   249             self.PythonThread.start()
   259             
   250             
   260     def StopPLC(self):
   251     def StopPLC(self):
   261         PLCprint("StopPLC")
   252         PLCprint("StopPLC")
   262         if self.PLCStatus == "Started":
   253         if self.PLCStatus == "Started":
       
   254             self.PLCStatus = "Stopped"
   263             self._stopPLC()
   255             self._stopPLC()
   264             return True
   256             return True
   265         return False
   257         return False
   266 
   258 
   267     def _Reload(self):
   259     def _Reload(self):
   382         """
   374         """
   383         Return a list of variables, corresponding to the list of required idx
   375         Return a list of variables, corresponding to the list of required idx
   384         """
   376         """
   385         if self.PLCStatus == "Started":
   377         if self.PLCStatus == "Started":
   386             res=[]
   378             res=[]
   387             self.PLClibraryLock.acquire()
       
   388             tick = ctypes.c_uint32()
   379             tick = ctypes.c_uint32()
   389             size = ctypes.c_uint32()
   380             size = ctypes.c_uint32()
   390             buffer = ctypes.c_void_p()
   381             buffer = ctypes.c_void_p()
   391             offset = 0
   382             offset = 0
   392             if self._GetDebugData(ctypes.byref(tick),ctypes.byref(size),ctypes.byref(buffer)) == 0 :
   383             if self.PLClibraryLock.acquire(False) and \
   393                 for idx, iectype, forced in self._Idxs:
   384                self._GetDebugData(ctypes.byref(tick),ctypes.byref(size),ctypes.byref(buffer)) == 0 :
   394                     cursor = ctypes.c_void_p(buffer.value + offset)
   385                 if size.value:
   395                     c_type,unpack_func, pack_func = self.TypeTranslator.get(iectype, (None,None,None))
   386                     for idx, iectype, forced in self._Idxs:
   396                     if c_type is not None and offset < size:
   387                         cursor = ctypes.c_void_p(buffer.value + offset)
   397                         res.append(unpack_func(ctypes.cast(cursor,
   388                         c_type,unpack_func, pack_func = self.TypeTranslator.get(iectype, (None,None,None))
   398                                                            ctypes.POINTER(c_type)).contents))
   389                         if c_type is not None and offset < size:
   399                         offset += ctypes.sizeof(c_type)
   390                             res.append(unpack_func(ctypes.cast(cursor,
   400                     else:
   391                                                                ctypes.POINTER(c_type)).contents))
   401                         if c_type is None:
   392                             offset += ctypes.sizeof(c_type)
   402                             PLCprint("Debug error - " + iectype + " not supported !")
   393                         else:
   403                         if offset >= size:
   394                             if c_type is None:
   404                             PLCprint("Debug error - buffer too small !")
   395                                 PLCprint("Debug error - " + iectype + " not supported !")
   405                         break
   396                             if offset >= size:
   406             self._FreeDebugData()
   397                                 PLCprint("Debug error - buffer too small !")
   407             self.PLClibraryLock.release()
   398                             break
       
   399                 self._FreeDebugData()
       
   400                 self.PLClibraryLock.release()
   408             if offset and offset == size.value:
   401             if offset and offset == size.value:
   409                 return self.PLCStatus, tick.value, res
   402                 return self.PLCStatus, tick.value, res
   410             else:
   403             elif size.value:
   411                 PLCprint("Debug error - bad buffer unpack !")
   404                 PLCprint("Debug error - wrong buffer unpack !")
   412         return self.PLCStatus, None, None
   405         return self.PLCStatus, None, None
   413 
   406