runtime/PLCObject.py
changeset 917 401e44bae7c0
parent 914 94436558f0ce
child 921 a8db48ec2c31
equal deleted inserted replaced
916:697d8b77d716 917:401e44bae7c0
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    24 
    24 
    25 import Pyro.core as pyro
    25 import Pyro.core as pyro
    26 from threading import Timer, Thread, Lock, Semaphore
    26 from threading import Timer, Thread, Lock, Semaphore
    27 import ctypes, os, commands, types, sys
    27 import ctypes, os, commands, types, sys
    28 from targets.typemapping import SameEndianessTypeTranslator as TypeTranslator
    28 from targets.typemapping import LogLevelsDefault, LogLevelsCount, SameEndianessTypeTranslator as TypeTranslator
       
    29 
    29 
    30 
    30 if os.name in ("nt", "ce"):
    31 if os.name in ("nt", "ce"):
    31     from _ctypes import LoadLibrary as dlopen
    32     from _ctypes import LoadLibrary as dlopen
    32     from _ctypes import FreeLibrary as dlclose
    33     from _ctypes import FreeLibrary as dlclose
    33 elif os.name == "posix":
    34 elif os.name == "posix":
    78 
    79 
    79     def StatusChange(self):
    80     def StatusChange(self):
    80         if self.statuschange is not None:
    81         if self.statuschange is not None:
    81             self.statuschange(self.PLCStatus)
    82             self.statuschange(self.PLCStatus)
    82 
    83 
    83     def LogMessage(self, msg):
    84     def LogMessage(self, *args):
    84         return self._LogMessage(msg, len(msg))
    85         if len(args) == 2:
    85 
    86             level, msg = args
    86 
    87         else:
    87     def GetLogCount(self):
    88             level = LogLevelsDefault
       
    89             msg, = args
       
    90         return self._LogMessage(level, msg, len(msg))
       
    91 
       
    92 
       
    93     def GetLogCount(self, level):
    88         if self._GetLogCount is not None :
    94         if self._GetLogCount is not None :
    89             return int(self._GetLogCount())
    95             return int(self._GetLogCount(level))
    90         elif self._loading_error is not None:
    96         elif self._loading_error is not None and level==0:
    91             return 1;
    97             return 1;
    92 
    98 
    93 
    99     def GetLogMessage(self, level, msgid):
    94     def GetLogMessage(self, msgid):
       
    95         if self._GetLogMessage is not None:
   100         if self._GetLogMessage is not None:
    96             maxsz = len(self._log_read_buffer)-1
   101             maxsz = len(self._log_read_buffer)-1
    97             sz = self._GetLogMessage(msgid, self._log_read_buffer, maxsz)
   102             sz = self._GetLogMessage(level, msgid, self._log_read_buffer, maxsz)
    98             if sz and sz <= maxsz:
   103             if sz and sz <= maxsz:
    99                 self._log_read_buffer[sz] = '\x00'
   104                 self._log_read_buffer[sz] = '\x00'
   100                 return self._log_read_buffer.value
   105                 return self._log_read_buffer.value
   101         elif self._loading_error is not None :
   106         elif self._loading_error is not None and level==0:
   102             return self._loading_error
   107             return self._loading_error
   103         return None
   108         return None
   104 
   109 
   105     def _GetMD5FileName(self):
   110     def _GetMD5FileName(self):
   106         return os.path.join(self.workingdir, "lasttransferedPLC.md5")
   111         return os.path.join(self.workingdir, "lasttransferedPLC.md5")
   169             self._resumeDebug = self.PLClibraryHandle.resumeDebug
   174             self._resumeDebug = self.PLClibraryHandle.resumeDebug
   170             self._resumeDebug.restype = None
   175             self._resumeDebug.restype = None
   171 
   176 
   172             self._GetLogCount = self.PLClibraryHandle.GetLogCount
   177             self._GetLogCount = self.PLClibraryHandle.GetLogCount
   173             self._GetLogCount.restype = ctypes.c_uint32
   178             self._GetLogCount.restype = ctypes.c_uint32
       
   179             self._GetLogCount.argtypes = [ctypes.c_uint8]
   174 
   180 
   175             self._LogMessage = self.PLClibraryHandle.LogMessage
   181             self._LogMessage = self.PLClibraryHandle.LogMessage
   176             self._LogMessage.restype = ctypes.c_int
   182             self._LogMessage.restype = ctypes.c_int
   177             self._LogMessage.argtypes = [ctypes.c_char_p, ctypes.c_uint32]
   183             self._LogMessage.argtypes = [ctypes.c_uint8, ctypes.c_char_p, ctypes.c_uint32]
   178             
   184             
   179             self._log_read_buffer = ctypes.create_string_buffer(1<<14) #16K
   185             self._log_read_buffer = ctypes.create_string_buffer(1<<14) #16K
   180             self._GetLogMessage = self.PLClibraryHandle.GetLogMessage
   186             self._GetLogMessage = self.PLClibraryHandle.GetLogMessage
   181             self._GetLogMessage.restype = ctypes.c_uint32
   187             self._GetLogMessage.restype = ctypes.c_uint32
   182             self._GetLogMessage.argtypes = [ctypes.c_uint32, ctypes.c_char_p, ctypes.c_uint32]
   188             self._GetLogMessage.argtypes = [ctypes.c_uint8, ctypes.c_uint32, ctypes.c_char_p, ctypes.c_uint32]
   183 
   189 
   184             self._loading_error = None
   190             self._loading_error = None
   185             return True
   191             return True
   186         except:
   192         except:
   187             self._loading_error = traceback.format_exc()
   193             self._loading_error = traceback.format_exc()
   204         self._GetDebugData = lambda:-1
   210         self._GetDebugData = lambda:-1
   205         self._suspendDebug = lambda x:-1
   211         self._suspendDebug = lambda x:-1
   206         self._resumeDebug = lambda:None
   212         self._resumeDebug = lambda:None
   207         self._PythonIterator = lambda:""
   213         self._PythonIterator = lambda:""
   208         self._GetLogCount = None 
   214         self._GetLogCount = None 
   209         self._LogMessage = lambda m,s:PLCprint("OFF LOG :"+m)
   215         self._LogMessage = lambda l,m,s:PLCprint("OFF LOG :"+m)
   210         self._GetLogMessage = None
   216         self._GetLogMessage = None
   211         self.PLClibraryHandle = None
   217         self.PLClibraryHandle = None
   212         # Unload library explicitely
   218         # Unload library explicitely
   213         if getattr(self,"_PLClibraryHandle",None) is not None:
   219         if getattr(self,"_PLClibraryHandle",None) is not None:
   214             dlclose(self._PLClibraryHandle)
   220             dlclose(self._PLClibraryHandle)
   291         self.PLCStatus = "Stopped"
   297         self.PLCStatus = "Stopped"
   292         self.StatusChange()
   298         self.StatusChange()
   293         self.evaluator(self.FinishRuntimePy)
   299         self.evaluator(self.FinishRuntimePy)
   294     
   300     
   295     def StartPLC(self):
   301     def StartPLC(self):
   296         PLCprint("StartPLC")
       
   297         self.LogMessage("Hello Log")
       
   298         if self.CurrentPLCFilename is not None and self.PLCStatus == "Stopped":
   302         if self.CurrentPLCFilename is not None and self.PLCStatus == "Stopped":
   299             c_argv = ctypes.c_char_p * len(self.argv)
   303             c_argv = ctypes.c_char_p * len(self.argv)
   300             error = None
   304             error = None
   301             res = self._startPLC(len(self.argv),c_argv(*self.argv))
   305             res = self._startPLC(len(self.argv),c_argv(*self.argv))
   302             if res == 0:
   306             if res == 0:
   303                 self.StartSem=Semaphore(0)
   307                 self.StartSem=Semaphore(0)
   304                 self.PythonThread = Thread(target=self.PythonThreadProc)
   308                 self.PythonThread = Thread(target=self.PythonThreadProc)
   305                 self.PythonThread.start()
   309                 self.PythonThread.start()
   306                 self.StartSem.acquire()
   310                 self.StartSem.acquire()
       
   311                 self.LogMessage("PLC started")
   307             else:
   312             else:
   308                 PLCprint(_("Problem starting PLC : error %d" % res))
   313                 self.LogMessage(_("Problem starting PLC : error %d" % res))
   309                 self.PLCStatus = "Broken"
   314                 self.PLCStatus = "Broken"
   310                 self.StatusChange()
   315                 self.StatusChange()
   311             
   316             
   312     def StopPLC(self):
   317     def StopPLC(self):
   313         PLCprint("StopPLC")
       
   314         if self.PLCStatus == "Started":
   318         if self.PLCStatus == "Started":
       
   319             self.LogMessage("PLC stopped")
   315             self._stopPLC()
   320             self._stopPLC()
   316             self.PythonThread.join()
   321             self.PythonThread.join()
   317             return True
   322             return True
   318         return False
   323         return False
   319 
   324 
   328         # respawn python interpreter
   333         # respawn python interpreter
   329         Timer(0.1,self._Reload).start()
   334         Timer(0.1,self._Reload).start()
   330         return True
   335         return True
   331 
   336 
   332     def GetPLCstatus(self):
   337     def GetPLCstatus(self):
   333         return self.PLCStatus, self.GetLogCount()
   338         return self.PLCStatus, map(self.GetLogCount,xrange(LogLevelsCount))
   334     
   339     
   335     def NewPLC(self, md5sum, data, extrafiles):
   340     def NewPLC(self, md5sum, data, extrafiles):
   336         PLCprint("NewPLC (%s)"%md5sum)
   341         self.LogMessage("NewPLC (%s)"%md5sum)
   337         if self.PLCStatus in ["Stopped", "Empty", "Broken"]:
   342         if self.PLCStatus in ["Stopped", "Empty", "Broken"]:
   338             NewFileName = md5sum + lib_ext
   343             NewFileName = md5sum + lib_ext
   339             extra_files_log = os.path.join(self.workingdir,"extra_files.txt")
   344             extra_files_log = os.path.join(self.workingdir,"extra_files.txt")
   340 
   345 
   341             self._FreePLC()
   346             self._FreePLC()
   449                                     #PLCprint("Debug error - buffer too small ! %d != %d"%(offset, size.value))
   454                                     #PLCprint("Debug error - buffer too small ! %d != %d"%(offset, size.value))
   450                                 break
   455                                 break
   451                     self._FreeDebugData()
   456                     self._FreeDebugData()
   452                 self.PLClibraryLock.release()
   457                 self.PLClibraryLock.release()
   453             if offset and offset == size.value:
   458             if offset and offset == size.value:
   454                 return self.PLCStatus, self.GetLogCount(), tick.value, res
   459                 return self.PLCStatus, tick.value, res
   455             #elif size.value:
   460             #elif size.value:
   456                 #PLCprint("Debug error - wrong buffer unpack ! %d != %d"%(offset, size.value))
   461                 #PLCprint("Debug error - wrong buffer unpack ! %d != %d"%(offset, size.value))
   457         return self.PLCStatus, self.GetLogCount(), None, []
   462         return self.PLCStatus, None, []
   458 
   463 
   459     def RemoteExec(self, script, **kwargs):
   464     def RemoteExec(self, script, **kwargs):
   460         try:
   465         try:
   461             exec script in kwargs
   466             exec script in kwargs
   462         except:
   467         except: