system.tag.queryTagHistory - merge row by timestamp

Hi @Colby.Clegg,

I query history db with : this.gatewayContext.getTagManager().queryHistory(tagHistoryQueryParams, this.streamingDatasetWriter);

which provide the same function as :system.tag.queryTagHistory

With mode WIDE and ReturnSize(-1) and no interpolation, the result dataset contain one line for each each tag datachange.

I would like to obtain a result dataset with all the raw tags datachanges (no interpolation) merged when the t_stamp is the same.

Is it possible with system.tag.queryTagHistory ???

History DB :

Result :

In this case => only the last Row, but if some datachanges with different timestamp => different row.

Other question : what is the kind of streamingDataset we need to use with

this.gatewayContext.getTagManager().queryHistory

to block until all the data are available ?

I’m curious, if that provides the same function as system.tag.queryTagHistory, why not just use system.tag.queryTagHistory?

Also what is the streamingDatasetWriter?

I’m fairly new to Ignition and have done quite a bit of scripting with tags and tag history, I’m wondering what there is to gain with your method. Sorry I know this doesn’t answer your question

To do this, you would just use a BasicStreamingDataset - although in your case, I think a custom StreamingDatasetWriter would be better - though you could try just overriding write() on BasicStreamingDataset. You'll need to update the dataList and qualityList fields inside the dataset. By overriding write, you could match multiple streamed rows by the timestamp.

@mazeyrat is doing module development - so this is actual Java code directly against the API.

@PGriffith thanks a lot, overrinding seem to be a good solution to merge data.
But what do you mean by
You’ll need to update the dataList and qualityList fields inside the dataset.
I need to create new fields ? I can’t modify the raw data inside the datset ?
write method only append a new row ?

Another question,
if I use a BasicStreamingDataset with TagManager::queryHistory,
when the function return, all the data are available in the dataset or I need to override finish() method to be notified ?

Can I use a StreamingDataset class with TagManager::queryHistory and use readFully() to wait until all the data are available ?

Ok I think I've understood what you mean with the overriding of write method of the BasicStreamingDataset.
I will keep row in a buffer as long as the date is the same and flush the row when the date change.

2 Likes

The default implementation of write in BasicStreamingDataset just adds each data and quality array to fields on the class - dataList and qualityList. If you override write, you can keep the rest of the class working fine as long as you take responsibility for updating those lists yourself. The definitions are pretty simple:

    List<Object[]> dataList;
    List<DataQuality[]> qualityList;
1 Like

Don't forget to flush when you get finish().

1 Like

Yes Indeed. Thanks for the reminder.

If you use the TagHistoryQueryFlags.NO_INTERPOLATION flag, it won’t include any rows that only have interpolated values. Then, you can set your return size to be based on the smallest amount of time you would ever see changing values (typically 1 second).

For example, if you query for 1 day and request 86400 results, but have NO_INTERPOLATION set, what you should get is a row at a 1 second resolution each time any of the values in that row have changed. If you didn’t have the flag, you would of course get a row for each second of the day.

1 Like

Thanks a lot @Colby.Clegg, I 've tested this solution to gather only the raw history datachange with the following settings :

flags = Flags.createFromValue(TagHistoryQueryFlags.BOUNDING_VALUES_YES);
flags.and(TagHistoryQueryFlags.NO_INTERPOLATION);
flags.and(TagHistoryQueryFlags.NO_SCANCLASS_VALIDATION);

with a return size set to :

Math.abs(endDate.getTime() - startDate.getTime())/1000

and I have one row for ecah second.
on this period my history contain only 14 tags value datachange.
is it normal ?

Flag.and() doesn’t mutate the object, it returns a new one. So try:
flags = Flags.of(TagHistoryQueryFlags.BOUNDING_VALUES_YES, TagHistoryQueryFlags.NO_INTERPOLATION, TagHistoryQueryFlags.NO_SCANCLASS_VALIDATION);

1 Like

Perfect. It return now exactly what's I needed ! :clap: :clap: :clap:

1 Like