State Filter (Range Filter) Profile

Some time ago, I tried submitting a range filter profile to core, but it was rejected because such profiles should be added as an add-on.

I noticed that Basic Profiles add-on was recently merged into the official openhab repo. This includes a State Filter profile.

I’ve been working on improvements to this profile so that it can be used to filter incoming data based on the incoming data itself.

With this PR it supports:

  • Filtering (EQ and NEQ) based on the state of other items (the original feature of this profile)
  • Expanded comparisons using greater/less than operators (GT, GTE, LT, LTE)
  • Support comparisons using symbols too (==, != (or <>), >, >=, <, <=)
  • Filtering based on the incoming data (added in this PR)
  • Compare one item’s state against another item’s state, e.g. Item1 > Item2
  • Compare the input state against another items’s state, e.g. > LowerThresholdItem, < UpperThresholdItem

Some quick contrived examples:

Two conditions, checking two other items:

Number:Temperature Aircon_Temp { 
  channel="xxxx" [
    profile="basic-profiles:state-filter",
    conditions="Aircon_Power==ON", "House_Occupied == ON",
    mismatchState="UNDEF"
  ]
}

Checking against the incoming state, making sure it’s within a “reasonable” range

Number:Temperature BBQ_Temperature {
  channel="xxx" [
    profile="basic-profiles:state-filter",
    conditions=">= 0 °F", "< 1000 °F" 
  ]
}
1 Like

I could add a way to check for delta, average, stddev, median, in a separate pr later. Any other ideas?

sorry, no ideas yet. But woohoo. That sneaked in somehow and I didn’t notice it. It sounds awesome.
(I’m pretty sure that quite a few are fiddling around with proxy items and rules while most of it can be solved now just with those profiles).

Maybe one idea/question (but not for the state filter): Would the rollershutter-profile-addon fit into that package too? It emulates positions for rollershutters without this function. It currently lacks the ability to be configured within the UI, so this would be something that could be updated. Or is that too specific for the “basic”-package?

Would it be somehow possible to use another item state as input instead of a thing channel?
E.g. some kind of virtual channel which links one item to another item?

Interesting idea. While it’s possible, however the profile is only “triggered” / invoked when the actual channel / binding is sending an update though.

I wish the addon had a different name, but I can’t think of a better name right now :D. The word “basic” implies there could be an “advanced” one… and that’d just be confusing: “Is this “median” filter in the basic profile addon, or in the advanced one?”

And then there’s a concern (not mine) that things could get out of hand and we ended up with far too many profiles.

Updated the OP with some examples

The idea is that the profile would be triggered when the source item state updates, otherwise it would not be very useful.That way simple rules could become an easy item configuration.

e.g. I do some calculations and update an item. When the item state is over 100 a light should turn on.
Obviously I can write a simple rule that does exactly that but with a configuration it would be easier.

Also it would be nice to reference other item states as boundaries instead of fixed values.
E.g.

Number:Temperature BBQ_Temperature {
  channel="xxx" [
    profile="basic-profiles:state-filter",
    conditions=">= $MyLowerBoundaryItem", "< $MyUpperBoundaryItem" 
  ]
}
1 Like

That would only work if the source item is linked to a channel, and we’re “hijacking” that link. It won’t work for virtual items since profiles are only applicable to item channel links.

This is a good idea

Perhaps we need to require string literals to always be quoted. This way we can treat bare words to be item names, thus avoiding the need to use special symbols like $ in this case.

I was thinking of using $ for special operators like $delta

@Spaceman_Spiff I’ve added the feature to compare against another item as you suggested, thanks!

I’ll update the OP to show this use case.

Note that DateTimeType currently cannot utilise inequality operators e.g. DateTimeItem1 > DateTimeItem2. If this PR is merged, then we can have inequality comparisons for DateTimeType here.

Nice - you’re on fire!

Does it re-trigger evaluation when the referenced item changes?
Will this work for all profiles?

It reevaluates item states every time the incoming data is received.

Please elaborate this question

So if I understand it correctly when the referenced item changes nothing happens.
Only when a value through the channel is received the new boundary will be picked up.
That’s a gotcha that needs to be explicitly made clear in the docs.

Will referencing other items work for all profiles or just the “basic profiles” you are mentioning in the title?

This is correct.

Let’s say in a profile for item A, you have conditions that check for items X and Y.

Number X
Number Y
Number A { channel="xxx" [profile="basic-profiles:state-filter", conditions="> X, < Y" ]}

What happens is that whenever the channel xxx sends an updated data to item A, the profile will be invoked and it then re-evaluates the conditions based on the current states of item X and Y.

That’s all it does.

That profile does not get invoked independently when X or Y changes, because that’s not how profiles work.

If you want something to happen whenever X or Y changed, you’d either add a rule that triggers when X or Y changed, or you’d add a profile on X or Y, but that has nothing to do with this profile on item A.

I know that the basic-profiles addon contains multiple profiles. I’m only making changes to the basic-profiles:state-filter profile. It does not affect/apply to any other profiles within the basic-profiles addon, nor any other profiles outside this addon.

So it works as I suspected. It’s clear to me why but I still think there should an explicit warning or info in the docs with a behavior example (like you posted above) because it’s probably not clear for everyone.

I see. Do you think referencing item states should work across all profiles in the same manner?
E.g. also for the system:range

Maybe. It just needs to be implemented separately on a case by case basis, as there’s no one central place to change them all.

Hm, shame. It would have been really nice if there is a central place where this functionality could have been implemented. It’s really awkward, that referencing items will work for one profile but not for the other.

Maybe it would make sense to rework the whole profiles so that

  • there is a central place that handles these things
  • it’s possible to chain profiles together
  • it’s possible to apply profiles on “virtual items”.

This one is easy. Introduce a “virtual binding” then you can have your profile as usual. But this is a very convoluted way of avoiding to write a rule.

  • Improve the conditions flexibility so that any type of operand can be on either side of the operator, e.g.: ItemName > 10 and 10 < ItemName
  • Add support for functions:
    • $DELTA to represent the absolute difference between the incoming value and the previously accepted value.
    • $AVERAGE, or $AVG to represent the average of the previous incoming values, excluding the incoming value.
    • $STDDEV to represent the population standard deviation of the previous unfiltered incoming values.
    • $MEDIAN to represent the median value of the previous incoming values.
    • $MIN to represent the minimum value of the previous incoming values.
    • $MAX to represent the maximum value of the previous incoming values.
      By default, 5 samples of the previous values are kept.
      This can be customized by specifying the “window size” or sample count applicable to the function, e.g. $MEDIAN(10) will return the median of the last 10 values.
      All the functions except $DELTA support a custom window size.

Example:

Filter out incoming data with very small difference from the previous one:

Number:Power PowerUsage {
  channel="mybinding:mything:mychannel" [ 
    profile="basic-profiles:state-filter",
    conditions="$DELTA > 10 W"
  ]
}
3 Likes