runtime/PyroServer.py
changeset 3884 34da877021d5
parent 3883 a6e7dd8bac36
child 3885 22a009561502
equal deleted inserted replaced
3883:a6e7dd8bac36 3884:34da877021d5
     1 #!/usr/bin/env python
       
     2 # -*- coding: utf-8 -*-
       
     3 
       
     4 # This file is part of Beremiz runtime.
       
     5 
       
     6 # Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
       
     7 # Copyright (C) 2017: Andrey Skvortsov
       
     8 # Copyright (C) 2018: Edouard TISSERANT
       
     9 
       
    10 # See COPYING file for copyrights details.
       
    11 
       
    12 
       
    13 
       
    14 import sys
       
    15 import os
       
    16 
       
    17 import Pyro5
       
    18 import Pyro5.server
       
    19 
       
    20 import runtime
       
    21 from runtime.ServicePublisher import ServicePublisher
       
    22 
       
    23 Pyro5.config.SERIALIZER = "msgpack"
       
    24 
       
    25 def make_pyro_exposed_stub(method_name):
       
    26     stub = lambda self, *args, **kwargs: \
       
    27         getattr(self.plc_object_instance, method_name)(*args, **kwargs)
       
    28     stub.__name__ = method_name
       
    29     Pyro5.server.expose(stub)
       
    30     return stub
       
    31     
       
    32 
       
    33 class PLCObjectPyroAdapter(type("PLCObjectPyroStubs", (), {
       
    34     name: make_pyro_exposed_stub(name) for name in [
       
    35         "AppendChunkToBlob",
       
    36         "GetLogMessage",
       
    37         "GetPLCID",
       
    38         "GetPLCstatus",
       
    39         "GetTraceVariables",
       
    40         "MatchMD5", 
       
    41         "NewPLC",
       
    42         "PurgeBlobs",
       
    43         "RemoteExec",
       
    44         "RepairPLC",
       
    45         "ResetLogCount",
       
    46         "SeedBlob",
       
    47         "SetTraceVariablesList",
       
    48         "StartPLC",
       
    49         "StopPLC"
       
    50     ]
       
    51 })):
       
    52     def __init__(self, plc_object_instance):
       
    53         self.plc_object_instance = plc_object_instance
       
    54     
       
    55 
       
    56 class PyroServer(object):
       
    57     def __init__(self, servicename, ip_addr, port):
       
    58         self.continueloop = True
       
    59         self.daemon = None
       
    60         self.servicename = servicename
       
    61         self.ip_addr = ip_addr
       
    62         self.port = port
       
    63         self.servicepublisher = None
       
    64         self.piper, self.pipew = None, None
       
    65 
       
    66     def _to_be_published(self):
       
    67         return self.servicename is not None and \
       
    68                self.ip_addr not in ["", "localhost", "127.0.0.1"]
       
    69 
       
    70     def PrintServerInfo(self):
       
    71         print(_("Pyro port :"), self.port)
       
    72 
       
    73         if self._to_be_published():
       
    74             print(_("Publishing service on local network"))
       
    75 
       
    76         if sys.stdout:
       
    77             sys.stdout.flush()
       
    78 
       
    79     def PyroLoop(self, when_ready):
       
    80         if self._to_be_published():
       
    81             self.Publish()
       
    82 
       
    83         while self.continueloop:
       
    84             self.daemon = Pyro5.server.Daemon(host=self.ip_addr, port=self.port)
       
    85 
       
    86             self.daemon.register(PLCObjectPyroAdapter(runtime.GetPLCObjectSingleton()), "PLCObject")
       
    87 
       
    88             when_ready()
       
    89 
       
    90             self.daemon.requestLoop()
       
    91 
       
    92         self.Unpublish()
       
    93 
       
    94     def Restart(self):
       
    95         self.daemon.shutdown(True)
       
    96 
       
    97     def Quit(self):
       
    98         self.continueloop = False
       
    99         self.daemon.shutdown()
       
   100         if not sys.platform.startswith('win'):
       
   101             if self.pipew is not None:
       
   102                 os.write(self.pipew, "goodbye")
       
   103 
       
   104     def Publish(self):
       
   105         self.servicepublisher = ServicePublisher("PYRO")
       
   106         self.servicepublisher.RegisterService(self.servicename,
       
   107                                               self.ip_addr, self.port)
       
   108 
       
   109     def Unpublish(self):
       
   110         if self.servicepublisher is not None:
       
   111             self.servicepublisher.UnRegisterService()
       
   112             self.servicepublisher = None