--- a/svghmi/svghmi.py Fri Nov 24 23:56:38 2023 +0100
+++ b/svghmi/svghmi.py Sat Nov 25 00:18:05 2023 +0100
@@ -44,20 +44,19 @@
# note: this only works because library's Generate_C is
# systematicaly invoked before CTN's CTNGenerate_C
-on_hmitree_update = None
class SVGHMILibrary(POULibrary):
+ maxConnectionsTotal = 0 def GetLibraryPath(self):
return paths.AbsNeighbourFile(__file__, "pous.xml")
def Generate_C(self, buildpath, varlist, IECCFLAGS):
- global hmi_tree_root, on_hmitree_update, maxConnectionsTotal
- maxConnectionsTotal = 0
+ self.maxConnectionsTotal = 0 already_found_watchdog = False
found_SVGHMI_instance = False
@@ -65,7 +64,7 @@
if isinstance(CTNChild, SVGHMI):
found_SVGHMI_instance = True
# collect maximum connection total for all svghmi nodes
- maxConnectionsTotal += CTNChild.GetParamsAttributes("SVGHMI.MaxConnections")["value"]
+ self.maxConnectionsTotal += CTNChild.GetParamsAttributes("SVGHMI.MaxConnections")["value"] if CTNChild.GetParamsAttributes("SVGHMI.EnableWatchdog")["value"]:
@@ -114,14 +113,14 @@
hmi_types_instances = [v for v in varlist if v["derived"] in HMI_TYPES]
+ self.hmi_tree_root = None # take first HMI_NODE (placed as special node), make it root
for i,v in enumerate(hmi_types_instances):
path = v["IEC_path"].split(".")
if derived == "HMI_NODE":
- hmi_tree_root = HMITreeNode(path, "", derived, v["type"], v["vartype"], v["C_path"])
+ self.hmi_tree_root = HMITreeNode(path, "", derived, v["type"], v["vartype"], v["C_path"]) hmi_types_instances.pop(i)
@@ -144,7 +143,7 @@
new_node = HMITreeNode(path, name, derived, v["type"], vartype, v["C_path"], **kwargs)
- placement_result = hmi_tree_root.place_node(new_node)
+ placement_result = self.hmi_tree_root.place_node(new_node) if placement_result is not None:
cause, problematic_node = placement_result
if cause == "Non_Unique":
@@ -171,8 +170,7 @@
self.FatalError("SVGHMI : " + message)
- if on_hmitree_update is not None:
- on_hmitree_update(hmi_tree_root)
+ self.on_hmitree_update() extern_variables_declarations = []
@@ -182,7 +180,7 @@
hearbeat_IEC_path = ['CONFIG', 'HEARTBEAT']
- for node in hmi_tree_root.traverse():
+ for node in self.hmi_tree_root.traverse(): if not found_heartbeat and node.path == hearbeat_IEC_path:
hmi_tree_hearbeat_index = item_count
@@ -232,8 +230,8 @@
"item_count": item_count,
"var_access_code": targets.GetCode("var_access.c"),
"PLC_ticktime": self.GetCTR().GetTicktime(),
- "hmi_hash_ints": ",".join(map(str,hmi_tree_root.hash())),
- "max_connections": maxConnectionsTotal
+ "hmi_hash_ints": ",".join(map(str,self.hmi_tree_root.hash())), + "max_connections": self.maxConnectionsTotal gen_svghmi_c_path = os.path.join(buildpath, "svghmi.c")
@@ -254,7 +252,7 @@
# Backup HMI Tree in XML form so that it can be loaded without building
hmitree_backup_path = os.path.join(buildpath, "hmitree.xml")
hmitree_backup_file = open(hmitree_backup_path, 'wb')
- hmitree_backup_file.write(etree.tostring(hmi_tree_root.etree()))
+ hmitree_backup_file.write(etree.tostring(self.hmi_tree_root.etree())) hmitree_backup_file.close()
return ((["svghmi"], [(gen_svghmi_c_path, IECCFLAGS)], True), "",
@@ -268,15 +266,18 @@
return [(name, iec_type, "") for name, iec_type in SPECIAL_NODES]
+ def on_hmitree_update(self): + for uiref in self.registered_uis[:]: + self.registered_uis.remove(uiref) + obj.HMITreeUpdate(self.hmi_tree_root) -def Register_SVGHMI_UI_for_HMI_tree_updates(ref):
- global on_hmitree_update
- def HMITreeUpdate(_hmi_tree_root):
- obj.HMITreeUpdate(_hmi_tree_root)
- on_hmitree_update = HMITreeUpdate
+ def Register_SVGHMI_UI_for_HMI_tree_updates(self, uiref): + self.registered_uis.append(uiref) class SVGHMIEditor(ConfTreeNodeEditor):
@@ -288,18 +289,19 @@
self.Controler = controler
def CreateSVGHMI_UI(self, parent):
+ ctroot = self.Controler.GetCTRoot() + svghmilib = ctroot.Libraries["SVGHMI"] - if hmi_tree_root is None:
- buildpath = self.Controler.GetCTRoot()._getBuildPath()
+ if svghmilib.hmi_tree_root is None: + buildpath = ctroot._getBuildPath() hmitree_backup_path = os.path.join(buildpath, "hmitree.xml")
if os.path.exists(hmitree_backup_path):
hmitree_backup_file = open(hmitree_backup_path, 'rb')
- hmi_tree_root = HMITreeNode.from_etree(etree.parse(hmitree_backup_file).getroot())
+ svghmilib.hmi_tree_root = HMITreeNode.from_etree(etree.parse(hmitree_backup_file).getroot()) - ret = SVGHMI_UI(parent, self.Controler, Register_SVGHMI_UI_for_HMI_tree_updates)
+ ret = SVGHMI_UI(parent, self.Controler, svghmilib.Register_SVGHMI_UI_for_HMI_tree_updates) - on_hmitree_update(hmi_tree_root)
+ svghmilib.on_hmitree_update() @@ -450,9 +452,10 @@
+ ctroot = self.GetCTRoot() + svghmilib = ctroot.Libraries["SVGHMI"] self.ProgressStart("hmitree", "getting HMI tree")
- res = [hmi_tree_root.etree(add_hash=True)]
+ res = [svghmilib.hmi_tree_root.etree(add_hash=True)] self.ProgressEnd("hmitree")
@@ -527,7 +530,10 @@
def CTNGenerate_C(self, buildpath, locations):
+ ctroot = self.GetCTRoot() + svghmilib = ctroot.Libraries["SVGHMI"] + hmi_tree_root = svghmilib.hmi_tree_root if hmi_tree_root is None:
self.FatalError("SVGHMI : Library is not selected. Please select it in project config.")
@@ -545,7 +551,7 @@
target_path = os.path.join(build_path, target_fname)
hash_path = os.path.join(build_path, "svghmi_"+location_str+".md5")
- self.GetCTRoot().logger.write("SVGHMI:\n")
+ ctroot.logger.write("SVGHMI:\n") if os.path.exists(svgfile):
@@ -729,7 +735,7 @@
watchdog_initial = self.GetParamsAttributes("SVGHMI.WatchdogInitial")["value"],
watchdog_interval = self.GetParamsAttributes("SVGHMI.WatchdogInterval")["value"],
maxConnections = self.GetParamsAttributes("SVGHMI.MaxConnections")["value"],
- maxConnections_total = maxConnectionsTotal,
+ maxConnections_total = svghmilib.maxConnectionsTotal,