34 from threading import Thread, Semaphore, Lock, current_thread |
34 from threading import Thread, Semaphore, Lock, current_thread |
35 import builtins |
35 import builtins |
36 from functools import partial |
36 from functools import partial |
37 |
37 |
38 import runtime |
38 import runtime |
39 from runtime.PyroServer import PyroServer |
39 from runtime.eRPCServer import eRPCServer as RPCServer |
40 from runtime.xenomai import TryPreloadXenomai |
40 from runtime.xenomai import TryPreloadXenomai |
41 from runtime import LogMessageAndException |
41 from runtime import LogMessageAndException |
42 from runtime import PlcStatus |
42 from runtime import PlcStatus |
43 from runtime import default_evaluator |
43 from runtime import default_evaluator |
44 from runtime.Stunnel import ensurePSK |
44 from runtime.Stunnel import ensurePSK |
268 TBMENU_CHANGE_NAME = wx.NewIdRef() |
268 TBMENU_CHANGE_NAME = wx.NewIdRef() |
269 TBMENU_CHANGE_PORT = wx.NewIdRef() |
269 TBMENU_CHANGE_PORT = wx.NewIdRef() |
270 TBMENU_CHANGE_INTERFACE = wx.NewIdRef() |
270 TBMENU_CHANGE_INTERFACE = wx.NewIdRef() |
271 TBMENU_LIVE_SHELL = wx.NewIdRef() |
271 TBMENU_LIVE_SHELL = wx.NewIdRef() |
272 TBMENU_WXINSPECTOR = wx.NewIdRef() |
272 TBMENU_WXINSPECTOR = wx.NewIdRef() |
273 TBMENU_CHANGE_WD = wx.NewIdRef() |
273 # TBMENU_CHANGE_WD = wx.NewIdRef() |
274 TBMENU_QUIT = wx.NewIdRef() |
274 TBMENU_QUIT = wx.NewIdRef() |
275 |
275 |
276 def __init__(self, pyroserver): |
276 def __init__(self, rpc_server): |
277 wx.adv.TaskBarIcon.__init__(self) |
277 wx.adv.TaskBarIcon.__init__(self) |
278 self.pyroserver = pyroserver |
278 self.rpc_server = rpc_server |
279 # Set the image |
279 # Set the image |
280 self.UpdateIcon(None) |
280 self.UpdateIcon(None) |
281 |
281 |
282 # bind some events |
282 # bind some events |
283 self.Bind(wx.EVT_MENU, self.OnTaskBarStartPLC, id=self.TBMENU_START) |
283 self.Bind(wx.EVT_MENU, self.OnTaskBarStartPLC, id=self.TBMENU_START) |
285 self.Bind(wx.EVT_MENU, self.OnTaskBarChangeName, id=self.TBMENU_CHANGE_NAME) |
285 self.Bind(wx.EVT_MENU, self.OnTaskBarChangeName, id=self.TBMENU_CHANGE_NAME) |
286 self.Bind(wx.EVT_MENU, self.OnTaskBarChangeInterface, id=self.TBMENU_CHANGE_INTERFACE) |
286 self.Bind(wx.EVT_MENU, self.OnTaskBarChangeInterface, id=self.TBMENU_CHANGE_INTERFACE) |
287 self.Bind(wx.EVT_MENU, self.OnTaskBarLiveShell, id=self.TBMENU_LIVE_SHELL) |
287 self.Bind(wx.EVT_MENU, self.OnTaskBarLiveShell, id=self.TBMENU_LIVE_SHELL) |
288 self.Bind(wx.EVT_MENU, self.OnTaskBarWXInspector, id=self.TBMENU_WXINSPECTOR) |
288 self.Bind(wx.EVT_MENU, self.OnTaskBarWXInspector, id=self.TBMENU_WXINSPECTOR) |
289 self.Bind(wx.EVT_MENU, self.OnTaskBarChangePort, id=self.TBMENU_CHANGE_PORT) |
289 self.Bind(wx.EVT_MENU, self.OnTaskBarChangePort, id=self.TBMENU_CHANGE_PORT) |
290 self.Bind(wx.EVT_MENU, self.OnTaskBarChangeWorkingDir, id=self.TBMENU_CHANGE_WD) |
290 # self.Bind(wx.EVT_MENU, self.OnTaskBarChangeWorkingDir, id=self.TBMENU_CHANGE_WD) |
291 self.Bind(wx.EVT_MENU, self.OnTaskBarQuit, id=self.TBMENU_QUIT) |
291 self.Bind(wx.EVT_MENU, self.OnTaskBarQuit, id=self.TBMENU_QUIT) |
292 |
292 |
293 def CreatePopupMenu(self): |
293 def CreatePopupMenu(self): |
294 """ |
294 """ |
295 This method is called by the base class when it needs to popup |
295 This method is called by the base class when it needs to popup |
302 menu.Append(self.TBMENU_STOP, _("Stop PLC")) |
302 menu.Append(self.TBMENU_STOP, _("Stop PLC")) |
303 menu.AppendSeparator() |
303 menu.AppendSeparator() |
304 menu.Append(self.TBMENU_CHANGE_NAME, _("Change Name")) |
304 menu.Append(self.TBMENU_CHANGE_NAME, _("Change Name")) |
305 menu.Append(self.TBMENU_CHANGE_INTERFACE, _("Change IP of interface to bind")) |
305 menu.Append(self.TBMENU_CHANGE_INTERFACE, _("Change IP of interface to bind")) |
306 menu.Append(self.TBMENU_CHANGE_PORT, _("Change Port Number")) |
306 menu.Append(self.TBMENU_CHANGE_PORT, _("Change Port Number")) |
307 menu.Append(self.TBMENU_CHANGE_WD, _("Change working directory")) |
307 # menu.Append(self.TBMENU_CHANGE_WD, _("Change working directory")) |
308 menu.AppendSeparator() |
308 menu.AppendSeparator() |
309 menu.Append(self.TBMENU_LIVE_SHELL, _("Launch a live Python shell")) |
309 menu.Append(self.TBMENU_LIVE_SHELL, _("Launch a live Python shell")) |
310 menu.Append(self.TBMENU_WXINSPECTOR, _("Launch WX GUI inspector")) |
310 menu.Append(self.TBMENU_WXINSPECTOR, _("Launch WX GUI inspector")) |
311 menu.AppendSeparator() |
311 menu.AppendSeparator() |
312 menu.Append(self.TBMENU_QUIT, _("Quit")) |
312 menu.Append(self.TBMENU_QUIT, _("Quit")) |
330 |
330 |
331 def OnTaskBarStopPLC(self, evt): |
331 def OnTaskBarStopPLC(self, evt): |
332 runtime.GetPLCObjectSingleton().StopPLC() |
332 runtime.GetPLCObjectSingleton().StopPLC() |
333 |
333 |
334 def OnTaskBarChangeInterface(self, evt): |
334 def OnTaskBarChangeInterface(self, evt): |
335 ip_addr = self.pyroserver.ip_addr |
335 ip_addr = self.rpc_server.ip_addr |
336 ip_addr = '' if ip_addr is None else ip_addr |
336 ip_addr = '' if ip_addr is None else ip_addr |
337 dlg = ParamsEntryDialog(None, _("Enter the IP of the interface to bind"), defaultValue=ip_addr) |
337 dlg = ParamsEntryDialog(None, _("Enter the IP of the interface to bind"), defaultValue=ip_addr) |
338 dlg.SetTests([(re.compile(r'\d{1,3}(?:\.\d{1,3}){3}$').match, _("IP is not valid!")), |
338 dlg.SetTests([(re.compile(r'\d{1,3}(?:\.\d{1,3}){3}$').match, _("IP is not valid!")), |
339 (lambda x:len([x for x in x.split(".") if 0 <= int(x) <= 255]) == 4, |
339 (lambda x:len([x for x in x.split(".") if 0 <= int(x) <= 255]) == 4, |
340 _("IP is not valid!"))]) |
340 _("IP is not valid!"))]) |
341 if dlg.ShowModal() == wx.ID_OK: |
341 if dlg.ShowModal() == wx.ID_OK: |
342 self.pyroserver.ip_addr = dlg.GetValue() |
342 self.rpc_server.ip_addr = dlg.GetValue() |
343 self.pyroserver.Restart() |
343 self.rpc_server.Restart() |
344 |
344 |
345 def OnTaskBarChangePort(self, evt): |
345 def OnTaskBarChangePort(self, evt): |
346 dlg = ParamsEntryDialog(None, _("Enter a port number "), defaultValue=str(self.pyroserver.port)) |
346 dlg = ParamsEntryDialog(None, _("Enter a port number "), defaultValue=str(self.rpc_server.port)) |
347 dlg.SetTests([(str.isdigit, _("Port number must be an integer!")), (lambda port: 0 <= int(port) <= 65535, _("Port number must be 0 <= port <= 65535!"))]) |
347 dlg.SetTests([(str.isdigit, _("Port number must be an integer!")), (lambda port: 0 <= int(port) <= 65535, _("Port number must be 0 <= port <= 65535!"))]) |
348 if dlg.ShowModal() == wx.ID_OK: |
348 if dlg.ShowModal() == wx.ID_OK: |
349 self.pyroserver.port = int(dlg.GetValue()) |
349 self.rpc_server.port = int(dlg.GetValue()) |
350 self.pyroserver.Restart() |
350 self.rpc_server.Restart() |
351 |
351 |
352 def OnTaskBarChangeWorkingDir(self, evt): |
352 # def OnTaskBarChangeWorkingDir(self, evt): |
353 dlg = wx.DirDialog(None, _("Choose a working directory "), self.pyroserver.workdir, wx.DD_NEW_DIR_BUTTON) |
353 # dlg = wx.DirDialog(None, _("Choose a working directory "), self.rpc_server.workdir, wx.DD_NEW_DIR_BUTTON) |
354 if dlg.ShowModal() == wx.ID_OK: |
354 # if dlg.ShowModal() == wx.ID_OK: |
355 self.pyroserver.workdir = dlg.GetPath() |
355 # self.rpc_server.workdir = dlg.GetPath() |
356 self.pyroserver.Restart() |
356 # self.rpc_server.Restart() |
357 |
357 |
358 def OnTaskBarChangeName(self, evt): |
358 def OnTaskBarChangeName(self, evt): |
359 _servicename = self.pyroserver.servicename |
359 _servicename = self.rpc_server.servicename |
360 _servicename = '' if _servicename is None else _servicename |
360 _servicename = '' if _servicename is None else _servicename |
361 dlg = ParamsEntryDialog(None, _("Enter a name "), defaultValue=_servicename) |
361 dlg = ParamsEntryDialog(None, _("Enter a name "), defaultValue=_servicename) |
362 dlg.SetTests([(lambda name: len(name) != 0, _("Name must not be null!"))]) |
362 dlg.SetTests([(lambda name: len(name) != 0, _("Name must not be null!"))]) |
363 if dlg.ShowModal() == wx.ID_OK: |
363 if dlg.ShowModal() == wx.ID_OK: |
364 self.pyroserver.servicename = dlg.GetValue() |
364 self.rpc_server.servicename = dlg.GetValue() |
365 self.pyroserver.Restart() |
365 self.rpc_server.Restart() |
366 |
366 |
367 def _LiveShellLocals(self): |
367 def _LiveShellLocals(self): |
368 return {"locals": runtime.GetPLCObjectSingleton().python_runtime_vars} |
368 return {"locals": runtime.GetPLCObjectSingleton().python_runtime_vars} |
369 |
369 |
370 def OnTaskBarLiveShell(self, evt): |
370 def OnTaskBarLiveShell(self, evt): |
511 ensurePSK(servicename, PSKpath) |
511 ensurePSK(servicename, PSKpath) |
512 |
512 |
513 runtime.CreatePLCObjectSingleton( |
513 runtime.CreatePLCObjectSingleton( |
514 WorkingDir, argv, statuschange, evaluator, pyruntimevars) |
514 WorkingDir, argv, statuschange, evaluator, pyruntimevars) |
515 |
515 |
516 pyroserver = PyroServer(servicename, interface, port) |
516 rpc_server = RPCServer(servicename, interface, port) |
517 |
517 |
518 if havewx: |
518 if havewx: |
519 taskbar_instance = BeremizTaskBarIcon(pyroserver) |
519 taskbar_instance = BeremizTaskBarIcon(rpc_server) |
520 |
520 |
521 if havetwisted: |
521 if havetwisted: |
522 if webport is not None: |
522 if webport is not None: |
523 try: |
523 try: |
524 website = NS.RegisterWebsite(interface, webport) |
524 website = NS.RegisterWebsite(interface, webport) |
531 WC.RegisterWampClient(wampconf, PSKpath) |
531 WC.RegisterWampClient(wampconf, PSKpath) |
532 WC.RegisterWebSettings(NS) |
532 WC.RegisterWebSettings(NS) |
533 except Exception: |
533 except Exception: |
534 LogMessageAndException(_("WAMP client startup failed. ")) |
534 LogMessageAndException(_("WAMP client startup failed. ")) |
535 |
535 |
536 pyro_thread = None |
536 rpc_server_thread = None |
537 |
537 |
538 def FirstWorkerJob(): |
538 def FirstWorkerJob(): |
539 """ |
539 """ |
540 RPC through pyro/wamp/UI may lead to delegation to Worker, |
540 RPC through rpc/wamp/UI may lead to delegation to Worker, |
541 then this function ensures that Worker is already |
541 then this function ensures that Worker is already |
542 created when pyro starts |
542 created when rpc starts |
543 """ |
543 """ |
544 global pyro_thread, pyroserver |
544 global rpc_server_thread, rpc_server |
545 |
545 |
546 pyro_thread_started = Lock() |
546 rpc_thread_started = Lock() |
547 pyro_thread_started.acquire() |
547 rpc_thread_started.acquire() |
548 pyro_thread = Thread(target=pyroserver.PyroLoop, |
548 rpc_server_thread = Thread(target=rpc_server.Loop, |
549 kwargs=dict(when_ready=pyro_thread_started.release), |
549 kwargs=dict(when_ready=rpc_thread_started.release), |
550 name="PyroThread") |
550 name="RPCThread") |
551 |
551 |
552 pyro_thread.start() |
552 rpc_server_thread.start() |
553 |
553 |
554 # Wait for pyro thread to be effective |
554 # Wait for rpc thread to be effective |
555 pyro_thread_started.acquire() |
555 rpc_thread_started.acquire() |
556 |
556 |
557 pyroserver.PrintServerInfo() |
557 rpc_server.PrintServerInfo() |
558 |
558 |
559 # Beremiz IDE detects LOCAL:// runtime is ready by looking |
559 # Beremiz IDE detects LOCAL:// runtime is ready by looking |
560 # for self.workdir in the daemon's stdout. |
560 # for self.workdir in the daemon's stdout. |
561 if sys.stdout: |
561 if sys.stdout: |
562 sys.stdout.write(_("Current working directory :") + WorkingDir + "\n") |
562 sys.stdout.write(_("Current working directory :") + WorkingDir + "\n") |