Reasonableness constraints

As in your first post. I’m thinking that is what the state.to_f is doing

You could do that, but when you are dealing with a dimensioned item, I prefer to utilise the unit.

In the simpler example two posts up, you could strip off the unit and do:

profile(:discard_anomalies) { |state:| state? && (0..300).cover?(state.to_f) }

But this assumes that the value coming in will always be in °F whereas keeping the unit in the code means that it will work regardless of what unit the binding will feed to you. You can even write the check using celsius range and it will still work exactly the same, even when the incoming value is in °F.

profile(:discard_anomalies) { |state:| state? && ((-17.78|"°C")..(148.89|"°C")).cover?(state) }

Or you can even mix it up, and it will still work.

profile(:discard_anomalies) { |state:| state? && ((-17.78|"°C")..(300|"°F")).cover?(state) }

No, this should work for this case. The trouble comes from the fact that previousState returns the most recent entry in the database which is almost never actually the previousState and almost always is the current state. That’s fine for this use case, no so much when what the user really wants is the previous state.

Yes, you’re correct, because it’s all persisted manually, so the previousState will give you the actual previous state when it was last persisted, and because you only persisted the “good” data, it’s fine.

I was thinking about the bug with previousState(true) when dealing with quantitytype, but that doesn’t apply here since we’ll call previousState() which defaults to previousState(false)

I use the OH2.4 version and do it this way with my Sonoff modules.
I filter out 0 (zero) values and ‘nan’ values.

rule “Read Sonoff1 Periodically”
when
Time cron “2/10 * * * * ?” //elke 10 seconden; 2 seconden na hele 10-tal
then
if (StableAfterSystemStarted.state!=ON) return;
createTimer(now, [ |
val result=sendHttpGetRequest(“http://192.168.178.221/json”,902) //retrieve all Sonoff data
if (result===null) return;
if (transform(“JSONPATH”, “$.Sensors[0]TaskValues[0][?(@.Value!=0)].Value”, result) !=“nan”) {Sonoff1_Temp1.sendCommand(transform(“JSONPATH”, “$.Sensors[0]TaskValues[0][?(@.Value!=0)].Value”, result) )}
if (transform(“JSONPATH”, “$.Sensors[1]TaskValues[0][?(@.Value!=0)].Value”, result) !=“nan”) {Sonoff1_Temp2.sendCommand(transform(“JSONPATH”, “$.Sensors[1]TaskValues[0][?(@.Value!=0)].Value”, result) )}
if (transform(“JSONPATH”, “$.Sensors[2]TaskValues[0][?(@.Value!=0)].Value”, result) !=“nan”) {Sonoff1_Temp3.sendCommand(transform(“JSONPATH”, “$.Sensors[2]TaskValues[0][?(@.Value!=0)].Value”, result) )}
if (transform(“JSONPATH”, “$.Sensors[3]TaskValues[0][?(@.Value!=0)].Value”, result) !=“nan”) {Sonoff1_Temp4.sendCommand(transform(“JSONPATH”, “$.Sensors[3]TaskValues[0][?(@.Value!=0)].Value”, result) )}
if (transform(“JSONPATH”, “$.Sensors[4]TaskValues[0][?(@.Value!=0)].Value”, result) !=“nan”) {Sonoff1_Temp5.sendCommand(transform(“JSONPATH”, “$.Sensors[4]TaskValues[0][?(@.Value!=0)].Value”, result) )}
if (transform(“JSONPATH”, “$.Sensors[5]TaskValues[0][?(@.Value!=0)].Value”, result) !=“nan”) {Sonoff1_Temp6.sendCommand(transform(“JSONPATH”, “$.Sensors[5]TaskValues[0][?(@.Value!=0)].Value”, result) )}
Sonoff1_Uptime.sendCommand(transform(“JSONPATH”, “$.System.Uptime”,result) )

end

@rlkoshak I’ve submitted Add SystemFilterProfile to filter values within a given range by jimtng · Pull Request #3534 · openhab/openhab-core · GitHub
I’d appreciate your input/feedback.

5 Likes

Question: In addition to the basic range filter above, should I also add an outlier-filter profile, as in, would anyone need/use it?

It can filter outliers based on various methods, based on a given window size (either in number of samples, or all data received within a time duration)

  • Inter Quartile Range method
  • Standard deviation as the range (i.e. only accept data if it’s below the standard deviation) method
  • A fixed “deviation” method - check how much it deviates from the median of the collected samples - basically the same way HomeAssistant does it
2 Likes

Your PR makes sense to me for correcting things that misbehave, but I don’t think I would use an outlier filter.

Just wanted to say thank you to everyone that helped with this. Using the Ruby profile is working great for me.

1 Like

An outlier filter is essentially a “dynamic” range filter, so you don’t have to come up with / specify the range limits, but it always depends on the application.

1 Like

Thank you very much for this, I’ll definitely use it.

Just a question: what are the min and max settings on state description for? I don’t see any use of these.

Which min max are you referring to?

Those give hints to MainUI when selecting a default slider or setpoint widget. They do not change the behavior of the Item and have no influence over the Link or Channel what-so-ever.

Thank you for that clarification :+1:
I always wondered what they are used for :slight_smile: