Stuck with Maths in Rule

Hello,

i just updated to Oh4 and installed the java Binding. I also tried to work with Data Conversion, because some Information i get from my devices are wrong and i cant change them there, so i have to deal with it in openhab.

One thing i have is my power grid, it gives the right value, but its 10 times too high. So i tried to do a rule to convert it via java, but i always fail.

rule "Convert Photovoltaik_Data"
  when
    Item Photovoltaik_Momentan changed
or  Item Photovoltaik_Ladestatus changed

 then

//Get new Values 
        val Photovoltaik_Momentan_val = transform("JSONPATH", "$.values.pvpowerin", Photovoltaik_Momentan.state.toString)
        val Photovoltaik_Ladestatus_val = transform("JSONPATH", "$.values.bms_soc", Photovoltaik_Ladestatus.state.toString)

//Set New Values
        Photovoltaik_Momentan_Num.postUpdate( Photovoltaik_Momentan_val )
        Photovoltaik_Ladestatus_Num.postUpdate( Photovoltaik_Ladestatus_val )

//Calc down PV
//        var Photovoltaik_Ladestatus_Num_Korrekt = items.getItem("Photovoltaik_Ladestatus_Num");
        var Photovoltaik_Ladestatus_Num_Korrekt = Photovoltaik_Ladestatus_Num.state;
        Photovoltaik_Ladestatus_Num_Korrekt.divide(10);
        Photovoltaik_Ladestatus_Num.postUpdate("Photovoltaik_Ladestatus_Num_Korrekt");

end

So up until my Calc Down PV Values Part everything is working how its supposed to, but then i always fail. I either get no data, or i get that my data is in wrong formats, or whatever.

Right now its: Script execution of rule with Script execution of rule with UID ‘transform-1’ failed: ‘divide’ is not a member of ‘org.openhab.core.types.State’; line 18, column 2, length 46 in transform

Anyone who could help me? Thank you very much :smiley:

Have a nice day
Michael

What Java binding? Do you mean JavaScript? You are not using Java nor JavaScript here. This is Rules DSL. I’m confused.

Did you try to get ChatGPT to write this for you? None of the AI chatbots produce openHAB rules that make any sense. There are no shortcuts. Instead of messing with chatbots, use Blockly which is much easier for most to use and understand.

Some problems:

You’ve just updated Photovoltaik_Ladestatus_Num. There is no guarantee, and in fact it’s unlikely, that the Item will be in the newly updated state when the next line of code runs to get the state from this same Item. You already have the value in Photovoltaik_Ladestatus_val, so just use that (you’ll have to parse it).

The error tells you exactly what’s wrong. There is no divide function on a State. That’s the type that gets returned by Item.state. You’d need to cast it to something else. In this case casting it to a Number makes sense. However, Number doesn’t have a divide method either. You need to use the division operator /. Furthermore, you don’t save the result of the division. Neither math operators nor the math functions modify the operand. They always return a new value that is the result of the operation. You need to capture that result or else it just disappears.

rule "Convert Photovoltaik_Data"
  when
    Item Photovoltaik_Momentan changed
or  Item Photovoltaik_Ladestatus changed

 then

//Get new Values 
        val Photovoltaik_Momentan_val = Double.parseDouble(transform("JSONPATH", "$.values.pvpowerin", Photovoltaik_Momentan.state.toString))
        val Photovoltaik_Ladestatus_val = Double.parseDouble(transform("JSONPATH", "$.values.bms_soc", Photovoltaik_Ladestatus.state.toString))

//Set New Values
        Photovoltaik_Momentan_Num.postUpdate( Photovoltaik_Momentan_val )
        Photovoltaik_Ladestatus_Num.postUpdate( Photovoltaik_Ladestatus_val )

//Calc down PV
        val Photovoltaik_Ladestatus_Num_Korrekt = Photovoltaik_Ladestatus_val / 10
        Photovoltaik_Ladestatus_Num.postUpdate("Photovoltaik_Ladestatus_Num_Korrekt")
