25 import os, sys, getopt |
25 import os, sys, getopt |
26 |
26 |
27 def usage(): |
27 def usage(): |
28 print """ |
28 print """ |
29 Usage of Beremiz PLC execution service :\n |
29 Usage of Beremiz PLC execution service :\n |
30 %s {[-n name] [-i ip] [-p port] [-x enabletaskbar] [-a autostart]|-h|--help} working_dir |
30 %s {[-n servicename] [-i ip] [-p port] [-x enabletaskbar] [-a autostart]|-h|--help} working_dir |
31 -n - zeroconf service name |
31 -n - zeroconf service name (default:disabled) |
32 -i - ip of interface to bind to (x.x.x.x) |
32 -i - ip of interface to bind to (default:localhost) |
33 -p - port number |
33 -p - port number default:3000 |
34 -h - print this help text and quit |
34 -h - print this help text and quit |
35 -a - autostart PLC (0:disable 1:enable) |
35 -a - autostart PLC (0:disable 1:enable) (default:0) |
36 -x - enable/disable wxTaskbarIcon (0:disable 1:enable) |
36 -x - enable/disable wxTaskbarIcon (0:disable 1:enable) (default:1) |
37 -t - enable/disable Twisted web interface (0:disable 1:enable) |
37 -t - enable/disable Twisted web interface (0:disable 1:enable) (default:1) |
38 |
38 |
39 working_dir - directory where are stored PLC files |
39 working_dir - directory where are stored PLC files |
40 """%sys.argv[0] |
40 """%sys.argv[0] |
41 |
41 |
42 try: |
42 try: |
429 |
427 |
430 def default_evaluator(callable, *args, **kwargs): |
428 def default_evaluator(callable, *args, **kwargs): |
431 return callable(*args,**kwargs) |
429 return callable(*args,**kwargs) |
432 |
430 |
433 class Server(): |
431 class Server(): |
434 def __init__(self, name, ip, port, workdir, argv, autostart=False, statuschange=None, evaluator=default_evaluator, website=None): |
432 def __init__(self, servicename, ip, port, workdir, argv, autostart=False, statuschange=None, evaluator=default_evaluator, website=None): |
435 self.continueloop = True |
433 self.continueloop = True |
436 self.daemon = None |
434 self.daemon = None |
437 self.name = name |
435 self.servicename = servicename |
438 self.ip = ip |
436 self.ip = ip |
439 self.port = port |
437 self.port = port |
440 self.workdir = workdir |
438 self.workdir = workdir |
441 self.argv = argv |
439 self.argv = argv |
442 self.plcobj = None |
440 self.plcobj = None |
461 pyro.initServer() |
459 pyro.initServer() |
462 self.daemon=pyro.Daemon(host=self.ip, port=self.port) |
460 self.daemon=pyro.Daemon(host=self.ip, port=self.port) |
463 self.plcobj = PLCObject(self.workdir, self.daemon, self.argv, self.statuschange, self.evaluator, self.website) |
461 self.plcobj = PLCObject(self.workdir, self.daemon, self.argv, self.statuschange, self.evaluator, self.website) |
464 uri = self.daemon.connect(self.plcobj,"PLCObject") |
462 uri = self.daemon.connect(self.plcobj,"PLCObject") |
465 |
463 |
466 print "The daemon runs on port :",self.port |
464 print "Pyro port :",self.port |
467 print "The object's uri is :",uri |
465 print "Pyro object's uri :",uri |
468 print "The working directory :",self.workdir |
466 print "Current working directory :",self.workdir |
469 |
467 |
470 # Configure and publish service |
468 # Configure and publish service |
471 # Not publish service if localhost in address params |
469 # Not publish service if localhost in address params |
472 if self.ip != "localhost" and self.ip != "127.0.0.1": |
470 if self.servicename is not None and self.ip != "localhost" and self.ip != "127.0.0.1": |
473 print "Publish service on local network" |
471 print "Publishing service on local network" |
474 self.servicepublisher = ServicePublisher.ServicePublisher() |
472 self.servicepublisher = ServicePublisher.ServicePublisher() |
475 self.servicepublisher.RegisterService(self.name, self.ip, self.port) |
473 self.servicepublisher.RegisterService(self.servicename, self.ip, self.port) |
476 |
474 |
477 if self.autostart: |
475 if self.autostart: |
478 self.plcobj.StartPLC() |
476 self.plcobj.StartPLC() |
479 |
477 |
480 sys.stdout.flush() |
478 sys.stdout.flush() |
483 |
481 |
484 def Stop(self): |
482 def Stop(self): |
485 self.plcobj.StopPLC() |
483 self.plcobj.StopPLC() |
486 if self.servicepublisher is not None: |
484 if self.servicepublisher is not None: |
487 self.servicepublisher.UnRegisterService() |
485 self.servicepublisher.UnRegisterService() |
488 del self.servicepublisher |
486 self.servicepublisher = None |
489 self.daemon.shutdown(True) |
487 self.daemon.shutdown(True) |
490 |
488 |
491 if enabletwisted: |
489 if enabletwisted: |
492 try: |
490 try: |
|
491 from threading import Thread, currentThread |
493 if havewx: |
492 if havewx: |
494 from twisted.internet import wxreactor |
493 from twisted.internet import wxreactor |
495 wxreactor.install() |
494 wxreactor.install() |
496 from twisted.internet import reactor, task |
495 from twisted.internet import reactor, task |
497 from twisted.python import log, util |
496 from twisted.python import log, util |
498 from nevow import rend, appserver, inevow, tags, loaders, athena |
497 from nevow import rend, appserver, inevow, tags, loaders, athena |
499 from nevow.page import renderer |
498 from nevow.page import renderer |
500 |
499 |
501 havetwisted = True |
500 havetwisted = True |
502 except: |
501 except: |
|
502 print "Twisted unavailable !" |
503 havetwisted = False |
503 havetwisted = False |
504 |
504 |
505 if havetwisted: |
505 if havetwisted: |
506 |
506 |
507 xhtml_header = '''<?xml version="1.0" encoding="utf-8"?> |
507 xhtml_header = '''<?xml version="1.0" encoding="utf-8"?> |
646 #print reason |
646 #print reason |
647 #print "We will be called back when the client disconnects" |
647 #print "We will be called back when the client disconnects" |
648 |
648 |
649 if havewx: |
649 if havewx: |
650 reactor.registerWxApp(app) |
650 reactor.registerWxApp(app) |
651 res = WebInterface() |
651 website = WebInterface() |
652 site = appserver.NevowSite(res) |
652 site = appserver.NevowSite(website) |
653 |
653 |
654 website_port = 8009 |
654 website_port = 8009 |
655 listening = False |
655 listening = False |
656 while not listening: |
656 while not listening: |
657 try: |
657 try: |
658 reactor.listenTCP(website_port, site) |
658 reactor.listenTCP(website_port, site) |
659 listening = True |
659 listening = True |
660 except: |
660 except: |
661 website_port += 1 |
661 website_port += 1 |
|
662 print "Http interface port :",website_port |
662 else: |
663 else: |
663 res = None |
664 website = None |
664 |
665 |
665 if havewx: |
666 if havewx: |
666 from threading import Semaphore |
667 from threading import Semaphore |
667 wx_eval_lock = Semaphore(0) |
668 wx_eval_lock = Semaphore(0) |
668 mythread = currentThread() |
669 mythread = currentThread() |
686 callable(*args,**kwargs) |
687 callable(*args,**kwargs) |
687 else: |
688 else: |
688 wx.CallAfter(wx_evaluator,callable,*args,**kwargs) |
689 wx.CallAfter(wx_evaluator,callable,*args,**kwargs) |
689 wx_eval_lock.acquire() |
690 wx_eval_lock.acquire() |
690 return eval_res |
691 return eval_res |
691 |
692 |
692 pyroserver = Server(name, ip, port, WorkingDir, argv, autostart, statuschange, evaluator, res) |
693 pyroserver = Server(servicename, ip, port, WorkingDir, argv, autostart, statuschange, evaluator, website) |
693 taskbar_instance = BeremizTaskBarIcon(pyroserver) |
694 taskbar_instance = BeremizTaskBarIcon(pyroserver) |
694 |
695 else: |
|
696 pyroserver = Server(servicename, ip, port, WorkingDir, argv, autostart, website=website) |
|
697 |
|
698 if havetwisted or havewx: |
695 pyro_thread=Thread(target=pyroserver.Loop) |
699 pyro_thread=Thread(target=pyroserver.Loop) |
696 pyro_thread.start() |
700 pyro_thread.start() |
|
701 |
|
702 if havetwisted: |
|
703 reactor.run() |
|
704 elif havewx: |
|
705 app.MainLoop() |
697 else: |
706 else: |
698 pyroserver = Server(name, ip, port, WorkingDir, argv, autostart, website=res) |
707 try : |
699 |
708 pyroserver.Loop() |
700 if havetwisted: |
709 except KeyboardInterrupt,e: |
701 reactor.run() |
710 pass |
702 elif havewx: |
711 pyroserver.Quit() |
703 app.MainLoop() |
712 sys.exit(0) |
704 else: |
713 |
705 pyroserver.Loop() |
|