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