In summary, the exact same code:
-
populates
opcFolderCompareRowscorrectly and builds a non‑empty Dataset when run in the Script Console, and -
writes successfully to the Dataset Memory tag
[default]tgpna/OPC_Folder_Comparisionthere,
but in Gateway Timer / Tag Change scripts:
-
ICCP.DataValidation.compareFolder(...)appears to fail or return nothing soopcFolderCompareRowsis empty or only contains the"ERROR"fallback rows, and -
the Dataset written to the tag is therefore empty or just error rows, and the tag value does not change.
Function is as follows. It used OOPC browse
”” # locate 'To QSE' and From QSE folder on a server
def _findFolderNodeId(opcServer, targetName):
"""
Search the whole namespace starting at root for a folder (or object)
whose display name matches targetName.
Returns its nodeId or "" if not found.
"""
stack = [""] # start at root nodeId
while stack:
nid = stack.pop()
children = system.opc.browseServer(opcServer, nid)
for ch in children:
name = ch.getDisplayName()
childId = ch.getServerNodeId().getNodeId()
etype = str(ch.getElementType()).lower()
if name == targetName:
return childId
# keep walking through Folder/Object nodes
if "folder" in etype or "object" in etype:
stack.append(childId)
return "" and another code is
import system
def compareFolder(serverA, serverB, folderName):
"""
Compare tag counts under a given folder (e.g. 'To QSE' or 'From QSE')
on two OPC UA servers. Continues even if one server is down.
"""
# Result structure returned to the caller (screen / other script)
result = {
"ok": False, # set True only if comparison completed
"serverA": serverA, # echo server names for display/logging
"serverB": serverB,
"folder": folderName, # which folder was compared
"stateA": None, # OPC connection state for serverA
"stateB": None, # OPC connection state for serverB
"countA": 0, # tag count on serverA under folderName
"countB": 0, # tag count on serverB under folderName
"diff": 0, # absolute difference between counts
"sameCount": False, # True if counts are equal
"error": None # error message text, if any
}
# Safety check: servers exist
servers = system.opc.getServers()
if serverA not in servers or serverB not in servers:
result\["error"\] = "One or both OPC servers are not configured."
return result
# Get connection states (no early return)
stateA = system.opc.getServerState(serverA)
stateB = system.opc.getServerState(serverB)
result\["stateA"\] = stateA
result\["stateB"\] = stateB
# Log connection warnings but continue
if stateA != "CONNECTED":
result\["error"\] = "ServerA (%s) not CONNECTED: %s" % (serverA, stateA)
if stateB != "CONNECTED":
msg = "ServerB (%s) not CONNECTED: %s" % (serverB, stateB)
result\["error"\] = (result\["error"\] + " " + msg) if result\["error"\] else msg
# Main comparison (tolerant per-server)
nodeA = \_findFolderNodeId(serverA, folderName)
nodeB = \_findFolderNodeId(serverB, folderName)
# Note missing folders but continue counting
if not nodeA:
msg = "Could not find '%s' on serverA (%s)." % (folderName, serverA)
result\["error"\] = (result\["error"\] + " " + msg) if result\["error"\] else msg
if not nodeB:
msg = "Could not find '%s' on serverB (%s)." % (folderName, serverB)
result\["error"\] = (result\["error"\] + " " + msg) if result\["error"\] else msg
# Count tags under the folder on serverA, catching any browse errors.
if nodeA:
try:
countA = \_countVariables(serverA, nodeA)
except Exception, e:
msg = "Browse error on serverA (%s): %s" % (serverA, str(e))
result\["error"\] = (result\["error"\] + " " + msg) if result\["error"\] else msg
countA = 0
else:
countA = 0
# Same for serverB.
if nodeB:
try:
countB = \_countVariables(serverB, nodeB)
except Exception, e:
msg = "Browse error on serverB (%s): %s" % (serverB, str(e))
result\["error"\] = (result\["error"\] + " " + msg) if result\["error"\] else msg
countB = 0
else:
countB = 0
# Store counts safely as integers
result\["countA"\] = int(countA or 0)
result\["countB"\] = int(countB or 0)
# Calculate difference and equality flag
result\["diff"\] = abs(result\["countA"\] - result\["countB"\])
result\["sameCount"\] = (result\["diff"\] == 0)
# Always mark as completed
result\["ok"\] = True
return result. "“
Looking for guidance on what could cause this difference between console and gateway/tag‑event scope (project library scope, permissions, threading, or something else) and how to correctly call the ICCP library and write the Dataset tag from a Gateway Timer or Tag Change script.
