Edouard@2270: #!/usr/bin/env python Edouard@2270: # -*- coding: utf-8 -*- Edouard@2270: Edouard@2270: # This file is part of Beremiz runtime. Edouard@2270: Edouard@2270: # Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD Edouard@2270: # Copyright (C) 2017: Andrey Skvortsov Edouard@2270: # Copyright (C) 2018: Edouard TISSERANT Edouard@2270: Edouard@2270: # See COPYING file for copyrights details. Edouard@2270: edouard@2309: from __future__ import absolute_import edouard@2309: from __future__ import print_function Edouard@2270: import sys Edouard@2603: import os Edouard@2270: Edouard@2270: import Pyro Edouard@2270: import Pyro.core as pyro Edouard@2270: import runtime Edouard@2270: from runtime.ServicePublisher import ServicePublisher Edouard@2270: edouard@2309: Edouard@2476: class PyroServer(object): Edouard@2270: def __init__(self, servicename, ip_addr, port): Edouard@2270: self.continueloop = True Edouard@2270: self.daemon = None Edouard@2270: self.servicename = servicename Edouard@2270: self.ip_addr = ip_addr Edouard@2270: self.port = port Edouard@2270: self.servicepublisher = None Edouard@2603: self.piper, self.pipew = None, None Edouard@2270: Edouard@2270: def _to_be_published(self): Edouard@2270: return self.servicename is not None and \ Edouard@2311: self.ip_addr not in ["", "localhost", "127.0.0.1"] Edouard@2270: Edouard@2270: def PrintServerInfo(self): Edouard@2270: print(_("Pyro port :"), self.port) Edouard@2270: Edouard@2270: if self._to_be_published(): Edouard@2270: print(_("Publishing service on local network")) Edouard@2270: Edouard@2270: sys.stdout.flush() Edouard@2270: Edouard@2270: def PyroLoop(self, when_ready): edouard@2492: if self._to_be_published(): edouard@2492: self.Publish() edouard@2492: Edouard@2270: while self.continueloop: Edouard@2270: Pyro.config.PYRO_MULTITHREADED = 0 Edouard@2270: pyro.initServer() Edouard@2270: self.daemon = pyro.Daemon(host=self.ip_addr, port=self.port) Edouard@2270: Edouard@2270: # pyro never frees memory after connection close if no timeout set Edouard@2270: # taking too small timeout value may cause Edouard@2270: # unwanted diconnection when IDE is kept busy for long periods Edouard@2270: self.daemon.setTimeout(60) edouard@2309: edouard@2309: pyro_obj = Pyro.core.ObjBase() Edouard@2270: pyro_obj.delegateTo(runtime.GetPLCObjectSingleton()) Edouard@2270: Edouard@2270: self.daemon.connect(pyro_obj, "PLCObject") Edouard@2270: Edouard@2270: when_ready() edouard@3308: edouard@3308: # "pipe to self" trick to to accelerate runtime shutdown edouard@3308: # instead of waiting for arbitrary pyro timeout. edouard@3308: others = [] edouard@3308: if not sys.platform.startswith('win'): edouard@3308: self.piper, self.pipew = os.pipe() edouard@3311: others.append(self.piper) edouard@3308: edouard@3308: self.daemon.requestLoop(others=others, callback=lambda x: None) Edouard@2603: self.piper, self.pipew = None, None edouard@2625: if hasattr(self, 'sock'): Edouard@2603: self.daemon.sock.close() Edouard@2476: self.Unpublish() Edouard@2270: Edouard@2270: def Restart(self): Edouard@2476: self.daemon.shutdown(True) Edouard@2270: Edouard@2270: def Quit(self): Edouard@2270: self.continueloop = False Edouard@2476: self.daemon.shutdown(True) Edouard@2603: self.daemon.closedown() edouard@3308: if not sys.platform.startswith('win'): edouard@3308: if self.pipew is not None: edouard@3308: os.write(self.pipew, "goodbye") Edouard@2270: Edouard@2476: def Publish(self): Edouard@2476: self.servicepublisher = ServicePublisher("PYRO") Edouard@2476: self.servicepublisher.RegisterService(self.servicename, Edouard@2476: self.ip_addr, self.port) Edouard@2476: Edouard@2476: def Unpublish(self): Edouard@2270: if self.servicepublisher is not None: Edouard@2270: self.servicepublisher.UnRegisterService() Edouard@2270: self.servicepublisher = None