Working with Number:Temperature item type

Just in case I need to link it in the future:

You can add the desired unit to the label of your item or in the sitemap. The framework will do the conversion automatically. e.g.

demo.items:

Number:Temperature testNumberTemperature

demo.sitemap:

sitemap demo label="My home automation" {
    Frame label="Temperature" {
        Text item=testNumberTemperature label="Temperature [%.1f %unit%]" icon="temperature"
        Text item=testNumberTemperature label="Temperature [%.1f °C]" icon="temperature"
        Text item=testNumberTemperature label="Temperature [%.1f °F]" icon="temperature"
    }
}

It will look like this:

Thanks @cweitkamp. I was able to confirm it is indeed working that way.

I have a NumberItem (using the mqtt binding), that I need to compare to a Number:Temperature Item (from the Nest binding), how can I do this?

Number myMqttNumber ...
Number:Temperature myNestAmbientTemperature ...
if (myMqttNumber.state == myNestAmbientTemperature.state) //Doesn't work at run time but no issues in VSCode

val a = myMqttNumber.state|°C
val b = (myMqttNumber.state as Number)|°C
val c = (myMqttNumber.state as Number).doubleValue|°C
// For all above, VSCode reports: no viable alternative at input '|'

As you can see above I have tried creating a new QuantityType using the state from the myMqttNumber item but I can’t get it to work.

I also thought about trying to extract the Number value from the QuantityType that is the state of the myNestAmbientTemperature item, but since it does not appear to be possible to cast the state to a QuantityType<Temperature> object, I can’t get VSCode to let me do that either.

val QuantityType<Temperature> foo = myNestAmbientTemperature.state as QuantityType<Temperature> 

VSCode reports Temperature cannot be resolved to a type.

I even tried:

import org.eclipse.smarthome.core.library.dimension.*
import javax.measure.quantity.*

but that didn’t help.

Any ideas?

You can do it in the other way::

var Number tempSalon = (TemperatureSalon.state as QuantityType<Number>).doubleValue

This is what I am using. I suppose that I get the value in the unit the item was last set.

1 Like

Thanks @Lolodomo, that works.
I have two additional questions:

  1. What is the best way to perform arithmetic on QuantityTypes?
val temp = myNestAmbientTemperature.state as QuantityType<Number>
temp += 2|°C

This causes the following error in VSCode: Type mismatch: cannot convert from QuantityType<?> to QuantityType<Number>

I am trying to increment the ambient temperature by two and then send this new value as a command to the setpoint item. Since the setpoint item is also a Number:Temperature I need a QuantityType.
I know I could extract the number value from the ambient temperature QuantityType, increment it and then create a new string item with the value and the ‘°C’ then send this as the command, but this seems messy. Plus I don’t understand why VSCode thinks 2|°C is a QuantityType<?> vs a QuantityType<Number>
To add to the confusion, this code produces the same error in VSCode:

val temp = myNestAmbientTemperature.state as QuantityType<Number>
temp += (2|°C as QuantityType<Number>)

:confused:

  1. Why QuantityType<Number> ?
    Is it possible to have a QuantityType that holds a value of any type other than Number? Why not just QuantityType or even QuantityType<Temperatue>?
    I am not questioning that you are correct, only trying to learn and understand.

Thanks!


Edit: More questions! :question: :question:

  1. Why does the following code underline num with error no viable alternative at input 'num'
val double num = 2
var QuantityType<Number> qt = num|°C

In other words, how do I create a QuantityType using a value from a variable?

  1. This blog post references QuantityType<Temperature> but as described earlier, this does not work in OH rules (as far as I can see) and so why the difference? @cweitkamp mentioned this blog post but due to this discrepancy I am actually more confused now. What am I missing?

…Sorry for the ridiculously long post. :blush:

2 Likes

Good questions but sorry I have not the answers.

@mcqwerty In some cases, I think it’s better to just test the rules with openHAB than just rely on the errors generated in VSCode. Especially with new features, I have seen some unnecessary errors in VSCode that are interpreted just fine in openHAB.

This works from my testing. I just want to point out that you can’t increment a variable defined as final (val). Also, I would recommend defining the QuantityType specific dimension over the overall Number one.

