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.
Thanks @Lolodomo, that works.
I have two additional questions:
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>)
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!
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?
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?
@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")
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?
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.
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
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
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
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