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 |