21 #You should have received a copy of the GNU General Public |
21 #You should have received a copy of the GNU General Public |
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, Lock |
27 import ctypes, os, commands, types, sys |
27 import ctypes, os, commands, types, sys |
28 import time |
28 import time |
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 |
51 self.evaluator = evaluator |
51 self.evaluator = evaluator |
52 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... |
53 self.workingdir = workingdir |
53 self.workingdir = workingdir |
54 self.PLCStatus = "Stopped" |
54 self.PLCStatus = "Stopped" |
55 self.PLClibraryHandle = None |
55 self.PLClibraryHandle = None |
|
56 self.PLClibraryLock = Lock() |
56 # Creates fake C funcs proxies |
57 # Creates fake C funcs proxies |
57 self._FreePLC() |
58 self._FreePLC() |
58 self.daemon = daemon |
59 self.daemon = daemon |
59 self.statuschange = statuschange |
60 self.statuschange = statuschange |
60 self.hmi_frame = None |
61 self.hmi_frame = None |
91 |
92 |
92 self._startPLC = self.PLClibraryHandle.startPLC |
93 self._startPLC = self.PLClibraryHandle.startPLC |
93 self._startPLC.restype = ctypes.c_int |
94 self._startPLC.restype = ctypes.c_int |
94 self._startPLC.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_char_p)] |
95 self._startPLC.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_char_p)] |
95 |
96 |
96 self._stopPLC = self.PLClibraryHandle.stopPLC |
97 def StopPLCLock(): |
|
98 self.PLClibraryLock.acquire() |
|
99 self.PLClibraryHandle.stopPLC() |
|
100 self.PLClibraryLock.release() |
|
101 |
|
102 self._stopPLC = StopPLCLock |
97 self._stopPLC.restype = None |
103 self._stopPLC.restype = None |
98 |
104 |
99 self._ResetDebugVariables = self.PLClibraryHandle.ResetDebugVariables |
105 self._ResetDebugVariables = self.PLClibraryHandle.ResetDebugVariables |
100 self._ResetDebugVariables.restype = None |
106 self._ResetDebugVariables.restype = None |
101 |
107 |
131 def _FreePLC(self): |
137 def _FreePLC(self): |
132 """ |
138 """ |
133 Unload PLC library. |
139 Unload PLC library. |
134 This is also called by __init__ to create dummy C func proxies |
140 This is also called by __init__ to create dummy C func proxies |
135 """ |
141 """ |
|
142 self.PLClibraryLock.acquire() |
136 # Forget all refs to library |
143 # Forget all refs to library |
137 self._startPLC = lambda:None |
144 self._startPLC = lambda:None |
138 self._stopPLC = lambda:None |
145 self._stopPLC = lambda:None |
139 self._ResetDebugVariables = lambda:None |
146 self._ResetDebugVariables = lambda:None |
140 self._RegisterDebugVariable = lambda x:None |
147 self._RegisterDebugVariable = lambda x:None |
249 self._resumeDebug() |
256 self._resumeDebug() |
250 self.PLCStatus = "Started" |
257 self.PLCStatus = "Started" |
251 self.StatusChange() |
258 self.StatusChange() |
252 self.evaluator(self.PrepareRuntimePy) |
259 self.evaluator(self.PrepareRuntimePy) |
253 res,cmd = "None","None" |
260 res,cmd = "None","None" |
254 while self.PLCStatus == "Started": |
261 while True: |
255 #print "_PythonIterator(", res, ")", |
262 #print "_PythonIterator(", res, ")", |
256 cmd = self._PythonIterator(res) |
263 cmd = self._PythonIterator(res) |
257 #print " -> ", cmd |
264 #print " -> ", cmd |
258 if cmd is None: |
265 if cmd is None: |
259 break |
266 break |
270 else: |
277 else: |
271 error = "loading" |
278 error = "loading" |
272 if error is not None: |
279 if error is not None: |
273 PLCprint("Problem %s PLC"%error) |
280 PLCprint("Problem %s PLC"%error) |
274 self.PLCStatus = "Broken" |
281 self.PLCStatus = "Broken" |
275 self._DoStopPLC() |
|
276 self._FreePLC() |
282 self._FreePLC() |
277 PLCprint("PythonThreadProc interrupted") |
283 PLCprint("PythonThreadProc interrupted") |
278 |
284 |
279 def StartPLC(self, debug=False): |
285 def StartPLC(self, debug=False): |
280 PLCprint("StartPLC") |
286 PLCprint("StartPLC") |
281 if self.CurrentPLCFilename is not None and self.PLCStatus == "Stopped": |
287 if self.CurrentPLCFilename is not None: |
282 self.PythonThread = Thread(target=self.PythonThreadProc, args=[debug]) |
288 self.PythonThread = Thread(target=self.PythonThreadProc, args=[debug]) |
283 self.PythonThread.start() |
289 self.PythonThread.start() |
284 |
290 |
285 def _DoStopPLC(self): |
|
286 self.StatusChange() |
|
287 self._stopPLC() |
|
288 self.StatusChange() |
|
289 return True |
|
290 |
|
291 def StopPLC(self): |
291 def StopPLC(self): |
292 PLCprint("StopPLC") |
292 PLCprint("StopPLC") |
293 if self.PLCStatus == "Started": |
293 if self.PLCStatus == "Started": |
294 self._DoStopPLC() |
294 self._stopPLC() |
295 self.PLCStatus = "Stopped" |
|
296 return True |
295 return True |
297 return False |
296 return False |
298 |
297 |
299 def _Reload(self): |
298 def _Reload(self): |
300 self.daemon.shutdown(True) |
299 self.daemon.shutdown(True) |