var temp = myNestAmbientTemperature.state as QuantityType<Temperature>
temp += 2|°C

As I mentioned above, QuantityType<Number> covers all dimensions. So QuantityType<Temperature> is derived from it.

Per my understanding, for QuantityType declaration using the value of a variable, you will need to use the declaration function. This works in my testing.

val double num = 2
val QuantityType<Temperature> qt = new QuantityType(num + "°C")

@jeshab Thanks for the reply:

Good call on the var vs val that was me carelessly editing code directly in the post.

Your code is not working for me - VSCode complains all over the place but even when I save I get an error in openhab.log: no viable alternative at input 'xC2' This looks like some kind of unicode issue since the xC2 in the log appears like a single character. I’m not sure how to explain but my guess is that the °C is the problem. I tried with copy pasting directly from .toString of real temperature states but all I get is either xE2 or xC2 in the log with the above error.
Also, with your sample code, do you have any errors in VSStudio? If not, did you have to import anything to get the namespace for the Temperature Class to stop VSCode complaining?

I tried:

import org.eclipse.smarthome.core.library.dimension.*
import javax.measure.quantity.*

but Temperature still causes Temperature cannot be resolved to a type in VSCode.

I think these are two different problems and I can live with the VSCode complaints but the unicode issue is stopping the compile from working.


OK that makes sense, thanks.


Thanks, that works even though VSCode complains about Temperature, it still compiles and works fine.

Looking at the source code here, I see:

public QuantityType(Number value, Unit<T> unit) {
        // Avoid scientific notation for double
        BigDecimal bd = new BigDecimal(value.toString());
        quantity = (Quantity<T>) Quantities.getQuantity(bd, unit);
    }

To me that implies that we could create a QuantityType without resorting to magic strings but I can’t work out how to get it to work. After re-reading the blog post referenced by @cweitkamp I tried this:

val double num = 2
val QuantityType<Temperature> qt = new QuantityType(num, SIUnits.CELSIUS)

VSCode complains a lot but it does seem to compile. However at run time I get the following error in the log: The name 'SIUnits' cannot be resolved to an item or type;
Any ideas what the syntax should be?

You seem to have pinpointed the issue. You should check your rule file encoding and convert it to UTF-8 if necessary. I unfortunately don’t use VSCode that much so I can’t comment on the errors you are seeing.

I am not sure about this. I just tried to give a practical solution to your problem. If you want to use that specific method, you will probably need to import the library that defines SIUnits.

