OPC-HDA Scripting

I’m struggling a bit here with a disconnect between documentation and real life…

I’m trying to read raw values from an OPC-HDA historical source using scripting so I can translate the values into an external SQL table

I’ve managed to system.opchda,readRaw on a single tag and gotten a ReadResults list back which looks like:

[[value size=1, quality=Good, datatype=null]]

How do I get to the actual value?

qualifiedValue = ReadResults[0]

Gives me

[value size=1, quality=Good, datatype=null]

And then I guessed that qualifiedValue.getValue() would return the value but it errors out with:

AttributeError: ‘com.inductiveautomation.opccom.hda.ReadResult’ object has no attribute ‘value’

Ah, qualifiedValue.getValues()

Anyone got any documentation on this?

python’s dir() and my inspect.introspect() functions are your best friends in these cases. But note that the docs for readRaw() don’t say that what you think is a QV is actually a QV. The docs imply you need one more level of dereferencing, though they aren’t very clear.

Yeah I wasn’t even reverse engineering - just poking about and seeing what might work. Not ideal but I managed to get it going.

OPC-HDA is a bit obscure but the docs really need a tidy up - lots of outright wrong information in that section and, like you say, implying but not telling

Thought I’d document an example to help the next guy

Gateway Timer Script

OPCHDA_Server = system.opchda.getServers()[0]
Ignition_System_Name = system.tag.read('[System]Gateway/SystemName').value
OPCHDA_Root = 'Sites'
path = 'histprov:' + OPCHDA_Server + ':/drv:' + Ignition_System_Name + ':default/' + OPCHDA_Root
boundingValues = False
startDate = system.date.now()
endDate = system.date.addDays(startDate,-1)
maxValues = 0 #0 means all the values
CheckOPCHDA.browse(CS_Server, path, boundingValues, startDate, endDate, maxValues)

Project Script

Scripting > Project Library > CheckOPCHDA

def browse(OPCHDA_Server, path, boundingValues, startDate, endDate, maxValues):
    logger = system.util.getLogger("myLogger")
 	Logging = False
 	for result in system.tag.browseHistoricalTags(path).getResults():
 		#List of historical tags
 		result_path = str(result.getPath())
 		if result_path.endswith('.Voltage') :
 			itemId = result_path.split('/tag:')[1]		
 			itemIds = [itemId]
 			SiteName = itemIds[0].split('.')[2]
 			Measurement = '.'
 			Measurement = Measurement.join(itemIds[0].split('.')[3:])
 			ReadResults = system.opchda.readRaw(OPCHDA_Server, itemIds, startDate, endDate, maxValues, boundingValues)
 			for qualifiedValues in ReadResults:
 				for qualifiedValue in qualifiedValues.getValues():
 					if Logging:				
 						logger.info( SiteName + ', ' + Measurement + ', ' + str(qualifiedValue.getValue()) + ', ' + str(qualifiedValue.getTimestamp()))
 		if result.hasChildren():
 			browse(OPCHDA_Server, result.getPath(), boundingValues, startDate, endDate, maxValues)

So this will periodically drill through all the HDA tags in the OPCHDA server and get the values for any tag that ends with “.Voltage” for the last 24 hours.