--- a/Beremiz_service.py Wed May 10 17:02:05 2023 +0200
+++ b/Beremiz_service.py Fri May 12 18:09:55 2023 +0200
@@ -31,7 +31,7 @@
-from threading import Thread, Semaphore, Lock, currentThread
+from threading import Thread, Semaphore, Lock, current_thread from functools import partial
@@ -208,19 +208,7 @@
- default_locale = locale.getdefaultlocale()[1]
- # sys.stdout.encoding = default_locale
- # if Beremiz_service is started from Beremiz IDE
- # sys.stdout.encoding is None (that means 'ascii' encoding').
- # And unicode string returned by wx.GetTranslation() are
- # automatically converted to 'ascii' string.
- def unicode_translation(message):
- return wx.GetTranslation(message).encode(default_locale)
- builtins.__dict__['_'] = unicode_translation
- # builtins.__dict__['_'] = wx.GetTranslation
+ builtins.__dict__['_'] = wx.GetTranslation # Life is hard... have a candy.
@@ -371,7 +359,7 @@
_servicename = self.pyroserver.servicename
_servicename = '' if _servicename is None else _servicename
dlg = ParamsEntryDialog(None, _("Enter a name "), defaultValue=_servicename)
- dlg.SetTests([(lambda name: len(name) is not 0, _("Name must not be null!"))])
+ dlg.SetTests([(lambda name: len(name) != 0, _("Name must not be null!"))]) if dlg.ShowModal() == wx.ID_OK:
self.pyroserver.servicename = dlg.GetValue()
self.pyroserver.Restart()
@@ -448,10 +436,10 @@
obj.res = default_evaluator(tocall, *args, **kwargs)
- main_thread_id = currentThread().ident
+ main_thread_id = current_thread().ident def evaluator(tocall, *args, **kwargs):
# To prevent deadlocks, check if current thread is not one already main
- current_id = currentThread().ident
+ current_id = current_thread().ident if main_thread_id != current_id:
o = type('', (object,), dict(call=(tocall, args, kwargs), res=None))
--- a/runtime/NevowServer.py Wed May 10 17:02:05 2023 +0200
+++ b/runtime/NevowServer.py Fri May 12 18:09:55 2023 +0200
@@ -29,7 +29,7 @@
import platform as platform_module
-from zope.interface import implements
+from zope.interface import implementer from nevow import appserver, inevow, tags, loaders, athena, url, rend
from nevow.page import renderer
from nevow.static import File
@@ -44,7 +44,7 @@
PAGE_TITLE = 'Beremiz Runtime Web Interface'
-xhtml_header = '''<?xml version="1.0" encoding="utf-8"?>
+xhtml_header = b'''<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
@@ -248,6 +248,7 @@
extensions_settings_od = collections.OrderedDict()
class SettingsPage(rend.Page):
@@ -255,8 +256,6 @@
# This makes webform_css url answer some default CSS
child_webform_css = webform.defaultCSS
child_webinterface_css = File(paths.AbsNeighbourFile(__file__, 'webinterface.css'), 'text/css')
def __getattr__(self, name):
global extensions_settings_od
--- a/runtime/PyroServer.py Wed May 10 17:02:05 2023 +0200
+++ b/runtime/PyroServer.py Fri May 12 18:09:55 2023 +0200
@@ -14,11 +14,42 @@
-import Pyro.core as pyro
from runtime.ServicePublisher import ServicePublisher
+def make_pyro_exposed_stub(method_name): + stub = lambda self, *args, **kwargs: \ + getattr(self.plc_object_instance, method_name)(self, *args, **kwargs) + stub.__name__ = method_name + Pyro5.server.expose(stub) +class PLCObjectPyroAdapter(type("PLCObjectPyroStubs", (), { + name: make_pyro_exposed_stub(name) for name in [ + "SetTraceVariablesList", + def __init__(self, plc_object_instance): + self.plc_object_instance = plc_object_instance class PyroServer(object):
def __init__(self, servicename, ip_addr, port):
@@ -47,33 +78,14 @@
- Pyro.config.PYRO_MULTITHREADED = 0
- self.daemon = pyro.Daemon(host=self.ip_addr, port=self.port)
+ self.daemon = Pyro5.server.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")
+ self.daemon.register(PLCObjectPyroAdapter(runtime.GetPLCObjectSingleton()), "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() - self.daemon.requestLoop(others=others, callback=lambda x: None)
- self.piper, self.pipew = None, None
- if hasattr(self, 'sock'):
- self.daemon.sock.close()
@@ -81,8 +93,7 @@
self.continueloop = False
- self.daemon.shutdown(True)
- self.daemon.closedown()
if not sys.platform.startswith('win'):
if self.pipew is not None:
os.write(self.pipew, "goodbye")