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: |