31 |
33 |
32 from XSLTransform import XSLTransform |
34 from XSLTransform import XSLTransform |
33 |
35 |
34 ScriptDirectory = paths.AbsDir(__file__) |
36 ScriptDirectory = paths.AbsDir(__file__) |
35 |
37 |
|
38 class HMITreeNode(object): |
|
39 def __init__(self, path, name, nodetype): |
|
40 self.path = path |
|
41 self.name = name |
|
42 self.nodetype = nodetype |
|
43 if nodetype in ["HMI_LABEL", "HMI_ROOT"]: |
|
44 self.children = [] |
|
45 |
|
46 def pprint(self, indent = 0): |
|
47 res = ">"*indent + pformat(self.__dict__, indent = indent, depth = 1) + "\n" |
|
48 if hasattr(self, "children"): |
|
49 res += "\n".join([child.pprint(indent = indent + 1) |
|
50 for child in self.children]) |
|
51 res += "\n" |
|
52 |
|
53 return res |
|
54 |
|
55 def place_node(self, node): |
|
56 best_child = None |
|
57 known_best_match = 0 |
|
58 for child in self.children: |
|
59 in_common = 0 |
|
60 for child_path_item, node_path_item in izip(child.path, node.path): |
|
61 if child_path_item == node_path_item: |
|
62 in_common +=1 |
|
63 else: |
|
64 break |
|
65 if in_common > known_best_match: |
|
66 known_best_match = in_common |
|
67 best_child = child |
|
68 if best_child is not None and best_child.nodetype == "HMI_LABEL": |
|
69 best_child.place_node(node) |
|
70 else: |
|
71 self.children.append(node) |
|
72 |
|
73 |
36 class SVGHMILibrary(POULibrary): |
74 class SVGHMILibrary(POULibrary): |
37 def GetLibraryPath(self): |
75 def GetLibraryPath(self): |
38 return paths.AbsNeighbourFile(__file__, "pous.xml") |
76 return paths.AbsNeighbourFile(__file__, "pous.xml") |
39 |
77 |
40 def Generate_C(self, buildpath, varlist, IECCFLAGS): |
78 def Generate_C(self, buildpath, varlist, IECCFLAGS): |
41 |
79 |
|
80 """ |
|
81 PLC Instance Tree: |
|
82 prog0 |
|
83 +->v1 HMI_INT |
|
84 +->v2 HMI_INT |
|
85 +->fb0 (type mhoo) |
|
86 | +->va HMI_LABEL |
|
87 | +->v3 HMI_INT |
|
88 | +->v4 HMI_INT |
|
89 | |
|
90 +->fb1 (type mhoo) |
|
91 | +->va HMI_LABEL |
|
92 | +->v3 HMI_INT |
|
93 | +->v4 HMI_INT |
|
94 | |
|
95 +->fb2 |
|
96 +->v5 HMI_IN |
|
97 |
|
98 HMI tree: |
|
99 hmi0 |
|
100 +->v1 |
|
101 +->v2 |
|
102 +->fb0_va |
|
103 | +-> v3 |
|
104 | +-> v4 |
|
105 | |
|
106 +->fb1_va |
|
107 | +-> v3 |
|
108 | +-> v4 |
|
109 | |
|
110 +->v5 |
|
111 |
|
112 """ |
|
113 |
42 # Filter known HMI types |
114 # Filter known HMI types |
43 hmi_types_instances = [v for v in varlist if v["derived"] in HMI_TYPES] |
115 hmi_types_instances = [v for v in varlist if v["derived"] in HMI_TYPES] |
44 |
116 # TODO XXX !!! filter intermediate variables added for FBD feedback loop |
45 # TODO deduce HMI tree |
117 |
|
118 hmi_tree_root = HMITreeNode(None, "hmi0", "HMI_ROOT") |
|
119 |
|
120 # TODO add always available variables here ? |
|
121 # - plc status |
|
122 # - current page |
|
123 # - ... |
|
124 |
|
125 # deduce HMI tree from PLC HMI_* instances |
|
126 for v in hmi_types_instances: |
|
127 path = v["IEC_path"].split(".") |
|
128 new_node = HMITreeNode(path, path[-1], v["derived"]) |
|
129 hmi_tree_root.place_node(new_node) |
|
130 |
|
131 print(hmi_tree_root.pprint()) |
46 |
132 |
47 # TODO generate C code to observe/access HMI tree variables |
133 # TODO generate C code to observe/access HMI tree variables |
48 svghmi_c_filepath = paths.AbsNeighbourFile(__file__, "svghmi.c") |
134 svghmi_c_filepath = paths.AbsNeighbourFile(__file__, "svghmi.c") |
49 svghmi_c_file = open(svghmi_c_filepath, 'r') |
135 svghmi_c_file = open(svghmi_c_filepath, 'r') |
50 svghmi_c_code = svghmi_c_file.read() |
136 svghmi_c_code = svghmi_c_file.read() |