iCloud binding - Rules problem

Hi everyone,
I just installed and successfully configured the icloud binding into my OpenHab2. The problem is on a rule that I made to know if I am at home or not. I made a rule which is triggered when the location changes, but i want to read the location accuracy on that point, to check if the values are acceptable.
Rule:

rule "iPhone Home"
when
    Item Vaz_Location changed
then
    // specify your home location
    val PointType home_location  = new PointType(new DecimalType(38.XXX), new DecimalType(-8.XXX))
    val PointType phone_location = Vaz_Location.state as PointType
    val int distance = phone_location.distanceFrom(home_location).intValue()
    val Decimal accuracy = Vaz_LocationAccuracy.state

    // specify your preferred radius (in meters)
    logInfo("iPhone Home",accuracy)
    if(distance < 100)
    {
        Vaz_Home.sendCommand(ON)
        logInfo("iPhone Home", "Vaz is at home.")
    }
    else
        {
            Vaz_Home.sendCommand(OFF)
            logInfo("iPhone Home","Vaz is away from home.")
        }
end

i tried to log to check the values but i am getting [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule ‘iPhone Home’: An error occurred during the script execution: Could not invoke method: org.eclipse.smarthome.model.script.actions.LogAction.logInfo(java.lang.String,java.lang.String,java.lang.Object[]) on instance: null

However, is i do logInfo(“iPhone Home”,Vaz_LocationAccuracy.state.toString) is outputs the value.

Can someone help me ?

Try adding the .toString to ”accuracy” in the logInfo. Logging expects strings and accuracy is Decimal.

Why don’t you keep doing that then if it works or you can do:

logInfo("iPhone Home", accuracy.toString)

Dealing with primitives and Decimal can be problematic in Rules DSL. In this particular place it is failing to recognize that accuracy is an Object with a toString method. The problem would be even worse if you try to log distance because primitive int doesn’t even have a toString method.

So there are some things you can do:

  • Don’t be any more specific than you have to be. Rather than Decimal, use Number. Or even better leave the Type off and let the Rules DSL figure out the Type. It is usually pretty good at this. Only when it fails should you become more constrictive.

  • Avoid primitives if possible. Some methods will require a primitive (e.g. now.plusMinutes) but calculations in the Rules DSL will use Numbers by default (actually BigDecimal) and forcing primitives is causing the Rules DSL to do a lot of unnecessary work and increases the likelihood you will encounter problems like this.

  • When the first thing you are trying to log is not a String, you must call toString on the Object or you can add an empty String in front of it. e.g. logInfo("iPhone Home", accuracy.toString) or logInfo("iPhone Home", ""+accuracy).

So the following version of the Rule will be less likely to run into problems like this.

val home_location  = new PointType(new DecimalType(38.XXX), new DecimalType(-8.XXX)) // never changes, so make it a global constant

rule "iPhone Home"
when
    Item Vaz_Location changed
then
    // specify your home location
    val phone_location = Vaz_Location.state as PointType // you don't need to define the type on the left, it is implied by the as PointType
    val distance = phone_location.distanceFrom(home_location) as Number // let this be a Number, it returns a DecimalType but that can cause problems in calls to sendCommand or postUpdate
    val accuracy = Vaz_LocationAccuracy.state as Number // let this be a Number

    // specify your preferred radius (in meters)
    logInfo("iPhone Home",accuracy.toString)
    if(distance < 100)
    {
        Vaz_Home.sendCommand(ON)
        logInfo("iPhone Home", "Vaz is at home.")
    }
    else
        {
            Vaz_Home.sendCommand(OFF)
            logInfo("iPhone Home","Vaz is away from home.")
        }
end