Analytics function for Last Good Value
We have come across a number of occasions where we want to bring in the last good value of an attribute as an input to an analytics. But there is no way to do this without additional attributes and analytics. It would be convenient if a function existed that brought in the last good value of the attribute. This is particularly useful when your data source is known to send NULL value frequent which translate into No Data or Bad Input. One specific example:
We have a number of analytics that only run if one of our engine is on. But the SCADA system we get run status from flakes out often and PI records it as No Data. When SCADA flakes out, we assume Last Good Value. Meaning if the engine was on before the outage, we consider it on until SCADA returns and tells us otherwise. But if we bring the run status into an analytic, it uses the value No Data and breaks everything. Instead of No Data, we should be able to wrap that attribute in a LGV function that will report On instead of No Data.
Looking for more inputs on how to determine what the last good value is (was). While it’s simple to say a numeric value is good, but what if it’s a non-sensical numeric value like 1000 for temperature? It is also possible to the source system to send out status like NoData. How should that be interpreted? Please provide your inputs.
Steve Boyko commented
I agree with others, this function should behave like the opposite of BadVal(). Under the hood, it should start with the most recent value for the tag and work backward in time, discarding any events that would be "bad" using BadVal() until it finds the first one that isn't "bad" and returns that single value.
I would also agree that it should be the opposite of the badval function. So anything that would trigger badval to be true would be skipped in the LGV function. This would be a great function that I would find useful in several use cases. Thanks.
Christoph Rose commented
I'd also keep this request to a single value. With multiple values we can already use RecordedValues and then FilterData or MapData.
A lot of the time where a LastGoodValue function would be useful for us is in having an Attribute with an Analysis Data Reference that always has a "clean" value. This is currently relatively complicated, as using any of the Find* functions is not possible for that.
Nonsense numeric values can already be found using FindGT and similar. It would be nice to be able to use that function with an Analysis Data Reference, but that is another topic.
I'd expect the "filter" for a LastGoodValue function to use the same logic as using BadVal. So anything that resolves BadVal('attribute') to True should be skipped.
I'd choose to keep this request to a single-value retrieval. I'd envisaged something like PrevGoodVal(tag,timestamp), or if that's not achievable then at least LastGoodVal(tag,timestamp1,timestamp2). When users need a multi-value option we could use this function to build a 'clean' copy of the tag we're trying to analyse, and run a regular multi-value function on it.
Ok, thanks all for the added context and use case.
I do want to point out one thing, if this attribute is used in an analysis and it's interspersed with these error values, and the user has a summary function like TagAvg(), what's the desired behavior? Would you want to skip all the error values?
Perhaps this discussion should be kept to a single value?
Say you want PrevVal(Atr,*) and Atr is the output of an analysis. On the previous evaluation of of Atr it results in 'calc failed' system digital statr.
I would want PrevVal(Atr,*) to have the option to skip this, or any, values that are system digital states and then return the first available numeric value.
For a single-value retrieval then we wouldn't be concerned about nonsense numeric values, and would expect to manage cases like that ourselves elsewhere in the code. For NoData we'd want to treat that as a bad value, and continue looking backward for the last good numeric or digital value. In my view the whole point is trying to establish the last value.
Not clear on the question about summary calculations - the requested function as I understood it was a function to find and return a single value.
@stephen, I just want it to tell me the last entry that isn't a SYSTEM digital state. I'll handle any weird unique data issues.
In the case where multiple historical values are needed, such as a summary (for example, average), what's the desired behavior with respect to last good value?