Transforming incoming Channel Values without needing a traditional rule

Hi All

I know everyone has a lot going on with the new releases but thought i would take a quick moment to show a feature that I am sure many people have seen but will create a rule to handle (I almost did)

So this is just a callout to all the people who continuously provide us such a flexible system and if i could do anything better (including writing this tutorial better please let me know)

I have a scenario where there are 2 inverters primary and secondary - the secondary inverter actually just feeds everything it has to the house power line (well actually to the primary inverter ) and if there is insufficient demand that primary inverter will send to the batteries if needed.

Just for clarity the primary and secondary inverters are actually a group of 3 inverters with 120Kwh of Batteries attached - yes a big installation)

the challenge - how to know what the real consumption is if it is not just the Sum of the two inverters)

In this case there is a Smart Meter (an EM2 with Tasmota software but not 100% relevant) and this meter measures the the power and when it goes to the inverter (insufficient demand ) the value goes negative - how to handle that

First thought - Easy create a rule on update to EM2_power0 and when its negative update the new Item (i called it c_inverterFeedbackFlow) with the negative value and include that Item in whichever group is needed -

actually turned out to be far simpler - I created a new Item and linked it to the Power0 of the EM2 and when I went to link it and choose the SCRIPT Ruby Profile

i added this ruby script to the “Thing to Item Transformation”

|(input = input.to_f) > 0 ? 0 : input

Basically it says if the value is greater than 0 set the Item(c_inverterFeedbackFlow) to 0 or if its negative make it the value of the Channel.

I just add that new Item to the group for the Consumption calculation and I can also show the item it separately in the UI as needed - no need to have a rule triggered every time the field is updated.

Using the “NEW” YAML Copy option here is the complete Item Definition

version: 1
items:
  c_inverterFeedbackFlow:
    type: Number
    dimension: Power
    label: This is the Feedback from the Kostal to the Outback(W)
    format: JS(config:js:hasThousandToK):%s
    unit: W
    groups:
      - g_kostal_AC_Power_Total
      - g_TotalPower
    channels:
      mqtt:topic:a5958ecfef:9f24bd3e63:Power0:
        profile: transform:RB
        toItemScript: "|(input = input.to_f) > 0 ? 0 : input"
e

c_inverterFeedbackFlow

Thanks for posting! It’s always great to see new tutorials.

Just note that this doesn’t make the transformation any more effecient than doing this in a rule. The script engine still needs to process the jRuby code.

But it is a bit more stramlined and ends up creating fewer events on the event bus as it runs between the Channel update and the Item update. So it’s Channel → Transformation → Item instead of Channel → Item → Rule → Item.

Some other things you can do with script transformations is pass them arguments. This is more for situations where you create a generic script transformation that would be used across multiple Links instead of an inline. You use URL encoding to pass the arguments when you call the script (e.g. JS(myTransform.js?arg1=value1)) and in the script you can use arg1 same as you use input. So you could make a relatively generic script transformation that can be “configured” each time you use it.

You can see an example of this on the marketplace, e.g. Auto scale units. Also, as you can see, if you ever do create a transformation like that you’d want to share, you can post them to the marketplace. And others will be able to install them from Add-on store → Transformations.

@rlkoshak thanks for the advice and comments as always its appreciated