Does this mean the following would not work anymore?
if (Weather_MaxTemp_0.state > 23) {

Is it mandatory to use
Number:Termperature instead of Number items?

No it should still work. It does for me.

Is there any way to do math in line of an if statement ?

ex:

	if ( atticTemperature.state < (atticSetpoint.state as QuantityType<Temperature> + "0.5 °F" ) )

I’ve tried a dozen different variations and they all fail with something along :

[ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'attic test something something': An error occurred during the script execution: Could not invoke method: org.eclipse.smarthome.model.script.lib.NumberExtensions.operator_lessThan(org.eclipse.smarthome.core.types.Type,java.lang.Number) on instance: null

the closest I got with no errors (but didn’t seem to work anyway was:

rule "attic test something something"
when
	Item atticSetpoint changed
then
	if ( atticTemperature.state > (atticSetpoint.state as QuantityType<Temperature> + 0.5 ) )
	logInfo("success","addition")
end

but i never got the success logging. i also don’t get any other errors…so…progress? hah!

rule "attic test something something"
when
	Item atticSetpoint changed
then
	if ( atticTemperature.state > ((atticSetpoint.state as Number) + 0.5 ) )
	logInfo("success","addition")
end
1 Like

hey all,
how can i make this rule work with this?
items

Number:Temperature		Weather_Temperature				"Temperatuur buiten [%.1f %unit%]"							<temperature>	(gTemperatures, gWeather) 	{ channel="openweathermap:weather:api:local:current#temperature" }
Number					Weather_Temp_Min				"Temp. buiten Min [%.1f °C]"								<temperature>	(gWeather)
Number					Weather_Temp_Max				"Temp. buiten Max [%.1f °C]"								<temperature>	(gWeather)

rules

rule "Set daily max and min temperature"
when
	Item Weather_Temperature changed or
	Time cron "0 0 0 * * ?" or
	System started
then
	val max = Weather_Temperature.maximumSince(now.withTimeAtStartOfDay)
	val min = Weather_Temperature.minimumSince(now.withTimeAtStartOfDay)
	logInfo("rules.weather", "Temperatuur is " + Weather_Temperature.state)
	if( max !== null && min !== null) {
		postUpdate(Weather_Temp_Max, max.state)
		postUpdate(Weather_Temp_Min, min.state)
		logInfo("rules.weather", "Max Temperatuur is " + max.state)
		logInfo("rules.weather", "Min Temperatuur is " + min.state)
	}
end

What not working right now?

it wasn’t updating Weather_Temp_Max and Weather_Temp_Min, but i changed it to this, and that works so far now.

rule "Set daily max and min temperature"
when
	Item Weather_Temperature changed or
	Time cron "0 0 0 * * ?" or
	System started
then
	var Number CurrentValue = (Weather_Temperature.state as QuantityType<Number>).doubleValue
	postUpdate(Weather_Temp, CurrentValue)
	val max = Weather_Temp.maximumSince(now.withTimeAtStartOfDay)
	val min = Weather_Temp.minimumSince(now.withTimeAtStartOfDay)
	logInfo("rules.weather", "Temperatuur is " + CurrentValue)
	if( max !== null && min !== null) {
		postUpdate(Weather_Temp_Max, max.state)
		postUpdate(Weather_Temp_Min, min.state)
		logInfo("rules.weather", "Max Temperatuur is " + max.state)
		logInfo("rules.weather", "Min Temperatuur is " + min.state)
	}
end

You need to include one missing definition. At the top of your rules file, add:

import org.eclipse.smarthome.core.library.unit.SIUnits

I believe this missing include will be automatically added at a certain point in time.

2 Likes

Thank you @Lolodomo!

Just used your syntax for the DarkSky binding to remove the UNIT value so I could use it else where.

rule "Remove UNITS from Temperature and Round Numbers for Alexa"
	when
		Item FIOTemp received update or
		Item FIOTemp_Min0 received update or
		Item FIOTemp_Max0 received update or
		Item FIOTemp_Min1 received update or
		Item FIOTemp_Max1 received update or
		Item FIOTemp_Min2 received update or
		Item FIOTemp_Max2 received update or
		Item FIOTemp_Min3 received update or
		Item FIOTemp_Max3 received update or	
		Item FIOTemp_Min4 received update or
		Item FIOTemp_Max4 received update			
	then

		if (systemStarted.state != ON && FIOTemp.state != NULL && FIOTemp.state !== null && FIOTemp.state != UNDEF) {

			FIOTemp_Number.postUpdate((FIOTemp.state as QuantityType<Number>).doubleValue)
			logInfo("FIO" , "FIOTemp_Number postUpdate is at " + FIOTemp_Number.state)

			// Used for Alexa Speaking

			val roundedNumber1 = (Math::round((FIOTemp_Number.state as DecimalType).floatValue()* 10)).floatValue() / 10
			FIOTemp_Rounded.postUpdate(roundedNumber1)
		}

Hi All, I am following this thread with interest and have tried various things from the replies, but I can get this to work:

var o_trigger = HueOutdoorTemperatureSensorTemperature.state + 2 | °C

It results int he following error in the log:

2020-01-06 20:41:45.598 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Shed Fan ON': An error occurred during the script execution: Could not invoke method: org.eclipse.xtext.xbase.lib.ObjectExtensions.operator_plus(java.lang.Object,java.lang.String) on instance: null

The value of HueOutdoorTemperatureSensorTemperature.state is 7.61 °C

Could you give some pointers please?

So after spending about 3 hours doing thsi and posting thes question, I finally sussed it:

val o_trigger = (HueOutdoorTemperatureSensorTemperature.state as QuantityType<Temperature>) + 2 | °C
3 Likes