MAP transform in rule not working

Hey all, I’m having trouble with a transformation in a rule and I need a hand. Right now I have a switch statement in a rule that turns the day number into the day name for use in a say() statement. Works great, no problem. It seems like a transformation is a good use case for this instead of potentially duplicating the same logic again somewhere else. (Trying to make Rich K. proud you know.) I created a weekday.map file:

1=Monday
2=Tuesday
3=Wednesday
4=Thursday
5=Friday
6=Saturday
7=Sunday

I created a var in my rule based on an example in the online docs:

var vTest = transform("MAP", "weekday.map", now.getDayOfWeek)

When I fire say(vTest) in my rule I see the following in my log:

Variable 'vTest' on rule file 'test.rules' cannot be initialized with value 'transform(<XStringLiteralImpl>,<XStringLiteralImpl>,<XMemberFeatureCallImplCustom>)': An error occurred during the script execution: Could not invoke method: org.eclipse.smarthome.core.transform.actions.Transformation.transform(java.lang.String,java.lang.String,java.lang.String) on instance: null

I’m not sure if I have a problem in my statement or a lower level issue. I have the MAP transform installed and it’s working for some other stuff. I also tried this: (I have something like this in an items file, figured I’d try it.)

var vTest = [MAP(weekday.map):now.getDayOfWeek]

Any ideas?

Thanks in advance,

~Mark

One thing that jumped out use that Sunday is 0, not 7.

getDayOfWeek returns an int. Transform requires a String. You need to convert the int to a String. The easiest way to do that is as follows:

var vTest = transform("MAP", "weekday.map", ""+now.getDayOfWeek)
1 Like

Thanks Rich! You’ve come through once again! (I started testing this on a Monday and just numbered the days from there, Sunday is fixed now.)

Can I ask one more question related to my rule? I’m using the weather forecast max temp in my good morning say command. I created a variable to hold it:

var vHighTemp = String::format("%.0f", (Temp_Max_FC0.state as DecimalType).floatValue())

It works fine but I see this in the log:

Validation issues found in configuration model 'test.rules', using it anyway:Cannot reference the field 'Temp_Max_FC0' before it is defined

The item is defined and it works fine in my sitemap. It’s not an error or warning in the log, just info. Should I be doing it differently?

Thanks again,

~Mark

These warnings appear because the rule parser is having a hard time interpreting what you are trying to do but when it comes to running the rule it works just fine. They are only warnings…
Do you get an error message in VSCode?

Hey Vincent, I’ve been using Notepad++ with the OH plugin but it doesn’t seem to work very well. I was actually just about to get VSCode and give that a shot.

I wasn’t too worried, just wondering if there was a better/more correct way to build the rule as to not get the warning. I’ll see what VSCode says once I get it set up.

Thanks!

~Mark

I highly recommend VSCode:

Do you see that warning every time the rule runs out just when the .rules file is loaded or just when OH restarts?

If I’m reading what you are trying to do correctly, you are just rounding off the decimal places, right? So why not just use

var vHighTemp = (Temp_Max_FC0.state as Number).intValue

Presumably you are concatinating this to a String later and it should figure out how to add the int to the message for you so you don’t have to explicitly convert it to a String yourself.

I know you have a solution for this already, but here are some options that don’t require using a MAP transform:

If you would like to stay with Joda Time…

// imports are placed at the very top of the rule
import java.time.DayOfWeek

// somewhere in your rule
val String theDay = DayOfWeek.of(now.getDayOfWeek).toString.toLowerCase.toFirstUpper

Pure Java… because Joda Time will not be around forever…

import java.time.ZonedDateTime
import java.time.ZoneId
import java.util.TimeZone

val String theDay = ZonedDateTime.now(ZoneId.of(TimeZone.getDefault.getID)).dayOfWeek.toString.toLowerCase.toFirstUpper

These will also work in JSR223-Jython.

Hey guys, thanks for the responses! Rich, you’re correct about the rounding. (Found that example somewhere in the forums.) Your revised variable works great. I only see the warning when I change the rule. It doesn’t appear when I run it.

Scott, your weekday var works as well. Is Joda going away in a future release? I guess I’d like to have rules that will work for the long haul if I can.

Thanks again,

~Mark

There is no plans for Joda to be replaced as far as I know. I think Scott is just saying in the generic “nothing lasts forever” sense. I’d bet that the entire Rules DSL would be scraped before Joda were replaced. The impact is such a change would be too great. Joda DateTime had been the central way Rules process time since the beginning (well at least since 1.5).

For ~3 years, the Joda website recommends to not use it, in favour of java.time (Java 8). I don’t really know if the new rule engine has access to Joda-Time, but you do with JSR223, and you also have the date/time classes available in your chosen JVM language. I have no idea what the core team have in store for Joda-Time, but I’m not aware of any dependency on it by ESH or OH, so it seems to me to be a bit vestigial.

It would be interesting to hear @Kai’s thoughts on the future of Joda Time!

We have indeed removed JodaTime whereever possible already - Java8 DateTime API is unsed instead.
The new rule engine does not use JodaTime. The only remaining use is in DSL rules - I haven’t investigated it in detail, but I fear that we cannot remove it there without breaking existing rules. Hence my plan would rather be to enhance the new rule engine to also support DSL rules (but then only using Java8 DateTime) and keeping the current rule engine as “legacy” so that people can decide when to do the switch (which possibly involves a slight refactoring of their existing rules). I cannot give any timeline though, but that’s at least the direction I envision.

2 Likes