Use number in rules

Any one that can see whats wrong with this:

rule "Ladning af bil med solceller"
when
//	Time cron "0 0/5 * * * ?"		//hvert 5 min
//	Time cron "0 * * * * ?"			//hvert 1 min
	Time cron "0/10 * * ? * * *"	//hvert 10 sec
//	Time cron "0 0 * ? * * *"		//hver time
then
	if (Sun_car_power.state == ON){

		var String[] fase_123 = Easee_Circuit_Dynamic_Phases.state.toString.split(";")
		var Number amp_p3 = fase_123.get(2)
		var Number forbrug = el_forbrug_lige_nu.state.toString

		logInfo("bil-lader.rules", Easee_Circuit_Dynamic_Phases.state.toString)
		logInfo("bil-lader.rules", amp_p3)
		logInfo("bil-lader.rules", forbrug)



		if (Easee_Charger_Start_Stop.state == ON){
			if (forbrug < 0){
				Easee_Circuit_Dynamic_Phases.sendCommand(String::format("%d;%d;%s", 0, 0, amp_p3 + 1))
			}
			if (forbrug > 100 && amp_p3 > 6){
				Easee_Circuit_Dynamic_Phases.sendCommand(String::format("%d;%d;%d", 0, 0, amp_p3 - 1))
			}
			if (forbrug > 700 && amp_p3 == 6){
				Easee_Charger_Start_Stop.sendCommand(OFF)
			}
		}
		if (Easee_Charger_Start_Stop.state == OFF && forbrug < (-700)){
			Easee_Circuit_Dynamic_Phases.sendCommand(String::format("%d;%d;%d", 0, 0, 6))
			Easee_Charger_Start_Stop.sendCommand(ON)
		}
	}
end

Log:
2023-02-20 19:22:20.502 [INFO ] [ab.core.model.script.bil-lader.rules] - 0;0;11
2023-02-20 19:22:20.503 [INFO ] [ab.core.model.script.bil-lader.rules] - 11
2023-02-20 19:22:20.503 [INFO ] [ab.core.model.script.bil-lader.rules] - 489
2023-02-20 19:22:20.504 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID ā€˜bil-lader-2ā€™ failed: An error occurred during the script execution: Could not invoke method: org.openhab.core.model.script.lib.NumberExtensions.operator_lessThan(java.lang.Number,java.lang.Number) on instance: null in bil-lader

Meanwhile, until an expert replies: you are assigning a string to a number variable.
Try:

var Number forbrug = el_forbrug_lige_nu.state as Number

Hi @Jakob

You are assigning a string here

var Number forbrug = el_forbrug_lige_nu.state.toString

and then you compare it with a Number

if (forbrug < 0){

Must fail. But donā€™t ask me why a Number declared variable changes to String by assignment :wink:

What is the datatype of ā€œel_forbrug_lige_nuā€. Perhaps you just have to delete ā€œ.toStringā€

As has been pointed out. A String is not a Number and you canā€™t do math with it as if it were a Number.

Rules DSL really wants to be weakly typed. Your life will go much better if you let it be weakly typed. And because it wants to be weakly typed, there is nothing that fixes the type or any variable. It will happily assign a String to a variable that was declared to be a Number.

The only times you should force a type in Rules DSL include:

  • you are initializing the variable to null: e.g. var Timer myTimer = null
  • you are casting because Rules DSL wasnā€™t able to determine the correct type on itā€™s own: e.g. (MyItem.state as Number)
  • itā€™s required to be a specific type, usually a primitive, for a call to a Java method: e.g. now.plusSeconds(mySecondsVariable.intValue)

In all other cases, forcing the type in Rules DSL will cause way more problems than it solves.

2 Likes

If I change it to


		var Number forbrug = el_forbrug_lige_nu.state

I will get an error on this line:


		logInfo("bil-lader.rules", forbrug)

2023-02-20 20:48:00.808 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID ā€˜bil-lader-2ā€™ failed: An error occurred during the script execution: Could not invoke method: org.openhab.core.model.script.actions.Log.logInfo(java.lang.String,java.lang.String,java.lang.Object) on instance: null in bil-lader

Any clue?

There is nothing on that line of code to tell logInfo that you want forbrug to be converted to a String. So call toString there.

I see, toString worked.

Now I get error on this line

if (forbrug > 100 && amp_p3 > 6){

2023-02-20 21:11:20.874 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID ā€˜bil-lader-2ā€™ failed: An error occurred during the script execution: Could not invoke method: org.openhab.core.model.script.lib.NumberExtensions.operator_greaterThan(java.lang.Number,java.lang.Number) on instance: null in bil-lader

amp_p3 isnā€™t a Number either. Itā€™s a String. You have to parse it into a Number to do math with it.

Again, see my reply above. var Number amp_p3 does not convert a String to a Number. For the most part, that does nothing. You have to parse a String into a Number.

All things considered, youā€™d have a much better time of this if you switched to Blockly.

1 Like

Arh, now I see it.
Works if I change amp_p3 to Integer::parseInt(amp_p3)

Think you are right regarding the Blockly.
The downside is that I have many rules written in files since OpenHab 1.8

But in the future I will try Blockly

Thanks for your help :wink:

You can do it little by little. As you find you need to write new rules, choose Blockly for those. As you need to change rules, consider translating them to Blockly.

Thereā€™s no real harm in having a mix of .rules files and Blockly rules.

Blockly hast another advantage: you can do the blocks and then look into the code tab and learn from it if you want use code later on. Blockly tries to do its best to keep the typed blocks consistent.

And as Rich said: you can have a mixed set of rules. I still have a few rules based on pure code while most of the others are blockly but that is matter of tasteā€¦