I gave up on OH 2.3 Unit of Measure (UM)

rules
state
temperature
Tags: #<Tag:0x00007f51e07136b0> #<Tag:0x00007f51e0713390> #<Tag:0x00007f51e0713188>

(Claude Benshaul) #21

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.


(Christoph Zimmermann) #22

Hi,
yes I tried that

 Configuration model 'heizung.rules' has errors, therefore ignoring it: [74,34]: mismatched input '|' expecting 'then'

Was my first idea :wink:

– Christoph


(Christoph Zimmermann) #23

I’m torn. Maybe that’s a good idea, but maybe not.
We will see how this evolves.

– Christoph


(Jens W.) #24

I’m having troubles with implementing UoM as well. :roll_eyes: 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.

Thanks a lot in advance for any input!


(Wouter Born) #25

Can you try instead:

val n = 5|m³

It doesn’t show the error for me when I use it this way in a rule.
If that also works for you the documentation needs to be updated. :slight_smile:


(Jens W.) #26

Oh no! :man_facepalming: Yes that works. I feel a bit stupid now. :slight_smile: 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.

Thanks a million for the quick response! :+1:


(Wouter Born) #27

Excellent news that it now works! :smiley:

The documentation also contains several wrong unit symbols, so I’ve created a PR to update it:


(Vincent Regaud) #28

Thanks


(Jens W.) #29

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.

Thanks,
Jens


(Rossko57) #30

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.


(Jens W.) #31

Thanks for the feedback! :+1: 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! :slight_smile:


(Crispin) #32

I’ve not seen it do this. My example does not work.

Number:ElectricCurrent	 ffjj " Value [%.1f mA]"

Am I missing something? I cannot see it change when I give it a value of 100 or 0.1. Result printed is always mA

Apologies for hijack :slight_smile:


(Rossko57) #33

I think you need to more specific, like 100 A

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?


(Jens W.) #34

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

See also:


(Rossko57) #35

Now what we need is a bit of nifty code to interrogate the “live” Item to establish UoM, and automatically choose the “recreated” value UoM.

I can see that causing odd issues when the unit of the live Item gets changed after some data already recorded. :crazy_face:


(Jens W.) #36

Haha! :slight_smile: 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).

Number:Power TestPower "Test [%d W]" (PersistDBEveryMinute)

When I do the following:

PowerItem.postUpdate(2000|W)

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.


(Olivier Biot) #37

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.


(Rossko57) #38

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.


(Jens W.) #39

@rossko57, @shutterfreak Just fyi: I opened an issue over at GitHub.