end

Depending on how this data come into OH, it’s probably better to use transformations in the Thing’s Channel configs or using the transform profile instead of a rule.

Hey there,

thank you for your reply. The binding i thought would help me (and the one i thought i was using) was this one: JavaScript Scripting

The reason why i try doing this via rules, is that i want to have a number item, that i can use for further Rules, so i can start active use of the grid power, whenever its high. I dont know if this would fully work with a transformation?

The reason i was trying to work with the num item, is that my first errors when trying to work with the rules were that the val item was a string, so maths would be a problem anyway.

The Data Comes from grott, a growatt inverter reading tool that gives the data to openhab via mqtt

I will try again tomorrow with your suggestions, thank you very much :slight_smile:
Have a nice day
Michael

OK, then the rule is completely off. That’s not what a JS Scripting rule looks. I might suggest looking at Blockly for developing your rules if you are not that familiar with programming. It’s visual and much easier to understand for most people.

As a file based .js rule it would look something like this:

rules.JSRule({
  name: "Convert Photovoltaik_Data",
  description: "Extracts the photovoltaik and adjusts is as necessary",
  triggers: [triggers.ItemStateChangeTrigger('Photovoltaik_Momentan'), triggers.ItemStateChangeTrigger('Photovoltaik_Momentan')],
  execute: (event) => {
    // Get new values
    var momentan = JSON.parse(items.Photovoltaik_Momentan.state).values.pvpowerin; // this is likely already a number, no parsing required.
    var ladestatus = JSON.parse(items.Photovoltaik_Ladestatus.state).values.bms_soc; // this is likely already a number, no parsing required

    // Set new values
    items.Photovoltaik_Momentan_Num.postUpdate(momentan);

    // Calc down PV
    var corrected = ladestatus / 10;
    items.Photovoltaik_Ladestatus_Num.postUpdate(corrected);

  },
  tags: [],
  id: "convert-pv"
});

Note, I just noticed there was another error in the original code. The two updates of the Ladestatus are redundant. Above only updates it once.

As you can see, it’s quite different. It needs to be put in a different folder too.

As Blockly though it would look something like this:

( I threw in some Units). This is kind of a skeleton though. I don’t have your Items and I don’t know the proper units so those are just placeholders.

Yes, it would work with a transformation. What the transformation does is modify the value before it gets to the Item. If the value is wrong, you can adjust it before it gets to the Item and eliminate the intermediate steps.

You can link that Channel to a Number Item.

Usually how something like this is set up is as follows:

  1. Create a Generic MQTT Thing that represents the device, in this case your Growattt

  2. Create a Channel on the Thing for each sensor and actuator on the device (if I understand correctly, this is a sensor only device). Even all of the data from this device is delivered as one JSON String, you still want to create a separate Channel for each piece of data in that one JSON String you care about. For each piece of information:
    a. Create a channel of the appropriate type (e.g. if it’s a number, create a number type Channel)
    b. Set the state transformation (you may need to click on “show advanced”) to extract the value that the Channel represents and, when necessary, modifies it. For example, create a Number Channel for pvpowerIn and use JSONPATH:$.values.pvpowerin as the state transformation. Create another Number Channel for bms_soc and use JSONPATH:$.values.bms_soc∩JS: | parseFloat(input) / 10. The MQTT binding lets you chain transformations and the JS transformation lets you do simple things inline so that second Channel extracts the value from the JSON and then divides it by 10. Notice that we had to parse the input to the transform first.

  3. Link the Channels to Items of the matching type. Since both are number Channels, both would be Number Items. You have to option to append units if you want in which case they would be Number:Power (or what ever is appropriate).

With this approach you not only eliminate the rule, you also eliminate at least three of your Items. All you need is Photovoltaik_Momentan_Num and Photovoltaik_Ladestatus_Num linked to those to MQTT Channels.

1 Like