Rule problem: no viable alternative at input '0'

I want just to see values in my val if they are greater than 0 (therefore energy is pushed into the net) otherwise I don’t want to show value in val Einspeisung.

tried the following rule:

rule "einspeisungCalc"
when
	Item SMARTMETER_Current received update AND SMARTMETER_Current.state as Number > 0
then
	Einspeisung.postUpdate(SMARTMETER_Current.state as Number);
end

declaration is:

Number Einspeisung "Netz-Einspeisung [%.2f %%]" <inverter>
Number  SMARTMETER_Current "Aktueller Verbrauch [%0f W]"  <inverter>    (PV)    { http="<[smartmeter:4000:JSONPATH($.Body.Data.PowerReal_P_Sum)]"}

failure:
2021-09-30 16:40:51.724 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model ‘pvcalculations.rules’ has errors, therefore ignoring it: [38,46]: missing ‘then’ at ‘SMARTMETER_Current’
[38,83]: no viable alternative at input ‘0’
[45,46]: missing ‘then’ at ‘SMARTMETER_Current’
[45,83]: no viable alternative at input ‘then’

i think an “AND” combination in the when-condition is not possible.
try to move the second part as in if-condition in the then-part, like:

rule "einspeisungCalc"
when
	Item SMARTMETER_Current received update
then
    if (SMARTMETER_Current.state as Number > 0){
	    Einspeisung.postUpdate(SMARTMETER_Current.state as Number)
    }
end

thanks for the help.

I get the following error:
2021-09-30 16:59:29.382 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model ‘pvcalculations.rules’ has errors, therefore ignoring it: [40,43]: no viable alternative at input ‘0’

on exactly the > 0 in the if condition.

Stefan is exactly right. Rule triggers are events, not states. There is no such thing as an event SMARTMETER_Current.state as Number > 0.

If using .rules files you need to check the state inside the rule as Stefan demonstrates. In a UI rule you can configure a Rule Condition which is separate from the triggers and which does test the state before allowing the rule to run.

It’s not clear what is causing the error though. Are you certain SMARTMETER_Current isn’t NULL or UNDEF when the rule runs?

i just tried the following:

rule "einspeisungCalc"
when
	Item SMARTMETER_Current received update
then
	if (SMARTMETER_Current.state as Number > 0){
		Einspeisung.postUpdate(SMARTMETER_Current.state as Number);
	}
	if (SMARTMETER_Current.state as Number < 0){
		Bezug.postUpdate(SMARTMETER_Current.state as Number *-1);
	}
end

getting:
2021-09-30 17:07:01.347 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model ‘pvcalculations.rules’ has errors, therefore ignoring it: [43,43]: no viable alternative at input ‘0’

this is exactly this line:
if (SMARTMETER_Current.state as Number < 0){

SMARTMETER_Current is actually:
-443.40

tried to escape from second if with else! :wink: this works:

rule "einspeisungCalc"
when
	Item SMARTMETER_Current received update
then
	if (SMARTMETER_Current.state as Number > 0){
		Bezug.postUpdate(SMARTMETER_Current.state as Number);
		Einspeisung.postUpdate("0");
	}
	else {
		Einspeisung.postUpdate(SMARTMETER_Current.state as Number *-1);
		Bezug.postUpdate("0");
	}
end

last problem: the postUpdate(“0”) does work but looks not very nice.

thanks

0 already is a number. There’s no need to cast it. Just use 0, no quotes, no casting.

You have to cast the state of an Item to Number because an Item’s state can be all sorts of things. It you want to use it as a Number you have to tell it so.

It shouldn’t be necessary but maybe the casting needs to be encapsulated.

if((SMARTMETER_Current.state as Number) > 0) {

If that doesn’t work try forcing it to be a float.

if((SMARTMETER_Current.state as Number).floatValue > 0){

Neither should be necessary in this case but the error doesn’t tell us what is really wrong.

Would be better to test if the status is of type number…

rule "einspeisungCalc"
when
    Item SMARTMETER_Current received update
then
    if(!(SMARTMETER_Current.state instanceof Number)){
        logWarn("smartmeter","SMARTMETER_Current.state not of type Number:{}",SMARTMETER_Current.state)
        return;
    }

    val Number nSM = (SMARTMETER_Current.state as Number).floatValue
    if(nSM > 0){
        Bezug.postUpdate(nSM)
        Einspeisung.postUpdate(0)
    } else {
        Einspeisung.postUpdate(- nSM)
        Bezug.postUpdate(0)
    }
end

Please be aware that you don’t need to use ; at end of each line, but only if using return; this is due to the fact, that return will send a value, that is the part after return, but Rules DSL does not allow to return a value, so the ; is to mark “no value at all”.