In some cases, the total production of a piece of equipment can be determined by retrieving the time weighted average of the raw instrument PV value, thus providing an integral of the total units produced for the time period.
Flow has a Time Weighted Average retrieval method and with the use of a Filter tag, one can determine total production on one filter condition, such as the equipment's State tag.
But what if your business rule to determine this is a little more complex? For example, what if the equipment is only considered to be in use when it is in a certain state AND when the flow rate exceeds a threshold value?
This is where custom expressions come into play. With a custom expression, you can evaluate complex conditions and re-use Flow retrieval methods, such as the Time Weighted Average retrieval method.
After all, you don't want to rewrite functionality that comes in the box!
Example
Assume that we are monitoring the actual state of a piece of equipment (tag: FL001.State) and the incoming product flow rate (tag: 110-FQ-001.PV).
The business rule is that the equipment is being utilized only if its state is 0 AND the flow rate is greater than 10hl/hr
The total production can be evaluated with the following custom expression:
List<TranslationRow> data = (List<TranslationRow>)Data; List<TranslationRow> dataFiltered = new List<TranslationRow>(); foreach(var row in data) {
TranslationRow rownew = new TranslationRow();
rownew.Timestamp = row.Timestamp; //Only add the value in the equipment is in state 0 and the product flow is greater than 10 hl/h // double? value = ((row.Results[FL001.State].Value == 0) && (row.Results[110-FQ-001.PV].Value > 10))? row.Results[110-FQ-001.PV].Value : 0.0; rownew.Results = new List<Result>(); //Add quality of 192 (Always good) - The minimum quality value of the two tags could also been used // rownew.Results.Add(new Result(value,192)); dataFiltered.Add(rownew); } Aggregations<TranslationRow> aggregations = new Aggregations<TranslationRow>(dataFiltered , input => {return new Flow.DataSource.Utilities.Point ( input.Timestamp, input.Results[0].Value, input.Results[0].Quality); });
return aggregations.Average(PeriodStart, PeriodEnd);
After adding the two tags (FL001.State and 110-FQ-001.PV) as Items to the custom expression, one can write C# code to evaluate and return the utilization of the equipment.
- Flow retrieves all data points (timestamp, value and quality) for each item for the period (e.g. for the hour in an hourly measure) and store these in the Data object.
- In this expression, each row of Data is iterated through, and any rows where FL001.State is 0 AND 110-FQ-001.PV > 10 is added to a list named dataFiltered
- Once the filtered data is in an object of type Aggregations (a Flow object), one can use the built-in aggregation methods. In this case, the Average method is used to return the total production for which the equipment was in the specified condition
Note that Average will always return a double value.
For more information, see the section on Custom Expressions.