How to convert the value without units of measurement to string in rules

My rule broke when I added units of measurement to my items.

My item used to be

Number TempLivingTarget “Living set [%.1f °C]” (gTempLiving, gTemperature, GH_gTempLiving) {homekit=“TargetTemperature” [minValue=19, maxValue=25], ga=“thermostatTemperatureSetpoint” }

I now changed it (added :Temperature) to

Number:Temperature TempLivingTarget “Living set [%.1f °C]” (gTempLiving, gTemperature, GH_gTempLiving) {homekit=“TargetTemperature” [minValue=19, maxValue=25], ga=“thermostatTemperatureSetpoint” }

The problem I have is the rule that uses this items is now broken

this rule was using
TempLivingTarget.state.toString

which used to give only the value but now gives 19.5 °C

I can’t seem to figure out how to pull the value and convert it to String.

Any idea what to use in a rule to get 19.5 as output in stringformat to use in rules ?

If you are working with a String, what’s the problem? Whether it has the units or not you can’t do math with a String anyway?

If you are doing math, then show us what you are doing. Usually the best approach is to stay working the units. But sometimes it isn’t but we need to see your broken rule to tell.

Rich, you are right. Sorry. I asked the question in a generic way because I can see myself having to decompose items with UOM in a number of cases.

But the exact use case is the following. I’m using this to make an API cll.

This was the old line in the rules

sendHttpGetRequest(“http://xxx.xxx.xxx.xxx/api/menutree/write_datapoint.json?SessionId=” + sessionid + “&Id=617&Type=Numeric&Value=” + TempLivingTarget.state.toString)

I managed to convert the rule eventually but it wasn’t very straightforward, so doubting whether I will adopt this UOM broadly.

I changed it to the following but maybe there is a more elegant and intuitive way to achieve the same.
I could get rid of the creation of the variable but this way I could at least print the variable in the logs to see what the output was during the whole journey.

var String temptosendliving = ((TempLivingTarget.state as QuantityType).toBigDecimal).toString
sendHttpGetRequest(“http://xx.xx.xx.xx/api/menutree/write_datapoint.json?SessionId=” + sessionid + “&Id=617&Type=Numeric&Value=” + temptosendliving)

I would convert the state to the unit expected by your api first, just to be sure.

Don’t over specify the types of variables in Rules DSL so you don’t need var String temptosendliving but instead just var temptosendliving.

@JimT is correct, you should make sure the units are right for what your API expects. This temperature so it could be storing °F, °C or °K. Calling toBigDecimal is just going to give you what ever units the Item happens to be storing. You’d use toUnit() for that.

(TempLivingTarget.state as QuantityType).toUnit('°C')

That’s kind of the point of QuantityTypes in the first place. Even if you are given °F, you don’t care and you don’t have to do anything special to convert to °C. You just need to tell OH that it’s °C that you want.

After that point there are a number of options available to you to strip off the units. They are all pretty much the same in terms of length.

If you were doing math or comparisons, in Rules DSL, you can add units to a number with | <unit>. For example MyTemp.state < 20 | °C.

You have to be careful when doing math with temperatures because 0 °C and 0 °F are not the same so some calculations do not work as expected.

Have you tried the following:

(TempLivingTarget.state asNumber).floatValue

which will eliminate the Unit, or

(TempLivingTarget.state asNumber).floatValue.toString
1 Like

Thanks Rich, didn’t know you don’t have to specify variable type and changed it to

ar temptosendliving = ((TempLivingTarget.state as QuantityType).toUnit(‘°C’).toBigDecimal).toString

Still have to get used to this UOM. I’m sure it will be very powerful when you deal with multiple units.

I want to avoid float as the API expects the value to be in rounded to 0.5.

So set per 0.5 degree.

Float would risk in returning a number with lots of decimals, not ?

…that’s correct.

Without decimals you can try this:

(TempLivingTarget.state as Number).intValue

If you want to have one decimal, either .5 or .0, I fear you have to calculate it separately.