runtime/PyroServer.py
author Edouard Tisserant <edouard.tisserant@gmail.com>
Thu, 28 Sep 2023 17:56:03 +0200
changeset 3843 832bcf1b5b60
parent 3808 3e219f00151a
permissions -rw-r--r--
Runtime/win32: no sys.stdout with pythonw.exe
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
     1
#!/usr/bin/env python
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
     2
# -*- coding: utf-8 -*-
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
     3
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
     4
# This file is part of Beremiz runtime.
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
     5
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
     6
# Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
     7
# Copyright (C) 2017: Andrey Skvortsov
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
     8
# Copyright (C) 2018: Edouard TISSERANT
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
     9
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    10
# See COPYING file for copyrights details.
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    11
3750
f62625418bff automated conversion using 2to3-3.9 tool
GP Orcullo <kinsamanka@gmail.com>
parents: 3311
diff changeset
    12
f62625418bff automated conversion using 2to3-3.9 tool
GP Orcullo <kinsamanka@gmail.com>
parents: 3311
diff changeset
    13
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    14
import sys
2603
1ffdc62784cf Add some "pipe to self" trick in Pyro server to accelerate runtime shutdown instead of waiting for arbitrary pyro timeout.
Edouard Tisserant
parents: 2492
diff changeset
    15
import os
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    16
3800
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    17
import Pyro5
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    18
import Pyro5.server
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    19
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    20
import runtime
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    21
from runtime.ServicePublisher import ServicePublisher
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    22
3808
3e219f00151a Use msgpack and remove serpent's bytes workaround
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3805
diff changeset
    23
Pyro5.config.SERIALIZER = "msgpack"
3e219f00151a Use msgpack and remove serpent's bytes workaround
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3805
diff changeset
    24
3800
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    25
def make_pyro_exposed_stub(method_name):
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    26
    stub = lambda self, *args, **kwargs: \
3805
5a66d4be2e49 Pyro5: fix runtime typo + IDE exception handling
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3800
diff changeset
    27
        getattr(self.plc_object_instance, method_name)(*args, **kwargs)
3800
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    28
    stub.__name__ = method_name
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    29
    Pyro5.server.expose(stub)
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    30
    return stub
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    31
    
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    32
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    33
class PLCObjectPyroAdapter(type("PLCObjectPyroStubs", (), {
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    34
    name: make_pyro_exposed_stub(name) for name in [
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    35
        "AppendChunkToBlob",
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    36
        "GetLogMessage",
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    37
        "GetPLCID",
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    38
        "GetPLCstatus",
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    39
        "GetTraceVariables",
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    40
        "MatchMD5", 
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    41
        "NewPLC",
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    42
        "PurgeBlobs",
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    43
        "RemoteExec",
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    44
        "RepairPLC",
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    45
        "ResetLogCount",
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    46
        "SeedBlob",
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    47
        "SetTraceVariablesList",
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    48
        "StartPLC",
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    49
        "StopPLC"
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    50
    ]
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    51
})):
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    52
    def __init__(self, plc_object_instance):
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    53
        self.plc_object_instance = plc_object_instance
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    54
    
2309
d8fb90a2e11f Please pylint and pep8
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2270
diff changeset
    55
2476
1881d0ff5ae2 PyroServer: fixed naming of class, and reorganized methods in order to ease subclassing, in case of customization of service publication on the local network (i.e. zeroconf)
Edouard Tisserant
parents: 2315
diff changeset
    56
class PyroServer(object):
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    57
    def __init__(self, servicename, ip_addr, port):
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    58
        self.continueloop = True
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    59
        self.daemon = None
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    60
        self.servicename = servicename
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    61
        self.ip_addr = ip_addr
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    62
        self.port = port
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    63
        self.servicepublisher = None
2603
1ffdc62784cf Add some "pipe to self" trick in Pyro server to accelerate runtime shutdown instead of waiting for arbitrary pyro timeout.
Edouard Tisserant
parents: 2492
diff changeset
    64
        self.piper, self.pipew = None, None
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    65
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    66
    def _to_be_published(self):
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    67
        return self.servicename is not None and \
2311
bef2b4b87370 Beremiz_service now binds both pyro and nevow ports to interface given with '-i' argument.
Edouard Tisserant
parents: 2270
diff changeset
    68
               self.ip_addr not in ["", "localhost", "127.0.0.1"]
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    69
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    70
    def PrintServerInfo(self):
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    71
        print(_("Pyro port :"), self.port)
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    72
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    73
        if self._to_be_published():
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    74
            print(_("Publishing service on local network"))
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    75
3843
832bcf1b5b60 Runtime/win32: no sys.stdout with pythonw.exe
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3808
diff changeset
    76
        if sys.stdout:
