--- a/Beremiz_service.py Thu Aug 16 11:22:40 2018 +0200
+++ b/Beremiz_service.py Tue Aug 21 16:11:02 2018 +0200
@@ -31,13 +31,12 @@
from threading import Thread, Semaphore, Lock
-import Pyro.core as pyro
-from runtime import PLCObject, ServicePublisher, MainWorker
+from runtime.PyroServer import Server from runtime.xenomai import TryPreloadXenomai
+from runtime import LogMessageAndException import util.paths as paths
@@ -242,12 +241,11 @@
TBMENU_CHANGE_WD = wx.NewId()
- def __init__(self, pyroserver, level):
+ def __init__(self, pyroserver): wx.TaskBarIcon.__init__(self)
self.pyroserver = pyroserver
self.Bind(wx.EVT_MENU, self.OnTaskBarStartPLC, id=self.TBMENU_START)
@@ -270,15 +268,14 @@
menu.Append(self.TBMENU_START, _("Start PLC"))
menu.Append(self.TBMENU_STOP, _("Stop PLC"))
- menu.Append(self.TBMENU_CHANGE_NAME, _("Change Name"))
- menu.Append(self.TBMENU_CHANGE_INTERFACE, _("Change IP of interface to bind"))
- menu.Append(self.TBMENU_CHANGE_PORT, _("Change Port Number"))
- menu.Append(self.TBMENU_CHANGE_WD, _("Change working directory"))
- menu.Append(self.TBMENU_LIVE_SHELL, _("Launch a live Python shell"))
- menu.Append(self.TBMENU_WXINSPECTOR, _("Launch WX GUI inspector"))
+ menu.Append(self.TBMENU_CHANGE_NAME, _("Change Name")) + menu.Append(self.TBMENU_CHANGE_INTERFACE, _("Change IP of interface to bind")) + menu.Append(self.TBMENU_CHANGE_PORT, _("Change Port Number")) + menu.Append(self.TBMENU_CHANGE_WD, _("Change working directory")) + menu.Append(self.TBMENU_LIVE_SHELL, _("Launch a live Python shell")) + menu.Append(self.TBMENU_WXINSPECTOR, _("Launch WX GUI inspector")) menu.Append(self.TBMENU_QUIT, _("Quit"))
@@ -297,19 +294,10 @@
def OnTaskBarStartPLC(self, evt):
- if self.pyroserver.plcobj is not None:
- plcstatus = self.pyroserver.plcobj.GetPLCstatus()[0]
- if plcstatus is "Stopped":
- self.pyroserver.plcobj.StartPLC()
- print(_("PLC is empty or already started."))
+ runtime.GetPLCObjectSingleton().StartPLC() def OnTaskBarStopPLC(self, evt):
- if self.pyroserver.plcobj is not None:
- if self.pyroserver.plcobj.GetPLCstatus()[0] == "Started":
- Thread(target=self.pyroserver.plcobj.StopPLC).start()
- print(_("PLC is not started."))
+ runtime.GetPLCObjectSingleton().StopPLC() def OnTaskBarChangeInterface(self, evt):
ip_addr = self.pyroserver.ip_addr
@@ -345,10 +333,7 @@
self.pyroserver.Restart()
def _LiveShellLocals(self):
- if self.pyroserver.plcobj is not None:
- return {"locals": self.pyroserver.plcobj.python_runtime_vars}
+ return {"locals": runtime.GetPLCObjectSingleton().python_runtime_vars} def OnTaskBarLiveShell(self, evt):
@@ -391,90 +376,6 @@
res = (None, sys.exc_info())
- def __init__(self, servicename, ip_addr, port,
- statuschange=None, evaluator=default_evaluator,
- self.continueloop = True
- self.servicename = servicename
- self.servicepublisher = None
- self.statuschange = statuschange
- self.evaluator = evaluator
- self.pyruntimevars = pyruntimevars
- self.plcobj = PLCObject(self)
- def _to_be_published(self):
- return self.servicename is not None and \
- self.ip_addr is not None and \
- self.ip_addr != "localhost" and \
- self.ip_addr != "127.0.0.1"
- def PrintServerInfo(self):
- print(_("Pyro port :"), self.port)
- # Beremiz IDE detects LOCAL:// runtime is ready by looking
- # for self.workdir in the daemon's stdout.
- print(_("Current working directory :"), self.workdir)
- if self._to_be_published():
- print(_("Publishing service on local network"))
- def PyroLoop(self, when_ready):
- while self.continueloop:
- 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)
- self.daemon.connect(self.plcobj, "PLCObject")
- if self._to_be_published():
- self.servicepublisher = ServicePublisher.ServicePublisher()
- self.servicepublisher.RegisterService(self.servicename, self.ip_addr, self.port)
- self.daemon.requestLoop()
- self.daemon.sock.close()
- self.continueloop = False
- if self.plcobj is not None:
- self.plcobj.UnLoadPLC()
- if self.plcobj is not None:
- if self.servicepublisher is not None:
- self.servicepublisher.UnRegisterService()
- self.servicepublisher = None
- self.daemon.shutdown(True)
- if self.plcobj.GetPLCstatus()[0] == "Stopped":
- self.plcobj.StatusChange()
with warnings.catch_warnings():
@@ -522,31 +423,11 @@
wx.CallAfter(wx_evaluator, o)
- pyroserver = Server(servicename, given_ip, port,
- statuschange, evaluator, pyruntimevars)
- taskbar_instance = BeremizTaskBarIcon(pyroserver, enablewx)
- pyroserver = Server(servicename, given_ip, port,
- statuschange, pyruntimevars=pyruntimevars)
+ evaluator = default_evaluator
-def LogMessageAndException(msg, exp=None):
- if pyroserver.plcobj is not None:
- pyroserver.plcobj.LogMessage(0, msg + '\n'.join(traceback.format_exception(*exp)))
- traceback.print_exception(*exp)
LogMessageAndException("", exp)
@@ -596,6 +477,15 @@
sys.path.append(extension_folder)
execfile(os.path.join(extension_folder, extention_file), locals())
+runtime.CreatePLCObjectSingleton( + WorkingDir, argv, statuschange, evaluator, pyruntimevars) +pyroserver = Server(servicename, given_ip, port) + taskbar_instance = BeremizTaskBarIcon(pyroserver) @@ -625,6 +515,11 @@
pyroserver.PrintServerInfo()
+# Beremiz IDE detects LOCAL:// runtime is ready by looking +# for self.workdir in the daemon's stdout. +print(_("Current working directory :"), WorkingDir) if havetwisted or havewx:
ui_thread_started = Lock()
ui_thread_started.acquire()
@@ -651,9 +546,15 @@
print("UI thread started successfully.")
- MainWorker.runloop(pyroserver.AutoLoad)
+ runtime.MainWorker.runloop( + runtime.GetPLCObjectSingleton().AutoLoad, autostart) except KeyboardInterrupt:
+plcobj = runtime.GetPLCObjectSingleton() --- a/runtime/PLCObject.py Thu Aug 16 11:22:40 2018 +0200
+++ b/runtime/PLCObject.py Tue Aug 21 16:11:02 2018 +0200
@@ -23,7 +23,6 @@
from __future__ import absolute_import
from threading import Thread, Lock, Semaphore, Event, Condition
@@ -31,10 +30,10 @@
import _ctypes # pylint: disable=wrong-import-order
-import Pyro.core as pyro
from runtime.typemapping import TypeTranslator
from runtime.loglevels import LogLevelsDefault, LogLevelsCount
+from runtime import MainWorker if os.name in ("nt", "ce"):
dlopen = _ctypes.LoadLibrary
@@ -61,107 +60,6 @@
- job to be executed by a worker
- def __init__(self, call, *args, **kwargs):
- self.job = (call, args, kwargs)
- do the job by executing the call, and deal with exceptions
- call, args, kwargs = self.job
- self.result = call(*args, **kwargs)
- self.exc_info = sys.exc_info()
- serialize main thread load/unload of PLC shared objects
- # Only one job at a time
- self.todo = Condition(self.mutex)
- self.done = Condition(self.mutex)
- self.free = Condition(self.mutex)
- def runloop(self, *args, **kwargs):
- meant to be called by worker thread (blocking)
- self._threadID = thread.get_ident()
- job(*args, **kwargs).do()
- while not self._finish:
- if self.job is not None:
- def call(self, *args, **kwargs):
- creates a job, execute it in worker thread, and deliver result.
- if job execution raise exception, re-raise same exception
- meant to be called by non-worker threads, but this is accepted.
- blocking until job done
- _job = job(*args, **kwargs)
- if self._threadID == thread.get_ident() or self._threadID is None:
- # if caller is worker thread execute immediately
- # otherwise notify and wait for completion
- while self.job is not None:
- raise _job.exc_info[0], _job.exc_info[1], _job.exc_info[2]
- unblocks main thread, and terminate execution of runloop()
def func_wrapper(*args, **kwargs):
@@ -169,22 +67,19 @@
-class PLCObject(pyro.ObjBase):
- def __init__(self, server):
- pyro.ObjBase.__init__(self)
- self.evaluator = server.evaluator
- self.argv = [server.workdir] + server.argv # force argv[0] to be "path" to exec...
- self.workingdir = server.workdir
+class PLCObject(object): + def __init__(self, WorkingDir, argv, statuschange, evaluator, pyruntimevars): + self.workingdir = WorkingDir + # FIXME : is argv of any use nowadays ? + self.argv = [WorkingDir] + argv # force argv[0] to be "path" to exec... + self.statuschange = statuschange + self.evaluator = evaluator + self.pyruntimevars = pyruntimevars self.PLClibraryHandle = None
self.PLClibraryLock = Lock()
- self.DummyIteratorLock = None
# Creates fake C funcs proxies
- self.daemon = server.daemon
- self.statuschange = server.statuschange
- self.pyruntimevars = server.pyruntimevars
self._loading_error = None
self.python_runtime_vars = None
@@ -192,7 +87,7 @@
# First task of worker -> no @RunInMain
+ def AutoLoad(self, autostart): # Get the last transfered PLC
self.CurrentPLCFilename = open(
@@ -200,10 +95,15 @@
"r").read().strip() + lib_ext
self.PLCStatus = "Stopped"
self.CurrentPLCFilename = None
if self.statuschange is not None:
for callee in self.statuschange: