Rule complexity breaks OpenHab/Java?

  • Platform information:
    • Hardware: Raspberry Pi 4
    • OS: Newest OpenHabian, default installation
    • openHAB version: 3.3

I’m trying to write a rule that will forecast solar radiation on an arbitrary day of the year. Eventually, the goal is to use this to control the charging behavior of a battery/PV system when combined with weather forecasting data.

Unfortunately, I seem to have written a rule that can’t be compiled? With the rule in place, OpenHab just gets completely stuck during startup and never moves past [el.core.internal.ModelRepositoryImpl] - Loading model 'SMART_SolCasting.rules'. It doesn’t even say there was a compiliation error or anything, it simply sits there.

Checking top reveals that even minutes after starting, the java process consumes ~130% of CPU.

So, my question: Did I do something “illegal”? Did I goof the syntax somewhere or is there too much trigonometry for java to handle? It’s very frustrating to test what exactly is causing the issue, because whatever it is, it doesn’t get cleared away by a systemctl restart openhab but rather requires a full reboot before the rules engine starts working again.

Here my code:

import java.util.List
import java.util.ArrayList
//Forecasting of solar stuff

rule "rule name"
when
    Item triggerDebug received command ON
then
    logInfo("SolCasting", "Beginning Calculation...")
    //Get the current Decimal Local time
    //var v_LT = now.getHour + now.getMinute * 0.01666666

    //Get the current day of the year
    var v_D = now.getDayOfYear 
    //var v_D = 365
    val Lat = 50.0
    val Lon = 9
    val unused = 0

    var pi180 = 0.0174532925

    //Do Timezone nonsense
    val v_dUTC = Integer.parseInt( now.getOffset.toString.substring(1,3) ) 
    val v_LTSM = 15.0 * v_dUTC

    //Calculate EoT for the day
    var v_B   = ( (360.0 / 365.0) * (v_D - 81) ) * pi180
    var v_EoT = 9.87 * Math::sin( 2 * v_B ) - 7.53 * Math::cos( v_B ) - 1.5 * Math::sin( v_B )
    
    //Find Time correction (in minutes)
    val v_TC = 4 * (Lon - v_LTSM) + v_EoT

    //Calculate High noon
    val v_LST_noon = 12 - v_TC / 60

    //Calculate the day's Declination
    val v_decl = ( 23.45 * pi180 * Math::sin( v_B ) ) * 57.2958 

    //Calculate the Solar Zenith/Elevation Angles
    var List<Float> v_elevation = newArrayList(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23)

    for(var c = 0; c < 24; c = c + 1){
        v_elevation.add(c, Math::asin( Math::sin( v_decl * pi180) * Math::sin( Lat * pi180 ) + Math::cos( v_decl * pi180) * Math::sin( Lat * pi180 ) * Math::cos( pi180 * (15 * ((c + v_TC / 60) - 12)) ) ) )
    }
 
    for(var c = 0; c < 24; c = c + 1){
        logInfo("SolCasting", "Hour " + c + " Solar Elevation " + v_elevation.get(c))
    }

    logInfo("SolCasting", "Current  day " + v_D )
    logInfo("SolCasting", "Current  v_B " + v_B )
    logInfo("SolCasting", "Current  EoT " + v_EoT )
    logInfo("SolCasting", "Todays time correction: " + v_TC)
    logInfo("SolCasting", "High Noon Today: " + v_LST_noon)
    logInfo("SolCasting", "Today's Solar Declination: " + v_decl)

    
end

Also, more generally, is there a better way to do this (forecast solar stuff)? The Astro binding delivers current radiation values, but afaik can’t predict future ones which is inconvenient.

Maybe.

Back in the days of OH2 we discovered that complex maths evaluations like that could become compilation sinkholes. I think each step brings exponential workload.

In particular, integer maths came with a penalty. It seems always better to use Number types (which is essentially the “native” type for DSL) and only force integer results when you have to.

Breaking down an evaluation into simpler steps gives the compiler measurably less work to do.

So

// instead of
var v_B   = ( (360.0 / 365.0) * (v_D - 81) ) * pi180

//try
var interA = 360.0 / 365.0  // why not pre-calculate that constant anyway
var interB = v_D - 81.0
var v_B   = ( interA * interB ) * pi180

EDIT - some discussion here

That was the “old rules engine” but I don’t imagine much has changed for DSL really.

2 Likes