22 #License along with this library; if not, write to the Free Software |
22 #License along with this library; if not, write to the Free Software |
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 |
26 from threading import Timer, Thread |
27 import ctypes, os, commands |
27 import ctypes, os, commands, types, sys |
28 import sys |
28 |
29 |
29 |
30 if os.name in ("nt", "ce"): |
30 if os.name in ("nt", "ce"): |
31 from _ctypes import LoadLibrary as dlopen |
31 from _ctypes import LoadLibrary as dlopen |
32 from _ctypes import FreeLibrary as dlclose |
32 from _ctypes import FreeLibrary as dlclose |
33 elif os.name == "posix": |
33 elif os.name == "posix": |
44 sys.stdout.write("PLCobject : "+message+"\n") |
44 sys.stdout.write("PLCobject : "+message+"\n") |
45 sys.stdout.flush() |
45 sys.stdout.flush() |
46 |
46 |
47 class PLCObject(pyro.ObjBase): |
47 class PLCObject(pyro.ObjBase): |
48 _Idxs = [] |
48 _Idxs = [] |
49 def __init__(self, workingdir, daemon, argv, statuschange=None): |
49 def __init__(self, workingdir, daemon, argv, statuschange=None, evaluator=eval): |
50 pyro.ObjBase.__init__(self) |
50 pyro.ObjBase.__init__(self) |
|
51 self.evaluator = evaluator |
51 self.argv = [workingdir] + argv # force argv[0] to be "path" to exec... |
52 self.argv = [workingdir] + argv # force argv[0] to be "path" to exec... |
52 self.workingdir = workingdir |
53 self.workingdir = workingdir |
53 self.PLCStatus = "Stopped" |
54 self.PLCStatus = "Stopped" |
54 self.PLClibraryHandle = None |
55 self.PLClibraryHandle = None |
55 # Creates fake C funcs proxies |
56 # Creates fake C funcs proxies |
56 self._FreePLC() |
57 self._FreePLC() |
57 self.daemon = daemon |
58 self.daemon = daemon |
58 self.statuschange = statuschange |
59 self.statuschange = statuschange |
59 self.python_threads_vars = None |
60 self.python_threads_vars = None |
|
61 self.hmi_frame = None |
60 |
62 |
61 # Get the last transfered PLC if connector must be restart |
63 # Get the last transfered PLC if connector must be restart |
62 try: |
64 try: |
63 self.CurrentPLCFilename=open( |
65 self.CurrentPLCFilename=open( |
64 self._GetMD5FileName(), |
66 self._GetMD5FileName(), |
179 return False |
181 return False |
180 |
182 |
181 def PrepareRuntimePy(self): |
183 def PrepareRuntimePy(self): |
182 self.python_threads_vars = globals().copy() |
184 self.python_threads_vars = globals().copy() |
183 pyfile = os.path.join(self.workingdir, "runtime.py") |
185 pyfile = os.path.join(self.workingdir, "runtime.py") |
|
186 hmifile = os.path.join(self.workingdir, "hmi.py") |
184 if os.path.exists(pyfile): |
187 if os.path.exists(pyfile): |
185 try: |
188 try: |
186 # TODO handle exceptions in runtime.py |
189 # TODO handle exceptions in runtime.py |
187 # pyfile may redefine _runtime_cleanup |
190 # pyfile may redefine _runtime_cleanup |
188 # or even call _PythonThreadProc itself. |
191 # or even call _PythonThreadProc itself. |
|
192 if os.path.exists(hmifile): |
|
193 execfile(hmifile, self.python_threads_vars) |
189 execfile(pyfile, self.python_threads_vars) |
194 execfile(pyfile, self.python_threads_vars) |
|
195 try: |
|
196 # try to instanciate the first frame found. |
|
197 for name, obj in self.python_threads_vars.iteritems(): |
|
198 # obj is a class |
|
199 if type(obj)==type(type) and issubclass(obj,self.python_threads_vars['wx'].Frame): |
|
200 self.hmi_frame = obj(None) |
|
201 self.python_threads_vars['_'+name] = self.hmi_frame |
|
202 self.hmi_frame.Show() |
|
203 break |
|
204 except: |
|
205 PLCprint(traceback.format_exc()) |
190 except: |
206 except: |
191 PLCprint(traceback.format_exc()) |
207 PLCprint(traceback.format_exc()) |
192 |
208 |
193 def BeginRuntimePy(self): |
209 def BeginRuntimePy(self): |
194 runtime_begin = self.python_threads_vars.get("_runtime_begin",None) |
210 runtime_begin = self.python_threads_vars.get("_runtime_begin",None) |
195 if runtime_begin is not None: |
211 if runtime_begin is not None: |
196 runtime_begin() |
212 self.evaluator(runtime_begin) |
197 |
213 |
198 def FinishRuntimePy(self): |
214 def FinishRuntimePy(self): |
199 runtime_cleanup = self.python_threads_vars.get("_runtime_cleanup",None) |
215 runtime_cleanup = self.python_threads_vars.get("_runtime_cleanup",None) |
200 if runtime_cleanup is not None: |
216 if runtime_cleanup is not None: |
201 runtime_cleanup() |
217 self.evaluator(runtime_cleanup) |
|
218 if self.hmi_frame is not None: |
|
219 self.evaluator(self.hmi_frame.Destroy) |
202 self.python_threads_vars = None |
220 self.python_threads_vars = None |
203 |
221 |
204 def PythonThreadProc(self): |
222 def PythonThreadProc(self): |
205 PLCprint("PythonThreadProc started") |
223 PLCprint("PythonThreadProc started") |
206 self.BeginRuntimePy() |
224 self.BeginRuntimePy() |
225 if self._LoadNewPLC() and self._startPLC(len(self.argv),c_argv(*self.argv)) == 0: |
243 if self._LoadNewPLC() and self._startPLC(len(self.argv),c_argv(*self.argv)) == 0: |
226 if debug: |
244 if debug: |
227 self._resumeDebug() |
245 self._resumeDebug() |
228 self.PLCStatus = "Started" |
246 self.PLCStatus = "Started" |
229 self.StatusChange() |
247 self.StatusChange() |
230 self.PrepareRuntimePy() |
248 self.evaluator(self.PrepareRuntimePy) |
231 self.PythonThread = Thread(target=self.PythonThreadProc) |
249 self.PythonThread = Thread(target=self.PythonThreadProc) |
232 self.PythonThread.start() |
250 self.PythonThread.start() |
233 return True |
251 return True |
234 else: |
252 else: |
235 PLCprint("Problem starting PLC") |
253 PLCprint("Problem starting PLC") |