Calculating the average for tags


I have a question how to count the average for several tags. Suppose I have 10 measurement sensors. I would like to count the average from them with the exclusion conditions if, for example, the value is unreasonable or there is no comminkation, i.e. Quality tag is "Bad". So far I only have readings of many devices, but no idea how to make an easy average and exclude bad readings according to the conditions ( too small or too large) so that they are not taken into the average.



You might get a load of recommendations on how to do this with fancy expression tags later. But I would just put a script into the gateway tag events, either timer or tag change. Something like:

avg = 0
cnt = 0
results = system.tag.browse(path = YourPath, filter = {'tagType':'AtomicTag'})
for result in results.getResults():
    if result["value"].quality == "Good" and otherConditions:
        avg = avg + result['value'].value
        cnt += 1
yourAverage = avg / cnt

You could then use system.tag.writeBlocking to write to a tag. Have a play around with it and see what works

def check(qval):
    return qval.good and qval.value >= SOME_MIN_VALUE and qval.value <= SOME_MAX_VALUE
values = [qval.value for qval in system.tag.readBlocking(your_tags_paths) if check(qval)]
return sum(values) / len(values)

Note that the check function is not necessary. You could just replace the call with what's in its return.
I did it that way to clearly separate what needs to be changed and what doesn't.

1 Like

You could do some basic checking within expression tags too. Probably doable if you have one instance of 10 tags, but might get a bit unwieldy or inefficient if you have a lot more to do this with.


	if({[.]Tag 1} >= {[.]Min} && {[.]Tag 1} <= {[.]Max}, {[.]Tag 1}, 0)
	+ if({[.]Tag 2} >= {[.]Min} && {[.]Tag 2} <= {[.]Max}, {[.]Tag 2}, 0)
	+ if({[.]Tag 3} >= {[.]Min} && {[.]Tag 3} <= {[.]Max}, {[.]Tag 3}, 0)

/ (
	if({[.]Tag 1} >= {[.]Min} && {[.]Tag 1} <= {[.]Max}, 1, 0)
	+ if({[.]Tag 2} >= {[.]Min} && {[.]Tag 2} <= {[.]Max}, 1, 0)
	+ if({[.]Tag 3} >= {[.]Min} && {[.]Tag 3} <= {[.]Max}, 1, 0)
	if(isGood({[.]Tag 1}), {[.]Tag 1}, null),
	if(isGood({[.]Tag 2}), {[.]Tag 2}, null),
	if(isGood({[.]Tag 3}), {[.]Tag 3}, null),
	if(isGood({[.]Tag 4}), {[.]Tag 4}, null)

If you want to do your own range check, you can add a couple of memory tags '''InstrumentHigh''' and '''InstrumentLow'''.

	if(isGood(if ({[.]1}>{[.]InstrumentHigh}||{[.]1}<{[.]InstrumentLow},qualifiedValue({[.]1},'bad',524,'Out of instrument range'),{[.]1})), {[.]1}, null),
	if(isGood(if ({[.]2}>{[.]InstrumentHigh}||{[.]2}<{[.]InstrumentLow},qualifiedValue({[.]2},'bad',524,'Out of instrument range'),{[.]2})), {[.]2}, null),
	if(isGood(if ({[.]3}>{[.]InstrumentHigh}||{[.]3}<{[.]InstrumentLow},qualifiedValue({[.]3},'bad',524,'Out of instrument range'),{[.]3})), {[.]3}, null),
	if(isGood(if ({[.]4}>{[.]InstrumentHigh}||{[.]4}<{[.]InstrumentLow},qualifiedValue({[.]4},'bad',524,'Out of instrument range'),{[.]4})), {[.]4}, null),
	if(isGood(if ({[.]5}>{[.]InstrumentHigh}||{[.]5}<{[.]InstrumentLow},qualifiedValue({[.]5},'bad',524,'Out of instrument range'),{[.]5})), {[.]5}, null),
	if(isGood(if ({[.]6}>{[.]InstrumentHigh}||{[.]6}<{[.]InstrumentLow},qualifiedValue({[.]6},'bad',524,'Out of instrument range'),{[.]6})), {[.]6}, null),
	if(isGood(if ({[.]7}>{[.]InstrumentHigh}||{[.]7}<{[.]InstrumentLow},qualifiedValue({[.]7},'bad',524,'Out of instrument range'),{[.]7})), {[.]7}, null),
	if(isGood(if ({[.]8}>{[.]InstrumentHigh}||{[.]8}<{[.]InstrumentLow},qualifiedValue({[.]8},'bad',524,'Out of instrument range'),{[.]8})), {[.]8}, null),
	if(isGood(if ({[.]9}>{[.]InstrumentHigh}||{[.]9}<{[.]InstrumentLow},qualifiedValue({[.]9},'bad',524,'Out of instrument range'),{[.]9})), {[.]9}, null),
	if(isGood(if ({[.]10}>{[.]InstrumentHigh}||{[.]10}<{[.]InstrumentLow},qualifiedValue({[.]10},'bad',524,'Out of instrument range'),{[.]10})), {[.]10}, null)

If those instrument high/low limits are real, then you probably want those applied to all uses of the tag rather than just in calculating the mean.
If so, you could add a second set of derived tags '''Validated1''' etc, with an expression

if ({[.]1}>{[.]InstrumentHigh}||{[.]1}<{[.]InstrumentLow},qualifiedValue({[.]1},'bad',524,'Out of instrument range'),{[.]1})

If you reference Validated1 instead of 1 then you get the benefit of quality in displays and all calculations.