[SOLVED] Difference in strings

I want to show the difference between to strings and I have tried to make a rule but it gives me errors in the log " Error during the execution of startup rule ‘Vandforbrug’: Could not cast 368.522"

rule "Vandforbrug"
when
		System started
then
	var String FF_Water_Target_volume = (FF_Water_Target_volume.state as DecimalType).floatValue
	var String FF_Water_volume = (FF_Water_volume.state as DecimalType).floatValue
	var Number WaterDiff = 0
	WaterDiff = (FF_Water_volume-FF_Water_Target_volume)
	
		logInfo("test", "test: " + diff + " (" + FF_Water_Target_volume.state +" : " + FF_Water_volume.state +")")
	
	postUpdate(WaterDiff, diff)
	
	end 

You can’t substract text, only numbers.
You can “add” them but that’s called concatenation, it’s not an addition in the mathematical sense
I assume that WaterDiff is a Number item defined in your *.items file

rule "Vandforbrug"
when
    System started
then
    var Number FF_Water_Target_volume = (FF_Water_Target_volume.state as DecimalType).floatValue
    var Number FF_Water_volume = (FF_Water_volume.state as DecimalType).floatValue
    var Number diff = FF_Water_volume - FF_Water_Target_volume
    logInfo("test", "test: " + diff.toString + " (" + FF_Water_Target_volume.state +" : " + FF_Water_volume.state +")")
    WaterDiff.postUpdate(diff)
end 
1 Like

Now it gives me this error : Error during the execution of rule ‘Vandforbrug’: ‘state’ is not a member of ‘java.lang.Number’; line 8, column 55, length 28
I have change the rule to run every minut.

rule "Vandforbrug"
when
    Time cron "1 * * ? * * *" // Every minute at 1 second past
then
    var Number FF_Water_Target_volume = (FF_Water_Target_volume.state as DecimalType).floatValue
    var Number FF_Water_volume = (FF_Water_volume.state as DecimalType).floatValue
    var Number diff = FF_Water_volume - FF_Water_Target_volume
    logInfo("test", "test: " + diff.toString + " (" + FF_Water_Target_volume.state +" : " + FF_Water_volume.state +")")
    WaterDiff.postUpdate(diff)
end 
rule "Vandforbrug"
when
    Time cron "1 * * ? * * *" // Every minute at 1 second past
then
    var Number target = (FF_Water_Target_volume.state as DecimalType).floatValue
    var Number volume = (FF_Water_volume.state as DecimalType).floatValue
    var Number diff = volume - target
    logInfo("test", "test: " + diff.toString + " (" + target.toString +" : " + volume.toString +")")
    WaterDiff.postUpdate(diff)
end 

You are my hero. It works. Thanks

You are welcome.
Do you understand why it work and why you code didn’t?

You can’t name variables in a rule the same as items
To convert a Number variable to a string (For display purposes), use the .toString method
You can only do math on numerical variables like int float Number
Use the Number type as much as possible as it is very flexible
Only use int types when really necessary

Now your rules could be shortened to:

rule "Vandforbrug"
when
    Time cron "1 * * ? * * *" // Every minute at 1 second past
then
    WaterDiff.postUpdate((FF_Water_volume.state as DecimalType).floatValue as Number) - (FF_Water_Target_volume.state as DecimalType).floatValue as Number))
end 

Slightly simpler. There is no need to go from DecimalType to float and back to Number. You can directly cast DecimalType to Number and I highly recommend always casting to Number and never casting to DecimalType. If you are casting at all, it’s because you want to do math but if you try to sendCommand using a DecimalType you will get an “ambiguous function call” exception because DecimalType is a Number and for some reason there are two versions of of sendCommand, one that takes a Number and another that takes a DecimalType and as a result the Rules DSL doesn’t know which one you mean.

WaterDiff.postUpdate((FF_Water_volume.state as Number) - (FF_Water_Target_volume.state as Number))
1 Like

Yes but that would not necessarily work with UoM number items

Neither would the cast to DecimalType.

No but you would do that to cast to float. You can’t do that with as Number because it keeps the unit in

You can’t cast directly to float. And unless I’m wrong, you need to cast a UoM State to a QuatityType and can’t cast it to a DecimalType. I’ve been using JSR223 for long enough that I may be missremembering but MyTemperature.state as DecimalType will produce an error if MyTemperature.state is a QuantityType. So if you have a QuantityType, you need to (MyTemperature.state as QuantityType<Number>).floatValue but for DecimalType you need only use MyTemperature.state as Number.

There are two ways to do it. I’ll check my rules when I get home.