# OPC-HDA Scripting

**URL:** <https://forum.inductiveautomation.com/t/opc-hda-scripting/32921>\
**Category:** Ignition\
**Created:** [March 8, 2020, 9:32pm UTC](https://forum.inductiveautomation.com/t/opc-hda-scripting/32921 "2020-03-08T21:32:45Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![SteveE](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/stevee/32/14460_2.png) [@SteveE](https://forum.inductiveautomation.com/u/SteveE)\
**Post date:** [March 8, 2020, 9:32pm UTC](https://forum.inductiveautomation.com/t/opc-hda-scripting/32921/1 "2020-03-08T21:32:45Z")

</div>

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’

---

<div class="post-metadata">

**Author:** ![SteveE](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/stevee/32/14460_2.png) [@SteveE](https://forum.inductiveautomation.com/u/SteveE)\
**Post date:** [March 8, 2020, 10:27pm UTC](https://forum.inductiveautomation.com/t/opc-hda-scripting/32921/2 "2020-03-08T22:27:51Z")

</div>

Ah, qualifiedValue.getValues()

Anyone got any documentation on this?

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [March 8, 2020, 11:07pm UTC](https://forum.inductiveautomation.com/t/opc-hda-scripting/32921/3 "2020-03-08T23:07:28Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![SteveE](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/stevee/32/14460_2.png) [@SteveE](https://forum.inductiveautomation.com/u/SteveE)\
**Post date:** [March 8, 2020, 11:33pm UTC](https://forum.inductiveautomation.com/t/opc-hda-scripting/32921/4 "2020-03-08T23:33:24Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![SteveE](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/stevee/32/14460_2.png) [@SteveE](https://forum.inductiveautomation.com/u/SteveE)\
**Post date:** [March 11, 2020, 7:37pm UTC](https://forum.inductiveautomation.com/t/opc-hda-scripting/32921/5 "2020-03-11T19:37:36Z")

</div>

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

**Gateway Timer Script**

```auto
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

```auto
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.
