41 |
41 |
42 |
42 |
43 ScriptDirectory = paths.AbsDir(__file__) |
43 ScriptDirectory = paths.AbsDir(__file__) |
44 |
44 |
45 class HMITreeNode(object): |
45 class HMITreeNode(object): |
46 def __init__(self, path, name, nodetype, iectype = None, vartype = None, hmiclass = None): |
46 def __init__(self, path, name, nodetype, iectype = None, vartype = None, cpath = None, hmiclass = None): |
47 self.path = path |
47 self.path = path |
48 self.name = name |
48 self.name = name |
49 self.nodetype = nodetype |
49 self.nodetype = nodetype |
50 self.hmiclass = hmiclass |
50 self.hmiclass = hmiclass |
51 |
51 |
52 if iectype is not None: |
52 if iectype is not None: |
53 self.iectype = iectype |
53 self.iectype = iectype |
54 self.vartype = vartype |
54 self.vartype = vartype |
|
55 self.cpath = cpath |
|
56 |
55 if nodetype in ["HMI_NODE", "HMI_ROOT"]: |
57 if nodetype in ["HMI_NODE", "HMI_ROOT"]: |
56 self.children = [] |
58 self.children = [] |
57 |
59 |
58 def pprint(self, indent = 0): |
60 def pprint(self, indent = 0): |
59 res = ">"*indent + pformat(self.__dict__, indent = indent, depth = 1) + "\n" |
61 res = ">"*indent + pformat(self.__dict__, indent = indent, depth = 1) + "\n" |
131 |
133 |
132 hmi_tree_root = None |
134 hmi_tree_root = None |
133 |
135 |
134 on_hmitree_update = None |
136 on_hmitree_update = None |
135 |
137 |
|
138 SPECIAL_NODES = [("heartbeat", "HMI_INT")] |
|
139 # ("current_page", "HMI_STRING")]) |
|
140 |
136 class SVGHMILibrary(POULibrary): |
141 class SVGHMILibrary(POULibrary): |
137 def GetLibraryPath(self): |
142 def GetLibraryPath(self): |
138 return paths.AbsNeighbourFile(__file__, "pous.xml") |
143 return paths.AbsNeighbourFile(__file__, "pous.xml") |
139 |
144 |
140 def Generate_C(self, buildpath, varlist, IECCFLAGS): |
145 def Generate_C(self, buildpath, varlist, IECCFLAGS): |
141 global hmi_tree_root, on_hmitree_update, hmi_tree_unique_id |
146 global hmi_tree_root, on_hmitree_update |
142 |
147 |
143 """ |
148 """ |
144 PLC Instance Tree: |
149 PLC Instance Tree: |
145 prog0 |
150 prog0 |
146 +->v1 HMI_INT |
151 +->v1 HMI_INT |
177 # Filter known HMI types |
182 # Filter known HMI types |
178 hmi_types_instances = [v for v in varlist if v["derived"] in HMI_TYPES] |
183 hmi_types_instances = [v for v in varlist if v["derived"] in HMI_TYPES] |
179 |
184 |
180 hmi_tree_root = HMITreeNode(None, "/", "HMI_ROOT") |
185 hmi_tree_root = HMITreeNode(None, "/", "HMI_ROOT") |
181 |
186 |
182 # add special nodes |
|
183 map(lambda (n,t): hmi_tree_root.children.append(HMITreeNode(None,n,t)), [ |
|
184 ("plc_status", "HMI_PLC_STATUS"), |
|
185 ("current_page", "HMI_CURRENT_PAGE")]) |
|
186 |
|
187 # deduce HMI tree from PLC HMI_* instances |
187 # deduce HMI tree from PLC HMI_* instances |
188 for v in hmi_types_instances: |
188 for v in hmi_types_instances: |
189 path = v["C_path"].split(".") |
189 path = v["IEC_path"].split(".") |
190 # ignores variables starting with _TMP_ |
190 # ignores variables starting with _TMP_ |
191 if path[-1].startswith("_TMP_"): |
191 if path[-1].startswith("_TMP_"): |
192 continue |
192 continue |
193 derived = v["derived"] |
193 derived = v["derived"] |
194 kwargs={} |
194 kwargs={} |
195 if derived == "HMI_NODE": |
195 if derived == "HMI_NODE": |
|
196 # TODO : make problem if HMI_NODE used in CONFIG or RESOURCE |
196 name = path[-2] |
197 name = path[-2] |
197 kwargs['hmiclass'] = path[-1] |
198 kwargs['hmiclass'] = path[-1] |
198 else: |
199 else: |
199 name = path[-1] |
200 name = path[-1] |
200 new_node = HMITreeNode(path, name, derived, v["type"], v["vartype"], **kwargs) |
201 new_node = HMITreeNode(path, name, derived, v["type"], v["vartype"], v["C_path"], **kwargs) |
201 hmi_tree_root.place_node(new_node) |
202 hmi_tree_root.place_node(new_node) |
202 |
203 |
203 if on_hmitree_update is not None: |
204 if on_hmitree_update is not None: |
204 on_hmitree_update() |
205 on_hmitree_update() |
205 |
206 |
206 variable_decl_array = [] |
207 variable_decl_array = [] |
207 extern_variables_declarations = [] |
208 extern_variables_declarations = [] |
208 buf_index = 0 |
209 buf_index = 0 |
209 item_count = 0 |
210 item_count = 0 |
|
211 found_heartbeat = False |
|
212 |
|
213 # find heartbeat in hmi tree |
|
214 # it is supposed to come first, but some HMI_* intances |
|
215 # in config's globals might shift them |
|
216 hearbeat_IEC_path = ['CONFIG', 'HEARTBEAT'] |
210 for node in hmi_tree_root.traverse(): |
217 for node in hmi_tree_root.traverse(): |
211 if hasattr(node, "iectype") and \ |
218 if node.path == hearbeat_IEC_path: |
212 node.nodetype not in ["HMI_NODE"]: |
219 hmi_tree_hearbeat_index = item_count |
|
220 found_heartbeat = True |
|
221 extern_variables_declarations += [ |
|
222 "#define heartbeat_index "+str(hmi_tree_hearbeat_index) |
|
223 ] |
|
224 break; |
|
225 |
|
226 for node in hmi_tree_root.traverse(): |
|
227 if hasattr(node, "iectype") and node.nodetype != "HMI_NODE": |
213 sz = DebugTypesSize.get(node.iectype, 0) |
228 sz = DebugTypesSize.get(node.iectype, 0) |
214 variable_decl_array += [ |
229 variable_decl_array += [ |
215 "{&(" + ".".join(node.path) + "), " + node.iectype + { |
230 "{&(" + node.cpath + "), " + node.iectype + { |
216 "EXT": "_P_ENUM", |
231 "EXT": "_P_ENUM", |
217 "IN": "_P_ENUM", |
232 "IN": "_P_ENUM", |
218 "MEM": "_O_ENUM", |
233 "MEM": "_O_ENUM", |
219 "OUT": "_O_ENUM", |
234 "OUT": "_O_ENUM", |
220 "VAR": "_ENUM" |
235 "VAR": "_ENUM" |
224 item_count += 1 |
239 item_count += 1 |
225 if len(node.path) == 1: |
240 if len(node.path) == 1: |
226 extern_variables_declarations += [ |
241 extern_variables_declarations += [ |
227 "extern __IEC_" + node.iectype + "_" + |
242 "extern __IEC_" + node.iectype + "_" + |
228 "t" if node.vartype is "VAR" else "p" |
243 "t" if node.vartype is "VAR" else "p" |
229 + ".".join(node.path) + ";"] |
244 + node.cpath + ";"] |
|
245 |
|
246 assert(found_heartbeat) |
230 |
247 |
231 # TODO : filter only requiered external declarations |
248 # TODO : filter only requiered external declarations |
232 for v in varlist : |
249 for v in varlist : |
233 if v["C_path"].find('.') < 0 and v["vartype"] == "FB" : |
250 if v["C_path"].find('.') < 0 : # and v["vartype"] == "FB" : |
234 extern_variables_declarations += [ |
251 extern_variables_declarations += [ |
235 "extern %(type)s %(C_path)s;" % v] |
252 "extern %(type)s %(C_path)s;" % v] |
236 |
253 |
237 # TODO check if programs need to be declared separately |
254 # TODO check if programs need to be declared separately |
238 # "programs_declarations": "\n".join(["extern %(type)s %(C_path)s;" % |
255 # "programs_declarations": "\n".join(["extern %(type)s %(C_path)s;" % |