1 #!/usr/bin/env python |
|
2 # -*- coding: utf-8 -*- |
|
3 |
|
4 # This file is part of Beremiz, a Integrated Development Environment for |
|
5 # programming IEC 61131-3 automates supporting plcopen standard and CanFestival. |
|
6 # |
|
7 # Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD |
|
8 # |
|
9 # See COPYING file for copyrights details. |
|
10 # |
|
11 # This program is free software; you can redistribute it and/or |
|
12 # modify it under the terms of the GNU General Public License |
|
13 # as published by the Free Software Foundation; either version 2 |
|
14 # of the License, or (at your option) any later version. |
|
15 # |
|
16 # This program is distributed in the hope that it will be useful, |
|
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
19 # GNU General Public License for more details. |
|
20 # |
|
21 # You should have received a copy of the GNU General Public License |
|
22 # along with this program; if not, write to the Free Software |
|
23 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
24 |
|
25 |
|
26 from __future__ import absolute_import |
|
27 import os |
|
28 from builtins import str as text |
|
29 |
|
30 from nevow import tags, loaders |
|
31 import simplejson as json # pylint: disable=import-error |
|
32 import runtime.NevowServer as NS |
|
33 |
|
34 svgfile = '%(svgfile)s' |
|
35 |
|
36 svguiWidgets = {} |
|
37 |
|
38 currentId = 0 |
|
39 |
|
40 |
|
41 def getNewId(): |
|
42 global currentId |
|
43 currentId += 1 |
|
44 return currentId |
|
45 |
|
46 |
|
47 class SvguiWidget(object): |
|
48 |
|
49 def __init__(self, classname, id, **kwargs): |
|
50 self.classname = classname |
|
51 self.id = id |
|
52 self.attrs = kwargs.copy() |
|
53 self.inputs = {} |
|
54 self.outputs = {} |
|
55 self.inhibit = False |
|
56 self.changed = False |
|
57 |
|
58 def setinput(self, attrname, value): |
|
59 self.inputs[attrname] = value |
|
60 |
|
61 def getinput(self, attrname, default=None): |
|
62 if attrname not in self.inputs: |
|
63 self.inputs[attrname] = default |
|
64 return self.inputs[attrname] |
|
65 |
|
66 def setoutput(self, attrname, value): |
|
67 if self.outputs.get(attrname) != value: |
|
68 self.outputs[attrname] = value |
|
69 self.changed = True |
|
70 self.RefreshInterface() |
|
71 |
|
72 def updateoutputs(self, **kwargs): |
|
73 for attrname, value in kwargs.iteritems(): |
|
74 if self.outputs.get(attrname) != value: |
|
75 self.outputs[attrname] = value |
|
76 self.changed = True |
|
77 self.RefreshInterface() |
|
78 |
|
79 def RefreshInterface(self): |
|
80 interface = website.getHMI() |
|
81 if isinstance(interface, SVGUI_HMI) and self.changed and not self.inhibit: |
|
82 self.changed = False |
|
83 d = interface.sendData(self) |
|
84 if d is not None: |
|
85 self.inhibit = True |
|
86 d.addCallback(self.InterfaceRefreshed) |
|
87 |
|
88 def InterfaceRefreshed(self, result): |
|
89 self.inhibit = False |
|
90 if self.changed: |
|
91 self.RefreshInterface() |
|
92 |
|
93 |
|
94 def get_object_init_state(obj): |
|
95 # Convert objects to a dictionary of their representation |
|
96 attrs = obj.attrs.copy() |
|
97 attrs.update(obj.inputs) |
|
98 d = { |
|
99 '__class__': obj.classname, |
|
100 'id': obj.id, |
|
101 'kwargs': json.dumps(attrs), |
|
102 } |
|
103 return d |
|
104 |
|
105 |
|
106 def get_object_current_state(obj): |
|
107 # Convert objects to a dictionary of their representation |
|
108 d = { |
|
109 '__class__': obj.classname, |
|
110 'id': obj.id, |
|
111 'kwargs': json.dumps(obj.outputs), |
|
112 } |
|
113 return d |
|
114 |
|
115 |
|
116 class SVGUI_HMI(website.PLCHMI): |
|
117 jsClass = u"LiveSVGPage.LiveSVGWidget" |
|
118 |
|
119 docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[ |
|
120 tags.xml(loaders.xmlfile(os.path.join(NS.WorkingDir, svgfile))), |
|
121 ]) |
|
122 |
|
123 def HMIinitialisation(self): |
|
124 gadgets = [] |
|
125 for gadget in svguiWidgets.values(): |
|
126 gadgets.append(text(json.dumps(gadget, default=get_object_init_state, indent=2), 'ascii')) |
|
127 d = self.callRemote('init', gadgets) |
|
128 d.addCallback(self.HMIinitialised) |
|
129 |
|
130 def sendData(self, data): |
|
131 if self.initialised: |
|
132 return self.callRemote('receiveData', text(json.dumps(data, default=get_object_current_state, indent=2), 'ascii')) |
|
133 return None |
|
134 |
|
135 def setattr(self, id, attrname, value): |
|
136 svguiWidgets[id].setinput(attrname, value) |
|
137 |
|
138 |
|
139 def createSVGUIControl(*args, **kwargs): |
|
140 id = getNewId() |
|
141 gad = SvguiWidget(args[0], id, **kwargs) |
|
142 svguiWidgets[id] = gad |
|
143 gadget = [text(json.dumps(gad, default=get_object_init_state, indent=2), 'ascii')] |
|
144 interface = website.getHMI() |
|
145 if isinstance(interface, SVGUI_HMI) and interface.initialised: |
|
146 interface.callRemote('init', gadget) |
|
147 return id |
|
148 |
|
149 |
|
150 def setAttr(id, attrname, value): |
|
151 gad = svguiWidgets.get(id, None) |
|
152 if gad is not None: |
|
153 gad.setoutput(attrname, value) |
|
154 |
|
155 |
|
156 def updateAttr(id, **kwargs): |
|
157 gad = svguiWidgets.get(id, None) |
|
158 if gad is not None: |
|
159 gad.updateoutput(**kwargs) |
|
160 |
|
161 |
|
162 def getAttr(id, attrname, default=None): |
|
163 gad = svguiWidgets.get(id, None) |
|
164 if gad is not None: |
|
165 return gad.getinput(attrname, default) |
|
166 return default |
|