832bcf1b5b60 Runtime/win32: no sys.stdout with pythonw.exe
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3808
diff changeset
    77
            sys.stdout.flush()
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    78
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    79
    def PyroLoop(self, when_ready):
2492
7dd551ac2fa0 check_sources.sh makes me become even less productive
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2476
diff changeset
    80
        if self._to_be_published():
7dd551ac2fa0 check_sources.sh makes me become even less productive
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2476
diff changeset
    81
            self.Publish()
7dd551ac2fa0 check_sources.sh makes me become even less productive
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2476
diff changeset
    82
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    83
        while self.continueloop:
3800
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    84
            self.daemon = Pyro5.server.Daemon(host=self.ip_addr, port=self.port)
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    85
3800
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    86
            self.daemon.register(PLCObjectPyroAdapter(runtime.GetPLCObjectSingleton()), "PLCObject")
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    87
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    88
            when_ready()
3308
358ccd42e052 Runtime: avoids using "pipe to self" bailout unblocking trick on windows, since select() only takes sockets.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2625
diff changeset
    89
3800
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    90
            self.daemon.requestLoop()
3308
358ccd42e052 Runtime: avoids using "pipe to self" bailout unblocking trick on windows, since select() only takes sockets.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2625
diff changeset
    91
2476
1881d0ff5ae2 PyroServer: fixed naming of class, and reorganized methods in order to ease subclassing, in case of customization of service publication on the local network (i.e. zeroconf)
Edouard Tisserant
parents: 2315
diff changeset
    92
        self.Unpublish()
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    93
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    94
    def Restart(self):
2476
1881d0ff5ae2 PyroServer: fixed naming of class, and reorganized methods in order to ease subclassing, in case of customization of service publication on the local network (i.e. zeroconf)
Edouard Tisserant
parents: 2315
diff changeset
    95
        self.daemon.shutdown(True)
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    96
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    97
    def Quit(self):
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    98
        self.continueloop = False
3800
a5a6ee271e65 WIP python3 support for runtime
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3750
diff changeset
    99
        self.daemon.shutdown()
3308
358ccd42e052 Runtime: avoids using "pipe to self" bailout unblocking trick on windows, since select() only takes sockets.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2625
diff changeset
   100
        if not sys.platform.startswith('win'):
358ccd42e052 Runtime: avoids using "pipe to self" bailout unblocking trick on windows, since select() only takes sockets.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2625
diff changeset
   101
            if self.pipew is not None:
358ccd42e052 Runtime: avoids using "pipe to self" bailout unblocking trick on windows, since select() only takes sockets.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2625
diff changeset
   102
                os.write(self.pipew, "goodbye")
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   103
2476
1881d0ff5ae2 PyroServer: fixed naming of class, and reorganized methods in order to ease subclassing, in case of customization of service publication on the local network (i.e. zeroconf)
Edouard Tisserant
parents: 2315
diff changeset
   104
    def Publish(self):
1881d0ff5ae2 PyroServer: fixed naming of class, and reorganized methods in order to ease subclassing, in case of customization of service publication on the local network (i.e. zeroconf)
Edouard Tisserant
parents: 2315
diff changeset
   105
        self.servicepublisher = ServicePublisher("PYRO")
1881d0ff5ae2 PyroServer: fixed naming of class, and reorganized methods in order to ease subclassing, in case of customization of service publication on the local network (i.e. zeroconf)
Edouard Tisserant
parents: 2315
diff changeset
   106
        self.servicepublisher.RegisterService(self.servicename,
1881d0ff5ae2 PyroServer: fixed naming of class, and reorganized methods in order to ease subclassing, in case of customization of service publication on the local network (i.e. zeroconf)
Edouard Tisserant
parents: 2315
diff changeset
   107
                                              self.ip_addr, self.port)
1881d0ff5ae2 PyroServer: fixed naming of class, and reorganized methods in order to ease subclassing, in case of customization of service publication on the local network (i.e. zeroconf)
Edouard Tisserant
parents: 2315
diff changeset
   108
1881d0ff5ae2 PyroServer: fixed naming of class, and reorganized methods in order to ease subclassing, in case of customization of service publication on the local network (i.e. zeroconf)
Edouard Tisserant
parents: 2315
diff changeset
   109
    def Unpublish(self):
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   110
        if self.servicepublisher is not None:
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   111
            self.servicepublisher.UnRegisterService()
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   112
            self.servicepublisher = None