[SOLVED] Best practice for float calculations in Rules? (NULL, UNDEF, TRY, CATCH)

I constantly have error messages in the log because of NULL or UNDEF. How do I get rid of them?

Example code from me:

rule "FanStop_badezimmer steuern" 

when
	Item Dewpoint_av_badezimmer   changed or
  Item Dewpoint_aussen          changed 
  
then

  try {
   
    var di = (Dewpoint_av_badezimmer.state as DecimalType)?.doubleValue
    var da = (Dewpoint_aussen.state as DecimalType)?.doubleValue  
    var feuchter_als_draussen = Math.round( (di-da)*10.0)/10.0     // positiv: Innenluft ist feuchter als die AuĂźenluft
        
  } // try
  catch(Throwable t) {
    // logError("Error", "Fehler: " + T.toString)
  }
  
end  

Error message (if item is not ready set, or in case of network problems):
Could not cast NULL to org.eclipse.smarthome.core.library.types.DecimalType

Why doesn’t try/catch suppress the error message?
I also tried to test for NULL and UNDEF before, but that also caused problems.

How can I calculate in a rule without constantly producing error messages just because an item is NULL or UNDEF?

Because the error is not the result of an Exception being thrown.

What problems did this cause? Can you show what specifically you tried?

Test for them before trying to cast an Item’s state.

if(Dewpoint_av_badezimmer.state == NULL || Dewpoint_av_badezimmer.state == UNDEF) return;

As Mark indicates, this isn’t an Exception. One of the problems with Rules DSL is that type errors do not throw exceptions, they just end the Rule. Thus you can’t catch them and if you are relying on a finally clause, that finally will not run.

Trying to cast NULL or UNDEF to DecimalType is a type error because neither are of type DecimalType.

Edit: A more efficient in terms of typing if statement would be

if(!Dewpoint_av_badezimmer.state instanceof Number) return;

I think it was like this:

if (Dewpoint_av_badezimmer.state == NULL || Dewpoint_av_badezimmer.state == UNDEF  || Dewpoint_aussen.state == NULL  || Dewpoint_aussen.state == UNDEF) {
  // do nothing
}
else {
    var di = (Dewpoint_av_badezimmer.state as DecimalType)?.doubleValue
    var da = (Dewpoint_aussen.state as DecimalType)?.doubleValue  
   // (now i can do something)
  // ...
}

It’s not easy to test for me, because there are no items NULL or UNDEF now.

I had items holding a dewpoint-value that where NULL, and others where UNDEF, so i had to test for both.
Test for UNDEF was difficult, I think there was a difference between undef and UNDEF.

The code above is long and ugly.

So how can I just calculate my calculation, if it is a regular numer, otherwise not?

ok I try

if(!Dewpoint_av_badezimmer.state instanceof Number) return;

I thought there was a problem with early return but it seems to be fixed.

Thank you, Mark and Rich!

you have two items which can trigger. I think better use:

if(!triggeringItem.state instanceof Number) return;
1 Like

It’s working now, no more error messages :slight_smile:
I use this code now:

  if (! (Dewpoint_av_badezimmer.state instanceof Number) )  return;
  if (! (Dewpoint_aussen.state instanceof Number) )  return; 

The DSL needs one more pair of brackets. And it’s not enough to test just the triggeringItem, because if both items are NULL it will throw an error again.

Thank you!

1 Like