[Perspective] Scripting using DateTimeInput.prop

I have a script in the project library that runs at a set interval on the gateway script. Im looking to use a date input selector component in the script to set a date time. Currently its set to a fixed last 3 hours. i can find any doc about using component property’s in script lang. I need to use the tag value.

Example :

    end =  DateTimeInput.props.value
	start = DateTimeInput_0.props.value
	data = system.tag.queryTagCalculations(paths, calc, start,end)

Current Code :

    end = system.date.now()
	start = system.date.addHours(end,-3)
	data = system.tag.queryTagCalculations(paths, calc, start,end)

Gateway timer scripts don’t have any access to a user interface. Possibly you need a user interface that will place a date-time into a tag, and the timer script can access that tag.

1 Like

You can’t use a component’s properties in a gateway script for a couple of reasons:

  1. If there are no client views active there is no component to read properties from.
  2. If there were two client views active then which would determine the property?

Instead …

  • Create a memory tag with a sensible name that relates to the project.
  • Set its Data Type to DateTime.
  • Create a view with a date picker and bind this to the tag bidirectionally (so that it can both update the tag and can itself be updated if another client changes the tag).

Then you can read the tag value using system.tag.readBlocking(["My/Tag/Path"]).

See Reading and Writing to Tags - Ignition User Manual 8.1 - Ignition Documentation for more.

I set this up but im still getting an error.


    end = system.tag.readBlocking(["[default]AFE1/End"])
	start = system.tag.readBlocking(["[default]AFE1/Start"])
	data = system.tag.queryTagCalculations(paths, calc, start,end)


Traceback (most recent call last):
  File "<TimerScript:AFE_ANDON_MONITOR/AST @1,000ms >", line 1, in <module>
  File "<module:AFE1_AST_Time>", line 27, in AST
	at com.inductiveautomation.ignition.common.TypeUtilities.coerce(TypeUtilities.java:1422)
	at com.inductiveautomation.ignition.common.script.builtin.PyArgumentMap.coerce(PyArgumentMap.java:130)
	at com.inductiveautomation.ignition.common.script.builtin.PyArgumentMap.interpretPyArgs(PyArgumentMap.java:82)
	at com.inductiveautomation.ignition.common.script.builtin.PyArgumentMap.interpretPyArgs(PyArgumentMap.java:40)
	at com.inductiveautomation.ignition.common.script.builtin.AbstractTagUtilities.queryTagCalculations(AbstractTagUtilities.java:643)
	at jdk.internal.reflect.GeneratedMethodAccessor56.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
java.lang.ClassCastException: java.lang.ClassCastException: Cannot coerce value '[[Thu May 26 00:06:00 PDT 2022, Good, Wed May 25 13:46:20 PDT 2022 (1653511580527)]]' into type: class java.util.Date

8.1.3 (b2021030309)
Azul Systems, Inc. 11.0.9

Reading a Tag from a script is accomplished with the system.tag.readBlocking() function, which requires the Tag path you wish to read from. This function returns a ‘Qualified Value’; this object is more than just the value. A Qualified Value is the Tag value that has three attributes; Value, Quality, and TimeStamp.


so it should be something like.

end = system.tag.readBlocking(["[default]AFE1/End"]).getValue()

Add a [0] in there. The function returns a list of Qualified Values.

Ok not sure if this is correct … the attribute is not found. Is there somthing i need to import for this function?

end = system.tag.readBlocking(["[default]AFE1/End"]).getValue([0])
end = system.tag.readBlocking(["[default]AFE1/End"])[0].getValue()

Since readBlocking takes a list, and returns a list, consider using one call to get both QVs. Then apply the .value where you use them.

Something like this:

startQV, endQV = system.tag.readBlocking(["[default]AFE1/Start", "[default]AFE1/End"])
data = system.tag.queryTagCalculations(paths, calc, startQV.value, endQV.value)

The first line use python’s tuple packing/unpacking syntax to assign elements of a list to individual variables. The last line uses jython’s automatic recognition of NetBeans getter methods as properties. This is more efficient that calling the .getValue() method itself.


Yes thank you this makes more since . i have yet to need to structure my scripts this way haha . thanks should make it way easier now i know i can lay it out this way

1 Like

So this changed the Index on me … the dataset is now different . i cant use. I get an error stating index out of bounds.
Code :

system.tag.writeBlocking("[default]AFE1/Assistance Beacons/INDUCTS/AST_IND1_2",str(data.getValueAt(0,1)/60))


