rule “Update time on modbus devices”
when
Time cron “0 0/1 * * * ?”
then
var Calendar cal = Calendar.getInstance()
logInfo("===", “===”)
var int second = cal.get(Calendar.SECOND)
var int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK) - 1
if (dayOfWeek == 0) dayOfWeek = 7
var int hourOfDay = cal.get(Calendar.HOUR_OF_DAY)
var int minute = cal.get(Calendar.MINUTE)
var int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH)
var int month = cal.get(Calendar.MONTH) + 1 var int year = (Math.floor(cal.get(Calendar.YEAR) / 100) << 8) + (cal.get(Calendar.YEAR) % 100)
why I receive an error
Error during the execution of rule ‘Update time on modbus devices’: Unknown variable or command ‘<<’; line 17, column 20, length 45 (Line 17 in bold).
Rules DSL does not implement bit wise operators like shift. In Xtend << is the doubleLessThan operator which means “much less than”, not a bit shift left. It would appear that Rules DSL doesn’t support bit shift operations at all.
that one works without any issues. So, my question is why is working one those lines, but if I try to use Math function it stops. but in rules only. when I use JS transformation, then my formula works perfect
I know I can use *256 or biginteger. But what me confused:
(Math.floor(year/ 100) << 8) + (year % 100)) —> return error about “<<”
((month << 8) + dayOfMonth) ----> no error, works perfect.
Then the problem could be that the value isn’t cast to int until after the entire expression is evaluated. The <<-operator might work on primitive ints, but not on whatever the Calendar-functions or Math.floor returns. Try splitting it up in different steps, something like:
var int century = Math.floor(cal.get(Calendar.YEAR) / 100)
var int year = cal.get(Calendar.YEAR) % 100
reg40036.sendCommand((century << 8) + year)
What programming language is your transform written in? It doesn’t seem surprising that any given statement doesn’t work (or works differently) in any given language.
Why do you think that is strange? Rules are not written in javascript. There’s no reason any particular operator from javascript should be available in rules.
Math.floor returns a double accordning to javadoc, while bitshift for technical reasons only works with ints (please correct me if I’m wrong). However (unless the rules DSL/Xtend performs some conversion) division with ints should return an int with the remainder discarded, so Math.floor shouldn’t be necessary. Edit: Since Calendar.get returns an int.
rule "test"
when
Item Test received command //or
then
val cal = Calendar.getInstance()
var y = cal.get(Calendar.YEAR)
logInfo("test", "y is a " + y.class.toString + " with value " + y.toString)
var century = y / 100
logInfo("test", "century is a " + century.class.toString + " with value " + century.toString)
var rounded = Math.floor(century)
logInfo("test", "rounded is a " + rounded.class.toString + " with value " + rounded.toString)
logInfo("test", "y << 8 returns a " + (y << 8).class.toString + " with value " + (y << 8).toString)
logInfo("test", "century << 8 returns a " + (century << 8).class.toString + " with value " + (century << 8).toString)
logInfo("test", "rounded << 8 returns a " + (rounded << 8).class.toString + " with value " + (rounded << 8).toString)
end
outputs:
2019-10-18 12:45:03.847 [INFO ] [.eclipse.smarthome.model.script.test] - y is a class java.lang.Integer with value 2019
2019-10-18 12:45:03.849 [INFO ] [.eclipse.smarthome.model.script.test] - century is a class java.lang.Integer with value 20
2019-10-18 12:45:03.850 [INFO ] [.eclipse.smarthome.model.script.test] - rounded is a class java.lang.Double with value 20.0
2019-10-18 12:45:03.852 [INFO ] [.eclipse.smarthome.model.script.test] - y << 8 returns a class java.lang.Integer with value 516864
2019-10-18 12:45:03.853 [INFO ] [.eclipse.smarthome.model.script.test] - century << 8 returns a class java.lang.Integer with value 5120
2019-10-18 12:45:03.855 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'test': Unknown variable or command '<<'; line 17, column 48, length 12
Conclusion: No need for Math.floor, the returned Double (note: not primitive double, but its wrapper class) don’t support the <<-operator, but since the division is performed on Integers no rounding is needed.