34 from XSLTransform import XSLTransform |
35 from XSLTransform import XSLTransform |
35 |
36 |
36 ScriptDirectory = paths.AbsDir(__file__) |
37 ScriptDirectory = paths.AbsDir(__file__) |
37 |
38 |
38 class HMITreeNode(object): |
39 class HMITreeNode(object): |
39 def __init__(self, path, name, nodetype): |
40 def __init__(self, path, name, nodetype, iectype = None, vartype = None): |
40 self.path = path |
41 self.path = path |
41 self.name = name |
42 self.name = name |
42 self.nodetype = nodetype |
43 self.nodetype = nodetype |
|
44 |
|
45 if iectype is not None: |
|
46 self.iectype = iectype |
|
47 self.vartype = vartype |
43 if nodetype in ["HMI_LABEL", "HMI_ROOT"]: |
48 if nodetype in ["HMI_LABEL", "HMI_ROOT"]: |
44 self.children = [] |
49 self.children = [] |
45 |
50 |
46 def pprint(self, indent = 0): |
51 def pprint(self, indent = 0): |
47 res = ">"*indent + pformat(self.__dict__, indent = indent, depth = 1) + "\n" |
52 res = ">"*indent + pformat(self.__dict__, indent = indent, depth = 1) + "\n" |
83 for child_etree in imap(lambda c:c.etree(), self.children): |
88 for child_etree in imap(lambda c:c.etree(), self.children): |
84 res.append(child_etree) |
89 res.append(child_etree) |
85 |
90 |
86 return res |
91 return res |
87 |
92 |
|
93 def traverse(self): |
|
94 yield self |
|
95 if hasattr(self, "children"): |
|
96 for c in self.children: |
|
97 for yoodl in c.traverse(): |
|
98 yield yoodl |
|
99 |
88 # module scope for HMITree root |
100 # module scope for HMITree root |
89 # so that CTN can use HMITree deduced in Library |
101 # so that CTN can use HMITree deduced in Library |
90 # note: this only works because library's Generate_C is |
102 # note: this only works because library's Generate_C is |
91 # systematicaly invoked before CTN's CTNGenerate_C |
103 # systematicaly invoked before CTN's CTNGenerate_C |
92 |
104 |
143 ("plc_status", "HMI_PLC_STATUS"), |
155 ("plc_status", "HMI_PLC_STATUS"), |
144 ("current_page", "HMI_CURRENT_PAGE")]) |
156 ("current_page", "HMI_CURRENT_PAGE")]) |
145 |
157 |
146 # deduce HMI tree from PLC HMI_* instances |
158 # deduce HMI tree from PLC HMI_* instances |
147 for v in hmi_types_instances: |
159 for v in hmi_types_instances: |
148 path = v["IEC_path"].split(".") |
160 path = v["C_path"].split(".") |
149 # ignores variables starting with _TMP_ |
161 # ignores variables starting with _TMP_ |
150 if path[-1].startswith("_TMP_"): |
162 if path[-1].startswith("_TMP_"): |
151 continue |
163 continue |
152 new_node = HMITreeNode(path, path[-1], v["derived"]) |
164 new_node = HMITreeNode(path, path[-1], v["derived"], v["type"], v["vartype"]) |
153 hmi_tree_root.place_node(new_node) |
165 hmi_tree_root.place_node(new_node) |
154 |
166 |
155 print(hmi_tree_root.pprint()) |
167 print(hmi_tree_root.pprint()) |
|
168 |
|
169 variable_decl_array = [] |
|
170 extern_variables_declarations = [] |
|
171 bofs = 0 |
|
172 for node in hmi_tree_root.traverse(): |
|
173 if hasattr(node, "iectype"): |
|
174 sz = DebugTypesSize.get(node.iectype, 0) |
|
175 variable_decl_array += [ |
|
176 "{&(" + ".".join(node.path) + "), " + node.iectype + { |
|
177 "EXT": "_P_ENUM", |
|
178 "IN": "_P_ENUM", |
|
179 "MEM": "_O_ENUM", |
|
180 "OUT": "_O_ENUM", |
|
181 "VAR": "_ENUM" |
|
182 }[node.vartype] + "}"] |
|
183 bofs += sz |
|
184 if len(node.path) == 1: |
|
185 extern_variables_declarations += [ |
|
186 "extern __IEC_" + node.iectype + "_" + |
|
187 "t" if node.vartype is "VAR" else "p" |
|
188 + ".".join(node.path) + ";"] |
|
189 |
|
190 # TODO : filter only requiered external declarations |
|
191 for v in varlist : |
|
192 if v["C_path"].find('.') < 0 and v["vartype"] == "FB" : |
|
193 extern_variables_declarations += [ |
|
194 "extern %(type)s %(C_path)s;" % v] |
|
195 |
|
196 # TODO check if programs need to be declared separately |
|
197 # "programs_declarations": "\n".join(["extern %(type)s %(C_path)s;" % |
|
198 # p for p in self._ProgramList]), |
156 |
199 |
157 # TODO generate C code to observe/access HMI tree variables |
200 # TODO generate C code to observe/access HMI tree variables |
158 svghmi_c_filepath = paths.AbsNeighbourFile(__file__, "svghmi.c") |
201 svghmi_c_filepath = paths.AbsNeighbourFile(__file__, "svghmi.c") |
159 svghmi_c_file = open(svghmi_c_filepath, 'r') |
202 svghmi_c_file = open(svghmi_c_filepath, 'r') |
160 svghmi_c_code = svghmi_c_file.read() |
203 svghmi_c_code = svghmi_c_file.read() |
161 svghmi_c_file.close() |
204 svghmi_c_file.close() |
162 svghmi_c_code = svghmi_c_code % { "hmi_tree": "TODO !!!"} |
205 svghmi_c_code = svghmi_c_code % { |
|
206 "variable_decl_array": ",\n".join(variable_decl_array), |
|
207 "extern_variables_declarations": "\n".join(extern_variables_declarations), |
|
208 "varinit":"", |
|
209 "varret":"", |
|
210 "varpub":"" |
|
211 } |
163 |
212 |
164 gen_svghmi_c_path = os.path.join(buildpath, "svghmi.c") |
213 gen_svghmi_c_path = os.path.join(buildpath, "svghmi.c") |
165 gen_svghmi_c = open(gen_svghmi_c_path, 'w') |
214 gen_svghmi_c = open(gen_svghmi_c_path, 'w') |
166 gen_svghmi_c.write(svghmi_c_code) |
215 gen_svghmi_c.write(svghmi_c_code) |
167 gen_svghmi_c.close() |
216 gen_svghmi_c.close() |
241 when _generate_softPLC have been called |
290 when _generate_softPLC have been called |
242 @param locations: ignored |
291 @param locations: ignored |
243 @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND |
292 @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND |
244 """ |
293 """ |
245 |
294 |
246 # TODO fetch HMI tree from library |
|
247 |
|
248 svgfile = self._getSVGpath() |
295 svgfile = self._getSVGpath() |
249 if os.path.exists(svgfile): |
296 if os.path.exists(svgfile): |
250 |
297 |
251 # TODO : move to __init__ |
298 # TODO : move to __init__ |
252 transform = XSLTransform(os.path.join(ScriptDirectory, "gen_index_xhtml.xslt"), |
299 transform = XSLTransform(os.path.join(ScriptDirectory, "gen_index_xhtml.xslt"), |