java.lang.ArrayIndexOutOfBoundsException: java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0

Full Script:

import system
def AST():	# Build a list of String tag paths
	paths = [
				"[default]AFE1/Assistance Beacons/INDUCTS/LT_AST_IND1",
				"[default]AFE1/Assistance Beacons/INDUCTS/LT_AST_IND2",
				"[default]AFE1/Assistance Beacons/INDUCTS/LT_AST_IND3",
				"[default]AFE1/Assistance Beacons/INDUCTS/LT_AST_IND4",
				"[default]AFE1/Assistance Beacons/INDUCTS/LT_AST_IND5",
				"[default]AFE1/Assistance Beacons/INDUCTS/LT_AST_IND6",
				"[default]AFE1/Assistance Beacons/INDUCTS/LT_AST_IND7",
				"[default]AFE1/Assistance Beacons/INDUCTS/LT_AST_IND8",
				"[default]AFE1/Assistance Beacons/INDUCTS/LT_AST_IND9",
				"[default]AFE1/Assistance Beacons/INDUCTS/LT_AST_IND10"
	# Determine the calculation to use
	calc = ["DurationOn"]
	# Define the date range
	#end = system.date.now()
	#start = system.date.addHours(end,-3)
	startQV,endQV = system.tag.readBlocking(["[default]AFE1/Start", "[default]AFE1/End"])
	data = system.tag.queryTagCalculations(paths, calc, startQV.value, endQV.value)
	#start = system.tag.readBlocking("[AFE1/Start]")[0].value
	# Run the query, returning the results as an Ignition dataset
	#data = system.tag.queryTagCalculations(paths, calc, start,end)
	# From here you would need to do something useful with the data variable. You could extract the values
	#   and write them to a tag, pass them to a dataset property on a component, or any number of other things.
	system.tag.writeBlocking("[default]AFE1/Assistance Beacons/INDUCTS/AST_IND1_2",str(data.getValueAt(0,1)/60))
	system.tag.writeBlocking("[default]AFE1/Assistance Beacons/INDUCTS/AST_IND3_4",str(data.getValueAt(1,1)/60))
	system.tag.writeBlocking("[default]AFE1/Assistance Beacons/INDUCTS/AST_IND5_6",str(data.getValueAt(2,1)/60))
	system.tag.writeBlocking("[default]AFE1/Assistance Beacons/INDUCTS/AST_IND7_8",str(data.getValueAt(3,1)/60))
	system.tag.writeBlocking("[default]AFE1/Assistance Beacons/INDUCTS/AST_IND9_10",str(data.getValueAt(4,1)/60))
	system.tag.writeBlocking("[default]AFE1/Assistance Beacons/INDUCTS/AST_IND11_12",str(data.getValueAt(5,1)/60))
	system.tag.writeBlocking("[default]AFE1/Assistance Beacons/INDUCTS/AST_IND13_14",str(data.getValueAt(6,1)/60))
	system.tag.writeBlocking("[default]AFE1/Assistance Beacons/INDUCTS/AST_IND15_16",str(data.getValueAt(7,1)/60))
	system.tag.writeBlocking("[default]AFE1/Assistance Beacons/INDUCTS/AST_IND17_18",str(data.getValueAt(8,1)/60))
	system.tag.writeBlocking("[default]AFE1/Assistance Beacons/INDUCTS/AST_IND19_20",str(data.getValueAt(9,1)/60))

That means you got a result with no rows. You need to check for that before using data. Consider writing it to a dataset memory tag so you can look at it while debugging.

1 Like

I was just searching for a way to see what is in the dataset.

I also recommend you not use so many .writeBlocking calls. Built a list of the target paths, and a list of the computed values. Then you can call .writeBlocking once. Much more efficient. Something like this:

writePaths = ["[default]AFE1/Assistance Beacons/INDUCTS/AST_IND1_%d" % (2*r+2) for r in range(data.rowCount)]
writeValues = [str(data.getValueAt(r, 1)/60) for r in range(data.rowCount)]
system.tag.writeBlocking(writePaths, writeValues)

yes i haven’t refined it yet

Thank you . for the index out of range i had my start and end time reversed i have data now .

ok can we talk about this part is it regex . I kinda get how it work but say i want to skip by odd numbers . r+2 ya ?? I tried that but still was only placing in the 2 to 5 tag . i ended up just renaming my tags but for future reference.

%d" % (2*r+2)

r starts with zero, then one, continuing while r is less than the value supplied to range(). You want the interval to be by twos, so multiply by two. The first to be two, so add two.