For loop variable,Could not invoke method: org.eclipse.xtext.xbase.lib.IntegerExtensions.operator_lessThan(int,int) on instance: null

Hello, I’m having trouble getting a FOR loop to run when using variables, I have assured all my variables are ints and tried importing different libraries and had no luck

Rule:

import org.eclipse.xtext.xbase.lib.IntegerExtensions.operator_lessThan

rule "backDoorObjectFound"
when
    Item Zoneminder_ObjectsFound changed
then
    // Raw JSON
    //var rawObjects = Zoneminder_ObjectsFound.state.toString
    // Sample data
    var rawObjects = '{"state":"alarm","eventtype":"event_start","detection":[{"label":"chair","type":"object","box":[281,38,465,460],"confidence":"90.33%"},{"label":"chair","type":"object","box":[-4,26,342,458],"confidence":"65.65%"}],"name":"patioDoors:(12836) [a] detected:chair:90%  Forced Web","eventid":"12836","monitor":"2","hookvalue":"0"}'

    //logInfo("CDS", rawObjects)
    // Get num of objects detected
    var int objects = transform("JSONPATH", "$.detection.length()", rawObjects) //works
    //var int objects = 2 // Some reason wont work
    logInfo("CDS-len", objects) //works

    var int i
    var String key
    var String value
    for (i=1; i < objects ; i++) { //Error here
         var fitleredObjects = transform("JSONPATH", "$.detection[i].label", rawObjects)
         logInfo("CDS", fitleredObjects)
    }

    //logInfo("CDS-len", )
    //logInfo("CDS-len", transform("JSONPATH", "$.detection.length", rawObjects))
    //var fitleredObjects = transform("JSONPATH", "$.detection[0].label", rawObjects)
    //var fitleredObjects = transform("JSONPATH", "$.*", rawObjects)
    //logInfo("CDS", fitleredObjects)
    //sendPushbulletNote("OD", fitleredObjects)
end

Log:
Rule 'backDoorObjectFound': An error occurred during the script execution: Could not invoke method: org.eclipse.xtext.xbase.lib.IntegerExtensions.operator_lessThan(int,int) on instance: null

Anyone got any ideas? The loop works if the objects var is a programmed number .e.g 2.

  • Platform information:
    • OS: Linux Ubuntu
    • Java Runtime Environment: build 1.8.0_201-b09
    • openHAB version: 2.4.0-1

The error is complaining about an < operator. You have only one line of code that has an < operator.

for (i=1; i < objects; i++)

One of i or objects is not usable in a <. i is pretty straight forward but objects is populated using a transform. Transforms only return Strings. I’m a little surprised that it doesn’t complain about trying to assign a String to an int variable but this is almost certainly the source of the error.

Some additional things I notice which might become a problem but are not the source of the error in the logs:

Unnecessarily typing variables significantly slows down the parsing of .rules files. Use of primitives really slows it down. It’s generally best practice with Rules DSL to never explicitly type variables unless it’s required and to avoid primitives as much as possible.

I’m not 100% positive that JSONPATH supports .length(). It definitely has challenges dealing with arrays in JSON. The JSONPATH transformation is not pure JSONPATH.

There is a much shorter way to define the for loop.

for(i: 1 ..< objects)

So change the code as follows:

    val rawObjects = '{"state":"alarm","eventtype":"event_start","detection":[{"label":"chair","type":"object","box":[281,38,465,460],"confidence":"90.33%"},{"label":"chair","type":"object","box":[-4,26,342,458],"confidence":"65.65%"}],"name":"patioDoors:(12836) [a] detected:chair:90%  Forced Web","eventid":"12836","monitor":"2","hookvalue":"0"}'

    // Get num of objects detected
    val objects = new Integer(transform("JSONPATH", "$.detection.length()", rawObjects)) // You might want to add some error checking here
    logInfo("CDS-len", objects)

    for(i: 1..< objects) { 
         var fitleredObjects = transform("JSONPATH", "$.detection[i].label", rawObjects)
         logInfo("CDS", fitleredObjects)
    }
1 Like

Thank you for the reply, had to make some edits but got there in the end. The information of transforms only returns String was very helpful, since it didn’t throw a error when I didn’t explicitly change the type so just assumed it was a int :smile:.

I will include the final framework of the rule in case anyone needs something similar.

rule "backDoorObjectFound"
when
    Item Zoneminder_ObjectsFound changed
then
    logInfo("CDS-real value", Zoneminder_ObjectsFound.state.toString)
    // Raw JSON
    var rawObjects = Zoneminder_ObjectsFound.state.toString

    // Get num of objects detected
    val int objects = new Integer(transform("JSONPATH", "$.detection.length()", rawObjects))
    //logInfo("CDS-len", objects.toString())

    for(i: 0..< objects) {
         var fitleredObjects = transform("JSONPATH", "$.detection[" + i + "].label", rawObjects)
         //logInfo("CDS", fitleredObjects)

         if (fitleredObjects == "cat") {
             logInfo("CDS", "Mewo")
             sendPushbulletNote("CAT DETECTION SYSTEM", "Cat is at back doors")
         } else {
             logInfo("CDS", "Not a cat")
             //sendPushbulletNote("CAT DETECTION SYSTEM", "NOT(Cat is at back doors)")
         }
    }
end

Lord cat should approve of the system
-Thanks Sam