Example using Temperature type to control a switch

I was having a very difficult time using temperature values in my calculations until I stumbled across a lambda function that provided the hints for conversions. If you are working with scalars such as percent, you can work with it like so:
var myPcntType = 10|%
if (myPcntType < 11|%) {
// do something
}
Or, convert them from an item to some Number:

val org.eclipse.xtext.xbase.lib.Functions$Function2<Double, Double, Double> calculateDewPoint = [
    double temperature, double humidity
    |
    var double a
    var double b
    var double SDD
    var double DD
    var double v
    var double TD
    
    a = 7.5
    b = 237.3
    SDD=(6.1078 * Math::pow(10.0, ((a*temperature)/(b+temperature)).doubleValue)).doubleValue
    DD = (humidity/100*SDD).doubleValue
    v = Math::log10((DD/6.107).doubleValue)
    TD = ((b*v)/(a-v)).doubleValue
    TD
]

rule "lampsCtrl"
when 
//    Time cron "0 * * * * ?"
    Item weatherunderground_weather_local_current_relativeHumidity received update
then 
    var ts = 40 // temperature setpoint
    var dpd = 5 // delta degrees for dew point turn on
    var h = (weatherunderground_weather_local_current_relativeHumidity.state as Number).doubleValue
	var t = (weatherunderground_weather_local_current_temperature.state as Number).doubleValue
    var dp = calculateDewPoint.apply(t, h)

    // logInfo("Logger","lampsCtrl humidity is " + h)
    // logInfo("Logger","lampsCtrl temperature is " + t)
    logInfo("Logger","lampsCtrl dew point is " + dp)
    if (dp > (t - dpd) ) {
        if (laserLamp.state == OFF){laserLamp.sendCommand(ON);}
        if (gooseLampEngine.state == OFF){gooseLampEngine.sendCommand(ON);}
        if (gooseLampInterior.state == OFF){gooseLampInterior.sendCommand(ON);}
    }
    if (t < ts) {
        if (laserLamp.state == OFF){laserLamp.sendCommand(ON);}
    }
    if (dp < (t-dpd) && 
        t > ts) {
            if (laserLamp.state == ON){laserLamp.sendCommand(OFF);}
            if (gooseLampEngine.state == ON){gooseLampEngine.sendCommand(OFF)};
            if (gooseLampInterior.state == ON){gooseLampInterior.sendCommand(OFF)};
    }
end
1 Like

Try the following syntax instead. It is a little easier for the OH Rules parser to process and looks a little cleaner.

The big things are you don’t need to use Functions$Function and avoid the use of primitives except where necessary.

val calculateDuePoint = [ Double temperature, Double humidity |
    val a = 7.5
    val b = 237.3
    val SDD = (6.1078 * Math::pow(10.0, ((a*temperature)/(b+temperature)).doubleValue)
    val DD = humidity/100*SDD
    val v = Math::log10((dd/6.107).doubleValue)

    (b*v)/(a-v) // return value
]

The problem with primitives is that it gives the Rules parser a really hard time causing much increased parsing times. On an RPi this can result in extra minutes to Rules loading time.

Thanks for posting!

1 Like

Thanks! There were some minor errors in your solution, so here is a corrected version. You probably did this in your head without an IDE.
NOTE: I did check on promotion to doubles, and the following results in the same answer.

val calculateDewPoint = [ Double temperature, Double humidity |
    val a = 7.5
    val b = 237.3
    val SDD = (6.1078 * Math::pow(10.0, ((a*temperature)/(b+temperature))))
    val DD = (humidity/100*SDD)
    val v = Math::log10((DD/6.107))

    (b*v)/(a-v) // return value
]

i think he has IDE in his brain :slight_smile:

And on my phone

Maybe but it isn’t a very good one as evidenced above. :wink:

1 Like