Generating random values in rules DSL in OH3

I’m still not really clear on where to find differences between the rules DSL in OH2 and the one in OH3, is there any good documentation to search in? I have converted most of my rules files to using the GUI, just a few more complicated left…

Currently I’m struggling with generating random values. In my old rules file I have something like the following:

import java.util.Random
val Random rand = new Random()
var float randomnumber = rand.nextFloat()

Nothing of this works anymore, it doesn’t even recognize the word “import”. Where do I start?

Sorry for my confusion…

Most all OH3 documentation, as it currently exists is in this forum as users try to write it.

Ok. I have searched what I can find in the forum, hoped there would exist more resources. I guess there haven’t been anything written regarding random numbers yet.

Anyone that knows how to do?

What is in your logs? This should work just the same as it always has.

The rule above gives this in the logs:

20:58:16.410 [ERROR] [.internal.handler.ScriptActionHandler] - Script execution of rule with UID '320dfc5364' failed:  ___ import  ___ java.util.Random
val Random rand = new Random ___ ()
var float randomnumber = rand.nextFloat()
   1. Random cannot be resolved to a type.; line 2, column 28, length 6
   2. The method or field import is undefined; line 1, column 0, length 6
   3. Random cannot be resolved.; line 2, column 46, length 6
   4. This expression is not allowed in this context, since it doesn't cause any side effects.; line 1, column 7, length 16

Just to make sure, this is in a .rules file or is it in a MainUI rule?

Does it work without the import? Remove the import and change the line to

var java.util.Random rand - new java.util.Random()

It’s a rule in the Main UI.

Changed to that, now I instead get:

21:53:46.431 [ERROR] [.internal.handler.ScriptActionHandler] - Script execution of rule with UID '320dfc5364' failed: var java.util.Random rand  ___ - new java.util.Random()
var float randomnumber = rand.nextFloat()
   - cannot be resolved.; line 1, column 26, length 1

At this point the best I can offer is to file an issue. It’s supposed to work. I verified already that java.util.Random still exists in Java 11. The import isn’t the root cause of the problem. For some reason it just can’t find Random.

Ok, filed it:

Also upgraded to RC1, confirming the same problem after upgrade.

@DanielMalmgren The solution is very simple: Imports are not supported in scripts, just use the FQCN instead:

val java.util.Random rand = new java.util.Random()
var float randomnumber = rand.nextFloat()

@rlkoshak Also for your information, that might be an important fact for the tutorial!

1 Like

Well, that explains it :sunglasses:

(weird though, I thought I tried doing exactly that after @rlkoshak’s suggestion earlier in the thread. When doing it now it works fine…)

The difference between both might be the “-” vs “=” …

Hahaha… I guess both @rlkoshak and me are too tired :stuck_out_tongue:

1 Like

Right now the Getting Started tutorial mostly presents JavaScript (I’m considering adding a Blockly page but time is running out). I’ll see how I can work it in there or in the Rules DSL docs. As I mentioned on the tracking issue, I think the whole Rules docs need a complete overhaul now that building rules in the UI is working.


Ok, another thing I really can’t seem to succeed with in the GUI, might as well continue in the same thread…

In a rule in a .rules file I use the following

(Utetemperatur.state as QuantityType<Temperature>).doubleValue

to get the value of a Number:Temperature Item into decimal form. When I do this in a rule in the GUI it simply says

Temperature cannot be resolved to a type.

What am I doing wrong now?

If I recall correctly, you needed an import for Temperature already in the .rules file. So look at your import and put the package path before Temperature. I think it’ll look something like javax.measure.quantity.Temperature.

No, I have nothing like that in the file. And javax.measure.quantity.Temperature isn’t recognized either (altough there seems to be something named like that when I Google it).

Then I’m not sure. But a different question is do you really need that? What’s the full line and why do you need the doubleValue?

That’s actually a legitimate question :stuck_out_tongue: It’s the same rule as the random stuff discussed earlier in this thread. I’m sending temperature readings to a stupid API which thinks my sensor is broken if I don’t periodically send values, and they have to be different than the value I sent before. Since my sensor only reports values with one decimal it sometimes happens that it’s stable for too long. So I add a random second decimal before sending the value to eliminate the risk of it being tha same as the last. I hope you’re following :sunglasses:

The entire relevant code looks like this:

rule "Utetemperatur changed"
        Item Utetemperatur changed or
    Time cron "0 5/20 * * * ? *"
        var float slumptemp = (Utetemperatur.state as QuantityType<Temperature>).doubleValue + rand.nextFloat()*0.04
        sendHttpGetRequest("http://<removed_url>&t=" + slumptemp)

OK, I think you don’t need to use “Temperature” here. I think you can use “Number” instead and achieve the same result. You are stripping the units off of the value anyway so it really doesn’t matter what type it is beyond just Number.

This leaves the original question unanswered I know, but it should get you to the next step at least.

However, I see a few other Rules DSL problems with the rule which might be done better.

For one you are forcing the variable to be a float but pulling a double from the Item’s state. And then adding a float to that. You should stick to floats for all of these for one. For a second, get rid of the type for the the variable. It’s not needed and there will be a whole bunch of conversions taking place in that one line to get to it. This is known to drastically slow down the loading and parsing of rules.

var slumptemp = (Utetemperatur.state as QuantityType<Number>).floatValue + rand.nextFloat()*0.04

In fact it might even work without the .floatValue.

In general Rules DSL is going to try really hard to convert all the numbers and results of calculations to BigDecimal. Don’t fight it. Only force it to a primitive when you absolutely have to.