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 |
|