Same rule for 2 proxy items

I have 2 items (pressure from different sources) which needs to be converted in the same way to a different format, just a simple math with rounding.
Currently I have 1 rule for 1 [proxy] item. Do I need a separate rule for another item or there is a nice way to combine?
Thanks!

  • You can create a rule that triggers on changes to either Item and just calculate both. It isn’t even a measurable amount of extra work.

  • You can write a lambda and have both rules call the same lambda.

For some reasons I did not know about lamda.
Now I want to create one to be able to re-use it a future, but as I’m doing this for a fist time I’m doing it wrong. Please correct me!

// creating Lambda to convert hPa or mbar to mmHg
val Functions$Function1 convertAtm = [ GenericItem pressuredata |
	val newdata = ((pressuredata as DecimalType) / 1.3332239 + 0.5).intValue
	postUpdate(pressuredata,newdata)
	]

// converting mbar to mmHg for barometric pressure from OWM
rule "PressureProxy2"
when
   Item Pressure_OWM received update
then
   val Pressure2_mm = convertAtm.apply(Pressure_OWM)
   postUpdate(PressureProxy2,Pressure2_mm)   
end

Pressure_OWM is the real item reported by the binding and PressureProxy2 is a proxy item I want to display.
Yes, I know it’s now full of mistakes after I’ve made lots of attempts to fix it.
Thanks!

I assume you saw this:

Things that I see that are errors or don’t make sense:

  • why postUpdate the new value to the same Item? That will trigger the rule again and never update the proxy Item

  • you do not return anything from the lambda. The result of the last line of the lambda is what gets returned. Since postUpdate returns void, the line val Pressure2_mm = convertsAtm.apply(Pressure_OWM) doesn’t make sense.

  • not an error, but it is better to use MyItem.postUpdate than the postUpdate Actions

  • you need to get the value of an Item by calling item.state (e.g. pressuredata.state)

The following makes more sense. However, for one liners like this you really are not saving anything and adding a lot of complexity by using a lambda. (NOTE: I’m using a slightly different syntax here, one that will eliminate warnings in ESH Designer). I also change things up a bit to avoid needing to case things inline which makes the code clearer.

import org.eclipse.xtext.xbase.lib.Functions

val Functions$Function1<Number, Integer> convertAtm = [ pressureData |
    (pressuredata / 1.3332239 + 0.5).intValue
]

rule "PressureProxy2"
when
    Item Pressure_OWM changed
then
    PressureProxy2.postUpdate(convertAtm.apply(Pressure_OWM.state as Number))
end

Personally, I’d just write (assuming two Pressure Items):

rule "PressureProxy"
when
    Item Pressure_OWM changed or
    Item Pressure_Other changed
then
    PressureProxy1.postUpdate((Pressure_Other.state as DecimalType) / 1.3332239 + 0.5).intValue)
    PressureProxy2.postUpdate((Pressure_OWM.state as DecimalType) / 1.3332239 + 0.5).intValue)
end

The above code does more in far fewer lines of code and is much easier to understand and maintain.

1 Like

Thanks for the explanations!
Yes, I saw the topic with an example but I was missing some key points. Now I’m better :wink:
I fully agree that for this simple task lambda is not really necessary, but for me it was easier to learn how to use it on this basic example.
Everything works now. Thanks again!

I’m trying to add one more lambda very similar to the working one but I’m stuck :frowning:

This is the lambda (it is very simple but I will add more logic later):

// Lambda to convert temperature readings
val Functions$Function2<Number, Integer> convertTemp = [ tempData |
    (tempData / 10.0)
]

This is the rule:

var int tempDec = Integer::parseInt(tempHex, 16)
logInfo("RFLink", "decimal data is: " + tempDec)
TemperatureOut.postUpdate(convertTemp.apply(tempDec))

The whole idea is to get decimal representation of the hex string obtained from the sensor, divide it by 10 and update the item:

Number TemperatureOut "External temperature (RFLink) [%.1f °C]" <temperature>

I’m getting the right decimal number in the log (not yet divided) then the following error:
Rule 'RFLink': An error occured during the script execution: index=1, size=1

You are only passing one argument so should use Functions$Function1.

My stupid copy/paste mistake. Thanks again!