andrej@1511: #!/usr/bin/env python laurent@371: # -*- coding: utf-8 -*- laurent@371: andrej@1511: # This file is part of Beremiz, a Integrated Development Environment for andrej@1511: # programming IEC 61131-3 automates supporting plcopen standard and CanFestival. andrej@1511: # andrej@1511: # Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD andrej@1511: # andrej@1511: # See COPYING file for copyrights details. andrej@1511: # andrej@1511: # This program is free software; you can redistribute it and/or andrej@1511: # modify it under the terms of the GNU General Public License andrej@1511: # as published by the Free Software Foundation; either version 2 andrej@1511: # of the License, or (at your option) any later version. andrej@1511: # andrej@1511: # This program is distributed in the hope that it will be useful, andrej@1511: # but WITHOUT ANY WARRANTY; without even the implied warranty of andrej@1511: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the andrej@1511: # GNU General Public License for more details. andrej@1511: # andrej@1511: # You should have received a copy of the GNU General Public License andrej@1511: # along with this program; if not, write to the Free Software andrej@1511: # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. andrej@1511: andrej@1881: andrej@1881: from __future__ import absolute_import laurent@371: import os andrej@2434: from builtins import str as text laurent@371: andrej@1850: from nevow import tags, loaders Edouard@1919: import simplejson as json # pylint: disable=import-error andrej@1872: import runtime.NevowServer as NS laurent@371: laurent@371: svgfile = '%(svgfile)s' laurent@371: laurent@381: svguiWidgets = {} laurent@381: laurent@381: currentId = 0 andrej@1736: andrej@1736: laurent@381: def getNewId(): laurent@381: global currentId laurent@381: currentId += 1 laurent@381: return currentId laurent@371: andrej@1736: andrej@1831: class SvguiWidget(object): andrej@1730: laurent@381: def __init__(self, classname, id, **kwargs): laurent@371: self.classname = classname laurent@381: self.id = id laurent@371: self.attrs = kwargs.copy() laurent@381: self.inputs = {} laurent@381: self.outputs = {} laurent@371: self.inhibit = False laurent@371: self.changed = False laurent@371: laurent@381: def setinput(self, attrname, value): laurent@381: self.inputs[attrname] = value andrej@1730: laurent@381: def getinput(self, attrname, default=None): andrej@1775: if attrname not in self.inputs: laurent@381: self.inputs[attrname] = default laurent@381: return self.inputs[attrname] laurent@371: laurent@381: def setoutput(self, attrname, value): laurent@381: if self.outputs.get(attrname) != value: laurent@381: self.outputs[attrname] = value laurent@381: self.changed = True laurent@381: self.RefreshInterface() andrej@1730: laurent@381: def updateoutputs(self, **kwargs): laurent@371: for attrname, value in kwargs.iteritems(): laurent@381: if self.outputs.get(attrname) != value: laurent@381: self.outputs[attrname] = value laurent@371: self.changed = True laurent@381: self.RefreshInterface() andrej@1730: laurent@381: def RefreshInterface(self): laurent@371: interface = website.getHMI() laurent@381: if isinstance(interface, SVGUI_HMI) and self.changed and not self.inhibit: laurent@371: self.changed = False laurent@381: d = interface.sendData(self) laurent@381: if d is not None: laurent@381: self.inhibit = True laurent@381: d.addCallback(self.InterfaceRefreshed) andrej@1730: laurent@381: def InterfaceRefreshed(self, result): laurent@381: self.inhibit = False laurent@381: if self.changed: laurent@381: self.RefreshInterface() laurent@371: andrej@1736: laurent@381: def get_object_init_state(obj): laurent@371: # Convert objects to a dictionary of their representation laurent@381: attrs = obj.attrs.copy() laurent@381: attrs.update(obj.inputs) andrej@1747: d = { andrej@1747: '__class__': obj.classname, andrej@1747: 'id': obj.id, andrej@1747: 'kwargs': json.dumps(attrs), andrej@1747: } laurent@371: return d laurent@371: andrej@1736: laurent@381: def get_object_current_state(obj): laurent@381: # Convert objects to a dictionary of their representation andrej@1747: d = { andrej@1747: '__class__': obj.classname, andrej@1747: 'id': obj.id, andrej@1747: 'kwargs': json.dumps(obj.outputs), andrej@1747: } laurent@381: return d laurent@371: andrej@1736: laurent@381: class SVGUI_HMI(website.PLCHMI): laurent@371: jsClass = u"LiveSVGPage.LiveSVGWidget" andrej@1730: andrej@1730: docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[ andrej@1878: tags.xml(loaders.xmlfile(os.path.join(NS.WorkingDir, svgfile))), andrej@1878: ]) andrej@1730: laurent@381: def HMIinitialisation(self): laurent@381: gadgets = [] laurent@381: for gadget in svguiWidgets.values(): andrej@2434: gadgets.append(text(json.dumps(gadget, default=get_object_init_state, indent=2), 'ascii')) laurent@381: d = self.callRemote('init', gadgets) laurent@381: d.addCallback(self.HMIinitialised) andrej@1730: andrej@1740: def sendData(self, data): laurent@381: if self.initialised: andrej@2434: return self.callRemote('receiveData', text(json.dumps(data, default=get_object_current_state, indent=2), 'ascii')) laurent@381: return None andrej@1730: laurent@381: def setattr(self, id, attrname, value): laurent@381: svguiWidgets[id].setinput(attrname, value) laurent@371: andrej@1736: laurent@381: def createSVGUIControl(*args, **kwargs): laurent@381: id = getNewId() laurent@381: gad = SvguiWidget(args[0], id, **kwargs) laurent@381: svguiWidgets[id] = gad andrej@2434: gadget = [text(json.dumps(gad, default=get_object_init_state, indent=2), 'ascii')] laurent@381: interface = website.getHMI() laurent@381: if isinstance(interface, SVGUI_HMI) and interface.initialised: laurent@381: interface.callRemote('init', gadget) laurent@381: return id laurent@371: andrej@1736: laurent@381: def setAttr(id, attrname, value): laurent@381: gad = svguiWidgets.get(id, None) laurent@381: if gad is not None: laurent@381: gad.setoutput(attrname, value) laurent@371: andrej@1736: laurent@381: def updateAttr(id, **kwargs): laurent@381: gad = svguiWidgets.get(id, None) laurent@381: if gad is not None: laurent@381: gad.updateoutput(**kwargs) laurent@371: andrej@1736: laurent@381: def getAttr(id, attrname, default=None): laurent@381: gad = svguiWidgets.get(id, None) laurent@381: if gad is not None: laurent@381: return gad.getinput(attrname, default) laurent@381: return default