It’s not really a workaround IMHO because this is the exact way OH behaved before 2.3.
I’m probably a vocal minority here who thinks that UoM is a BAD idea. It’s absolutely not needed in sitemaps, it’s purpose of having automatic conversions is rarely necessary and when it does it’s trivial to accomplish without UoM. On the other hand UoM will cause every single rule to fail unless every state is specified as a number quantity.
I’m having troubles with implementing UoM as well. Quick question: Is this supposed to work or am I doing something wrong? I am trying to do calculations with gas consumption, which is in cubic metres.
rule "Test"
when
System started
then
val n = 5|m3
end
The expected warning about the unused value aside: I’m getting a:
[ERROR] [ntime.internal.engine.RuleEngineImpl] - Error during the execution of startup rule 'Test': unexpected token 8
Putting the cubic metres in quotes doesn’t help. Other units like “W” or “week” work just fine.
I’m on 2.5.0.M1 but 2.4.0 produces the same result.
Oh no! Yes that works. I feel a bit stupid now. Although in my defense the “power of three” isn’t even on the Mac keyboard and I hadn’t considered such a rare character to be working.
Hi, it’s me again. I am using lots of Functions and Procedures and found that any UoM argument needs to be of QuantityType<Number> or the rule wouldn’t execute. E.g. QuantityType<Angle> wouldn’t work. Is there anything I can do about that or is that normal / “standard procedure”?
Having said this, I found that a Procedure or Function doesn’t accept a negative angle as an argument. One use case is handing over a negative elevation (sun below horizon). In case anyone is wondering.
test.rules:
rule "Test"
when
System started
then
val Procedures$Procedure1<QuantityType<Number>> elevation = [ angle |
logError("Test", "Elevation is: " + angle)
]
// VSCode: Type mismatch: cannot convert from QuantityType<?> to QuantityType<Number>
// Log: Configuration model 'test.rules' has errors, therefore ignoring it: [xx,xx]: no viable alternative at input '|'
// elevation.apply(-5|°)
// elevation.apply((-5)|°)
// VSCode: Type mismatch: cannot convert from QuantityType<?> to QuantityType<Number>
// Log: Nothing logged (rule works)
elevation.apply(5|° * -1) // Elevation is: -5 °
elevation.apply(-5|"°") // Elevation is: -5.0 °
// No errors
elevation.apply(5|°) // Elevation is: 5 °
elevation.apply(5|"°") // Elevation is: 5 °
end
I’m also curious about the sudden conversion to floating point in case of (-5|“°”).
It would be great if someone could shed light on this.
Take anything VScode says about this with a pinch of salt. These are new features and may not be fully recognized by the extension yet, so worth seeing what happens when you actually execute them.
Please keep experimenting and let us know!
I think that’s just an oddity about rules use of Number and parsing - hyphen, it crops up all over the place unconnected with UoM.
Thanks for the feedback! I did some further experiments and here is an updated version of the rule that does run successfully with a negative angle.
// VSCode goes up in flames, but Rules DSL is fine with the import
import org.eclipse.smarthome.core.library.dimension
rule "Test"
when
System started
then
// Strongly typing with Angle instead of Number makes the procedure
// accept negative angles. VSCode and Angle are not friends, though.
val Procedures$Procedure1<QuantityType<Angle>> elevation = [ angle |
logError("Test", "Elevation is: " + angle)
]
elevation.apply(-5|°)
end
This is what happened: I once got an error by the Rules DSL which I thought was from the import and didn’t try that ever again because I thought the import wouldn’t work. So I stuck with Number. Turns out the import works fine. And with it,
QuantityType<Angle>
(etc.) can be used. The procedure in my example then accepts negative angles. I still think Number not accepting a negative angle is a bug. But it works now! And everything’s strongly typed. Yay!
EDIT - oh wait, did you mean automatically scaling a display, like Item vale 23005 A getting displayed as 23.005 kA? In theory [%f.3 %unit%] could do that, but I don’t think it’s implemented?
Here’s another thing I’ve learned. Persistence doesn’t return QuantityTypes so we sometimes need to convert a Number or primitive numerical value to QuantityType. This is how it’s done.
import org.eclipse.smarthome.core.library.unit.SIUnits
rule "Test"
when
// Also triggered upon saving of file
System started
then
// This can be any item of type Number:Power (W)
val item = WashingMachinePower
// Its state is a QuantityType<Power> (W)
val state = item.state
logError("Test", "State: " + state)
// Persistence produces a value of type DecimalType
val average = item.averageSince(now.minusMinutes(5), "rrd4j")
logError("Test", "Average: " + average)
// Convert to QuanttyType using the constructor
// QuantityType(Number, javax.measure.Unit)
val averageTyped = new QuantityType(average, SIUnits.WATT)
logError("Test", "Average (typed): " + averageTyped)
// A way to convert to QuantityType from double using static
// factory method
val typed = QuantityType::valueOf(42, SIUnits.WATT)
logError("Test", "Value 42 (typed): " + typed)
end
Haha! Now that you mentioned it I got worried and checked my persisted values. Let’s say I have the following item. As the group name indicates is is persisted to DB every minute (for debugging).
The number 2000 is written to DB. If I do the following:
PowerItem.postUpdate(2|kW)
You guessed it: The number 2 is written to DB. Shouldn’t the unit as defined in the item definition (in this case: W) be used? In my opinion this is really, really bad. It means that there either needs to be a proxy item for persistence or the postUpdate must never receive a different unit.
I would suggest to have persistence store values in their canonical representation (SI units for most, imperial units for some). To avoid unit conversion errors, I would even adhere to persisting in SI, according to a defined convention (e.g. metre as canonical length unit).
Whenever UoM would be invoked, it would always know the starting unit. Any unit conversion requested would then use the proper factor.
Oh. Um. That is … undesirable. I mean, I understand the limitations of the persistence services not (yet) dealing with UoM properly, but that’s a nasty consequence.