Source timestamping in opcua driver

I’m using source timestamping for a driver I wrote and it works fine.

If I change the value of the Node, I get it in the Tag in the Ignition Designer with the good timestamp on the LastChange Property, and then if I use history, it archives the data (I use value fot the “source timestamping” parameter in the history tab of the Tag).

If I only change the timestamp (as the data value didn’t change in my equipement), the tag is not refreshed in the Ignition designer, and then I use history, it does not archives the data.

Is there’s a way to refresh the tag in Ignition even if the value didn’t change ?

Thanks again for your help

Not right now, sorry.

The UA client part of Ignition only subscribes to value and status code changes; not time stamp changes. There is currently no way to change this configuration, but I can take a look at how difficult it would be to expose it as an option in a future version.

Hi Kevin.

Thanks for your answer.

We are very, very interested in this feature in the way that for a lot of french equipement this is a standard for telemetry process.

In energy we have equipements that gives 10 minutes values and we need to have the values in the history as we make calculation on it (average, cumulation, etc…), so we need to have a point each 10 minutes even if the value didn’t change.

We need it too in water treatment, metrology and town heating for public buildings cause we have equipements that store data and we don’t have real time data so we have to insert each data with old timestamps even if the value doesn’t change. We read the equipements once per day and push the datas only in this case.

Just an other question on this last point, if I have to push a big quantity of points of one opcua node, can I change repeatedly the DataValue or is there a function for that (like a bulk insert for a huge insertion in a database) ?

Thanks for your help.

I’m sorry to keep disappointing you here, but you’re going to run into another problem.

There is no ‘bulk insert’ for pushing a large quantity of values to a UA node. You would just repeatedly call setValue() on it. The problem is that the way our UA client and UA subscriptions work is that ONLY the latest value is sent to the client each time the subscription evaluates.

What this means is that even if you set 10 different values in a row in one particular node, only the last value you set gets sent to the client.

The server is only providing and the client is only expecting the current/real-time value, not any past values.

Just to seek clarification,

if a point toggles in the field (0->1->0) and my driver/provider that I am writing receives both changes at the same time but with a slightly different time stamp, will both events make it into the system?

And If yes, what is the issue with entering a bunch of old(er) data all at once? The use case here is the source device can queue changes while the connection is down. When Ignition reconnects, it can get a flood of old data as the source device empties it’s queue.

[quote=“Robert”]Just to seek clarification,

if a point toggles in the field (0->1->0) and my driver/provider that I am writing receives both changes at the same time but with a slightly different time stamp, will both events make it into the system?

And If yes, what is the issue with entering a bunch of old(er) data all at once? The use case here is the source device can queue changes while the connection is down. When Ignition reconnects, it can get a flood of old data as the source device empties it’s queue.[/quote]

If the 0->1->0 happens in succession (like, 1 call after the other in code, etc…) the client will never see the 1 unless you get incredibly lucky, meaning the value goes 1 and the UA subscription evaluates and catches it at 1 before it goes back to 0. But what is likely to happen is that the client just sees the 0 with the updated timestamp.

The subscriptions on the server get created at whatever rate your scan class is.

by client do you mean Vision? I don’t care if the vision client sees it. I do care if the change doesn’t go to history.

Just to be clear, we are creating our own tag provider that will be calling the api to process a change with every change.

[quote=“Robert”]by client do you mean Vision? I don’t care if the vision client sees it. I do care if the change doesn’t go to history.

Just to be clear, we are creating our own tag provider that will be calling the api to process a change with every change.[/quote]

I don’t know if this applies to a tag provider. I’m talking about the UA client, meaning the Ignition Gateway’s connection to the UA server. History would not see the change in the case that a UA driver executed the above scenario.

Does that mean that if I make several calls for updating a ua node in my driver only the last one would be seen by the gateway (and then effectively goes to history) ?

Is there’s a cycle time to respect in order to let the gateway validate the change ?

The cycle time would be whatever rate the subscription is running at.

This stuff is going to change eventually. UA has the ability to send multiple values to the client all at once; we’re just not using it. The reason for this is that the interface SQLTags exposes to the OPC system has no facilities for receiving multiple values for a single tag and having that mean anything other than using the latest value.

I imagine it will change in the 7.7 release.

so to put this a different way, Ignition has no ability to support spontaneous reporting. It will never just sit there until something happens. It always has to poll for data and the event resolution is limited by the poll rate.

When it comes to OPC connections and OPC drivers, yes.

Ah.

What about tags created using the default tag provider? (cause the simple tag provider is too simple :slight_smile: )

With SQLTags, since 7.3, values are evaluated and pushed through as soon as setValue is called, for the current value. History, however, is still on the historical scan class, and doesn’t look at all the values that have come in in the mean time, only the most recent.

As Kevin mentioned, we are going to update the system to better handle data buffers soon. There are probably some things you can do with the module sdk, such as perhaps writing data for a tag directly to the store and forward system. But I’m not sure if this is the route you’re interested in taking.

One note about the original question about storing data that hasn’t changed: If you must store a value every 10 minutes, a transaction group might be better. If you really want to use tag history, wouldn’t the “max age” feature on the history settings work? If your scan class was 10 seconds, your max cycle could be set to 1, and would force it to log each time.

Regards,

Ouch.

So there is the real possibility of losing data here. Our customers will not be happy to hear this.

The big problem this represents for us is with boolean tags. Every change has to be recorded. Can you create a ‘on change’ scan class? ie event driven.

I already tried the transaction group, but in the same way, it seems it doesn’t take the new timestamp if the value didn’t change.
In fact, the tag in Ignition does not change until I change the value of the tag.

I’m trying another way to do it with transaction group but I have another problem.

What I tried, is to update tags with their value and to set another tag in wich I put the timestamp of the equipement. So in this way, I can make the transaction group using the timestamp of the equipement instead of the natural timestamp of the group.

But to do that, I tried to change the DataValue with a Date, with a Calendar, with a String formatted as a Date, with a DateTime and I didn’t succeed…
I used a type DateTime like this :
((DataNode) node).setType(DataType.DateTime);
where DataNode extends the DataVariableNode class
and in the setValue, I tried to cast, to coerce and other things but I have an exception.

Can you just give me the exact type of parameter to pass at the constructor of the DataValue ?

DataValue newValue = new DataValue(new Variant(value), StatusCode.GOOD, UtcTime.fromJavaTime(timeStamp.getTimeInMillis()), new UtcTime());

I should have install the driver tomorrow, so if you have an answer to that It would help :slight_smile:

Thanks.

The DataValue would be constructed something like this:

new DataValue(new Variant(new UtcTime()));