# HG changeset patch # User Edouard Tisserant # Date 1533558643 -7200 # Node ID fe3394697b02726434706fe4274aed051606395b # Parent 42566291b9bce249c3e83ba4468d1cbf03e7b851# Parent addb6eff8d94d84e70607212f059bb5580d538ba merged diff -r 42566291b9bc -r fe3394697b02 Beremiz_service.py --- a/Beremiz_service.py Mon Aug 06 13:14:50 2018 +0200 +++ b/Beremiz_service.py Mon Aug 06 14:30:43 2018 +0200 @@ -45,17 +45,17 @@ print(""" Usage of Beremiz PLC execution service :\n %s {[-n servicename] [-i IP] [-p port] [-x enabletaskbar] [-a autostart]|-h|--help} working_dir - -n - zeroconf service name (default:disabled) - -i - IP address of interface to bind to (default:localhost) - -p - port number default:3000 - -h - print this help text and quit - -a - autostart PLC (0:disable 1:enable) (default:0) - -x - enable/disable wxTaskbarIcon (0:disable 1:enable) (default:1) - -t - enable/disable Twisted web interface (0:disable 1:enable) (default:1) - -w - web server port or "off" to disable web server (default:8009) - -c - WAMP client default config file (default:wampconf.json) - -s - WAMP client secret, given as a file - -e - python extension (absolute path .py) + -n zeroconf service name (default:disabled) + -i IP address of interface to bind to (default:localhost) + -p port number default:3000 + -h print this help text and quit + -a autostart PLC (0:disable 1:enable) (default:0) + -x enable/disable wxTaskbarIcon (0:disable 1:enable) (default:1) + -t enable/disable Twisted web interface (0:disable 1:enable) (default:1) + -w web server port or "off" to disable web server (default:8009) + -c WAMP client config file (can be overriden by wampconf.json in project) + -s WAMP client secret, given as a file (can be overriden by wamp.secret in project) + -e python extension (absolute path .py) working_dir - directory where are stored PLC files """ % sys.argv[0]) @@ -571,29 +571,23 @@ installThreadExcepthook() +havewamp = False if havetwisted: if webport is not None: try: import runtime.NevowServer as NS # pylint: disable=ungrouped-imports - except Exception, e: - print(_("Nevow/Athena import failed :"), e) + except Exception: + LogMessageAndException(_("Nevow/Athena import failed :")) webport = None NS.WorkingDir = WorkingDir - # Find pre-existing project WAMP config file - _wampconf = os.path.join(WorkingDir, "wampconf.json") - - # If project's WAMP config file exits, override default (-c) - if os.path.exists(_wampconf): - wampconf = _wampconf - - if wampconf is not None: - try: - import runtime.WampClient as WC # pylint: disable=ungrouped-imports - except Exception, e: - print(_("WAMP import failed :"), e) - wampconf = None + try: + import runtime.WampClient as WC # pylint: disable=ungrouped-imports + WC.WorkingDir = WorkingDir + havewamp = True + except Exception: + LogMessageAndException(_("WAMP import failed :")) # Load extensions for extention_file, extension_folder in extensions: @@ -605,22 +599,16 @@ try: website = NS.RegisterWebsite(webport) pyruntimevars["website"] = website + NS.SetServer(pyroserver) statuschange.append(NS.website_statuslistener_factory(website)) except Exception: LogMessageAndException(_("Nevow Web service failed. ")) - if wampconf is not None: + if havewamp: try: - _wampconf = WC.LoadWampClientConf(wampconf) - if _wampconf: - if _wampconf["url"]: # TODO : test more ? - WC.RegisterWampClient(wampconf, wampsecret) - pyruntimevars["wampsession"] = WC.GetSession - WC.SetServer(pyroserver) - else: - raise Exception(_("WAMP config is incomplete.")) - else: - raise Exception(_("WAMP config is missing.")) + WC.SetServer(pyroserver) + WC.RegisterWampClient(wampconf, wampsecret) + WC.RegisterWebSettings(NS) except Exception: LogMessageAndException(_("WAMP client startup failed. ")) diff -r 42566291b9bc -r fe3394697b02 ProjectController.py --- a/ProjectController.py Mon Aug 06 13:14:50 2018 +0200 +++ b/ProjectController.py Mon Aug 06 14:30:43 2018 +0200 @@ -1354,6 +1354,31 @@ if self.AppFrame is not None: self.AppFrame.LogViewer.SetLogCounters(log_count) + DefaultMethods = { + "_Run": False, + "_Stop": False, + "_Transfer": False, + "_Connect": True, + "_Disconnect": False + } + + MethodsFromStatus = { + "Started": {"_Stop": True, + "_Transfer": True, + "_Connect": False, + "_Disconnect": True}, + "Stopped": {"_Run": True, + "_Transfer": True, + "_Connect": False, + "_Disconnect": True}, + "Empty": {"_Transfer": True, + "_Connect": False, + "_Disconnect": True}, + "Broken": {"_Connect": False, + "_Disconnect": True}, + "Disconnected": {}, + } + def UpdateMethodsFromPLCStatus(self): updated = False status = None @@ -1366,21 +1391,11 @@ self._SetConnector(None, False) status = "Disconnected" if self.previous_plcstate != status: - for args in { - "Started": [("_Run", False), - ("_Stop", True)], - "Stopped": [("_Run", True), - ("_Stop", False)], - "Empty": [("_Run", False), - ("_Stop", False)], - "Broken": [], - "Disconnected": [("_Run", False), - ("_Stop", False), - ("_Transfer", False), - ("_Connect", True), - ("_Disconnect", False)], - }.get(status, []): - self.ShowMethod(*args) + allmethods = self.DefaultMethods.copy() + allmethods.update( + self.MethodsFromStatus.get(status, {})) + for method, active in allmethods.items(): + self.ShowMethod(method,active) self.previous_plcstate = status if self.AppFrame is not None: updated = True @@ -1715,10 +1730,6 @@ # Oups. self.logger.write_error(_("Connection failed to %s!\n") % uri) else: - self.ShowMethod("_Connect", False) - self.ShowMethod("_Disconnect", True) - self.ShowMethod("_Transfer", True) - self.CompareLocalAndRemotePLC() # Init with actual PLC status and print it diff -r 42566291b9bc -r fe3394697b02 editors/CodeFileEditor.py --- a/editors/CodeFileEditor.py Mon Aug 06 13:14:50 2018 +0200 +++ b/editors/CodeFileEditor.py Mon Aug 06 14:30:43 2018 +0200 @@ -598,7 +598,30 @@ # Helper for VariablesGrid values # ------------------------------------------------------------------------------- +class AllGridCellEditor(wx.grid.GridCellTextEditor): + def __init__(self, table, row, col): + wx.grid.GridCellTextEditor.__init__(self) + +class ClassGridCellEditor(wx.grid.GridCellChoiceEditor): + def __init__(self, table, row, col): + wx.grid.GridCellChoiceEditor.__init__(self) + self.SetParameters("input,memory,output") + + class VariablesTable(CustomTable): + __defaultColumnType = dict( + [(name, AllGridCellEditor) for name in + ["Name", "Initial", "Description", "OnChange", "Options"]] + + [('Class', ClassGridCellEditor), ('Type', None)]) + + def __init__(self, *args, **kwargs): + my_columns = kwargs.pop("additional_columns") + super(VariablesTable, self).__init__(*args, **kwargs) + self.columnTypes = dict(self.__defaultColumnType) + if my_columns is not None: + for key in my_columns.keys(): + if key in self.columnTypes.keys(): + self.columnTypes[key] = my_columns[key] def GetValue(self, row, col): if row < self.GetNumberRows(): @@ -621,15 +644,9 @@ renderer = None colname = self.GetColLabelValue(col, False) - if colname in ["Name", "Initial", "Description", "OnChange", "Options"]: - editor = wx.grid.GridCellTextEditor() - elif colname == "Class": - editor = wx.grid.GridCellChoiceEditor() - editor.SetParameters("input,memory,output") - elif colname == "Type": - pass - else: - grid.SetReadOnly(row, col, True) + editortype = self.columnTypes.get(colname, None) + if editortype is not None: + editor = editortype(self, row, col) grid.SetCellEditor(row, col, editor) grid.SetCellRenderer(row, col, renderer) @@ -640,7 +657,7 @@ class VariablesEditor(wx.Panel): - def __init__(self, parent, window, controler): + def __init__(self, parent, window, controler, additional_columns=None): wx.Panel.__init__(self, parent, style=wx.TAB_TRAVERSAL) main_sizer = wx.FlexGridSizer(cols=2, hgap=0, rows=1, vgap=4) @@ -680,7 +697,8 @@ "OnChange": "", "Options": "" } - self.Table = VariablesTable(self, [], self.GetVariableTableColnames()) + + self.Table = VariablesTable(self, [], self.GetVariableTableColnames(), additional_columns=additional_columns) self.ColAlignements = [wx.ALIGN_RIGHT] + \ [wx.ALIGN_LEFT]*(len(self.VariablesDefaultValue)) self.ColSizes = [20, 150] + [130]*(len(self.VariablesDefaultValue)-1) @@ -845,6 +863,7 @@ CONFNODEEDITOR_TABS = [] CODE_EDITOR = None + COLUMNS_TYPE = None def _create_CodePanel(self, prnt): self.CodeEditorPanel = wx.SplitterWindow(prnt) @@ -852,7 +871,8 @@ self.VariablesPanel = VariablesEditor(self.CodeEditorPanel, self.ParentWindow, - self.Controler) + self.Controler, + self.COLUMNS_TYPE) if self.CODE_EDITOR is not None: self.CodeEditor = self.CODE_EDITOR(self.CodeEditorPanel, diff -r 42566291b9bc -r fe3394697b02 runtime/NevowServer.py --- a/runtime/NevowServer.py Mon Aug 06 13:14:50 2018 +0200 +++ b/runtime/NevowServer.py Mon Aug 06 14:30:43 2018 +0200 @@ -26,10 +26,19 @@ from __future__ import absolute_import from __future__ import print_function import os -from nevow import appserver, inevow, tags, loaders, athena +import platform +from zope.interface import implements +from nevow import appserver, inevow, tags, loaders, athena, url, rend from nevow.page import renderer +from formless import annotate +from formless import webform +from formless import configurable from twisted.internet import reactor + import util.paths as paths +from runtime.loglevels import LogLevels, LogLevelsDict + +PAGE_TITLE = 'Beremiz Runtime Web Interface' xhtml_header = ''' - + diff -r 42566291b9bc -r fe3394697b02 tests/wamp/project_files/wampconf.json --- a/tests/wamp/project_files/wampconf.json Mon Aug 06 13:14:50 2018 +0200 +++ b/tests/wamp/project_files/wampconf.json Mon Aug 06 14:30:43 2018 +0200 @@ -1,7 +1,10 @@ { - "url":"ws://127.0.0.1:8888", - "realm":"Automation", - "ID":"wamptest", - "password":"1234567890", - "key":"ABCDEFGHIJ" + "ID": "wamptest", + "active": true, + "protocolOptions": { + "autoPingInterval": 60, + "autoPingTimeout": 20 + }, + "realm": "Automation", + "url": "ws://127.0.0.1:8888" }